FELIX-2211: Simplify the repository parser based on KXml2

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@924667 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundlerepository/pom.xml b/bundlerepository/pom.xml
index 652e0fc..9db3ee8 100644
--- a/bundlerepository/pom.xml
+++ b/bundlerepository/pom.xml
@@ -47,6 +47,12 @@
       <artifactId>kxml2</artifactId>
       <version>2.2.2</version>
       <optional>true</optional>
+      <exclusions>
+        <exclusion>
+          <groupId>xmlpull</groupId>
+          <artifactId>xmlpull</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
         <groupId>org.osgi</groupId>
@@ -81,7 +87,11 @@
         <configuration>
           <instructions>
             <Export-Package>org.apache.felix.bundlerepository;version="2.0"</Export-Package>
-            <Private-Package>org.kxml2.*,org.xmlpull.*;-split-package:=merge-first,org.apache.felix.bundlerepository.impl.*</Private-Package>
+            <Private-Package>
+                org.kxml2.io,
+                org.xmlpull.v1,
+                org.apache.felix.bundlerepository.impl.*
+            </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>
             <Bundle-Activator>${pom.artifactId}.impl.Activator</Bundle-Activator>
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
new file mode 100644
index 0000000..1a1b47b
--- /dev/null
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/PullParser.java
@@ -0,0 +1,319 @@
+/*
+ * 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.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.kxml2.io.KXmlParser;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * Repository XML parser based on StaX
+ */
+public class PullParser implements RepositoryImpl.RepositoryParser
+{
+
+    public PullParser()
+    {
+    }
+
+    public void parse(RepositoryImpl repository, InputStream is) throws Exception
+    {
+        KXmlParser reader = new KXmlParser();
+        reader.setInput(new BufferedReader(new InputStreamReader(is)));
+        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");
+        }
+        for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
+        {
+            String name = reader.getAttributeName(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()) == XmlPullParser.START_TAG)
+        {
+            String element = reader.getName();
+            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);
+    }
+
+    private void sanityCheckEndElement(KXmlParser reader, int event, String element)
+    {
+        if (event != XmlPullParser.END_TAG || !element.equals(reader.getName()))
+        {
+            throw new IllegalStateException("Unexpected state while finishing element " + element);
+        }
+    }
+
+    private Referral parseReferral(KXmlParser reader) throws Exception
+    {
+        Referral referral = new Referral();
+        for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
+        {
+            String name = reader.getAttributeName(i);
+            String value = reader.getAttributeValue(i);
+            if (DEPTH.equals(name))
+            {
+                referral.setDepth(value);
+            }
+            else if (URL.equals(name))
+            {
+                referral.setUrl(value);
+            }
+        }
+        sanityCheckEndElement(reader, reader.nextTag(), REFERRAL);
+        return referral;
+    }
+
+    private ResourceImpl parseResource(KXmlParser reader) throws Exception
+    {
+        ResourceImpl resource = new ResourceImpl();
+        try
+        {
+            for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
+            {
+                resource.put(reader.getAttributeName(i), reader.getAttributeValue(i));
+            }
+            int event;
+            while ((event = reader.nextTag()) == XmlPullParser.START_TAG)
+            {
+                String element = reader.getName();
+                if (CATEGORY.equals(element))
+                {
+                    CategoryImpl category = parseCategory(reader);
+                    resource.addCategory(category);
+                }
+                else if (CAPABILITY.equals(element))
+                {
+                    CapabilityImpl capability = parseCapability(reader);
+                    resource.addCapability(capability);
+                }
+                else if (REQUIRE.equals(element))
+                {
+                    RequirementImpl requirement = parseRequire(reader);
+                    resource.addRequire(requirement);
+                }
+                else
+                {
+                    StringBuffer sb = null;
+                    String type = reader.getAttributeValue(null, "type");
+                    while ((event = reader.next()) != XmlPullParser.END_TAG)
+                    {
+                        switch (event)
+                        {
+                            case XmlPullParser.START_TAG:
+                                throw new Exception("Unexpected element inside <require/> element");
+                            case XmlPullParser.TEXT:
+                                if (sb == null)
+                                {
+                                    sb = new StringBuffer();
+                                }
+                                sb.append(reader.getText());
+                                break;
+                        }
+                    }
+                    if (sb != null)
+                    {
+                        resource.put(element, sb.toString().trim(), type);
+                    }
+                }
+            }
+            // Sanity check
+            if (event != XmlPullParser.END_TAG || !RESOURCE.equals(reader.getName()))
+            {
+                throw new Exception("Unexpected state");
+            }
+            return resource;
+        }
+        catch (Exception e)
+        {
+            throw new Exception("Error while parsing resource " + resource.getId() + " at line " + reader.getLineNumber() + " and column " + reader.getColumnNumber(), e);
+        }
+    }
+
+    private CategoryImpl parseCategory(KXmlParser reader) throws IOException, XmlPullParserException
+    {
+        CategoryImpl category = new CategoryImpl();
+        for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
+        {
+            if (ID.equals(reader.getAttributeName(i)))
+            {
+                category.setId(reader.getAttributeValue(i));
+            }
+        }
+        sanityCheckEndElement(reader, reader.nextTag(), CATEGORY);
+        return category;
+    }
+
+    private CapabilityImpl parseCapability(KXmlParser reader) throws Exception
+    {
+        CapabilityImpl capability = new CapabilityImpl();
+        for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
+        {
+            String name = reader.getAttributeName(i);
+            String value = reader.getAttributeValue(i);
+            if (NAME.equals(name))
+            {
+                capability.setName(value);
+            }
+        }
+        int event;
+        while ((event = reader.nextTag()) == XmlPullParser.START_TAG)
+        {
+            String element = reader.getName();
+            if (P.equals(element))
+            {
+                PropertyImpl prop = parseProperty(reader);
+                capability.addP(prop);
+            }
+            else
+            {
+                ignoreTag(reader);
+            }
+        }
+        // Sanity check
+        sanityCheckEndElement(reader, event, CAPABILITY);
+        return capability;
+    }
+
+    private PropertyImpl parseProperty(KXmlParser reader) throws Exception
+    {
+        String n = null, t = null, v = null;
+        for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
+        {
+            String name = reader.getAttributeName(i);
+            String value = reader.getAttributeValue(i);
+            if (N.equals(name))
+            {
+                n = value;
+            }
+            else if (T.equals(name))
+            {
+                t = value;
+            }
+            else if (V.equals(name))
+            {
+                v = value;
+            }
+        }
+        PropertyImpl prop = new PropertyImpl(n, t, v);
+        // Sanity check
+        sanityCheckEndElement(reader, reader.nextTag(), P);
+        return prop;
+    }
+
+    private RequirementImpl parseRequire(KXmlParser reader) throws Exception
+    {
+        RequirementImpl requirement = new RequirementImpl();
+        for (int i = 0, nb = reader.getAttributeCount(); i < nb; i++)
+        {
+            String name = reader.getAttributeName(i);
+            String value = reader.getAttributeValue(i);
+            if (NAME.equals(name))
+            {
+                requirement.setName(value);
+            }
+            else if (FILTER.equals(name))
+            {
+                requirement.setFilter(value);
+            }
+            else if (EXTEND.equals(name))
+            {
+                requirement.setExtend(value);
+            }
+            else if (MULTIPLE.equals(name))
+            {
+                requirement.setMultiple(value);
+            }
+            else if (OPTIONAL.equals(name))
+            {
+                requirement.setOptional(value);
+            }
+        }
+        int event;
+        StringBuffer sb = null;
+        while ((event = reader.next()) != XmlPullParser.END_TAG)
+        {
+            switch (event)
+            {
+                case XmlPullParser.START_TAG:
+                    throw new Exception("Unexpected element inside <require/> element");
+                case XmlPullParser.TEXT:
+                    if (sb == null)
+                    {
+                        sb = new StringBuffer();
+                    }
+                    sb.append(reader.getText());
+                    break;
+            }
+        }
+        if (sb != null)
+        {
+            requirement.addText(sb.toString());
+        }
+        // Sanity check
+        sanityCheckEndElement(reader, event, REQUIRE);
+        return requirement;
+    }
+
+    private void ignoreTag(KXmlParser reader) throws IOException, XmlPullParserException {
+        int level = 1;
+        int event = 0;
+        while (level > 0)
+        {
+            event = reader.next();
+            if (event == XmlPullParser.START_TAG)
+            {
+                level++;
+            }
+            else if (event == XmlPullParser.END_TAG)
+            {
+                level--;
+            }
+        }
+    }
+}
\ 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 db8af53..4518f5a 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
@@ -39,8 +39,6 @@
 import org.apache.felix.bundlerepository.Capability;
 import org.apache.felix.bundlerepository.Requirement;
 import org.apache.felix.bundlerepository.Resource;
