[FELIX-4506] [FELIX-4406] [FELIX-4507] Implement felix extension attribute namespace and service scope parsing.  Also use extension attribute to turn persistent factory component on

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1591420 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/Component.java b/scr/src/main/java/org/apache/felix/scr/Component.java
index df21574..bca75c0 100644
--- a/scr/src/main/java/org/apache/felix/scr/Component.java
+++ b/scr/src/main/java/org/apache/felix/scr/Component.java
@@ -183,7 +183,10 @@
      * the <code>service</code> element. If the component has no service
      * element, this method returns <code>false</code>.
      */
+    @Deprecated
     boolean isServiceFactory();
+    
+    String getServiceScope();
 
 
     /**
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java b/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java
index 9823ad2..92fd360 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java
@@ -328,8 +328,8 @@
                     out.print( "          " );
                     out.println( services[i] );
                 }
-                out.print( "Service Type: " );
-                out.println( component.isServiceFactory() ? "service factory" : "service" );
+                out.print( "Service Scope: " );
+                out.println( component.getServiceScope() );
             }
 
             Reference[] refs = component.getReferences();
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurableComponentHolder.java b/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurableComponentHolder.java
index f35e022..b921092 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurableComponentHolder.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurableComponentHolder.java
@@ -33,6 +33,7 @@
 import org.apache.felix.scr.impl.manager.SingleComponentManager;
 import org.apache.felix.scr.impl.manager.ServiceFactoryComponentManager;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
+import org.apache.felix.scr.impl.metadata.ServiceMetadata.Scope;
 import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.log.LogService;
 
@@ -120,11 +121,17 @@
         {
             throw new IllegalArgumentException( "Cannot create component factory for " + m_componentMetadata.getName() );
         }
-        else if ( m_componentMetadata.getServiceMetadata() != null && m_componentMetadata.getServiceMetadata().isServiceFactory() )
+        else if ( m_componentMetadata.getServiceScope() == Scope.bundle )
         {
             manager = new ServiceFactoryComponentManager<S>( m_activator, this, m_componentMetadata, m_componentMethods );
         }
 
+        else if ( m_componentMetadata.getServiceScope() == Scope.prototype )
+        {
+        	manager = null;// NYI
+//            manager = new ServiceFactoryComponentManager<S>( m_activator, this, m_componentMetadata, m_componentMethods );
+        }
+
         else
         {
             //immediate or delayed
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
index 1672a0a..5c1d1e9 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
@@ -51,6 +51,7 @@
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
 import org.apache.felix.scr.impl.metadata.ServiceMetadata;
+import org.apache.felix.scr.impl.metadata.ServiceMetadata.Scope;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
@@ -165,8 +166,8 @@
 
             if ( metadata.getServiceMetadata() != null )
             {
-                log( LogService.LOG_DEBUG, "Component {0} Services: servicefactory={1}, services={2}", new Object[]
-                    { metadata.getName(), Boolean.valueOf( metadata.getServiceMetadata().isServiceFactory() ),
+                log( LogService.LOG_DEBUG, "Component {0} Services: scope={1}, services={2}", new Object[]
+                    { metadata.getName(), metadata.getServiceScope(),
                         Arrays.asList( metadata.getServiceMetadata().getProvides() ) }, null );
             }
 
@@ -714,8 +715,12 @@
 
     public boolean isServiceFactory()
     {
-        return m_componentMetadata.getServiceMetadata() != null
-                && m_componentMetadata.getServiceMetadata().isServiceFactory();
+        return m_componentMetadata.getServiceScope() == Scope.bundle;
+    }
+    
+    public String getServiceScope()
+    {
+    	return m_componentMetadata.getServiceScope().name();
     }
 
     public boolean isFactory()
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
index 010454e..b210cdc 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
@@ -105,13 +105,12 @@
         super( activator, metadata, new ComponentMethods() );
         m_componentInstances = new IdentityHashMap<SingleComponentManager<S>, SingleComponentManager<S>>();
         m_configuration = new Hashtable<String, Object>();
-        m_nonPersistentFactory = true;
     }
 
 
     protected boolean verifyDependencyManagers()
     {
-        if (m_nonPersistentFactory)
+        if (!getComponentMetadata().isPersistentFactoryComponent())
         {
             return super.verifyDependencyManagers();
         }
@@ -143,7 +142,7 @@
         cm.activateInternal( getTrackingCount().get() );
 
         instance = cm.getComponentInstance();
-        if ( instance == null || (m_nonPersistentFactory && instance.getInstance() == null) )
+        if ( instance == null || (!getComponentMetadata().isPersistentFactoryComponent() && instance.getInstance() == null) )
         {
             // activation failed, clean up component manager
             cm.dispose( ComponentConstants.DEACTIVATION_REASON_DISPOSED );
@@ -155,7 +154,7 @@
             m_componentInstances.put( cm, cm );
         }
         
-        if ( !m_nonPersistentFactory ) 
+        if ( getComponentMetadata().isPersistentFactoryComponent() ) 
         {
             instance = new ModifyComponentInstance(cm);
         }
@@ -543,7 +542,7 @@
      */
     private SingleComponentManager<S> createComponentManager()
     {
-        return new SingleComponentManager<S>( getActivator(), this, getComponentMetadata(), getComponentMethods(), m_nonPersistentFactory );
+        return new SingleComponentManager<S>( getActivator(), this, getComponentMetadata(), getComponentMethods(), !getComponentMetadata().isPersistentFactoryComponent() );
     }
 
 
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java b/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java
index 7c1ec7e..5a35d8b 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java
@@ -29,6 +29,7 @@
 import java.util.TreeSet;
 
 import org.apache.felix.scr.impl.helper.Logger;
