FELIX-2719 Fix namespace support: allow for 1.0.0, 1.1.0, and new 1.2.0 namespaces
 - throw if unsupported namespace is encountered
 - don't further process namespace

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1187808 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/metatype/src/main/java/org/apache/felix/metatype/MetaDataReader.java b/metatype/src/main/java/org/apache/felix/metatype/MetaDataReader.java
index d6c196a..690f1c1 100644
--- a/metatype/src/main/java/org/apache/felix/metatype/MetaDataReader.java
+++ b/metatype/src/main/java/org/apache/felix/metatype/MetaDataReader.java
@@ -53,6 +53,24 @@
 public class MetaDataReader
 {
 
+    /**
+     * The initial XML Namespace for Metatype 1.1 descriptors. This has
+     * been replaced by the v1.1.0 namespace in the Compendium
+     * Specification 4.2. We still have to support this namespace for
+     * backwards compatibility.
+     */
+    private static final String NAMESPACE_1_0 = "http://www.osgi.org/xmlns/metatype/v1.0.0";
+
+    /**
+     * The XML Namespace for Metatype 1.1 descriptors.
+     */
+    private static final String NAMESPACE_1_1 = "http://www.osgi.org/xmlns/metatype/v1.1.0";
+
+    /**
+     * The XML Namespace for Metatype 1.2 descriptors.
+     */
+    private static final String NAMESPACE_1_2 = "http://www.osgi.org/xmlns/metatype/v1.2.0";
+
     /** The XML parser used to read the XML documents */
     private KXmlParser parser = new KXmlParser();
 
@@ -81,8 +99,6 @@
         {
             ins = url.openStream();
             this.parser.setProperty( "http://xmlpull.org/v1/doc/properties.html#location", url.toString() );
-            this.parser.setFeature( KXmlParser.FEATURE_PROCESS_NAMESPACES, true );
-            this.parser.setFeature( KXmlParser.FEATURE_REPORT_NAMESPACE_ATTRIBUTES, false );
             MetaData md = this.parse( ins );
             if ( md != null )
             {
@@ -110,27 +126,16 @@
     /**
      * Checks if this document has a meta type name space.
      *
-     * @return <code>true</code> if this document has a meta type name space
      * @throws XmlPullParserException when there the meta type name space is not valid
      */
-    private boolean hasMetaTypeNameSpace() throws XmlPullParserException
+    private void checkMetatypeNamespace() throws XmlPullParserException
     {
-
-        int attrs = this.parser.getAttributeCount();
-        for ( int i = 0; i < attrs; i++ )
+        final String namespace = this.parser.getNamespace();
+        if ( namespace != null && namespace.length() > 0 && !NAMESPACE_1_0.equals( namespace )
+            && !NAMESPACE_1_1.equals( namespace ) && !NAMESPACE_1_2.equals( namespace ) )
         {
-
-            if ( this.parser.getAttributeName( i ).equals( "xmlns:metatype" ) )
-            {
-                if ( !"http://www.osgi.org/xmlns/metatype/v1.0.0".equals( this.parser.getAttributeValue( i ) ) )
-                {
-                    throw new XmlPullParserException( "invalid namespace: " + this.parser.getAttributeValue( i ),
-                        this.parser, null );
-                }
-                return true;
-            }
+            throw new XmlPullParserException( "Unsupported Namespace " + namespace );
         }
-        return false;
     }
 
 
@@ -152,6 +157,8 @@
      */
     public MetaData parse( InputStream ins ) throws IOException, XmlPullParserException
     {
+        this.parser.setFeature( KXmlParser.FEATURE_PROCESS_NAMESPACES, true );
+
         // set the parser input, use null encoding to force detection with <?xml?>
         this.parser.setInput( ins, null );
 
@@ -162,15 +169,10 @@
         {
             if ( eventType == XmlPullParser.START_TAG )
             {
-                boolean nameSpaceAware = hasMetaTypeNameSpace();
-
-                if ( nameSpaceAware && "metatype:MetaData".equals( this.parser.getName() ) )
+                if ( "MetaData".equals( this.parser.getName() ) )
                 {
-                    mti = this.readMetaData( nameSpaceAware );
-                }
-                else if ( "MetaData".equals( this.parser.getName() ) )
-                {
-                    mti = this.readMetaData( nameSpaceAware );
+                    checkMetatypeNamespace();
+                    mti = this.readMetaData( );
                 }
                 else
                 {
@@ -184,7 +186,7 @@
     }
 
 
-    private MetaData readMetaData( boolean nameSpaceAware ) throws IOException, XmlPullParserException
+    private MetaData readMetaData() throws IOException, XmlPullParserException
     {
         MetaData mti = this.createMetaData();
         mti.setLocalePrefix( this.getOptionalAttribute( "localization" ) );
@@ -209,10 +211,6 @@
             }
             else if ( eventType == XmlPullParser.END_TAG )
             {
-                if ( nameSpaceAware && "metatype:MetaData".equals( this.parser.getName() ) )
-                {
-                    break;
-                }
                 if ( "MetaData".equals( this.parser.getName() ) )
                 {
                     break;
diff --git a/metatype/src/test/java/org/apache/felix/metatype/MetaDataReaderTest.java b/metatype/src/test/java/org/apache/felix/metatype/MetaDataReaderTest.java
index d5b1857..7a9ae02 100644
--- a/metatype/src/test/java/org/apache/felix/metatype/MetaDataReaderTest.java
+++ b/metatype/src/test/java/org/apache/felix/metatype/MetaDataReaderTest.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
@@ -66,41 +66,77 @@
         assertNull( mti.getObjectClassDefinitions() );
     }
 
-    public void testWithNamespace() throws IOException, XmlPullParserException
+
+    public void testWithNamespace_1_0_0() throws IOException, XmlPullParserException
     {
-        String empty = "<metatype:MetaData xmlns:metatype=\"http://www.osgi.org/xmlns/metatype/v1.0.0\" " + 
-        	"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ></metatype:MetaData>";
+        String empty = "<metatype:MetaData xmlns:metatype=\"http://www.osgi.org/xmlns/metatype/v1.0.0\" "
+            + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ></metatype:MetaData>";
         MetaData mti = read( empty );
-        
+
         assertNotNull( mti );
         assertNull( mti.getLocalePrefix() );
         assertNull( mti.getObjectClassDefinitions() );
     }
 
-    public void testWithInvalidNamespaceUri() throws IOException, XmlPullParserException
+
+    public void testWithNamespace_1_1_0() throws IOException, XmlPullParserException
     {
-        String empty = "<metatype:MetaData xmlns:metatype=\"http://www.osgi.org/xmlns/datatype/v1.0.0\" " + 
-        	"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ></metatype:MetaData>";
-        
-        Exception exc = null;
-        try {
-        	MetaData mti = read( empty );
-        } catch (Exception e) {
-        	exc = e;
-		}
-        assertNotNull(exc);
+        String empty = "<metatype:MetaData xmlns:metatype=\"http://www.osgi.org/xmlns/metatype/v1.1.0\" "
+            + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ></metatype:MetaData>";
+        MetaData mti = read( empty );
+
+        assertNotNull( mti );
+        assertNull( mti.getLocalePrefix() );
+        assertNull( mti.getObjectClassDefinitions() );
     }
 
-    public void testWithInvalidNamespaceName() throws IOException, XmlPullParserException
+
+    public void testWithNamespace_1_2_0() throws IOException, XmlPullParserException
     {
-        String empty = "<datatype:MetaData xmlns:metatype=\"http://www.osgi.org/xmlns/metatype/v1.0.0\" " + 
-        	"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ></datatype:MetaData>";
-        
+        String empty = "<metatype:MetaData xmlns:metatype=\"http://www.osgi.org/xmlns/metatype/v1.1.0\" "
+            + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ></metatype:MetaData>";
         MetaData mti = read( empty );
-        
-        assertNull( mti );
+
+        assertNotNull( mti );
+        assertNull( mti.getLocalePrefix() );
+        assertNull( mti.getObjectClassDefinitions() );
     }
 
+
+    public void testWithInvalidNamespaceUri() throws IOException
+    {
+        String empty = "<metatype:MetaData xmlns:metatype=\"http://www.osgi.org/xmlns/datatype/v1.0.0\" "
+            + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ></metatype:MetaData>";
+
+        try
+        {
+            read( empty );
+            fail( "Parse failure expected for unsupported namespace URI" );
+        }
+        catch ( XmlPullParserException e )
+        {
+            // expected due to unsupported namespace URI
+        }
+    }
+
+
+    public void testWithInvalidNamespaceName() throws IOException
+    {
+        String empty = "<datatype:MetaData xmlns:metatype=\"http://www.osgi.org/xmlns/metatype/v1.0.0\" "
+            + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ></datatype:MetaData>";
+
+        try
+        {
+            read( empty );
+            fail( "Parse failure expected for undefined namespace prefix" );
+        }
+        catch ( XmlPullParserException e )
+        {
+            // expected due to undefined namespace prefix used
+        }
+    }
+
+
     public void testEmptyLocalization() throws IOException, XmlPullParserException
     {
         String testLoc = "OSGI-INF/folder/base";