-import org.apache.felix.bundlerepository.impl.metadataparser.XmlCommonHandler;
-import org.apache.felix.bundlerepository.impl.metadataparser.kxmlsax.KXml2SAXParser;
 import org.apache.felix.bundlerepository.Repository;
 
 public class RepositoryImpl implements Repository
@@ -287,7 +285,7 @@
         }
         if (parser == null)
         {
-            parser = new KXml2Parser();
+            parser = new PullParser();
 
         }
         parser.parse(this, is);
@@ -295,45 +293,27 @@
 
     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;
     }
 
-    public static class KXml2Parser implements RepositoryParser
-    {
-        public void parse(final RepositoryImpl repository, final InputStream is) throws Exception
-        {
-            BufferedReader br;// Create the parser Kxml
-            XmlCommonHandler handler = new XmlCommonHandler(repository.m_logger);
-            Object factory = new Object()
-            {
-                public RepositoryImpl newInstance()
-                {
-                    return repository;
-                }
-            };
-
-            // Get default setter method for Repository.
-            Method repoSetter = RepositoryImpl.class.getDeclaredMethod(
-                "put", new Class[] { Object.class, Object.class });
-
-            // Get default setter method for Resource.
-            Method resSetter = ResourceImpl.class.getDeclaredMethod(
-                "put", new Class[] { Object.class, Object.class });
-
-            // Map XML tags to types.
-            handler.addType("repository", factory, Repository.class, repoSetter);
-            handler.addType("referral", Referral.class, null, null);
-            handler.addType("resource", ResourceImpl.class, Resource.class, resSetter);
-            handler.addType("category", CategoryImpl.class, null, null);
-            handler.addType("require", RequirementImpl.class, Requirement.class, null);
-            handler.addType("capability", CapabilityImpl.class, Capability.class, null);
-            handler.addType("p", PropertyImpl.class, null, null);
-            handler.setDefaultType(String.class, null, null);
-
-            br = new BufferedReader(new InputStreamReader(is));
-            KXml2SAXParser parser;
-            parser = new KXml2SAXParser(br);
-            parser.parseXML(handler);
-        }
-    }
 }