+import org.apache.felix.scr.impl.metadata.ServiceMetadata.Scope;
 import org.osgi.service.component.ComponentException;
 import org.osgi.service.log.LogService;
 
@@ -111,6 +112,12 @@
 
     // List of service references, (required services 0..*)
     private List<ReferenceMetadata> m_references = new ArrayList<ReferenceMetadata>();
+    
+    private boolean m_configurableServiceProperties;
+    private boolean m_persistentFactoryComponent;
+    private boolean m_deleteCallsModify;
+    private boolean m_obsoleteFactoryComponentFactory;
+    private boolean m_configureWithInterfaces;
 
     // Flag that is set once the component is verified (its properties cannot be changed)
     private boolean m_validated = false;
@@ -354,10 +361,51 @@
         m_references.add( newReference );
     }
 
+    public void setConfigurableServiceProperties( boolean configurableServiceProperties) {
+        if ( m_validated )
+        {
+            return;
+        }
+		this.m_configurableServiceProperties = configurableServiceProperties;
+	}
+
+	public void setPersistentFactoryComponent(boolean persistentFactoryComponent) {
+        if ( m_validated )
+        {
+            return;
+        }
+		this.m_persistentFactoryComponent = persistentFactoryComponent;
+	}
+
+	public void setDeleteCallsModify(boolean deleteCallsModify) {
+        if ( m_validated )
+        {
+            return;
+        }
+		this.m_deleteCallsModify = deleteCallsModify;
+	}
+
+	public void setObsoleteFactoryComponentFactory( boolean obsoleteFactoryComponentFactory) {
+        if ( m_validated )
+        {
+            return;
+        }
+		this.m_obsoleteFactoryComponentFactory = obsoleteFactoryComponentFactory;
+	}
+
+	public void setConfigureWithInterfaces(boolean configureWithInterfaces) {
+        if ( m_validated )
+        {
+            return;
+        }
+		this.m_configureWithInterfaces = configureWithInterfaces;
+	}
+
+    
 
     /////////////////////////////////////////// GETTERS //////////////////////////////////////
 
