FELIX-2215: Refactor bundlerepository and maven bundle plugin obr data model

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@925279 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/pom.xml b/bundleplugin/pom.xml
index 0d13b3a..019ec09 100644
--- a/bundleplugin/pom.xml
+++ b/bundleplugin/pom.xml
@@ -64,6 +64,11 @@
     <version>2.2.2</version>
   </dependency>
   <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.bundlerepository</artifactId>
+      <version>1.5.0-SNAPSHOT</version>
+  </dependency>
+  <dependency>
     <groupId>org.apache.felix</groupId>
     <artifactId>org.osgi.core</artifactId>
     <version>1.0.0</version>
diff --git a/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundleAllPlugin.java b/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundleAllPlugin.java
index 28391af..54fd5f4 100644
--- a/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundleAllPlugin.java
+++ b/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundleAllPlugin.java
@@ -426,12 +426,6 @@
     }
 
 
-    protected String getBundleName( MavenProject project )
-    {
-        return getBundleName( project.getArtifact() );
-    }
-
-
     private String getBundleName( Artifact artifact )
     {
         return getMaven2OsgiConverter().getBundleFileName( artifact );
diff --git a/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java b/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java
index 1ebffac..94b34a3 100644
--- a/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java
+++ b/bundleplugin/src/main/java/org/apache/felix/bundleplugin/BundlePlugin.java
@@ -815,7 +815,6 @@
         {
             return finalName + '-' + classifier + ".jar";
         }
-
         return finalName + ".jar";
     }
 
diff --git a/bundleplugin/src/main/java/org/apache/felix/obrplugin/Capability.java b/bundleplugin/src/main/java/org/apache/felix/obrplugin/Capability.java
deleted file mode 100644
index a5f9cbb..0000000
--- a/bundleplugin/src/main/java/org/apache/felix/obrplugin/Capability.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.obrplugin;
-
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-
-/**
- * This class describe and store capability node.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class Capability
-{
-
-    /**
-     * m_name: name of the capability.
-     */
-    private String m_name;
-
-    /**
-     * m_p: List of PElement.
-     */
-    private List m_p = new ArrayList();
-
-
-    /**
-     * get the name attribute.
-     * 
-     * @return name attribute
-     */
-    public String getName()
-    {
-        return m_name;
-    }
-
-
-    /**
-     * set the name attribute.
-     * 
-     * @param name new name value
-     *            
-     */
-    public void setName( String name )
-    {
-        m_name = name;
-    }
-
-
-    /**
-     * return the capabilities.
-     * 
-     * @return List of PElement
-     */
-    public List getP()
-    {
-        return m_p;
-    }
-
-
-    /**
-     * set the capabilities.
-     * 
-     * @param mp List of PElement
-     *            
-     */
-    public void setP( List mp )
-    {
-        m_p = mp;
-    }
-
-
-    /**
-     * add one element in List.
-     * 
-     * @param pelement PElement
-     *            
-     */
-    public void addP( PElement pelement )
-    {
-        m_p.add( pelement );
-    }
-
-
-    /**
-     * transform this object to Node.
-     * 
-     * @param father father document for create Node
-     * @return node
-     */
-    public Node getNode( Document father )
-    {
-        Element capability = father.createElement( "capability" );
-        capability.setAttribute( "name", getName() );
-        for ( int i = 0; i < getP().size(); i++ )
-        {
-            capability.appendChild( ( ( PElement ) ( getP().get( i ) ) ).getNode( father ) );
-        }
-        return capability;
-    }
-
-}
diff --git a/bundleplugin/src/main/java/org/apache/felix/obrplugin/Category.java b/bundleplugin/src/main/java/org/apache/felix/obrplugin/Category.java
deleted file mode 100644
index 7ed1b2e..0000000
--- a/bundleplugin/src/main/java/org/apache/felix/obrplugin/Category.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.obrplugin;
-
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-
-/**
- * describe and store category node.
- * 
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-
-public class Category
-{
-    /**
-     * id of the category.
-     */
-    private String m_id;
-
-
-    /**
-     * get the id attribute.
-     * 
-     * @return id
-     */
-    public String getId()
-    {
-        return m_id;
-    }
-
-
-    /**
-     * set the id attribute.
-     * @param id new id value
-     */
-    public void setId( String id )
-    {
-        m_id = id;
-    }
-
-
-    /**
-     * transform this object to node.
-     * @param father father document for create Node
-     * @return node
-     */
-    public Node getNode( Document father )
-    {
-        Element category = father.createElement( "category" );
-        category.setAttribute( "id", getId() );
-        return category;
-    }
-}
diff --git a/bundleplugin/src/main/java/org/apache/felix/obrplugin/ExtractBindexInfo.java b/bundleplugin/src/main/java/org/apache/felix/obrplugin/ExtractBindexInfo.java
deleted file mode 100644
index 62edc53..0000000
--- a/bundleplugin/src/main/java/org/apache/felix/obrplugin/ExtractBindexInfo.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.obrplugin;
-
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.maven.plugin.MojoExecutionException;
-import org.osgi.impl.bundle.obr.resource.BundleInfo;
-import org.osgi.impl.bundle.obr.resource.CapabilityImpl;
-import org.osgi.impl.bundle.obr.resource.RepositoryImpl;
-import org.osgi.impl.bundle.obr.resource.RequirementImpl;
-import org.osgi.impl.bundle.obr.resource.ResourceImpl;
-import org.osgi.impl.bundle.obr.resource.VersionRange;
-
-
-/**
- * this class is used to configure bindex and get information built by bindex about targeted bundle.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class ExtractBindexInfo
-{
-
-    /**
-     * attribute get from bindex which describe targeted resource.
-     */
-    private ResourceImpl m_resource;
-
-
-    /**
-     * configure bindex and build information.
-     * @param repoFilename URI on OBR descriptor file
-     * @param outFile path on targeted jar-file
-     * @throws MojoExecutionException occurs if bindex configuration failed
-     */
-    public ExtractBindexInfo( URI repoFilename, String outFile ) throws MojoExecutionException
-    {
-
-        m_resource = null;
-        RepositoryImpl repository = null;
-        try
-        {
-            repository = new RepositoryImpl( new File( repoFilename ).getAbsoluteFile().toURL() );
-        }
-        catch ( MalformedURLException e )
-        {
-            e.printStackTrace();
-            throw new MojoExecutionException( "MalformedURLException" );
-        }
-        BundleInfo info = null;
-        try
-        {
-            info = new BundleInfo( repository, new File( outFile ) );
-        }
-        catch ( Exception e )
-        {
-            e.printStackTrace();
-            throw new MojoExecutionException( "Exception" );
-        }
-
-        try
-        {
-            m_resource = info.build();
-        }
-        catch ( Exception e )
-        {
-            e.printStackTrace();
-            throw new MojoExecutionException( "Exception" );
-        }
-    }
-
-
-    /**
-     * extract capabilities from bindex information.
-     * @return bundle capabilities List
-     */
-    public List getCapabilities()
-    {
-        List list = new ArrayList();
-        Collection res = m_resource.getCapabilityList();
-        Iterator it = res.iterator();
-        while ( it.hasNext() )
-        {
-            Capability capability = new Capability();
-            CapabilityImpl ci = ( CapabilityImpl ) it.next();
-            capability.setName( ci.getName() );
-            // System.out.println(ci.getName()) ;
-            if ( !( ci.getName().compareTo( "bundle" ) == 0 ) )
-            {
-                Map properties = ci.getProperties();
-                for ( Iterator e = properties.entrySet().iterator(); e.hasNext(); )
-                {
-                    PElement p = new PElement();
-                    Map.Entry entry = ( Map.Entry ) e.next();
-                    String key = ( String ) entry.getKey();
-                    List values = ( List ) entry.getValue();
-                    for ( Iterator v = values.iterator(); v.hasNext(); )
-                    {
-                        Object value = v.next();
-                        p.setN( key );
-                        if ( value != null )
-                        {
-                            p.setV( value.toString() );
-                        }
-                        else
-                        {
-                            System.out.println( "Missing value " + key );
-                        }
-                        String type = null;
-                        if ( value instanceof Number )
-                        {
-                            type = "number";
-                        }
-                        else
-                        {
-                            if ( value instanceof VersionRange )
-                            {
-                                type = "version";
-                            }
-                        }
-                        if ( type != null )
-                        {
-                            p.setT( type );
-                        }
-                    }
-                    capability.addP( p );
-                }
-
-                list.add( capability );
-            }
-        }
-        return list;
-    }
-
-
-    /**
-     * extract requirement from bindex information.
-     * @return bundle requirement List
-     */
-    public List getRequirement()
-    {
-        List list = new ArrayList();
-        Collection res = m_resource.getRequirementList();
-        Iterator it = res.iterator();
-        while ( it.hasNext() )
-        {
-            RequirementImpl ci = ( RequirementImpl ) it.next();
-            Require require = new Require();
-
-            require.setExtend( String.valueOf( ci.isExtend() ) );
-            require.setMultiple( String.valueOf( ci.isMultiple() ) );
-            require.setOptional( String.valueOf( ci.isOptional() ) );
-            require.setName( ci.getName() );
-            require.setFilter( ci.getFilter() );
-            require.setValue( ci.getComment() );
-            list.add( require );
-        }
-        return list;
-    }
-
-
-    /**
-     * extract categories from bindex information.
-     * @return bundle categories List
-     */
-    public List getCategories() 
-    {
-        List list = new ArrayList();
-        String[] res = m_resource.getCategories();
-        for (int i = 0; i < res.length; i++)
-        {
-            Category category = new Category();
-            category.setId( res[i] );
-            list.add( category );
-        }
-        return list;
-    }
-
-
-    /**
-     * extract symbolic name from bindex information.
-     * @return bundle symbolic name
-     */
-    public String getSymbolicName()
-    {
-        return m_resource.getSymbolicName();
-    }
-
-
-    /**
-     * extract version from bindex information.
-     * @return bundle version
-     */
-    public String getVersion()
-    {
-        if ( m_resource.getVersion() != null )
-        {
-            return m_resource.getVersion().toString();
-        }
-
-        return null;
-    }
-
-
-    /**
-     * extract presentation name from bindex information.
-     * @return bundle presentation name
-     */
-    public String getPresentationName()
-    {
-        return m_resource.getPresentationName();
-    }
-
-
-    /**
-     * extract copyright from bindex information.
-     * @return bundle copyright
-     */
-    public String getCopyright()
-    {
-        return m_resource.getCopyright();
-    }
-
-
-    /**
-     * extract description from bindex information.
-     * @return bundle description
-     */
-    public String getDescription()
-    {
-        return m_resource.getDescription();
-    }
-
-
-    /**
-     * extract documentation from bindex information.
-     * @return bundle documentation
-     */
-    public String getDocumentation()
-    {
-        if ( m_resource.getDocumentation() != null )
-        {
-            return m_resource.getDocumentation().toString();
-        }
-
-        return null;
-    }
-
-
-    /**
-     * extract license from bindex information.
-     * @return bundle license
-     */
-    public String getLicense()
-    {
-        if ( m_resource.getLicense() != null )
-        {
-            return m_resource.getLicense().toString();
-        }
-
-        return null;
-    }
-
-
-    /**
-     * extract source from bindex information.
-     * @return bundle source
-     */
-    public String getSource()
-    {
-        if ( m_resource.getSource() != null )
-        {
-            return m_resource.getSource().toString();
-        }
-
-        return null;
-    }
-
-
-    /**
-     * extract source from bindex information.
-     * @return bundle source
-     */
-    public String getId()
-    {
-        if ( m_resource.getId() != null )
-        {
-            return m_resource.getId();
-        }
-
-        return null;
-    }
-
-}
diff --git a/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrCleanRepo.java b/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrCleanRepo.java
index 512943b..881f03a 100644
--- a/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrCleanRepo.java
+++ b/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrCleanRepo.java
@@ -202,7 +202,7 @@
     /**
      * Open an XML file.
      * 
-     * @param filename : XML file path
+     * @param file : XML file path
      * @param constructor DocumentBuilder get from xerces
      * @return Document which describes this file
      * @throws MojoExecutionException occurs when the given file cannot be opened or is a valid XML file.
diff --git a/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrIndex.java b/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrIndex.java
new file mode 100644
index 0000000..9abfc47
--- /dev/null
+++ b/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrIndex.java
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.obrplugin;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.bundlerepository.Property;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.bundlerepository.impl.DataModelHelperImpl;
+import org.apache.felix.bundlerepository.impl.RepositoryImpl;
+import org.apache.felix.bundlerepository.impl.ResourceImpl;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.logging.Log;
+
+/**
+ * Index the content of a maven repository using OBR
+ *
+ * @goal index
+ * @requiresProject false
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public final class ObrIndex extends AbstractMojo {
+
+    /**
+     * OBR Repository.
+     *
+     * @parameter expression="${obrRepository}"
+     */
+    private String obrRepository;
+
+    /**
+     * Template for urls
+     *
+     * @parameter expression="${urlTemplate}"
+     */
+    private String urlTemplate;
+
+    /**
+     * Local Repository.
+     *
+     * @parameter expression="${localRepository}"
+     * @required
+     * @readonly
+     */
+    private ArtifactRepository localRepository;
+
+    public void execute() throws MojoExecutionException {
+        Log log = getLog();
+        try
+        {
+            log.info("Indexing...");
+
+            String mavenRepository = localRepository.getBasedir();
+            URI mavenRepoUri = new File(mavenRepository).toURI();
+
+            URI repositoryXml = ObrUtils.findRepositoryXml( mavenRepository, obrRepository );
+
+            log.info("Repository:   " + mavenRepoUri);
+            log.info("OBR xml:      " + repositoryXml);
+            log.info("URL template: " + urlTemplate);
+
+            List<File> files = new ArrayList<File>();
+            findAllJars( new File(mavenRepository), files );
+
+            DataModelHelperImpl dmh = new DataModelHelperImpl();
+            RepositoryImpl repository = (RepositoryImpl) dmh.repository( repositoryXml.toURL() );
+            for (File file : files)
+            {
+                try
+                {
+                    ResourceImpl resource = (ResourceImpl) dmh.createResource(file.toURI().toURL());
+                    if (resource != null)
+                    {
+                        repository.addResource(resource);
+                        doTemplate(mavenRepoUri, file, resource);
+                        log.info("Adding resource: " + file);
+                    }
+                    else
+                    {
+                        log.info("Ignoring non OSGi bundle: " + file);
+                    }
+                }
+                catch (Exception e)
+                {
+                    log.warn("Error processing bundle: " + file, e);
+                }
+            }
+            Writer writer = new FileWriter( new File(repositoryXml) );
+            try
+            {
+                dmh.writeRepository( repository, writer );
+            }
+            finally
+            {
+                writer.close();
+            }
+        }
+        catch ( Exception e )
+        {
+            log.warn( "Exception while updating local OBR: " + e.getLocalizedMessage(), e );
+        }
+    }
+
+    protected void doTemplate(URI root, File path, ResourceImpl resource) throws IOException, URISyntaxException
+    {
+        path = path.getAbsoluteFile().getCanonicalFile();
+        String finalUri = root.relativize(path.toURI()).toString();
+        if ("maven".equals(urlTemplate))
+        {
+            String dir = root.relativize(path.toURI()).toString();
+            String[] p = dir.split("/");
+            if (p.length >= 4 && p[p.length-1].startsWith(p[p.length-3] + "-" + p[p.length-2]))
+            {
+                String artifactId = p[p.length-3];
+                String version = p[p.length-2];
+                String classifier;
+                String type;
+                String artifactIdVersion = artifactId + "-" + version;
+                StringBuffer sb = new StringBuffer();
+                if (p[p.length-1].charAt(artifactIdVersion.length()) == '-')
+                {
+                    classifier = p[p.length-1].substring(artifactIdVersion.length() + 1, p[p.length-1].lastIndexOf('.'));
+                }
+                else
+                {
+                    classifier = null;
+                }
+                type = p[p.length-1].substring(p[p.length-1].lastIndexOf('.') + 1);
+                sb.append("mvn:");
+                for (int j = 0; j < p.length - 3; j++)
+                {
+                    if (j > 0)
+                    {
+                        sb.append('.');
+                    }
+                    sb.append(p[j]);
+                }
+                sb.append('/').append(artifactId).append('/').append(version);
+                if (!"jar".equals(type) || classifier != null)
+                {
+                    sb.append('/');
+                    if (!"jar".equals(type))
+                    {
+                        sb.append(type);
+                    }
+                    if (classifier != null)
+                    {
+                        sb.append('/').append(classifier);
+                    }
+                }
+                finalUri = sb.toString();
+            }
+        }
+        else
+        {
+            String dir = path.getParentFile().toURI().toURL().toString();
+            if (dir.endsWith("/"))
+                dir = dir.substring(0, dir.length() - 1);
+
+            if (dir.startsWith(root.toString()))
+                dir = dir.substring(root.toString().length());
+
+            String url = urlTemplate.replaceAll("%v", "" + resource.getVersion());
+            url = url.replaceAll("%s", resource.getSymbolicName());
+            url = url.replaceAll("%f", path.getName());
+            url = url.replaceAll("%p", dir);
+            finalUri = url;
+        }
+        resource.put(Resource.URI, finalUri, Property.URI);
+    }
+
+    private final FileFilter filter = new FileFilter() {
+
+        public boolean accept(File pathname) {
+            return pathname.getName().endsWith(".jar");
+        }
+
+    };
+
+
+    private void findAllJars(File mainRoot, List<File> files) {
+        List<File> roots = new ArrayList<File>();
+        roots.add(mainRoot);
+        while (!roots.isEmpty()) {
+            File root = roots.remove(0);
+            File[] children = root.listFiles();
+            if (children != null) {
+                for (File child : children) {
+                    if (child.isFile() && filter.accept(child)) {
+                        files.add(child);
+                    } else if (child.isDirectory()) {
+                        roots.add(child);
+                    }
+                }
+            }
+        }
+    }
+
+}
diff --git a/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrInstall.java b/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrInstall.java
index a2b1566..02216b2 100644
--- a/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrInstall.java
+++ b/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrInstall.java
@@ -40,7 +40,7 @@
  * 
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public final class ObrInstall extends AbstractMojo
+public final class  ObrInstall extends AbstractMojo
 {
     /**
      * OBR Repository.
diff --git a/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrRemoteClean.java b/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrRemoteClean.java
index 86e840f..5363d89 100644
--- a/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrRemoteClean.java
+++ b/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrRemoteClean.java
@@ -389,7 +389,7 @@
     /**
      * Open an XML file.
      * 
-     * @param filename : XML file path
+     * @param file : XML file
      * @param constructor DocumentBuilder get from xerces
      * @return Document which describes this file
      * @throws MojoExecutionException occurs when the given file cannot be opened or is a valid XML file.
diff --git a/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrUpdate.java b/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrUpdate.java
index 51472f4..3a66cfe 100644
--- a/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrUpdate.java
+++ b/bundleplugin/src/main/java/org/apache/felix/obrplugin/ObrUpdate.java
@@ -20,34 +20,26 @@
 
 
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
 import java.net.URI;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Properties;
 
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.Result;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.bundlerepository.impl.DataModelHelperImpl;
+import org.apache.felix.bundlerepository.impl.PullParser;
+import org.apache.felix.bundlerepository.impl.RepositoryImpl;
+import org.apache.felix.bundlerepository.impl.RepositoryParser;
+import org.apache.felix.bundlerepository.impl.ResourceImpl;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
 import org.codehaus.plexus.util.FileUtils;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
+import org.kxml2.io.KXmlParser;
+import org.xmlpull.v1.XmlPullParser;
 
 
 /**
@@ -57,11 +49,6 @@
 public class ObrUpdate
 {
     /**
-     * generate the date format to insert it in repository descriptor file.
-     */
-    static SimpleDateFormat m_format = new SimpleDateFormat( "yyyyMMddHHmmss.SSS" );
-
-    /**
      * logger for this plugin.
      */
     private Log m_logger;
@@ -87,19 +74,14 @@
     private Config m_userConfig;
 
     /**
-     * used to build another xml document.
-     */
-    private DocumentBuilder m_documentBuilder;
-
-    /**
      * root on parent document.
      */
-    private Document m_repositoryDoc;
+    private RepositoryImpl m_repository;
 
     /**
      * used to store bundle information.
      */
-    private ResourcesBundle m_resourceBundle;
+    private ResourceImpl m_resourceBundle;
 
     /**
      * base URI used to relativize bundle URIs.
@@ -134,8 +116,6 @@
         {
             m_baseURI = m_repositoryXml;
         }
-
-        m_documentBuilder = initDocumentBuilder();
     }
 
 
@@ -157,13 +137,11 @@
         m_logger.debug( " (f) sourceJar = " + sourceJar );
         m_logger.debug( " (f) obrXml = " + m_obrXml );
 
-        if ( m_repositoryDoc == null )
+        if ( m_repository == null )
         {
             return;
         }
 
-        m_resourceBundle = new ResourcesBundle( m_logger );
-
         // get the file size
         File bundleFile = new File( bundleJar );
         if ( bundleFile.exists() )
@@ -187,8 +165,17 @@
                 m_logger.info( "Installing " + resourceURI );
             }
 
-            m_resourceBundle.setSize( String.valueOf( bundleFile.length() ) );
-            m_resourceBundle.setUri( resourceURI.toASCIIString() );
+            try
+            {
+                m_resourceBundle = (ResourceImpl) new DataModelHelperImpl().createResource( bundleJar.toURL() );
+            }
+            catch (IOException e)
+            {
+                throw new MojoExecutionException("Unable to load resource information", e);
+            }
+
+            m_resourceBundle.put( Resource.SIZE, String.valueOf( bundleFile.length() ) );
+            m_resourceBundle.put( Resource.URI, resourceURI.toASCIIString() );
         }
         else
         {
@@ -201,47 +188,51 @@
         {
             m_logger.info( "Adding " + m_obrXml );
 
+            try
+            {
+                KXmlParser kxp = new KXmlParser();
+                kxp.setInput(new FileInputStream(new File(m_obrXml)), null);
+                PullParser parser = new PullParser();
+                for (int event = kxp.nextTag(); event != XmlPullParser.START_TAG; event = kxp.nextTag())
+                {
+                    if (RepositoryParser.CATEGORY.equals(kxp.getName()))
+                    {
+                        m_resourceBundle.addCategory(parser.parseCategory(kxp));
+                    }
+                    else if (RepositoryParser.REQUIRE.equals(kxp.getName()))
+                    {
+                        m_resourceBundle.addRequire(parser.parseRequire(kxp));
+                    }
+                    else if (RepositoryParser.CAPABILITY.equals(kxp.getName()))
+                    {
+                        m_resourceBundle.addCapability(parser.parseCapability(kxp));
+                    }
+                    else
+                    {
+                        parser.ignoreTag(kxp);
+                    }
+                }
+
+            }
+            catch (Exception e)
+            {
+                throw new MojoExecutionException("Unable to parse obr xml: " + m_obrXml, e);
+            }
             // URL url = getClass().getResource("/SchemaObr.xsd");
             // TODO validate obr.xml file
 
-            Document obrXmlDoc = parseFile( m_obrXml, m_documentBuilder );
-            if ( obrXmlDoc == null )
-            {
-                return;
-            }
-
-            Node obrXmlRoot = obrXmlDoc.getDocumentElement();
-
             // add contents to resource bundle
-            sortObrXml( obrXmlRoot );
-        }
-
-        ExtractBindexInfo bindexExtractor;
-        try
-        {
-            // use bindex to extract bundle information
-            bindexExtractor = new ExtractBindexInfo( m_repositoryXml, bundleJar.getPath() );
-        }
-        catch ( MojoExecutionException e )
-        {
-            m_logger.error( "unable to build Bindex informations" );
-            e.printStackTrace();
-
-            throw new MojoExecutionException( "BindexException" );
+            parseObrXml();
         }
 
         String sourcePath = relativisePath( sourceJar );
         String docPath = relativisePath( docJar );
 
-        m_resourceBundle.construct( m_project, bindexExtractor, sourcePath, docPath );
+//        m_resourceBundle.construct( m_project, bindexExtractor, sourcePath, docPath );
+//         TODO: rebuild wrt m_project
 
-        Element rootElement = m_repositoryDoc.getDocumentElement();
-        if ( !walkOnTree( rootElement ) )
-        {
-            // the correct resource node was not found, we must create it
-            String id = m_resourceBundle.getId();
-            searchRepository( rootElement, id );
-        }
+        m_repository.addResource( m_resourceBundle );
+        m_repository.setLastModified(System.currentTimeMillis());
     }
 
 
@@ -265,250 +256,37 @@
     {
         m_logger.info( "Writing OBR metadata" );
 
-        writeToFile( m_repositoryXml, m_repositoryDoc );
-    }
-
-
-    /**
-     * init the document builder from xerces.
-     * @return DocumentBuilder ready to create new document
-     */
-    private DocumentBuilder initDocumentBuilder()
-    {
-        DocumentBuilder documentBuilder = null;
-        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        File file = null;
+        Writer writer;
         try
         {
-            documentBuilder = factory.newDocumentBuilder();
-        }
-        catch ( ParserConfigurationException e )
-        {
-            m_logger.error( "unable to create a new xml document" );
-            e.printStackTrace();
-        }
-        return documentBuilder;
-
-    }
-
-
-    /**
-     * Parse the repository descriptor file.
-     * 
-     * @return true if the repository file was parsed, otherwise false
-     * @throws MojoExecutionException if the plugin failed
-     */
-    public boolean parseRepositoryXml() throws MojoExecutionException
-    {
-        File fout = new File( m_repositoryXml );
-        if ( !fout.exists() )
-        {
-            Document doc = m_documentBuilder.newDocument();
-
-            // create xml tree
-            Date d = new Date();
-            d.setTime( System.currentTimeMillis() );
-            Element root = doc.createElement( "repository" );
-            root.setAttribute( "lastmodified", m_format.format( d ) );
-            root.setAttribute( "name", "MyRepository" );
-            try
-            {
-                writeToFile( m_repositoryXml, root );
-            }
-            catch ( MojoExecutionException e )
-            {
-                e.printStackTrace();
-                throw new MojoExecutionException( "IOException" );
-            }
-        }
-
-        m_repositoryDoc = parseFile( m_repositoryXml, m_documentBuilder );
-
-        return ( null != m_repositoryDoc );
-    }
-
-
-    /**
-     * transform a xml file to a xerces Document.
-     * @param filename path to the xml file
-     * @param documentBuilder DocumentBuilder get from xerces
-     * @return Document which describe this file
-     */
-    private Document parseFile( URI filename, DocumentBuilder documentBuilder )
-    {
-        if ( documentBuilder == null )
-        {
-            return null;
-        }
-        // The document is the root of the DOM tree.
-        m_logger.info( "Parsing " + filename );
-        Document doc = null;
-        try
-        {
-            doc = documentBuilder.parse( new File( filename ) );
-        }
-        catch ( SAXException e )
-        {
-            e.printStackTrace();
-            return null;
+            file = File.createTempFile( "repository", ".xml" );
+            writer = new OutputStreamWriter( new FileOutputStream( file ) );
         }
         catch ( IOException e )
         {
-            m_logger.error( "cannot open file: " + filename );
+            m_logger.error( "Unable to write to file: " + file.getName() );
             e.printStackTrace();
-            return null;
+            throw new MojoExecutionException( "Unable to write to file: " + file.getName() + " : " + e.getMessage() );
         }
-        return doc;
-    }
 
-
-    /**
-     * put the information from obr.xml into ressourceBundle object.
-     * @param node Node to the OBR.xml file
-     */
-    private void sortObrXml( Node node )
-    {
-        if ( node.getNodeName().compareTo( "require" ) == 0 )
-        {
-            Require newRequireNode = new Require();
-            NamedNodeMap list = node.getAttributes();
-            try
-            {
-                newRequireNode.setExtend( list.getNamedItem( "extend" ).getNodeValue() );
-                newRequireNode.setMultiple( list.getNamedItem( "multiple" ).getNodeValue() );
-                newRequireNode.setOptional( list.getNamedItem( "optional" ).getNodeValue() );
-                newRequireNode.setFilter( list.getNamedItem( "filter" ).getNodeValue() );
-                newRequireNode.setName( list.getNamedItem( "name" ).getNodeValue() );
-            }
-            catch ( NullPointerException e )
-            {
-                m_logger
-                    .error( "the obr.xml file seems to be invalid in a \"require\" tag (one or more attributes are missing)" );
-                // e.printStackTrace();
-            }
-            newRequireNode.setValue( XmlHelper.getTextContent( node ) );
-            m_resourceBundle.addRequire( newRequireNode );
-        }
-        else if ( node.getNodeName().compareTo( "capability" ) == 0 )
-        {
-            Capability newCapability = new Capability();
-            try
-            {
-                newCapability.setName( node.getAttributes().getNamedItem( "name" ).getNodeValue() );
-            }
-            catch ( NullPointerException e )
-            {
-                m_logger.error( "attribute \"name\" is missing in obr.xml in a \"capability\" tag" );
-                e.printStackTrace();
-            }
-            NodeList list = node.getChildNodes();
-            for ( int i = 0; i < list.getLength(); i++ )
-            {
-                PElement p = new PElement();
-                Node n = list.item( i );
-                Node item = null;
-                // System.err.println(n.getNodeName());
-                if ( n.getNodeName().compareTo( "p" ) == 0 )
-                {
-
-                    p.setN( n.getAttributes().getNamedItem( "n" ).getNodeValue() );
-                    item = n.getAttributes().getNamedItem( "t" );
-                    if ( item != null )
-                    {
-                        p.setT( item.getNodeValue() );
-                    }
-                    item = n.getAttributes().getNamedItem( "v" );
-                    if ( item != null )
-                    {
-                        p.setV( item.getNodeValue() );
-                    }
-
-                    newCapability.addP( p );
-                }
-            }
-            m_resourceBundle.addCapability( newCapability );
-        }
-        else if ( node.getNodeName().compareTo( "category" ) == 0 )
-        {
-            Category newCategory = new Category();
-            newCategory.setId( node.getAttributes().getNamedItem( "id" ).getNodeValue() );
-            m_resourceBundle.addCategory( newCategory );
-        }
-        else
-        {
-            NodeList list = node.getChildNodes();
-            for ( int i = 0; i < list.getLength(); i++ )
-            {
-                sortObrXml( list.item( i ) );
-            }
-        }
-    }
-
-
-    /**
-     * write a Node in a xml file.
-     * @param outputFilename URI to the output file
-     * @param treeToBeWrite Node root of the tree to be write in file
-     * @throws MojoExecutionException if the plugin failed
-     */
-    private void writeToFile( URI outputFilename, Node treeToBeWrite ) throws MojoExecutionException
-    {
-        // init the transformer
-        Transformer transformer = null;
-        TransformerFactory tfabrique = TransformerFactory.newInstance();
         try
         {
-            transformer = tfabrique.newTransformer();
-        }
-        catch ( TransformerConfigurationException e )
-        {
-            m_logger.error( "Unable to write to file: " + outputFilename.toString() );
-            e.printStackTrace();
-            throw new MojoExecutionException( "TransformerConfigurationException" );
-        }
-
-        Properties proprietes = new Properties();
-        proprietes.put( "method", "xml" );
-        proprietes.put( "version", "1.0" );
-        proprietes.put( "encoding", "ISO-8859-1" );
-        proprietes.put( "standalone", "yes" );
-        proprietes.put( "indent", "yes" );
-        proprietes.put( "omit-xml-declaration", "no" );
-        transformer.setOutputProperties( proprietes );
-
-        DOMSource input = new DOMSource( treeToBeWrite );
-
-        File fichier = null;
-        FileOutputStream flux = null;
-        try
-        {
-            fichier = File.createTempFile( "repository", ".xml" );
-            flux = new FileOutputStream( fichier );
+            new DataModelHelperImpl().writeRepository(m_repository, writer);
         }
         catch ( IOException e )
         {
-            m_logger.error( "Unable to write to file: " + fichier.getName() );
-            e.printStackTrace();
-            throw new MojoExecutionException( "Unable to write to file: " + fichier.getName() + " : " + e.getMessage() );
-        }
-        Result output = new StreamResult( flux );
-        try
-        {
-            transformer.transform( input, output );
-        }
-        catch ( TransformerException e )
-        {
-            e.printStackTrace();
-            throw new MojoExecutionException( "TransformerException" );
+            throw new MojoExecutionException( "Unable to write repository xml", e );
         }
 
         try
         {
-            flux.flush();
-            flux.close();
+            writer.flush();
+            writer.close();
 
-            File outputFile = new File( outputFilename );
+            File outputFile = new File( m_repositoryXml );
             outputFile.getParentFile().mkdirs();
-            FileUtils.rename( fichier, outputFile );
+            FileUtils.rename( file, outputFile );
         }
         catch ( IOException e )
         {
@@ -519,87 +297,83 @@
     }
 
 
-    /**
-     * walk on the tree until the targeted node was found.
-     * @param node targeted node
-     * @return true if the requiered node was found else false.
+   /**
+     * Parse the repository descriptor file.
+     *
+     * @throws MojoExecutionException if the plugin failed
      */
-    private boolean walkOnTree( Node node )
+    public void parseRepositoryXml() throws MojoExecutionException
     {
-        if ( node.getNodeName().compareTo( "resource" ) == 0 )
+        File fout = new File( m_repositoryXml );
+        if ( !fout.exists() )
         {
-            return resource( node );
+            m_repository = new RepositoryImpl();
+            writeRepositoryXml();
         }
-
-        // look at the repository node (first in the file)
-        if ( node.getNodeName().compareTo( "repository" ) == 0 )
+        else
         {
-            Date d = new Date();
-            d.setTime( System.currentTimeMillis() );
-            NamedNodeMap nList = node.getAttributes();
-            Node n = nList.getNamedItem( "lastmodified" );
-            n.setNodeValue( m_format.format( d ) );
-        }
-
-        NodeList list = node.getChildNodes();
-        if ( list.getLength() > 0 )
-        {
-            for ( int i = 0; i < list.getLength(); i++ )
+            try
             {
-                if ( walkOnTree( list.item( i ) ) )
-                {
-                    return true;
-                }
+                m_repository = (RepositoryImpl) new DataModelHelperImpl().repository( m_repositoryXml.toURL() );
             }
-        }
-
-        return false;
-    }
-
-
-    /**
-     * put the resource bundle in the tree.
-     * @param node Node on the xml file
-     * @param id id of the bundle ressource
-     */
-    private void searchRepository( Node node, String id )
-    {
-        if ( node.getNodeName().compareTo( "repository" ) == 0 )
-        {
-            node.appendChild( m_resourceBundle.getNode( m_repositoryDoc ) );
-            return;
-        }
-
-        m_logger.info( "Second branch..." );
-        NodeList list = node.getChildNodes();
-        if ( list.getLength() > 0 )
-        {
-            for ( int i = 0; i < list.getLength(); i++ )
+            catch ( Exception e )
             {
-                searchRepository( list.item( i ), id );
+                throw new MojoExecutionException( "Unable to read repository xml: " + m_repositoryXml, e );
             }
         }
     }
 
 
     /**
-     * compare two node and update the array which compute the smallest free id.
-     * @param node : node
-     * @return true if the node is the same bundle than the ressourceBundle, else false.
+     * put the information from obr.xml into ressourceBundle object.
      */
-    private boolean resource( Node node )
-    {
-        // this part save all the id free if we need to add resource
-        String id = node.getAttributes().getNamedItem( "id" ).getNodeValue();
-        NamedNodeMap map = node.getAttributes();
-
-        if ( m_resourceBundle.isSameBundleResource( map.getNamedItem( "symbolicname" ).getNodeValue(), map
-            .getNamedItem( "version" ).getNodeValue() ) )
+    private void parseObrXml() throws MojoExecutionException {
+        try
         {
-            m_resourceBundle.setId( String.valueOf( id ) );
-            node.getParentNode().replaceChild( m_resourceBundle.getNode( m_repositoryDoc ), node );
-            return true;
+            InputStream is = new FileInputStream(new File(m_obrXml));
+            try
+            {
+                KXmlParser kxp = new KXmlParser();
+                kxp.setInput(is, null);
+                kxp.nextTag();
+                parseObrXml(kxp);
+            }
+            finally
+            {
+                is.close();
+            }
         }
-        return false;
+        catch (Exception e)
+        {
+            throw new MojoExecutionException("Unable to parse obr xml: " + m_obrXml, e);
+        }
     }
+
+    private void parseObrXml(KXmlParser kxp) throws Exception
+    {
+        PullParser parser = new PullParser();
+        while (kxp.getEventType() == XmlPullParser.START_TAG)
+        {
+            if (RepositoryParser.CATEGORY.equals(kxp.getName()))
+            {
+                m_resourceBundle.addCategory(parser.parseCategory(kxp));
+            }
+            else if (RepositoryParser.REQUIRE.equals(kxp.getName()))
+            {
+                m_resourceBundle.addRequire(parser.parseRequire(kxp));
+            }
+            else if (RepositoryParser.CAPABILITY.equals(kxp.getName()))
+            {
+                m_resourceBundle.addCapability(parser.parseCapability(kxp));
+            }
+            else
+            {
+                kxp.nextTag();
+                parseObrXml(kxp);
+            }
+            kxp.nextTag();
+        }
+    }
+
+
 }
diff --git a/bundleplugin/src/main/java/org/apache/felix/obrplugin/PElement.java b/bundleplugin/src/main/java/org/apache/felix/obrplugin/PElement.java
deleted file mode 100644
index 2748dfb..0000000
--- a/bundleplugin/src/main/java/org/apache/felix/obrplugin/PElement.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.obrplugin;
-
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-
-/**
- * this class describe the p element in a capability tag.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- * 
- */
-public class PElement
-{
-    /**
-     * store the v tag (value).
-     */
-    private String m_v;
-
-    /**
-     * store the t tag (type).
-     */
-    private String m_t;
-
-    /**
-     * store the n tag (name).
-     */
-    private String m_n;
-
-
-    /**
-     * get the n tag.
-     * @return attribute n
-     */
-    public String getN()
-    {
-        return m_n;
-    }
-
-
-    /**
-     * set the n tage.
-     * @param n new value
-     */
-    public void setN( String n )
-    {
-        m_n = n;
-    }
-
-
-    /**
-     * get the t tag.
-     * @return attribute t
-     */
-    public String getT()
-    {
-        return m_t;
-    }
-
-
-    /**
-     * set the t tag.
-     * @param t new value
-     */
-    public void setT( String t )
-    {
-        m_t = t;
-    }
-
-
-    /**
-     * get the v tag.
-     * @return attribute v
-     */
-    public String getV()
-    {
-        return m_v;
-    }
-
-
-    /**
-     * set the v tag.
-     * @param v new value
-     */
-    public void setV( String v )
-    {
-        m_v = v;
-    }
-
-
-    /**
-     * transform this object to node.
-     * @param father father document for create Node
-     * @return node
-     */
-    public Node getNode( Document father )
-    {
-        Element p = father.createElement( "p" );
-        p.setAttribute( "n", getN() );
-        if ( getT() != null )
-        {
-            p.setAttribute( "t", getT() );
-        }
-
-        if ( getV() != null )
-        {
-            p.setAttribute( "v", getV() );
-        }
-
-        return p;
-    }
-}
diff --git a/bundleplugin/src/main/java/org/apache/felix/obrplugin/RemoteFileManager.java b/bundleplugin/src/main/java/org/apache/felix/obrplugin/RemoteFileManager.java
index f9be14e..c05be54 100644
--- a/bundleplugin/src/main/java/org/apache/felix/obrplugin/RemoteFileManager.java
+++ b/bundleplugin/src/main/java/org/apache/felix/obrplugin/RemoteFileManager.java
@@ -337,7 +337,6 @@
 
     /**
      * this method indicates if the targeted file is locked or not.
-     * @param remote connection manager
      * @param fileName name targeted
      * @return  true if the required file is locked, else false
      * @throws MojoExecutionException
diff --git a/bundleplugin/src/main/java/org/apache/felix/obrplugin/Require.java b/bundleplugin/src/main/java/org/apache/felix/obrplugin/Require.java
deleted file mode 100644
index 9b44f9d..0000000
--- a/bundleplugin/src/main/java/org/apache/felix/obrplugin/Require.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.obrplugin;
-
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-
-/**
- * this class store a Require tag.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class Require
-{
-
-    /**
-     * store the extend attribute.
-     */
-    private String m_extend;
-
-    /**
-     * store the multiple attribute.
-     */
-    private String m_multiple;
-
-    /**
-     * store the optional attribute.
-     */
-    private String m_optional;
-
-    /**
-     * store the name attribute.
-     */
-    private String m_name;
-
-    /**
-     * store the filter attribute.
-     */
-    private String m_filter;
-
-    /**
-     * store the value of the tag.
-     */
-    private String m_value;
-
-
-    /**
-     * get the extend attribute.
-     * @return a string which contains the value of the boolean
-     */
-    public String getExtend()
-    {
-        return m_extend;
-    }
-
-
-    /**
-     * set the extend attribute.
-     * @param extend new value for the extend attribute
-     */
-    public void setExtend( String extend )
-    {
-        m_extend = extend;
-    }
-
-
-    /**
-     * get the filter attribute.
-     * @return m_filter value
-     */
-    public String getFilter()
-    {
-        return m_filter;
-    }
-
-
-    /**
-     * set the filter attribute.
-     * @param filter new value for filter
-     */
-    public void setFilter( String filter )
-    {
-        m_filter = filter;
-    }
-
-
-    /**
-     * get multiple attribute.
-     * @return m_multiple value
-     */
-    public String getMultiple()
-    {
-        return m_multiple;
-    }
-
-
-    /**
-     * set multiple attribute.
-     * @param multiple new value for m_multiple
-     */
-    public void setMultiple( String multiple )
-    {
-        m_multiple = multiple;
-    }
-
-
-    /**
-     * get name attribute.
-     * @return m_name value
-     */
-    public String getName()
-    {
-        return m_name;
-    }
-
-
-    /**
-     * set name attribute.
-     * @param name new value for m_name
-     */
-    public void setName( String name )
-    {
-        m_name = name;
-    }
-
-
-    /**
-     * get the optional attribute.
-     * @return m_optional value
-     */
-    public String getOptional()
-    {
-        return m_optional;
-    }
-
-
-    /**
-     * set the optional attribute.
-     * @param optionnal new value for m_optional
-     */
-    public void setOptional( String optionnal )
-    {
-        m_optional = optionnal;
-    }
-
-
-    /**
-     * get value of the tag.
-     * @return value of this tag
-     */
-    public String getValue()
-    {
-        return m_value;
-    }
-
-
-    /**
-     * set the value of the tag.
-     * @param value new value for this tag
-     */
-    public void setValue( String value )
-    {
-        m_value = value;
-    }
-
-
-    /**
-     * transform this object to Node.
-     * 
-     * @param father father document for create Node
-     * @return node
-     */
-    public Node getNode( Document father )
-    {
-        Element require = father.createElement( "require" );
-        require.setAttribute( "name", getName() );
-        require.setAttribute( "filter", getFilter() );
-        require.setAttribute( "extend", getExtend() );
-        require.setAttribute( "multiple", getMultiple() );
-        require.setAttribute( "optional", getOptional() );
-        XmlHelper.setTextContent( require, getValue() );
-
-        return require;
-    }
-
-}
diff --git a/bundleplugin/src/main/java/org/apache/felix/obrplugin/ResourcesBundle.java b/bundleplugin/src/main/java/org/apache/felix/obrplugin/ResourcesBundle.java
deleted file mode 100644
index 22d3538..0000000
--- a/bundleplugin/src/main/java/org/apache/felix/obrplugin/ResourcesBundle.java
+++ /dev/null
@@ -1,708 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.obrplugin;
-
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.maven.plugin.logging.Log;
-import org.apache.maven.project.MavenProject;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-
-/**
- * this class describe all information by bundle.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class ResourcesBundle
-{
-    /**
-     * store the bundle symbolic name.
-     */
-    private String m_symbolicName;
-
-    /**
-     * store the bundle presentation name.
-     */
-    private String m_presentationName;
-
-    /**
-     * store the bundle version.
-     */
-    private String m_version;
-
-    /**
-     * store the bundle URI.
-     */
-    private String m_uri;
-
-    /**
-     * store the bundle description.
-     */
-    private String m_description;
-
-    /**
-     * store the bundle size.
-     */
-    private String m_size;
-
-    /**
-     * store the bundle documentation.
-     */
-    private String m_documentation;
-
-    /**
-     * store the bundle source.
-     */
-    private String m_source;
-
-    /**
-     * store the bundle javadoc.
-     */
-    private String m_javadoc;
-
-    /**
-     * store the bundle license.
-     */
-    private String m_license;
-
-    /**
-     * store the bundle id.
-     */
-    private String m_id;
-
-    /**
-     * store the bundle categories.
-     */
-    private List m_category = new ArrayList();
-
-    /**
-     * store the bundle capabilities.
-     */
-    private List m_capability = new ArrayList();
-
-    /**
-     * store the bundle requirement.
-     */
-    private List m_require = new ArrayList();
-
-    /**
-     * get the plugin logger.
-     */
-    private Log m_logger;
-
-
-    /**
-     * initialize logger.
-     * @param log log use by plugin
-     */
-    public ResourcesBundle( Log log )
-    {
-        m_logger = log;
-    }
-
-
-    public List getCapability()
-    {
-        return m_capability;
-    }
-
-
-    public void setCapability( List capability )
-    {
-        m_capability = capability;
-    }
-
-
-    public List getCategory()
-    {
-        return m_category;
-    }
-
-
-    public void setCategory( List category )
-    {
-        m_category = category;
-    }
-
-
-    public String getLicense()
-    {
-        return m_license;
-    }
-
-
-    public void setLicense( String license )
-    {
-        m_license = license;
-    }
-
-
-    public String getDescription()
-    {
-        return m_description;
-    }
-
-
-    public void setDescription( String description )
-    {
-        m_description = description;
-    }
-
-
-    public String getDocumentation()
-    {
-        return m_documentation;
-    }
-
-
-    public void setDocumentation( String documentation )
-    {
-        m_documentation = documentation;
-    }
-
-
-    public String getPresentationName()
-    {
-        return m_presentationName;
-    }
-
-
-    public void setPresentationName( String name )
-    {
-        m_presentationName = name;
-    }
-
-
-    public String getSize()
-    {
-        return m_size;
-    }
-
-
-    public void setSize( String size )
-    {
-        m_size = size;
-    }
-
-
-    public String getSymbolicName()
-    {
-        return m_symbolicName;
-    }
-
-
-    public void setSymbolicName( String name )
-    {
-        m_symbolicName = name;
-    }
-
-
-    public String getUri()
-    {
-        return m_uri;
-    }
-
-
-    public void setUri( String url )
-    {
-        m_uri = url;
-    }
-
-
-    public String getVersion()
-    {
-        return m_version;
-    }
-
-
-    public void setVersion( String version )
-    {
-        m_version = version;
-    }
-
-
-    public List getRequire()
-    {
-        return m_require;
-    }
-
-
-    public void setRequire( List require )
-    {
-        m_require = require;
-    }
-
-
-    public String getSource()
-    {
-        return m_source;
-    }
-
-
-    public void setSource( String source )
-    {
-        m_source = source;
-    }
-
-
-    public String getJavadoc()
-    {
-        return m_javadoc;
-    }
-
-
-    public void setJavadoc( String javadoc )
-    {
-        m_javadoc = javadoc;
-    }
-
-
-    public String getId()
-    {
-        return m_id;
-    }
-
-
-    public void setId( String id )
-    {
-        m_id = id;
-    }
-
-
-    /**
-     * add a new capability for this bundle description.
-     * @param capability the Capability to add
-     */
-    public void addCapability( Capability capability )
-    {
-        m_capability.add( capability );
-    }
-
-
-    /**
-     * add a new requirement for this bundle description.
-     * @param require th Require to add
-     */
-    public void addRequire( Require require )
-    {
-        m_require.add( require );
-    }
-
-
-    /**
-     * add a new category for this bundle decription.
-     * @param category the Category to add
-     */
-    public void addCategory( Category category )
-    {
-        m_category.add( category );
-    }
-
-
-    /**
-     * transform this object to Node.
-     * tranform all sub-object to node also
-     * @param father father document for create Node
-     * @return node
-     */
-    public Node getNode( Document father )
-    {
-        // return the complete resource tree
-        if ( !isValid() || getId() == null )
-        {
-            m_logger.error( "those properties was not defined:" + getInvalidProperties() );
-            return null;
-        }
-
-        Element resource = father.createElement( "resource" );
-        Element description = father.createElement( "description" );
-        Element size = father.createElement( "size" );
-        Element documentation = father.createElement( "documentation" );
-        Element source = father.createElement( "source" );
-        Element javadoc = father.createElement( "javadoc" );
-        Element license = father.createElement( "license" );
-
-        resource.setAttribute( "id", getId() );
-        resource.setAttribute( "symbolicname", getSymbolicName() );
-        resource.setAttribute( "presentationname", getPresentationName() );
-        resource.setAttribute( "uri", getUri() );
-        resource.setAttribute( "version", getVersion() );
-
-        XmlHelper.setTextContent( description, getDescription() );
-        resource.appendChild( description );
-
-        XmlHelper.setTextContent( size, getSize() );
-        resource.appendChild( size );
-
-        if ( getDocumentation() != null )
-        {
-            XmlHelper.setTextContent( documentation, getDocumentation() );
-            resource.appendChild( documentation );
-        }
-
-        if ( getSource() != null )
-        {
-            XmlHelper.setTextContent( source, getSource() );
-            resource.appendChild( source );
-        }
-
-        if ( getJavadoc() != null )
-        {
-            XmlHelper.setTextContent( javadoc, getJavadoc() );
-            resource.appendChild( javadoc );
-        }
-
-        if ( getLicense() != null )
-        {
-            XmlHelper.setTextContent( license, getLicense() );
-            resource.appendChild( license );
-        }
-
-        List list = getNodeCategories( father );
-        for ( int i = 0; i < list.size(); i++ )
-        {
-            resource.appendChild( ( Node ) list.get( i ) );
-        }
-
-        list = getNodeCapabilities( father );
-        for ( int i = 0; i < list.size(); i++ )
-        {
-            resource.appendChild( ( Node ) list.get( i ) );
-        }
-
-        list = getNodeRequirement( father );
-        for ( int i = 0; i < list.size(); i++ )
-        {
-            resource.appendChild( ( Node ) list.get( i ) );
-        }
-
-        return resource;
-    }
-
-
-    /**
-     * this method gets information form pom.xml to complete missing data from those given by user.
-     * @param project project information given by maven
-     * @param ebi bundle information extracted from bindex
-     * @param sourcePath path to local sources
-     * @param javadocPath path to local javadocs
-     * @return true
-     */
-    public boolean construct( MavenProject project, ExtractBindexInfo ebi, String sourcePath, String javadocPath )
-    {
-
-        if ( ebi.getPresentationName() != null )
-        {
-            setPresentationName( ebi.getPresentationName() );
-            if ( project.getName() != null )
-            {
-                m_logger.debug( "pom property override:<presentationname> " + project.getName() );
-            }
-        }
-        else
-        {
-            setPresentationName( project.getName() );
-        }
-
-        if ( ebi.getSymbolicName() != null )
-        {
-            setSymbolicName( ebi.getSymbolicName() );
-            if ( project.getArtifactId() != null )
-            {
-                m_logger.debug( "pom property override:<symbolicname> " + project.getArtifactId() );
-            }
-        }
-        else
-        {
-            setSymbolicName( project.getArtifactId() );
-        }
-
-        if ( ebi.getVersion() != null )
-        {
-            setVersion( ebi.getVersion() );
-            if ( project.getVersion() != null )
-            {
-                m_logger.debug( "pom property override:<version> " + project.getVersion() );
-            }
-        }
-        else
-        {
-            setVersion( project.getVersion() );
-        }
-
-        if ( ebi.getId() != null )
-        {
-            setId( ebi.getId() );
-        }
-
-        if ( ebi.getDescription() != null )
-        {
-            setDescription( ebi.getDescription() );
-            if ( project.getDescription() != null )
-            {
-                m_logger.debug( "pom property override:<description> " + project.getDescription() );
-            }
-        }
-        else
-        {
-            setDescription( project.getDescription() );
-        }
-
-        // fallback to javadoc if no project URL
-        String documentation = project.getUrl();
-        if ( null == documentation )
-        {
-            documentation = javadocPath;
-        }
-
-        if ( ebi.getDocumentation() != null )
-        {
-            setDocumentation( ebi.getDocumentation() );
-            if ( documentation != null )
-            {
-                m_logger.debug( "pom property override:<documentation> " + documentation );
-            }
-        }
-        else
-        {
-            setDocumentation( documentation );
-        }
-
-        if ( ebi.getSource() != null )
-        {
-            setSource( ebi.getSource() );
-            if ( sourcePath != null )
-            {
-                m_logger.debug( "pom property override:<source> " + sourcePath );
-            }
-        }
-        else
-        {
-            setSource( sourcePath );
-        }
-
-        setJavadoc( javadocPath );
-
-        if ( ebi.getLicense() != null )
-        {
-            setLicense( ebi.getLicense() );
-            String lic = null;
-            List l = project.getLicenses();
-            Iterator it = l.iterator();
-            while ( it.hasNext() )
-            {
-                if ( it.next() != null )
-                {
-                    m_logger.debug( "pom property override:<license> " + lic );
-                    break;
-                }
-            }
-        }
-        else
-        {
-            String lic = null;
-            List l = project.getLicenses();
-            Iterator it = l.iterator();
-            while ( it.hasNext() )
-            {
-                lic = it.next() + ";";
-            }
-
-            setLicense( lic );
-        }
-
-        // create the first capability (ie : bundle)
-        Capability capability = new Capability();
-        capability.setName( "bundle" );
-        PElement p = new PElement();
-        p.setN( "manifestversion" );
-        p.setV( "2" );
-        capability.addP( p );
-
-        p = new PElement();
-        p.setN( "presentationname" );
-        p.setV( getPresentationName() );
-        capability.addP( p );
-
-        p = new PElement();
-        p.setN( "symbolicname" );
-        p.setV( getSymbolicName() );
-        capability.addP( p );
-
-        p = new PElement();
-        p.setN( "version" );
-        p.setT( "version" );
-        p.setV( getVersion() );
-        capability.addP( p );
-
-        addCapability( capability );
-
-        List capabilities = ebi.getCapabilities();
-        for ( int i = 0; i < capabilities.size(); i++ )
-        {
-            addCapability( ( Capability ) capabilities.get( i ) );
-        }
-
-        List requirement = ebi.getRequirement();
-        for ( int i = 0; i < requirement.size(); i++ )
-        {
-            addRequire( ( Require ) requirement.get( i ) );
-        }
-
-        List categories = ebi.getCategories();
-        for ( int i = 0; i < categories.size(); i++ )
-        {
-            addCategory( ( Category ) categories.get( i ) );
-        }
-
-        // we also add the goupId
-        Category category = new Category();
-        category.setId( project.getGroupId() );
-        addCategory( category );
-
-        return true;
-    }
-
-
-    /**
-     * return if the bundle resource is complete.
-     * @return false if an information is missing, else true
-     */
-    public boolean isValid()
-    {
-        // we must verify required properties are present
-        return getPresentationName() != null && getSymbolicName() != null && getVersion() != null && getUri() != null
-            && getSize() != null;
-    }
-
-
-    /**
-     * test if this bundle has the same symbolicname, and version number.
-     * @param symbolicName symbolicName to compare with current bundle
-     * @param presentationName presentationName to compare with current bundlde
-     * @param version version to compare with current bundle
-     * @return true if the information are the same, else false
-     */
-    public boolean isSameBundleResource( String symbolicName, String version )
-    {
-        if ( isValid() )
-        {
-            return ( symbolicName.compareTo( getSymbolicName() ) == 0 ) && ( version.compareTo( getVersion() ) == 0 );
-        }
-
-        return false;
-    }
-
-
-    /**
-     * return a list of categories transformed to node.
-     * @param father father document to create node from same document
-     * @return List of Node
-     */
-    private List getNodeCategories( Document father )
-    {
-        List listNode = new ArrayList();
-        List listCategory = getCategory();
-        for ( int i = 0; i < listCategory.size(); i++ )
-        {
-            listNode.add( ( ( Category ) listCategory.get( i ) ).getNode( father ) );
-        }
-        return listNode;
-    }
-
-
-    /**
-     * return a list of capabilities transformed to node.
-     * @param father father document to create node from same document
-     * @return List of Node
-     */
-    private List getNodeCapabilities( Document father )
-    {
-        List listNode = new ArrayList();
-        List listCapability = getCapability();
-        for ( int i = 0; i < listCapability.size(); i++ )
-        {
-            listNode.add( ( ( Capability ) listCapability.get( i ) ).getNode( father ) );
-        }
-        return listNode;
-    }
-
-
-    /**
-     * return a list of requirement transformed to node.
-     * @param father father document to create node from same document
-     * @return List of Node.
-     */
-    private List getNodeRequirement( Document father )
-    {
-        List listNode = new ArrayList();
-        List listRequirement = getRequire();
-        for ( int i = 0; i < listRequirement.size(); i++ )
-        {
-            listNode.add( ( ( Require ) listRequirement.get( i ) ).getNode( father ) );
-        }
-        return listNode;
-    }
-
-
-    /**
-     * return the list of properties not define in this bundle resource.
-     * @return list of properties not define
-     */
-    private String getInvalidProperties()
-    {
-        if ( isValid() )
-        {
-            if ( getId() == null )
-            {
-                return "id";
-            }
-
-            return "";
-        }
-        String result = "";
-        if ( getPresentationName() == null )
-        {
-            result = result + "presentationName;";
-        }
-        if ( getSymbolicName() == null )
-        {
-            result = result + "symbolicName;";
-        }
-        if ( getVersion() == null )
-        {
-            result = result + "version;";
-        }
-        if ( getUri() == null )
-        {
-            result = result + "Uri;";
-        }
-        if ( getSize() == null )
-        {
-            result = result + "Size";
-        }
-        return result;
-    }
-
-}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
deleted file mode 100644
index e30163c..0000000
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/BundleInfo.java
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * $Id: BundleInfo.java 96 2009-08-26 13:44:04Z peter.kriens@aqute.biz $
- * 
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.impl.bundle.obr.resource;
-
-import java.io.*;
-import java.net.URL;
-import java.util.*;
-import java.util.zip.*;
-
-import org.osgi.service.obr.Resource;
-
-/**
- * Convert a bundle to a generic resource description and store its local
- * dependencies (like for example a license file in the JAR) in a zip file.
- * 
- * @version $Revision: 96 $
- */
-public class BundleInfo {
-	Manifest manifest;
-	File bundleJar;
-	ZipFile jar;
-	String license;
-	Properties localization;
-	RepositoryImpl repository;
-
-	/**
-	 * Parse a zipFile from the file system. We only need the manifest and the
-	 * localization. So a zip file is used to minimze memory consumption.
-	 * 
-	 * @param bundleJar
-	 *            Path name
-	 * @throws Exception
-	 *             Any errors that occur
-	 */
-	public BundleInfo(RepositoryImpl repository, File bundleJar)
-			throws Exception {
-		this.bundleJar = bundleJar;
-		this.repository = repository;
-
-		if (!this.bundleJar.exists())
-			throw new FileNotFoundException(bundleJar.toString());
-
-		jar = new ZipFile(bundleJar);
-		ZipEntry entry = jar.getEntry("META-INF/MANIFEST.MF");
-		if (entry == null)
-			throw new FileNotFoundException("No Manifest in "
-					+ bundleJar.toString());
-		manifest = new Manifest(jar.getInputStream(entry));
-	}
-
-	public BundleInfo(Manifest manifest) throws Exception {
-		this.manifest = manifest;
-	}
-
-	/**
-	 * Convert the bundle to a Resource. All URIs are going to be abslute, but
-	 * could be local.
-	 * 
-	 * @return the resource
-	 * @throws Exception
-	 */
-	public ResourceImpl build() throws Exception {
-		ResourceImpl resource;
-		// Setup the manifest
-		// and create a resource
-		resource = new ResourceImpl(repository, manifest.getSymbolicName(),
-				manifest.getVersion());
-
-		try {
-
-			// Calculate the location URL of the JAR
-			URL location = new URL("jar:" + bundleJar.toURL().toString() + "!/");
-			resource.setURL(bundleJar.toURL());
-			resource.setFile(bundleJar);
-
-			doReferences(resource, location);
-			doSize(resource);
-			doCategories(resource);
-			doImportExportServices(resource);
-			doDeclarativeServices(resource);
-			doFragment(resource);
-			doRequires(resource);
-			doBundle(resource);
-			doExports(resource);
-			doImports(resource);
-			doExecutionEnvironment(resource);
-
-			return resource;
-		} finally {
-			try {
-				jar.close();
-			} catch (Exception e) {
-				// ignore
-			}
-		}
-	}
-
-	/**
-	 * Check the size and add it.
-	 * 
-	 * @param resource
-	 */
-	void doSize(ResourceImpl resource) {
-		long size = bundleJar.length();
-		if (size > 0)
-			resource.setSize(size);
-	}
-
-	/**
-	 * Find the categories, break them up and add them.
-	 * 
-	 * @param resource
-	 */
-	void doCategories(ResourceImpl resource) {
-		for (int i = 0; i < manifest.getCategories().length; i++) {
-			String category = manifest.getCategories()[i];
-			resource.addCategory(category);
-		}
-	}
-
-	void doReferences(ResourceImpl resource, URL location) {
-		// Presentation name
-		String name = translated("Bundle-Name");
-		if (name != null)
-			resource.setPresentationName(name);
-
-		// Handle license. -l allows a global license
-		// set when no license is included.
-
-		String license = translated("Bundle-License");
-		if (license != null)
-			resource.setLicense(toURL(location, license));
-		else if (this.license != null)
-			resource.setLicense(toURL(location, this.license));
-
-		String description = translated("Bundle-Description");
-		if (description != null)
-			resource.setDescription(description);
-
-		String copyright = translated("Bundle-Copyright");
-		if (copyright != null)
-			resource.setCopyright(copyright);
-
-		String documentation = translated("Bundle-DocURL");
-		if (documentation != null)
-			resource.setDocumentation(toURL(location, documentation));
-
-		String source = manifest.getValue("Bundle-Source");
-		if (source != null)
-			resource.setSource(toURL(location, source));
-	}
-
-	URL toURL(URL location, String source) {
-		try {
-			return new URL(location, source);
-		} catch (Exception e) {
-			System.err.println("Error in converting url: " + location + " : "
-					+ source);
-			return null;
-		}
-	}
-
-	void doDeclarativeServices(ResourceImpl resource) throws Exception {
-		String serviceComponent = manifest.getValue("service-component");
-		if (serviceComponent == null)
-			return;
-
-		StringTokenizer st = new StringTokenizer(serviceComponent, " ,\t");
-		String parts[] = new String[st.countTokens()];
-		for (int i = 0; i < parts.length; i++)
-			parts[i] = st.nextToken();
-
-		for (int i = 0; i < parts.length; i++) {
-			ZipEntry entry = jar.getEntry(parts[i]);
-			if (entry == null) {
-				System.err.println("Bad Service-Component header: "
-						+ serviceComponent + ", no such file " + parts[i]);
-			}
-			InputStream in = jar.getInputStream(entry);
-			// TODO parse declarative services files.
-			in.close();
-		}
-	}
-
-	void doImportExportServices(ResourceImpl resource) throws IOException {
-		String importServices = manifest.getValue("import-service");
-		if (importServices != null) {
-			List entries = manifest.getEntries(importServices);
-			for (Iterator i = entries.iterator(); i.hasNext();) {
-				ManifestEntry entry = (ManifestEntry) i.next();
-				RequirementImpl ri = new RequirementImpl("service");
-				ri.setFilter(createServiceFilter(entry));
-				ri.setComment("Import Service " + entry.getName());
-
-                String avail = entry.getDirective("availability");
-				ri.setOptional("optional".equals(avail));
-				ri.setMultiple(true);
-				resource.addRequirement(ri);
-			}
-		}
-
-		String exportServices = manifest.getValue("export-service");
-		if (exportServices != null) {
-			List entries = manifest.getEntries(exportServices);
-			for (Iterator i = entries.iterator(); i.hasNext();) {
-				ManifestEntry entry = (ManifestEntry) i.next();
-				CapabilityImpl cap = createServiceCapability(entry);
-				resource.addCapability(cap);
-			}
-		}
-	}
-
-	String translated(String key) {
-		return translate(manifest.getValue(key));
-	}
-
-	void doFragment(ResourceImpl resource) {
-		// Check if we are a fragment
-		ManifestEntry entry = manifest.getHost();
-		if (entry == null) {
-			return;
-		} else {
-			// We are a fragment, create a requirement
-			// to our host.
-			RequirementImpl r = new RequirementImpl("bundle");
-			StringBuffer sb = new StringBuffer();
-			sb.append("(&(symbolicname=");
-			sb.append(entry.getName());
-			sb.append(")");
-			appendVersion(sb, entry.getVersion());
-			sb.append(")");
-			r.setFilter(sb.toString());
-			r.setComment("Required Host " + entry.getName());
-			r.setExtend(true);
-			r.setOptional(false);
-			r.setMultiple(false);
-			resource.addRequirement(r);
-
-			// And insert a capability that we are available
-			// as a fragment. ### Do we need that with extend?
-			CapabilityImpl capability = new CapabilityImpl("fragment");
-			capability.addProperty("host", entry.getName());
-			capability.addProperty("version", entry.getVersion());
-			resource.addCapability(capability);
-		}
-	}
-
-	void doRequires(ResourceImpl resource) {
-		List entries = manifest.getRequire();
-		if (entries == null)
-			return;
-
-		for (Iterator i = entries.iterator(); i.hasNext();) {
-			ManifestEntry entry = (ManifestEntry) i.next();
-			RequirementImpl r = new RequirementImpl("bundle");
-
-			Map attrs = entry.getAttributes();
-			String version = "0";
-			if (attrs != null) {
-				if (attrs.containsKey("bundle-version"))
-					version = (String) attrs.get("bundle-version");
-				else
-					version = "0";
-			}
-			VersionRange v = new VersionRange(version);
-
-			StringBuffer sb = new StringBuffer();
-			sb.append("(&(symbolicname=");
-			sb.append(entry.getName());
-			sb.append(")");
-			appendVersion(sb, v);
-			sb.append(")");
-			r.setFilter(sb.toString());
-
-			r.setComment("Require Bundle " + entry.getName() + "; " + v);
-			if (entry.directives != null
-					&& "optional".equalsIgnoreCase((String) entry.directives
-							.get("resolution")))
-				r.setOptional(true);
-			else
-				r.setOptional(false);
-			resource.addRequirement(r);
-		}
-	}
-
-	void doExecutionEnvironment(ResourceImpl resource) {
-		String[] parts = manifest.getRequiredExecutionEnvironments();
-		if (parts == null)
-			return;
-
-		StringBuffer sb = new StringBuffer();
-		sb.append("(|");
-		for (int i = 0; i < parts.length; i++) {
-			String part = parts[i];
-			sb.append("(ee=");
-			sb.append(part);
-			sb.append(")");
-		}
-		sb.append(")");
-
-		RequirementImpl req = new RequirementImpl("ee");
-		req.setFilter(sb.toString());
-		req.setComment("Execution Environment " + sb.toString());
-		resource.addRequirement(req);
-	}
-
-	void doImports(ResourceImpl resource) {
-		List requirements = new ArrayList();
-		List packages = manifest.getImports();
-		if (packages == null)
-			return;
-
-		for (Iterator i = packages.iterator(); i.hasNext();) {
-			ManifestEntry pack = (ManifestEntry) i.next();
-			RequirementImpl requirement = new RequirementImpl("package");
-
-			createImportFilter(requirement, "package", pack);
-			requirement.setComment("Import package " + pack);
-			String resolution = pack.getDirective("resolution");
-			requirement.setOptional("optional".equals(resolution));
-			requirements.add(requirement);
-		}
-		for (Iterator i = requirements.iterator(); i.hasNext();)
-			resource.addRequirement((RequirementImpl) i.next());
-	}
-
-	String createServiceFilter(ManifestEntry pack) {
-        String f = pack.getAttribute("filter");
-		StringBuffer filter = new StringBuffer();
-        if (f != null) {
-            filter.append("(&");
-        }
-		filter.append("(service=");
-		filter.append(pack.getName());
-		filter.append(")");
-        if (f != null) {
-            filter.append(f);
-            filter.append(")");
-        }
-		return filter.toString();
-	}
-
-	void createImportFilter(RequirementImpl req, String name, ManifestEntry pack) {
-		StringBuffer filter = new StringBuffer();
-		filter.append("(&(");
-		filter.append(name);
-		filter.append("=");
-		filter.append(pack.getName());
-		filter.append(")");
-		appendVersion(filter, pack.getVersion());
-		Map attributes = pack.getAttributes();
-		Set attrs = doImportPackageAttributes(req, filter, attributes);
-		
-		// The next code is using the subset operator 
-		// to check mandatory attributes, it seems to be
-		// impossible to rewrite. It must assert that whateber
-		// is in mandatory: must be in any of the attributes.
-		// This is a fundamental shortcoming of the filter language.
-		if (attrs.size() > 0) {
-			String del = "";
-			filter.append("(mandatory:<*");
-			for (Iterator i = attrs.iterator(); i.hasNext();) {
-				filter.append(del);
-				filter.append(i.next());
-				del = ", ";
-			}
-			filter.append(")");
-		}
-		filter.append(")");
-		req.setFilter(filter.toString());
-	}
-
-	private void appendVersion(StringBuffer filter, VersionRange version) {
-		if (version != null) {
-			if (version.isRange()) {
-				if (version.includeLow()) {
-					filter.append("(version");
-					filter.append(">=");
-					filter.append(version.low);
-					filter.append(")");
-				}
-				else {
-					filter.append("(!(version");
-					filter.append("<=");
-					filter.append(version.low);
-					filter.append("))");
-				}
-
-				if ( version.includeHigh() ) {
-					filter.append("(version");
-					filter.append("<=");
-					filter.append(version.high);
-					filter.append(")");					
-				}
-				else {
-					filter.append("(!(version");
-					filter.append(">=");
-					filter.append(version.high);
-					filter.append("))");
-				}
-			} else {
-				filter.append("(version>=");
-				filter.append(version);
-				filter.append(")");
-			}
-		}
-	}
-
-	Set doImportPackageAttributes(RequirementImpl req, StringBuffer filter,
-			Map attributes) {
-		HashSet set = new HashSet();
-
-		if (attributes != null)
-			for (Iterator i = attributes.keySet().iterator(); i.hasNext();) {
-				String attribute = (String) i.next();
-				String value = (String) attributes.get(attribute);
-				if (attribute.equalsIgnoreCase("specification-version")
-						|| attribute.equalsIgnoreCase("version"))
-					continue;
-				else if (attribute.equalsIgnoreCase("resolution:")) {
-					req.setOptional(value.equalsIgnoreCase("optional"));
-				}
-				if (attribute.endsWith(":")) {
-					// Ignore
-				} else {
-					filter.append("(");
-					filter.append(attribute);
-					filter.append("=");
-					filter.append(attributes.get(attribute));
-					filter.append(")");
-					set.add(attribute);
-				}
-			}
-		return set;
-	}
-
-	void doBundle(ResourceImpl resource) {
-		CapabilityImpl capability = new CapabilityImpl("bundle");
-		capability.addProperty("symbolicname", manifest.getSymbolicName());
-		if (manifest.getValue("Bundle-Name") != null)
-			capability.addProperty(Resource.PRESENTATION_NAME,
-					translated("Bundle-Name"));
-		capability.addProperty("version", manifest.getVersion());
-		capability
-				.addProperty("manifestversion", manifest.getManifestVersion());
-
-		/**
-		 * Is this needed TODO
-		 */
-		ManifestEntry host = manifest.getHost();
-		if (host != null) {
-			capability.addProperty("host", host.getName());
-			if (host.getVersion() != null)
-				capability.addProperty("version", host.getVersion());
-		}
-		resource.addCapability(capability);
-	}
-
-	void doExports(ResourceImpl resource) {
-		List capabilities = new ArrayList();
-		List packages = manifest.getExports();
-		if (packages != null) {
-			for (Iterator i = packages.iterator(); i.hasNext();) {
-				ManifestEntry pack = (ManifestEntry) i.next();
-				CapabilityImpl capability = createCapability("package", pack);
-				capabilities.add(capability);
-			}
-		}
-		for (Iterator i = capabilities.iterator(); i.hasNext();)
-			resource.addCapability((CapabilityImpl) i.next());
-	}
-
-	CapabilityImpl createServiceCapability(ManifestEntry pack) {
-		CapabilityImpl capability = new CapabilityImpl("service");
-		capability.addProperty("service", pack.getName());
-        Map attributes = pack.getAttributes();
-        if (attributes != null)
-            for (Iterator at = attributes.keySet().iterator(); at.hasNext();) {
-                String key = (String) at.next();
-                Object value = attributes.get(key);
-                capability.addProperty(key, value);
-            }
-		return capability;
-	}
-
-	CapabilityImpl createCapability(String name, ManifestEntry pack) {
-		CapabilityImpl capability = new CapabilityImpl(name);
-		capability.addProperty(name, pack.getName());
-		capability.addProperty("version", pack.getVersion());
-		Map attributes = pack.getAttributes();
-		if (attributes != null)
-			for (Iterator at = attributes.keySet().iterator(); at.hasNext();) {
-				String key = (String) at.next();
-				if (key.equalsIgnoreCase("specification-version")
-						|| key.equalsIgnoreCase("version"))
-					continue;
-				else {
-					Object value = attributes.get(key);
-					capability.addProperty(key, value);
-				}
-			}
-		Map directives = pack.getDirectives();
-		if (directives != null)
-			for (Iterator at = directives.keySet().iterator(); at.hasNext();) {
-				String key = (String) at.next();
-				Object value = directives.get(key);
-				capability.addProperty(key + ":", value);
-			}
-		return capability;
-	}
-
-	String translate(String s) {
-		if (s == null)
-			return null;
-
-		if (!s.startsWith("%")) {
-			return s;
-		}
-
-		if (localization == null)
-			try {
-				localization = new Properties();
-				String path = manifest
-						.getValue("Bundle-Localization", "bundle");
-				path += ".properties";
-				InputStream in = jar.getInputStream(new ZipEntry(path));
-				if (in != null) {
-					localization.load(in);
-					in.close();
-				}
-			} catch (IOException e) {
-				e.printStackTrace();
-			}
-		s = s.substring(1);
-		return localization.getProperty(s, s);
-	}
-
-	File getZipFile() {
-		return bundleJar;
-	}
-}
\ No newline at end of file
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/CapabilityImpl.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/CapabilityImpl.java
deleted file mode 100644
index 6d2ce8a..0000000
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/CapabilityImpl.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * $Id: CapabilityImpl.java 84 2008-08-28 08:11:30Z peter.kriens@aqute.biz $
- * 
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.impl.bundle.obr.resource;
-
-import java.lang.reflect.Array;
-import java.util.*;
-
-import org.osgi.service.obr.Capability;
-import org.xmlpull.v1.XmlPullParser;
-
-
-
-public class CapabilityImpl implements Capability {
-	String				name;
-	Map	properties	= new TreeMap();
-
-	public CapabilityImpl(String name) {
-		this.name = name;
-	}
-
-	public CapabilityImpl(XmlPullParser parser) throws Exception {
-		parser.require(XmlPullParser.START_TAG, null, "capability");
-		name = parser.getAttributeValue(null,"name");
-		while ( parser.nextTag() == XmlPullParser.START_TAG ) {
-			if ( parser.getName().equals("p")) {
-				String name = parser.getAttributeValue(null,"n");
-				String value = parser.getAttributeValue(null,"v");
-				String type = parser.getAttributeValue(null,"t");
-				Object v = value;
-
-				if ( "nummeric".equals(type))
-					v = new Long(value);
-				else if ( "version".equals(type))
-					v = new VersionRange(value);
-				addProperty(name,v);
-			}
-			parser.next();
-			parser.require(XmlPullParser.END_TAG, null, "p" );
-		}
-		parser.require(XmlPullParser.END_TAG, null, "capability" );
-	}
-
-
-	public void addProperty(String key, Object value) {
-		List values = (List) properties.get(key);
-		if (values == null) {
-			values = new ArrayList();
-			properties.put(key, values);
-		}
-		values.add(value);
-	}
-
-	public Tag toXML() {
-		return toXML(this);
-	}
-	
-	public static Tag toXML(Capability capability) {
-		Tag tag = new Tag("capability");
-		tag.addAttribute("name", capability.getName());
-		Map properties = capability.getProperties();
-		for ( Iterator k= properties.keySet().iterator(); k.hasNext(); ) {
-			String key = (String) k.next();
-			List values = (List) properties.get(key);
-			for ( Iterator v = values.iterator(); v.hasNext(); ) {
-				Object value = v.next();
-				Tag p = new Tag("p");
-				tag.addContent(p);
-				p.addAttribute("n", key);
-				if ( value != null ) {
-					p.addAttribute("v", valueString(value));
-					String type = null;
-					if (value instanceof Number )
-						type = "number";
-					else if (value.getClass() == VersionRange.class)
-						type = "version";
-					else if ( value.getClass().isArray() ) {
-						type = "set";
-					}
-					
-					if (type != null)
-						p.addAttribute("t", type);
-				}
-				else
-					System.out.println("Missing value " + key);
-			}
-		}
-		return tag;
-	}
-
-
-	private static String valueString(Object value) {
-		if ( value.getClass().isArray() ) {
-			StringBuffer buf = new StringBuffer();
-			for ( int i = 0; i < Array.getLength(value); i++) {
-				if ( i > 0 ) {
-					buf.append( "," );
-				}
-				buf.append( Array.get(value, i).toString() );
-			}
-			return buf.toString();
-		}
-		else {
-			return value.toString();
-		}
-	}
-
-	public String getName() {
-		return name;
-	}
-
-
-	public Map getProperties() {
-		return properties;
-	}
-
-}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/FilterImpl.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/FilterImpl.java
deleted file mode 100644
index b0feb87..0000000
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/FilterImpl.java
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * $Id: FilterImpl.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $
- * 
- * Copyright (c) 2000 Gatespace AB. All Rights Reserved.
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.impl.bundle.obr.resource;
-
-import java.lang.reflect.*;
-import java.math.BigInteger;
-import java.util.*;
-
-public class FilterImpl {
-	final char		WILDCARD	= 65535;
-
-	final int		EQ			= 0;
-	final int		LE			= 1;
-	final int		GE			= 2;
-	final int		APPROX		= 3;
-	final int		LESS		= 4;
-	final int		GREATER		= 5;
-	final int		SUBSET		= 6;
-	final int		SUPERSET	= 7;
-
-	private String	filter;
-
-	abstract class Query {
-		static final String	GARBAGE		= "Trailing garbage";
-		static final String	MALFORMED	= "Malformed query";
-		static final String	EMPTY		= "Empty list";
-		static final String	SUBEXPR		= "No subexpression";
-		static final String	OPERATOR	= "Undefined operator";
-		static final String	TRUNCATED	= "Truncated expression";
-		static final String	EQUALITY	= "Only equality supported";
-
-		private String		tail;
-
-		boolean match() throws IllegalArgumentException {
-			tail = filter;
-			boolean val = doQuery();
-			if (tail.length() > 0)
-				error(GARBAGE);
-			return val;
-		}
-
-		private boolean doQuery() throws IllegalArgumentException {
-			if (tail.length() < 3 || !prefix("("))
-				error(MALFORMED);
-			boolean val;
-
-			switch (tail.charAt(0)) {
-				case '&' :
-					val = doAnd();
-					break;
-				case '|' :
-					val = doOr();
-					break;
-				case '!' :
-					val = doNot();
-					break;
-				default :
-					val = doSimple();
-					break;
-			}
-
-			if (!prefix(")"))
-				error(MALFORMED);
-			return val;
-		}
-
-		private boolean doAnd() throws IllegalArgumentException {
-			tail = tail.substring(1);
-			boolean val = true;
-			if (!tail.startsWith("("))
-				error(EMPTY);
-			do {
-				if (!doQuery())
-					val = false;
-			} while (tail.startsWith("("));
-			return val;
-		}
-
-		private boolean doOr() throws IllegalArgumentException {
-			tail = tail.substring(1);
-			boolean val = false;
-			if (!tail.startsWith("("))
-				error(EMPTY);
-			do {
-				if (doQuery())
-					val = true;
-			} while (tail.startsWith("("));
-			return val;
-		}
-
-		private boolean doNot() throws IllegalArgumentException {
-			tail = tail.substring(1);
-			if (!tail.startsWith("("))
-				error(SUBEXPR);
-			return !doQuery();
-		}
-
-		private boolean doSimple() throws IllegalArgumentException {
-			int op = 0;
-			Object attr = getAttr();
-
-			if (prefix("="))
-				op = EQ;
-			else if (prefix("<="))
-				op = LE;
-			else if (prefix(">="))
-				op = GE;
-			else if (prefix("~="))
-				op = APPROX;
-			else if (prefix("*>"))
-				op = SUPERSET;
-			else if (prefix("<*"))
-				op = SUBSET;
-			else if (prefix("<"))
-				op = LESS;
-			else if (prefix(">"))
-				op = GREATER;
-			else
-				error(OPERATOR);
-
-			return compare(attr, op, getValue());
-		}
-
-		private boolean prefix(String pre) {
-			if (!tail.startsWith(pre))
-				return false;
-			tail = tail.substring(pre.length());
-			return true;
-		}
-
-		private Object getAttr() {
-			int len = tail.length();
-			int ix = 0;
-			label: for (; ix < len; ix++) {
-				switch (tail.charAt(ix)) {
-					case '(' :
-					case ')' :
-					case '<' :
-					case '>' :
-					case '=' :
-					case '~' :
-					case '*' :
-					case '}' :
-					case '{' :
-					case '\\' :
-						break label;
-				}
-			}
-			String attr = tail.substring(0, ix).toLowerCase();
-			tail = tail.substring(ix);
-			return getProp(attr);
-		}
-
-		abstract Object getProp(String key);
-
-		private String getValue() {
-			StringBuffer sb = new StringBuffer();
-			int len = tail.length();
-			int ix = 0;
-			label: for (; ix < len; ix++) {
-				char c = tail.charAt(ix);
-				switch (c) {
-					case '(' :
-					case ')' :
-						break label;
-					case '*' :
-						sb.append(WILDCARD);
-						break;
-					case '\\' :
-						if (ix == len - 1)
-							break label;
-						sb.append(tail.charAt(++ix));
-						break;
-					default :
-						sb.append(c);
-						break;
-				}
-			}
-			tail = tail.substring(ix);
-			return sb.toString();
-		}
-
-		private void error(String m) throws IllegalArgumentException {
-			throw new IllegalArgumentException(m + " " + tail);
-		}
-
-		private boolean compare(Object obj, int op, String s) {
-			if (obj == null) {
-				// No value is ok for a subset
-				if (op == SUBSET)
-					return true;
-
-				// No value is ok for a superset when the value is
-				// empty
-				if (op == SUPERSET) {
-					return s.trim().length() == 0;
-				}
-
-				return false;
-			}
-			try {
-				Class numClass = obj.getClass();
-				if (numClass == String.class) {
-					return compareString((String) obj, op, s);
-				}
-				else if (numClass == Character.class) {
-					return compareString(obj.toString(), op, s);
-				}
-				else if (numClass == Long.class) {
-					return compareSign(op, Long.valueOf(s)
-							.compareTo((Long) obj));
-				}
-				else if (numClass == Integer.class) {
-					return compareSign(op, Integer.valueOf(s).compareTo(
-							(Integer) obj));
-				}
-				else if (numClass == Short.class) {
-					return compareSign(op, Short.valueOf(s).compareTo(
-							(Short) obj));
-				}
-				else if (numClass == Byte.class) {
-					return compareSign(op, Byte.valueOf(s)
-							.compareTo((Byte) obj));
-				}
-				else if (numClass == Double.class) {
-					return compareSign(op, Double.valueOf(s).compareTo(
-							(Double) obj));
-				}
-				else if (numClass == Float.class) {
-					return compareSign(op, Float.valueOf(s).compareTo(
-							(Float) obj));
-				}
-				else if (numClass == Boolean.class) {
-					if (op != EQ)
-						return false;
-					int a = Boolean.valueOf(s).booleanValue() ? 1 : 0;
-					int b = ((Boolean) obj).booleanValue() ? 1 : 0;
-					return compareSign(op, a - b);
-				}
-				else if (numClass == BigInteger.class) {
-					return compareSign(op, new BigInteger(s)
-							.compareTo((BigInteger) obj));
-				}
-				else if (obj instanceof Collection) {
-					if (op == SUBSET || op == SUPERSET) {
-						StringSet set = new StringSet(s);
-						if (op == SUBSET)
-							return set.containsAll((Collection) obj);
-						else
-							return ((Collection) obj).containsAll(set);
-					}
-
-					for (Iterator i = ((Collection) obj).iterator(); i
-							.hasNext();) {
-						Object element = i.next();
-						if (compare(element, op, s))
-							return true;
-					}
-				}
-				else if (numClass.isArray()) {
-					int len = Array.getLength(obj);
-					for (int i = 0; i < len; i++)
-						if (compare(Array.get(obj, i), op, s))
-							return true;
-				}
-				else {
-					try {
-						if (op == SUPERSET || op == SUBSET) {
-							StringSet set = new StringSet(s);
-							if (op == SUPERSET)
-								return set.contains(obj);
-							else
-								return set.size() == 0
-										|| (set.size() == 1 && set.iterator()
-												.next().equals(obj));
-						}
-						else {
-							Constructor constructor = numClass
-									.getConstructor(new Class[] {String.class});
-							Object instance = constructor
-									.newInstance(new Object[] {s});
-							switch (op) {
-								case EQ :
-									return obj.equals(instance);
-								case LESS :
-									return ((Comparable) obj)
-											.compareTo(instance) < 0;
-								case GREATER :
-									return ((Comparable) obj)
-											.compareTo(instance) > 0;
-								case LE :
-									return ((Comparable) obj)
-											.compareTo(instance) <= 0;
-								case GE :
-									return ((Comparable) obj)
-											.compareTo(instance) >= 0;
-							}
-						}
-					}
-					catch (Exception e) {
-						e.printStackTrace();
-						// Ignore
-					}
-				}
-			}
-			catch (Exception e) {
-			}
-			return false;
-		}
-	}
-
-	class DictQuery extends Query {
-		private Map	dict;
-
-		DictQuery(Map dict) {
-			this.dict = dict;
-		}
-
-		Object getProp(String key) {
-			return dict.get(key);
-		}
-	}
-
-	public FilterImpl(String filter) throws IllegalArgumentException {
-		// NYI: Normalize the filter string?
-		this.filter = filter;
-		if (filter == null || filter.length() == 0)
-			throw new IllegalArgumentException("Null query");
-	}
-
-	public boolean match(Map dict) {
-		try {
-			return new DictQuery(dict).match();
-		}
-		catch (IllegalArgumentException e) {
-			return false;
-		}
-	}
-
-	public String toString() {
-		return filter;
-	}
-
-	public boolean equals(Object obj) {
-		return obj != null && obj instanceof FilterImpl
-				&& filter.equals(((FilterImpl) obj).filter);
-	}
-
-	public int hashCode() {
-		return filter.hashCode();
-	}
-
-	boolean compareString(String s1, int op, String s2) {
-		switch (op) {
-			case EQ :
-				return patSubstr(s1, s2);
-			case APPROX :
-				return patSubstr(fixupString(s1), fixupString(s2));
-			default :
-				return compareSign(op, s2.compareTo(s1));
-		}
-	}
-
-	boolean compareSign(int op, int cmp) {
-		switch (op) {
-			case LE :
-				return cmp >= 0;
-			case GE :
-				return cmp <= 0;
-			case EQ :
-				return cmp == 0;
-			default : /* APPROX */
-				return cmp == 0;
-		}
-	}
-
-	String fixupString(String s) {
-		StringBuffer sb = new StringBuffer();
-		int len = s.length();
-		boolean isStart = true;
-		boolean isWhite = false;
-		for (int i = 0; i < len; i++) {
-			char c = s.charAt(i);
-			if (Character.isWhitespace(c)) {
-				isWhite = true;
-			}
-			else {
-				if (!isStart && isWhite)
-					sb.append(' ');
-				if (Character.isUpperCase(c))
-					c = Character.toLowerCase(c);
-				sb.append(c);
-				isStart = false;
-				isWhite = false;
-			}
-		}
-		return sb.toString();
-	}
-
-	boolean patSubstr(String s, String pat) {
-		if (s == null)
-			return false;
-		if (pat.length() == 0)
-			return s.length() == 0;
-		if (pat.charAt(0) == WILDCARD) {
-			pat = pat.substring(1);
-			for (;;) {
-				if (patSubstr(s, pat))
-					return true;
-				if (s.length() == 0)
-					return false;
-				s = s.substring(1);
-			}
-		}
-		else {
-			if (s.length() == 0 || s.charAt(0) != pat.charAt(0))
-				return false;
-			return patSubstr(s.substring(1), pat.substring(1));
-		}
-	}
-}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Manifest.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Manifest.java
deleted file mode 100644
index 8d991e6..0000000
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Manifest.java
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * $Id: Manifest.java 84 2008-08-28 08:11:30Z peter.kriens@aqute.biz $
- * 
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.impl.bundle.obr.resource;
-
-import java.io.*;
-import java.util.*;
-
-
-public class Manifest extends Hashtable {
-	static final long	serialVersionUID	= 1L;
-	List				imports;
-	List				exports;
-	ManifestEntry		name;
-	String				activator;
-	String				classpath[]	= new String[] {"."};
-	int					section;
-	String				location;
-	Native				_native[];
-	Vector				duplicates	= new Vector();
-	final static String	wordparts	= "~!@#$%^&*_/?><.-+";
-	ManifestEntry		bsn;
-	VersionRange			version;
-	ManifestEntry		host;
-	List				require;
-
-	public Manifest(InputStream in) throws IOException {
-		parse(new InputStreamReader(in, "UTF8"));
-	}
-
-	public Manifest(Reader in) throws IOException {
-		parse(in);
-	}
-
-	public Object put(Object header, Object value) {
-		if (containsKey(header)) {
-			if (!((String) header).equalsIgnoreCase("comment"))
-				duplicates.add(header + ":" + value);
-		}
-		return super.put(header, value);
-	}
-
-	void parse(Reader in) throws IOException {
-		BufferedReader rdr = new BufferedReader(in);
-		String current = " ";
-		String buffer = rdr.readLine();
-		int section = 0;
-		if (buffer != null && !buffer.startsWith("Manifest-Version")) {
-			System.err
-					.println("The first line of a manifest file must be the Manifest-Version attribute");
-			throw new IOException(
-					"The first line of a manifest file must be the Manifest-Version attribute");
-		}
-		while (buffer != null && current != null && section == 0) {
-			if (current.startsWith(" ")) {
-				buffer += current.substring(1);
-			}
-			else {
-				section += entry(buffer);
-				buffer = current;
-			}
-			current = rdr.readLine();
-		}
-		entry(buffer);
-	}
-
-	int entry(String line) throws IOException {
-		if (line.length() < 2)
-			return 1;
-		int colon = line.indexOf(':');
-		if (colon < 1) {
-			error("Invalid header '" + line + "'");
-		}
-		else {
-			String header = line.substring(0, colon).toLowerCase();
-			String alphanum = "abcdefghijklmnopqrstuvwxyz0123456789";
-			String set = alphanum;
-			if (alphanum.indexOf(header.charAt(0)) < 0)
-				error("Header does not start with alphanum: " + header);
-			for (int i = 0; i < header.length(); i++) {
-				if (set.indexOf(header.charAt(i)) < 0)
-					error("Header contains non alphanum, - _: " + header);
-				set = "_-" + alphanum;
-			}
-			String value = "";
-			if (colon + 2 < line.length())
-				value = line.substring(colon + 2);
-			else
-				error("No value for manifest header " + header);
-			if (section == 0) {
-				if (header.equals("bundle-symbolicname")) {
-					bsn = (ManifestEntry) getEntries(value).get(0);
-				}
-				if (header.equals("bundle-version")) {
-					try {
-						version = new VersionRange(value.trim());
-					}
-					catch (Exception e) {
-						version = new VersionRange("0");
-						System.err.println("Invalid version attr for: " + bsn
-								+ " value is " + value);
-					}
-				}
-				if (header.equals("fragment-host"))
-					host = (ManifestEntry) getEntries(value).get(0);
-				if (header.equals("require-bundle"))
-					require = getEntries(value);
-				if (header.equals("import-package"))
-					imports = getEntries(value);
-				else if (header.equals("export-package"))
-					exports = getEntries(value);
-				else if (header.equals("bundle-activator"))
-					activator = value.trim();
-				else if (header.equals("bundle-updatelocation"))
-					location = value.trim();
-				else if (header.equals("bundle-classpath"))
-					classpath = getClasspath(value);
-				else if (header.equals("bundle-nativecode"))
-					_native = getNative(value);
-				put(header, value);
-			}
-		}
-		return 0;
-	}
-
-	void error(String msg) throws IOException {
-		System.err.println("Reading manifest: " + msg);
-	}
-
-	void warning(String msg) throws IOException {
-		System.err.println("Reading manifest: " + msg);
-	}
-
-	StreamTokenizer getStreamTokenizer(String line) {
-		StreamTokenizer st = new StreamTokenizer(new StringReader(line));
-		st.resetSyntax();
-		st.wordChars('a', 'z');
-		st.wordChars('A', 'Z');
-		st.wordChars('0', '9');
-		st.whitespaceChars(0, ' ');
-		st.quoteChar('"');
-		for (int i = 0; i < wordparts.length(); i++)
-			st.wordChars(wordparts.charAt(i), wordparts.charAt(i));
-		return st;
-	}
-
-	String word(StreamTokenizer st) throws IOException {
-		switch (st.nextToken()) {
-			case '"' :
-			case StreamTokenizer.TT_WORD :
-				String result = st.sval;
-				st.nextToken();
-				return result;
-		}
-		return null;
-	}
-
-	Parameter getParameter(StreamTokenizer st) throws IOException {
-
-		Parameter parameter = new Parameter();
-		parameter.key = word(st);
-		if (st.ttype == ':') {
-			st.nextToken();
-			parameter.type = Parameter.DIRECTIVE;
-		}
-		else {
-			parameter.type = Parameter.ATTRIBUTE;
-		}
-
-		if (st.ttype == '=') {
-			parameter.value = word(st);
-			while (st.ttype == StreamTokenizer.TT_WORD || st.ttype == '"') {
-				parameter.value += " " + st.sval;
-				st.nextToken();
-			}
-		}
-
-		return parameter;
-	}
-
-	public List getEntries(String line) throws IOException {
-		List v = new Vector();
-		Set aliases = new HashSet();
-
-		StreamTokenizer st = getStreamTokenizer(line);
-		do {
-			Parameter parameter = getParameter(st);
-			ManifestEntry p = new ManifestEntry(parameter.key);
-			while (st.ttype == ';') {
-				parameter = getParameter(st);
-				if (parameter.value == null) {
-					aliases.add(parameter.key);
-				}
-				else {
-					if (parameter.type == Parameter.ATTRIBUTE)
-						p.addParameter(parameter);
-					else if ( parameter.type == Parameter.DIRECTIVE )
-						p.addParameter(parameter);
-					else
-						p.addParameter(parameter);
-				}
-			}
-			v.add(p);
-			for (Iterator a = aliases.iterator(); a.hasNext();) {
-				v.add(p.getAlias((String) a.next()));
-			}
-		} while (st.ttype == ',');
-		return v;
-	}
-
-	Native[] getNative(String line) throws IOException {
-		Vector v = new Vector();
-		StreamTokenizer st = getStreamTokenizer(line);
-		do {
-			Native spec = new Native();
-			Vector names = new Vector();
-			do {
-				Parameter parameter = getParameter(st);
-				if (parameter.value == null)
-					names.add(parameter.key);
-				else if (parameter.is("processor", Parameter.ATTRIBUTE))
-					spec.processor = parameter.value;
-				else if (parameter.is("osname", Parameter.ATTRIBUTE))
-					spec.osname = parameter.value;
-				else if (parameter.is("osversion", Parameter.ATTRIBUTE))
-					spec.osversion = parameter.value;
-				else if (parameter.is("language", Parameter.ATTRIBUTE))
-					spec.language = parameter.value;
-				else if (parameter.is("selection-filter", Parameter.DIRECTIVE))
-					spec.filter = parameter.value;
-				else
-					warning("Unknown parameter for native code : " + parameter);
-			} while (st.ttype == ';');
-			spec.paths = new String[names.size()];
-			names.copyInto(spec.paths);
-			v.add(spec);
-		} while (st.ttype == ',');
-		Native[] result = new Native[v.size()];
-		v.copyInto(result);
-		return result;
-	}
-
-	String[] getClasspath(String line) throws IOException {
-		StringTokenizer st = new StringTokenizer(line, " \t,");
-		String result[] = new String[st.countTokens()];
-		for (int i = 0; i < result.length; i++)
-			result[i] = st.nextToken();
-		return result;
-	}
-
-	public List getImports() {
-		return imports;
-	}
-
-	public List getExports() {
-		return exports;
-	}
-
-	public String getActivator() {
-		return activator;
-	}
-
-	public String getLocation() {
-		return location;
-	}
-
-	public String[] getClasspath() {
-		return classpath;
-	}
-
-	public Native[] getNative() {
-		return _native;
-	}
-
-	public Object get(Object key) {
-		if (key instanceof String)
-			return super.get(((String) key).toLowerCase());
-		else
-			return null;
-	}
-
-	public String getValue(String key) {
-		return (String) super.get(key.toLowerCase());
-	}
-
-	public String getValue(String key, String deflt) {
-		String s = getValue(key);
-		if (s == null)
-			return deflt;
-		else
-			return s;
-	}
-
-	public String[] getRequiredExecutionEnvironments() {
-		String ees = getValue("Bundle-RequiredExecutionEnvironment");
-		if (ees != null)
-			return ees.trim().split("\\s*,\\s*");
-		else
-			return null;
-	}
-
-	public VersionRange getVersion() {
-		if (version == null)
-			return new VersionRange("0");
-		return version;
-	}
-
-	public String getSymbolicName() {
-		ManifestEntry bsn = getBsn();
-
-		if (bsn == null) {
-			String name = getValue("Bundle-Name");
-			if (name == null)
-				name = "Untitled-" + hashCode();
-			return name;
-		}
-		else
-			return bsn.getName();
-	}
-
-	public String getManifestVersion() {
-		return getValue("Bundle-ManifestVersion", "1");
-	}
-
-	public String getCopyright() {
-		return getValue("Bundle-Copyright");
-	}
-
-	public String getDocumentation() {
-		return getValue("Bundle-DocURL");
-	}
-
-	public String[] getCategories() {
-		String cats = getValue("Bundle-Category");
-		if (cats == null)
-			return new String[0];
-		else
-			return cats.split("\\s*,\\s*");
-	}
-
-	public Native[] get_native() {
-		return _native;
-	}
-
-	public void set_native(Native[] _native) {
-		this._native = _native;
-	}
-
-	public ManifestEntry getBsn() {
-		return bsn;
-	}
-
-	public void setBsn(ManifestEntry bsn) {
-		this.bsn = bsn;
-	}
-
-	public Vector getDuplicates() {
-		return duplicates;
-	}
-
-	public void setDuplicates(Vector duplicates) {
-		this.duplicates = duplicates;
-	}
-
-	public ManifestEntry getHost() {
-		return host;
-	}
-
-	public void setHost(ManifestEntry host) {
-		this.host = host;
-	}
-
-	public List getRequire() {
-		return require;
-	}
-
-}
-
-class Native {
-	String	filter;
-	int		index	= -1;
-	String	paths[];
-	String	osname;
-	String	osversion;
-	String	language;
-	String	processor;
-
-}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java
deleted file mode 100644
index b7a4c4a..0000000
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ManifestEntry.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * $Id: ManifestEntry.java 92 2008-11-06 07:46:37Z peter.kriens@aqute.biz $
- * 
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.impl.bundle.obr.resource;
-
-import java.util.*;
-
-
-public class ManifestEntry implements Comparable {
-	String		name;
-	VersionRange	version;
-	Map			attributes;
-	public Map	directives;
-	public Set	uses;
-
-	public ManifestEntry(String name) {
-		this.name = name;
-	}
-
-	public ManifestEntry(String name, VersionRange version) {
-		this.name = name;
-		this.version = version;
-	}
-
-	public String toString() {
-		if (version == null)
-			return name;
-		return name + " ;version=" + version;
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public VersionRange getVersion() {
-		if (version != null)
-			return version;
-		return new VersionRange("0");
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see java.lang.Comparable#compareTo(java.lang.Object)
-	 */
-	public int compareTo(Object o) {
-		ManifestEntry p = (ManifestEntry) o;
-		return name.compareTo(p.name);
-	}
-
-	/**
-	 * @return
-	 */
-	public Object getPath() {
-		return getName().replace('.', '/');
-	}
-
-	public Map getDirectives() {
-		return directives;
-	}
-
-	public Map getAttributes() {
-		return attributes;
-	}
-
-	/**
-	 * @param parameter
-	 */
-	public void addParameter(Parameter parameter) {
-		switch (parameter.type) {
-			case Parameter.ATTRIBUTE :
-				if (attributes == null)
-					attributes = new HashMap();
-				attributes.put(parameter.key, parameter.value);
-				if (parameter.key.equalsIgnoreCase("version")
-						|| parameter.key.equalsIgnoreCase("specification-version")
-						|| parameter.key.equalsIgnoreCase("bundle-version"))
-					this.version = new VersionRange(parameter.value);
-				break;
-
-			case Parameter.DIRECTIVE :
-				if (directives == null)
-					directives = new HashMap();
-				directives.put(parameter.key, parameter.value);
-				break;
-		}
-	}
-
-	public ManifestEntry getAlias(String key) {
-		ManifestEntry me = new ManifestEntry(key);
-		me.attributes = attributes;
-		me.directives = directives;
-		me.version = version;
-		return me;
-	}
-
-	public String getDirective(String directive) {
-		if ( directives == null )
-			return null;
-		
-		return (String) directives.get(directive);
-	}
-
-	public String getAttribute(String attribute) {
-		if ( attributes == null )
-			return null;
-		
-		return (String) attributes.get(attribute);
-	}
-
-}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Parameter.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Parameter.java
deleted file mode 100644
index 8601dc2..0000000
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Parameter.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * $Id: Parameter.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $
- * 
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.impl.bundle.obr.resource;
-
-class Parameter {
-	final static int	ATTRIBUTE	= 1;
-	final static int	DIRECTIVE	= 2;
-	final static int	SINGLE		= 0;
-
-	int					type;
-	String				key;
-	String				value;
-
-	public String toString() {
-		StringBuffer sb = new StringBuffer();
-		sb.append(key);
-		switch (type) {
-			case ATTRIBUTE :
-				sb.append("=");
-				break;
-			case DIRECTIVE :
-				sb.append(":=");
-				break;
-			case SINGLE :
-				return sb.toString();
-		}
-		sb.append(value);
-		return sb.toString();
-	}
-
-	boolean is(String s, int type) {
-		return this.type == type && key.equalsIgnoreCase(s);
-	}
-}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RepositoryImpl.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RepositoryImpl.java
deleted file mode 100644
index b7ebeb4..0000000
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RepositoryImpl.java
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * $Id: RepositoryImpl.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $
- * 
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.osgi.impl.bundle.obr.resource;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.zip.*;
-
-import org.kxml2.io.KXmlParser;
-import org.osgi.service.obr.*;
-import org.xmlpull.v1.*;
-
-/**
- * Implements the basic repository. A repository holds a set of resources.
- * 
- * 
- * @version $Revision: 44 $
- */
-public class RepositoryImpl implements Repository {
-	transient Set			resources		= new HashSet();
-	URL						url;
-	String					date;
-	Set						visited			= new HashSet();
-	final static Resource[]	EMPTY_RESOURCE	= new Resource[0];
-	String					name			= "Untitled";
-	long					lastModified;
-	Exception				exception;
-	int						ranking=0;
-
-	/**
-	 * Each repository is identified by a single URL.
-	 * 
-	 * A repository can hold referrals to other repositories. These referred
-	 * repositories are included at the point of referall.
-	 * 
-	 * @param url
-	 */
-	public RepositoryImpl(URL url) {
-		this.url = url;
-	}
-
-	/**
-	 * Refresh the repository from the URL.
-	 * 
-	 * @throws Exception
-	 */
-	public boolean refresh() {
-		exception = null;
-		try {
-			resources.clear();
-			parseDocument(url);
-			visited = null;
-			return true;
-		}
-		catch (Exception e) {
-			e.printStackTrace();
-			exception = e;
-		}
-		return false;
-	}
-
-	/**
-	 * Parse the repository.
-	 * 
-	 * @param parser
-	 * @throws Exception
-	 */
-	private void parseRepository(XmlPullParser parser) throws Exception {
-		try {
-			parser.require(XmlPullParser.START_DOCUMENT, null, null);
-			parser.nextTag();
-			if (parser.getName().equals("bundles"))
-				parseOscar(parser);
-			else {
-				parser.require(XmlPullParser.START_TAG, null, "repository");
-				date = parser.getAttributeValue(null, "lastmodified");
-				name = parser.getAttributeValue(null, "name");
-				if (name == null)
-					name = "Untitled";
-
-				while (parser.nextTag() == XmlPullParser.START_TAG) {
-					if (parser.getName().equals("resource")) {
-						ResourceImpl resource = new ResourceImpl(this, parser);
-						resources.add(resource);
-					}
-					else if (parser.getName().equals("referral"))
-						referral(parser);
-					else
-						throw new IllegalArgumentException(
-								"Invalid tag in repository: " + url + " "
-										+ parser.getName());
-				}
-				parser.require(XmlPullParser.END_TAG, null, "repository");
-			}
-		}
-		catch (XmlPullParserException e) {
-			e.printStackTrace();
-			throw new IllegalArgumentException("XML unregognized around: "
-					+ e.getLineNumber() + " " + e.getMessage());
-		}
-	}
-
-	/**
-	 * Parse an old style OBR repository.
-	 * 
-	 * <dtd-version>1.0</dtd-version> <repository> <name>Oscar Bundle
-	 * Repository</name> <url>http://oscar-osgi.sourceforge.net/</url>
-	 * <date>Fri May 07 16:45:07 CEST 2004</date> <extern-repositories> <!--
-	 * Stefano Lenzi (kismet@interfree.it) -->
-	 * <url>http://domoware.isti.cnr.it/osgi-obr/niche-osgi-obr.xml</url>
-	 * <!--Manuel Palencia (santillan@dit.upm.es) --> <!--
-	 * <url>http://jmood.forge.os4os.org/repository.xml</url> --> <!-- Enrique
-	 * Rodriguez (erodriguez@apache.org) -->
-	 * <url>http://update.cainenable.org/repository.xml</url>
-	 * </extern-repositories> </repository> <bundle> <bundle-name>Bundle
-	 * Repository</bundle-name> <bundle-description> A bundle repository
-	 * service for Oscar. </bundle-description> <bundle-updatelocation>
-	 * http://oscar-osgi.sf.net/repo/bundlerepository/bundlerepository.jar
-	 * </bundle-updatelocation> <bundle-sourceurl>
-	 * http://oscar-osgi.sf.net/repo/bundlerepository/bundlerepository-src.jar
-	 * </bundle-sourceurl> <bundle-version>1.1.3</bundle-version>
-	 * <bundle-docurl> http://oscar-osgi.sf.net/repo/bundlerepository/
-	 * </bundle-docurl> <bundle-category>General</bundle-category>
-	 * <import-package package="org.osgi.framework"/> <export-package
-	 * package="org.ungoverned.osgi.service.bundlerepository"
-	 * specification-version="1.1.0"/> </bundle> *
-	 */
-	private void parseOscar(XmlPullParser parser) throws Exception {
-		parser.require(XmlPullParser.START_TAG, null, "bundles");
-		while (true) {
-			int event = parser.next();
-
-			// Error ..
-			if (event == XmlPullParser.TEXT)
-				event = parser.next();
-
-			if (event != XmlPullParser.START_TAG)
-				break;
-
-			ResourceImpl resource = new ResourceImpl(this);
-
-			if (parser.getName().equals("bundle")) {
-				while (parser.nextTag() == XmlPullParser.START_TAG) {
-					String key = parser.getName();
-					if (key.equals("import-package")) {
-						RequirementImpl requirement = new RequirementImpl(
-								"package");
-						
-						requirement.setOptional(false);
-						requirement.setMultiple(false);
-						
-						String p = parser.getAttributeValue(null, "package");
-						StringBuffer sb = new StringBuffer();
-						sb.append("(&(package=");
-						sb.append(p);
-						sb.append(")");
-						String version = parser.getAttributeValue(null,
-								"specification-version");
-						VersionRange v = new VersionRange("0");
-						if (version != null) {
-							sb.append("(version=");
-							sb.append(v= new VersionRange(version));
-							sb.append(")");
-						}
-						sb.append(")");
-						requirement.setFilter(sb.toString());
-						requirement.setComment("Import-Package: " + p + ";" + v );
-						resource.addRequirement(requirement);
-						
-						parser.nextTag();
-					}
-					else if (key.equals("export-package")) {
-						CapabilityImpl capability = new CapabilityImpl(
-								"package");
-						capability.addProperty("package", parser
-								.getAttributeValue(null, "package"));
-						String version = parser.getAttributeValue(null,
-								"specification-version");
-						if (version != null) {
-							capability.addProperty("version", new VersionRange(
-									version));
-						}
-						resource.addCapability(capability);
-						parser.nextTag();
-					}
-					else {
-						String value = parser.nextText().trim();
-						if (key.equals("bundle-sourceurl"))
-							resource.setSource(new URL(value));
-						else if (key.equals("bundle-docurl"))
-							resource.setDocumentation(new URL(value));
-						else if (key.equals("bundle-updatelocation"))
-							resource.setURL(new URL(value));
-						else if (key.equals("bundle-description"))
-							resource.setDescription(value);
-						else if (key.equals("bundle-category"))
-							resource.addCategory(value);
-						else if (key.equals("bundle-name")) {
-							resource.setName(value);
-							resource.setPresentationName(value);
-						}
-						else if (key.equals("bundle-version"))
-							resource.setVersion(new VersionRange(value));
-						else {
-							resource.put(key, value);
-						}
-					}
-				}
-				resources.add(resource);
-				parser.require(XmlPullParser.END_TAG, null, "bundle");
-			}
-			else if (parser.getName().equals("repository")) {
-				parser.require(XmlPullParser.START_TAG, null, "repository");
-				while (parser.nextTag() == XmlPullParser.START_TAG) {
-					String tag = parser.getName();
-					if (tag.equals("name")) {
-						String name = parser.nextText();
-						if (this.name == null)
-							this.name = name.trim();
-					}
-					else if (tag.equals("url"))
-						parser.nextText().trim();
-					else if (tag.equals("date"))
-						parser.nextText().trim();
-					else if (tag.equals("extern-repositories")) {
-						parser.require(XmlPullParser.START_TAG, null,
-								"extern-repositories");
-						while (parser.nextTag() == XmlPullParser.START_TAG) {
-							if (parser.getName().equals("url"))
-								parseDocument(new URL(parser.nextText().trim()));
-							else
-								throw new IllegalArgumentException(
-										"Invalid tag in repository while parsing extern repositories: "
-												+ url + " " + parser.getName());
-						}
-						parser.require(XmlPullParser.END_TAG, null,
-								"extern-repositories");
-					}
-					else
-						throw new IllegalArgumentException(
-								"Invalid tag in repository: " + url + " "
-										+ parser.getName());
-				}
-				parser.require(XmlPullParser.END_TAG, null, "repository");
-			}
-			else if (parser.getName().equals("dtd-version")) {
-				parser.nextText();
-			}
-			else
-				throw new IllegalArgumentException(
-						"Invalid tag in repository: " + url + " "
-								+ parser.getName());
-		}
-		parser.require(XmlPullParser.END_TAG, null, "bundles");
-	}
-
-	/**
-	 * We have a referral to another repository. Just create another parser and
-	 * read it inline.
-	 * 
-	 * @param parser
-	 */
-	void referral(XmlPullParser parser) {
-		// TODO handle depth!
-		try {
-			parser.require(XmlPullParser.START_TAG, null, "referral");
-			// String depth = parser.getAttributeValue(null, "depth");
-			String path = parser.getAttributeValue(null, "url");
-			URL url = new URL(this.url, path);
-			parseDocument(url);
-			parser.next();
-			parser.require(XmlPullParser.END_TAG, null, "referral");
-		}
-		catch (Exception e) {
-			e.printStackTrace();
-		}
-	}
-
-	/**
-	 * Parse a repository document.
-	 * 
-	 * @param url
-	 * @throws IOException
-	 * @throws XmlPullParserException
-	 * @throws Exception
-	 */
-	void parseDocument(URL url) throws IOException, XmlPullParserException,
-			Exception {
-		if (!visited.contains(url)) {
-			visited.add(url);
-			try {
-				System.out.println("Visiting: " + url);
-				InputStream in = null;
-				
-				if ( url.getPath().endsWith(".zip")) {
-					ZipInputStream zin = new ZipInputStream( url.openStream() );
-					ZipEntry entry = zin.getNextEntry();
-					while ( entry != null ) {
-						if ( entry.getName().equals("repository.xml")) {
-							in = zin;
-							break;
-						}
-						entry = zin.getNextEntry();
-					}
-				} else {
-					in = url.openStream();
-				}
-				Reader reader = new InputStreamReader(in);
-				XmlPullParser parser = new KXmlParser();
-				parser.setInput(reader);
-				parseRepository(parser);
-			} catch( MalformedURLException e ) {
-				System.out.println("Cannot create connection to url");
-			}
-		}
-	}
-
-	public URL getURL() {
-		return url;
-	}
-
-	/**
-	 * @return
-	 */
-	public Collection getResourceList() {
-		return resources;
-	}
-
-	public Resource[] getResources() {
-		return (Resource[]) getResourceList().toArray(EMPTY_RESOURCE);
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public Resource getResource(String id) {
-		for (Iterator i = getResourceList().iterator(); i.hasNext();) {
-			ResourceImpl resource = (ResourceImpl) i.next();
-			if (resource.getId().equals(id))
-				return resource;
-		}
-		return null;
-	}
-
-	public long getLastModified() {
-		return lastModified;
-	}
-
-	public int getRanking() {
-		return ranking;
-	}
-
-	public void setRanking(int ranking) {
-		this.ranking = ranking;
-	}
-
-}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RequirementImpl.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RequirementImpl.java
deleted file mode 100644
index c58f48f..0000000
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/RequirementImpl.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * $Id: RequirementImpl.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $
- * 
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.impl.bundle.obr.resource;
-
-import org.osgi.service.obr.*;
-import org.xmlpull.v1.XmlPullParser;
-
-
-
-/**
- * Implements the Requirement interface.
- * 
- * 
- * @version $Revision: 44 $
- */
-public class RequirementImpl implements Requirement {
-	int		id;
-	String	name;
-	String	filter="()";
-	FilterImpl	_filter;
-	String	comment;
-	boolean optional;
-	boolean multiple;
-	boolean extend;
-	
-	/**
-	 * Create a requirement with the given name.
-	 * 
-	 * @param name
-	 */
-	public RequirementImpl(String name) {
-		this.name = name;
-	}
-
-
-	/**
-	 * Parse the requirement from the pull parser.
-	 * 
-	 * @param parser
-	 * @throws Exception
-	 */
-	public RequirementImpl(XmlPullParser parser) throws Exception {
-		parser.require(XmlPullParser.START_TAG, null, null );
-		name = parser.getAttributeValue(null, "name");
-		filter = parser.getAttributeValue(null, "filter");
-		
-		String opt = parser.getAttributeValue(null,"optional");
-		String mul = parser.getAttributeValue(null,"multiple");
-		String ext = parser.getAttributeValue(null,"extend");
-		optional = "true".equalsIgnoreCase(opt);
-		multiple = "true".equalsIgnoreCase(mul);
-		extend = "true".equalsIgnoreCase(ext);
-		
-		
-		StringBuffer sb = new StringBuffer();
-		while ( parser.next() == XmlPullParser.TEXT ) {
-			sb.append( parser.getText() );
-		}
-		if ( sb.length() > 0 )
-			setComment(sb.toString().trim());
-			
-		parser.require(XmlPullParser.END_TAG, null, null );
-	}
-
-	public void setFilter(String filter) {
-		this.filter = filter;
-		_filter= null;
-	}
-
-	public String getFilter() {
-		return filter;
-	}
-
-	public Tag toXML(String name) {
-		Tag tag = toXML(this);
-		tag.rename(name);
-		return tag;
-	}
-
-
-	public String getName() {
-		return name;
-	}
-
-	public boolean isSatisfied(Capability capability) {
-		if (_filter == null)
-			_filter = new FilterImpl(filter);
-
-		boolean result = _filter.match(capability.getProperties());
-		return result;
-	}
-
-	public String toString() {
-		return name + " " + filter;
-	}
-
-
-	public String getComment() {
-		return comment;
-	}
-
-
-	public void setComment(String comment) {
-		this.comment=comment;
-	}
-
-
-	public static Tag toXML(Requirement requirement) {
-		Tag req = new Tag("require");
-		req.addAttribute("name", requirement.getName());
-		req.addAttribute("filter", requirement.getFilter());
-		
-		req.addAttribute("optional", requirement.isOptional()+"");
-		req.addAttribute("multiple", requirement.isMultiple()+"");
-		req.addAttribute("extend", requirement.isExtend()+"");
-		
-		if ( requirement.getComment() != null )
-			req.addContent(requirement.getComment());
-		
-		return req;
-	}
-
-
-	public boolean isMultiple() {
-		return multiple;
-	}
-
-
-	public boolean isOptional() {
-		return optional;
-	}
-
-
-	public void setOptional(boolean b) {
-		optional = b;
-	}
-
-	public void setMultiple(boolean b) {
-		multiple = b;
-	}
-
-
-	public boolean equals(Object o) {
-		if ( ! (o instanceof Requirement) )
-			return false;
-		
-		Requirement r2 = (Requirement)o;
-		return filter.equals(r2.getFilter()) && name.equals(r2.getName()); 
-	}
-	
-	public int hashCode() {
-		return filter.hashCode() ^ name.hashCode();
-	}
-	
-	public boolean isExtend() {
-		return extend;
-	}
-	
-	public void setExtend(boolean extend) {
-		this.extend = extend;
-	}
-}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ResourceImpl.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ResourceImpl.java
deleted file mode 100644
index 7363bf6..0000000
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/ResourceImpl.java
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * $Id: ResourceImpl.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $
- * 
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.impl.bundle.obr.resource;
-
-import java.io.File;
-import java.net.URL;
-import java.util.*;
-
-import org.osgi.framework.Version;
-import org.osgi.service.obr.*;
-import org.xmlpull.v1.XmlPullParser;
-
-public class ResourceImpl implements Resource {
-	List			capabilities	= new ArrayList();
-	List			requirements	= new ArrayList();
-	URL				url;
-	String			symbolicName;
-	VersionRange		version;
-	List			categories		= new ArrayList();
-	long			size			= -1;
-	String			id;
-	static int		ID				= 1;
-	Map				map				= new HashMap();
-	RepositoryImpl	repository;
-	String			presentationName;
-	File			file;
-
-
-	public ResourceImpl(RepositoryImpl repository, String name,
-			VersionRange version) {
-		this.version = version;
-		if ( version == null)
-			this.version = new VersionRange("0");
-		this.symbolicName = name;
-		this.repository = repository;
-	}
-
-	public ResourceImpl(RepositoryImpl repository, XmlPullParser parser)
-			throws Exception {
-		this.repository = repository;
-		parser.require(XmlPullParser.START_TAG, null, "resource");
-		symbolicName = parser.getAttributeValue(null, "symbolicname");
-		if (symbolicName == null)
-			System.err.println("Hey, no symb name! "
-					+ parser.getAttributeValue(null, "uri"));
-
-		map.put(SYMBOLIC_NAME, symbolicName);
-		presentationName = parser.getAttributeValue(null, PRESENTATION_NAME);
-		if (presentationName != null)
-			map.put(PRESENTATION_NAME, presentationName);
-		String v = parser.getAttributeValue(null, "version");
-		if (v == null)
-			setVersion(new VersionRange("0"));
-		else
-			setVersion(new VersionRange(v));
-
-		setURL(toURL(parser.getAttributeValue(null, "uri")));
-
-		while (parser.nextTag() == XmlPullParser.START_TAG) {
-			if (parser.getName().equals("category")) {
-				categories.add(parser.getAttributeValue(null, "id").trim());
-			}
-			else if (parser.getName().equals("require"))
-				addRequirement(new RequirementImpl(parser));
-			else if (parser.getName().equals("capability"))
-				addCapability(new CapabilityImpl(parser));
-			else {
-				String text = parser.nextText();
-				if (text != null)
-					map.put(parser.getName(), text.trim());
-			}
-			parser.next();
-		}
-		parser.require(XmlPullParser.END_TAG, null, "resource");
-	}
-
-	public ResourceImpl(RepositoryImpl impl) {
-		this.repository = impl;
-	}
-
-	private URL toURL(String attributeValue) throws Exception {
-		if (attributeValue == null)
-			return null;
-
-		return new URL(repository.getURL(), attributeValue);
-	}
-
-	public void addCategory(String category) {
-		categories.add(category);
-	}
-
-	public void addCapability(CapabilityImpl capability) {
-		if (capability != null)
-			capabilities.add(capability);
-	}
-
-	public void addRequirement(RequirementImpl requirement) {
-		if (requirement != null)
-			requirements.add(requirement);
-	}
-
-	public void setLicense(URL license) {
-		if (license != null)
-			map.put(LICENSE_URL, license);
-	}
-
-	public String getDescription() {
-		return (String) map.get(DESCRIPTION);
-	}
-
-	public void setDescription(String description) {
-		if (description != null)
-			map.put(DESCRIPTION, description);
-	}
-
-	public Capability[] getCapabilities() {
-		return (Capability[]) capabilities.toArray(new Capability[capabilities
-				.size()]);
-	}
-
-	public URL getLicense() {
-		return (URL) map.get(LICENSE_URL);
-	}
-
-	public String getSymbolicName() {
-		return symbolicName;
-	}
-
-	public Requirement[] getRequirements() {
-		return (Requirement[]) requirements
-				.toArray(new Requirement[requirements.size()]);
-	}
-
-	public Tag toXML() {
-		return toXML(this );
-	}
-
-	public static Tag toXML(Resource resource) {
-		return toXML(resource,true);
-	}
-
-	public static Tag toXML(Resource resource, boolean relative ) {
-		Tag meta = new Tag("resource");
-		URL url = resource.getURL();
-		String urlString = url.toExternalForm();
-		
-		if ( relative )
-			urlString = makeRelative(resource.getRepository().getURL(), url);
-		
-		meta.addAttribute("uri", urlString );
-		meta.addAttribute(SYMBOLIC_NAME, resource.getSymbolicName());
-		if (resource.getPresentationName() != null)
-			meta
-					.addAttribute(PRESENTATION_NAME, resource
-							.getPresentationName());
-		meta.addAttribute(VERSION, resource.getVersion().toString());
-		meta.addAttribute("id", resource.getId());
-		Map map = new TreeMap(resource.getProperties());
-		for (int i = 0; i < Resource.KEYS.length; i++) {
-			String key = KEYS[i];
-			if (!(key.equals(URL) || key.equals(SYMBOLIC_NAME) || key
-					.equals(VERSION) || key.equals(PRESENTATION_NAME))) {
-				Object value = map.get(KEYS[i]);
-				if (value != null) {
-					if (value instanceof URL)
-						value = makeRelative(resource.getRepository().getURL(),(URL) value);
-					meta.addContent(new Tag(key, value.toString()));
-				}
-			}
-		}
-
-		String[] categories = resource.getCategories();
-		for (int i = 0; i < categories.length; i++) {
-			String category = categories[i];
-			meta.addContent(new Tag("category", new String[] {"id",
-					category.toLowerCase()}));
-		}
-
-		Capability[] capabilities = resource.getCapabilities();
-		for (int i = 0; i < capabilities.length; i++) {
-			meta.addContent(CapabilityImpl.toXML(capabilities[i]));
-		}
-
-		Requirement[] requirements = resource.getRequirements();
-		for (int i = 0; i < requirements.length; i++) {
-			meta.addContent(RequirementImpl.toXML(requirements[i]));
-		}
-		return meta;
-	}
-
-	public URL getURL() {
-		return url;
-	}
-
-	static String makeRelative(URL repository, URL url) {
-		try {
-			if (repository != null) {
-				String a = url.toExternalForm();
-				String b = repository.toExternalForm();
-				int index = b.lastIndexOf('/');
-				if ( index > 0 )
-					b = b.substring(0,index+1);
-				if (a.startsWith(b))
-					return a.substring(b.length());
-			}
-		}
-		catch (Exception e) {
-			// Ignore
-		}
-		return url.toExternalForm();
-	}
-
-	public void setURL(URL url) {
-		this.url = url;
-		if (url != null)
-			map.put(URL, url);
-	}
-
-	public String getCopyright() {
-		return (String) map.get(COPYRIGHT);
-	}
-
-	public Version getVersion() {
-		if (version == null)
-			version = new VersionRange("0");
-		return version.low;
-	}
-
-	void setVersion(VersionRange version) {
-		if (version == null)
-			this.version = new VersionRange("0");
-		else
-			this.version = version;
-	}
-
-	public void setCopyright(String copyright) {
-		if (copyright != null)
-			map.put(COPYRIGHT, copyright);
-	}
-
-	public URL getDocumentation() {
-		return (URL) map.get(DOCUMENTATION_URL);
-	}
-
-	public void setDocumentation(URL documentation) {
-		if (documentation != null)
-			map.put(DOCUMENTATION_URL, documentation);
-	}
-
-	public URL getSource() {
-		return (URL) map.get(SOURCE_URL);
-	}
-
-	public void setSource(URL source) {
-		if (source != null)
-			map.put(SOURCE_URL, source);
-	}
-
-	public boolean satisfies(RequirementImpl requirement) {
-		for (Iterator i = capabilities.iterator(); i.hasNext();) {
-			CapabilityImpl capability = (CapabilityImpl) i.next();
-			if (requirement.isSatisfied(capability))
-				return true;
-		}
-		return false;
-	}
-
-	public String toString() {
-		return symbolicName + "-" + version;
-	}
-
-	public long getSize() {
-		return size;
-	}
-
-	public void setSize(long size) {
-		this.size = size;
-		map.put(SIZE, new Long(size));
-	}
-
-	public Collection getRequirementList() {
-		return requirements;
-	}
-
-	public Collection getCapabilityList() {
-		return capabilities;
-	}
-
-	public int hashCode() {
-		return symbolicName.hashCode() ^ version.hashCode();
-	}
-
-	public boolean equals(Object o) {
-		try {
-			ResourceImpl other = (ResourceImpl) o;
-			return symbolicName.equals(other.symbolicName)
-					&& version.equals(other.version);
-		}
-		catch (ClassCastException e) {
-			return false;
-		}
-	}
-
-	public String[] getCategories() {
-		return (String[]) categories.toArray(new String[categories.size()]);
-	}
-
-	public Map getProperties() {
-		return Collections.unmodifiableMap(map);
-	}
-
-	public synchronized String getId() {
-		if ( id == null )
-			id = symbolicName + "/" + version;
-		return id;
-	}
-
-	public Repository getRepository() {
-		return repository;
-	}
-
-	void setName(String value) {
-		this.symbolicName = value;
-	}
-
-	void put(String name, Object value) {
-		map.put(name, value);
-	}
-
-	public void setPresentationName(String name) {
-		presentationName = name;
-		if (name != null)
-			map.put(PRESENTATION_NAME, name);
-	}
-
-	public String getPresentationName() {
-		return presentationName;
-	}
-
-	public void setFile(File zipFile) {
-		file = zipFile;
-	}
-
-	public Set getExtendList() {
-		Set set = new HashSet();
-		for (Iterator i = requirements.iterator(); i.hasNext();) {
-			RequirementImpl	impl = (RequirementImpl) i.next();
-			if ( impl.isExtend())
-				set.add(impl);
-		}
-		return set;
-	}
-
-}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/StringSet.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/StringSet.java
deleted file mode 100644
index 36d2a27..0000000
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/StringSet.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * $Id: StringSet.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $
- * 
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package org.osgi.impl.bundle.obr.resource;
-
-import java.util.*;
-
-public class StringSet extends HashSet {
-	static final long	serialVersionUID	= 1L;
-
-	public StringSet(String set) {
-		StringTokenizer st = new StringTokenizer(set, ",");
-		while (st.hasMoreTokens())
-			add(st.nextToken().trim());
-	}
-}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Tag.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Tag.java
deleted file mode 100644
index 973c989..0000000
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/Tag.java
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
- * $Id: Tag.java 44 2007-07-13 20:49:41Z hargrave@us.ibm.com $
- * 
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.osgi.impl.bundle.obr.resource;
-
-import java.io.*;
-import java.text.SimpleDateFormat;
-import java.util.*;
-
-/**
- * The Tag class represents a minimal XML tree. It consist of a named element
- * with a hashtable of named attributes. Methods are provided to walk the tree
- * and get its constituents. The content of a Tag is a list that contains String
- * objects or other Tag objects.
- */
-public class Tag {
-	Tag						parent;
-	String					name;
-	Map						attributes	= new TreeMap();
-	Vector					content		= new Vector();
-
-	static SimpleDateFormat	format		= new SimpleDateFormat(
-												"yyyyMMddhhmmss.SSS");
-
-	/**
-	 * Construct a new Tag with a name.
-	 */
-	public Tag(String name) {
-		this.name = name;
-	}
-
-	/**
-	 * Construct a new Tag with a name.
-	 */
-	public Tag(String name, Map attributes) {
-		this.name = name;
-		this.attributes = attributes;
-	}
-
-	/**
-	 * Construct a new Tag with a name and a set of attributes. The attributes
-	 * are given as ( name, value ) ...
-	 */
-	public Tag(String name, String[] attributes) {
-		this.name = name;
-		for (int i = 0; i < attributes.length; i += 2)
-			addAttribute(attributes[i], attributes[i + 1]);
-	}
-
-	/**
-	 * Construct a new Tag with a single string as content.
-	 */
-	public Tag(String name, String content) {
-		this.name = name;
-		addContent(content);
-	}
-
-	/**
-	 * Add a new attribute.
-	 */
-	public void addAttribute(String key, String value) {
-		attributes.put(key, value);
-	}
-
-	/**
-	 * Add a new attribute.
-	 */
-	public void addAttribute(String key, Object value) {
-		if (value == null)
-			return;
-		attributes.put(key, value.toString());
-	}
-
-	/**
-	 * Add a new attribute.
-	 */
-	public void addAttribute(String key, int value) {
-		attributes.put(key, Integer.toString(value));
-	}
-
-	/**
-	 * Add a new date attribute. The date is formatted as the SimpleDateFormat
-	 * describes at the top of this class.
-	 */
-	public void addAttribute(String key, Date value) {
-		attributes.put(key, format.format(value));
-	}
-
-	/**
-	 * Add a new content string.
-	 */
-	public void addContent(String string) {
-		content.addElement(string);
-	}
-
-	/**
-	 * Add a new content tag.
-	 */
-	public void addContent(Tag tag) {
-		content.addElement(tag);
-		tag.parent = this;
-	}
-
-	/**
-	 * Return the name of the tag.
-	 */
-	public String getName() {
-		return name;
-	}
-
-	/**
-	 * Return the attribute value.
-	 */
-	public String getAttribute(String key) {
-		return (String) attributes.get(key);
-	}
-
-	/**
-	 * Return the attribute value or a default if not defined.
-	 */
-	public String getAttribute(String key, String deflt) {
-		String answer = getAttribute(key);
-		return answer == null ? deflt : answer;
-	}
-
-	/**
-	 * Answer the attributes as a Dictionary object.
-	 */
-	public Map getAttributes() {
-		return attributes;
-	}
-
-	/**
-	 * Return the contents.
-	 */
-	public Vector getContents() {
-		return content;
-	}
-
-	/**
-	 * Return a string representation of this Tag and all its children
-	 * recursively.
-	 */
-	public String toString() {
-		StringWriter sw = new StringWriter();
-		print(0, new PrintWriter(sw));
-		return sw.toString();
-	}
-
-	/**
-	 * Return only the tags of the first level of descendants that match the
-	 * name.
-	 */
-	public Vector getContents(String tag) {
-		Vector out = new Vector();
-		for (Enumeration e = content.elements(); e.hasMoreElements();) {
-			Object o = e.nextElement();
-			if (o instanceof Tag && ((Tag) o).getName().equals(tag))
-				out.addElement(o);
-		}
-		return out;
-	}
-
-	/**
-	 * Return the whole contents as a String (no tag info and attributes).
-	 */
-	public String getContentsAsString() {
-		StringBuffer sb = new StringBuffer();
-		getContentsAsString(sb);
-		return sb.toString();
-	}
-
-	/**
-	 * convenient method to get the contents in a StringBuffer.
-	 */
-	public void getContentsAsString(StringBuffer sb) {
-		for (Enumeration e = content.elements(); e.hasMoreElements();) {
-			Object o = e.nextElement();
-			if (o instanceof Tag)
-				((Tag) o).getContentsAsString(sb);
-			else
-				sb.append(o.toString());
-		}
-	}
-
-	/**
-	 * Print the tag formatted to a PrintWriter.
-	 */
-	public void print(int indent, PrintWriter pw) {
-		pw.print("\n");
-		spaces(pw, indent);
-		pw.print('<');
-		pw.print(name);
-
-		for (Iterator e = attributes.keySet().iterator(); e.hasNext();) {
-			String key = (String) e.next();
-			String value = escape((String) attributes.get(key));
-			pw.print(' ');
-			pw.print(key);
-			pw.print("=");
-			String quote = "'";
-			if (value.indexOf(quote) >= 0)
-				quote = "\"";
-			pw.print(quote);
-			pw.print(value);
-			pw.print(quote);
-		}
-
-		if (content.size() == 0)
-			pw.print('/');
-		else {
-			pw.print('>');
-			for (Enumeration e = content.elements(); e.hasMoreElements();) {
-				Object content = e.nextElement();
-				if (content instanceof String) {
-					formatted(pw, indent + 2, 60, escape((String) content));
-				}
-				else if (content instanceof Tag) {
-					Tag tag = (Tag) content;
-					tag.print(indent + 2, pw);
-				}
-			}
-			pw.print("\n");
-			spaces(pw, indent);
-			pw.print("</");
-			pw.print(name);
-		}
-		pw.print('>');
-	}
-
-	/**
-	 * Convenience method to print a string nicely and does character conversion
-	 * to entities.
-	 */
-	void formatted(PrintWriter pw, int left, int width, String s) {
-		int pos = width + 1;
-		s = s.trim();
-
-		for (int i = 0; i < s.length(); i++) {
-			char c = s.charAt(i);
-			if (i == 0 || (Character.isWhitespace(c) && pos > width - 3)) {
-				pw.print("\n");
-				spaces(pw, left);
-				pos = 0;
-			}
-			switch (c) {
-				case '<' :
-					pw.print("&lt;");
-					pos += 4;
-					break;
-				case '>' :
-					pw.print("&gt;");
-					pos += 4;
-					break;
-				case '&' :
-					pw.print("&amp;");
-					pos += 5;
-					break;
-				default :
-					pw.print(c);
-					pos++;
-					break;
-			}
-
-		}
-	}
-
-	/**
-	 * Escape a string, do entity conversion.
-	 */
-	String escape(String s) {
-		if  ( s == null )
-			return "?null?";
-		
-		StringBuffer sb = new StringBuffer();
-		for (int i = 0; i < s.length(); i++) {
-			char c = s.charAt(i);
-			switch (c) {
-				case '<' :
-					sb.append("&lt;");
-					break;
-				case '>' :
-					sb.append("&gt;");
-					break;
-				case '&' :
-					sb.append("&amp;");
-					break;
-				default :
-					sb.append(c);
-					break;
-			}
-		}
-		return sb.toString();
-	}
-
-	/**
-	 * Make spaces.
-	 */
-	void spaces(PrintWriter pw, int n) {
-		while (n-- > 0)
-			pw.print(' ');
-	}
-
-	/**
-	 * root/preferences/native/os
-	 */
-	public Tag[] select(String path) {
-		return select(path, (Tag) null);
-	}
-
-	public Tag[] select(String path, Tag mapping) {
-		Vector v = new Vector();
-		select(path, v, mapping);
-		Tag[] result = new Tag[v.size()];
-		v.copyInto(result);
-		return result;
-	}
-
-	void select(String path, Vector results, Tag mapping) {
-		if (path.startsWith("//")) {
-			int i = path.indexOf('/', 2);
-			String name = path.substring(2, i < 0 ? path.length() : i);
-
-			for (Enumeration e = content.elements(); e.hasMoreElements();) {
-				Object o = e.nextElement();
-				if (o instanceof Tag) {
-					Tag child = (Tag) o;
-					if (match(name, child, mapping))
-						results.add(child);
-					child.select(path, results, mapping);
-				}
-
-			}
-			return;
-		}
-
-		if (path.length() == 0) {
-			results.addElement(this);
-			return;
-		}
-
-		int i = path.indexOf("/");
-		String elementName = path;
-		String remainder = "";
-		if (i > 0) {
-			elementName = path.substring(0, i);
-			remainder = path.substring(i + 1);
-		}
-
-		for (Enumeration e = content.elements(); e.hasMoreElements();) {
-			Object o = e.nextElement();
-			if (o instanceof Tag) {
-				Tag child = (Tag) o;
-				if (child.getName().equals(elementName)
-						|| elementName.equals("*"))
-					child.select(remainder, results, mapping);
-			}
-		}
-	}
-
-	public boolean match(String search, Tag child, Tag mapping) {
-		String target = child.getName();
-		String sn = null;
-		String tn = null;
-
-		if (search.equals("*"))
-			return true;
-
-		int s = search.indexOf(':');
-		if (s > 0) {
-			sn = search.substring(0, s);
-			search = search.substring(s + 1);
-		}
-		int t = target.indexOf(':');
-		if (t > 0) {
-			tn = target.substring(0, t);
-			target = target.substring(t + 1);
-		}
-
-		if (!search.equals(target)) // different tag names
-			return false;
-
-		if (mapping == null) {
-			return tn == sn || (sn != null && sn.equals(tn));
-		}
-		else {
-			String suri = sn == null ? mapping.getAttribute("xmlns") : mapping
-					.getAttribute("xmlns:" + sn);
-			String turi = tn == null ? child.findRecursiveAttribute("xmlns")
-					: child.findRecursiveAttribute("xmlns:" + tn);
-			return turi == suri
-					|| (turi != null && suri != null && turi.equals(suri));
-		}
-	}
-
-	public String getString(String path) {
-		String attribute = null;
-		int index = path.indexOf("@");
-		if (index >= 0) {
-			// attribute
-			attribute = path.substring(index + 1);
-
-			if (index > 0) {
-				// prefix path
-				path = path.substring(index - 1); // skip -1
-			}
-			else
-				path = "";
-		}
-		Tag tags[] = select(path);
-		StringBuffer sb = new StringBuffer();
-		for (int i = 0; i < tags.length; i++) {
-			if (attribute == null)
-				tags[i].getContentsAsString(sb);
-			else
-				sb.append(tags[i].getAttribute(attribute));
-		}
-		return sb.toString();
-	}
-
-	public String getStringContent() {
-		StringBuffer sb = new StringBuffer();
-		for (Enumeration e = content.elements(); e.hasMoreElements();) {
-			Object c = e.nextElement();
-			if (!(c instanceof Tag))
-				sb.append(c);
-		}
-		return sb.toString();
-	}
-
-	public String getNameSpace() {
-		return getNameSpace(name);
-	}
-
-	public String getNameSpace(String name) {
-		int index = name.indexOf(':');
-		if (index > 0) {
-			String ns = name.substring(0, index);
-			return findRecursiveAttribute("xmlns:" + ns);
-		}
-		else
-			return findRecursiveAttribute("xmlns");
-	}
-
-	public String findRecursiveAttribute(String name) {
-		String value = getAttribute(name);
-		if (value != null)
-			return value;
-		if (parent != null)
-			return parent.findRecursiveAttribute(name);
-		return null;
-	}
-
-	public String getLocalName() {
-		int index = name.indexOf(':');
-		if (index <= 0)
-			return name;
-
-		return name.substring(index + 1);
-	}
-
-	public void rename(String string) {
-		name = string;
-	}
-
-
-	public static void convert( Collection c, String type, Tag parent ) {
-		for ( Iterator i=c.iterator(); i.hasNext(); ) {
-			Map	map = (Map) i.next();
-			parent.addContent( new Tag(type, map) );
-		}
-	}
-
-}
diff --git a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/VersionRange.java b/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/VersionRange.java
deleted file mode 100644
index 5770c17..0000000
--- a/bundleplugin/src/main/java/org/osgi/impl/bundle/obr/resource/VersionRange.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * $Id: VersionRange.java 84 2008-08-28 08:11:30Z peter.kriens@aqute.biz $
- * 
- * Copyright (c) OSGi Alliance (2002, 2006, 2007). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.osgi.impl.bundle.obr.resource;
-
-import java.util.regex.*;
-
-import org.osgi.framework.*;
-
-public class VersionRange implements Comparable {
-	Version high;
-	Version low;
-	char start = '[';
-	char end = ']';
-
-	static String V = "[0-9]+(\\.[0-9]+(\\.[0-9]+(\\.[a-zA-Z0-9_-]+)?)?)?";
-	static Pattern RANGE = Pattern.compile("(\\(|\\[)\\s*(" + V + ")\\s*,\\s*(" + V
-			+ ")\\s*(\\)|\\])");
-
-	public VersionRange(String string) {
-		string = string.trim();
-		Matcher m = RANGE.matcher(string);
-		if (m.matches()) {
-			start = m.group(1).charAt(0);
-			low = new Version(m.group(2));
-			high = new Version(m.group(6));
-			end = m.group(10).charAt(0);
-			if (low.compareTo(high) > 0)
-				throw new IllegalArgumentException(
-						"Low Range is higher than High Range: " + low + "-"
-								+ high);
-
-		} else
-			high = low = new Version(string);
-	}
-
-	public boolean isRange() {
-		return high != low;
-	}
-
-	public boolean includeLow() {
-		return start == '[';
-	}
-
-	public boolean includeHigh() {
-		return end == ']';
-	}
-
-	public String toString() {
-		if (high == low)
-			return high.toString();
-
-		StringBuffer sb = new StringBuffer();
-		sb.append(start);
-		sb.append(low);
-		sb.append(',');
-		sb.append(high);
-		sb.append(end);
-		return sb.toString();
-	}
-
-	public boolean equals(Object other) {
-		if (other instanceof VersionRange) {
-			return compareTo(other)==0;
-		}
-		return false;
-	}
-
-	public int hashCode() {
-		return low.hashCode() * high.hashCode();
-	}
-
-	public int compareTo(Object other) {
-		VersionRange range = (VersionRange) other;
-		VersionRange a = this, b = range;
-		if (range.isRange()) {
-			a = range;
-			b = this;
-		} else {
-			if ( !isRange() )
-				return low.compareTo(range.high);
-		}
-		int l = a.low.compareTo(b.low);
-		boolean ll = false;
-		if (a.includeLow())
-			ll = l <= 0;
-		else
-			ll = l < 0;
-
-		if (!ll)
-			return -1;
-
-		int h = a.high.compareTo(b.high);
-		if (a.includeHigh())
-			ll = h >= 0;
-		else
-			ll = h > 0;
-
-		if (ll)
-			return 0;
-		else
-			return 1;
-	}
-}
\ No newline at end of file
diff --git a/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java b/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java
index 8c9ac37..729576c 100644
--- a/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java
+++ b/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BlueprintComponentTest.java
@@ -73,6 +73,9 @@
         instructions.put("nsh_interface", "foo.bar.Namespace");
         instructions.put("nsh_namespace", "ns");
 
+        instructions.put("Export-Service", "p7.Foo;mk=mv");
+        instructions.put("Import-Service", "org.osgi.service.cm.ConfigurationAdmin;availability:=optional");
+
         Properties props = new Properties();
         Builder builder = plugin.buildOSGiBundle(project, instructions, props, plugin.getClasspath(project));
 
diff --git a/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BundlePluginTest.java b/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BundlePluginTest.java
index c9748e8..e968e0e 100644
--- a/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BundlePluginTest.java
+++ b/bundleplugin/src/test/java/org/apache/felix/bundleplugin/BundlePluginTest.java
@@ -21,21 +21,10 @@
  */
 
 import java.io.File;
-import java.io.FileOutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
 import java.util.Properties;
-import java.util.jar.Manifest;
 
-import org.apache.maven.model.Resource;
 import org.apache.maven.plugin.testing.stubs.MavenProjectStub;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.shared.osgi.DefaultMaven2OsgiConverter;
@@ -44,9 +33,6 @@
 import aQute.lib.osgi.Analyzer;
 import aQute.lib.osgi.Builder;
 import aQute.lib.osgi.Jar;
-import org.osgi.framework.Constants;
-import org.osgi.impl.bundle.obr.resource.RepositoryImpl;
-import org.osgi.impl.bundle.obr.resource.BundleInfo;
 
 
 /**
@@ -73,10 +59,6 @@
 
     public void testConvertVersionToOsgi()
     {
-        try {
-            new BundleInfo(new RepositoryImpl(new URL("file:.")), new File("/Users/gnodet/.m2/repository/org/apache/felix/karaf/webconsole/org.apache.felix.karaf.webconsole.branding/1.5.0-SNAPSHOT/org.apache.felix.karaf.webconsole.branding-1.5.0-SNAPSHOT.jar")).build();
-        } catch(Exception e ) {}
-
         String osgiVersion;
 
         osgiVersion = plugin.convertVersionToOsgi( "2.1.0-SNAPSHOT" );
diff --git a/bundlerepository/pom.xml b/bundlerepository/pom.xml
index 9db3ee8..0a541dc 100644
--- a/bundlerepository/pom.xml
+++ b/bundlerepository/pom.xml
@@ -32,6 +32,12 @@
   <dependencies>
     <dependency>
       <groupId>${pom.groupId}</groupId>
+      <artifactId>org.apache.felix.utils</artifactId>
+      <version>0.1.0-SNAPSHOT</version>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>${pom.groupId}</groupId>
       <artifactId>org.osgi.service.obr</artifactId>
       <version>1.0.2</version>
       <optional>true</optional>
@@ -45,7 +51,7 @@
     <dependency>
       <groupId>net.sf.kxml</groupId>
       <artifactId>kxml2</artifactId>
-      <version>2.2.2</version>
+      <version>2.3.0</version>
       <optional>true</optional>
       <exclusions>
         <exclusion>
@@ -90,7 +96,8 @@
             <Private-Package>
                 org.kxml2.io,
                 org.xmlpull.v1,
-                org.apache.felix.bundlerepository.impl.*
+                org.apache.felix.bundlerepository.impl.*,
+                org.apache.felix.utils.*
             </Private-Package>
             <Import-Package>!javax.xml.parsers,!org.xml.sax,org.osgi.service.log;resolution:=optional,org.osgi.service.obr;resolution:=optional,javax.xml.stream;resolution:=optional,*</Import-Package>
             <DynamicImport-Package>org.apache.felix.shell</DynamicImport-Package>
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Capability.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Capability.java
index 4ddba95..09cadff 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Capability.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Capability.java
@@ -49,6 +49,13 @@
  */
 public interface Capability
 {
+
+    String BUNDLE = "bundle";
+    String FRAGMENT = "fragment";
+    String PACKAGE = "package";
+    String SERVICE = "service";
+    String EXECUTIONENVIRONMENT = "ee";
+
     /**
      * Return the name of the capability.
      * 
@@ -56,12 +63,19 @@
     String getName();
 
     /**
-     * Return the set of properties.
+     * Return the properties of this capability
      * 
-     * Notice that the value of the properties is a list of values.
-     * 
-     * @return a Map<String,List>
+     * @return
      */
-    Map getProperties();
+    Property[] getProperties();
+
+    /**
+     * Return the map of properties.
+     * 
+     * @return a Map<String,Object>
+     */
+    Map getPropertiesAsMap();
+
+
 
 }
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/DataModelHelper.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/DataModelHelper.java
new file mode 100644
index 0000000..7ab70c2
--- /dev/null
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/DataModelHelper.java
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * $Header: /cvshome/build/org.osgi.service.obr/src/org/osgi/service/obr/Requirement.java,v 1.4 2006/03/16 14:56:17 hargrave Exp $
+ *
+ * Copyright (c) OSGi Alliance (2006). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This document is an experimental draft to enable interoperability
+// between bundle repositories. There is currently no commitment to
+// turn this draft into an official specification.
+package org.apache.felix.bundlerepository;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.URL;
+import java.util.Map;
+import java.util.jar.Attributes;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Filter;
+
+public interface DataModelHelper {
+
+    /**
+     * Create a simple requirement to be used for selection
+     * @param name
+     * @param filter
+     * @return
+     * @throws org.osgi.framework.InvalidSyntaxException
+     */
+    Requirement requirement(String name, String filter);
+
+    /**
+     * Create an extender filter supporting the SUBSET, SUPERSET and other extensions
+     *
+     * @param filter the string filter
+     * @return
+     * @throws org.osgi.framework.InvalidSyntaxException
+     */
+    Filter filter(String filter);
+
+    /**
+     * Create a repository from the specified URL.
+     *
+     * @param repository
+     * @return
+     * @throws Exception
+     */
+    Repository repository(URL repository) throws Exception;
+
+    /**
+     * Create a repository for the given set of resources.
+     * Such repositories can be used to create a resolver
+     * that would resolve on a subset of available resources
+     * instead of all of them.
+     *
+     * @param resources an array of resources
+     * @return a repository containing the given resources
+     */
+    Repository repository(Resource[] resources);
+
+    /**
+     * Create a capability
+     *
+     * @param name name of this capability
+     * @param properties the properties
+     * @return a new capability with the specified name and properties
+     */
+    Capability capability(String name, Map properties);
+
+    /**
+     * Create a resource corresponding to the given bundle.
+     *
+     * @param bundle the bundle
+     * @return the corresponding resource
+     */
+    Resource createResource(Bundle bundle);
+
+    /**
+     * Create a resource for the bundle located at the
+     * given location.
+     *
+     * @param bundleUrl the location of the bundle
+     * @return the corresponding resource
+     * @throws IOException
+     */
+    Resource createResource(URL bundleUrl) throws IOException;
+
+    /**
+     * Create a resource corresponding to the given manifest
+     * entries.
+     *
+     * @param attributes the manifest headers
+     * @return the corresponding resource
+     */
+    Resource createResource(Attributes attributes);
+
+    //===========================
+    //==   XML serialization   ==
+    //===========================
+
+    Repository readRepository(String xml) throws Exception;
+
+    Repository readRepository(Reader reader) throws Exception;
+
+    Resource readResource(String xml) throws Exception;
+
+    Resource readResource(Reader reader) throws Exception;
+
+    Capability readCapability(String xml) throws Exception;
+
+    Capability readCapability(Reader reader) throws Exception;
+
+    Requirement readRequirement(String xml) throws Exception;
+
+    Requirement readRequirement(Reader reader) throws Exception;
+
+    Property readProperty(String xml) throws Exception;
+
+    Property readProperty(Reader reader) throws Exception;
+
+    String writeRepository(Repository repository);
+
+    void writeRepository(Repository repository, Writer writer) throws IOException;
+
+    String writeResource(Resource resource);
+
+    void writeResource(Resource resource, Writer writer) throws IOException;
+
+    String writeCapability(Capability capability);
+
+    void writeCapability(Capability capability, Writer writer) throws IOException;
+
+    String writeRequirement(Requirement requirement);
+
+    void writeRequirement(Requirement requirement, Writer writer) throws IOException;
+
+    String writeProperty(Property property);
+
+    void writeProperty(Property property, Writer writer) throws IOException;
+
+}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CategoryImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Property.java
similarity index 70%
rename from bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CategoryImpl.java
rename to bundlerepository/src/main/java/org/apache/felix/bundlerepository/Property.java
index 84c4eba..469beac 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CategoryImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Property.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -16,19 +16,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.bundlerepository.impl;
+package org.apache.felix.bundlerepository;
 
-public class CategoryImpl
+public interface Property
 {
-    String m_id = null;
 
-    public void setId(String id)
-    {
-        m_id = id;
-    }
+    String VERSION = "version";
+    String URL = "url";
+    String URI = "uri";
+    String LONG = "long";
+    String DOUBLE = "double";
+    String SET = "set";
 
-    public String getId()
-    {
-        return m_id;
-    }
-}
\ No newline at end of file
+    String getName();
+
+    String getType();
+
+    String getValue();
+
+    Object getConvertedValue();
+
+}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdmin.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdmin.java
index f43ba62..cfa43de 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdmin.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdmin.java
@@ -40,9 +40,7 @@
 package org.apache.felix.bundlerepository;
 
 import java.net.URL;
-import java.util.Map;
 
-import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
 
 /**
@@ -171,50 +169,10 @@
     Repository getLocalRepository();
 
     /**
-     * Create a simple requirement to be used for selection
-     * @param name
-     * @param filter
-     * @return
-     * @throws InvalidSyntaxException
-     */
-    Requirement requirement(String name, String filter) throws InvalidSyntaxException;
-
-    /**
-     * Create an extender filter supporting the SUBSET, SUPERSET and other extensions
+     * Return a helper to perform various operations on the data model
      *
-     * @param filter the string filter
      * @return
-     * @throws InvalidSyntaxException
      */
-    Filter filter(String filter) throws InvalidSyntaxException;
-
-    /**
-     * Create a repository from the specified URL.
-     * 
-     * @param repository
-     * @return
-     * @throws Exception
-     */
-    Repository repository(URL repository) throws Exception;
-
-    /**
-     * Create a repository for the given set of resources.
-     * Such repositories can be used to create a resolver
-     * that would resolve on a subset of available resources
-     * instead of all of them.
-     *
-     * @param resources an array of resources
-     * @return a repository containing the given resources
-     */
-    Repository repository(Resource[] resources);
-
-    /**
-     * Create a capability
-     *
-     * @param name name of this capability
-     * @param properties the properties
-     * @return a new capability with the specified name and properties
-     */
-    Capability capability(String name, Map properties);
+    DataModelHelper getHelper();
 
 }
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resource.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resource.java
index 1208b31..7246873 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resource.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resource.java
@@ -48,8 +48,6 @@
  * 
  * Resources have capabilities and requirements. All a resource's requirements
  * must be satisfied before it can be installed.
- * 
- * @version $Revision: 1.5 $
  */
 public interface Resource
 {
@@ -79,25 +77,68 @@
 
     final String CATEGORY = "category";
 
-    // get readable name
+    final String MANIFEST_VERSION = "manifestversion";
 
+    /**
+     * Get all resource properties
+     * @return
+     */
     Map getProperties();
 
-    String getSymbolicName();
-
-    String getPresentationName();
-
-    Version getVersion();
-
+    /**
+     * Shortcut for {{getProperties().get(ID)}}
+     * @return
+     */
     String getId();
 
+    /**
+     * Shortcut for {{getProperties().get(SYMBOLIC_NAME)}}
+     * @return
+     */
+    String getSymbolicName();
+
+    /**
+     * Shortcut for {{getProperties().get(VERSION)}}
+     * @return
+     */
+    Version getVersion();
+
+    /**
+     * Shortcut for {{getProperties().get(PRESENTATION_NAME)}}
+     * @return
+     */
+    String getPresentationName();
+
+    /**
+     * Shortcut for {{getProperties().get(URI)}}
+     * @return
+     */
     String getURI();
 
-    Requirement[] getRequirements();
+    /**
+     * Shortcut for {{getProperties().get(SIZE)}}
+     * @return
+     */
+    Long getSize();
 
+    /**
+     * Retrieve this resource categories
+     * @return
+     */
+    String[] getCategories();
+
+    /**
+     * Retrieve the capabilities
+     * @return
+     */
     Capability[] getCapabilities();
 
-    String[] getCategories();
+    /**
+     * Retrieve the requirements
+     *
+     * @return
+     */
+    Requirement[] getRequirements();
 
     /**
      * Returns whether this resource is a local one or not.
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/Activator.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/Activator.java
index 1d5b0cb..160f065 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/Activator.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/Activator.java
@@ -21,6 +21,7 @@
 import java.util.Hashtable;
 
 import org.apache.felix.bundlerepository.impl.wrapper.Wrapper;
+import org.apache.felix.utils.log.Logger;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.apache.felix.bundlerepository.RepositoryAdmin;
@@ -29,15 +30,44 @@
 
 public class Activator implements BundleActivator
 {
-    private transient BundleContext m_context = null;
+    private static BundleContext context = null;
+    private static Logger logger = new Logger(null);
     private transient RepositoryAdminImpl m_repoAdmin = null;
 
+
+    public static BundleContext getContext()
+    {
+        return context;
+    }
+
+    static void setContext(BundleContext context)
+    {
+        Activator.context = context;
+    }
+
+    public static void log(int level, String message)
+    {
+        if (logger != null)
+        {
+            logger.log(level, message);
+        }
+    }
+
+    public static void log(int level, String message, Throwable exception)
+    {
+        if (logger != null)
+        {
+            logger.log(level, message, exception);
+        }
+    }
+
     public void start(BundleContext context)
     {
-        m_context = context;
+        Activator.context = context;
+        Activator.logger = new Logger(context);
 
         // Register bundle repository service.
-        m_repoAdmin = new RepositoryAdminImpl(m_context, new Logger(m_context));
+        m_repoAdmin = new RepositoryAdminImpl(context, logger);
         context.registerService(
             RepositoryAdmin.class.getName(),
             m_repoAdmin, null);
@@ -62,7 +92,7 @@
             // wrapper for the bundle repository service.
             context.registerService(
                 org.apache.felix.shell.Command.class.getName(),
-                new ObrCommandImpl(m_context, m_repoAdmin), null);
+                new ObrCommandImpl(Activator.context, m_repoAdmin), null);
         }
         catch (Throwable th)
         {
@@ -74,7 +104,7 @@
 			Hashtable dict = new Hashtable();
 			dict.put(URLConstants.URL_HANDLER_PROTOCOL, "obr");
 			context.registerService(URLStreamHandlerService.class.getName(),
-					new ObrURLStreamHandlerService(m_context, m_repoAdmin), dict);
+					new ObrURLStreamHandlerService(Activator.context, m_repoAdmin), dict);
 		}
         catch (Exception e)
 		{
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/Base64Encoder.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/Base64Encoder.java
new file mode 100644
index 0000000..93b8908
--- /dev/null
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/Base64Encoder.java
@@ -0,0 +1,131 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.bundlerepository.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class Base64Encoder
+{
+    private static final byte encTab[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
+        0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52,
+        0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64,
+        0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+        0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31,
+        0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f };
+
+    public static String base64Encode(String s) throws IOException
+    {
+        return encode(s.getBytes(), 0);
+    }
+
+    /**
+     * Encode a raw byte array to a Base64 String.
+     * 
+     * @param in Byte array to encode.
+     * @param len Length of Base64 lines. 0 means no line breaks.
+    **/
+    public static String encode(byte[] in, int len) throws IOException
+    {
+        ByteArrayOutputStream baos = null;
+        ByteArrayInputStream bais = null;
+        try
+        {
+            baos = new ByteArrayOutputStream();
+            bais = new ByteArrayInputStream(in);
+            encode(bais, baos, len);
+            // ASCII byte array to String
+            return (new String(baos.toByteArray()));
+        }
+        finally
+        {
+            if (baos != null)
+            {
+                baos.close();
+            }
+            if (bais != null)
+            {
+                bais.close();
+            }
+        }
+    }
+
+    public static void encode(InputStream in, OutputStream out, int len)
+        throws IOException
+    {
+
+        // Check that length is a multiple of 4 bytes
+        if (len % 4 != 0)
+        {
+            throw new IllegalArgumentException("Length must be a multiple of 4");
+        }
+
+        // Read input stream until end of file
+        int bits = 0;
+        int nbits = 0;
+        int nbytes = 0;
+        int b;
+
+        while ((b = in.read()) != -1)
+        {
+            bits = (bits << 8) | b;
+            nbits += 8;
+            while (nbits >= 6)
+            {
+                nbits -= 6;
+                out.write(encTab[0x3f & (bits >> nbits)]);
+                nbytes++;
+                // New line
+                if (len != 0 && nbytes >= len)
+                {
+                    out.write(0x0d);
+                    out.write(0x0a);
+                    nbytes -= len;
+                }
+            }
+        }
+
+        switch (nbits)
+        {
+            case 2:
+                out.write(encTab[0x3f & (bits << 4)]);
+                out.write(0x3d); // 0x3d = '='
+                out.write(0x3d);
+                break;
+            case 4:
+                out.write(encTab[0x3f & (bits << 2)]);
+                out.write(0x3d);
+                break;
+        }
+
+        if (len != 0)
+        {
+            if (nbytes != 0)
+            {
+                out.write(0x0d);
+                out.write(0x0a);
+            }
+            out.write(0x0d);
+            out.write(0x0a);
+        }
+    }
+}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CapabilityImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CapabilityImpl.java
index 376d82a..e33dd40 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CapabilityImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CapabilityImpl.java
@@ -21,17 +21,32 @@
 import java.util.*;
 
 import org.apache.felix.bundlerepository.Capability;
-import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.bundlerepository.Property;
 
 public class CapabilityImpl implements Capability
 {
     private String m_name = null;
     private final Map m_map = new HashMap();
+    private final List m_list = new ArrayList();
 
     public CapabilityImpl()
     {
     }
 
+    public CapabilityImpl(String name)
+    {
+        setName(name);
+    }
+
+    public CapabilityImpl(String name, PropertyImpl[] properties)
+    {
+        setName(name);
+        for (int i = 0; properties != null && i < properties.length; i++)
+        {
+            addProperty(properties[i]);
+        }
+    }
+
     public String getName()
     {
         return m_name;
@@ -42,19 +57,30 @@
         m_name = name.intern();
     }
 
-    public Map getProperties()
+    public Map getPropertiesAsMap()
     {
         return m_map;
     }
 
-    protected void addP(PropertyImpl prop)
+    public Property[] getProperties()
     {
-        addP(prop.getN(), prop.getV());
+        return (Property[]) m_list.toArray(new Property[m_list.size()]);
     }
 
-    protected void addP(String name, Object value)
+    public void addProperty(Property prop)
     {
-        m_map.put(name.toLowerCase(), value);
+        m_map.put(prop.getName().toLowerCase(), prop.getConvertedValue());
+        m_list.add(prop);
+    }
+
+    public void addProperty(String name, String value)
+    {
+        addProperty(name, null, value);
+    }
+
+    public void addProperty(String name, String type, String value)
+    {
+        addProperty(new PropertyImpl(name, type, value));
     }
 
     public String toString()
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/DataModelHelperImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/DataModelHelperImpl.java
new file mode 100644
index 0000000..1d63fe1
--- /dev/null
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/DataModelHelperImpl.java
@@ -0,0 +1,1042 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.bundlerepository.impl;
+
+import java.io.*;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.DataModelHelper;
+import org.apache.felix.bundlerepository.Property;
+import org.apache.felix.bundlerepository.Repository;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.utils.filter.FilterImpl;
+import org.apache.felix.utils.manifest.Attribute;
+import org.apache.felix.utils.manifest.Clause;
+import org.apache.felix.utils.manifest.Directive;
+import org.apache.felix.utils.manifest.Parser;
+import org.apache.felix.utils.version.VersionCleaner;
+import org.apache.felix.utils.version.VersionRange;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.Version;
+
+public class DataModelHelperImpl implements DataModelHelper
+{
+
+    public static final String BUNDLE_LICENSE = "Bundle-License";
+    public static final String BUNDLE_SOURCE = "Bundle-Source";
+
+    public Requirement requirement(String name, String filter)
+    {
+        RequirementImpl req = new RequirementImpl();
+        req.setName(name);
+        if (filter != null)
+        {
+            req.setFilter(filter);
+        }
+        return req;
+    }
+
+    public Filter filter(String filter)
+    {
+        try
+        {
+            return FilterImpl.newInstance(filter);
+        }
+        catch (InvalidSyntaxException e)
+        {
+            IllegalArgumentException ex = new IllegalArgumentException();
+            ex.initCause(e);
+            throw ex;
+        }
+    }
+
+    public Repository repository(final URL url) throws Exception
+    {
+        InputStream is = null;
+        BufferedReader br = null;
+
+        try
+        {
+            // Do it the manual way to have a chance to
+            // set request properties as proxy auth (EW).
+            URLConnection conn = url.openConnection();
+
+            // Support for http proxy authentication
+            String auth = System.getProperty("http.proxyAuth");
+            if ((auth != null) && (auth.length() > 0))
+            {
+                if ("http".equals(url.getProtocol()) || "https".equals(url.getProtocol()))
+                {
+                    String base64 = Base64Encoder.base64Encode(auth);
+                    conn.setRequestProperty("Proxy-Authorization", "Basic " + base64);
+                }
+            }
+
+            if (url.getPath().endsWith(".zip"))
+            {
+                ZipInputStream zin = new ZipInputStream(conn.getInputStream());
+                ZipEntry entry = zin.getNextEntry();
+                while (entry != null)
+                {
+                    if (entry.getName().equals("repository.xml"))
+                    {
+                        is = zin;
+                        break;
+                    }
+                    entry = zin.getNextEntry();
+                }
+            }
+            else
+            {
+                is = conn.getInputStream();
+            }
+
+            if (is != null)
+            {
+                RepositoryImpl repository = repository(is);
+                repository.setURI(url.toExternalForm());
+                return repository;
+            }
+            else
+            {
+                // This should not happen.
+                throw new Exception("Unable to get input stream for repository.");
+            }
+        }
+        finally
+        {
+            try
+            {
+                if (is != null)
+                {
+                    is.close();
+                }
+            }
+            catch (IOException ex)
+            {
+                // Not much we can do.
+            }
+        }
+    }
+
+    public RepositoryImpl repository(InputStream is) throws Exception
+    {
+        RepositoryParser parser = RepositoryParser.getParser();
+        RepositoryImpl repository = parser.parseRepository(is);
+        return repository;
+    }
+
+    public Repository repository(Resource[] resources)
+    {
+        return new RepositoryImpl(resources);
+    }
+
+    public Capability capability(String name, Map properties)
+    {
+        CapabilityImpl cap = new CapabilityImpl(name);
+        for (Iterator it = properties.entrySet().iterator(); it.hasNext();)
+        {
+            Map.Entry e = (Map.Entry) it.next();
+            cap.addProperty((String) e.getKey(), (String) e.getValue());
+        }
+        return cap;
+    }
+
+    public String writeRepository(Repository repository)
+    {
+        try
+        {
+            StringWriter sw = new StringWriter();
+            writeRepository(repository, sw);
+            return sw.toString();
+        }
+        catch (IOException e)
+        {
+            IllegalStateException ex = new IllegalStateException(e);
+            ex.initCause(e);
+            throw ex;
+        }
+    }
+
+    public void writeRepository(Repository repository, Writer writer) throws IOException
+    {
+        XmlWriter w = new XmlWriter(writer);
+        toXml(w, repository);
+    }
+
+    public String writeResource(Resource resource)
+    {
+        try
+        {
+            StringWriter sw = new StringWriter();
+            writeResource(resource, sw);
+            return sw.toString();
+        }
+        catch (IOException e)
+        {
+            IllegalStateException ex = new IllegalStateException(e);
+            ex.initCause(e);
+            throw ex;
+        }
+    }
+
+    public void writeResource(Resource resource, Writer writer) throws IOException
+    {
+        XmlWriter w = new XmlWriter(writer);
+        toXml(w, resource);
+    }
+
+    public String writeCapability(Capability capability)
+    {
+        try
+        {
+            StringWriter sw = new StringWriter();
+            writeCapability(capability, sw);
+            return sw.toString();
+        }
+        catch (IOException e)
+        {
+            IllegalStateException ex = new IllegalStateException(e);
+            ex.initCause(e);
+            throw ex;
+        }
+    }
+
+    public void writeCapability(Capability capability, Writer writer) throws IOException
+    {
+        XmlWriter w = new XmlWriter(writer);
+        toXml(w, capability);
+    }
+
+    public String writeRequirement(Requirement requirement)
+    {
+        try
+        {
+            StringWriter sw = new StringWriter();
+            writeRequirement(requirement, sw);
+            return sw.toString();
+        }
+        catch (IOException e)
+        {
+            IllegalStateException ex = new IllegalStateException(e);
+            ex.initCause(e);
+            throw ex;
+        }
+    }
+
+    public void writeRequirement(Requirement requirement, Writer writer) throws IOException
+    {
+        XmlWriter w = new XmlWriter(writer);
+        toXml(w, requirement);
+    }
+
+    public String writeProperty(Property property)
+    {
+        try
+        {
+            StringWriter sw = new StringWriter();
+            writeProperty(property, sw);
+            return sw.toString();
+        }
+        catch (IOException e)
+        {
+            IllegalStateException ex = new IllegalStateException(e);
+            ex.initCause(e);
+            throw ex;
+        }
+    }
+
+    public void writeProperty(Property property, Writer writer) throws IOException
+    {
+        XmlWriter w = new XmlWriter(writer);
+        toXml(w, property);
+    }
+
+    private static void toXml(XmlWriter w, Repository repository) throws IOException
+    {
+        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmss.SSS");
+        w.element(RepositoryParser.REPOSITORY)
+            .attribute(RepositoryParser.NAME, repository.getName())
+            .attribute(RepositoryParser.LASTMODIFIED, format.format(new Date(repository.getLastModified())));
+
+        if (repository instanceof RepositoryImpl)
+        {
+            Referral[] referrals = ((RepositoryImpl) repository).getReferrals();
+            for (int i = 0; referrals != null && i < referrals.length; i++)
+            {
+                w.element(RepositoryParser.REFERRAL)
+                    .attribute(RepositoryParser.DEPTH, new Integer(referrals[i].getDepth()))
+                    .attribute(RepositoryParser.URL, referrals[i].getUrl())
+                    .end();
+            }
+        }
+
+        Resource[] resources = repository.getResources();
+        for (int i = 0; resources != null && i < resources.length; i++)
+        {
+            toXml(w, resources[i]);
+        }
+
+        w.end();
+    }
+
+    private static void toXml(XmlWriter w, Resource resource) throws IOException
+    {
+        w.element(RepositoryParser.RESOURCE)
+            .attribute(Resource.ID, resource.getId())
+            .attribute(Resource.SYMBOLIC_NAME, resource.getSymbolicName())
+            .attribute(Resource.PRESENTATION_NAME, resource.getPresentationName())
+            .attribute(Resource.URI, resource.getURI())
+            .attribute(Resource.VERSION, resource.getVersion().toString());
+
+        w.textElement(Resource.DESCRIPTION, resource.getProperties().get(Resource.DESCRIPTION))
+            .textElement(Resource.SIZE, resource.getProperties().get(Resource.SIZE))
+            .textElement(Resource.DOCUMENTATION_URI, resource.getProperties().get(Resource.DOCUMENTATION_URI))
+            .textElement(Resource.SOURCE_URI, resource.getProperties().get(Resource.SOURCE_URI))
+            .textElement(Resource.JAVADOC_URI, resource.getProperties().get(Resource.JAVADOC_URI))
+            .textElement(Resource.LICENSE_URI, resource.getProperties().get(Resource.LICENSE_URI));
+
+        String[] categories = resource.getCategories();
+        for (int i = 0; categories != null && i < categories.length; i++)
+        {
+            w.element(RepositoryParser.CATEGORY)
+                .attribute(RepositoryParser.ID, categories[i])
+                .end();
+        }
+        Capability[] capabilities = resource.getCapabilities();
+        for (int i = 0; capabilities != null && i < capabilities.length; i++)
+        {
+            toXml(w, capabilities[i]);
+        }
+        Requirement[] requirements = resource.getRequirements();
+        for (int i = 0; requirements != null && i < requirements.length; i++)
+        {
+            toXml(w, requirements[i]);
+        }
+        w.end();
+    }
+
+    private static void toXml(XmlWriter w, Capability capability) throws IOException
+    {
+        w.element(RepositoryParser.CAPABILITY)
+            .attribute(RepositoryParser.NAME, capability.getName());
+        Property[] props = capability.getProperties();
+        for (int j = 0; props != null && j < props.length; j++)
+        {
+            toXml(w, props[j]);
+        }
+        w.end();
+    }
+
+    private static void toXml(XmlWriter w, Property property) throws IOException
+    {
+        w.element(RepositoryParser.P)
+            .attribute(RepositoryParser.N, property.getName())
+            .attribute(RepositoryParser.T, property.getType())
+            .attribute(RepositoryParser.V, property.getValue())
+            .end();
+    }
+
+    private static void toXml(XmlWriter w, Requirement requirement) throws IOException
+    {
+        w.element(RepositoryParser.REQUIRE)
+            .attribute(RepositoryParser.NAME, requirement.getName())
+            .attribute(RepositoryParser.FILTER, requirement.getFilter())
+            .attribute(RepositoryParser.EXTEND, Boolean.toString(requirement.isExtend()))
+            .attribute(RepositoryParser.MULTIPLE, Boolean.toString(requirement.isMultiple()))
+            .attribute(RepositoryParser.OPTIONAL, Boolean.toString(requirement.isOptional()))
+            .text(requirement.getComment().trim())
+            .end();
+    }
+
+    public Resource createResource(final Bundle bundle)
+    {
+        final Dictionary dict = bundle.getHeaders();
+        return createResource(new Headers()
+        {
+            public String getHeader(String name)
+            {
+                return (String) dict.get(name);
+            }
+        });
+    }
+
+    public Resource createResource(final URL bundleUrl) throws IOException
+    {
+        ResourceImpl resource = createResource(new Headers()
+        {
+            private final Manifest manifest;
+            private Properties localization;
+            {
+                // Do not use a JarInputStream so that we can read the manifest even if it's not
+                // the first entry in the JAR.  
+                byte[] man = loadEntry(JarFile.MANIFEST_NAME);
+                if (man == null)
+                {
+                    throw new IllegalArgumentException("The specified url is not a valid jar (can't read manifest): " + bundleUrl);
+                }
+                manifest = new Manifest(new ByteArrayInputStream(man));
+            }
+            public String getHeader(String name)
+            {
+                String value = manifest.getMainAttributes().getValue(name);
+                if (value != null && value.startsWith("%"))
+                {
+                    if (localization == null)
+                    {
+                        try
+                        {
+                            localization = new Properties();
+                            String path = manifest.getMainAttributes().getValue(Constants.BUNDLE_LOCALIZATION);
+                            if (path == null)
+                            {
+                                path = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
+                            }
+                            path += ".properties";
+                            byte[] loc = loadEntry(path);
+                            if (loc != null)
+                            {
+                                localization.load(new ByteArrayInputStream(loc));
+                            }
+                        }
+                        catch (IOException e)
+                        {
+                            // TODO: ?
+                        }
+                    }
+                    value = value.substring(1);
+                    value = localization.getProperty(value, value);
+                }
+                return value;
+            }
+            private byte[] loadEntry(String name) throws IOException
+            {
+                InputStream is = bundleUrl.openStream();
+                try
+                {
+                    ZipInputStream jis = new ZipInputStream(is);
+                    for (ZipEntry e = jis.getNextEntry(); e != null; e = jis.getNextEntry())
+                    {
+                        if (name.equalsIgnoreCase(e.getName()))
+                        {
+                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                            byte[] buf = new byte[1024];
+                            int n;
+                            while ((n = jis.read(buf, 0, buf.length)) > 0)
+                            {
+                                baos.write(buf, 0, n);
+                            }
+                            return baos.toByteArray();
+                        }
+                    }
+                }
+                finally
+                {
+                    is.close();
+                }
+                return null;
+            }
+        });
+        if (resource != null)
+        {
+            if ("file".equals(bundleUrl.getProtocol()))
+            {
+                try {
+                    File f = new File(bundleUrl.toURI());
+                    resource.put(Resource.SIZE, Long.toString(f.length()), null);
+                } catch (URISyntaxException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+            resource.put(Resource.URI, bundleUrl.toExternalForm(), null);
+        }
+        return resource;
+    }
+
+    public Resource createResource(final Attributes attributes)
+    {
+        return createResource(new Headers()
+        {
+            public String getHeader(String name)
+            {
+                return attributes.getValue(name);
+            }
+        });
+    }
+
+    public ResourceImpl createResource(Headers headers)
+    {
+        String bsn = headers.getHeader(Constants.BUNDLE_SYMBOLICNAME);
+        if (bsn == null)
+        {
+            return null;
+        }
+        ResourceImpl resource = new ResourceImpl();
+        populate(headers, resource);
+        return resource;
+    }
+
+    static void populate(Headers headers, ResourceImpl resource)
+    {
+        String bsn = getSymbolicName(headers);
+        String v = getVersion(headers);
+
+        resource.put(Resource.ID, bsn + "/" + v);
+        resource.put(Resource.SYMBOLIC_NAME, bsn);
+        resource.put(Resource.VERSION, v);
+        if (headers.getHeader(Constants.BUNDLE_NAME) != null)
+        {
+            resource.put(Resource.PRESENTATION_NAME, headers.getHeader(Constants.BUNDLE_NAME));
+        }
+        if (headers.getHeader(Constants.BUNDLE_DESCRIPTION) != null)
+        {
+            resource.put(Resource.DESCRIPTION, headers.getHeader(Constants.BUNDLE_DESCRIPTION));
+        }
+        if (headers.getHeader(BUNDLE_LICENSE) != null)
+        {
+            resource.put(Resource.LICENSE_URI, headers.getHeader(BUNDLE_LICENSE));
+        }
+        if (headers.getHeader(Constants.BUNDLE_COPYRIGHT) != null)
+        {
+            resource.put(Resource.COPYRIGHT, headers.getHeader(Constants.BUNDLE_COPYRIGHT));
+        }
+        if (headers.getHeader(Constants.BUNDLE_DOCURL) != null)
+        {
+            resource.put(Resource.DOCUMENTATION_URI, headers.getHeader(Constants.BUNDLE_DOCURL));
+        }
+        if (headers.getHeader(BUNDLE_SOURCE) != null)
+        {
+            resource.put(Resource.SOURCE_URI, headers.getHeader(BUNDLE_SOURCE));
+        }
+
+        doSize(resource, headers);
+        doCategories(resource, headers);
+        doBundle(resource, headers);
+        doImportExportServices(resource, headers);
+        doFragment(resource, headers);
+        doRequires(resource, headers);
+        doExports(resource, headers);
+        doImports(resource, headers);
+        doExecutionEnvironment(resource, headers);
+    }
+
+    private static void doSize(ResourceImpl resource, Headers headers)
+    {
+        //To change body of created methods use File | Settings | File Templates.
+    }
+
+    private static void doCategories(ResourceImpl resource, Headers headers)
+    {
+        Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.BUNDLE_CATEGORY));
+        for (int i = 0; clauses != null && i < clauses.length; i++)
+        {
+            resource.addCategory(clauses[i].getName());
+        }
+    }
+
+    private static void doImportExportServices(ResourceImpl resource, Headers headers)
+    {
+        Clause[] imports = Parser.parseHeader(headers.getHeader(Constants.IMPORT_SERVICE));
+        for (int i = 0; imports != null && i < imports.length; i++) {
+            RequirementImpl ri = new RequirementImpl(Capability.SERVICE);
+            ri.setFilter(createServiceFilter(imports[i]));
+            ri.addText("Import Service " + imports[i].getName());
+
+            String avail = imports[i].getDirective("availability");
+            ri.setOptional("optional".equalsIgnoreCase(avail));
+            ri.setMultiple(true);
+            resource.addRequire(ri);
+        }
+
+        Clause[] exports = Parser.parseHeader(headers.getHeader(Constants.EXPORT_SERVICE));
+        for (int i = 0; exports != null && i < exports.length; i++) {
+            CapabilityImpl cap = createServiceCapability(exports[i]);
+            resource.addCapability(cap);
+        }
+    }
+
+    private static String createServiceFilter(Clause clause) {
+        String f = clause.getAttribute("filter");
+		StringBuffer filter = new StringBuffer();
+        if (f != null) {
+            filter.append("(&");
+        }
+        filter.append("(");
+        filter.append(Capability.SERVICE);
+        filter.append("=");
+		filter.append(clause.getName());
+		filter.append(")");
+        if (f != null) {
+            if (!f.startsWith("("))
+            {
+                filter.append("(").append(f).append(")");
+            }
+            else
+            {
+                filter.append(f);
+            }
+            filter.append(")");
+        }
+		return filter.toString();
+    }
+
+    private static CapabilityImpl createServiceCapability(Clause clause) {
+        CapabilityImpl capability = new CapabilityImpl(Capability.SERVICE);
+        capability.addProperty(Capability.SERVICE, clause.getName());
+        Attribute[] attributes = clause.getAttributes();
+        for (int i = 0; attributes != null && i < attributes.length; i++)
+        {
+            capability.addProperty(attributes[i].getName(), attributes[i].getValue());
+        }
+        return capability;
+    }
+
+    private static void doFragment(ResourceImpl resource, Headers headers)
+    {
+        // Check if we are a fragment
+        Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.FRAGMENT_HOST));
+        if (clauses != null && clauses.length == 1)
+        {
+            // We are a fragment, create a requirement
+            // to our host.
+            RequirementImpl r = new RequirementImpl(Capability.BUNDLE);
+            StringBuffer sb = new StringBuffer();
+            sb.append("(&(symbolicname=");
+            sb.append(clauses[0].getName());
+            sb.append(")");
+            appendVersion(sb, VersionRange.parseVersionRange(clauses[0].getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE)));
+            sb.append(")");
+            r.setFilter(sb.toString());
+            r.addText("Required Host " + clauses[0].getName());
+            r.setExtend(true);
+            r.setOptional(false);
+            r.setMultiple(false);
+            resource.addRequire(r);
+
+            // And insert a capability that we are available
+            // as a fragment. ### Do we need that with extend?
+            CapabilityImpl capability = new CapabilityImpl(Capability.FRAGMENT);
+            capability.addProperty("host", clauses[0].getName());
+            capability.addProperty("version", Property.VERSION, getVersion(clauses[0]));
+            resource.addCapability(capability);
+        }
+    }
+
+    private static void doRequires(ResourceImpl resource, Headers headers)
+    {
+        Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.REQUIRE_BUNDLE));
+        for (int i = 0; clauses != null && i < clauses.length; i++) {
+            RequirementImpl r = new RequirementImpl(Capability.BUNDLE);
+
+            VersionRange v = VersionRange.parseVersionRange(clauses[i].getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE));
+
+            StringBuffer sb = new StringBuffer();
+            sb.append("(&(symbolicname=");
+            sb.append(clauses[i].getName());
+            sb.append(")");
+            appendVersion(sb, v);
+            sb.append(")");
+            r.setFilter(sb.toString());
+
+            r.addText("Require Bundle " + clauses[i].getName() + "; " + v);
+            r.setOptional(Constants.RESOLUTION_OPTIONAL.equalsIgnoreCase(clauses[i].getDirective(Constants.RESOLUTION_DIRECTIVE)));
+            resource.addRequire(r);
+        }
+    }
+
+    private static void doBundle(ResourceImpl resource, Headers headers) {
+        CapabilityImpl capability = new CapabilityImpl(Capability.BUNDLE);
+        capability.addProperty(Resource.SYMBOLIC_NAME, getSymbolicName(headers));
+        if (headers.getHeader(Constants.BUNDLE_NAME) != null)
+        {
+            capability.addProperty(Resource.PRESENTATION_NAME, headers.getHeader(Constants.BUNDLE_NAME));
+        }
+        capability.addProperty(Resource.VERSION, Property.VERSION, getVersion(headers));
+        capability.addProperty(Resource.MANIFEST_VERSION, getManifestVersion(headers));
+        resource.addCapability(capability);
+    }
+
+    private static void doExports(ResourceImpl resource, Headers headers)
+    {
+        Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.EXPORT_PACKAGE));
+        for (int i = 0; clauses != null && i < clauses.length; i++)
+        {
+            CapabilityImpl capability = createCapability(Capability.PACKAGE, clauses[i]);
+            resource.addCapability(capability);
+        }
+    }
+
+    private static CapabilityImpl createCapability(String name, Clause clause)
+    {
+        CapabilityImpl capability = new CapabilityImpl(name);
+        capability.addProperty(name, clause.getName());
+        capability.addProperty(Resource.VERSION, Property.VERSION, getVersion(clause));
+        Attribute[] attributes = clause.getAttributes();
+        for (int i = 0; attributes != null && i < attributes.length; i++)
+        {
+            String key = attributes[i].getName();
+            if (key.equalsIgnoreCase(Constants.PACKAGE_SPECIFICATION_VERSION) || key.equalsIgnoreCase(Constants.VERSION_ATTRIBUTE))
+            {
+                continue;
+            }
+            else
+            {
+                String value = attributes[i].getValue();
+                capability.addProperty(key, value);
+            }
+        }
+        Directive[] directives = clause.getDirectives();
+        for (int i = 0; directives != null && i < directives.length; i++)
+        {
+            String key = directives[i].getName();
+            String value = directives[i].getValue();
+            capability.addProperty(key + ":", value);
+        }
+        return capability;
+    }
+
+    private static void doImports(ResourceImpl resource, Headers headers)
+    {
+        Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.IMPORT_PACKAGE));
+        for (int i = 0; clauses != null && i < clauses.length; i++)
+        {
+            RequirementImpl requirement = new RequirementImpl(Capability.PACKAGE);
+
+            createImportFilter(requirement, Capability.PACKAGE, clauses[i]);
+            requirement.addText("Import package " + clauses[i]);
+            requirement.setOptional(Constants.RESOLUTION_OPTIONAL.equalsIgnoreCase(clauses[i].getDirective(Constants.RESOLUTION_DIRECTIVE)));
+            resource.addRequire(requirement);
+        }
+    }
+
+    private static void createImportFilter(RequirementImpl requirement, String name, Clause clause)
+    {
+        StringBuffer filter = new StringBuffer();
+        filter.append("(&(");
+        filter.append(name);
+        filter.append("=");
+        filter.append(clause.getName());
+        filter.append(")");
+        appendVersion(filter, getVersionRange(clause));
+        Attribute[] attributes = clause.getAttributes();
+        Set attrs = doImportPackageAttributes(requirement, filter, attributes);
+
+        // The next code is using the subset operator
+        // to check mandatory attributes, it seems to be
+        // impossible to rewrite. It must assert that whateber
+        // is in mandatory: must be in any of the attributes.
+        // This is a fundamental shortcoming of the filter language.
+        if (attrs.size() > 0)
+        {
+            String del = "";
+            filter.append("(mandatory:<*");
+            for (Iterator i = attrs.iterator(); i.hasNext();)
+            {
+                filter.append(del);
+                filter.append(i.next());
+                del = ", ";
+            }
+            filter.append(")");
+        }
+        filter.append(")");
+        requirement.setFilter(filter.toString());
+    }
+
+    private static Set doImportPackageAttributes(RequirementImpl requirement, StringBuffer filter, Attribute[] attributes)
+    {
+        HashSet set = new HashSet();
+        for (int i = 0; attributes != null && i < attributes.length; i++)
+        {
+            String name = attributes[i].getName();
+            String value = attributes[i].getValue();
+            if (name.equalsIgnoreCase(Constants.PACKAGE_SPECIFICATION_VERSION) || name.equalsIgnoreCase(Constants.VERSION_ATTRIBUTE))
+            {
+                continue;
+            }
+            else if (name.equalsIgnoreCase(Constants.RESOLUTION_DIRECTIVE + ":"))
+            {
+                requirement.setOptional(Constants.RESOLUTION_OPTIONAL.equalsIgnoreCase(value));
+            }
+            if (name.endsWith(":"))
+            {
+                // Ignore
+            }
+            else
+            {
+                filter.append("(");
+                filter.append(name);
+                filter.append("=");
+                filter.append(value);
+                filter.append(")");
+                set.add(name);
+            }
+        }
+        return set;
+    }
+
+    private static void doExecutionEnvironment(ResourceImpl resource, Headers headers)
+    {
+        Clause[] clauses = Parser.parseHeader(headers.getHeader(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT));
+        if (clauses != null && clauses.length > 0)
+        {
+            StringBuffer sb = new StringBuffer();
+            sb.append("(|");
+            for (int i = 0; i < clauses.length; i++)
+            {
+                sb.append("(");
+                sb.append(Capability.EXECUTIONENVIRONMENT);
+                sb.append("=");
+                sb.append(clauses[i].getName());
+                sb.append(")");
+            }
+            sb.append(")");
+            RequirementImpl req = new RequirementImpl(Capability.EXECUTIONENVIRONMENT);
+            req.setFilter(sb.toString());
+            req.addText("Execution Environment " + sb.toString());
+            resource.addRequire(req);
+        }
+    }
+
+    private static String getVersion(Clause clause)
+    {
+        String v = clause.getAttribute(Constants.VERSION_ATTRIBUTE);
+        if (v == null)
+        {
+            v = clause.getAttribute(Constants.PACKAGE_SPECIFICATION_VERSION);
+        }
+        if (v == null)
+        {
+            v = clause.getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE);
+        }
+        return VersionCleaner.clean(v);
+    }
+
+    private static VersionRange getVersionRange(Clause clause)
+    {
+        String v = clause.getAttribute(Constants.VERSION_ATTRIBUTE);
+        if (v == null)
+        {
+            v = clause.getAttribute(Constants.PACKAGE_SPECIFICATION_VERSION);
+        }
+        if (v == null)
+        {
+            v = clause.getAttribute(Constants.BUNDLE_VERSION_ATTRIBUTE);
+        }
+        return VersionRange.parseVersionRange(v);
+    }
+
+    private static String getSymbolicName(Headers headers)
+    {
+        String bsn = headers.getHeader(Constants.BUNDLE_SYMBOLICNAME);
+        if (bsn == null)
+        {
+            bsn = headers.getHeader(Constants.BUNDLE_NAME);
+            if (bsn == null)
+            {
+                bsn = "Untitled-" + headers.hashCode();
+            }
+        }
+        Clause[] clauses = Parser.parseHeader(bsn);
+        return clauses[0].getName();
+    }
+
+    private static String getVersion(Headers headers)
+    {
+        String v = headers.getHeader(Constants.BUNDLE_VERSION);
+        return VersionCleaner.clean(v);
+    }
+
+    private static String getManifestVersion(Headers headers)
+    {
+        String v = headers.getHeader(Constants.BUNDLE_MANIFESTVERSION);
+        if (v == null)
+        {
+            v = "1";
+        }
+        return v;
+    }
+
+    private static void appendVersion(StringBuffer filter, VersionRange version)
+    {
+        if (version != null)
+        {
+            if ( !version.isOpenFloor() )
+            {
+                if ( !Version.emptyVersion.equals(version.getFloor()) )
+                {
+                    filter.append("(");
+                    filter.append(Constants.VERSION_ATTRIBUTE);
+                    filter.append(">=");
+                    filter.append(version.getFloor());
+                    filter.append(")");
+                }
+            }
+            else
+            {
+                filter.append("(!(");
+                filter.append(Constants.VERSION_ATTRIBUTE);
+                filter.append("<=");
+                filter.append(version.getFloor());
+                filter.append("))");
+            }
+
+            if (!VersionRange.INFINITE_VERSION.equals(version.getCeiling()))
+            {
+                if ( !version.isOpenCeiling() )
+                {
+                    filter.append("(");
+                    filter.append(Constants.VERSION_ATTRIBUTE);
+                    filter.append("<=");
+                    filter.append(version.getCeiling());
+                    filter.append(")");
+                }
+                else
+                {
+                    filter.append("(!(");
+                    filter.append(Constants.VERSION_ATTRIBUTE);
+                    filter.append(">=");
+                    filter.append(version.getCeiling());
+                    filter.append("))");
+                }
+            }
+        }
+    }
+
+    interface Headers
+    {
+        String getHeader(String name);
+    }
+
+    public Repository readRepository(String xml) throws Exception
+    {
+        try
+        {
+            return readRepository(new StringReader(xml));
+        }
+        catch (IOException e)
+        {
+            IllegalStateException ex = new IllegalStateException(e);
+            ex.initCause(e);
+            throw ex;
+        }
+    }
+
+    public Repository readRepository(Reader reader) throws Exception
+    {
+        return RepositoryParser.getParser().parseRepository(reader);
+    }
+
+    public Resource readResource(String xml) throws Exception
+    {
+        try
+        {
+            return readResource(new StringReader(xml));
+        }
+        catch (IOException e)
+        {
+            IllegalStateException ex = new IllegalStateException(e);
+            ex.initCause(e);
+            throw ex;
+        }
+    }
+
+    public Resource readResource(Reader reader) throws Exception
+    {
+        return RepositoryParser.getParser().parseResource(reader);
+    }
+
+    public Capability readCapability(String xml) throws Exception
+    {
+        try
+        {
+            return readCapability(new StringReader(xml));
+        }
+        catch (IOException e)
+        {
+            IllegalStateException ex = new IllegalStateException(e);
+            ex.initCause(e);
+            throw ex;
+        }
+    }
+
+    public Capability readCapability(Reader reader) throws Exception
+    {
+        return RepositoryParser.getParser().parseCapability(reader);
+    }
+
+    public Requirement readRequirement(String xml) throws Exception
+    {
+        try
+        {
+            return readRequirement(new StringReader(xml));
+        }
+        catch (IOException e)
+        {
+            IllegalStateException ex = new IllegalStateException(e);
+            ex.initCause(e);
+            throw ex;
+        }
+    }
+
+    public Requirement readRequirement(Reader reader) throws Exception
+    {
+        return RepositoryParser.getParser().parseRequirement(reader);
+    }
+
+    public Property readProperty(String xml) throws Exception
+    {
+        try
+        {
+            return readProperty(new StringReader(xml));
+        }
+        catch (IOException e)
+        {
+            IllegalStateException ex = new IllegalStateException(e);
+            ex.initCause(e);
+            throw ex;
+        }
+    }
+
+    public Property readProperty(Reader reader) throws Exception
+    {
+        return RepositoryParser.getParser().parseProperty(reader);
+    }
+}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FilterImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FilterImpl.java
deleted file mode 100644
index 07ed019..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/FilterImpl.java
+++ /dev/null
@@ -1,2124 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Copyright (c) OSGi Alliance (2005, 2009). All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.felix.bundlerepository.impl;
-
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.*;
-import javax.security.auth.x500.X500Principal;
-
-import org.osgi.framework.Filter;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.Version;
-
-public class FilterImpl implements Filter {
-
-    /* filter operators */
-    private static final int			EQUAL		= 1;
-    private static final int			APPROX		= 2;
-    private static final int			GREATER		= 3;
-    private static final int			LESS		= 4;
-    private static final int			PRESENT		= 5;
-    private static final int			SUBSTRING	= 6;
-    private static final int			AND			= 7;
-    private static final int			OR			= 8;
-    private static final int			NOT			= 9;
-    private static final int			SUBSET		= 10;
-    private static final int			SUPERSET	= 11;
-
-    /** filter operation */
-    private final int					op;
-    /** filter attribute or null if operation AND, OR or NOT */
-    private final String				attr;
-    /** filter operands */
-    private final Object				value;
-    /** optim in case of version */
-    private final Object                converted;
-
-    /* normalized filter string for Filter object */
-    private transient volatile String	filterString;
-
-    /**
-     * Constructs a {@link FilterImpl} object. This filter object may be
-     * used to match a {@link org.osgi.framework.ServiceReference} or a Dictionary.
-     *
-     * <p>
-     * If the filter cannot be parsed, an {@link org.osgi.framework.InvalidSyntaxException}
-     * will be thrown with a human readable message where the filter became
-     * unparsable.
-     *
-     * @param filterString the filter string.
-     * @exception InvalidSyntaxException If the filter parameter contains an
-     *            invalid filter string that cannot be parsed.
-     */
-    static FilterImpl newInstance(String filterString)
-            throws InvalidSyntaxException {
-        return newInstance(filterString, false);
-    }
-
-    static FilterImpl newInstance(String filterString, boolean ignoreCase)
-            throws InvalidSyntaxException {
-        return new Parser(filterString, ignoreCase).parse();
-    }
-
-    FilterImpl(int operation, String attr, Object value) {
-        this.op = operation;
-        this.attr = attr;
-        this.value = value;
-        Object conv = null;
-        try {
-            if (op == SUBSET || op == SUPERSET)
-            {
-                conv = getSet(value);
-            }
-            else if ("version".equalsIgnoreCase(attr))
-            {
-                if (value instanceof String) {
-                    conv = new Version((String) value);
-                } else if (value instanceof Version) {
-                    conv = (Version) value;
-                }
-            }
-        } catch (Throwable t) {
-            // Ignore any conversion issue
-        }
-        converted = conv;
-    }
-
-
-    /**
-     * Filter using a service's properties.
-     * <p>
-     * This <code>Filter</code> is executed using the keys and values of the
-     * referenced service's properties. The keys are case insensitively
-     * matched with this <code>Filter</code>.
-     *
-     * @param reference The reference to the service whose properties are
-     *        used in the match.
-     * @return <code>true</code> if the service's properties match this
-     *         <code>Filter</code>; <code>false</code> otherwise.
-     */
-    public boolean match(ServiceReference reference) {
-        return match0(new ServiceReferenceDictionary(reference));
-    }
-
-    /**
-     * Filter using a <code>Dictionary</code>. This <code>Filter</code> is
-     * executed using the specified <code>Dictionary</code>'s keys and
-     * values. The keys are case insensitively matched with this
-     * <code>Filter</code>.
-     *
-     * @param dictionary The <code>Dictionary</code> whose keys are used in
-     *        the match.
-     * @return <code>true</code> if the <code>Dictionary</code>'s keys and
-     *         values match this filter; <code>false</code> otherwise.
-     * @throws IllegalArgumentException If <code>dictionary</code> contains
-     *         case variants of the same key name.
-     */
-    public boolean match(Dictionary dictionary) {
-        return match0(new CaseInsensitiveDictionary(dictionary));
-    }
-
-    /**
-     * Filter with case sensitivity using a <code>Dictionary</code>. This
-     * <code>Filter</code> is executed using the specified
-     * <code>Dictionary</code>'s keys and values. The keys are case
-     * sensitively matched with this <code>Filter</code>.
-     *
-     * @param dictionary The <code>Dictionary</code> whose keys are used in
-     *        the match.
-     * @return <code>true</code> if the <code>Dictionary</code>'s keys and
-     *         values match this filter; <code>false</code> otherwise.
-     * @since 1.3
-     */
-    public boolean matchCase(Dictionary dictionary) {
-        return match0(dictionary);
-    }
-
-    /**
-     * Filter using a <code>Map</code>. This <code>Filter</code> is
-     * executed using the specified <code>Map</code>'s keys and
-     * values. The keys are case insensitively matched with this
-     * <code>Filter</code>.
-     *
-     * @param map The <code>Map</code> whose keys are used in
-     *        the match.
-     * @return <code>true</code> if the <code>Map</code>'s keys and
-     *         values match this filter; <code>false</code> otherwise.
-     * @throws IllegalArgumentException If <code>map</code> contains
-     *         case variants of the same key name.
-     */
-    public boolean matchCase(Map map) {
-        return match0(map);
-    }
-
-    /**
-     * Returns this <code>Filter</code>'s filter string.
-     * <p>
-     * The filter string is normalized by removing whitespace which does not
-     * affect the meaning of the filter.
-     *
-     * @return This <code>Filter</code>'s filter string.
-     */
-    public String toString() {
-        String result = filterString;
-        if (result == null) {
-            filterString = result = normalize();
-        }
-        return result;
-    }
-
-    /**
-     * Returns this <code>Filter</code>'s normalized filter string.
-     * <p>
-     * The filter string is normalized by removing whitespace which does not
-     * affect the meaning of the filter.
-     *
-     * @return This <code>Filter</code>'s filter string.
-     */
-    private String normalize() {
-        StringBuffer sb = new StringBuffer();
-        sb.append('(');
-
-        switch (op) {
-            case AND : {
-                sb.append('&');
-
-                FilterImpl[] filters = (FilterImpl[]) value;
-                for (int i = 0, size = filters.length; i < size; i++) {
-                    sb.append(filters[i].normalize());
-                }
-
-                break;
-            }
-
-            case OR : {
-                sb.append('|');
-
-                FilterImpl[] filters = (FilterImpl[]) value;
-                for (int i = 0, size = filters.length; i < size; i++) {
-                    sb.append(filters[i].normalize());
-                }
-
-                break;
-            }
-
-            case NOT : {
-                sb.append('!');
-                FilterImpl filter = (FilterImpl) value;
-                sb.append(filter.normalize());
-
-                break;
-            }
-
-            case SUBSTRING : {
-                sb.append(attr);
-                sb.append('=');
-
-                String[] substrings = (String[]) value;
-
-                for (int i = 0, size = substrings.length; i < size; i++) {
-                    String substr = substrings[i];
-
-                    if (substr == null) /* * */{
-                        sb.append('*');
-                    }
-                    else /* xxx */{
-                        sb.append(encodeValue(substr));
-                    }
-                }
-
-                break;
-            }
-            case EQUAL : {
-                sb.append(attr);
-                sb.append('=');
-                sb.append(encodeValue((String) value));
-
-                break;
-            }
-            case GREATER : {
-                sb.append(attr);
-                sb.append(">=");
-                sb.append(encodeValue((String) value));
-
-                break;
-            }
-            case LESS : {
-                sb.append(attr);
-                sb.append("<=");
-                sb.append(encodeValue((String) value));
-
-                break;
-            }
-            case APPROX : {
-                sb.append(attr);
-                sb.append("~=");
-                sb.append(encodeValue(approxString((String) value)));
-
-                break;
-            }
-            case PRESENT : {
-                sb.append(attr);
-                sb.append("=*");
-
-                break;
-            }
-            case SUBSET : {
-                sb.append(attr);
-                sb.append("<*");
-                sb.append(encodeValue(approxString((String) value)));
-
-                break;
-            }
-            case SUPERSET : {
-                sb.append(attr);
-                sb.append("*>");
-                sb.append(encodeValue(approxString((String) value)));
-
-                break;
-            }
-        }
-
-        sb.append(')');
-
-        return sb.toString();
-    }
-
-    /**
-     * Compares this <code>Filter</code> to another <code>Filter</code>.
-     *
-     * <p>
-     * This implementation returns the result of calling
-     * <code>this.toString().equals(obj.toString()</code>.
-     *
-     * @param obj The object to compare against this <code>Filter</code>.
-     * @return If the other object is a <code>Filter</code> object, then
-     *         returns the result of calling
-     *         <code>this.toString().equals(obj.toString()</code>;
-     *         <code>false</code> otherwise.
-     */
-    public boolean equals(Object obj) {
-        if (obj == this) {
-            return true;
-        }
-
-        if (!(obj instanceof FilterImpl)) {
-            return false;
-        }
-
-        return this.toString().equals(obj.toString());
-    }
-
-    /**
-     * Returns the hashCode for this <code>Filter</code>.
-     *
-     * <p>
-     * This implementation returns the result of calling
-     * <code>this.toString().hashCode()</code>.
-     *
-     * @return The hashCode of this <code>Filter</code>.
-     */
-    public int hashCode() {
-        return this.toString().hashCode();
-    }
-
-    /**
-     * Internal match routine. Dictionary parameter must support
-     * case-insensitive get.
-     *
-     * @param properties A dictionary whose keys are used in the match.
-     * @return If the Dictionary's keys match the filter, return
-     *         <code>true</code>. Otherwise, return <code>false</code>.
-     */
-    private boolean match0(Dictionary properties) {
-        switch (op) {
-            case AND : {
-                FilterImpl[] filters = (FilterImpl[]) value;
-                for (int i = 0, size = filters.length; i < size; i++) {
-                    if (!filters[i].match0(properties)) {
-                        return false;
-                    }
-                }
-
-                return true;
-            }
-
-            case OR : {
-                FilterImpl[] filters = (FilterImpl[]) value;
-                for (int i = 0, size = filters.length; i < size; i++) {
-                    if (filters[i].match0(properties)) {
-                        return true;
-                    }
-                }
-
-                return false;
-            }
-
-            case NOT : {
-                FilterImpl filter = (FilterImpl) value;
-
-                return !filter.match0(properties);
-            }
-
-            case SUBSTRING :
-            case EQUAL :
-            case GREATER :
-            case LESS :
-            case APPROX :
-            case SUBSET :
-            case SUPERSET : {
-                Object prop = (properties == null) ? null : properties
-                        .get(attr);
-
-                return compare(op, prop, value);
-            }
-
-            case PRESENT : {
-                Object prop = (properties == null) ? null : properties
-                        .get(attr);
-
-                return prop != null;
-            }
-        }
-
-        return false;
-    }
-
-    private boolean match0(Map properties) {
-        switch (op) {
-            case AND : {
-                FilterImpl[] filters = (FilterImpl[]) value;
-                for (int i = 0, size = filters.length; i < size; i++) {
-                    if (!filters[i].match0(properties)) {
-                        return false;
-                    }
-                }
-
-                return true;
-            }
-
-            case OR : {
-                FilterImpl[] filters = (FilterImpl[]) value;
-                for (int i = 0, size = filters.length; i < size; i++) {
-                    if (filters[i].match0(properties)) {
-                        return true;
-                    }
-                }
-
-                return false;
-            }
-
-            case NOT : {
-                FilterImpl filter = (FilterImpl) value;
-
-                return !filter.match0(properties);
-            }
-
-            case SUBSTRING :
-            case EQUAL :
-            case GREATER :
-            case LESS :
-            case APPROX :
-            case SUBSET :
-            case SUPERSET : {
-                Object prop = (properties == null) ? null : properties
-                        .get(attr);
-
-                return compare(op, prop, value);
-            }
-
-            case PRESENT : {
-                Object prop = (properties == null) ? null : properties
-                        .get(attr);
-
-                return prop != null;
-            }
-        }
-
-        return false;
-    }
-    /**
-     * Encode the value string such that '(', '*', ')' and '\' are escaped.
-     *
-     * @param value unencoded value string.
-     * @return encoded value string.
-     */
-    private static String encodeValue(String value) {
-        boolean encoded = false;
-        int inlen = value.length();
-        int outlen = inlen << 1; /* inlen 2 */
-
-        char[] output = new char[outlen];
-        value.getChars(0, inlen, output, inlen);
-
-        int cursor = 0;
-        for (int i = inlen; i < outlen; i++) {
-            char c = output[i];
-
-            switch (c) {
-                case '(' :
-                case '*' :
-                case ')' :
-                case '\\' : {
-                    output[cursor] = '\\';
-                    cursor++;
-                    encoded = true;
-
-                    break;
-                }
-            }
-
-            output[cursor] = c;
-            cursor++;
-        }
-
-        return encoded ? new String(output, 0, cursor) : value;
-    }
-
-    private Collection getSet(Object value)
-    {
-        Collection s;
-        if (value instanceof Set)
-        {
-            s = (Set) value;
-        }
-        else if (value instanceof Collection)
-        {
-            s = (Collection) value;
-            if (s.size() > 1) {
-                s = new HashSet(s);
-            }
-        }
-        else if (value != null)
-        {
-            String v = value.toString();
-            if (v.indexOf(',') < 0)
-            {
-                s = Collections.singleton(v);
-            }
-            else {
-                StringTokenizer st = new StringTokenizer(value.toString(), ",");
-                s = new HashSet();
-                while (st.hasMoreTokens())
-                {
-                    s.add(st.nextToken().trim());
-                }
-            }
-        }
-        else
-        {
-            s = Collections.emptySet();
-        }
-        return s;
-    }
-
-    private boolean compare(int operation, Object value1, Object value2) {
-        if (op == SUPERSET || op == SUBSET)
-        {
-            Collection s1 = getSet(value1);
-            Collection s2 = converted instanceof Collection ? (Collection) converted : getSet(value2);
-            if (op == SUPERSET)
-            {
-                return s1.containsAll(s2);
-            }
-            else
-            {
-                return s2.containsAll(s1);
-            }
-        }
-
-        if (value1 == null) {
-            return false;
-        }
-        if (value1 instanceof String) {
-            return compare_String(operation, (String) value1, value2);
-        }
-
-        Class clazz = value1.getClass();
-        if (clazz.isArray()) {
-            Class type = clazz.getComponentType();
-            if (type.isPrimitive()) {
-                return compare_PrimitiveArray(operation, type, value1,
-                        value2);
-            }
-            return compare_ObjectArray(operation, (Object[]) value1, value2);
-        }
-        if (value1 instanceof Version) {
-            if (converted != null) {
-                switch (operation) {
-                    case APPROX :
-                    case EQUAL : {
-                        return ((Version) value1).compareTo(converted) == 0;
-                    }
-                    case GREATER : {
-                        return ((Version) value1).compareTo(converted) >= 0;
-                    }
-                    case LESS : {
-                        return ((Version) value1).compareTo(converted) <= 0;
-                    }
-                }
-            } else {
-                return compare_Comparable(operation, (Version) value1, value2);
-            }
-        }
-        if (value1 instanceof Collection) {
-            return compare_Collection(operation, (Collection) value1,
-                    value2);
-        }
-        if (value1 instanceof Integer) {
-            return compare_Integer(operation,
-                    ((Integer) value1).intValue(), value2);
-        }
-        if (value1 instanceof Long) {
-            return compare_Long(operation, ((Long) value1).longValue(),
-                    value2);
-        }
-        if (value1 instanceof Byte) {
-            return compare_Byte(operation, ((Byte) value1).byteValue(),
-                    value2);
-        }
-        if (value1 instanceof Short) {
-            return compare_Short(operation, ((Short) value1).shortValue(),
-                    value2);
-        }
-        if (value1 instanceof Character) {
-            return compare_Character(operation, ((Character) value1)
-                    .charValue(), value2);
-        }
-        if (value1 instanceof Float) {
-            return compare_Float(operation, ((Float) value1).floatValue(),
-                    value2);
-        }
-        if (value1 instanceof Double) {
-            return compare_Double(operation, ((Double) value1)
-                    .doubleValue(), value2);
-        }
-        if (value1 instanceof Boolean) {
-            return compare_Boolean(operation, ((Boolean) value1)
-                    .booleanValue(), value2);
-        }
-        if (value1 instanceof Comparable) {
-            return compare_Comparable(operation, (Comparable) value1,
-                    value2);
-        }
-        return compare_Unknown(operation, value1, value2); // RFC 59
-    }
-
-    private boolean compare_Collection(int operation,
-            Collection collection, Object value2) {
-        if (op == SUBSET || op == SUPERSET)
-        {
-            StringSet set = new StringSet(value2.toString());
-            if (op == SUBSET)
-            {
-                return set.containsAll(collection);
-            }
-            else
-            {
-                return (collection).containsAll(set);
-            }
-        }
-        for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
-            if (compare(operation, iterator.next(), value2)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean compare_ObjectArray(int operation, Object[] array,
-            Object value2) {
-        for (int i = 0, size = array.length; i < size; i++) {
-            if (compare(operation, array[i], value2)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean compare_PrimitiveArray(int operation, Class type,
-            Object primarray, Object value2) {
-        if (Integer.TYPE.isAssignableFrom(type)) {
-            int[] array = (int[]) primarray;
-            for (int i = 0, size = array.length; i < size; i++) {
-                if (compare_Integer(operation, array[i], value2)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-        if (Long.TYPE.isAssignableFrom(type)) {
-            long[] array = (long[]) primarray;
-            for (int i = 0, size = array.length; i < size; i++) {
-                if (compare_Long(operation, array[i], value2)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-        if (Byte.TYPE.isAssignableFrom(type)) {
-            byte[] array = (byte[]) primarray;
-            for (int i = 0, size = array.length; i < size; i++) {
-                if (compare_Byte(operation, array[i], value2)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-        if (Short.TYPE.isAssignableFrom(type)) {
-            short[] array = (short[]) primarray;
-            for (int i = 0, size = array.length; i < size; i++) {
-                if (compare_Short(operation, array[i], value2)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-        if (Character.TYPE.isAssignableFrom(type)) {
-            char[] array = (char[]) primarray;
-            for (int i = 0, size = array.length; i < size; i++) {
-                if (compare_Character(operation, array[i], value2)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-        if (Float.TYPE.isAssignableFrom(type)) {
-            float[] array = (float[]) primarray;
-            for (int i = 0, size = array.length; i < size; i++) {
-                if (compare_Float(operation, array[i], value2)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-        if (Double.TYPE.isAssignableFrom(type)) {
-            double[] array = (double[]) primarray;
-            for (int i = 0, size = array.length; i < size; i++) {
-                if (compare_Double(operation, array[i], value2)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-        if (Boolean.TYPE.isAssignableFrom(type)) {
-            boolean[] array = (boolean[]) primarray;
-            for (int i = 0, size = array.length; i < size; i++) {
-                if (compare_Boolean(operation, array[i], value2)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-        return false;
-    }
-
-    private boolean compare_String(int operation, String string,
-            Object value2) {
-        switch (operation) {
-            case SUBSTRING : {
-                String[] substrings = (String[]) value2;
-                int pos = 0;
-                for (int i = 0, size = substrings.length; i < size; i++) {
-                    String substr = substrings[i];
-
-                    if (i + 1 < size) /* if this is not that last substr */{
-                        if (substr == null) /* * */{
-                            String substr2 = substrings[i + 1];
-
-                            if (substr2 == null) /* ** */
-                                continue; /* ignore first star */
-                            /* xxx */
-                            int index = string.indexOf(substr2, pos);
-                            if (index == -1) {
-                                return false;
-                            }
-
-                            pos = index + substr2.length();
-                            if (i + 2 < size) // if there are more
-                                // substrings, increment
-                                // over the string we just
-                                // matched; otherwise need
-                                // to do the last substr
-                                // check
-                                i++;
-                        }
-                        else /* xxx */{
-                            int len = substr.length();
-                            if (string.regionMatches(pos, substr, 0, len)) {
-                                pos += len;
-                            }
-                            else {
-                                return false;
-                            }
-                        }
-                    }
-                    else /* last substr */{
-                        if (substr == null) /* * */{
-                            return true;
-                        }
-                        /* xxx */
-                        return string.endsWith(substr);
-                    }
-                }
-
-                return true;
-            }
-            case EQUAL : {
-                return string.equals(value2);
-            }
-            case APPROX : {
-                string = approxString(string);
-                String string2 = approxString((String) value2);
-
-                return string.equalsIgnoreCase(string2);
-            }
-            case GREATER : {
-                return string.compareTo((String) value2) >= 0;
-            }
-            case LESS : {
-                return string.compareTo((String) value2) <= 0;
-            }
-        }
-        return false;
-    }
-
-    private boolean compare_Integer(int operation, int intval, Object value2) {
-        if (operation == SUBSTRING) {
-            return false;
-        }
-        int intval2;
-        try {
-            intval2 = Integer.parseInt(((String) value2).trim());
-        }
-        catch (IllegalArgumentException e) {
-            return false;
-        }
-        switch (operation) {
-            case APPROX :
-            case EQUAL : {
-                return intval == intval2;
-            }
-            case GREATER : {
-                return intval >= intval2;
-            }
-            case LESS : {
-                return intval <= intval2;
-            }
-        }
-        return false;
-    }
-
-    private boolean compare_Long(int operation, long longval, Object value2) {
-        if (operation == SUBSTRING) {
-            return false;
-        }
-        long longval2;
-        try {
-            longval2 = Long.parseLong(((String) value2).trim());
-        }
-        catch (IllegalArgumentException e) {
-            return false;
-        }
-
-        switch (operation) {
-            case APPROX :
-            case EQUAL : {
-                return longval == longval2;
-            }
-            case GREATER : {
-                return longval >= longval2;
-            }
-            case LESS : {
-                return longval <= longval2;
-            }
-        }
-        return false;
-    }
-
-    private boolean compare_Byte(int operation, byte byteval, Object value2) {
-        if (operation == SUBSTRING) {
-            return false;
-        }
-        byte byteval2;
-        try {
-            byteval2 = Byte.parseByte(((String) value2).trim());
-        }
-        catch (IllegalArgumentException e) {
-            return false;
-        }
-
-        switch (operation) {
-            case APPROX :
-            case EQUAL : {
-                return byteval == byteval2;
-            }
-            case GREATER : {
-                return byteval >= byteval2;
-            }
-            case LESS : {
-                return byteval <= byteval2;
-            }
-        }
-        return false;
-    }
-
-    private boolean compare_Short(int operation, short shortval,
-            Object value2) {
-        if (operation == SUBSTRING) {
-            return false;
-        }
-        short shortval2;
-        try {
-            shortval2 = Short.parseShort(((String) value2).trim());
-        }
-        catch (IllegalArgumentException e) {
-            return false;
-        }
-
-        switch (operation) {
-            case APPROX :
-            case EQUAL : {
-                return shortval == shortval2;
-            }
-            case GREATER : {
-                return shortval >= shortval2;
-            }
-            case LESS : {
-                return shortval <= shortval2;
-            }
-        }
-        return false;
-    }
-
-    private boolean compare_Character(int operation, char charval,
-            Object value2) {
-        if (operation == SUBSTRING) {
-            return false;
-        }
-        char charval2;
-        try {
-            charval2 = ((String) value2).charAt(0);
-        }
-        catch (IndexOutOfBoundsException e) {
-            return false;
-        }
-
-        switch (operation) {
-            case EQUAL : {
-                return charval == charval2;
-            }
-            case APPROX : {
-                return (charval == charval2)
-                        || (Character.toUpperCase(charval) == Character
-                                .toUpperCase(charval2))
-                        || (Character.toLowerCase(charval) == Character
-                                .toLowerCase(charval2));
-            }
-            case GREATER : {
-                return charval >= charval2;
-            }
-            case LESS : {
-                return charval <= charval2;
-            }
-        }
-        return false;
-    }
-
-    private boolean compare_Boolean(int operation, boolean boolval,
-            Object value2) {
-        if (operation == SUBSTRING) {
-            return false;
-        }
-        boolean boolval2 = Boolean.valueOf(((String) value2).trim())
-                .booleanValue();
-        switch (operation) {
-            case APPROX :
-            case EQUAL :
-            case GREATER :
-            case LESS : {
-                return boolval == boolval2;
-            }
-        }
-        return false;
-    }
-
-    private boolean compare_Float(int operation, float floatval,
-            Object value2) {
-        if (operation == SUBSTRING) {
-            return false;
-        }
-        float floatval2;
-        try {
-            floatval2 = Float.parseFloat(((String) value2).trim());
-        }
-        catch (IllegalArgumentException e) {
-            return false;
-        }
-
-        switch (operation) {
-            case APPROX :
-            case EQUAL : {
-                return Float.compare(floatval, floatval2) == 0;
-            }
-            case GREATER : {
-                return Float.compare(floatval, floatval2) >= 0;
-            }
-            case LESS : {
-                return Float.compare(floatval, floatval2) <= 0;
-            }
-        }
-        return false;
-    }
-
-    private boolean compare_Double(int operation, double doubleval,
-            Object value2) {
-        if (operation == SUBSTRING) {
-            return false;
-        }
-        double doubleval2;
-        try {
-            doubleval2 = Double.parseDouble(((String) value2).trim());
-        }
-        catch (IllegalArgumentException e) {
-            return false;
-        }
-
-        switch (operation) {
-            case APPROX :
-            case EQUAL : {
-                return Double.compare(doubleval, doubleval2) == 0;
-            }
-            case GREATER : {
-                return Double.compare(doubleval, doubleval2) >= 0;
-            }
-            case LESS : {
-                return Double.compare(doubleval, doubleval2) <= 0;
-            }
-        }
-        return false;
-    }
-
-    private static final Class[]	constructorType	= new Class[] {String.class};
-
-    private boolean compare_Comparable(int operation, Comparable value1,
-            Object value2) {
-        if (operation == SUBSTRING) {
-            return false;
-        }
-        Constructor constructor;
-        try {
-            constructor = value1.getClass().getConstructor(constructorType);
-        }
-        catch (NoSuchMethodException e) {
-            return false;
-        }
-        try {
-            if (!constructor.isAccessible())
-                AccessController.doPrivileged(new SetAccessibleAction(
-                        constructor));
-            value2 = constructor
-                    .newInstance(new Object[] {((String) value2).trim()});
-        }
-        catch (IllegalAccessException e) {
-            return false;
-        }
-        catch (InvocationTargetException e) {
-            return false;
-        }
-        catch (InstantiationException e) {
-            return false;
-        }
-
-        switch (operation) {
-            case APPROX :
-            case EQUAL : {
-                return value1.compareTo(value2) == 0;
-            }
-            case GREATER : {
-                return value1.compareTo(value2) >= 0;
-            }
-            case LESS : {
-                return value1.compareTo(value2) <= 0;
-            }
-        }
-        return false;
-    }
-
-    private boolean compare_Unknown(int operation, Object value1,
-            Object value2) {
-        if (operation == SUBSTRING) {
-            return false;
-        }
-        Constructor constructor;
-        try {
-            constructor = value1.getClass().getConstructor(constructorType);
-        }
-        catch (NoSuchMethodException e) {
-            return false;
-        }
-        try {
-            if (!constructor.isAccessible())
-                AccessController.doPrivileged(new SetAccessibleAction(
-                        constructor));
-            value2 = constructor
-                    .newInstance(new Object[] {((String) value2).trim()});
-        }
-        catch (IllegalAccessException e) {
-            return false;
-        }
-        catch (InvocationTargetException e) {
-            return false;
-        }
-        catch (InstantiationException e) {
-            return false;
-        }
-
-        switch (operation) {
-            case APPROX :
-            case EQUAL :
-            case GREATER :
-            case LESS : {
-                return value1.equals(value2);
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Map a string for an APPROX (~=) comparison.
-     *
-     * This implementation removes white spaces. This is the minimum
-     * implementation allowed by the OSGi spec.
-     *
-     * @param input Input string.
-     * @return String ready for APPROX comparison.
-     */
-    private static String approxString(String input) {
-        boolean changed = false;
-        char[] output = input.toCharArray();
-        int cursor = 0;
-        for (int i = 0, length = output.length; i < length; i++) {
-            char c = output[i];
-
-            if (Character.isWhitespace(c)) {
-                changed = true;
-                continue;
-            }
-
-            output[cursor] = c;
-            cursor++;
-        }
-
-        return changed ? new String(output, 0, cursor) : input;
-    }
-
-    /**
-     * Parser class for OSGi filter strings. This class parses the complete
-     * filter string and builds a tree of Filter objects rooted at the
-     * parent.
-     */
-    private static class Parser {
-        private final String	filterstring;
-        private final boolean   ignoreCase;
-        private final char[]	filterChars;
-        private int				pos;
-
-        Parser(String filterstring, boolean ignoreCase) {
-            this.filterstring = filterstring;
-            this.ignoreCase = ignoreCase;
-            filterChars = filterstring.toCharArray();
-            pos = 0;
-        }
-
-        FilterImpl parse() throws InvalidSyntaxException {
-            FilterImpl filter;
-            try {
-                filter = parse_filter();
-            }
-            catch (ArrayIndexOutOfBoundsException e) {
-                throw new InvalidSyntaxException("Filter ended abruptly",
-                        filterstring);
-            }
-
-            if (pos != filterChars.length) {
-                throw new InvalidSyntaxException(
-                        "Extraneous trailing characters: "
-                                + filterstring.substring(pos), filterstring);
-            }
-            return filter;
-        }
-
-        private FilterImpl parse_filter() throws InvalidSyntaxException {
-            FilterImpl filter;
-            skipWhiteSpace();
-
-            if (filterChars[pos] != '(') {
-                throw new InvalidSyntaxException("Missing '(': "
-                        + filterstring.substring(pos), filterstring);
-            }
-
-            pos++;
-
-            filter = parse_filtercomp();
-
-            skipWhiteSpace();
-
-            if (filterChars[pos] != ')') {
-                throw new InvalidSyntaxException("Missing ')': "
-                        + filterstring.substring(pos), filterstring);
-            }
-
-            pos++;
-
-            skipWhiteSpace();
-
-            return filter;
-        }
-
-        private FilterImpl parse_filtercomp() throws InvalidSyntaxException {
-            skipWhiteSpace();
-
-            char c = filterChars[pos];
-
-            switch (c) {
-                case '&' : {
-                    pos++;
-                    return parse_and();
-                }
-                case '|' : {
-                    pos++;
-                    return parse_or();
-                }
-                case '!' : {
-                    pos++;
-                    return parse_not();
-                }
-            }
-            return parse_item();
-        }
-
-        private FilterImpl parse_and() throws InvalidSyntaxException {
-            int lookahead = pos;
-            skipWhiteSpace();
-
-            if (filterChars[pos] != '(') {
-                pos = lookahead - 1;
-                return parse_item();
-            }
-
-            List operands = new ArrayList(10);
-
-            while (filterChars[pos] == '(') {
-                FilterImpl child = parse_filter();
-                operands.add(child);
-            }
-
-            return new FilterImpl(FilterImpl.AND, null, operands
-                    .toArray(new FilterImpl[operands.size()]));
-        }
-
-        private FilterImpl parse_or() throws InvalidSyntaxException {
-            int lookahead = pos;
-            skipWhiteSpace();
-
-            if (filterChars[pos] != '(') {
-                pos = lookahead - 1;
-                return parse_item();
-            }
-
-            List operands = new ArrayList(10);
-
-            while (filterChars[pos] == '(') {
-                FilterImpl child = parse_filter();
-                operands.add(child);
-            }
-
-            return new FilterImpl(FilterImpl.OR, null, operands
-                    .toArray(new FilterImpl[operands.size()]));
-        }
-
-        private FilterImpl parse_not() throws InvalidSyntaxException {
-            int lookahead = pos;
-            skipWhiteSpace();
-
-            if (filterChars[pos] != '(') {
-                pos = lookahead - 1;
-                return parse_item();
-            }
-
-            FilterImpl child = parse_filter();
-
-            return new FilterImpl(FilterImpl.NOT, null, child);
-        }
-
-        private FilterImpl parse_item() throws InvalidSyntaxException {
-            String attr = parse_attr();
-
-            skipWhiteSpace();
-
-            switch (filterChars[pos]) {
-                case '*': {
-                    if (filterChars[pos + 1] == '>') {
-                        pos += 2;
-                        return new FilterImpl(FilterImpl.SUPERSET, attr,
-                                parse_value());
-                    }
-                    break;
-                }
-                case '~' : {
-                    if (filterChars[pos + 1] == '=') {
-                        pos += 2;
-                        return new FilterImpl(FilterImpl.APPROX, attr,
-                                parse_value());
-                    }
-                    break;
-                }
-                case '>' : {
-                    if (filterChars[pos + 1] == '=') {
-                        pos += 2;
-                        return new FilterImpl(FilterImpl.GREATER, attr,
-                                parse_value());
-                    }
-                    break;
-                }
-                case '<' : {
-                    if (filterChars[pos + 1] == '=') {
-                        pos += 2;
-                        return new FilterImpl(FilterImpl.LESS, attr,
-                                parse_value());
-                    }
-                    if (filterChars[pos + 1] == '*') {
-                        pos += 2;
-                        return new FilterImpl(FilterImpl.SUBSET, attr,
-                                parse_value());
-                    }
-                    break;
-                }
-                case '=' : {
-                    if (filterChars[pos + 1] == '*') {
-                        int oldpos = pos;
-                        pos += 2;
-                        skipWhiteSpace();
-                        if (filterChars[pos] == ')') {
-                            return new FilterImpl(FilterImpl.PRESENT, attr,
-                                    null);
-                        }
-                        pos = oldpos;
-                    }
-
-                    pos++;
-                    Object string = parse_substring();
-
-                    if (string instanceof String) {
-                        return new FilterImpl(FilterImpl.EQUAL, attr,
-                                string);
-                    }
-                    return new FilterImpl(FilterImpl.SUBSTRING, attr,
-                            string);
-                }
-            }
-
-            throw new InvalidSyntaxException("Invalid operator: "
-                    + filterstring.substring(pos), filterstring);
-        }
-
-        private String parse_attr() throws InvalidSyntaxException {
-            skipWhiteSpace();
-
-            int begin = pos;
-            int end = pos;
-
-            char c = filterChars[pos];
-
-            while (c != '~' && c != '<' && c != '>' && c != '=' && c != '('
-                    && c != ')') {
-
-                if (c == '<' && filterChars[pos+1] == '*') {
-                    break;
-                }
-                if (c == '*' && filterChars[pos+1] == '>') {
-                    break;
-                }
-                pos++;
-
-                if (!Character.isWhitespace(c)) {
-                    end = pos;
-                }
-
-                c = filterChars[pos];
-            }
-
-            int length = end - begin;
-
-            if (length == 0) {
-                throw new InvalidSyntaxException("Missing attr: "
-                        + filterstring.substring(pos), filterstring);
-            }
-
-            String str = new String(filterChars, begin, length);
-            if (ignoreCase)
-            {
-                str = str.toLowerCase();
-            }
-            return str;
-        }
-
-        private String parse_value() throws InvalidSyntaxException {
-            StringBuffer sb = new StringBuffer(filterChars.length - pos);
-
-            parseloop: while (true) {
-                char c = filterChars[pos];
-
-                switch (c) {
-                    case ')' : {
-                        break parseloop;
-                    }
-
-                    case '(' : {
-                        throw new InvalidSyntaxException("Invalid value: "
-                                + filterstring.substring(pos), filterstring);
-                    }
-
-                    case '\\' : {
-                        pos++;
-                        c = filterChars[pos];
-                        /* fall through into default */
-                    }
-
-                    default : {
-                        sb.append(c);
-                        pos++;
-                        break;
-                    }
-                }
-            }
-
-            if (sb.length() == 0) {
-                throw new InvalidSyntaxException("Missing value: "
-                        + filterstring.substring(pos), filterstring);
-            }
-
-            return sb.toString();
-        }
-
-        private Object parse_substring() throws InvalidSyntaxException {
-            StringBuffer sb = new StringBuffer(filterChars.length - pos);
-
-            List operands = new ArrayList(10);
-
-            parseloop: while (true) {
-                char c = filterChars[pos];
-
-                switch (c) {
-                    case ')' : {
-                        if (sb.length() > 0) {
-                            operands.add(sb.toString());
-                        }
-
-                        break parseloop;
-                    }
-
-                    case '(' : {
-                        throw new InvalidSyntaxException("Invalid value: "
-                                + filterstring.substring(pos), filterstring);
-                    }
-
-                    case '*' : {
-                        if (sb.length() > 0) {
-                            operands.add(sb.toString());
-                        }
-
-                        sb.setLength(0);
-
-                        operands.add(null);
-                        pos++;
-
-                        break;
-                    }
-
-                    case '\\' : {
-                        pos++;
-                        c = filterChars[pos];
-                        /* fall through into default */
-                    }
-
-                    default : {
-                        sb.append(c);
-                        pos++;
-                        break;
-                    }
-                }
-            }
-
-            int size = operands.size();
-
-            if (size == 0) {
-                return "";
-            }
-
-            if (size == 1) {
-                Object single = operands.get(0);
-
-                if (single != null) {
-                    return single;
-                }
-            }
-
-            return operands.toArray(new String[size]);
-        }
-
-        private void skipWhiteSpace() {
-            for (int length = filterChars.length; (pos < length)
-                    && Character.isWhitespace(filterChars[pos]);) {
-                pos++;
-            }
-        }
-    }
-
-    /**
-     * This Dictionary is used for case-insensitive key lookup during filter
-     * evaluation. This Dictionary implementation only supports the get
-     * operation using a String key as no other operations are used by the
-     * Filter implementation.
-     */
-    private static class CaseInsensitiveDictionary extends Dictionary {
-        private final Dictionary	dictionary;
-        private final String[]		keys;
-
-        /**
-         * Create a case insensitive dictionary from the specified dictionary.
-         *
-         * @param dictionary
-         * @throws IllegalArgumentException If <code>dictionary</code> contains
-         *         case variants of the same key name.
-         */
-        CaseInsensitiveDictionary(Dictionary dictionary) {
-            if (dictionary == null) {
-                this.dictionary = null;
-                this.keys = new String[0];
-                return;
-            }
-            this.dictionary = dictionary;
-            List keyList = new ArrayList(dictionary.size());
-            for (Enumeration e = dictionary.keys(); e.hasMoreElements();) {
-                Object k = e.nextElement();
-                if (k instanceof String) {
-                    String key = (String) k;
-                    for (Iterator i = keyList.iterator(); i.hasNext();) {
-                        if (key.equalsIgnoreCase((String) i.next())) {
-                            throw new IllegalArgumentException();
-                        }
-                    }
-                    keyList.add(key);
-                }
-            }
-            this.keys = (String[]) keyList.toArray(new String[keyList.size()]);
-        }
-
-        public Object get(Object o) {
-            String k = (String) o;
-            for (int i = 0, length = keys.length; i < length; i++) {
-                String key = keys[i];
-                if (key.equalsIgnoreCase(k)) {
-                    return dictionary.get(key);
-                }
-            }
-            return null;
-        }
-
-        public boolean isEmpty() {
-            throw new UnsupportedOperationException();
-        }
-
-        public Enumeration keys() {
-            throw new UnsupportedOperationException();
-        }
-
-        public Enumeration elements() {
-            throw new UnsupportedOperationException();
-        }
-
-        public Object put(Object key, Object value) {
-            throw new UnsupportedOperationException();
-        }
-
-        public Object remove(Object key) {
-            throw new UnsupportedOperationException();
-        }
-
-        public int size() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    private static class SetAccessibleAction implements PrivilegedAction {
-        private final AccessibleObject accessible;
-
-        SetAccessibleAction(AccessibleObject accessible) {
-            this.accessible = accessible;
-        }
-
-        public Object run() {
-            accessible.setAccessible(true);
-            return null;
-        }
-    }
-
-    /**
-     * This class contains a method to match a distinguished name (DN) chain
-     * against and DN chain pattern.
-     * <p>
-     * The format of DNs are given in RFC 2253. We represent a signature chain
-     * for an X.509 certificate as a semicolon separated list of DNs. This is
-     * what we refer to as the DN chain. Each DN is made up of relative
-     * distinguished names (RDN) which in turn are made up of key value pairs.
-     * For example:
-     *
-     * <pre>
-     *   cn=ben+ou=research,o=ACME,c=us;ou=Super CA,c=CA
-     * </pre>
-     *
-     * is made up of two DNs: "<code>cn=ben+ou=research,o=ACME,c=us</code>
-     * " and " <code>ou=Super CA,c=CA</code>
-     * ". The first DN is made of of three RDNs: "
-     * <code>cn=ben+ou=research</code>" and "<code>o=ACME</code>" and "
-     * <code>c=us</code>". The first RDN has two name value pairs: "
-     * <code>cn=ben</code>" and "<code>ou=research</code>".
-     * <p>
-     * A chain pattern makes use of wildcards ('*' or '-') to match against DNs,
-     * and wildcards ('*') to match againts DN prefixes, and value. If a DN in a
-     * match pattern chain is made up of a wildcard ("*"), that wildcard will
-     * match zero or one DNs in the chain. If a DN in a match pattern chain is
-     * made up of a wildcard ("-"), that wildcard will match zero or more DNs in
-     * the chain. If the first RDN of a DN is the wildcard ("*"), that DN will
-     * match any other DN with the same suffix (the DN with the wildcard RDN
-     * removed). If a value of a name/value pair is a wildcard ("*"), the value
-     * will match any value for that name.
-     */
-    private static class DNChainMatching {
-        private static final String	MINUS_WILDCARD	= "-";
-        private static final String	STAR_WILDCARD	= "*";
-
-        /**
-         * Check the name/value pairs of the rdn against the pattern.
-         *
-         * @param rdn List of name value pairs for a given RDN.
-         * @param rdnPattern List of name value pattern pairs.
-         * @return true if the list of name value pairs match the pattern.
-         */
-        private static boolean rdnmatch(List rdn, List rdnPattern) {
-            if (rdn.size() != rdnPattern.size()) {
-                return false;
-            }
-            for (int i = 0; i < rdn.size(); i++) {
-                String rdnNameValue = (String) rdn.get(i);
-                String patNameValue = (String) rdnPattern.get(i);
-                int rdnNameEnd = rdnNameValue.indexOf('=');
-                int patNameEnd = patNameValue.indexOf('=');
-                if (rdnNameEnd != patNameEnd
-                        || !rdnNameValue.regionMatches(0, patNameValue, 0,
-                                rdnNameEnd)) {
-                    return false;
-                }
-                String patValue = patNameValue.substring(patNameEnd);
-                String rdnValue = rdnNameValue.substring(rdnNameEnd);
-                if (!rdnValue.equals(patValue) && !patValue.equals("=*")
-                        && !patValue.equals("=#16012a")) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        private static boolean dnmatch(List dn, List dnPattern) {
-            int dnStart = 0;
-            int patStart = 0;
-            int patLen = dnPattern.size();
-            if (patLen == 0) {
-                return false;
-            }
-            if (dnPattern.get(0).equals(STAR_WILDCARD)) {
-                patStart = 1;
-                patLen--;
-            }
-            if (dn.size() < patLen) {
-                return false;
-            }
-            else {
-                if (dn.size() > patLen) {
-                    if (!dnPattern.get(0).equals(STAR_WILDCARD)) {
-                        // If the number of rdns do not match we must have a
-                        // prefix map
-                        return false;
-                    }
-                    // The rdnPattern and rdn must have the same number of
-                    // elements
-                    dnStart = dn.size() - patLen;
-                }
-            }
-            for (int i = 0; i < patLen; i++) {
-                if (!rdnmatch((List) dn.get(i + dnStart), (List) dnPattern
-                        .get(i + patStart))) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        /**
-         * Parses a distinguished name chain pattern and returns a List where
-         * each element represents a distinguished name (DN) in the chain of
-         * DNs. Each element will be either a String, if the element represents
-         * a wildcard ("*" or "-"), or a List representing an RDN. Each element
-         * in the RDN List will be a String, if the element represents a
-         * wildcard ("*"), or a List of Strings, each String representing a
-         * name/value pair in the RDN.
-         *
-         * @param dnChain
-         * @return a list of DNs.
-         * @throws IllegalArgumentException
-         */
-        private static List parseDNchainPattern(String dnChain) {
-            if (dnChain == null) {
-                throw new IllegalArgumentException(
-                        "The DN chain must not be null.");
-            }
-            List parsed = new ArrayList();
-            int startIndex = 0;
-            startIndex = skipSpaces(dnChain, startIndex);
-            while (startIndex < dnChain.length()) {
-                int endIndex = startIndex;
-                boolean inQuote = false;
-                out: while (endIndex < dnChain.length()) {
-                    char c = dnChain.charAt(endIndex);
-                    switch (c) {
-                        case '"' :
-                            inQuote = !inQuote;
-                            break;
-                        case '\\' :
-                            endIndex++; // skip the escaped char
-                            break;
-                        case ';' :
-                            if (!inQuote)
-                                break out;
-                    }
-                    endIndex++;
-                }
-                if (endIndex > dnChain.length()) {
-                    throw new IllegalArgumentException("unterminated escape");
-                }
-                parsed.add(dnChain.substring(startIndex, endIndex));
-                startIndex = endIndex + 1;
-                startIndex = skipSpaces(dnChain, startIndex);
-            }
-            return parseDNchain(parsed);
-        }
-
-        private static List parseDNchain(List chain) {
-            if (chain == null) {
-                throw new IllegalArgumentException("DN chain must not be null.");
-            }
-            chain = new ArrayList(chain);
-            // Now we parse is a list of strings, lets make List of rdn out
-            // of them
-            for (int i = 0; i < chain.size(); i++) {
-                String dn = (String) chain.get(i);
-                if (dn.equals(STAR_WILDCARD) || dn.equals(MINUS_WILDCARD)) {
-                    continue;
-                }
-                List rdns = new ArrayList();
-                if (dn.charAt(0) == '*') {
-                    if (dn.charAt(1) != ',') {
-                        throw new IllegalArgumentException(
-                                "invalid wildcard prefix");
-                    }
-                    rdns.add(STAR_WILDCARD);
-                    dn = new X500Principal(dn.substring(2))
-                            .getName(X500Principal.CANONICAL);
-                }
-                else {
-                    dn = new X500Principal(dn).getName(X500Principal.CANONICAL);
-                }
-                // Now dn is a nice CANONICAL DN
-                parseDN(dn, rdns);
-                chain.set(i, rdns);
-            }
-            if (chain.size() == 0) {
-                throw new IllegalArgumentException("empty DN chain");
-            }
-            return chain;
-        }
-
-        /**
-         * Increment startIndex until the end of dnChain is hit or until it is
-         * the index of a non-space character.
-         */
-        private static int skipSpaces(String dnChain, int startIndex) {
-            while (startIndex < dnChain.length()
-                    && dnChain.charAt(startIndex) == ' ') {
-                startIndex++;
-            }
-            return startIndex;
-        }
-
-        /**
-         * Takes a distinguished name in canonical form and fills in the
-         * rdnArray with the extracted RDNs.
-         *
-         * @param dn the distinguished name in canonical form.
-         * @param rdn the list to fill in with RDNs extracted from the dn
-         * @throws IllegalArgumentException if a formatting error is found.
-         */
-        private static void parseDN(String dn, List rdn) {
-            int startIndex = 0;
-            char c = '\0';
-            List nameValues = new ArrayList();
-            while (startIndex < dn.length()) {
-                int endIndex;
-                for (endIndex = startIndex; endIndex < dn.length(); endIndex++) {
-                    c = dn.charAt(endIndex);
-                    if (c == ',' || c == '+') {
-                        break;
-                    }
-                    if (c == '\\') {
-                        endIndex++; // skip the escaped char
-                    }
-                }
-                if (endIndex > dn.length()) {
-                    throw new IllegalArgumentException("unterminated escape "
-                            + dn);
-                }
-                nameValues.add(dn.substring(startIndex, endIndex));
-                if (c != '+') {
-                    rdn.add(nameValues);
-                    if (endIndex != dn.length()) {
-                        nameValues = new ArrayList();
-                    }
-                    else {
-                        nameValues = null;
-                    }
-                }
-                startIndex = endIndex + 1;
-            }
-            if (nameValues != null) {
-                throw new IllegalArgumentException("improperly terminated DN "
-                        + dn);
-            }
-        }
-
-        /**
-         * This method will return an 'index' which points to a non-wildcard DN
-         * or the end-of-list.
-         */
-        private static int skipWildCards(List dnChainPattern,
-                int dnChainPatternIndex) {
-            int i;
-            for (i = dnChainPatternIndex; i < dnChainPattern.size(); i++) {
-                Object dnPattern = dnChainPattern.get(i);
-                if (dnPattern instanceof String) {
-                    if (!dnPattern.equals(STAR_WILDCARD)
-                            && !dnPattern.equals(MINUS_WILDCARD)) {
-                        throw new IllegalArgumentException(
-                                "expected wildcard in DN pattern");
-                    }
-                    // otherwise continue skipping over wild cards
-                }
-                else {
-                    if (dnPattern instanceof List) {
-                        // if its a list then we have our 'non-wildcard' DN
-                        break;
-                    }
-                    else {
-                        // unknown member of the DNChainPattern
-                        throw new IllegalArgumentException(
-                                "expected String or List in DN Pattern");
-                    }
-                }
-            }
-            // i either points to end-of-list, or to the first
-            // non-wildcard pattern after dnChainPatternIndex
-            return i;
-        }
-
-        /**
-         * recursively attempt to match the DNChain, and the DNChainPattern
-         * where DNChain is of the format: "DN;DN;DN;" and DNChainPattern is of
-         * the format: "DNPattern;*;DNPattern" (or combinations of this)
-         */
-        private static boolean dnChainMatch(List dnChain, int dnChainIndex,
-                List dnChainPattern, int dnChainPatternIndex)
-                throws IllegalArgumentException {
-            if (dnChainIndex >= dnChain.size()) {
-                return false;
-            }
-            if (dnChainPatternIndex >= dnChainPattern.size()) {
-                return false;
-            }
-            // check to see what the pattern starts with
-            Object dnPattern = dnChainPattern.get(dnChainPatternIndex);
-            if (dnPattern instanceof String) {
-                if (!dnPattern.equals(STAR_WILDCARD)
-                        && !dnPattern.equals(MINUS_WILDCARD)) {
-                    throw new IllegalArgumentException(
-                            "expected wildcard in DN pattern");
-                }
-                // here we are processing a wild card as the first DN
-                // skip all wildcard DN's
-                if (dnPattern.equals(MINUS_WILDCARD)) {
-                    dnChainPatternIndex = skipWildCards(dnChainPattern,
-                            dnChainPatternIndex);
-                }
-                else {
-                    dnChainPatternIndex++; // only skip the '*' wildcard
-                }
-                if (dnChainPatternIndex >= dnChainPattern.size()) {
-                    // return true iff the wild card is '-' or if we are at the
-                    // end of the chain
-                    return dnPattern.equals(MINUS_WILDCARD) ? true : dnChain
-                            .size() - 1 == dnChainIndex;
-                }
-                //
-                // we will now recursively call to see if the rest of the
-                // DNChainPattern matches increasingly smaller portions of the
-                // rest of the DNChain
-                //
-                if (dnPattern.equals(STAR_WILDCARD)) {
-                    // '*' option: only wildcard on 0 or 1
-                    return dnChainMatch(dnChain, dnChainIndex, dnChainPattern,
-                            dnChainPatternIndex)
-                            || dnChainMatch(dnChain, dnChainIndex + 1,
-                                    dnChainPattern, dnChainPatternIndex);
-                }
-                for (int i = dnChainIndex; i < dnChain.size(); i++) {
-                    // '-' option: wildcard 0 or more
-                    if (dnChainMatch(dnChain, i, dnChainPattern,
-                            dnChainPatternIndex)) {
-                        return true;
-                    }
-                }
-                // if we are here, then we didn't find a match.. fall through to
-                // failure
-            }
-            else {
-                if (dnPattern instanceof List) {
-                    // here we have to do a deeper check for each DN in the
-                    // pattern until we hit a wild card
-                    do {
-                        if (!dnmatch((List) dnChain.get(dnChainIndex),
-                                (List) dnPattern)) {
-                            return false;
-                        }
-                        // go to the next set of DN's in both chains
-                        dnChainIndex++;
-                        dnChainPatternIndex++;
-                        // if we finished the pattern then it all matched
-                        if ((dnChainIndex >= dnChain.size())
-                                && (dnChainPatternIndex >= dnChainPattern
-                                        .size())) {
-                            return true;
-                        }
-                        // if the DN Chain is finished, but the pattern isn't
-                        // finished then if the rest of the pattern is not
-                        // wildcard then we are done
-                        if (dnChainIndex >= dnChain.size()) {
-                            dnChainPatternIndex = skipWildCards(dnChainPattern,
-                                    dnChainPatternIndex);
-                            // return TRUE iff the pattern index moved past the
-                            // list-size (implying that the rest of the pattern
-                            // is all wildcards)
-                            return dnChainPatternIndex >= dnChainPattern.size();
-                        }
-                        // if the pattern finished, but the chain continues then
-                        // we have a mis-match
-                        if (dnChainPatternIndex >= dnChainPattern.size()) {
-                            return false;
-                        }
-                        // get the next DN Pattern
-                        dnPattern = dnChainPattern.get(dnChainPatternIndex);
-                        if (dnPattern instanceof String) {
-                            if (!dnPattern.equals(STAR_WILDCARD)
-                                    && !dnPattern.equals(MINUS_WILDCARD)) {
-                                throw new IllegalArgumentException(
-                                        "expected wildcard in DN pattern");
-                            }
-                            // if the next DN is a 'wildcard', then we will
-                            // recurse
-                            return dnChainMatch(dnChain, dnChainIndex,
-                                    dnChainPattern, dnChainPatternIndex);
-                        }
-                        else {
-                            if (!(dnPattern instanceof List)) {
-                                throw new IllegalArgumentException(
-                                        "expected String or List in DN Pattern");
-                            }
-                        }
-                        // if we are here, then we will just continue to the
-                        // match the next set of DN's from the DNChain, and the
-                        // DNChainPattern since both are lists
-                    } while (true);
-                    // should never reach here?
-                }
-                else {
-                    throw new IllegalArgumentException(
-                            "expected String or List in DN Pattern");
-                }
-            }
-            // if we get here, the the default return is 'mis-match'
-            return false;
-        }
-
-        /**
-         * Matches a distinguished name chain against a pattern of a
-         * distinguished name chain.
-         *
-         * @param dnChain
-         * @param pattern the pattern of distinguished name (DN) chains to match
-         *        against the dnChain. Wildcards ("*" or "-") can be used in
-         *        three cases:
-         *        <ol>
-         *        <li>As a DN. In this case, the DN will consist of just the "*"
-         *        or "-". When "*" is used it will match zero or one DNs. When
-         *        "-" is used it will match zero or more DNs. For example,
-         *        "cn=me,c=US;*;cn=you" will match
-         *        "cn=me,c=US";cn=you" and "cn=me,c=US;cn=her;cn=you". The
-         *        pattern "cn=me,c=US;-;cn=you" will match "cn=me,c=US";cn=you"
-         *        and "cn=me,c=US;cn=her;cn=him;cn=you".
-         *        <li>As a DN prefix. In this case, the DN must start with "*,".
-         *        The wild card will match zero or more RDNs at the start of a
-         *        DN. For example, "*,cn=me,c=US;cn=you" will match
-         *        "cn=me,c=US";cn=you" and
-         *        "ou=my org unit,o=my org,cn=me,c=US;cn=you"</li>
-         *        <li>As a value. In this case the value of a name value pair in
-         *        an RDN will be a "*". The wildcard will match any value for
-         *        the given name. For example, "cn=*,c=US;cn=you" will match
-         *        "cn=me,c=US";cn=you" and "cn=her,c=US;cn=you", but it will not
-         *        match "ou=my org unit,c=US;cn=you". If the wildcard does not
-         *        occur by itself in the value, it will not be used as a
-         *        wildcard. In other words, "cn=m*,c=US;cn=you" represents the
-         *        common name of "m*" not any common name starting with "m".</li>
-         *        </ol>
-         * @return true if dnChain matches the pattern.
-         * @throws IllegalArgumentException
-         */
-        static boolean match(String pattern, List/* <String> */dnChain) {
-            List parsedDNChain;
-            List parsedDNPattern;
-            try {
-                parsedDNChain = parseDNchain(dnChain);
-            }
-            catch (RuntimeException e) {
-                IllegalArgumentException iae = new IllegalArgumentException(
-                        "Invalid DN chain: " + toString(dnChain));
-                iae.initCause(e);
-                throw iae;
-            }
-            try {
-                parsedDNPattern = parseDNchainPattern(pattern);
-            }
-            catch (RuntimeException e) {
-                IllegalArgumentException iae = new IllegalArgumentException(
-                        "Invalid match pattern: " + pattern);
-                iae.initCause(e);
-                throw iae;
-            }
-            return dnChainMatch(parsedDNChain, 0, parsedDNPattern, 0);
-        }
-
-        private static String toString(List dnChain) {
-            if (dnChain == null) {
-                return null;
-            }
-            StringBuffer sb = new StringBuffer();
-            for (Iterator iChain = dnChain.iterator(); iChain.hasNext();) {
-                sb.append(iChain.next());
-                if (iChain.hasNext()) {
-                    sb.append("; ");
-                }
-            }
-            return sb.toString();
-        }
-    }
-
-    /**
-     * This Dictionary is used for key lookup from a ServiceReference during
-     * filter evaluation. This Dictionary implementation only supports the get
-     * operation using a String key as no other operations are used by the
-     * Filter implementation.
-     */
-    private static class ServiceReferenceDictionary extends Dictionary {
-        private final ServiceReference	reference;
-
-        ServiceReferenceDictionary(ServiceReference reference) {
-            this.reference = reference;
-        }
-
-        public Object get(Object key) {
-            if (reference == null) {
-                return null;
-            }
-            return reference.getProperty((String) key);
-        }
-
-        public boolean isEmpty() {
-            throw new UnsupportedOperationException();
-        }
-
-        public Enumeration keys() {
-            throw new UnsupportedOperationException();
-        }
-
-        public Enumeration elements() {
-            throw new UnsupportedOperationException();
-        }
-
-        public Object put(Object key, Object value) {
-            throw new UnsupportedOperationException();
-        }
-
-        public Object remove(Object key) {
-            throw new UnsupportedOperationException();
-        }
-
-        public int size() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/IteratorToEnumeration.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/IteratorToEnumeration.java
deleted file mode 100644
index 120c115..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/IteratorToEnumeration.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.bundlerepository.impl;
-
-import java.util.Enumeration;
-import java.util.Iterator;
-
-public class IteratorToEnumeration implements Enumeration
-{
-    private Iterator m_iter = null;
-
-    public IteratorToEnumeration(Iterator iter)
-    {
-        m_iter = iter;
-    }
-
-    public boolean hasMoreElements()
-    {
-        if (m_iter == null)
-            return false;
-        return m_iter.hasNext();
-    }
-
-    public Object nextElement()
-    {
-        if (m_iter == null)
-            return null;
-        return m_iter.next();
-    }
-}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalRepositoryImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalRepositoryImpl.java
index deb984d..71b0fb9 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalRepositoryImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalRepositoryImpl.java
@@ -21,6 +21,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.felix.utils.log.Logger;
 import org.osgi.framework.AllServiceListener;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalResourceImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalResourceImpl.java
index 17c3a84..eadfa70 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalResourceImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalResourceImpl.java
@@ -18,15 +18,11 @@
  */
 package org.apache.felix.bundlerepository.impl;
 
-import java.util.ArrayList;
 import java.util.Dictionary;
-import java.util.Enumeration;
 import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Set;
-import java.util.StringTokenizer;
 
+import org.apache.felix.bundlerepository.Capability;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
@@ -38,13 +34,6 @@
 
     LocalResourceImpl(Bundle bundle) throws InvalidSyntaxException
     {
-        this(null, bundle);
-    }
-
-    LocalResourceImpl(ResourceImpl resource, Bundle bundle)
-        throws InvalidSyntaxException
-    {
-        super(resource);
         m_bundle = bundle;
         initialize();
     }
@@ -61,22 +50,16 @@
 
     private void initialize() throws InvalidSyntaxException
     {
-        Dictionary dict = m_bundle.getHeaders();
+        final Dictionary dict = m_bundle.getHeaders();
 
-        // Convert bundle manifest header attributes to resource properties.
-        convertAttributesToProperties(dict);
-
-        // Convert properties to bundle capability
-        convertAttributesToBundleCapability();
-
-        // Convert import package declarations into requirements.
-        convertImportPackageToRequirement(dict);
-
-        // Convert import service declarations into requirements.
-        convertImportServiceToRequirement(dict);
-
-        // Convert export package declarations into capabilities.
-        convertExportPackageToCapability(dict);
+        DataModelHelperImpl.populate(new DataModelHelperImpl.Headers()
+        {
+            public String getHeader(String name)
+            {
+                return (String) dict.get(name);
+            }
+            public void close() { }
+        }, this);
 
         // Convert export service declarations and services into capabilities.
         convertExportServiceToCapability(dict, m_bundle);
@@ -85,23 +68,12 @@
         if (m_bundle.getBundleId() == 0)
         {
             // set the execution environment(s) as Capability ee of the
-            // system bundle to resolve bundles with specifc requirements
+            // system bundle to resolve bundles with specific requirements
             String ee = m_bundle.getBundleContext().getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT);
             if (ee != null)
             {
-                StringTokenizer tokener = new StringTokenizer(ee, ",");
-                List eeList = new ArrayList();
-                while (tokener.hasMoreTokens())
-                {
-                    String eeName = tokener.nextToken().trim();
-                    if (eeName.length() > 0)
-                    {
-                        eeList.add(eeName);
-                    }
-                }
-                CapabilityImpl cap = new CapabilityImpl();
-                cap.setName("ee");
-                cap.addP("ee", eeList);
+                CapabilityImpl cap = new CapabilityImpl(Capability.EXECUTIONENVIRONMENT);
+                cap.addProperty(Capability.EXECUTIONENVIRONMENT, ee);
                 addCapability(cap);
             }
 
@@ -151,181 +123,10 @@
         }
     }
 
-    private void convertAttributesToProperties(Dictionary dict)
-    {
-        for (Enumeration keys = dict.keys(); keys.hasMoreElements(); )
-        {
-            String key = (String) keys.nextElement();
-            if (key.equalsIgnoreCase(Constants.BUNDLE_SYMBOLICNAME))
-            {
-                String sn = (String) dict.get(key);
-                sn = sn.trim();
-                int index = sn.indexOf(";singleton:=true");
-                if (index != -1) {
-                    sn = sn.substring(0, index);
-                }
-                put(SYMBOLIC_NAME, sn);
-            }
-            else if (key.equalsIgnoreCase(Constants.BUNDLE_NAME))
-            {
-                put(PRESENTATION_NAME, (String) dict.get(key));
-            }
-            else if (key.equalsIgnoreCase(Constants.BUNDLE_VERSION))
-            {
-                put(VERSION, (String) dict.get(key));
-            }
-            else if (key.equalsIgnoreCase("Bundle-Source"))
-            {
-                put(SOURCE_URI, (String) dict.get(key));
-            }
-            else if (key.equalsIgnoreCase(Constants.BUNDLE_DESCRIPTION))
-            {
-                put(DESCRIPTION, (String) dict.get(key));
-            }
-            else if (key.equalsIgnoreCase(Constants.BUNDLE_DOCURL))
-            {
-                put(DOCUMENTATION_URI, (String) dict.get(key));
-            }
-            else if (key.equalsIgnoreCase(Constants.BUNDLE_COPYRIGHT))
-            {
-                put(COPYRIGHT, (String) dict.get(key));
-            }
-            else if (key.equalsIgnoreCase("Bundle-License"))
-            {
-                put(LICENSE_URI, (String) dict.get(key));
-            }
-        }
-    }
-
-    private void convertAttributesToBundleCapability()
-    {
-        CapabilityImpl cap = new CapabilityImpl();
-        cap.setName("bundle");
-        if (getPresentationName() != null) {
-            cap.addP(PRESENTATION_NAME, getPresentationName());
-        }
-        cap.addP(SYMBOLIC_NAME, getSymbolicName());
-        cap.addP(VERSION, getVersion());
-        addCapability(cap);
-    }
-
-    private void convertImportPackageToRequirement(Dictionary dict)
-        throws InvalidSyntaxException
-    {
-        String target = (String) dict.get(Constants.IMPORT_PACKAGE);
-        if (target != null)
-        {
-            R4Package[] pkgs = R4Package.parseImportOrExportHeader(target);
-            R4Import[] imports = new R4Import[pkgs.length];
-            for (int i = 0; i < pkgs.length; i++)
-            {
-                imports[i] = new R4Import(pkgs[i]);
-            }
-
-            for (int impIdx = 0; impIdx < imports.length; impIdx++)
-            {
-                RequirementImpl req = new RequirementImpl();
-                req.setMultiple("false");
-                req.setOptional(Boolean.toString(imports[impIdx].isOptional()));
-                req.setName("package");
-                req.addText("Import package " + imports[impIdx].toString());
-
-                String low = imports[impIdx].isLowInclusive()
-                            ? "(version>=" + imports[impIdx].getVersion() + ")"
-                            : "(!(version<=" + imports[impIdx].getVersion() + "))";
-
-                if (imports[impIdx].getVersionHigh() != null)
-                {
-                    String high = imports[impIdx].isHighInclusive()
-                        ? "(version<=" + imports[impIdx].getVersionHigh() + ")"
-                        : "(!(version>=" + imports[impIdx].getVersionHigh() + "))";
-                    req.setFilter("(&(package="
-                        + imports[impIdx].getName() + ")"
-                        + low + high + ")");
-                }
-                else
-                {
-                    req.setFilter(
-                        "(&(package="
-                        + imports[impIdx].getName() + ")"
-                        + low + ")");
-                }
-
-                addRequire(req);
-            }
-        }
-    }
-
-    private void convertImportServiceToRequirement(Dictionary dict)
-        throws InvalidSyntaxException
-    {
-        String target = (String) dict.get(Constants.IMPORT_SERVICE);
-        if (target != null)
-        {
-            R4Package[] pkgs = R4Package.parseImportOrExportHeader(target);
-            for (int pkgIdx = 0; (pkgs != null) && (pkgIdx < pkgs.length); pkgIdx++)
-            {
-                RequirementImpl req = new RequirementImpl();
-                req.setMultiple("false");
-                req.setName("service");
-                req.addText("Import service " + pkgs[pkgIdx].toString());
-                req.setFilter("(service="
-                    + pkgs[pkgIdx].getName() + ")");
-                addRequire(req);
-            }
-        }
-    }
-
-    private void convertExportPackageToCapability(Dictionary dict)
-    {
-        String target = (String) dict.get(Constants.EXPORT_PACKAGE);
-        if (target != null)
-        {
-            R4Package[] pkgs = R4Package.parseImportOrExportHeader(target);
-            for (int pkgIdx = 0; (pkgs != null) && (pkgIdx < pkgs.length); pkgIdx++)
-            {
-                CapabilityImpl cap = new CapabilityImpl();
-                cap.setName("package");
-                cap.addP(new PropertyImpl("package", null, pkgs[pkgIdx].getName()));
-                cap.addP(new PropertyImpl("version", "version", pkgs[pkgIdx].getVersion().toString()));
-                for (int i = 0; i < pkgs[pkgIdx].getAttributes().length; i++)
-                {
-                    R4Attribute attribute = pkgs[pkgIdx].getAttributes()[i];
-                    String key = attribute.getName();
-                    if (!key.equalsIgnoreCase("specification-version")
-                        && !key.equalsIgnoreCase("version"))
-                    {
-                        Object value = attribute.getValue();
-                        cap.addP(key, value);
-                    }
-                }
-                for (int i = 0; i < pkgs[pkgIdx].getDirectives().length; i++)
-                {
-                    R4Directive directive = pkgs[pkgIdx].getDirectives()[i];
-                    String key = directive.getName() + ":";
-                    Object value = directive.getValue();
-                    cap.addP(key, value);
-                }
-                addCapability(cap);
-            }
-        }
-    }
-
     private void convertExportServiceToCapability(Dictionary dict, Bundle bundle)
     {
         Set services = new HashSet();
 
-        // collect Export-Service
-        String target = (String) dict.get(Constants.EXPORT_SERVICE);
-        if (target != null)
-        {
-            R4Package[] pkgs = R4Package.parseImportOrExportHeader(target);
-            for (int pkgIdx = 0; (pkgs != null) && (pkgIdx < pkgs.length); pkgIdx++)
-            {
-                services.add(pkgs[pkgIdx].getName());
-            }
-        }
-
         // add actual registered services
         ServiceReference[] refs = bundle.getRegisteredServices();
         for (int i = 0; refs != null && i < refs.length; i++)
@@ -333,18 +134,14 @@
             String[] cls = (String[]) refs[i].getProperty(Constants.OBJECTCLASS);
             for (int j = 0; cls != null && j < cls.length; j++)
             {
-                services.add(cls[j]);
+                CapabilityImpl cap = new CapabilityImpl();
+                cap.setName(Capability.SERVICE);
+                cap.addProperty(new PropertyImpl(Capability.SERVICE, null, cls[j]));
+                // TODO: add service properties
+                addCapability(cap);
             }
         }
-
-        // register capabilities for combined set
-        for (Iterator si = services.iterator(); si.hasNext();)
-        {
-            CapabilityImpl cap = new CapabilityImpl();
-            cap.setName("service");
-            cap.addP(new PropertyImpl("service", null, (String) si.next()));
-            addCapability(cap);
-        }
+        // TODO: check duplicates with service-export properties
     }
 
     public String toString()
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/Logger.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/Logger.java
deleted file mode 100644
index b32bb16..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/Logger.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.bundlerepository.impl;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.log.LogService;
-
-import java.io.PrintStream;
-
-/**
- * Internal logger to be used in order to avoid a manatory dependency on OSGi LogService.
- * It first tries to log to a log service implementation if there is one available and then fallback to System out/err
- * in case there is no log service available.
- * <p/>
- * As OBR implementation (this bundle) logs only errors the strategy is to lookup the log service on each log call.
- * This can prove as not efficient on a more intensive ussage as for example debug logging, case when a
- * ServiceListener or ServiceTracker can be used.
- */
-public class Logger
-{
-    public static final int LOG_ERROR = 1;
-    public static final int LOG_WARNING = 2;
-    public static final int LOG_INFO = 3;
-    public static final int LOG_DEBUG = 4;
-
-    /**
-     * Bundle context.
-     */
-    private final BundleContext m_context;
-    private boolean m_isLogClassPresent;
-
-    /**
-     * Constructor.
-     *
-     * @param context bundle context
-     */
-    Logger(BundleContext context)
-    {
-        m_context = context;
-        try
-        {
-            org.osgi.service.log.LogService.class.getName();
-            m_isLogClassPresent = true;
-        }
-        catch (NoClassDefFoundError ex)
-        {
-            m_isLogClassPresent = false;
-        }
-    }
-
-    /**
-     * @see LogService#log(int, String)
-     */
-    public void log(int level, String message)
-    {
-        log(level, message, null);
-    }
-
-    /**
-     * @see LogService#log(int, String, Throwable)
-     */
-    public void log(int level, String message, Throwable exception)
-    {
-        if (!m_isLogClassPresent || !_log(level, message, exception))
-        {
-            final PrintStream stream = getStream(level);
-            stream.println(message);
-            if (exception != null)
-            {
-                exception.printStackTrace(stream);
-            }
-
-        }
-    }
-
-    /**
-     * Lookup the OSGi LogService and if available use it.
-     */
-    private boolean _log(int level, String message, Throwable exception)
-    {
-        try
-        {
-            ServiceReference reference = null;
-            reference = m_context.getServiceReference(LogService.class.getName());
-            if (reference != null)
-            {
-                final LogService logService = (LogService) m_context.getService(reference);
-                if (logService != null)
-                {
-                    logService.log(level, message, exception);
-                    m_context.ungetService(reference);
-                    return true;
-                }
-            }
-        }
-        catch (NoClassDefFoundError e)
-        {
-            //ignore
-        }
-        return false;
-    }
-
-    /**
-     * Return the standard print streams to use depending on log level.
-     *
-     * @param level log level
-     * @return print stream corresponding to log level
-     */
-    private PrintStream getStream(int level)
-    {
-        switch (level)
-        {
-            case LOG_ERROR:
-                System.err.print("ERROR: ");
-                return System.err;
-            case LOG_WARNING:
-                System.err.print("WARNING: ");
-                return System.err;
-            case LOG_INFO:
-                System.out.print("INFO: ");
-                return System.out;
-            case LOG_DEBUG:
-                System.out.print("DEBUG: ");
-                return System.out;
-            default:
-                System.out.print("UNKNOWN: ");
-                return System.out;
-        }
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/MapToDictionary.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/MapToDictionary.java
deleted file mode 100644
index 81f7d6a..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/MapToDictionary.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.bundlerepository.impl;
-
-import java.util.*;
-
-
-/**
- * This is a simple class that implements a <tt>Dictionary</tt>
- * from a <tt>Map</tt>. The resulting dictionary is immutatable.
-**/
-public class MapToDictionary extends Dictionary
-{
-    /**
-     * Map source.
-    **/
-    private Map m_map = null;
-
-    public MapToDictionary(Map map)
-    {
-        m_map = map;
-    }
-
-    public void setSourceMap(Map map)
-    {
-        m_map = map;
-    }
-
-    public Enumeration elements()
-    {
-        if (m_map == null)
-        {
-            return null;
-        }
-        return new IteratorToEnumeration(m_map.values().iterator());
-    }
-
-    public Object get(Object key)
-    {
-        if (m_map == null)
-        {
-            return null;
-        }
-        return m_map.get(key);
-    }
-
-    public boolean isEmpty()
-    {
-        if (m_map == null)
-        {
-            return true;
-        }
-        return m_map.isEmpty();
-    }
-
-    public Enumeration keys()
-    {
-        if (m_map == null)
-        {
-            return null;
-        }
-        return new IteratorToEnumeration(m_map.keySet().iterator());
-    }
-
-    public Object put(Object key, Object value)
-    {
-        throw new UnsupportedOperationException();
-    }
-
-    public Object remove(Object key)
-    {
-        throw new UnsupportedOperationException();
-    }
-
-    public int size()
-    {
-        if (m_map == null)
-        {
-            return 0;
-        }
-        return m_map.size();
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrCommandImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrCommandImpl.java
index 47c2e29..e784c97 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrCommandImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrCommandImpl.java
@@ -28,6 +28,7 @@
 import org.apache.felix.bundlerepository.Requirement;
 import org.apache.felix.bundlerepository.Resolver;
 import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.bundlerepository.impl.FileUtil;
 import org.apache.felix.shell.Command;
 import org.osgi.framework.*;
 
@@ -577,7 +578,7 @@
             out.println("Capabilities:");
             for (int i = 0; i < caps.length; i++)
             {
-                out.println("   " + caps[i].getProperties());
+                out.println("   " + caps[i].getPropertiesAsMap());
             }
         }
     }
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrURLStreamHandlerService.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrURLStreamHandlerService.java
index a99d4eb..1e38bd1 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrURLStreamHandlerService.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrURLStreamHandlerService.java
@@ -26,6 +26,7 @@
 import java.util.SortedMap;
 import java.util.TreeMap;
 
+import org.apache.felix.utils.log.Logger;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/PropertyImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/PropertyImpl.java
index 78acf43..3c4a25b 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/PropertyImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/PropertyImpl.java
@@ -18,83 +18,93 @@
  */
 package org.apache.felix.bundlerepository.impl;
 
-import java.net.MalformedURLException;
+import java.net.URI;
 import java.net.URL;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.StringTokenizer;
 
-import org.osgi.framework.Version;
-import org.osgi.service.obr.Resource;
+import org.apache.felix.bundlerepository.Property;
+import org.apache.felix.utils.version.VersionTable;
 
-public class PropertyImpl
+public class PropertyImpl implements Property
 {
-    private String m_name = null;
-    private String m_type = null;
-    private Object m_value = null;
-
-    public PropertyImpl()
-    {
-    }
+    private final String name;
+    private final String type;
+    private final String value;
 
     public PropertyImpl(String name, String type, String value)
     {
-        setN(name);
-        setT(type);
-        setV(value);
+        this.name = name;
+        this.type = type;
+        this.value = value;
     }
 
-    public void setN(String name)
+    public String getName()
     {
-        m_name = name;
+        return name;
     }
 
-    public String getN()
+    public String getType()
     {
-        return m_name;
+        return type;
     }
 
-    public void setT(String type)
+    public String getValue()
     {
-        m_type = type;
-
-        // If there is an existing value, then convert
-        // it based on the new type.
-        if (m_value != null)
-        {
-            m_value = convertType(m_value.toString());
-        }
-    }
-
-    public String getT()
-    {
-        return m_type;
-    }
-
-    public void setV(String value)
-    {
-        m_value = convertType(value);
-    }
-
-    public Object getV()
-    {
-        return m_value;
-    }
-
-    private Object convertType(String value)
-    {
-        if ((m_type != null) && m_type.equalsIgnoreCase(Resource.VERSION))
-        {
-            return new Version(value);
-        }
-        else if ((m_type != null) && (m_type.equalsIgnoreCase(Resource.URL)))
-        {
-            try
-            {
-                return new URL(value);
-            }
-            catch (MalformedURLException ex)
-            {
-                ex.printStackTrace();
-            }
-        }
         return value;
     }
+
+    public Object getConvertedValue()
+    {
+        return convert(value, type);
+    }
+
+    private static Object convert(String value, String type)
+    {
+        try
+        {
+            if (value != null && type != null)
+            {
+                if (VERSION.equalsIgnoreCase(type))
+                {
+                    return VersionTable.getVersion(value);
+                }
+                else if (URI.equalsIgnoreCase(type))
+                {
+                    return new URI(value);
+                }
+                else if (URL.equalsIgnoreCase(type))
+                {
+                    return new URL(value);
+                }
+                else if (LONG.equalsIgnoreCase(type))
+                {
+                    return new Long(value);
+                }
+                else if (DOUBLE.equalsIgnoreCase(type))
+                {
+                    return new Double(value);
+                }
+                else if (SET.equalsIgnoreCase(type))
+                {
+                    StringTokenizer st = new StringTokenizer(value, ",");
+                    Set s = new HashSet();
+                    while (st.hasMoreTokens())
+                    {
+                        s.add(st.nextToken().trim());
+                    }
+                    return s;
+                }
+            }
+            return value;
+        }
+        catch (Exception e)
+        {
+            IllegalArgumentException ex = new IllegalArgumentException();
+            ex.initCause(e);
+            throw ex;
+        }
+    }
 }
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/PullParser.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/PullParser.java
index 1a1b47b..5938c84 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/PullParser.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/PullParser.java
@@ -18,34 +18,99 @@
  */
 package org.apache.felix.bundlerepository.impl;
 
-import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
+import java.io.Reader;
 
 import org.kxml2.io.KXmlParser;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 /**
- * Repository XML parser based on StaX
+ * Repository XML xml based on StaX
  */
-public class PullParser implements RepositoryImpl.RepositoryParser
+public class PullParser extends RepositoryParser
 {
 
     public PullParser()
     {
     }
 
-    public void parse(RepositoryImpl repository, InputStream is) throws Exception
+    public RepositoryImpl parseRepository(InputStream is) throws Exception
     {
-        KXmlParser reader = new KXmlParser();
-        reader.setInput(new BufferedReader(new InputStreamReader(is)));
+        XmlPullParser reader = new KXmlParser();
+        reader.setInput(is, null);
         int event = reader.nextTag();
         if (event != XmlPullParser.START_TAG || !REPOSITORY.equals(reader.getName()))
         {
             throw new Exception("Expected element 'repository' at the root of the document");
         }
+        return parse(reader);
+    }
+
+    public RepositoryImpl parseRepository(Reader r) throws Exception
+    {
+        XmlPullParser reader = new KXmlParser();
+        reader.setInput(r);
+        int event = reader.nextTag();
+        if (event != XmlPullParser.START_TAG || !REPOSITORY.equals(reader.getName()))
+        {
+            throw new Exception("Expected element 'repository' at the root of the document");
+        }
+        return parse(reader);
+    }
+
+    public ResourceImpl parseResource(Reader r) throws Exception
+    {
+        XmlPullParser reader = new KXmlParser();
+        reader.setInput(r);
+        int event = reader.nextTag();
+        if (event != XmlPullParser.START_TAG || !RESOURCE.equals(reader.getName()))
+        {
+            throw new Exception("Expected element 'resource'");
+        }
+        return parseResource(reader);
+    }
+
+    public CapabilityImpl parseCapability(Reader r) throws Exception
+    {
+        XmlPullParser reader = new KXmlParser();
+        reader.setInput(r);
+        int event = reader.nextTag();
+        if (event != XmlPullParser.START_TAG || !CAPABILITY.equals(reader.getName()))
+        {
+            throw new Exception("Expected element 'capability'");
+        }
+        return parseCapability(reader);
+    }
+
+    public PropertyImpl parseProperty(Reader r) throws Exception
+    {
+        XmlPullParser reader = new KXmlParser();
+        reader.setInput(r);
+        int event = reader.nextTag();
+        if (event != XmlPullParser.START_TAG || !P.equals(reader.getName()))
+        {
+            throw new Exception("Expected element 'p'");
+        }
+        return parseProperty(reader);
+    }
+
+    public RequirementImpl parseRequirement(Reader r) throws Exception
+    {
+        XmlPullParser reader = new KXmlParser();
+        reader.setInput(r);
+        int event = reader.nextTag();
+        if (event != XmlPullParser.START_TAG || !REQUIRE.equals(reader.getName()))
+        {
+            throw new Exception("Expected element 'require'");
+        }
+        return parseRequire(reader);
+    }
+
+    public RepositoryImpl parse(XmlPullParser reader) throws Exception
+    {
+        RepositoryImpl repository = new RepositoryImpl();
         for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
         {
             String name = reader.getAttributeName(i);
@@ -56,9 +121,10 @@
             }
             else if (LASTMODIFIED.equals(name))
             {
-                repository.setLastmodified(value);
+                repository.setLastModified(value);
             }
         }
+        int event;
         while ((event = reader.nextTag()) == XmlPullParser.START_TAG)
         {
             String element = reader.getName();
@@ -79,9 +145,10 @@
         }
         // Sanity check
         sanityCheckEndElement(reader, event, REPOSITORY);
+        return repository;
     }
 
-    private void sanityCheckEndElement(KXmlParser reader, int event, String element)
+    private void sanityCheckEndElement(XmlPullParser reader, int event, String element)
     {
         if (event != XmlPullParser.END_TAG || !element.equals(reader.getName()))
         {
@@ -89,7 +156,7 @@
         }
     }
 
-    private Referral parseReferral(KXmlParser reader) throws Exception
+    public Referral parseReferral(XmlPullParser reader) throws Exception
     {
         Referral referral = new Referral();
         for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
@@ -109,7 +176,7 @@
         return referral;
     }
 
-    private ResourceImpl parseResource(KXmlParser reader) throws Exception
+    public ResourceImpl parseResource(XmlPullParser reader) throws Exception
     {
         ResourceImpl resource = new ResourceImpl();
         try
@@ -124,7 +191,7 @@
                 String element = reader.getName();
                 if (CATEGORY.equals(element))
                 {
-                    CategoryImpl category = parseCategory(reader);
+                    String category = parseCategory(reader);
                     resource.addCategory(category);
                 }
                 else if (CAPABILITY.equals(element))
@@ -175,21 +242,21 @@
         }
     }
 
-    private CategoryImpl parseCategory(KXmlParser reader) throws IOException, XmlPullParserException
+    public String parseCategory(XmlPullParser reader) throws IOException, XmlPullParserException
     {
-        CategoryImpl category = new CategoryImpl();
+        String id = null;
         for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
         {
             if (ID.equals(reader.getAttributeName(i)))
             {
-                category.setId(reader.getAttributeValue(i));
+                id = reader.getAttributeValue(i);
             }
         }
         sanityCheckEndElement(reader, reader.nextTag(), CATEGORY);
-        return category;
+        return id;
     }
 
-    private CapabilityImpl parseCapability(KXmlParser reader) throws Exception
+    public CapabilityImpl parseCapability(XmlPullParser reader) throws Exception
     {
         CapabilityImpl capability = new CapabilityImpl();
         for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
@@ -208,7 +275,7 @@
             if (P.equals(element))
             {
                 PropertyImpl prop = parseProperty(reader);
-                capability.addP(prop);
+                capability.addProperty(prop);
             }
             else
             {
@@ -220,7 +287,7 @@
         return capability;
     }
 
-    private PropertyImpl parseProperty(KXmlParser reader) throws Exception
+    public PropertyImpl parseProperty(XmlPullParser reader) throws Exception
     {
         String n = null, t = null, v = null;
         for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
@@ -246,7 +313,7 @@
         return prop;
     }
 
-    private RequirementImpl parseRequire(KXmlParser reader) throws Exception
+    public RequirementImpl parseRequire(XmlPullParser reader) throws Exception
     {
         RequirementImpl requirement = new RequirementImpl();
         for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
@@ -263,15 +330,15 @@
             }
             else if (EXTEND.equals(name))
             {
-                requirement.setExtend(value);
+                requirement.setExtend(Boolean.parseBoolean(value));
             }
             else if (MULTIPLE.equals(name))
             {
-                requirement.setMultiple(value);
+                requirement.setMultiple(Boolean.parseBoolean(value));
             }
             else if (OPTIONAL.equals(name))
             {
-                requirement.setOptional(value);
+                requirement.setOptional(Boolean.parseBoolean(value));
             }
         }
         int event;
@@ -300,17 +367,16 @@
         return requirement;
     }
 
-    private void ignoreTag(KXmlParser reader) throws IOException, XmlPullParserException {
+    public void ignoreTag(XmlPullParser reader) throws IOException, XmlPullParserException {
         int level = 1;
-        int event = 0;
         while (level > 0)
         {
-            event = reader.next();
-            if (event == XmlPullParser.START_TAG)
+            int eventType = reader.next();
+            if (eventType == XmlPullParser.START_TAG)
             {
                 level++;
             }
-            else if (event == XmlPullParser.END_TAG)
+            else if (eventType == XmlPullParser.END_TAG)
             {
                 level--;
             }
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Attribute.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Attribute.java
deleted file mode 100644
index 9aff3c4..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Attribute.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.bundlerepository.impl;
-
-public class R4Attribute
-{
-    private String m_name = "";
-    private String m_value = "";
-    private boolean m_isMandatory = false;
-    
-    public R4Attribute(String name, String value, boolean isMandatory)
-    {
-        m_name = name;
-        m_value = value;
-        m_isMandatory = isMandatory;
-    }
-
-    public String getName()
-    {
-        return m_name;
-    }
-
-    public String getValue()
-    {
-        return m_value;
-    }
-
-    public boolean isMandatory()
-    {
-        return m_isMandatory;
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Directive.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Directive.java
deleted file mode 100644
index 3d2618b..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Directive.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.bundlerepository.impl;
-
-public class R4Directive
-{
-    private String m_name = "";
-    private String m_value = "";
-    
-    public R4Directive(String name, String value)
-    {
-        m_name = name;
-        m_value = value;
-    }
-
-    public String getName()
-    {
-        return m_name;
-    }
-
-    public String getValue()
-    {
-        return m_value;
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Export.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Export.java
deleted file mode 100644
index 2517ca7..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Export.java
+++ /dev/null
@@ -1,282 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.bundlerepository.impl;
-
-import java.util.*;
-
-import org.osgi.framework.Constants;
-
-public class R4Export extends R4Package
-{
-    private String[] m_uses = null;
-    private String[][] m_includeFilter = null;
-    private String[][] m_excludeFilter = null;
-
-    public R4Export(R4Package pkg)
-    {
-        this(pkg.getName(), pkg.getDirectives(), pkg.getAttributes());
-    }
-
-    public R4Export(String name, R4Directive[] directives, R4Attribute[] attrs)
-    {
-        super(name, directives, attrs);
-
-        // Find all export directives: uses, mandatory, include, and exclude.
-        String mandatory = "", uses = "";
-        for (int i = 0; i < m_directives.length; i++)
-        {
-            if (m_directives[i].getName().equals(Constants.USES_DIRECTIVE))
-            {
-                uses = m_directives[i].getValue();
-            }
-            else if (m_directives[i].getName().equals(Constants.MANDATORY_DIRECTIVE))
-            {
-                mandatory = m_directives[i].getValue();
-            }
-            else if (m_directives[i].getName().equals(Constants.INCLUDE_DIRECTIVE))
-            {
-                String[] ss = Util.parseDelimitedString(m_directives[i].getValue(), ",");
-                m_includeFilter = new String[ss.length][];
-                for (int filterIdx = 0; filterIdx < ss.length; filterIdx++)
-                {
-                    m_includeFilter[filterIdx] = parseSubstring(ss[filterIdx]);
-                }
-            }
-            else if (m_directives[i].getName().equals(Constants.EXCLUDE_DIRECTIVE))
-            {
-                String[] ss = Util.parseDelimitedString(m_directives[i].getValue(), ",");
-                m_excludeFilter = new String[ss.length][];
-                for (int filterIdx = 0; filterIdx < ss.length; filterIdx++)
-                {
-                    m_excludeFilter[filterIdx] = parseSubstring(ss[filterIdx]);
-                }
-            }
-        }
-
-        // Parse these uses directive.
-        StringTokenizer tok = new StringTokenizer(uses, ",");
-        m_uses = new String[tok.countTokens()];
-        for (int i = 0; i < m_uses.length; i++)
-        {
-            m_uses[i] = tok.nextToken().trim();
-        }
-
-        // Parse mandatory directive and mark specified
-        // attributes as mandatory.
-        tok = new StringTokenizer(mandatory, ",");
-        while (tok.hasMoreTokens())
-        {
-            // Get attribute name.
-            String attrName = tok.nextToken().trim();
-            // Find attribute and mark it as mandatory.
-            boolean found = false;
-            for (int i = 0; (!found) && (i < m_attrs.length); i++)
-            {
-                if (m_attrs[i].getName().equals(attrName))
-                {
-                    m_attrs[i] = new R4Attribute(
-                        m_attrs[i].getName(),
-                        m_attrs[i].getValue(), true);
-                    found = true;
-                }
-            }
-            // If a specified mandatory attribute was not found,
-            // then error.
-            if (!found)
-            {
-                throw new IllegalArgumentException(
-                    "Mandatory attribute '" + attrName + "' does not exist.");
-            }
-        }
-    }
-
-    public String[] getUses()
-    {
-        return m_uses;
-    }
-
-    public boolean isIncluded(String name)
-    {
-        if ((m_includeFilter == null) && (m_excludeFilter == null))
-        {
-            return true;
-        }
-
-        // Get the class name portion of the target class.
-        String className = Util.getClassName(name);
-
-        // If there are no include filters then all classes are included
-        // by default, otherwise try to find one match.
-        boolean included = (m_includeFilter == null);
-        for (int i = 0;
-            (!included) && (m_includeFilter != null) && (i < m_includeFilter.length);
-            i++)
-        {
-            included = checkSubstring(m_includeFilter[i], className);
-        }
-
-        // If there are no exclude filters then no classes are excluded
-        // by default, otherwise try to find one match.
-        boolean excluded = false;
-        for (int i = 0;
-            (!excluded) && (m_excludeFilter != null) && (i < m_excludeFilter.length);
-            i++)
-        {
-            excluded = checkSubstring(m_excludeFilter[i], className);
-        }
-        return included && !excluded;
-    }
-
-    //
-    // The following substring-related code was lifted and modified
-    // from the LDAP parser code.
-    //
-
-    private static String[] parseSubstring(String target)
-    {
-        List pieces = new ArrayList();
-        StringBuffer ss = new StringBuffer();
-        // int kind = SIMPLE; // assume until proven otherwise
-        boolean wasStar = false; // indicates last piece was a star
-        boolean leftstar = false; // track if the initial piece is a star
-        boolean rightstar = false; // track if the final piece is a star
-
-        int idx = 0;
-
-        // We assume (sub)strings can contain leading and trailing blanks
-loop:   for (;;)
-        {
-            if (idx >= target.length())
-            {
-                if (wasStar)
-                {
-                    // insert last piece as "" to handle trailing star
-                    rightstar = true;
-                }
-                else
-                {
-                    pieces.add(ss.toString());
-                    // accumulate the last piece
-                    // note that in the case of
-                    // (cn=); this might be
-                    // the string "" (!=null)
-                }
-                ss.setLength(0);
-                break loop;
-            }
-
-            char c = target.charAt(idx++);
-            if (c == '*')
-            {
-                if (wasStar)
-                {
-                    // encountered two successive stars;
-                    // I assume this is illegal
-                    throw new IllegalArgumentException("Invalid filter string: " + target);
-                }
-                if (ss.length() > 0)
-                {
-                    pieces.add(ss.toString()); // accumulate the pieces
-                    // between '*' occurrences
-                }
-                ss.setLength(0);
-                // if this is a leading star, then track it
-                if (pieces.size() == 0)
-                {
-                    leftstar = true;
-                }
-                ss.setLength(0);
-                wasStar = true;
-            }
-            else
-            {
-                wasStar = false;
-                ss.append(c);
-            }
-        }
-        if (leftstar || rightstar || pieces.size() > 1)
-        {
-            // insert leading and/or trailing "" to anchor ends
-            if (rightstar)
-            {
-                pieces.add("");
-            }
-            if (leftstar)
-            {
-                pieces.add(0, "");
-            }
-        }
-        return (String[]) pieces.toArray(new String[pieces.size()]);
-    }
-
-    private static boolean checkSubstring(String[] pieces, String s)
-    {
-        // Walk the pieces to match the string
-        // There are implicit stars between each piece,
-        // and the first and last pieces might be "" to anchor the match.
-        // assert (pieces.length > 1)
-        // minimal case is <string>*<string>
-
-        boolean result = false;
-        int len = pieces.length;
-
-loop:   for (int i = 0; i < len; i++)
-        {
-            String piece = (String) pieces[i];
-            int index = 0;
-            if (i == len - 1)
-            {
-                // this is the last piece
-                if (s.endsWith(piece))
-                {
-                    result = true;
-                }
-                else
-                {
-                    result = false;
-                }
-                break loop;
-            }
-            // initial non-star; assert index == 0
-            else if (i == 0)
-            {
-                if (!s.startsWith(piece))
-                {
-                    result = false;
-                    break loop;
-                }
-            }
-            // assert i > 0 && i < len-1
-            else
-            {
-                // Sure wish stringbuffer supported e.g. indexOf
-                index = s.indexOf(piece, index);
-                if (index < 0)
-                {
-                    result = false;
-                    break loop;
-                }
-            }
-            // start beyond the matching piece
-            index += piece.length();
-        }
-
-        return result;
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Import.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Import.java
deleted file mode 100644
index d7c30ba..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Import.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.bundlerepository.impl;
-
-import org.osgi.framework.Constants;
-import org.osgi.framework.Version;
-
-public class R4Import extends R4Package
-{
-    private VersionRange m_versionRange = null;
-    private boolean m_isOptional = false;
-
-    public R4Import(R4Package pkg)
-    {
-        this(pkg.getName(), pkg.getDirectives(), pkg.getAttributes());
-    }
-
-    public R4Import(String name, R4Directive[] directives, R4Attribute[] attrs)
-    {
-        super(name, directives, attrs);
-
-        // Find all import directives: resolution.
-        for (int i = 0; i < m_directives.length; i++)
-        {
-            if (m_directives[i].getName().equals(Constants.RESOLUTION_DIRECTIVE))
-            {
-                m_isOptional = m_directives[i].getValue().equals(Constants.RESOLUTION_OPTIONAL);
-            }
-        }
-
-        // Find and parse version attribute, if present.
-        String rangeStr = "0.0.0";
-        for (int i = 0; i < m_attrs.length; i++)
-        {
-            if (m_attrs[i].getName().equals(Constants.VERSION_ATTRIBUTE) ||
-                m_attrs[i].getName().equals(Constants.PACKAGE_SPECIFICATION_VERSION))
-            {
-                // Normalize version attribute name.
-                m_attrs[i] = new R4Attribute(
-                    Constants.VERSION_ATTRIBUTE, m_attrs[i].getValue(),
-                    m_attrs[i].isMandatory());
-                rangeStr = m_attrs[i].getValue();
-                break;
-            }
-        }
-        
-        m_versionRange = VersionRange.parse(rangeStr);
-        m_version = m_versionRange.getLow();
-    }
-
-    public Version getVersionHigh()
-    {
-        return m_versionRange.getHigh();
-    }
-
-    public boolean isLowInclusive()
-    {
-        return m_versionRange.isLowInclusive();
-    }
-
-    public boolean isHighInclusive()
-    {
-        return m_versionRange.isHighInclusive();
-    }
-
-    public boolean isOptional()
-    {
-        return m_isOptional;
-    }
-
-    public boolean isSatisfied(R4Export export)
-    {
-        // For packages to be compatible, they must have the
-        // same name.
-        if (!getName().equals(export.getName()))
-        {
-            return false;
-        }
-        
-        return m_versionRange.isInRange(export.getVersion())
-            && doAttributesMatch(export);
-    }
-
-    private boolean doAttributesMatch(R4Export export)
-    {
-        // Cycle through all attributes of this import package
-        // and make sure its values match the attribute values
-        // of the specified export package.
-        for (int impAttrIdx = 0; impAttrIdx < getAttributes().length; impAttrIdx++)
-        {
-            // Get current attribute from this import package.
-            R4Attribute impAttr = getAttributes()[impAttrIdx];
-
-            // Ignore version attribute, since it is a special case that
-            // has already been compared using isVersionInRange() before
-            // the call to this method was made.
-            if (impAttr.getName().equals(Constants.VERSION_ATTRIBUTE))
-            {
-                continue;
-            }
-
-            // Check if the export package has the same attribute.
-            boolean found = false;
-            for (int expAttrIdx = 0;
-                (!found) && (expAttrIdx < export.getAttributes().length);
-                expAttrIdx++)
-            {
-                // Get current attribute for the export package.
-                R4Attribute expAttr = export.getAttributes()[expAttrIdx];
-                // Check if the attribute names are equal.
-                if (impAttr.getName().equals(expAttr.getName()))
-                {
-                    // If the values are not equal, then return false immediately.
-                    // We should not compare version values here, since they are
-                    // a special case and have already been compared by a call to
-                    // isVersionInRange() before getting here; however, it is
-                    // possible for version to be mandatory, so make sure it is
-                    // present below.
-                    if (!impAttr.getValue().equals(expAttr.getValue()))
-                    {
-                        return false;
-                    }
-                    found = true;
-                }
-            }
-            // If the attribute was not found, then return false.
-            if (!found)
-            {
-                return false;
-            }
-        }
-
-        // Now, cycle through all attributes of the export package and verify that
-        // all mandatory attributes are present in this import package.
-        for (int expAttrIdx = 0; expAttrIdx < export.getAttributes().length; expAttrIdx++)
-        {
-            // Get current attribute for this package.
-            R4Attribute expAttr = export.getAttributes()[expAttrIdx];
-            
-            // If the export attribute is mandatory, then make sure
-            // this import package has the attribute.
-            if (expAttr.isMandatory())
-            {
-                boolean found = false;
-                for (int impAttrIdx = 0;
-                    (!found) && (impAttrIdx < getAttributes().length);
-                    impAttrIdx++)
-                {
-                    // Get current attribute from specified package.
-                    R4Attribute impAttr = getAttributes()[impAttrIdx];
-        
-                    // Check if the attribute names are equal
-                    // and set found flag.
-                    if (expAttr.getName().equals(impAttr.getName()))
-                    {
-                        found = true;
-                    }
-                }
-                // If not found, then return false.
-                if (!found)
-                {
-                    return false;
-                }
-            }
-        }
-
-        return true;
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Package.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Package.java
deleted file mode 100644
index 700c1c7..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/R4Package.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.bundlerepository.impl;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.osgi.framework.Constants;
-import org.osgi.framework.Version;
-
-public class R4Package
-{
-    private String m_name = "";
-    protected R4Directive[] m_directives = null;
-    protected R4Attribute[] m_attrs = null;
-    protected Version m_version = null;
-
-    public R4Package(String name, R4Directive[] directives, R4Attribute[] attrs)
-    {
-        m_name = name;
-        m_directives = (directives == null) ? new R4Directive[0] : directives;
-        m_attrs = (attrs == null) ? new R4Attribute[0] : attrs;
-
-        // Find and parse version attribute, if present.
-        String rangeStr = "0.0.0";
-        for (int i = 0; i < m_attrs.length; i++)
-        {
-            if (m_attrs[i].getName().equals(Constants.VERSION_ATTRIBUTE) ||
-                m_attrs[i].getName().equals(Constants.PACKAGE_SPECIFICATION_VERSION))
-            {
-                // Normalize version attribute name.
-                m_attrs[i] = new R4Attribute(
-                    Constants.VERSION_ATTRIBUTE, m_attrs[i].getValue(),
-                    m_attrs[i].isMandatory());
-                rangeStr = m_attrs[i].getValue();
-                break;
-            }
-        }
-        
-        VersionRange range = VersionRange.parse(rangeStr);
-        // For now, ignore if we have a version range.
-        m_version = range.getLow();
-    }
-
-    public String getName()
-    {
-        return m_name;
-    }
-
-    public R4Directive[] getDirectives()
-    {
-        return m_directives;
-    }
-
-    public R4Attribute[] getAttributes()
-    {
-        return m_attrs;
-    }
-
-    public Version getVersion()
-    {
-        return m_version;
-    }
-
-    public String toString()
-    {
-        String msg = getName();
-        for (int i = 0; (m_directives != null) && (i < m_directives.length); i++)
-        {
-            msg = msg + " [" + m_directives[i].getName() + ":="+ m_directives[i].getValue() + "]";
-        }
-        for (int i = 0; (m_attrs != null) && (i < m_attrs.length); i++)
-        {
-            msg = msg + " [" + m_attrs[i].getName() + "="+ m_attrs[i].getValue() + "]";
-        }
-        return msg;
-    }
-
-    // Like this: pkg1; pkg2; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2,
-    //            pkg1; pkg2; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
-    public static R4Package[] parseImportOrExportHeader(String s)
-    {
-        R4Package[] pkgs = null;
-        if (s != null)
-        {
-            if (s.length() == 0)
-            {
-                throw new IllegalArgumentException(
-                    "The import and export headers cannot be an empty string.");
-            }
-            String[] ss = Util.parseDelimitedString(s, ",");
-            pkgs = parsePackageStrings(ss);
-        }
-        return (pkgs == null) ? new R4Package[0] : pkgs;
-    }
-
-    // Like this: pkg1; pkg2; dir1:=dirval1; dir2:=dirval2; attr1=attrval1; attr2=attrval2
-    public static R4Package[] parsePackageStrings(String[] ss)
-        throws IllegalArgumentException
-    {
-        if (ss == null)
-        {
-            return null;
-        }
-
-        List completeList = new ArrayList();
-        for (int ssIdx = 0; ssIdx < ss.length; ssIdx++)
-        {
-            // Break string into semi-colon delimited pieces.
-            String[] pieces = Util.parseDelimitedString(ss[ssIdx], ";");
-
-            // Count the number of different packages; packages
-            // will not have an '=' in their string. This assumes
-            // that packages come first, before directives and
-            // attributes.
-            int pkgCount = 0;
-            for (int pieceIdx = 0; pieceIdx < pieces.length; pieceIdx++)
-            {
-                if (pieces[pieceIdx].indexOf('=') >= 0)
-                {
-                    break;
-                }
-                pkgCount++;
-            }
-
-            // Error if no packages were specified.
-            if (pkgCount == 0)
-            {
-                throw new IllegalArgumentException(
-                    "No packages specified on import: " + ss[ssIdx]);
-            }
-
-            // Parse the directives/attributes.
-            R4Directive[] dirs = new R4Directive[pieces.length - pkgCount];
-            R4Attribute[] attrs = new R4Attribute[pieces.length - pkgCount];
-            int dirCount = 0, attrCount = 0;
-            int idx = -1;
-            String sep = null;
-            for (int pieceIdx = pkgCount; pieceIdx < pieces.length; pieceIdx++)
-            {
-                // Check if it is a directive.
-                if ((idx = pieces[pieceIdx].indexOf(":=")) >= 0)
-                {
-                    sep = ":=";
-                }
-                // Check if it is an attribute.
-                else if ((idx = pieces[pieceIdx].indexOf("=")) >= 0)
-                {
-                    sep = "=";
-                }
-                // It is an error.
-                else
-                {
-                    throw new IllegalArgumentException(
-                        "Not a directive/attribute: " + ss[ssIdx]);
-                }
-
-                String key = pieces[pieceIdx].substring(0, idx).trim();
-                String value = pieces[pieceIdx].substring(idx + sep.length()).trim();
-
-                // Remove quotes, if value is quoted.
-                if (value.startsWith("\"") && value.endsWith("\""))
-                {
-                    value = value.substring(1, value.length() - 1);
-                }
-
-                // Save the directive/attribute in the appropriate array.
-                if (sep.equals(":="))
-                {
-                    dirs[dirCount++] = new R4Directive(key, value);
-                }
-                else
-                {
-                    attrs[attrCount++] = new R4Attribute(key, value, false);
-                }
-            }
-
-            // Shrink directive array.
-            R4Directive[] dirsFinal = new R4Directive[dirCount];
-            System.arraycopy(dirs, 0, dirsFinal, 0, dirCount);
-            // Shrink attribute array.
-            R4Attribute[] attrsFinal = new R4Attribute[attrCount];
-            System.arraycopy(attrs, 0, attrsFinal, 0, attrCount);
-
-            // Create package attributes for each package and
-            // set directives/attributes. Add each package to
-            // completel list of packages.
-            R4Package[] pkgs = new R4Package[pkgCount];
-            for (int pkgIdx = 0; pkgIdx < pkgCount; pkgIdx++)
-            {
-                pkgs[pkgIdx] = new R4Package(pieces[pkgIdx], dirsFinal, attrsFinal);
-                completeList.add(pkgs[pkgIdx]);
-            }
-        }
-    
-        R4Package[] pkgs = (R4Package[])
-            completeList.toArray(new R4Package[completeList.size()]);
-        return pkgs;
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryAdminImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryAdminImpl.java
index 09eb837..14cbc28 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryAdminImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryAdminImpl.java
@@ -19,19 +19,25 @@
 package org.apache.felix.bundlerepository.impl;
 
 import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.StringTokenizer;
 
 import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.DataModelHelper;
 import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Repository;
 import org.apache.felix.bundlerepository.Resolver;
 import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.utils.collections.MapToDictionary;
+import org.apache.felix.utils.log.Logger;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
@@ -40,10 +46,11 @@
 
 public class RepositoryAdminImpl implements RepositoryAdmin
 {
-    static BundleContext m_context = null;
+    private final BundleContext m_context;
     private final Logger m_logger;
     private final SystemRepositoryImpl m_system;
     private final LocalRepositoryImpl m_local;
+    private final DataModelHelper m_helper = new DataModelHelperImpl();
     private Map m_repoMap = new HashMap();
     private boolean m_initialized = false;
 
@@ -61,12 +68,17 @@
         m_local = new LocalRepositoryImpl(context, logger);
     }
 
-    public org.apache.felix.bundlerepository.Repository getLocalRepository()
+    public DataModelHelper getHelper()
+    {
+        return m_helper;
+    }
+
+    public Repository getLocalRepository()
     {
         return m_local;
     }
 
-    public org.apache.felix.bundlerepository.Repository getSystemRepository()
+    public Repository getSystemRepository()
     {
         return m_system;
     }
@@ -86,16 +98,46 @@
         return addRepository(url, Integer.MAX_VALUE);
     }
 
-    public synchronized RepositoryImpl addRepository(URL url, int hopCount) throws Exception
+    public synchronized RepositoryImpl addRepository(final URL url, int hopCount) throws Exception
     {
         initialize();
 
         // If the repository URL is a duplicate, then we will just
         // replace the existing repository object with a new one,
         // which is effectively the same as refreshing the repository.
-        RepositoryImpl repo = new RepositoryImpl(this, url, hopCount, m_logger);
-        m_repoMap.put(url.toExternalForm(), repo);
-        return repo;
+        try
+        {
+            RepositoryImpl repository = (RepositoryImpl) AccessController.doPrivileged(new PrivilegedExceptionAction()
+            {
+                public Object run() throws Exception
+                {
+                    return m_helper.repository(url);
+                }
+            });
+            m_repoMap.put(url.toExternalForm(), repository);
+
+            // resolve referrals
+            hopCount--;
+            if (hopCount > 0 && repository.getReferrals() != null)
+            {
+                for (int i = 0; i < repository.getReferrals().length; i++)
+                {
+                    Referral referral = repository.getReferrals()[i];
+
+                    URL referralUrl = new URL(url, referral.getUrl());
+                    hopCount = (referral.getDepth() > hopCount) ? hopCount : referral.getDepth();
+
+                    addRepository(referralUrl, hopCount);
+                }
+            }
+
+            return repository;
+        }
+        catch (PrivilegedActionException ex)
+        {
+            throw (Exception) ex.getCause();
+        }
+
     }
 
     public synchronized boolean removeRepository(String uri)
@@ -138,7 +180,7 @@
     {
         initialize();
 
-        Filter filter = filterExpr != null ? filter(filterExpr) : null;
+        Filter filter = filterExpr != null ? m_helper.filter(filterExpr) : null;
         Resource[] resources;
         MapToDictionary dict = new MapToDictionary(null);
         Repository[] repos = listRepositories();
@@ -208,44 +250,6 @@
         return resources;
     }
 
-    public Requirement requirement(String name, String filter) throws InvalidSyntaxException
-    {
-        RequirementImpl req = new RequirementImpl();
-        req.setName(name);
-        if (filter != null)
-        {
-            req.setFilter(filter);
-        }
-        return req;
-    }
-
-    public Filter filter(String filter) throws InvalidSyntaxException
-    {
-        return FilterImpl.newInstance(filter);
-    }
-
-    public Repository repository(URL url) throws Exception
-    {
-        return new RepositoryImpl(null, url, 0, m_logger);
-    }
-
-    public Repository repository(Resource[] resources) 
-    {
-        return new RepositoryImpl(resources);
-    }
-
-    public Capability capability(String name, Map properties)
-    {
-        CapabilityImpl cap = new CapabilityImpl();
-        cap.setName(name);
-        for (Iterator it = properties.entrySet().iterator(); it.hasNext();)
-        {
-            Map.Entry e = (Map.Entry) it.next();
-            cap.addP((String) e.getKey(), e.getValue());
-        }
-        return cap;
-    }
-
     private void initialize()
     {
         if (m_initialized)
@@ -280,4 +284,5 @@
         }
 
     }
-}
\ No newline at end of file
+
+}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryImpl.java
index 4518f5a..5c283d2 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryImpl.java
@@ -18,83 +18,32 @@
  */
 package org.apache.felix.bundlerepository.impl;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.net.URLConnection;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
 import java.util.Collections;
-import java.util.List;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
+import java.util.Set;
+import java.util.TreeSet;
 
-import org.apache.felix.bundlerepository.Capability;
-import org.apache.felix.bundlerepository.Requirement;
 import org.apache.felix.bundlerepository.Resource;
 import org.apache.felix.bundlerepository.Repository;
+import org.apache.felix.bundlerepository.impl.ResourceImpl;
 
 public class RepositoryImpl implements Repository
 {
-    public static final String OBR_PARSER_CLASS = "obr.parser.class";
-    public static final String OBR_PARSER_CLASS_DEFAULT = "org.apache.felix.bundlerepository.impl.StaxParser";
-
     private String m_name = null;
-    private long m_lastmodified = 0;
+    private long m_lastmodified = System.currentTimeMillis();
     private String m_uri = null;
-    private final Logger m_logger;
     private Resource[] m_resources = null;
     private Referral[] m_referrals = null;
-    private RepositoryAdminImpl m_repoAdmin = null;
-    private List m_resourceList;
+    private Set m_resourceSet = new TreeSet(new ResourceComparator());
 
-    // Reusable comparator for sorting resources by name.
-    private ResourceComparator m_nameComparator = new ResourceComparator();
+    public RepositoryImpl()
+    {
+    }
 
     public RepositoryImpl(Resource[] resources)
     {
-        m_repoAdmin = null;
-        m_uri = null;
-        m_logger = null;
         m_resources = resources;
-        m_lastmodified = System.currentTimeMillis();
-    }
-
-    public RepositoryImpl(RepositoryAdminImpl repoAdmin, URL url, Logger logger)
-        throws Exception
-    {
-        this(repoAdmin, url, Integer.MAX_VALUE, logger);
-    }
-
-    public RepositoryImpl(RepositoryAdminImpl repoAdmin, URL url, final int hopCount, Logger logger)
-        throws Exception
-    {
-        m_repoAdmin = repoAdmin;
-        m_uri = url.toExternalForm();
-        m_logger = logger;
-        m_resourceList = new ArrayList();
-        try
-        {
-            AccessController.doPrivileged(new PrivilegedExceptionAction()
-            {
-                public Object run() throws Exception
-                {
-                    parseRepositoryFile(hopCount);
-                    return null;
-                }
-            });
-        }
-        catch (PrivilegedActionException ex)
-        {
-            throw (Exception) ex.getCause();
-        }
     }
 
     public String getURI()
@@ -109,9 +58,9 @@
 
     public Resource[] getResources()
     {
-        if (m_resources == null) {
-            Collections.sort(m_resourceList, m_nameComparator);
-            m_resources = (Resource[]) m_resourceList.toArray(new Resource[m_resourceList.size()]);
+        if (m_resources == null)
+        {
+            m_resources = (Resource[]) m_resourceSet.toArray(new Resource[m_resourceSet.size()]);
         }
         return m_resources;
     }
@@ -119,10 +68,14 @@
     public void addResource(Resource resource)
     {
         // Set resource's repository.
-        ((ResourceImpl) resource).setRepository(this);
+        if (resource instanceof ResourceImpl)
+        {
+            ((ResourceImpl) resource).setRepository(this);
+        }
 
         // Add to resource array.
-        m_resourceList.add(resource);
+        m_resourceSet.remove(resource);
+        m_resourceSet.add(resource);
         m_resources = null;
     }
 
@@ -162,7 +115,12 @@
         return m_lastmodified;
     }
 
-    public void setLastmodified(String s)
+    public void setLastModified(long lastModified)
+    {
+        m_lastmodified = lastModified;
+    }
+
+    public void setLastModified(String s)
     {
         SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmss.SSS");
         try
@@ -184,136 +142,4 @@
         return null;
     }
 
-    protected void parseRepositoryFile(int hopCount) throws Exception
-    {
-        InputStream is = null;
-        BufferedReader br = null;
-
-        try
-        {
-            URL url = new URL(m_uri);
-            // Do it the manual way to have a chance to
-            // set request properties as proxy auth (EW).
-            URLConnection conn = url.openConnection();
-
-            // Support for http proxy authentication
-            String auth = System.getProperty("http.proxyAuth");
-            if ((auth != null) && (auth.length() > 0))
-            {
-                if ("http".equals(url.getProtocol()) || "https".equals(url.getProtocol()))
-                {
-                    String base64 = Util.base64Encode(auth);
-                    conn.setRequestProperty("Proxy-Authorization", "Basic " + base64);
-                }
-            }
-
-            if (url.getPath().endsWith(".zip"))
-            {
-                ZipInputStream zin = new ZipInputStream(conn.getInputStream());
-                ZipEntry entry = zin.getNextEntry();
-                while (entry != null)
-                {
-                    if (entry.getName().equals("repository.xml"))
-                    {
-                        is = zin;
-                        break;
-                    }
-                    entry = zin.getNextEntry();
-                }
-            }
-            else
-            {
-                is = conn.getInputStream();
-            }
-
-            if (is != null)
-            {
-                parseRepository(is);
-
-
-                // resolve referrals
-                hopCount--;
-                if (hopCount > 0 && m_referrals != null)
-                {
-                    for (int i = 0; i < m_referrals.length; i++)
-                    {
-                        Referral referral = m_referrals[i];
-
-                        URL referralUrl = new URL(url, referral.getUrl());
-                        hopCount = (referral.getDepth() > hopCount) ? hopCount : referral.getDepth();
-
-                        m_repoAdmin.addRepository(referralUrl, hopCount);
-                    }
-                }
-            }
-            else
-            {
-                // This should not happen.
-                throw new Exception("Unable to get input stream for repository.");
-            }
-        }
-        finally
-        {
-            try
-            {
-                if (is != null)
-                {
-                    is.close();
-                }
-            }
-            catch (IOException ex)
-            {
-                // Not much we can do.
-            }
-        }
-    }
-
-    protected void parseRepository(InputStream is) throws Exception
-    {
-        RepositoryParser parser = null;
-        try
-        {
-            String className = (String) RepositoryAdminImpl.m_context.getProperty(OBR_PARSER_CLASS);
-            if (className == null || className.length() == 0)
-            {
-                className = OBR_PARSER_CLASS_DEFAULT;
-            }
-            parser = (RepositoryParser) Class.forName(className).newInstance();
-        }
-        catch (Throwable t)
-        {
-        }
-        if (parser == null)
-        {
-            parser = new PullParser();
-
-        }
-        parser.parse(this, is);
-    }
-
-    public interface RepositoryParser
-    {
-        static final String REPOSITORY = "repository";
-        static final String NAME = "name";
-        static final String LASTMODIFIED = "lastmodified";
-        static final String REFERRAL = "referral";
-        static final String RESOURCE = "resource";
-        static final String DEPTH = "depth";
-        static final String URL = "url";
-        static final String CATEGORY = "category";
-        static final String ID = "id";
-        static final String CAPABILITY = "capability";
-        static final String REQUIRE = "require";
-        static final String P = "p";
-        static final String N = "n";
-        static final String T = "t";
-        static final String V = "v";
-        static final String FILTER = "filter";
-        static final String EXTEND = "extend";
-        static final String MULTIPLE = "multiple";
-        static final String OPTIONAL = "optional";
-
-        void parse(RepositoryImpl repository, InputStream is) throws Exception;
-    }
-
 }
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryParser.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryParser.java
new file mode 100644
index 0000000..e715de6
--- /dev/null
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryParser.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.bundlerepository.impl;
+
+import java.io.InputStream;
+import java.io.Reader;
+
+public abstract class RepositoryParser
+{
+    public static final String REPOSITORY = "repository";
+    public static final String NAME = "name";
+    public static final String LASTMODIFIED = "lastmodified";
+    public static final String REFERRAL = "referral";
+    public static final String RESOURCE = "resource";
+    public static final String DEPTH = "depth";
+    public static final String URL = "url";
+    public static final String CATEGORY = "category";
+    public static final String ID = "id";
+    public static final String CAPABILITY = "capability";
+    public static final String REQUIRE = "require";
+    public static final String P = "p";
+    public static final String N = "n";
+    public static final String T = "t";
+    public static final String V = "v";
+    public static final String FILTER = "filter";
+    public static final String EXTEND = "extend";
+    public static final String MULTIPLE = "multiple";
+    public static final String OPTIONAL = "optional";
+
+    public static final String OBR_PARSER_CLASS = "obr.xml.class";
+
+    public static RepositoryParser getParser()
+    {
+        RepositoryParser parser = null;
+        try
+        {
+            String className = Activator.getContext() != null
+                                    ? Activator.getContext().getProperty(OBR_PARSER_CLASS)
+                                    : System.getProperty(OBR_PARSER_CLASS);
+            if (className != null && className.length() > 0)
+            {
+                parser = (RepositoryParser) Class.forName(className).newInstance();
+            }
+        }
+        catch (Throwable t)
+        {
+            // Ignore
+        }
+        if (parser == null)
+        {
+            parser = new PullParser();
+
+        }
+        return parser;
+    }
+
+
+    public abstract RepositoryImpl parseRepository(InputStream is) throws Exception;
+
+    public abstract RepositoryImpl parseRepository(Reader r) throws Exception;
+
+    public abstract ResourceImpl parseResource(Reader reader) throws Exception;
+
+    public abstract CapabilityImpl parseCapability(Reader reader) throws Exception;
+
+    public abstract PropertyImpl parseProperty(Reader reader) throws Exception;
+
+    public abstract RequirementImpl parseRequirement(Reader reader) throws Exception;
+
+}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java
index b9675cb..d03109c 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java
@@ -20,6 +20,7 @@
 
 import org.apache.felix.bundlerepository.Capability;
 import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.utils.filter.FilterImpl;
 import org.osgi.framework.InvalidSyntaxException;
 
 public class RequirementImpl implements Requirement
@@ -35,75 +36,89 @@
     {
     }
 
-    public synchronized String getName()
+    public RequirementImpl(String name) 
+    {
+        setName(name);
+    }
+
+    public String getName()
     {
         return m_name;
     }
 
-    public synchronized void setName(String name)
+    public void setName(String name)
     {
         // Name of capabilities and requirements are interned for performances
-        // (with a very slow inter consumption as there are only a handful of values)
+        // (with a very low memory consumption as there are only a handful of values)
         m_name = name.intern();
     }
 
-    public synchronized String getFilter()
+    public String getFilter()
     {
         return m_filter.toString();
     }
 
-    public synchronized void setFilter(String filter) throws InvalidSyntaxException
+    public void setFilter(String filter)
     {
-        m_filter = FilterImpl.newInstance(filter, true);
+        try
+        {
+            m_filter = FilterImpl.newInstance(filter, true);
+        }
+        catch (InvalidSyntaxException e)
+        {
+            IllegalArgumentException ex = new IllegalArgumentException();
+            ex.initCause(e);
+            throw ex;
+        }
     }
 
-    public synchronized boolean isSatisfied(Capability capability)
+    public boolean isSatisfied(Capability capability)
     {
-        return m_name.equals(capability.getName()) && m_filter.matchCase(capability.getProperties())
-                && (m_filter.toString().indexOf("(mandatory:<*") >= 0 || capability.getProperties().get("mandatory:") == null);
+        return m_name.equals(capability.getName()) && m_filter.matchCase(capability.getPropertiesAsMap())
+                && (m_filter.toString().indexOf("(mandatory:<*") >= 0 || capability.getPropertiesAsMap().get("mandatory:") == null);
     }
 
-    public synchronized boolean isExtend()
+    public boolean isExtend()
     {
         return m_extend;
     }
 
-    public synchronized void setExtend(String s)
+    public void setExtend(boolean extend)
     {
-        m_extend = Boolean.valueOf(s).booleanValue();
+        m_extend = extend;
     }
 
-    public synchronized boolean isMultiple()
+    public boolean isMultiple()
     {
         return m_multiple;
     }
 
-    public synchronized void setMultiple(String s)
+    public void setMultiple(boolean multiple)
     {
-        m_multiple = Boolean.valueOf(s).booleanValue();
+        m_multiple = multiple;
     }
 
-    public synchronized boolean isOptional()
+    public boolean isOptional()
     {
         return m_optional;
     }
 
-    public synchronized void setOptional(String s)
+    public void setOptional(boolean optional)
     {
-        m_optional = Boolean.valueOf(s).booleanValue();
+        m_optional = optional;
     }
 
-    public synchronized String getComment()
+    public String getComment()
     {
         return m_comment;
     }
 
-    public synchronized void addText(String s)
+    public void addText(String s)
     {
         m_comment = s;
     }
 
-    public synchronized boolean equals(Object o)
+    public boolean equals(Object o)
     {
         if (this == o)
         {
@@ -122,12 +137,12 @@
         return false;
     }
 
-    public synchronized int hashCode()
+    public int hashCode()
     {
         return m_filter.toString().hashCode();
     }
 
-    public synchronized String toString()
+    public String toString()
     {
         return m_name + ":" + getFilter();
     }
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResolverImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResolverImpl.java
index 51cae3f..5d394e4 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResolverImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResolverImpl.java
@@ -23,6 +23,8 @@
 
 import org.apache.felix.bundlerepository.*;
 import org.apache.felix.bundlerepository.Resolver;
+import org.apache.felix.bundlerepository.impl.ResourceImpl;
+import org.apache.felix.utils.log.Logger;
 import org.osgi.framework.*;
 
 public class ResolverImpl implements Resolver
@@ -420,7 +422,7 @@
             {
                 best = current;
                 bestLocal = isCurrentLocal;
-                Object v = current.getCapability().getProperties().get(Resource.VERSION);
+                Object v = current.getCapability().getPropertiesAsMap().get(Resource.VERSION);
                 if ((v != null) && (v instanceof Version))
                 {
                     bestVersion = (Version) v;
@@ -428,7 +430,7 @@
             }
             else if ((m_resolutionFlags & DO_NOT_PREFER_LOCAL) != 0 || !bestLocal || isCurrentLocal)
             {
-                Object v = current.getCapability().getProperties().get(Resource.VERSION);
+                Object v = current.getCapability().getPropertiesAsMap().get(Resource.VERSION);
 
                 // If there is no version, then select the resource
                 // with the greatest number of capabilities.
@@ -575,7 +577,7 @@
                     {
                         m_logger.log(
                             Logger.LOG_ERROR,
-                            "Resolver: Update error - " + Util.getBundleName(localResource.getBundle()),
+                            "Resolver: Update error - " + getBundleName(localResource.getBundle()),
                             ex);
                         return;
                     }
@@ -767,4 +769,13 @@
         }
         return null;
     }
+
+    public static String getBundleName(Bundle bundle)
+    {
+        String name = (String) bundle.getHeaders().get(Constants.BUNDLE_NAME);
+        return (name == null)
+            ? "Bundle " + Long.toString(bundle.getBundleId())
+            : name;
+    }
+
 }
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResourceImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResourceImpl.java
index 31fb402..f896f4d 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResourceImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResourceImpl.java
@@ -19,40 +19,28 @@
 package org.apache.felix.bundlerepository.impl;
 
 import java.net.URI;
-import java.net.URISyntaxException;
 import java.util.*;
 
 import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.Property;
 import org.apache.felix.bundlerepository.Repository;
 import org.apache.felix.bundlerepository.Requirement;
 import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.utils.version.VersionTable;
 import org.osgi.framework.Version;
 
 public class ResourceImpl implements Resource
 {
 
     private final Map m_map = new HashMap();
+    private final List m_capList = new ArrayList();
+    private final List m_reqList = new ArrayList();
     private Repository m_repo;
-    private List m_capList = new ArrayList();
-    private List m_reqList = new ArrayList();
-
     private Map m_uris;
-
-    private int m_hash;
+    private transient int m_hash;
 
     public ResourceImpl()
     {
-        this(null);
-    }
-
-    public ResourceImpl(ResourceImpl resource)
-    {
-        if (resource != null)
-        {
-            m_map.putAll(resource.getProperties());
-            m_capList.addAll(resource.m_capList);
-            m_reqList.addAll(resource.m_reqList);
-        }
     }
 
     public boolean equals(Object o)
@@ -85,11 +73,13 @@
         return m_hash;
     }
 
-    public Repository getRepository() {
+    public Repository getRepository()
+    {
         return m_repo;
     }
 
-    public void setRepository(Repository repository) {
+    public void setRepository(Repository repository)
+    {
         this.m_repo = repository;
     }
 
@@ -127,12 +117,17 @@
         return (String) m_map.get(Resource.URI);
     }
 
+    public Long getSize()
+    {
+        return ((Long) m_map.get(Resource.SIZE));
+    }
+
     public Requirement[] getRequirements()
     {
         return (Requirement[]) m_reqList.toArray(new Requirement[m_reqList.size()]);
     }
 
-    protected void addRequire(Requirement req)
+    public void addRequire(Requirement req)
     {
         m_reqList.add(req);
     }
@@ -142,7 +137,7 @@
         return (Capability[]) m_capList.toArray(new Capability[m_capList.size()]);
     }
 
-    protected void addCapability(Capability cap)
+    public void addCapability(Capability cap)
     {
         m_capList.add(cap);
     }
@@ -157,7 +152,7 @@
         return (String[]) catList.toArray(new String[catList.size()]);
     }
 
-    protected void addCategory(CategoryImpl cat)
+    public void addCategory(String category)
     {
         List catList = (List) m_map.get(CATEGORY);
         if (catList == null)
@@ -165,7 +160,7 @@
             catList = new ArrayList();
             m_map.put(CATEGORY, catList);
         }
-        catList.add(cat.getId());
+        catList.add(category);
     }
 
     public boolean isLocal()
@@ -175,18 +170,18 @@
 
     /**
      * Default setter method when setting parsed data from the XML file. 
-    **/
-    protected Object put(Object key, Object value)
+     **/
+    public Object put(Object key, Object value)
     {
         put(key.toString(), value.toString(), null);
         return null;
     }
 
-    protected void put(String key, String value, String type)
+    public void put(String key, String value, String type)
     {
         key = key.toLowerCase();
         m_hash = 0;
-        if ("uri".equals(type) || URI.equals(key))
+        if (Property.URI.equals(type) || URI.equals(key))
         {
             if (m_uris == null)
             {
@@ -194,17 +189,23 @@
             }
             m_uris.put(key, value);
         }
-        else if ("version".equals(type) || VERSION.equals(key))
+        else if (Property.VERSION.equals(type) || VERSION.equals(key))
         {
-            m_map.put(key, Version.parseVersion(value));
+            m_map.put(key, VersionTable.getVersion(value));
         }
-        else if ("long".equals(type) || SIZE.equals(key))
+        else if (Property.LONG.equals(type) || SIZE.equals(key))
         {
-            m_map.put(key, Long.valueOf(value.toString()));
+            m_map.put(key, Long.valueOf(value));
         }
-        else if (CATEGORY.equals(key))
+        else if (Property.SET.equals(type) || CATEGORY.equals(key))
         {
-            m_map.put(key, Arrays.asList(value.toString().split(",")));
+            StringTokenizer st = new StringTokenizer(value, ",");
+            Set s = new HashSet();
+            while (st.hasMoreTokens())
+            {
+                s.add(st.nextToken().trim());
+            }
+            m_map.put(key, s);
         }
         else
         {
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/StaxParser.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/StaxParser.java
index 450c9ac..58880c0 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/StaxParser.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/StaxParser.java
@@ -19,6 +19,7 @@
 package org.apache.felix.bundlerepository.impl;
 
 import java.io.InputStream;
+import java.io.Reader;
 import javax.xml.stream.Location;
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamConstants;
@@ -26,25 +27,33 @@
 import javax.xml.stream.XMLStreamReader;
 
 /**
- * Repository XML parser based on StaX 
+ * Repository XML xml based on StaX
  */
-public class StaxParser implements RepositoryImpl.RepositoryParser
+public class StaxParser extends RepositoryParser
 {
 
     static XMLInputFactory factory;
 
+    public static synchronized void setFactory(XMLInputFactory factory)
+    {
+        StaxParser.factory = factory;
+    }
+
+    public static synchronized XMLInputFactory getFactory()
+    {
+        if (factory == null)
+        {
+            XMLInputFactory factory = XMLInputFactory.newInstance();
+            setProperty(factory, XMLInputFactory.IS_NAMESPACE_AWARE, false);
+            setProperty(factory, XMLInputFactory.IS_VALIDATING, false);
+            setProperty(factory, XMLInputFactory.IS_COALESCING, false);
+            StaxParser.factory = factory;
+        }
+        return factory;
+    }
+
     public StaxParser()
     {
-        synchronized (StaxParser.class)
-        {
-            if (factory == null)
-            {
-                factory = XMLInputFactory.newInstance();
-                setProperty(factory, XMLInputFactory.IS_NAMESPACE_AWARE, false);
-                setProperty(factory, XMLInputFactory.IS_VALIDATING, false);
-                setProperty(factory, XMLInputFactory.IS_COALESCING, false);
-            }
-        }
     }
 
     protected static boolean setProperty(XMLInputFactory factory, String name, boolean value)
@@ -60,54 +69,110 @@
         return false;
     }
 
-    public void parse(RepositoryImpl repository, InputStream is) throws Exception
+    public RepositoryImpl parseRepository(InputStream is) throws Exception
     {
-        XMLStreamReader reader = factory.createXMLStreamReader(is);
-        try
+        XMLStreamReader reader = getFactory().createXMLStreamReader(is);
+        int event = reader.nextTag();
+        if (event != XMLStreamConstants.START_ELEMENT || !REPOSITORY.equals(reader.getLocalName()))
         {
-            int event = reader.nextTag();
-            if (event != XMLStreamConstants.START_ELEMENT || !REPOSITORY.equals(reader.getLocalName()))
-            {
-                throw new Exception("Expected element 'repository' at the root of the document");
-            }
-            for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
-            {
-                String name = reader.getAttributeLocalName(i);
-                String value = reader.getAttributeValue(i);
-                if (NAME.equals(name))
-                {
-                    repository.setName(value);
-                }
-                else if (LASTMODIFIED.equals(name))
-                {
-                    repository.setLastmodified(value);
-                }
-            }
-            while ((event = reader.nextTag()) == XMLStreamConstants.START_ELEMENT)
-            {
-                String element = reader.getLocalName();
-                if (REFERRAL.equals(element))
-                {
-                    Referral referral = parseReferral(reader);
-                    repository.addReferral(referral);
-                }
-                else if (RESOURCE.equals(element))
-                {
-                    ResourceImpl resource = parseResource(reader);
-                    repository.addResource(resource);
-                }
-                else
-                {
-                    ignoreTag(reader);
-                }
-            }
-            // Sanity check
-            sanityCheckEndElement(reader, event, REPOSITORY);
+            throw new Exception("Expected element 'repository' at the root of the document");
         }
-        finally
+        return parseRepository(reader);
+    }
+
+    public RepositoryImpl parseRepository(Reader r) throws Exception
+    {
+        XMLStreamReader reader = getFactory().createXMLStreamReader(r);
+        int event = reader.nextTag();
+        if (event != XMLStreamConstants.START_ELEMENT || !REPOSITORY.equals(reader.getLocalName()))
         {
-            reader.close();
+            throw new Exception("Expected element 'repository' at the root of the document");
         }
+        return parseRepository(reader);
+    }
+
+    public ResourceImpl parseResource(Reader r) throws Exception
+    {
+        XMLStreamReader reader = getFactory().createXMLStreamReader(r);
+        int event = reader.nextTag();
+        if (event != XMLStreamConstants.START_ELEMENT || !RESOURCE.equals(reader.getLocalName()))
+        {
+            throw new Exception("Expected element 'resource'");
+        }
+        return parseResource(reader);
+    }
+
+    public CapabilityImpl parseCapability(Reader r) throws Exception
+    {
+        XMLStreamReader reader = getFactory().createXMLStreamReader(r);
+        int event = reader.nextTag();
+        if (event != XMLStreamConstants.START_ELEMENT || !CAPABILITY.equals(reader.getLocalName()))
+        {
+            throw new Exception("Expected element 'capability'");
+        }
+        return parseCapability(reader);
+    }
+
+    public PropertyImpl parseProperty(Reader r) throws Exception
+    {
+        XMLStreamReader reader = getFactory().createXMLStreamReader(r);
+        int event = reader.nextTag();
+        if (event != XMLStreamConstants.START_ELEMENT || !P.equals(reader.getLocalName()))
+        {
+            throw new Exception("Expected element 'p'");
+        }
+        return parseProperty(reader);
+    }
+
+    public RequirementImpl parseRequirement(Reader r) throws Exception 
+    {
+        XMLStreamReader reader = getFactory().createXMLStreamReader(r);
+        int event = reader.nextTag();
+        if (event != XMLStreamConstants.START_ELEMENT || !REQUIRE.equals(reader.getLocalName()))
+        {
+            throw new Exception("Expected element 'require'");
+        }
+        return parseRequire(reader);
+    }
+
+    public RepositoryImpl parseRepository(XMLStreamReader reader) throws Exception
+    {
+        RepositoryImpl repository = new RepositoryImpl();
+        for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
+        {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+            if (NAME.equals(name))
+            {
+                repository.setName(value);
+            }
+            else if (LASTMODIFIED.equals(name))
+            {
+                repository.setLastModified(value);
+            }
+        }
+        int event;
+        while ((event = reader.nextTag()) == XMLStreamConstants.START_ELEMENT)
+        {
+            String element = reader.getLocalName();
+            if (REFERRAL.equals(element))
+            {
+                Referral referral = parseReferral(reader);
+                repository.addReferral(referral);
+            }
+            else if (RESOURCE.equals(element))
+            {
+                ResourceImpl resource = parseResource(reader);
+                repository.addResource(resource);
+            }
+            else
+            {
+                ignoreTag(reader);
+            }
+        }
+        // Sanity check
+        sanityCheckEndElement(reader, event, REPOSITORY);
+        return repository;
     }
 
     private void sanityCheckEndElement(XMLStreamReader reader, int event, String element)
@@ -153,7 +218,7 @@
                 String element = reader.getLocalName();
                 if (CATEGORY.equals(element))
                 {
-                    CategoryImpl category = parseCategory(reader);
+                    String category = parseCategory(reader);
                     resource.addCategory(category);
                 }
                 else if (CAPABILITY.equals(element))
@@ -211,18 +276,18 @@
         }
     }
 
-    private CategoryImpl parseCategory(XMLStreamReader reader) throws XMLStreamException
+    private String parseCategory(XMLStreamReader reader) throws XMLStreamException
     {
-        CategoryImpl category = new CategoryImpl();
+        String id = null;
         for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
         {
             if (ID.equals(reader.getAttributeLocalName(i)))
             {
-                category.setId(reader.getAttributeValue(i));
+                id = reader.getAttributeValue(i);
             }
         }
         sanityCheckEndElement(reader, reader.nextTag(), CATEGORY);
-        return category;
+        return id;
     }
 
     private CapabilityImpl parseCapability(XMLStreamReader reader) throws Exception
@@ -244,7 +309,7 @@
             if (P.equals(element))
             {
                 PropertyImpl prop = parseProperty(reader);
-                capability.addP(prop);
+                capability.addProperty(prop);
             }
             else
             {
@@ -299,15 +364,15 @@
             }
             else if (EXTEND.equals(name))
             {
-                requirement.setExtend(value);
+                requirement.setExtend(Boolean.parseBoolean(value));
             }
             else if (MULTIPLE.equals(name))
             {
-                requirement.setMultiple(value);
+                requirement.setMultiple(Boolean.parseBoolean(value));
             }
             else if (OPTIONAL.equals(name))
             {
-                requirement.setOptional(value);
+                requirement.setOptional(Boolean.parseBoolean(value));
             }
         }
         int event;
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/StringSet.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/StringSet.java
deleted file mode 100644
index c05d417..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/StringSet.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.bundlerepository.impl;
-
-import java.util.*;
-
-public class StringSet extends HashSet
-{
-    private static final long serialVersionUID = 1L;
-
-    public StringSet(String set)
-    {
-        if (set != null)
-        {
-            StringTokenizer st = new StringTokenizer(set, ",");
-            while (st.hasMoreTokens())
-            {
-                add(st.nextToken().trim());
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/SystemRepositoryImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/SystemRepositoryImpl.java
index 078bb8e..502dd8a 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/SystemRepositoryImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/SystemRepositoryImpl.java
@@ -19,6 +19,7 @@
 package org.apache.felix.bundlerepository.impl;
 
 import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.utils.log.Logger;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
 import org.apache.felix.bundlerepository.Repository;
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/Util.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/Util.java
deleted file mode 100644
index 5ca6d72..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/Util.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.bundlerepository.impl;
-
-import java.io.*;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-
-public class Util
-{
-    public static String getClassName(String className)
-    {
-        if (className == null)
-        {
-            className = "";
-        }
-        return (className.lastIndexOf('.') < 0)
-            ? "" : className.substring(className.lastIndexOf('.') + 1);
-    }
-
-    public static String getBundleName(Bundle bundle)
-    {
-        String name = (String) bundle.getHeaders().get(Constants.BUNDLE_NAME);
-        return (name == null)
-            ? "Bundle " + Long.toString(bundle.getBundleId())
-            : name;
-    }
-
-    /**
-     * Parses delimited string and returns an array containing the tokens. This
-     * parser obeys quotes, so the delimiter character will be ignored if it is
-     * inside of a quote. This method assumes that the quote character is not
-     * included in the set of delimiter characters.
-     * @param value the delimited string to parse.
-     * @param delim the characters delimiting the tokens.
-     * @return an array of string tokens or null if there were no tokens.
-    **/
-    public static String[] parseDelimitedString(String value, String delim)
-    {
-        if (value == null)
-        {
-           value = "";
-        }
-
-        List list = new ArrayList();
-
-        int CHAR = 1;
-        int DELIMITER = 2;
-        int STARTQUOTE = 4;
-        int ENDQUOTE = 8;
-
-        StringBuffer sb = new StringBuffer();
-
-        int expecting = (CHAR | DELIMITER | STARTQUOTE);
-        
-        for (int i = 0; i < value.length(); i++)
-        {
-            char c = value.charAt(i);
-
-            boolean isDelimiter = (delim.indexOf(c) >= 0);
-            boolean isQuote = (c == '"');
-
-            if (isDelimiter && ((expecting & DELIMITER) > 0))
-            {
-                list.add(sb.toString().trim());
-                sb.delete(0, sb.length());
-                expecting = (CHAR | DELIMITER | STARTQUOTE);
-            }
-            else if (isQuote && ((expecting & STARTQUOTE) > 0))
-            {
-                sb.append(c);
-                expecting = CHAR | ENDQUOTE;
-            }
-            else if (isQuote && ((expecting & ENDQUOTE) > 0))
-            {
-                sb.append(c);
-                expecting = (CHAR | STARTQUOTE | DELIMITER);
-            }
-            else if ((expecting & CHAR) > 0)
-            {
-                sb.append(c);
-            }
-            else
-            {
-                throw new IllegalArgumentException("Invalid delimited string: " + value);
-            }
-        }
-
-        if (sb.length() > 0)
-        {
-            list.add(sb.toString().trim());
-        }
-
-        return (String[]) list.toArray(new String[list.size()]);
-    }
-
-    public static int compareVersion(int[] v1, int[] v2)
-    {
-        if (v1[0] > v2[0])
-        {
-            return 1;
-        }
-        else if (v1[0] < v2[0])
-        {
-            return -1;
-        }
-        else if (v1[1] > v2[1])
-        {
-            return 1;
-        }
-        else if (v1[1] < v2[1])
-        {
-            return -1;
-        }
-        else if (v1[2] > v2[2])
-        {
-            return 1;
-        }
-        else if (v1[2] < v2[2])
-        {
-            return -1;
-        }
-        return 0;
-    }
-
-    private static final byte encTab[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
-        0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52,
-        0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64,
-        0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
-        0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31,
-        0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2b, 0x2f };
-
-    private static final byte decTab[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1,
-        -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1,
-        -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
-        18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29,
-        30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-        48, 49, 50, 51, -1, -1, -1, -1, -1 };
-
-    public static String base64Encode(String s) throws IOException
-    {
-        return encode(s.getBytes(), 0);
-    }
-
-    /**
-     * Encode a raw byte array to a Base64 String.
-     * 
-     * @param in Byte array to encode.
-     * @param len Length of Base64 lines. 0 means no line breaks.
-    **/
-    public static String encode(byte[] in, int len) throws IOException
-    {
-        ByteArrayOutputStream baos = null;
-        ByteArrayInputStream bais = null;
-        try
-        {
-            baos = new ByteArrayOutputStream();
-            bais = new ByteArrayInputStream(in);
-            encode(bais, baos, len);
-            // ASCII byte array to String
-            return (new String(baos.toByteArray()));
-        }
-        finally
-        {
-            if (baos != null)
-            {
-                baos.close();
-            }
-            if (bais != null)
-            {
-                bais.close();
-            }
-        }
-    }
-
-    public static void encode(InputStream in, OutputStream out, int len)
-        throws IOException
-    {
-
-        // Check that length is a multiple of 4 bytes
-        if (len % 4 != 0)
-        {
-            throw new IllegalArgumentException("Length must be a multiple of 4");
-        }
-
-        // Read input stream until end of file
-        int bits = 0;
-        int nbits = 0;
-        int nbytes = 0;
-        int b;
-
-        while ((b = in.read()) != -1)
-        {
-            bits = (bits << 8) | b;
-            nbits += 8;
-            while (nbits >= 6)
-            {
-                nbits -= 6;
-                out.write(encTab[0x3f & (bits >> nbits)]);
-                nbytes++;
-                // New line
-                if (len != 0 && nbytes >= len)
-                {
-                    out.write(0x0d);
-                    out.write(0x0a);
-                    nbytes -= len;
-                }
-            }
-        }
-
-        switch (nbits)
-        {
-            case 2:
-                out.write(encTab[0x3f & (bits << 4)]);
-                out.write(0x3d); // 0x3d = '='
-                out.write(0x3d);
-                break;
-            case 4:
-                out.write(encTab[0x3f & (bits << 2)]);
-                out.write(0x3d);
-                break;
-        }
-
-        if (len != 0)
-        {
-            if (nbytes != 0)
-            {
-                out.write(0x0d);
-                out.write(0x0a);
-            }
-            out.write(0x0d);
-            out.write(0x0a);
-        }
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/VersionRange.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/VersionRange.java
deleted file mode 100644
index b82bafc..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/VersionRange.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.bundlerepository.impl;
-
-import org.osgi.framework.Version;
-
-public class VersionRange
-{
-    private Version m_low = null;
-    private boolean m_isLowInclusive = false;
-    private Version m_high = null;
-    private boolean m_isHighInclusive = false;
-    private String m_toString = null;
-    public static final VersionRange infiniteRange = new VersionRange(Version.emptyVersion, true, null, true);
-
-    public VersionRange(Version low, boolean isLowInclusive,
-        Version high, boolean isHighInclusive)
-    {
-        m_low = low;
-        m_isLowInclusive = isLowInclusive;
-        m_high = high;
-        m_isHighInclusive = isHighInclusive;
-    }
-
-    public Version getLow()
-    {
-        return m_low;
-    }
-
-    public boolean isLowInclusive()
-    {
-        return m_isLowInclusive;
-    }
-
-    public Version getHigh()
-    {
-        return m_high;
-    }
-
-    public boolean isHighInclusive()
-    {
-        return m_isHighInclusive;
-    }
-
-    public boolean isInRange(Version version)
-    {
-        // We might not have an upper end to the range.
-        if (m_high == null)
-        {
-            return (version.compareTo(m_low) >= 0);
-        }
-        else if (isLowInclusive() && isHighInclusive())
-        {
-            return (version.compareTo(m_low) >= 0) && (version.compareTo(m_high) <= 0);
-        }
-        else if (isHighInclusive())
-        {
-            return (version.compareTo(m_low) > 0) && (version.compareTo(m_high) <= 0);
-        }
-        else if (isLowInclusive())
-        {
-            return (version.compareTo(m_low) >= 0) && (version.compareTo(m_high) < 0);
-        }
-        return (version.compareTo(m_low) > 0) && (version.compareTo(m_high) < 0);
-    }
-
-    public static VersionRange parse(String range)
-    {
-        // Check if the version is an interval.
-        if (range.indexOf(',') >= 0)
-        {
-            String s = range.substring(1, range.length() - 1);
-            String vlo = s.substring(0, s.indexOf(',')).trim();
-            String vhi = s.substring(s.indexOf(',') + 1, s.length()).trim();
-            return new VersionRange (
-                new Version(vlo), (range.charAt(0) == '['),
-                new Version(vhi), (range.charAt(range.length() - 1) == ']'));
-        }
-        else
-        {
-            return new VersionRange(new Version(range), true, null, false);
-        }
-    }
-
-    public String toString()
-    {
-        if (m_toString == null)
-        {
-            if (m_high != null)
-            {
-                StringBuffer sb = new StringBuffer();
-                sb.append(m_isLowInclusive ? '[' : '(');
-                sb.append(m_low.toString());
-                sb.append(',');
-                sb.append(m_high.toString());
-                sb.append(m_isHighInclusive ? ']' : ')');
-                m_toString = sb.toString();
-            }
-            else
-            {
-                m_toString = m_low.toString();
-            }
-        }
-        return m_toString;
-    }
-}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/XmlWriter.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/XmlWriter.java
new file mode 100644
index 0000000..aaadb1d
--- /dev/null
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/XmlWriter.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.bundlerepository.impl;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+
+public class XmlWriter
+{
+    private final Writer w;
+    private final List elements = new ArrayList();
+    private boolean empty;
+    private boolean endAttr = true;
+    private boolean indent;
+
+    public XmlWriter(Writer w)
+    {
+        this(w, true);
+    }
+
+    public XmlWriter(Writer w, boolean indent)
+    {
+        this.w = w;
+        this.indent = indent;
+    }
+
+    public XmlWriter indent(int nb) throws IOException
+    {
+        if (indent)
+        {
+            while (nb-- > 0)
+            {
+                w.append("  ");
+            }
+        }
+        return this;
+    }
+
+    public XmlWriter newLine() throws IOException
+    {
+        if (indent)
+        {
+            w.append("\n");
+        }
+        return this;
+    }
+
+    public XmlWriter element(String name) throws IOException
+    {
+        if (!endAttr)
+        {
+            endAttr = true;
+            w.append(">");
+        }
+        if (!elements.isEmpty())
+        {
+            newLine();
+            indent(elements.size());
+        }
+        w.append("<").append(name);
+        elements.add(name);
+        empty = true;
+        endAttr = false;
+        return this;
+    }
+
+    public XmlWriter attribute(String name, Object value) throws IOException
+    {
+        if (value != null)
+        {
+            w.append(" ").append(name).append("='").append(encode(value.toString())).append("'");
+        }
+        return this;
+    }
+
+    public XmlWriter end() throws IOException
+    {
+        return end(true);
+    }
+
+    public XmlWriter end(boolean indent) throws IOException
+    {
+        String name = (String) elements.remove(elements.size() - 1);
+        if (!endAttr)
+        {
+            endAttr = true;
+            w.append("/>");
+        }
+        else
+        {
+            if (indent && !empty)
+            {
+                newLine();
+                indent(elements.size());
+            }
+            w.append("</").append(name).append(">");
+        }
+        empty = false;
+        return this;
+    }
+
+    public XmlWriter text(Object value) throws IOException
+    {
+        if (!endAttr)
+        {
+            endAttr = true;
+            w.append(">");
+        }
+        w.append(encode(value.toString()));
+        return this;
+    }
+
+    public XmlWriter textElement(String name, Object value) throws IOException
+    {
+        if (value != null)
+        {
+            element(name).text(value).end(false);
+        }
+        return this;
+    }
+
+    private static String encode(Object o) {
+        String s = o != null ? o.toString() : "";
+        return s.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
+    }
+
+}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/CapabilityWrapper.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/CapabilityWrapper.java
index f2dac89..fd3d779 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/CapabilityWrapper.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/CapabilityWrapper.java
@@ -36,6 +36,6 @@
     }
 
     public Map getProperties() {
-        return capability.getProperties();
+        return capability.getPropertiesAsMap();
     }
 }
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/DataModelHelperTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/DataModelHelperTest.java
new file mode 100644
index 0000000..ab4a5b5
--- /dev/null
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/DataModelHelperTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.bundlerepository.impl;
+
+import java.util.jar.Attributes;
+
+import junit.framework.TestCase;
+import org.apache.felix.bundlerepository.DataModelHelper;
+import org.apache.felix.bundlerepository.Resource;
+
+public class DataModelHelperTest extends TestCase
+{
+
+    private DataModelHelper dmh = new DataModelHelperImpl();
+
+    public void testResource() throws Exception
+    {
+        Attributes attr = new Attributes();
+        attr.putValue("Manifest-Version", "1.0");
+        attr.putValue("Bundle-Name", "Apache Felix Utils");
+        attr.putValue("Bundle-Version", "0.1.0.SNAPSHOT");
+        attr.putValue("Bundle-ManifestVersion", "2");
+        attr.putValue("Bundle-License", "http://www.apache.org/licenses/LICENSE-2.0.txt");
+        attr.putValue("Bundle-Description", "Utility classes for OSGi.");
+        attr.putValue("Import-Package", "org.osgi.framework;version=\"[1.4,2)\"");
+        attr.putValue("Bundle-SymbolicName", "org.apache.felix.utils");
+
+        Resource resource = dmh.createResource(attr);
+
+        String xml = dmh.writeResource(resource);
+        System.out.println(xml);
+
+        Resource resource2 = dmh.readResource(xml);
+        String xml2 = dmh.writeResource(resource2);
+        System.out.println(xml2);
+
+        assertEquals(xml, xml2);
+    }
+}
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/FilterImplTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/FilterImplTest.java
deleted file mode 100644
index f1fa32e..0000000
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/FilterImplTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/* 
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.bundlerepository.impl;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import junit.framework.TestCase;
-import org.osgi.framework.Version;
-
-public class FilterImplTest extends TestCase
-{
-    public void testStandardLDAP() throws Exception
-    {
-        FilterImpl filterImpl = FilterImpl.newInstance(
-            "(&(package=org.eclipse.core.runtime)(version>=0.0.0)(common=split))");
-
-        Dictionary dict = new Hashtable();
-        dict.put("package", "org.eclipse.core.runtime");
-        dict.put("version", "0.0.0");
-        dict.put("common", "split");
-
-        assertTrue(filterImpl.match(dict));
-
-        dict = new Hashtable();
-        dict.put("package", "org.eclipse.core.runtime");
-        dict.put("version", "0.0.0");
-        dict.put("common", "split-wrong");
-
-        assertFalse(filterImpl.match(dict));
-    }
-
-    public void testNoneStandardLDAPOperators() throws Exception
-    {
-        FilterImpl filterImpl = FilterImpl.newInstance(
-            "(&(package=org.eclipse.core.runtime)(version>=0.0.0)(common=split)(mandatory:<*common,test))");
-
-        Dictionary dict = new Hashtable();
-        dict.put("somethindifferent", "sonstwas");
-        assertFalse(filterImpl.match(dict));
-
-        dict = new Hashtable();
-        dict.put("mandatory:", "common");
-        dict.put("package", "org.eclipse.core.runtime");
-        dict.put("version", new Version("0.0.0"));
-        dict.put("common", "split");
-        assertTrue(filterImpl.match(dict));
-
-        dict = new Hashtable();
-        dict.put("mandatory:", "common,test");
-        dict.put("package", "org.eclipse.core.runtime");
-        dict.put("version", new Version("0.0.0"));
-        dict.put("common", "split");
-        assertTrue(filterImpl.match(dict));
-
-        dict = new Hashtable();
-        dict.put("package", "org.eclipse.core.runtime");
-        dict.put("version", new Version("0.0.0"));
-        dict.put("common", "split");
-        assertTrue(filterImpl.match(dict));
-
-        filterImpl = FilterImpl.newInstance(
-            "(&(package=org.eclipse.core.runtime)(version>=0.0.0)(common=split)(mandatory:*>common))");
-        dict = new Hashtable();
-        dict.put("mandatory:", "common");
-        dict.put("package", "org.eclipse.core.runtime");
-        dict.put("version", new Version("0.0.0"));
-        dict.put("common", "split");
-        assertTrue(filterImpl.match(dict));
-
-        dict = new Hashtable();
-        dict.put("mandatory:", "common,test");
-        dict.put("package", "org.eclipse.core.runtime");
-        dict.put("version", new Version("0.0.0"));
-        dict.put("common", "split");
-        assertTrue(filterImpl.match(dict));
-
-        filterImpl = FilterImpl.newInstance(
-            "(&(package=org.eclipse.core.runtime)(version>=0.0.0)(common=split)(mandatory:*>common,test))");
-        dict = new Hashtable();
-        dict.put("mandatory:", "common");
-        dict.put("package", "org.eclipse.core.runtime");
-        dict.put("version", new Version("0.0.0"));
-        dict.put("common", "split");
-        assertFalse(filterImpl.match(dict));
-
-        dict = new Hashtable();
-        dict.put("mandatory:", "common,test");
-        dict.put("package", "org.eclipse.core.runtime");
-        dict.put("version", new Version("0.0.0"));
-        dict.put("common", "split");
-        assertTrue(filterImpl.match(dict));
-    }
-
-    public void testCaseSensitive() throws Exception
-    {
-        FilterImpl filterImpl = FilterImpl.newInstance("(&(package=org.eclipse.core.runtime))");
-
-        Dictionary dict = new Hashtable();
-        dict.put("PACKAGE", "org.eclipse.core.runtime");
-        assertTrue(filterImpl.match(dict));
-
-        dict = new Hashtable();
-        dict.put("PACKAGE", "org.eclipse.core.runtime");
-        assertFalse(filterImpl.matchCase(dict));
-    }
-
-}
\ No newline at end of file
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryAdminTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryAdminTest.java
index aa1b0ca..70e38b7 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryAdminTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryAdminTest.java
@@ -23,6 +23,8 @@
 
 import junit.framework.TestCase;
 import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.utils.filter.FilterImpl;
+import org.apache.felix.utils.log.Logger;
 import org.easymock.Capture;
 import org.easymock.EasyMock;
 import org.easymock.IAnswer;
@@ -55,6 +57,7 @@
         BundleContext bundleContext = (BundleContext) EasyMock.createMock(BundleContext.class);
         Bundle systemBundle = (Bundle) EasyMock.createMock(Bundle.class);
 
+        Activator.setContext(bundleContext);
         EasyMock.expect(bundleContext.getProperty((String) EasyMock.anyObject())).andReturn(null).anyTimes();
         EasyMock.expect(bundleContext.getBundle(0)).andReturn(systemBundle);
         EasyMock.expect(systemBundle.getHeaders()).andReturn(new Hashtable());
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryImplTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryImplTest.java
index bcf1e76..7481cdc 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryImplTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryImplTest.java
@@ -25,6 +25,7 @@
 import junit.framework.TestCase;
 import org.apache.felix.bundlerepository.Repository;
 import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.utils.log.Logger;
 import org.easymock.EasyMock;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -94,6 +95,7 @@
         BundleContext bundleContext = (BundleContext) EasyMock.createMock(BundleContext.class);
         Bundle systemBundle = (Bundle) EasyMock.createMock(Bundle.class);
 
+        Activator.setContext(bundleContext);
         EasyMock.expect(bundleContext.getProperty((String) EasyMock.anyObject())).andReturn(null).anyTimes();
         EasyMock.expect(bundleContext.getBundle(0)).andReturn(systemBundle);
         EasyMock.expect(systemBundle.getHeaders()).andReturn(new Hashtable());
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/ResolverImplTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/ResolverImplTest.java
index 8a27bd7..7bd8f6b 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/ResolverImplTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/ResolverImplTest.java
@@ -25,6 +25,8 @@
 
 import org.apache.felix.bundlerepository.Requirement;
 import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.utils.filter.FilterImpl;
+import org.apache.felix.utils.log.Logger;
 import org.easymock.Capture;
 import org.easymock.EasyMock;
 import org.easymock.IAnswer;
@@ -61,7 +63,7 @@
         repoAdmin.addRepository(getClass().getResource("/repo_for_resolvertest.xml"));
 
         Resource[] res = repoAdmin.discoverResources(
-            new Requirement[] { repoAdmin.requirement(
+            new Requirement[] { repoAdmin.getHelper().requirement(
                 "package", "(package=org.apache.felix.test.osgi)") });
         assertNotNull(res);
         assertEquals(1, res.length);
@@ -73,7 +75,7 @@
         repoAdmin.addRepository(getClass().getResource("/repo_for_resolvertest.xml"));
 
         Resolver resolver = repoAdmin.resolver();
-        resolver.add(repoAdmin.requirement("package", "(package=org.apache.felix.test.osgi)"));
+        resolver.add(repoAdmin.getHelper().requirement("package", "(package=org.apache.felix.test.osgi)"));
         assertTrue(resolver.resolve());
     }
 
@@ -83,7 +85,7 @@
         repoAdmin.addRepository(getClass().getResource("/repo_for_resolvertest.xml"));
 
         Resolver resolver = repoAdmin.resolver();
-        resolver.add(repoAdmin.requirement("package", "(package=org.apache.felix.test.osgi)"));
+        resolver.add(repoAdmin.getHelper().requirement("package", "(package=org.apache.felix.test.osgi)"));
 
         Thread.currentThread().interrupt();
         try
@@ -103,7 +105,7 @@
         repoAdmin.addRepository(getClass().getResource("/repo_for_optional_resources.xml"));
 
         Resolver resolver = repoAdmin.resolver();
-        resolver.add(repoAdmin.requirement("bundle", "(symbolicname=res1)"));
+        resolver.add(repoAdmin.getHelper().requirement("bundle", "(symbolicname=res1)"));
 
         assertTrue(resolver.resolve());
         assertEquals(1, resolver.getRequiredResources().length);
@@ -116,15 +118,15 @@
         repoAdmin.addRepository(getClass().getResource("/repo_for_mandatory.xml"));
 
         Resolver resolver = repoAdmin.resolver();
-        resolver.add(repoAdmin.requirement("bundle", "(symbolicname=res2)"));
+        resolver.add(repoAdmin.getHelper().requirement("bundle", "(symbolicname=res2)"));
         assertFalse(resolver.resolve());
 
         resolver = repoAdmin.resolver();
-        resolver.add(repoAdmin.requirement("bundle", "(symbolicname=res3)"));
+        resolver.add(repoAdmin.getHelper().requirement("bundle", "(symbolicname=res3)"));
         assertTrue(resolver.resolve());
 
         resolver = repoAdmin.resolver();
-        resolver.add(repoAdmin.requirement("bundle", "(symbolicname=res4)"));
+        resolver.add(repoAdmin.getHelper().requirement("bundle", "(symbolicname=res4)"));
         assertFalse(resolver.resolve());
 
     }
@@ -139,6 +141,7 @@
         BundleContext bundleContext = (BundleContext) EasyMock.createMock(BundleContext.class);
         Bundle systemBundle = (Bundle) EasyMock.createMock(Bundle.class);
 
+        Activator.setContext(bundleContext);
         EasyMock.expect(bundleContext.getProperty(RepositoryAdminImpl.REPOSITORY_URL_PROP))
                     .andReturn(getClass().getResource("/referred.xml").toExternalForm());
         EasyMock.expect(bundleContext.getProperty((String) EasyMock.anyObject())).andReturn(null).anyTimes();
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/StaxParserTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/StaxParserTest.java
index 3d6cf2b..e2e5725 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/StaxParserTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/StaxParserTest.java
@@ -18,13 +18,16 @@
  */
 package org.apache.felix.bundlerepository.impl;
 
-import java.io.File;
 import java.net.URL;
 import java.util.Hashtable;
 
 import junit.framework.TestCase;
+import org.apache.felix.bundlerepository.impl.PullParser;
 import org.apache.felix.bundlerepository.Resolver;
 import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.bundlerepository.impl.StaxParser;
+import org.apache.felix.utils.filter.FilterImpl;
+import org.apache.felix.utils.log.Logger;
 import org.easymock.Capture;
 import org.easymock.EasyMock;
 import org.easymock.IAnswer;
@@ -80,7 +83,7 @@
     {
         long t0, t1;
 
-        StaxParser.factory = null;
+        StaxParser.setFactory(null);
         System.setProperty("javax.xml.stream.XMLInputFactory", "com.ctc.wstx.stax.WstxInputFactory");
         for (int i = 0; i < nbWarm; i++)
         {
@@ -97,7 +100,7 @@
         System.err.println("Woodstox: " + (t1 - t0) + " ms");
 
 
-        StaxParser.factory = null;
+        StaxParser.setFactory(null);
         System.setProperty("javax.xml.stream.XMLInputFactory", "com.sun.xml.internal.stream.XMLInputFactoryImpl");
         for (int i = 0; i < nbWarm; i++)
         {
@@ -138,9 +141,10 @@
         BundleContext bundleContext = (BundleContext) EasyMock.createMock(BundleContext.class);
         Bundle systemBundle = (Bundle) EasyMock.createMock(Bundle.class);
 
+        Activator.setContext(bundleContext);
         EasyMock.expect(bundleContext.getProperty(RepositoryAdminImpl.REPOSITORY_URL_PROP))
                     .andReturn(getClass().getResource("/referral1_repository.xml").toExternalForm());
-        EasyMock.expect(bundleContext.getProperty(RepositoryImpl.OBR_PARSER_CLASS))
+        EasyMock.expect(bundleContext.getProperty(RepositoryParser.OBR_PARSER_CLASS))
                     .andReturn(repositoryParser.getName());
         EasyMock.expect(bundleContext.getProperty((String) EasyMock.anyObject())).andReturn(null).anyTimes();
         EasyMock.expect(bundleContext.getBundle(0)).andReturn(systemBundle);