\ No newline at end of file
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 e13fe3d..450c9ac 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
@@ -30,25 +30,6 @@
  */
 public class StaxParser implements RepositoryImpl.RepositoryParser
 {
-    private static final String REPOSITORY = "repository";
-    private static final String NAME = "name";
-    private static final String LASTMODIFIED = "lastmodified";
-    private static final String REFERRAL = "referral";
-    private static final String RESOURCE = "resource";
-    private static final String DEPTH = "depth";
-    private static final String URL = "url";
-    private static final String CATEGORY = "category";
-    private static final String ID = "id";
-    private static final String CAPABILITY = "capability";
-    private static final String REQUIRE = "require";
-    private static final String P = "p";
-    private static final String N = "n";
-    private static final String T = "t";
-    private static final String V = "v";
-    private static final String FILTER = "filter";
-    private static final String EXTEND = "extend";
-    private static final String MULTIPLE = "multiple";
-    private static final String OPTIONAL = "optional";
 
     static XMLInputFactory factory;
 
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/ClassUtility.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/ClassUtility.java
deleted file mode 100644
index 5764068..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/ClassUtility.java
+++ /dev/null
@@ -1,136 +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.metadataparser;
-
-/**
- * This class provides methods to process class name
- */
-public class ClassUtility
-{
-    /**
-     * This method capitalizes the first character in the provided string.
-     * @return resulted string
-     */
-    public static String capitalize(String name)
-    {
-        int len = name.length();
-        StringBuffer sb = new StringBuffer(len);
-        boolean setCap = true;
-        for (int i = 0; i < len; i++)
-        {
-            char c = name.charAt(i);
-            if (c == '-' || c == '_')
-            {
-                setCap = true;
-            }
-            else
-            {
-                if (setCap)
-                {
-                    sb.append(Character.toUpperCase(c));
-                    setCap = false;
-                }
-                else
-                {
-                    sb.append(c);
-                }
-            }
-        }
-
-        return sb.toString();
-    }
-
-    /**
-     * This method minusculizes all characters in the provided string.
-     * @return resulted string
-     */
-    public static String toLowerCase(String name)
-    {
-        int len = name.length();
-        StringBuffer sb = new StringBuffer(len);
-        for (int i = 0; i < len; i++)
-        {
-            char c = name.charAt(i);
-            sb.append(Character.toLowerCase(c));
-        }
-        return sb.toString();
-    }
-
-    /**
-     * This method capitalizes all characters in the provided string.
-     * @return resulted string
-     */
-    public static String finalstaticOf(String membername)
-    {
-        int len = membername.length();
-        StringBuffer sb = new StringBuffer(len + 2);
-        for (int i = 0; i < len; i++)
-        {
-            char c = membername.charAt(i);
-            if (Character.isLowerCase(c))
-            {
-                sb.append(Character.toUpperCase(c));
-            }
-            else if (Character.isUpperCase(c))
-            {
-                sb.append('_').append(c);
-            }
-            else
-            {
-                sb.append(c);
-            }
-        }
-
-        return sb.toString();
-    }
-
-    /**
-     * This method returns the package name in a full class name
-     * @return resulted string
-     */
-    public static String packageOf(String fullclassname)
-    {
-        int index = fullclassname.lastIndexOf(".");
-        if (index > 0)
-        {
-            return fullclassname.substring(0, index);
-        }
-        else
-        {
-            return "";
-        }
-    }
-
-    /**
-     * This method returns the package name in a full class name
-     * @return resulted string
-     */
-    public static String classOf(String fullclassname)
-    {
-        int index = fullclassname.lastIndexOf(".");
-        if (index > 0)
-        {
-            return fullclassname.substring(index + 1);
-        }
-        else
-        {
-            return fullclassname;
-        }
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/KXml2MetadataHandler.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/KXml2MetadataHandler.java
deleted file mode 100644
index 0e48a1f..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/KXml2MetadataHandler.java
+++ /dev/null
@@ -1,47 +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.metadataparser;
-
-import java.io.*;
-
-import org.apache.felix.bundlerepository.impl.Logger;
-import org.apache.felix.bundlerepository.impl.metadataparser.kxmlsax.KXml2SAXParser;
-
-/**
- * handles the metadata in XML format
- * (use kXML (http://kxml.enhydra.org/) a open-source very light weight XML parser
- */
-public class KXml2MetadataHandler extends MetadataHandler
-{
-    public KXml2MetadataHandler(Logger logger)
-    {
-        super(logger);
-    }
-
-    /**
-     * Called to parse the InputStream and set bundle list and package hash map
-     */
-    public void parse(InputStream is) throws Exception
-    {
-        BufferedReader br = new BufferedReader(new InputStreamReader(is));
-        KXml2SAXParser parser;
-        parser = new KXml2SAXParser(br);
-        parser.parseXML(m_handler);
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/MappingProcessingInstructionHandler.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/MappingProcessingInstructionHandler.java
deleted file mode 100644
index 4387108..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/MappingProcessingInstructionHandler.java
+++ /dev/null
@@ -1,57 +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.metadataparser;
-
-/**
- * this class adds type of elements to the parser
- */
-public class MappingProcessingInstructionHandler
-{
-    private XmlCommonHandler m_handler;
-    private String m_name;
-    private String m_classname;
-
-    public MappingProcessingInstructionHandler(XmlCommonHandler handler)
-    {
-        m_handler = handler;
-    }
-
-    public void process() throws Exception
-    {
-        if (m_name == null)
-        {
-            throw new Exception("element is missing");
-        }
-        if (m_classname == null)
-        {
-            throw new Exception("class is missing");
-        }
-        m_handler.addType(m_name, getClass().getClassLoader().loadClass(m_classname), null, null);
-    }
-
-    public void setElement(String element)
-    {
-        m_name = element;
-    }
-
-    public void setClass(String classname)
-    {
-        m_classname = classname;
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/MetadataHandler.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/MetadataHandler.java
deleted file mode 100644
index 4994022..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/MetadataHandler.java
+++ /dev/null
@@ -1,150 +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.metadataparser;
-
-import org.apache.felix.bundlerepository.impl.Logger;
-
-import java.io.InputStream;
-import java.lang.reflect.Method;
-
-public abstract class MetadataHandler
-{
-    protected XmlCommonHandler m_handler;
-
-    /**
-     * constructor 
-     *
-     */
-    public MetadataHandler(Logger logger)
-    {
-        m_handler = new XmlCommonHandler(logger);
-    }
-
-    /**
-     * Called to parse the InputStream and set bundle list and package hash map
-     */
-    public abstract void parse(InputStream is) throws Exception;
-
-    /**
-     * return the metadata after the parsing
-     * @return a Object. Its class is the returned type of instanceFactory newInstance method for the root element of the XML document.
-     */
-    public final Object getMetadata()
-    {
-        return m_handler.getRoot();
-    }
-
-    /**
-     * Add a type for a element
-     * @param qname the name of the element to process
-     * @param instanceFactory the factory of objects representing an element. Must have a newInstance method. could be a class.
-     * @throws Exception
-     */
-    public final void addType(String qname, Object instanceFactory) throws Exception
-    {
-        m_handler.addType(qname, instanceFactory, null, null);
-    }
-
-    /**
-     * Add a type for a element
-     * @param qname the name of the element to process
-     * @param instanceFactory the factory of objects representing an element. Must have a newInstance method. could be a class.
-     * @param castClass the class used to introspect the adder/setter and parameters in parent adder/setter. if null the castClass is by default the class returned by the newInstance method of the instanceFactory.
-     * @throws Exception
-     */
-    public final void addType(String qname, Object instanceFactory, Class castClass) throws Exception
-    {
-        m_handler.addType(qname, instanceFactory, castClass, null);
-    }
-
-    /**
-     * Add a type for a element
-     * @param qname the name of the element to process
-     * @param instanceFactory the factory of objects representing an element. Must have a newInstance method. could be a class.
-     * @param castClass the class used to introspect the adder/setter and parameters in parent adder/setter. if null the castClass is by default the class returned by the newInstance method of the instanceFactory.
-     * @param defaultAddMethod the method used to add the sub-elements and attributes if no adder/setter is founded. could be omitted.
-     * @throws Exception
-     */
-    public final void addType(String qname, Object instanceFactory, Class castClass, Method defaultAddMethod) throws Exception
-    {
-        m_handler.addType(qname, instanceFactory, castClass, defaultAddMethod);
-    }
-
-    /**
-     * Add a type for the default element
-     * @param instanceFactory the factory of objects representing an element. Must have a newInstance method. could be a class.
-     * @throws Exception
-     */
-    public final void setDefaultType(Object instanceFactory) throws Exception
-    {
-        m_handler.setDefaultType(instanceFactory, null, null);
-    }
-
-    /**
-     * Add a type for the default element
-     * @param instanceFactory the factory of objects representing an element. Must have a newInstance method. could be a class.
-     * @param castClass the class used to introspect the adder/setter and parameters in parent adder/setter. if null the castClass is by default the class returned by the newInstance method of the instanceFactory.
-     * @throws Exception
-     */
-    public final void setDefaultType(Object instanceFactory, Class castClass) throws Exception
-    {
-        m_handler.setDefaultType(instanceFactory, castClass, null);
-    }
-
-    /**
-     * Add a type for the default element
-     * @param instanceFactory the factory of objects representing an element. Must have a newInstance method. could be a class.
-     * @param castClass the class used to introspect the adder/setter and parameters in parent adder/setter. if null the castClass is by default the class returned by the newInstance method of the instanceFactory.
-     * @param defaultAddMethod the method used to add the sub-elements and attributes if no adder/setter is founded. could be omitted.
-     * @throws Exception
-     */
-    public final void setDefaultType(Object instanceFactory, Class castClass, Method defaultAddMethod) throws Exception
-    {
-        m_handler.setDefaultType(instanceFactory, castClass, defaultAddMethod);
-    }
-
-    /**
-     * Add a type to process the processing instruction
-     * @param piname
-     * @param clazz
-     */
-    public final void addPI(String piname, Class clazz)
-    {
-        m_handler.addPI(piname, clazz);
-    }
-
-    /**
-     * set the missing PI exception flag. If during parsing, the flag is true and the processing instruction is unknown, then the parser throws a exception  
-     * @param flag
-     */
-    public final void setMissingPIExceptionFlag(boolean flag)
-    {
-        m_handler.setMissingPIExceptionFlag(flag);
-    }
-
-    /**
-     * 
-     * @param trace
-     * @since 0.9.1
-     */
-    public final void setTrace(boolean trace)
-    {
-        m_handler.setTrace(trace);
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/ReplaceUtility.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/ReplaceUtility.java
deleted file mode 100644
index 26cb4d4..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/ReplaceUtility.java
+++ /dev/null
@@ -1,82 +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.metadataparser;
-
-import java.util.Map;
-
-/**
- * This class provides methods to replace ${var} substring by values stored in a map
- */
-public class ReplaceUtility
-{
-    /**
-     * This method replaces ${var} substring by values stored in a map.
-     * @return resulted string
-     */
-    public static String replace(String str, Map values)
-    {
-        int len = str.length();
-        StringBuffer sb = new StringBuffer(len);
-
-        int prev = 0;
-        int start = str.indexOf("${");
-        int end = str.indexOf("}", start);
-        while (start != -1 && end != -1)
-        {
-            String key = str.substring(start + 2, end);
-            Object value = values.get(key);
-            if (value != null)
-            {
-                sb.append(str.substring(prev, start));
-                sb.append(value);
-            }
-            else
-            {
-                sb.append(str.substring(prev, end + 1));
-            }
-            prev = end + 1;
-            if (prev >= str.length())
-            {
-                break;
-            }
-            start = str.indexOf("${", prev);
-            if (start != -1)
-            {
-                end = str.indexOf("}", start);
-            }
-        }
-
-        sb.append(str.substring(prev));
-
-        return sb.toString();
-    }
-
-    //	public static void main(String[] args){
-    //		Map map=new HashMap();
-    //		map.put("foo","FOO");
-    //		map.put("bar","BAR");
-    //		map.put("map",map);
-    //				
-    //		String str;
-    //		if(args.length==0) str=""; else str=args[0];
-    //		
-    //		System.out.println(replace(str,map));
-    //		
-    //	}
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/XmlCommonHandler.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/XmlCommonHandler.java
deleted file mode 100644
index 6920a98..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/XmlCommonHandler.java
+++ /dev/null
@@ -1,1021 +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.metadataparser;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.*;
-
-import org.apache.felix.bundlerepository.impl.Logger;
-import org.apache.felix.bundlerepository.impl.metadataparser.kxmlsax.KXml2SAXHandler;
-import org.xml.sax.SAXException;
-
-/**
- * SAX handler for the XML file
- */
-public class XmlCommonHandler implements KXml2SAXHandler
-{
-    private static final String PI_MAPPING = "mapping";
-    public static final String METADATAPARSER_PIS = "METADATAPARSER_PIS";
-    public static final String METADATAPARSER_TYPES = "METADATAPARSER_TYPES";
-    private int m_columnNumber;
-    private int m_lineNumber;
-    private boolean m_traceFlag = false;
-    private static String VALUE = "value";
-
-    //
-    // Data
-    //
-    private XmlStackElement m_root;
-    private Stack m_elementStack;
-    private Map m_pis;
-    private boolean m_missingPIExceptionFlag;
-    private Map m_types;
-    private TypeEntry m_defaultType;
-    private StringBuffer m_currentText;
-    private Map m_context;
-    private final Logger m_logger;
-
-    private class XmlStackElement
-    {
-        public final String m_qname;
-        public Object m_object;
-
-        public XmlStackElement(String qname, Object object)
-        {
-            super();
-            m_qname = qname;
-            m_object = object;
-        }
-    }
-
-    public class TypeEntry
-    {
-        public final Object m_instanceFactory;
-        public final Class m_instanceClass;
-        public final Method m_newInstanceMethod;
-        public final Class m_castClass;
-        public final Method m_defaultAddMethod;
-
-        public TypeEntry(Object instanceFactory, Class castClass, Method defaultAddMethod) throws Exception
-        {
-            super();
-            m_instanceFactory = instanceFactory;
-
-            try
-            {
-                if (instanceFactory instanceof Class)
-                {
-                    m_newInstanceMethod = instanceFactory.getClass().getDeclaredMethod("newInstance", null);
-                    if (castClass == null)
-                    {
-                        m_castClass = (Class) instanceFactory;
-                    }
-                    else
-                    {
-                        if (!castClass.isAssignableFrom((Class) instanceFactory))
-                        {
-                            throw new Exception(
-                                "instanceFactory " + instanceFactory.getClass().getName() + " could not instanciate objects assignable to " + castClass.getName());
-                        }
-                        m_castClass = castClass;
-                    }
-                    m_instanceClass = (Class) instanceFactory;
-                }
-                else
-                {
-                    m_newInstanceMethod = instanceFactory.getClass().getDeclaredMethod("newInstance", null);
-                    Class returnType = m_newInstanceMethod.getReturnType();
-                    if (castClass == null)
-                    {
-                        m_castClass = returnType;
-                    }
-                    else if (!castClass.isAssignableFrom(returnType))
-                    {
-                        throw new Exception(
-                            "instanceFactory " + instanceFactory.getClass().getName() + " could not instanciate objects assignable to " + castClass.getName());
-                    }
-                    else
-                    {
-                        m_castClass = castClass;
-                    }
-                    m_instanceClass = returnType;
-                }
-            }
-            catch (NoSuchMethodException e)
-            {
-                throw new Exception(
-                    "instanceFactory " + instanceFactory.getClass().getName() + " should have a newInstance method");
-            }
-
-            // TODO check method
-            m_defaultAddMethod = defaultAddMethod;
-            if (m_defaultAddMethod != null)
-            {
-                m_defaultAddMethod.setAccessible(true);
-            }
-        }
-
-        public String toString()
-        {
-            StringBuffer sb = new StringBuffer();
-            sb.append("[");
-            if (m_instanceFactory instanceof Class)
-            {
-                sb.append("instanceFactory=").append(((Class) m_instanceFactory).getName());
-            }
-            else
-            {
-                sb.append("instanceFactory=").append(m_instanceFactory.getClass().getName());
-            }
-            sb.append(",instanceClass=").append(m_instanceClass.getName());
-            sb.append(",castClass=").append(m_castClass.getName());
-            sb.append(",defaultAddMethod=");
-            if (m_defaultAddMethod == null)
-            {
-                sb.append("");
-            }
-            else
-            {
-                sb.append(m_defaultAddMethod.getName());
-            }
-            sb.append("]");
-            return sb.toString();
-        }
-    }
-
-    public XmlCommonHandler(Logger logger)
-    {
-        m_logger = logger;
-        m_elementStack = new Stack();
-        m_pis = new HashMap();
-        m_missingPIExceptionFlag = false;
-        m_types = new HashMap();
-        m_context = new HashMap();
-        m_context.put(METADATAPARSER_PIS, m_pis);
-        m_context.put(METADATAPARSER_TYPES, m_types);
-    }
-
-    public void addPI(String piname, Class clazz)
-    {
-        m_pis.put(piname, clazz);
-    }
-
-    /**
-     * set the missing PI exception flag. If during parsing, the flag is true
-     * and the processing instruction is unknown, then the parser throws a
-     * exception
-     * 
-     * @param flag
-     */
-    public void setMissingPIExceptionFlag(boolean flag)
-    {
-        m_missingPIExceptionFlag = flag;
-    }
-
-    public void addType(String qname, Object instanceFactory, Class castClass, Method defaultAddMethod)
-        throws Exception
-    {
-
-        TypeEntry typeEntry;
-        try
-        {
-            typeEntry = new TypeEntry(
-                instanceFactory,
-                castClass,
-                defaultAddMethod);
-        }
-        catch (Exception e)
-        {
-            throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + qname + " : " + e.getMessage());
-        }
-        m_types.put(qname, typeEntry);
-        trace("element " + qname + " : " + typeEntry.toString());
-    }
-
-    public void setDefaultType(Object instanceFactory, Class castClass, Method defaultAddMethod)
-        throws Exception
-    {
-        TypeEntry typeEntry;
-        try
-        {
-            typeEntry = new TypeEntry(
-                instanceFactory,
-                castClass,
-                defaultAddMethod);
-        }
-        catch (Exception e)
-        {
-            throw new Exception(m_lineNumber + "," + m_columnNumber + ": default element : " + e.getMessage());
-        }
-        m_defaultType = typeEntry;
-        trace("default element " + " : " + typeEntry.toString());
-    }
-
-    public void setContext(Map context)
-    {
-        m_context = context;
-    }
-
-    public Map getContext()
-    {
-        return m_context;
-    }
-
-    public Object getRoot()
-    {
-        return m_root.m_object;
-    }
-
-    /* for PCDATA */
-    public void characters(char[] ch, int offset, int length) throws Exception
-    {
-        if (m_currentText != null)
-        {
-            m_currentText.append(ch, offset, length);
-        }
-    }
-
-    private String adderOf(Class clazz)
-    {
-        return "add" + ClassUtility.capitalize(ClassUtility.classOf(clazz.getName()));
-    }
-
-    private String adderOf(String key)
-    {
-        return "add" + ClassUtility.capitalize(key);
-    }
-
-    private String setterOf(Class clazz)
-    {
-        return "set" + ClassUtility.capitalize(ClassUtility.classOf(clazz.getName()));
-    }
-
-    private String setterOf(String key)
-    {
-        return "set" + ClassUtility.capitalize(key);
-    }
-
-    /**
-     * set the parser context in a object
-     */
-    private void setObjectContext(Object object)
-        throws IllegalArgumentException, IllegalAccessException,
-        InvocationTargetException
-    {
-        Method method = null;
-        try
-        {
-            // TODO setContext from castClass or object.getClass() ?
-            method = object.getClass().getDeclaredMethod("setContext",
-                new Class[]
-                {
-                    Map.class
-                });
-        }
-        catch (NoSuchMethodException e)
-        {
-            // do nothing
-        }
-        if (method != null)
-        {
-            trace(method.getName());
-            try
-            {
-                method.invoke(object, new Object[]
-                    {
-                        m_context
-                    });
-            }
-            catch (InvocationTargetException e)
-            {
-                m_logger.log(Logger.LOG_ERROR, "Error parsing repository metadata", e.getTargetException());
-                throw e;
-            }
-        }
-    }
-
-    /**
-     * set the parser context in a object
-     * 
-     * @throws Throwable
-     */
-    private void invokeProcess(Object object) throws Throwable
-    {
-        Method method = null;
-        try
-        {
-            // TODO process from castClass or object.getClass() ?
-            method = object.getClass().getDeclaredMethod("process", null);
-        }
-        catch (NoSuchMethodException e)
-        {
-            // do nothing
-        }
-        if (method != null)
-        {
-            trace(method.getName());
-            try
-            {
-                method.invoke(object, null);
-            }
-            catch (InvocationTargetException e)
-            {
-                // m_logger.log(Logger.LOG_ERROR, "Error parsing repository metadata", e.getTargetException());
-                throw e.getTargetException();
-            }
-        }
-    }
-
-    /**
-     * set the parent in a object
-     */
-    private void setObjectParent(Object object, Object parent)
-        throws InvocationTargetException, IllegalArgumentException,
-        IllegalAccessException
-    {
-        Method method = null;
-        try
-        {
-            // TODO setParent from castClass or object.getClass() ?
-            method = object.getClass().getDeclaredMethod("setParent",
-                new Class[]
-                {
-                    parent.getClass()
-                });
-        }
-        catch (NoSuchMethodException e)
-        {
-            // do nothing
-        }
-        if (method != null)
-        {
-            trace(method.getName());
-            try
-            {
-                method.invoke(object, new Object[]
-                    {
-                        parent
-                    });
-            }
-            catch (InvocationTargetException e)
-            {
-                m_logger.log(Logger.LOG_ERROR, "Error parsing repository metadata", e.getTargetException());
-                throw e;
-            }
-        }
-    }
-
-    /**
-     * Method called when a tag opens
-     * 
-     * @param uri
-     * @param localName
-     * @param qName
-     * @param attrib
-     * @exception SAXException
-     */
-    public void startElement(String uri, String localName, String qName,
-        Properties attrib) throws Exception
-    {
-
-        trace("START (" + m_lineNumber + "," + m_columnNumber + "):" + uri + ":" + qName);
-
-        // TODO: should add uri in the qname in the future
-        TypeEntry type = (TypeEntry) m_types.get(qName);
-        if (type == null)
-        {
-            type = m_defaultType;
-        }
-
-        Object obj = null;
-        if (type != null)
-        {
-
-            try
-            {
-                // enables to access to "unmuttable" method
-                type.m_newInstanceMethod.setAccessible(true);
-                obj = type.m_newInstanceMethod.invoke(type.m_instanceFactory, null);
-            }
-            catch (InvocationTargetException e)
-            {
-                m_logger.log(Logger.LOG_ERROR, "Error parsing repository metadata", e.getTargetException());
-            }
-
-            // set parent
-            if (!m_elementStack.isEmpty())
-            {
-                XmlStackElement parent = (XmlStackElement) m_elementStack.peek();
-                setObjectParent(obj, parent.m_object);
-            }
-
-            // set the parser context
-            setObjectContext(obj);
-
-            // set the attributes
-            Set keyset = attrib.keySet();
-            Iterator iter = keyset.iterator();
-            while (iter.hasNext())
-            {
-                String key = (String) iter.next();
-
-                // substitute ${property} sbustrings by context' properties
-                // values
-                String value = ReplaceUtility.replace((String) attrib.get(key),
-                    m_context);
-
-                // Firstly, test if the getter or the adder exists
-
-                Method method = null;
-                if (!(obj instanceof String))
-                {
-                    try
-                    {
-                        // method = castClass.getDeclaredMethod(setterOf(key),new
-                        // Class[] { String.class });
-                        method = type.m_instanceClass.getDeclaredMethod(setterOf(key),
-                            new Class[]
-                            {
-                                String.class
-                            });
-                    }
-                    catch (NoSuchMethodException e)
-                    {
-                        // do nothing
-                    }
-                    if (method == null)
-                    {
-                        try
-                        {
-                            method = type.m_instanceClass.getDeclaredMethod(adderOf(key),
-                                new Class[]
-                                {
-                                    String.class
-                                });
-
-                        }
-                        catch (NoSuchMethodException e)
-                        {
-                            /*
-                             * throw new Exception(lineNumber + "," +
-                             * columnNumber + ":" + "element " + qName + " does
-                             * not support the attribute " + key);
-                             */
-                        }
-                    }
-                }
-
-                if (method != null)
-                {
-                    trace(method.getName());
-                    try
-                    {
-                        method.invoke(obj, new String[]
-                            {
-                                value
-                            });
-                    }
-                    catch (InvocationTargetException e)
-                    {
-                        m_logger.log(Logger.LOG_ERROR, "Error parsing repository metadata", e.getTargetException());
-                        throw e;
-                    }
-                }
-                else
-                {
-
-                    if (obj instanceof String)
-                    {
-                        if (key.equals(VALUE))
-                        {
-                            obj = value;
-                        }
-                        else
-                        {
-                            throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + "String element " + qName + " cannot have other attribute than value");
-                        }
-                    }
-                    else
-                    {
-                        if (type.m_defaultAddMethod != null)
-                        {
-                            Class[] parameterTypes = type.m_defaultAddMethod.getParameterTypes();
-                            if (parameterTypes.length == 2 && parameterTypes[0].isAssignableFrom(String.class) && parameterTypes[1].isAssignableFrom(String.class))
-                            {
-                                type.m_defaultAddMethod.invoke(obj, new String[]
-                                    {
-                                        key, value
-                                    });
-                            }
-                            else if (parameterTypes.length == 1 && parameterTypes[0].isAssignableFrom(String.class))
-                            {
-                                type.m_defaultAddMethod.invoke(obj, new String[]
-                                    {
-                                        value
-                                    });
-                            }
-                            else
-                            {
-                                throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + "class " + type.m_instanceFactory.getClass().getName() + " for element " + qName + " does not support the attribute " + key);
-                            }
-                        }
-                        else
-                        {
-                            throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + "class " + type.m_instanceFactory.getClass().getName() + " for element " + qName + " does not support the attribute " + key);
-                        }
-                    }
-                }
-            }
-        }
-        else
-        {
-            throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + "this element " + qName + " has not corresponding class");
-        }
-        XmlStackElement element = new XmlStackElement(qName, obj);
-        if (m_root == null)
-        {
-            m_root = element;
-        }
-        m_elementStack.push(element);
-        m_currentText = new StringBuffer();
-
-        trace("START/ (" + m_lineNumber + "," + m_columnNumber + "):" + uri + ":" + qName);
-    }
-
-    /**
-     * Method called when a tag closes
-     * 
-     * @param uri
-     * @param localName
-     * @param qName
-     * @exception SAXException
-     */
-    public void endElement(java.lang.String uri, java.lang.String localName,
-        java.lang.String qName) throws Exception
-    {
-
-        trace("END (" + m_lineNumber + "," + m_columnNumber + "):" + uri + ":" + qName);
-
-        XmlStackElement element = (XmlStackElement) m_elementStack.pop();
-        TypeEntry elementType = (TypeEntry) m_types.get(element.m_qname);
-        if (elementType == null)
-        {
-            elementType = m_defaultType;
-        }
-
-        if (m_currentText != null && m_currentText.length() != 0)
-        {
-
-            String currentStr = ReplaceUtility.replace(m_currentText.toString(),
-                m_context).trim();
-            // TODO: trim may be not the right choice
-            trace("current text:" + currentStr);
-
-            Method method = null;
-            try
-            {
-                method = elementType.m_castClass.getDeclaredMethod("addText",
-                    new Class[]
-                    {
-                        String.class
-                    });
-            }
-            catch (NoSuchMethodException e)
-            {
-                try
-                {
-                    method = elementType.m_castClass.getDeclaredMethod("setText",
-                        new Class[]
-                        {
-                            String.class
-                        });
-                }
-                catch (NoSuchMethodException e2)
-                {
-                    // do nothing
-                }
-            }
-            if (method != null)
-            {
-                trace(method.getName());
-                try
-                {
-                    method.invoke(element.m_object, new String[]
-                        {
-                            currentStr
-                        });
-                }
-                catch (InvocationTargetException e)
-                {
-                    m_logger.log(Logger.LOG_ERROR, "Error parsing repository metadata", e.getTargetException());
-                    throw e;
-                }
-            }
-            else
-            {
-                if (String.class.isAssignableFrom(elementType.m_castClass))
-                {
-                    String str = (String) element.m_object;
-                    if (str.length() != 0)
-                    {
-                        throw new Exception(
-                            m_lineNumber + "," + m_columnNumber + ":" + "String element " + qName + " cannot have both PCDATA and an attribute value");
-                    }
-                    else
-                    {
-                        element.m_object = currentStr;
-                    }
-                }
-            }
-        }
-
-        m_currentText = null;
-
-        if (!m_elementStack.isEmpty())
-        {
-
-            XmlStackElement parent = (XmlStackElement) m_elementStack.peek();
-            TypeEntry parentType = (TypeEntry) m_types.get(parent.m_qname);
-            if (parentType == null)
-            {
-                parentType = m_defaultType;
-            }
-
-            String capqName = ClassUtility.capitalize(qName);
-            Method method = null;
-            try
-            {
-// TODO: OBR PARSER: We should also check for instance class as a parameter.
-                method = parentType.m_instanceClass.getDeclaredMethod(
-                    adderOf(capqName),
-                    new Class[]
-                    {
-                        elementType.m_castClass
-                    
-                    });  // instanceClass
-            }
-            catch (NoSuchMethodException e)
-            {
-                trace("NoSuchMethodException: " + adderOf(capqName) + "(" + elementType.m_castClass.getName() + ")");
-            // do nothing
-            }
-            if (method == null)
-            {
-                try
-                {
-                    method = parentType.m_instanceClass.getDeclaredMethod(
-                        setterOf(capqName),
-                        new Class[]
-                        {
-                            elementType.m_castClass
-                        
-                        });
-                }
-                catch (NoSuchMethodException e)
-                {
-                    trace("NoSuchMethodException: " + setterOf(capqName) + "(" + elementType.m_castClass.getName() + ")");
-                // do nothing
-                }
-            /*if (method == null)
-            try {
-            method = parentType.castClass.getDeclaredMethod(
-            adderOf(type.castClass),
-            new Class[] { type.castClass });
-            } catch (NoSuchMethodException e) {
-            trace("NoSuchMethodException: " + adderOf(type.castClass)+ "("+type.castClass.getName()+")");
-            // do nothing
-            }
-            if (method == null)
-            try {
-            method = parentType.castClass.getDeclaredMethod(
-            setterOf(type.castClass),
-            new Class[] { type.castClass });
-            } catch (NoSuchMethodException e) {
-            trace("NoSuchMethodException: " + setterOf(type.castClass)+ "("+type.castClass.getName()+")");
-            // do nothing
-            }
-             */
-            }
-            if (method != null)
-            {
-                trace(method.getName());
-                try
-                {
-                    method.setAccessible(true);
-                    method.invoke(parent.m_object, new Object[]
-                        {
-                            element.m_object
-                        
-                        });
-                }
-                catch (InvocationTargetException e)
-                {
-                    m_logger.log(Logger.LOG_ERROR, "Error parsing repository metadata", e.getTargetException());
-                    throw e;
-                }
-            }
-            else
-            {
-                if (parentType.m_defaultAddMethod != null)
-                {
-                    Class[] parameterTypes = parentType.m_defaultAddMethod.getParameterTypes();
-                    if (parameterTypes.length == 2 && parameterTypes[0].isAssignableFrom(String.class) && parameterTypes[1].isAssignableFrom(elementType.m_castClass))
-                    {
-                        parentType.m_defaultAddMethod.invoke(parent.m_object, new Object[]
-                            {
-                                qName, element.m_object
-                            
-                            });
-                    }
-                    else if (parameterTypes.length == 1 && parameterTypes[0].isAssignableFrom(elementType.m_castClass))
-                    {
-                        parentType.m_defaultAddMethod.invoke(parent.m_object, new Object[]
-                            {
-                                element.m_object
-                            
-                            });
-                    }
-                    else
-                    {
-                        throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + " element " + parent.m_qname + " cannot have an attribute " + qName + " of type " + elementType.m_castClass);
-                    }
-                }
-                else
-                {
-                    throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + " element " + parent.m_qname + " cannot have an attribute " + qName + " of type " + elementType.m_castClass);
-                }
-            }
-
-        }
-
-        // invoke the process method
-        try
-        {
-            invokeProcess(element);
-        }
-        catch (Throwable e)
-        {
-            m_logger.log(Logger.LOG_ERROR, "Error parsing repository metadata", e);
-            throw new Exception(e);
-        }
-
-        trace("END/ (" + m_lineNumber + "," + m_columnNumber + "):" + uri + ":" + qName);
-    }
-
-    public void setTrace(boolean trace)
-    {
-        m_traceFlag = trace;
-    }
-
-    private void trace(String msg)
-    {
-        if (m_traceFlag)
-        {
-            m_logger.log(Logger.LOG_DEBUG, msg);
-        }
-    }
-
-    /**
-     * @see kxml.sax.KXmlSAXHandler#setLineNumber(int)
-     */
-    public void setLineNumber(int lineNumber)
-    {
-        m_lineNumber = lineNumber;
-    }
-
-    /**
-     * @see kxml.sax.KXmlSAXHandler#setColumnNumber(int)
-     */
-    public void setColumnNumber(int columnNumber)
-    {
-        m_columnNumber = columnNumber;
-    }
-
-    /**
-     * @see kxml.sax.KXmlSAXHandler#processingInstruction(java.lang.String,
-     *      java.lang.String)
-     */
-    public void processingInstruction(String target, String data)
-        throws Exception
-    {
-        trace("PI:" + target + ";" + data);
-        trace("ignore PI : " + data);
-    /*		// reuse the kXML parser methods to parser the PI data
-    Reader reader = new StringReader(data);
-    XmlParser parser = new XmlParser(reader);
-    parser.parsePIData();
-    
-    target = parser.getTarget();
-    Map attributes = parser.getAttributes();
-    
-    // get the class
-    Class clazz = (Class) pis.get(target);
-    if (clazz == null) {
-    if (missingPIExceptionFlag)
-    throw new Exception(lineNumber + "," + columnNumber + ":"
-    + "Unknown processing instruction");
-    else {
-    trace(lineNumber + "," + columnNumber + ":"
-    + "No class for PI " + target);
-    return;
-    }
-    }
-    
-    // instanciate a object
-    Object object;
-    Constructor ctor = null;
-    try {
-    ctor = clazz.getConstructor(new Class[] { XmlCommonHandler.class });
-    } catch (NoSuchMethodException e) {
-    // do nothing
-    trace("no constructor with XmlCommonHandler parameter");
-    }
-    try {
-    if (ctor == null) {
-    object = clazz.newInstance();
-    } else {
-    object = ctor.newInstance(new Object[] { this });
-    }
-    } catch (InstantiationException e) {
-    throw new Exception(
-    lineNumber
-    + ","
-    + columnNumber
-    + ":"
-    + "class "
-    + clazz.getName()
-    + " for PI "
-    + target
-    + " should have an empty constructor or a constructor with XmlCommonHandler parameter");
-    } catch (IllegalAccessException e) {
-    throw new Exception(lineNumber + "," + columnNumber + ":"
-    + "illegal access on the constructor " + clazz.getName()
-    + " for PI " + target);
-    }
-    
-    // set the context
-    setObjectContext(object);
-    
-    // TODO: set the parent
-    
-    // invoke setter
-    Iterator iter = attributes.keySet().iterator();
-    while (iter.hasNext()) {
-    String key = (String) iter.next();
-    String value = ReplaceUtility.replace((String) attributes.get(key),
-    context);
-    Method method = null;
-    try {
-    method = clazz.getDeclaredMethod(setterOf(key),
-    new Class[] { String.class });
-    } catch (NoSuchMethodException e) {
-    // do nothing
-    }
-    if (method != null) {
-    trace(method.getName());
-    try {
-    method.invoke(object, new String[] { value });
-    } catch (InvocationTargetException e) {
-    m_logger.log(Logger.LOG_ERROR, "Error parsing repository metadata", e.getTargetException());
-    throw e;
-    }
-    }
-    
-    }
-    
-    // invoke process
-    try {
-    invokeProcess(object);
-    } catch (Throwable e) {
-    m_logger.log(Logger.LOG_ERROR, "Error parsing repository metadata", e);
-    throw new Exception(e);
-    }
-     */    }
-
-    public void processingInstructionForMapping(String target, String data)
-        throws Exception
-    {
-        if (target == null)
-        { // TODO kXML
-            if (!data.startsWith(PI_MAPPING))
-            {
-                return;
-            }
-        }
-        else if (!target.equals(PI_MAPPING))
-        {
-            return;        // defaultclass attribute
-        }
-        String datt = "defaultclass=\"";
-        int dstart = data.indexOf(datt);
-        if (dstart != -1)
-        {
-            int dend = data.indexOf("\"", dstart + datt.length());
-            if (dend == -1)
-            {
-                throw new Exception(
-                    m_lineNumber + "," + m_columnNumber + ":" + " \"defaultclass\" attribute in \"mapping\" PI is not quoted");
-            }
-            String classname = data.substring(dstart + datt.length(), dend);
-            Class clazz = null;
-            try
-            {
-                clazz = getClass().getClassLoader().loadClass(classname);
-            }
-            catch (ClassNotFoundException e)
-            {
-                throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + " cannot found class " + classname + " for \"mapping\" PI");
-            }
-
-            //			 TODO Add method
-            Method defaultdefaultAddMethod = null;
-            setDefaultType(clazz, null, defaultdefaultAddMethod);
-            return;
-        }
-
-        // element attribute
-        String eatt = "element=\"";
-        int estart = data.indexOf(eatt);
-        if (estart == -1)
-        {
-            throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + " missing \"element\" attribute in \"mapping\" PI");
-        }
-        int eend = data.indexOf("\"", estart + eatt.length());
-        if (eend == -1)
-        {
-            throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + " \"element\" attribute in \"mapping\" PI is not quoted");
-        }
-        String element = data.substring(estart + eatt.length(), eend);
-
-        // element class
-        String catt = "class=\"";
-        int cstart = data.indexOf(catt);
-        if (cstart == -1)
-        {
-            throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + " missing \"class\" attribute in \"mapping\" PI");
-        }
-        int cend = data.indexOf("\"", cstart + catt.length());
-        if (cend == -1)
-        {
-            throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + " \"class\" attribute in \"mapping\" PI is not quoted");
-        }
-        String classname = data.substring(cstart + catt.length(), cend);
-
-        // element cast (optional)
-        String castname = null;
-        String castatt = "cast=\"";
-        int caststart = data.indexOf(castatt);
-        if (caststart != -1)
-        {
-            int castend = data.indexOf("\"", cstart + castatt.length());
-            if (castend == -1)
-            {
-                throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + " \"cast\" attribute in \"mapping\" PI is not quoted");
-            }
-            castname = data.substring(caststart + castatt.length(), castend);
-        }
-
-        Class clazz = null;
-        try
-        {
-            clazz = getClass().getClassLoader().loadClass(classname);
-        }
-        catch (ClassNotFoundException e)
-        {
-            throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + " cannot found class " + classname + " for \"mapping\" PI");
-        }
-
-        Class castClazz = null;
-        if (castname != null)
-        {
-            try
-            {
-                clazz = getClass().getClassLoader().loadClass(castname);
-            }
-            catch (ClassNotFoundException e)
-            {
-                throw new Exception(m_lineNumber + "," + m_columnNumber + ":" + " cannot found cast class " + classname + " for \"mapping\" PI");
-            }        // TODO Add method
-        }
-        Method defaultAddMethod = null;
-
-        addType(element, clazz, castClazz, defaultAddMethod);
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/XmlMetadataHandler.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/XmlMetadataHandler.java
deleted file mode 100644
index 2c6e89f..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/XmlMetadataHandler.java
+++ /dev/null
@@ -1,60 +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.metadataparser;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.xml.parsers.*;
-
-import org.apache.felix.bundlerepository.impl.Logger;
-import org.xml.sax.*;
-
-/**
- * handles the metadata in XML format
- */
-public class XmlMetadataHandler extends MetadataHandler
-{
-    public XmlMetadataHandler(Logger logger)
-    {
-        super(logger);
-    }
-
-    /**
-     * Called to parse the InputStream and set bundle list and package hash map
-     */
-    public void parse(InputStream istream) throws ParserConfigurationException, IOException, SAXException
-    {
-        // Parse the Meta-Data
-
-        ContentHandler contenthandler = (ContentHandler) m_handler;
-
-        InputSource is = new InputSource(istream);
-
-        SAXParserFactory spf = SAXParserFactory.newInstance();
-        spf.setValidating(false);
-
-        SAXParser saxParser = spf.newSAXParser();
-
-        XMLReader xmlReader = null;
-        xmlReader = saxParser.getXMLReader();
-        xmlReader.setContentHandler(contenthandler);
-        xmlReader.parse(is);
-    }
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/kxmlsax/KXml2SAXHandler.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/kxmlsax/KXml2SAXHandler.java
deleted file mode 100644
index a2b2d62..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/kxmlsax/KXml2SAXHandler.java
+++ /dev/null
@@ -1,75 +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.metadataparser.kxmlsax;
-
-import java.util.Properties;
-
-/**
- * Interface for SAX handler with kXML
- */
-public interface KXml2SAXHandler
-{
-    /**
-     * Method called when parsing text
-     *
-     * @param   ch
-     * @param   offset
-     * @param   length
-     * @exception   SAXException
-     */
-    public void characters(char[] ch, int offset, int length) throws Exception;
-
-    /**
-     * Method called when a tag opens
-     *
-     * @param   uri
-     * @param   localName
-     * @param   qName
-     * @param   attrib
-     * @exception   SAXException
-     **/
-    public void startElement(
-        String uri,
-        String localName,
-        String qName,
-        Properties attrib)
-        throws Exception;
-
-    /**
-     * Method called when a tag closes
-     *
-     * @param   uri
-     * @param   localName
-     * @param   qName
-     * @exception   SAXException
-     */
-    public void endElement(
-        java.lang.String uri,
-        java.lang.String localName,
-        java.lang.String qName)
-        throws Exception;
-
-    public void processingInstruction(String target,
-        String data)
-        throws Exception;
-
-    public void setLineNumber(int lineNumber);
-
-    public void setColumnNumber(int columnNumber);
-}
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/kxmlsax/KXml2SAXParser.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/kxmlsax/KXml2SAXParser.java
deleted file mode 100644
index 78db998..0000000
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/metadataparser/kxmlsax/KXml2SAXParser.java
+++ /dev/null
@@ -1,93 +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.metadataparser.kxmlsax;
-
-import java.io.Reader;
-import java.util.Properties;
-
-import org.kxml2.io.KXmlParser;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-/**
- * The KXml2SAXParser extends the XmlParser from kxml2 (which  does not take into account the DTD).
- */
-public class KXml2SAXParser extends KXmlParser
-{
-    public String m_uri = "uri";
-
-    /**
-     * The constructor for a parser, it receives a java.io.Reader.
-     *
-     * @param   reader  The reader
-     * @throws XmlPullParserException 
-     */
-    public KXml2SAXParser(Reader reader) throws XmlPullParserException
-    {
-        super();
-        setInput(reader);
-    }
-
-    /**
-     * parse from the reader provided in the constructor, and call
-     * the startElement and endElement in the handler
-     *
-     * @param   handler  The handler
-     * @exception   Exception thrown by the superclass
-     */
-    public void parseXML(KXml2SAXHandler handler) throws Exception
-    {
-        while (next() != XmlPullParser.END_DOCUMENT)
-        {
-            handler.setLineNumber(getLineNumber());
-            handler.setColumnNumber(getColumnNumber());
-            if (getEventType() == XmlPullParser.START_TAG)
-            {
-                Properties props = new Properties();
-                for (int i = 0; i < getAttributeCount(); i++)
-                {
-                    props.put(getAttributeName(i), getAttributeValue(i));
-                }
-                handler.startElement(
-                    getNamespace(),
-                    getName(),
-                    getName(),
-                    props);
-            }
-            else if (getEventType() == XmlPullParser.END_TAG)
-            {
-                handler.endElement(getNamespace(), getName(), getName());
-            }
-            else if (getEventType() == XmlPullParser.TEXT)
-            {
-                String text = getText();
-                handler.characters(text.toCharArray(), 0, text.length());
-            }
-            else if (getEventType() == XmlPullParser.PROCESSING_INSTRUCTION)
-            {
-                // TODO extract the target from the evt.getText()
-                handler.processingInstruction(null, getText());
-            }
-            else
-            {
-                // do nothing
-            }
-        }
-    }
-}
\ No newline at end of file
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 9223871..3d6cf2b 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,6 +18,7 @@
  */
 package org.apache.felix.bundlerepository.impl;
 
+import java.io.File;
 import java.net.URL;
 import java.util.Hashtable;
 
@@ -52,11 +53,27 @@
         assertTrue(resolver.resolve());
     }
 