-    /**
+	/**
      * Returns the namespace code of the namespace of the component element
      * declaring this component. This is one of the XmlHandler.DS_VERSION_*
      * constants.
@@ -604,6 +652,15 @@
     {
         return m_service;
     }
+    
+    public Scope getServiceScope()
+    {
+    	if (m_service == null) 
+    	{
+    		return Scope.singleton;
+    	}
+    	return m_service.getScope();
+    }
 
 
     /**
@@ -681,7 +738,27 @@
     }
 
 
-    /**
+    public boolean isConfigurableServiceProperties() {
+		return m_configurableServiceProperties;
+	}
+
+	public boolean isPersistentFactoryComponent() {
+		return m_persistentFactoryComponent;
+	}
+
+	public boolean isDeleteCallsModify() {
+		return m_deleteCallsModify;
+	}
+
+	public boolean isObsoleteFactoryComponentFactory() {
+		return m_obsoleteFactoryComponentFactory;
+	}
+
+	public boolean isConfigureWithInterfaces() {
+		return m_configureWithInterfaces;
+	}
+
+	/**
      * Method used to verify if the semantics of this metadata are correct
      */
     public void validate( Logger logger )
@@ -763,10 +840,8 @@
         }
 
         // Next check if the properties are valid (and extract property values)
-        Iterator propertyIterator = m_propertyMetaData.iterator();
-        while ( propertyIterator.hasNext() )
+        for ( PropertyMetadata propMeta: m_propertyMetaData )
         {
-            PropertyMetadata propMeta = ( PropertyMetadata ) propertyIterator.next();
             propMeta.validate( this );
             m_properties.put( propMeta.getName(), propMeta.getValue() );
         }
@@ -783,11 +858,9 @@
         }
 
         // Check that the references are ok
-        HashSet refs = new HashSet();
-        Iterator referenceIterator = m_references.iterator();
-        while ( referenceIterator.hasNext() )
+        Set<String> refs = new HashSet<String>();
+        for  ( ReferenceMetadata refMeta: m_references )
         {
-            ReferenceMetadata refMeta = ( ReferenceMetadata ) referenceIterator.next();
             refMeta.validate( this, logger );
 
             // flag duplicates
@@ -824,11 +897,33 @@
         // the component is a factory component or an immediate component
         if ( m_service != null )
         {
-            if ( m_service.isServiceFactory() && ( isFactory() || isImmediate() ) )
+            if ( (m_service.getScope() != ServiceMetadata.Scope.singleton) && ( isFactory() || isImmediate() ) )
             {
-                throw validationFailure( "ServiceFactory cannot be factory or immediate" );
+                throw validationFailure( "factory or immediate must be scope singleton not " +  m_service.getScope());
             }
         }
+        
+        if (m_namespaceCode == XmlHandler.DS_VERSION_1_2_FELIX) 
+        {
+        	m_configurableServiceProperties = true;
+        }
+        if (m_namespaceCode >= XmlHandler.DS_VERSION_1_3)
+        {
+        	m_deleteCallsModify = true; //spec behavior as of 1.3
+        }
+        if (m_namespaceCode < XmlHandler.DS_VERSION_1_3 && m_configureWithInterfaces)
+        {
+        	throw validationFailure("Configuration with interfaces or annotations only possible with version 1.3 or later");
+        }
+        if (m_namespaceCode >= XmlHandler.DS_VERSION_1_3 && m_obsoleteFactoryComponentFactory)
+        {
+        	throw validationFailure("Configuration of component factory instances through config admin factory pids supported only through the 1.2 namespace");
+        }
+        if (m_persistentFactoryComponent && !isFactory())
+        {
+        	throw validationFailure("Only a factory component can be a persistent factory component");
+        }
+        
 
         m_validated = true;
     }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/metadata/ServiceMetadata.java b/scr/src/main/java/org/apache/felix/scr/impl/metadata/ServiceMetadata.java
index 0c7ebe4..6853996 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/metadata/ServiceMetadata.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/metadata/ServiceMetadata.java
@@ -28,9 +28,13 @@
  *
  */
 public class ServiceMetadata {
+	
+	public enum Scope { singleton, bundle, prototype}
 
 	// 112.4.6 Flag that indicates if the service is a ServiceFactory
-	private boolean m_serviceFactory = false;
+	private Boolean m_serviceFactory;
+	
+	private Scope m_scope;
 
 	// List of provided interfaces
 	private List<String> m_provides = new ArrayList<String>();
@@ -50,6 +54,19 @@
 
 		m_serviceFactory = serviceFactory;
 	}
+	
+	public void setScope(Scope scope) {
+		if(m_validated) {
+			return;
+		}
+		this.m_scope = scope;
+	}
+
+	
+
+	public Scope getScope() {
+		return m_scope;
+	}
 
 	/**
 	 * Add a provided interface to this service
@@ -65,15 +82,6 @@
 	}
 
 	/**
-	 * Return the flag that defines if it is a service factory or not
-	 *
-	 * @return a boolean flag
-	 */
-	public boolean isServiceFactory() {
-		return m_serviceFactory;
-	}
-
-	/**
      * Returns the implemented interfaces
      *
      * @return the implemented interfaces as a string array
@@ -93,6 +101,22 @@
             throw componentMetadata
                 .validationFailure( "At least one provided interface must be declared in the service element" );
         }
+        if (m_scope != null && componentMetadata.getNamespaceCode() < XmlHandler.DS_VERSION_1_3)
+        {
+        	throw componentMetadata.validationFailure("scope can only be specified in version 1.3 and later");
+        }
+        if (m_serviceFactory != null)
+        {
+        	if (componentMetadata.getNamespaceCode() >= XmlHandler.DS_VERSION_1_3)
+        	{
+            	throw componentMetadata.validationFailure("service-factory can only be specified in version 1.2 and earlier");
+        	}
+        	m_scope = m_serviceFactory? Scope.bundle: Scope.singleton;
+        }
+        if (m_scope == null) 
+        {
+        	m_scope = Scope.singleton;
+        }
         m_validated = true;
     }
 }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/metadata/XmlHandler.java b/scr/src/main/java/org/apache/felix/scr/impl/metadata/XmlHandler.java
index e5df6e0..f193527 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/metadata/XmlHandler.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/metadata/XmlHandler.java
@@ -30,6 +30,7 @@
 import java.util.Properties;
 import org.apache.felix.scr.impl.helper.Logger;
 import org.apache.felix.scr.impl.parser.KXml2SAXHandler;
+import org.apache.felix.scr.impl.parser.KXml2SAXParser.Attributes;
 import org.apache.felix.scr.impl.parser.ParseException;
 import org.osgi.framework.Bundle;
 import org.osgi.service.log.LogService;
@@ -60,6 +61,23 @@
     // Namespace URI of DS 1.2-felix (see FELIX-3377)
     public static final String NAMESPACE_URI_1_2_FELIX = "http://felix.apache.org/xmlns/scr/v1.2.0-felix";
 
+    // Namespace URI of DS 1.3
+    public static final String NAMESPACE_URI_1_3 = "http://www.osgi.org/xmlns/scr/v1.3.0";
+
+    // Namespace URI of felis DS extensions 1.0
+    public static final String NAMESPACE_URI_1_0_FELIX_EXTENSIONS = "http://felix.apache.org/xmlns/scr/extensions/v1.0.0";
+    
+    //extension features
+    public static final String CONFIGURABLE_SERVICE_PROPERTIES = "configurableServiceProperties";
+
+    public static final String PERSISTENT_FACTORY_COMPONENT = "persistentFactoryComponent";
+    
+    public static final String DELETE_CALLS_MODIFY = "deleteCallsModify";
+    
+    public static final String OBSOLETE_FACTORY_COMPONENT_FACTORY = "obsoleteFactoryComponentFactory";
+    
+    public static final String CONFIGURE_WITH_INTERFACES = "configureWithInterfaces";
+
     // namespace code for non-DS namespace
     public static final int DS_VERSION_NONE = -1;
 
@@ -78,8 +96,11 @@
     // namespace code for the DS 1.2-felix specification
     public static final int DS_VERSION_1_2_FELIX = 4;
 
+    // namespace code for the DS 1.3 specification
+    public static final int DS_VERSION_1_3 = 5;
+
     // mapping of namespace URI to namespace code
-    private static final Map NAMESPACE_CODE_MAP;
+    private static final Map<String, Integer> NAMESPACE_CODE_MAP;
 
     // the bundle containing the XML resource being parsed
     private final Bundle m_bundle;
@@ -94,7 +115,7 @@
     private ServiceMetadata m_currentService;
 
     // A list of component descriptors contained in the file
-    private List m_components = new ArrayList();
+    private List<ComponentMetadata> m_components = new ArrayList<ComponentMetadata>();
 
     // PropertyMetaData whose value attribute is missing, hence has element data
     private PropertyMetadata m_pendingProperty;
@@ -110,13 +131,14 @@
 
     static
     {
-        NAMESPACE_CODE_MAP = new HashMap();
+        NAMESPACE_CODE_MAP = new HashMap<String, Integer>();
         NAMESPACE_CODE_MAP.put( NAMESPACE_URI_EMPTY, DS_VERSION_1_0 );
         NAMESPACE_CODE_MAP.put( NAMESPACE_URI, DS_VERSION_1_0 );
         NAMESPACE_CODE_MAP.put( NAMESPACE_URI_1_1, DS_VERSION_1_1 );
         NAMESPACE_CODE_MAP.put( NAMESPACE_URI_1_1_FELIX, DS_VERSION_1_1_FELIX );
         NAMESPACE_CODE_MAP.put( NAMESPACE_URI_1_2, DS_VERSION_1_2 );
         NAMESPACE_CODE_MAP.put( NAMESPACE_URI_1_2_FELIX, DS_VERSION_1_2_FELIX );
+        NAMESPACE_CODE_MAP.put( NAMESPACE_URI_1_3, DS_VERSION_1_3 );
     }
 
 
@@ -134,7 +156,7 @@
     *
     * @return   A list of service descriptors
     */