+    public void testPullParser() throws Exception
+    {
+        URL url = getClass().getResource("/repo_for_resolvertest.xml");
+        RepositoryAdminImpl repoAdmin = createRepositoryAdmin(PullParser.class);
+        RepositoryImpl repo = (RepositoryImpl) repoAdmin.addRepository(url);
+
+        Resolver resolver = repoAdmin.resolver();
+
+        Resource[] discoverResources = repoAdmin.discoverResources("(symbolicname=org.apache.felix.test*)");
+        assertNotNull(discoverResources);
+        assertEquals(1, discoverResources.length);
+
+        resolver.add(discoverResources[0]);
+        assertTrue(resolver.resolve());
+    }
+
     public void testPerfs() throws Exception
     {
-//        for (int i = 0; i < 10; i++) {
+        for (int i = 0; i < 10; i++) {
 //            testPerfs(new File(System.getProperty("user.home"), ".m2/repository/repository.xml").toURI().toURL(), 0, 100);
-//        }
+        }
     }
 
     protected void testPerfs(URL url, int nbWarm, int nbTest) throws Exception
@@ -98,17 +115,17 @@
 
         for (int i = 0; i < nbWarm; i++)
         {
-            RepositoryAdminImpl repoAdmin = createRepositoryAdmin(RepositoryImpl.KXml2Parser.class);
+            RepositoryAdminImpl repoAdmin = createRepositoryAdmin(PullParser.class);
             RepositoryImpl repo = (RepositoryImpl) repoAdmin.addRepository(url);
         }
         t0 = System.currentTimeMillis();
         for (int i = 0; i < nbTest; i++)
         {
-            RepositoryAdminImpl repoAdmin = createRepositoryAdmin(RepositoryImpl.KXml2Parser.class);
+            RepositoryAdminImpl repoAdmin = createRepositoryAdmin(PullParser.class);
             RepositoryImpl repo = (RepositoryImpl) repoAdmin.addRepository(url);
         }
         t1 = System.currentTimeMillis();
-        System.err.println("KXmlParser: " + (t1 - t0) + " ms");
+        System.err.println("PullParser: " + (t1 - t0) + " ms");
     }
 
     public static void main(String[] args) throws Exception