-    public List getComponentMetadataList()
+    public List<ComponentMetadata> getComponentMetadataList()
     {
         return m_components;
     }
@@ -145,10 +167,10 @@
      *
      * @param   uri
      * @param   localName
-     * @param   attrib
+     * @param   attributes
      * @exception   ParseException
     **/
-    public void startElement( String uri, String localName, Properties attrib ) throws ParseException
+    public void startElement( String uri, String localName, Attributes attributes ) throws ParseException
     {
         // according to the spec, the elements should have the namespace,
         // except when the root element is the "component" element
@@ -192,58 +214,64 @@
                     m_currentComponent = new ComponentMetadata( namespaceCode.intValue() );
 
                     // name attribute is optional (since DS 1.1)
-                    if ( attrib.getProperty( "name" ) != null )
+                    if ( attributes.getAttribute( "name" ) != null )
                     {
-                        m_currentComponent.setName( attrib.getProperty( "name" ) );
+                        m_currentComponent.setName( attributes.getAttribute( "name" ) );
                     }
 
                     // enabled attribute is optional
-                    if ( attrib.getProperty( "enabled" ) != null )
+                    if ( attributes.getAttribute( "enabled" ) != null )
                     {
-                        m_currentComponent.setEnabled( attrib.getProperty( "enabled" ).equals( "true" ) );
+                        m_currentComponent.setEnabled( attributes.getAttribute( "enabled" ).equals( "true" ) );
                     }
 
                     // immediate attribute is optional
-                    if ( attrib.getProperty( "immediate" ) != null )
+                    if ( attributes.getAttribute( "immediate" ) != null )
                     {
-                        m_currentComponent.setImmediate( attrib.getProperty( "immediate" ).equals( "true" ) );
+                        m_currentComponent.setImmediate( attributes.getAttribute( "immediate" ).equals( "true" ) );
                     }
 
                     // factory attribute is optional
-                    if ( attrib.getProperty( "factory" ) != null )
+                    if ( attributes.getAttribute( "factory" ) != null )
                     {
-                        m_currentComponent.setFactoryIdentifier( attrib.getProperty( "factory" ) );
+                        m_currentComponent.setFactoryIdentifier( attributes.getAttribute( "factory" ) );
                     }
 
                     // configuration-policy is optional (since DS 1.1)
-                    if ( attrib.getProperty( "configuration-policy" ) != null )
+                    if ( attributes.getAttribute( "configuration-policy" ) != null )
                     {
-                        m_currentComponent.setConfigurationPolicy( attrib.getProperty( "configuration-policy" ) );
+                        m_currentComponent.setConfigurationPolicy( attributes.getAttribute( "configuration-policy" ) );
                     }
 
                     // activate attribute is optional (since DS 1.1)
-                    if ( attrib.getProperty( "activate" ) != null )
+                    if ( attributes.getAttribute( "activate" ) != null )
                     {
-                        m_currentComponent.setActivate( attrib.getProperty( "activate" ) );
+                        m_currentComponent.setActivate( attributes.getAttribute( "activate" ) );
                     }
 
                     // deactivate attribute is optional (since DS 1.1)
-                    if ( attrib.getProperty( "deactivate" ) != null )
+                    if ( attributes.getAttribute( "deactivate" ) != null )
                     {
-                        m_currentComponent.setDeactivate( attrib.getProperty( "deactivate" ) );
+                        m_currentComponent.setDeactivate( attributes.getAttribute( "deactivate" ) );
                     }
 
                     // modified attribute is optional (since DS 1.1)
-                    if ( attrib.getProperty( "modified" ) != null )
+                    if ( attributes.getAttribute( "modified" ) != null )
                     {
-                        m_currentComponent.setModified( attrib.getProperty( "modified" ) );
+                        m_currentComponent.setModified( attributes.getAttribute( "modified" ) );
                     }
 
                     // configuration-pid attribute is optional (since DS 1.2)
-                    if (attrib.getProperty("configuration-pid") != null)
+                    if (attributes.getAttribute("configuration-pid") != null)
                     {
-                        m_currentComponent.setConfigurationPid( attrib.getProperty( "configuration-pid" ) );
+                        m_currentComponent.setConfigurationPid( attributes.getAttribute( "configuration-pid" ) );
                     }
+                    
+                    m_currentComponent.setConfigurableServiceProperties("true".equals(attributes.getAttribute(NAMESPACE_URI_1_0_FELIX_EXTENSIONS, CONFIGURABLE_SERVICE_PROPERTIES)));
+                    m_currentComponent.setPersistentFactoryComponent("true".equals(attributes.getAttribute(NAMESPACE_URI_1_0_FELIX_EXTENSIONS, PERSISTENT_FACTORY_COMPONENT)));
+                    m_currentComponent.setDeleteCallsModify("true".equals(attributes.getAttribute(NAMESPACE_URI_1_0_FELIX_EXTENSIONS, DELETE_CALLS_MODIFY)));
+                    m_currentComponent.setObsoleteFactoryComponentFactory("true".equals(attributes.getAttribute(NAMESPACE_URI_1_0_FELIX_EXTENSIONS, OBSOLETE_FACTORY_COMPONENT_FACTORY)));
+                    m_currentComponent.setConfigureWithInterfaces("true".equals(attributes.getAttribute(NAMESPACE_URI_1_0_FELIX_EXTENSIONS, CONFIGURE_WITH_INTERFACES)));
 
                     // Add this component to the list
                     m_components.add( m_currentComponent );
@@ -261,7 +289,7 @@
                 else if ( localName.equals( "implementation" ) )
                 {
                     // Set the implementation class name (mandatory)
-                    m_currentComponent.setImplementationClassName( attrib.getProperty( "class" ) );
+                    m_currentComponent.setImplementationClassName( attributes.getAttribute( "class" ) );
                 }
                 // 112.4.5 [...] Property Elements
                 else if ( localName.equals( "property" ) )
@@ -269,18 +297,18 @@
                     PropertyMetadata prop = new PropertyMetadata();
 
                     // name attribute is mandatory
-                    prop.setName( attrib.getProperty( "name" ) );
+                    prop.setName( attributes.getAttribute( "name" ) );
 
                     // type attribute is optional
-                    if ( attrib.getProperty( "type" ) != null )
+                    if ( attributes.getAttribute( "type" ) != null )
                     {
-                        prop.setType( attrib.getProperty( "type" ) );
+                        prop.setType( attributes.getAttribute( "type" ) );
                     }
 
                     // 112.4.5: If the value attribute is specified, the body of the element is ignored.
-                    if ( attrib.getProperty( "value" ) != null )
+                    if ( attributes.getAttribute( "value" ) != null )
                     {
-                        prop.setValue( attrib.getProperty( "value" ) );
+                        prop.setValue( attributes.getAttribute( "value" ) );
                         m_currentComponent.addProperty( prop );
                     }
                     else
@@ -292,7 +320,7 @@
                 // 112.4.5 Properties [...] Elements
                 else if ( localName.equals( "properties" ) )
                 {
-                    readPropertiesEntry( attrib.getProperty( "entry" ) );
+                    readPropertiesEntry( attributes.getAttribute( "entry" ) );
                 }
                 // 112.4.6 Service Element
                 else if ( localName.equals( "service" ) )
@@ -301,16 +329,16 @@
                     m_currentService = new ServiceMetadata();
 
                     // servicefactory attribute is optional
-                    if ( attrib.getProperty( "servicefactory" ) != null )
+                    if ( attributes.getAttribute( "servicefactory" ) != null )
                     {
-                        m_currentService.setServiceFactory( attrib.getProperty( "servicefactory" ).equals( "true" ) );
+                        m_currentService.setServiceFactory( attributes.getAttribute( "servicefactory" ).equals( "true" ) );
                     }
 
                     m_currentComponent.setService( m_currentService );
                 }
                 else if ( localName.equals( "provide" ) )
                 {
-                    m_currentService.addProvide( attrib.getProperty( "interface" ) );
+                    m_currentService.addProvide( attributes.getAttribute( "interface" ) );
                 }
 
                 // 112.4.7 Reference element
@@ -319,34 +347,34 @@
                     ReferenceMetadata ref = new ReferenceMetadata();
 
                     // name attribute is optional (since DS 1.1)
-                    if ( attrib.getProperty( "name" ) != null )
+                    if ( attributes.getAttribute( "name" ) != null )
                     {
-                        ref.setName( attrib.getProperty( "name" ) );
+                        ref.setName( attributes.getAttribute( "name" ) );
                     }
 
-                    ref.setInterface( attrib.getProperty( "interface" ) );
+                    ref.setInterface( attributes.getAttribute( "interface" ) );
 
                     // Cardinality
-                    if ( attrib.getProperty( "cardinality" ) != null )
+                    if ( attributes.getAttribute( "cardinality" ) != null )
                     {
-                        ref.setCardinality( attrib.getProperty( "cardinality" ) );
+                        ref.setCardinality( attributes.getAttribute( "cardinality" ) );
                     }
 
-                    if ( attrib.getProperty( "policy" ) != null )
+                    if ( attributes.getAttribute( "policy" ) != null )
                     {
-                        ref.setPolicy( attrib.getProperty( "policy" ) );
+                        ref.setPolicy( attributes.getAttribute( "policy" ) );
                     }
 
-                    if ( attrib.getProperty( "policy-option" ) != null )
+                    if ( attributes.getAttribute( "policy-option" ) != null )
                     {
-                        ref.setPolicyOption( attrib.getProperty( "policy-option" ) );
+                        ref.setPolicyOption( attributes.getAttribute( "policy-option" ) );
                     }
 
                     //if
-                    ref.setTarget( attrib.getProperty( "target" ) );
-                    ref.setBind( attrib.getProperty( "bind" ) );
-                    ref.setUpdated( attrib.getProperty( "updated" ) );
-                    ref.setUnbind( attrib.getProperty( "unbind" ) );
+                    ref.setTarget( attributes.getAttribute( "target" ) );
+                    ref.setBind( attributes.getAttribute( "bind" ) );
+                    ref.setUpdated( attributes.getAttribute( "updated" ) );
+                    ref.setUnbind( attributes.getAttribute( "unbind" ) );
 
                     m_currentComponent.addDependency( ref );
                 }
@@ -504,9 +532,8 @@
         }
 
         // create PropertyMetadata for the properties from the file
-        for ( Iterator pi = props.entrySet().iterator(); pi.hasNext(); )
+        for ( Map.Entry<Object, Object> pEntry: props.entrySet() )
         {
-            Map.Entry pEntry = ( Map.Entry ) pi.next();
             PropertyMetadata prop = new PropertyMetadata();
             prop.setName( String.valueOf( pEntry.getKey() ) );
             prop.setValue( String.valueOf( pEntry.getValue() ) );
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/parser/KXml2SAXHandler.java b/scr/src/main/java/org/apache/felix/scr/impl/parser/KXml2SAXHandler.java
index 6b7857b..9a46f61 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/parser/KXml2SAXHandler.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/parser/KXml2SAXHandler.java
@@ -20,6 +20,8 @@
 

 import java.util.Properties;

 

+import org.apache.felix.scr.impl.parser.KXml2SAXParser.Attributes;

+

 /**

  * Interface for a SAX like handler with kXML

  */

@@ -38,13 +40,13 @@
 	*

 	* @param   uri

 	* @param   localName

-	* @param   attrib

+	* @param   attributes

 	* @exception   ParseException

 	*/

 	void startElement(

 		String uri,

 		String localName,

-		Properties attrib)

+		Attributes attributes)

 		throws ParseException;

 

    /**

diff --git a/scr/src/main/java/org/apache/felix/scr/impl/parser/KXml2SAXParser.java b/scr/src/main/java/org/apache/felix/scr/impl/parser/KXml2SAXParser.java
index f6e9938..ec79086 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/parser/KXml2SAXParser.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/parser/KXml2SAXParser.java
@@ -60,8 +60,9 @@
     public void parseXML( KXml2SAXHandler handler ) throws Exception

     {

 

-        final Stack openElements = new Stack();

+        final Stack<XmlElement> openElements = new Stack<XmlElement>();

         XmlElement currentElement = null;

+        final Attributes attributes = new Attributes();

 

         while ( next() != XmlPullParser.END_DOCUMENT )

         {

@@ -73,13 +74,7 @@
                 currentElement = new XmlElement( getNamespace(), getName(), getLineNumber(), getColumnNumber() );

                 openElements.push( currentElement );

 

-                Properties props = new Properties();

-                for ( int i = 0; i < getAttributeCount(); i++ )

-                {

-                    props.put( getAttributeName( i ), getAttributeValue( i ) );

-                }

-

-                handler.startElement( getNamespace(), getName(), props );

+                handler.startElement( getNamespace(), getName(), attributes );

             }

             else if ( getEventType() == XmlPullParser.END_TAG )

             {

@@ -156,4 +151,15 @@
             return name + "@" + line + ":" + col;

         }

     }

+    

+    public class Attributes {

+    	

+    	public String getAttribute(String name) {

+    		return getAttributeValue("", name);

+    	}

+    	

+    	public String getAttribute(String uri, String name) {

+    		return getAttributeValue(uri, name);

+    	}

+    }

 }

diff --git a/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java b/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java
index bd32067..833dc37 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java
@@ -270,8 +270,9 @@
 
         // service setup
         final ServiceMetadata sm = cm10.getServiceMetadata();
+        sm.validate( cm10 ); // service metadata requires validation to set scope properly
         assertNotNull( "service", sm );
-        assertEquals( "servicefactory", true, sm.isServiceFactory() );
+        assertEquals( "servicefactory", ServiceMetadata.Scope.bundle, sm.getScope() );
         assertEquals( "1 interface", 1, sm.getProvides().length );
         assertEquals( "service interface", "components.all.service", sm.getProvides()[0] );
 
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java b/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
index 130042c..1c77465 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
@@ -535,8 +535,8 @@
                     out.print( "          " );
                     out.println( services[i] );
                 }
-                out.print( "Service Type: " );
-                out.println( component.isServiceFactory() ? "service factory" : "service" );
+                out.print( "Service Scope: " );
+                out.println( component.getServiceScope() );
             }
 
             Reference[] refs = component.getReferences();