[FELIX-4406] [FELIX-4506] [FELIX-4507] finish r6 xml processing, felix extension processing, and test persistent factory component

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1591421 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
index 91a9b16..5d82523 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
@@ -237,7 +237,7 @@
             stream = descriptorURL.openStream();
 
             BufferedReader in = new BufferedReader( new InputStreamReader( stream, "UTF-8" ) );
-            XmlHandler handler = new XmlHandler( m_bundle, this );
+            XmlHandler handler = new XmlHandler( m_bundle, this, getConfiguration().isFactoryEnabled(), getConfiguration().keepInstances() );
             KXml2SAXParser parser;
 
             parser = new KXml2SAXParser( in );
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java b/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
index c40ab5f..435d323 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
@@ -544,7 +544,7 @@
             // 112.2.4 SCR must register a Component Factory
             // service on behalf of the component
             // as soon as the component factory is satisfied
-            if ( !activator.getConfiguration().isFactoryEnabled() )
+            if ( !metadata.isObsoleteFactoryComponentFactory() )
             {
                 holder = new ComponentFactoryImpl(activator, metadata );
             }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java b/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java
index 2615fa4..1efe84b 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java
@@ -38,7 +38,7 @@
  * {@link org.apache.felix.scr.impl.BundleComponentActivator} and the
  * {@link org.apache.felix.scr.impl.ComponentRegistry}.
  */
-public interface ComponentHolder
+public interface ComponentHolder<S>
 {
 
     /**
@@ -125,5 +125,5 @@
      * Informs the holder that the component has been disposed as a result of
      * calling the dispose method.
      */
-    void disposed( SingleComponentManager component );
+    void disposed( SingleComponentManager<S> component );
 }
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 b921092..3c878b4 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
@@ -54,7 +54,7 @@
  * <code>service.factoryPid</code> equals the component name.</li>
  * </ul>
  */
-public class ConfigurableComponentHolder<S> implements ComponentHolder, SimpleLogger
+public class ConfigurableComponentHolder<S> implements ComponentHolder<S>, SimpleLogger
 {
 
     /**
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 5c1d1e9..a9e75db 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
@@ -1389,7 +1389,7 @@
      *      <code>source</code> is <code>null</code> or empty and
      *      <code>target</code> was <code>null</code>.
      */
-    protected static Dictionary<String, Object> copyTo( Dictionary<String, Object> target, Dictionary<String, Object> source )
+    protected static Dictionary<String, Object> copyTo( Dictionary<String, Object> target, Dictionary<String, ?> source )
     {
         return copyTo( target, source, true );
     }
@@ -1413,7 +1413,7 @@
      *         <code>target</code> was <code>null</code> or all properties are
      *         private and had not to be copied
      */
-    protected static Dictionary<String, Object> copyTo( Dictionary<String, Object> target, final Dictionary<String, Object> source, final boolean allProps )
+    protected static Dictionary<String, Object> copyTo( Dictionary<String, Object> target, final Dictionary<String, ?> source, final boolean allProps )
     {
         if ( target == null )
         {
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 b210cdc..fa7d72c 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
@@ -52,13 +52,12 @@
  * class directly as the holder for component instances created by the
  * {@link #newInstance(Dictionary)} method.
  * <p>
- * Finally, if the <code>ds.factory.enabled</code> bundle context property is
- * set to <code>true</code>, component instances can be created by factory
- * configurations. This functionality is present for backwards compatibility
- * with earlier releases of the Apache Felix Declarative Services implementation.
- * But keep in mind, that this is non-standard behaviour.
+ * This class implements spec-compliant component factories and the felix 
+ * "persistent" component factory, where the factory is always registered whether or
+ * not all dependencies are present and the created components also persist whether or 
+ * not the dependencies are present to allow the component instance to exist.
  */
-public class ComponentFactoryImpl<S> extends AbstractComponentManager<S> implements ComponentFactory, ComponentHolder
+public class ComponentFactoryImpl<S> extends AbstractComponentManager<S> implements ComponentFactory, ComponentHolder<S>
 {
 
     /**
@@ -94,12 +93,6 @@
     
     protected TargetedPID m_targetedPID;
 
-    /**
-     * True if this is a R5 spec component factory
-     * False if this is a persistent component factory.
-     */
-    private boolean m_nonPersistentFactory;
-
     public ComponentFactoryImpl( BundleComponentActivator activator, ComponentMetadata metadata )
     {
         super( activator, metadata, new ComponentMethods() );
@@ -132,8 +125,7 @@
         log( LogService.LOG_DEBUG, "Creating new instance from component factory {0} with configuration {1}",
                 new Object[] {getComponentMetadata().getName(), dictionary}, null );
 
-        ComponentInstance instance;
-        cm.setFactoryProperties( ( Dictionary<String, Object> ) dictionary );
+        cm.setFactoryProperties( dictionary );
         //configure the properties
         cm.reconfigure( m_configuration, m_changeCount, m_targetedPID );
         // enable
@@ -141,12 +133,20 @@
         //activate immediately
         cm.activateInternal( getTrackingCount().get() );
 
-        instance = cm.getComponentInstance();
-        if ( instance == null || (!getComponentMetadata().isPersistentFactoryComponent() && instance.getInstance() == null) )
+        ComponentInstance instance;
+        if ( getComponentMetadata().isPersistentFactoryComponent() ) 
         {
-            // activation failed, clean up component manager
-            cm.dispose( ComponentConstants.DEACTIVATION_REASON_DISPOSED );
-            throw new ComponentException( "Failed activating component" );
+            instance = new ModifyComponentInstance<S>(cm);
+        }
+        else
+        {
+        	instance = cm.getComponentInstance();
+        	if ( instance == null ||  instance.getInstance() == null )
+        	{
+        		// activation failed, clean up component manager
+        		cm.dispose( ComponentConstants.DEACTIVATION_REASON_DISPOSED );
+        		throw new ComponentException( "Failed activating component" );
+        	}
         }
 
         synchronized ( m_componentInstances )
@@ -154,27 +154,21 @@
             m_componentInstances.put( cm, cm );
         }
         
-        if ( getComponentMetadata().isPersistentFactoryComponent() ) 
-        {
-            instance = new ModifyComponentInstance(cm);
-        }
-
         return instance;
     }
     
-    private static class ModifyComponentInstance implements ExtFactoryComponentInstance
+    private static class ModifyComponentInstance<S> implements ExtFactoryComponentInstance
     {
-        private final SingleComponentManager cm;
-        private long changeCount = 0;
+        private final SingleComponentManager<S> cm;
 
-        public ModifyComponentInstance(SingleComponentManager cm)
+        public ModifyComponentInstance(SingleComponentManager<S> cm)
         {
             this.cm = cm;
         }
 
         public void dispose()
         {
-            cm.getComponentInstance().dispose();            
+            cm.dispose();            
         }
 
         public Object getInstance()
@@ -205,12 +199,12 @@
      */
     public boolean equals(Object object)
     {
-        if (!(object instanceof ComponentFactoryImpl))
+        if (!(object instanceof ComponentFactoryImpl<?>))
         {
             return false;
         }
 
-        ComponentFactoryImpl other = (ComponentFactoryImpl) object;
+        ComponentFactoryImpl<?> other = (ComponentFactoryImpl<?>) object;
         return getComponentMetadata().getName().equals(other.getComponentMetadata().getName());
     }
     
@@ -355,7 +349,7 @@
 
             // So far, we were configured: clear the current configuration.
             m_hasConfiguration = false;
-            m_configuration = new Hashtable();
+            m_configuration = new Hashtable<String, Object>();
 
             log( LogService.LOG_DEBUG, "Current component factory state={0}", new Object[] {getState()}, null );
 
@@ -507,7 +501,7 @@
     {
         List<AbstractComponentManager<S>> cms = new ArrayList<AbstractComponentManager<S>>( );
         getComponentManagers( m_componentInstances, cms );
-        for ( AbstractComponentManager acm: cms )
+        for ( AbstractComponentManager<S> acm: cms )
         {
             acm.dispose( reason );
         }
@@ -522,7 +516,8 @@
     }
 
 
-    public void disposed( SingleComponentManager component )
+    @Override
+    public void disposed( SingleComponentManager<S> component )
     {
         synchronized ( m_componentInstances )
         {
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ConfigurationComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ConfigurationComponentFactoryImpl.java
index 41406af..9c7fd58 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ConfigurationComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ConfigurationComponentFactoryImpl.java
@@ -35,20 +35,14 @@
 import org.osgi.service.log.LogService;
 
 /**
- * The <code>ComponentFactoryImpl</code> extends the {@link org.apache.felix.scr.impl.manager.AbstractComponentManager}
- * class to implement the component factory functionality. As such the
- * OSGi Declarative Services <code>ComponentFactory</code> interface is
- * implemented.
- * <p>
- * In addition the {@link org.apache.felix.scr.impl.config.ComponentHolder} interface is implemented to use this
- * class directly as the holder for component instances created by the
- * {@link #newInstance(java.util.Dictionary)} method.
- * <p>
- * Finally, if the <code>ds.factory.enabled</code> bundle context property is
- * set to <code>true</code>, component instances can be created by factory
- * configurations. This functionality is present for backwards compatibility
- * with earlier releases of the Apache Felix Declarative Services implementation.
- * But keep in mind, that this is non-standard behaviour.
+ * This class implements the Felix non-standard and obsolete extended compponent factory
+ * that allows factory instances to be created through config admin using the component factory pid
+ * as a factory pid.  Do not use this for new code, use a plain component instead.
+ * Use of this behavior can be turned on globally with the framework config or config admin
+ * property <code>ds.factory.enabled</code> bundle context property
+ * set to <code>true</code> or turned on per-component with a component descriptor attribute
+ * xmlns:felix="http://felix.apache.org/xmlns/scr/extensions/v1.0.0"
+ * felix:obsoleteFactoryComponentFactory='true'
  */
 public class ConfigurationComponentFactoryImpl<S> extends ComponentFactoryImpl<S>
 {
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
index 9ddcdce..61ca8b8 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
@@ -405,7 +405,7 @@
         }
     }
 
-    protected void setFactoryProperties( Dictionary<String, Object> dictionary )
+    protected void setFactoryProperties( Dictionary<String, ?> dictionary )
     {
         m_factoryProperties = copyTo( null, dictionary );
     }
@@ -936,7 +936,7 @@
 
     private boolean keepInstances()
     {
-        return getActivator() != null && getActivator().getConfiguration().keepInstances();
+        return getComponentMetadata().isDelayedKeepInstances();
     }
 
     public long getChangeCount()
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 5a35d8b..c0d3208 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
@@ -118,6 +118,7 @@
     private boolean m_deleteCallsModify;
     private boolean m_obsoleteFactoryComponentFactory;
     private boolean m_configureWithInterfaces;
+    private boolean m_delayedKeepInstances;
 
     // Flag that is set once the component is verified (its properties cannot be changed)
     private boolean m_validated = false;
@@ -394,11 +395,15 @@
 	}
 
 	public void setConfigureWithInterfaces(boolean configureWithInterfaces) {
+		this.m_configureWithInterfaces = configureWithInterfaces;
+	}
+
+	public void setDelayedKeepInstances(boolean delayedKeepInstances) {
         if ( m_validated )
         {
             return;
         }
-		this.m_configureWithInterfaces = configureWithInterfaces;
+		this.m_delayedKeepInstances = delayedKeepInstances;
 	}
 
     
@@ -758,6 +763,10 @@
 		return m_configureWithInterfaces;
 	}
 
+	public boolean isDelayedKeepInstances() {
+		return m_delayedKeepInstances;
+	}
+
 	/**
      * Method used to verify if the semantics of this metadata are correct
      */
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java b/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java
index dd44dcc..c6d53d6 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java
@@ -29,6 +29,8 @@
  */
 public class ReferenceMetadata
 {
+	public enum ReferenceScope {bundle, prototype}
+	
     // constant for option single reference - 0..1
     public static final String CARDINALITY_0_1 = "0..1";
 
@@ -42,7 +44,7 @@
     public static final String CARDINALITY_1_N = "1..n";
 
     // set of valid cardinality settings
-    private static final Set CARDINALITY_VALID;
+    private static final Set<String> CARDINALITY_VALID;
 
     // constant for static policy
     public static final String POLICY_STATIC = "static";
@@ -51,7 +53,7 @@
     public static final String POLICY_DYNAMIC = "dynamic";
 
     // set of valid policy settings
-    private static final Set POLICY_VALID;
+    private static final Set<String> POLICY_VALID;
 
     // constant for reluctant policy option
     public static final String POLICY_OPTION_RELUCTANT = "reluctant";
@@ -60,7 +62,7 @@
     public static final String POLICY_OPTION_GREEDY = "greedy";
 
     // set of valid policy option settings
-    private static final Set POLICY_OPTION_VALID;
+    private static final Set<String> POLICY_OPTION_VALID;
 
     // Name for the reference (required)
     private String m_name = null;
@@ -88,9 +90,9 @@
 
     // Policy option attribute (optional, default = reluctant)
     private String m_policy_option = null;
-
-    // Flag that is set once the component is verified (its properties cannot be changed)
-    private boolean m_validated = false;
+    
+    private String m_scopeName;
+    private ReferenceScope m_scope = ReferenceScope.bundle;
 
     // Flags that store the values passed as strings
     private boolean m_isStatic = true;
@@ -98,19 +100,22 @@
     private boolean m_isMultiple = false;
     private boolean m_isReluctant = true;
 
+    // Flag that is set once the component is verified (its properties cannot be changed)
+    private boolean m_validated = false;
+
     static
     {
-        CARDINALITY_VALID = new TreeSet();
+        CARDINALITY_VALID = new TreeSet<String>();
         CARDINALITY_VALID.add( CARDINALITY_0_1 );
         CARDINALITY_VALID.add( CARDINALITY_0_N );
         CARDINALITY_VALID.add( CARDINALITY_1_1 );
         CARDINALITY_VALID.add( CARDINALITY_1_N );
 
-        POLICY_VALID = new TreeSet();
+        POLICY_VALID = new TreeSet<String>();
         POLICY_VALID.add( POLICY_DYNAMIC );
         POLICY_VALID.add( POLICY_STATIC );
 
-        POLICY_OPTION_VALID = new TreeSet();
+        POLICY_OPTION_VALID = new TreeSet<String>();
         POLICY_OPTION_VALID.add( POLICY_OPTION_RELUCTANT );
         POLICY_OPTION_VALID.add( POLICY_OPTION_GREEDY );
     }
@@ -272,10 +277,18 @@
         m_unbind = unbind;
     }
 
+	public void setScope(String scopeName) {
+        if ( m_validated )
+        {
+            return;
+        }
+		this.m_scopeName = scopeName;
+	}
+
 
     /////////////////////////////////////////////// getters ///////////////////////////////////
 
-    /**
+	/**
      * Returns the name of the reference
      *
      * @return A string containing the reference's name
@@ -441,6 +454,10 @@
     }
 
 
+    public ReferenceScope getScope() {
+		return m_scope;
+	}
+
     /**
      *  Method used to verify if the semantics of this metadata are correct
      *
@@ -502,6 +519,21 @@
             throw componentMetadata.validationFailure( "updated method declaration requires DS 1.2 or later namespace " );
         }
 
+        if (m_scopeName != null) {
+        	if (componentMetadata.getNamespaceCode() < XmlHandler.DS_VERSION_1_3)
+        	{
+        		throw componentMetadata.validationFailure( "reference scope can be set only for DS >= 1.3");
+        	}
+        	try 
+        	{
+        		m_scope = ReferenceScope.valueOf(m_scopeName);
+        	}
+        	catch (IllegalArgumentException e)
+        	{
+        		throw componentMetadata.validationFailure( "reference scope must be 'bundle' or 'prototype' not " + m_scopeName);
+       		
+        	}
+        }
         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 6853996..7c6f62c 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
@@ -34,7 +34,8 @@
 	// 112.4.6 Flag that indicates if the service is a ServiceFactory
 	private Boolean m_serviceFactory;
 	
-	private Scope m_scope;
+	private String m_scopeName;
+	private Scope m_scope = Scope.singleton;
 
 	// List of provided interfaces
 	private List<String> m_provides = new ArrayList<String>();
@@ -55,11 +56,11 @@
 		m_serviceFactory = serviceFactory;
 	}
 	
-	public void setScope(Scope scope) {
+	public void setScope(String scopeName) {
 		if(m_validated) {
 			return;
 		}
-		this.m_scope = scope;
+		this.m_scopeName = scopeName;
 	}
 
 	
@@ -101,10 +102,6 @@
             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)
@@ -113,9 +110,20 @@
         	}
         	m_scope = m_serviceFactory? Scope.bundle: Scope.singleton;
         }
-        if (m_scope == null) 
+        if ( m_scopeName != null )
         {
-        	m_scope = Scope.singleton;
+        	if (componentMetadata.getNamespaceCode() < XmlHandler.DS_VERSION_1_3)
+        	{
+            	throw componentMetadata.validationFailure("service scope can only be specified in version 1.3 and later");
+        	}
+        	try
+        	{
+        		m_scope = Scope.valueOf(m_scopeName);
+        	}
+        	catch (IllegalArgumentException e)
+        	{
+            	throw componentMetadata.validationFailure("Service scope may be only 'singleton' 'bundle' or 'prototype' not " + m_scopeName);
+        	}
         }
         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 f193527..32394c7 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
@@ -29,6 +29,7 @@
 import java.util.Map;
 import java.util.Properties;
 import org.apache.felix.scr.impl.helper.Logger;
+import org.apache.felix.scr.impl.metadata.ServiceMetadata.Scope;
 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;
@@ -78,6 +79,8 @@
     
     public static final String CONFIGURE_WITH_INTERFACES = "configureWithInterfaces";
 
+    public static final String DELAYED_KEEP_INSTANCES = "delayedKeepInstances";
+
     // namespace code for non-DS namespace
     public static final int DS_VERSION_NONE = -1;
 
@@ -107,6 +110,10 @@
 
     // logger for any messages
     private final Logger m_logger;
+    
+    private final boolean m_globalObsoleteFactoryComponentFactory;
+    
+    private final boolean m_globalDelayedKeepInstances;
 
     // A reference to the current component
     private ComponentMetadata m_currentComponent;
@@ -144,10 +151,12 @@
 
     // creates an instance with the bundle owning the component descriptor
     // file parsed by this instance
-    public XmlHandler( Bundle bundle, Logger logger )
+    public XmlHandler( Bundle bundle, Logger logger, boolean globalObsoleteFactoryComponentFactory, boolean globalDelayedKeepInstances )
     {
         m_bundle = bundle;
         m_logger = logger;
+        m_globalObsoleteFactoryComponentFactory = globalObsoleteFactoryComponentFactory;
+        m_globalDelayedKeepInstances = globalDelayedKeepInstances;
     }
 
 
@@ -270,8 +279,9 @@
                     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.setObsoleteFactoryComponentFactory(m_globalObsoleteFactoryComponentFactory ||  "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)));
+                    m_currentComponent.setDelayedKeepInstances(m_globalDelayedKeepInstances || "true".equals(attributes.getAttribute(NAMESPACE_URI_1_0_FELIX_EXTENSIONS, DELAYED_KEEP_INSTANCES)));
 
                     // Add this component to the list
                     m_components.add( m_currentComponent );
@@ -333,6 +343,11 @@
                     {
                         m_currentService.setServiceFactory( attributes.getAttribute( "servicefactory" ).equals( "true" ) );
                     }
+                    
+                    if ( attributes.getAttribute( "scope" ) != null )
+                    {
+                    	m_currentService.setScope( attributes.getAttribute( "scope" ) );
+                    }
 
                     m_currentComponent.setService( m_currentService );
                 }
@@ -370,6 +385,11 @@
                         ref.setPolicyOption( attributes.getAttribute( "policy-option" ) );
                     }
 
+                    if ( attributes.getAttribute( "scope" ) != null )
+                    {
+                        ref.setScope( attributes.getAttribute( "scope" ) );
+                    }
+
                     //if
                     ref.setTarget( attributes.getAttribute( "target" ) );
                     ref.setBind( attributes.getAttribute( "bind" ) );
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 ec79086..c9d2ad8 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
@@ -23,7 +23,9 @@
 import java.util.Properties;

 import java.util.Stack;

 

+import org.apache.felix.scr.impl.helper.Logger;

 import org.kxml2.io.KXmlParser;

+import org.osgi.service.log.LogService;

 import org.xmlpull.v1.XmlPullParser;

 import org.xmlpull.v1.XmlPullParserException;

 

@@ -161,5 +163,6 @@
     	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 833dc37..56c0b38 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
@@ -382,7 +382,7 @@
         {
             final KXml2SAXParser parser = new KXml2SAXParser( reader );
 
-            XmlHandler handler = new XmlHandler( new MockBundle(), logger );
+            XmlHandler handler = new XmlHandler( new MockBundle(), logger, false, false );
             parser.parseXML( handler );
 
             return handler.getComponentMetadataList();
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/PersistentComponentFactoryTest.java b/scr/src/test/java/org/apache/felix/scr/integration/PersistentComponentFactoryTest.java
new file mode 100644
index 0000000..c7b11ed
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/integration/PersistentComponentFactoryTest.java
@@ -0,0 +1,664 @@
+/*
+ * 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.scr.integration;
+
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.apache.felix.scr.Component;
+import org.apache.felix.scr.integration.components.SimpleComponent;
+import org.apache.felix.scr.integration.components.SimpleServiceImpl;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.component.ComponentConstants;
+import org.osgi.service.component.ComponentException;
+import org.osgi.service.component.ComponentFactory;
+import org.osgi.service.component.ComponentInstance;
+import org.osgi.service.log.LogService;
+
+
+@RunWith(JUnit4TestRunner.class)
+public class PersistentComponentFactoryTest extends ComponentTestBase
+{
+
+    private static final String PROP_NAME_FACTORY = ComponentTestBase.PROP_NAME + ".factory";
+
+    static
+    {
+        descriptorFile = "/integration_test_persistent_factory_components.xml";
+        // uncomment to enable debugging of this test class
+//        paxRunnerVmOption = DEBUG_VM_OPTION;
+    }
+
+    @Test
+    public void test_component_factory() throws InvalidSyntaxException
+    {
+        final String componentname = "factory.component";
+        final String componentfactory = "factory.component.factory";
+
+        final Component component = findComponentByName( componentname );
+
+        TestCase.assertNotNull( component );
+        TestCase.assertFalse( component.isDefaultEnabled() );
+
+        TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        component.enable();
+        delay();
+
+        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        final ServiceReference[] refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(), "("
+            + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
+        TestCase.assertNotNull( refs );
+        TestCase.assertEquals( 1, refs.length );
+        final ComponentFactory factory = ( ComponentFactory ) bundleContext.getService( refs[0] );
+        TestCase.assertNotNull( factory );
+
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
+        final ComponentInstance instance = factory.newInstance( props );
+        TestCase.assertNotNull( instance );
+
+        TestCase.assertNotNull( instance.getInstance() );
+        TestCase.assertEquals( SimpleComponent.INSTANCE, instance.getInstance() );
+        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
+
+        final Map<?, ?> instanceMap = ( Map<?, ?> ) getFieldValue( component, "m_componentInstances" );
+        TestCase.assertNotNull( instanceMap );
+        TestCase.assertEquals( 1, instanceMap.size() );
+
+        final Object instanceManager = getComponentManagerFromExtComponentInstance( instance );
+        TestCase.assertTrue( instanceMap.containsValue( instanceManager ) );
+
+        // check registered components
+        final Component[] allFactoryComponents = findComponentsByName( componentname );
+        TestCase.assertNotNull( allFactoryComponents );
+        TestCase.assertEquals( 2, allFactoryComponents.length );
+        for ( int i = 0; i < allFactoryComponents.length; i++ )
+        {
+            final Component c = allFactoryComponents[i];
+            if ( c.getId() == component.getId() )
+            {
+                TestCase.assertEquals( Component.STATE_FACTORY, c.getState() );
+            }
+            else if ( c.getId() == SimpleComponent.INSTANCE.m_id )
+            {
+                TestCase.assertEquals( Component.STATE_ACTIVE, c.getState() );
+            }
+            else
+            {
+                TestCase.fail( "Unexpected Component " + c );
+            }
+        }
+
+        instance.dispose();
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( instance.getInstance() ); // SCR 112.12.6.2
+
+        TestCase.assertEquals( 0, instanceMap.size() );
+        TestCase.assertFalse( instanceMap.containsValue( instanceManager ) );
+    }
+
+
+    @Test
+    public void test_component_factory_disable_factory() throws InvalidSyntaxException
+    {
+        // tests components remain alive after factory has been disabled
+
+        final String componentname = "factory.component";
+        final String componentfactory = "factory.component.factory";
+
+        final Component component = findComponentByName( componentname );
+
+        TestCase.assertNotNull( component );
+        TestCase.assertFalse( component.isDefaultEnabled() );
+
+        TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        component.enable();
+        delay();
+
+        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        final ServiceReference[] refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(), "("
+            + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
+        TestCase.assertNotNull( refs );
+        TestCase.assertEquals( 1, refs.length );
+        final ComponentFactory factory = ( ComponentFactory ) bundleContext.getService( refs[0] );
+        TestCase.assertNotNull( factory );
+
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
+        final ComponentInstance instance = factory.newInstance( props );
+        TestCase.assertNotNull( instance );
+
+        TestCase.assertNotNull( instance.getInstance() );
+        TestCase.assertEquals( SimpleComponent.INSTANCE, instance.getInstance() );
+        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
+
+        final Map<?, ?> instanceMap = ( Map<?, ?> ) getFieldValue( component, "m_componentInstances" );
+        TestCase.assertNotNull( instanceMap );
+        TestCase.assertEquals( 1, instanceMap.size() );
+
+        final Object instanceManager = getComponentManagerFromExtComponentInstance( instance );
+        TestCase.assertTrue( instanceMap.containsValue( instanceManager ) );
+
+        // disable the factory
+        component.disable();
+        delay();
+
+        // factory is disabled but the instance is still alive
+        TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+        TestCase.assertNotNull( SimpleComponent.INSTANCE );
+        TestCase.assertEquals( 1, instanceMap.size() );
+        TestCase.assertTrue( instanceMap.containsValue( instanceManager ) );
+
+        instance.dispose();
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( instance.getInstance() ); // SCR 112.12.6.2
+
+        TestCase.assertEquals( 0, instanceMap.size() );
+        TestCase.assertFalse( instanceMap.containsValue( instanceManager ) );
+    }
+
+
+    @Test
+    public void test_component_factory_newInstance_failure() throws InvalidSyntaxException
+    {
+        final String componentname = "factory.component";
+        final String componentfactory = "factory.component.factory";
+
+        final Component component = findComponentByName( componentname );
+
+        TestCase.assertNotNull( component );
+        TestCase.assertFalse( component.isDefaultEnabled() );
+
+        TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        component.enable();
+        delay();
+
+        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        final ServiceReference[] refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(), "("
+            + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
+        TestCase.assertNotNull( refs );
+        TestCase.assertEquals( 1, refs.length );
+        final ComponentFactory factory = ( ComponentFactory ) bundleContext.getService( refs[0] );
+        TestCase.assertNotNull( factory );
+
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
+        props.put( SimpleComponent.PROP_ACTIVATE_FAILURE, "Requested Failure" );
+        final ComponentInstance instance = factory.newInstance( props );
+        TestCase.assertNotNull( instance );
+
+        final Map<?, ?> instanceMap = ( Map<?, ?> ) getFieldValue( component, "m_componentInstances" );
+        TestCase.assertNotNull( instanceMap );
+        TestCase.assertEquals( 1, instanceMap.size() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+    }
+
+
+    @Test
+    public void test_component_factory_require_configuration() throws InvalidSyntaxException
+    {
+        final String componentname = "factory.component.configuration";
+        final String componentfactory = "factory.component.factory.configuration";
+
+        // ensure there is no configuration for the component
+        deleteConfig( componentname );
+        delay();
+
+        final Component component = findComponentByName( componentname );
+
+        TestCase.assertNotNull( component );
+        TestCase.assertFalse( component.isDefaultEnabled() );
+
+        TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        component.enable();
+        delay();
+
+        TestCase.assertEquals( Component.STATE_UNSATISFIED, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        // At this point, since we don't have created the configuration, then the ComponentFactory
+        // should not be available.
+        
+        ServiceReference[] refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(), "("
+            + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
+        TestCase.assertNull( refs );
+        
+        // supply configuration now and ensure active
+        configure( componentname );
+        delay();        
+
+        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        // get the component factory service
+        refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(), "("
+            + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
+        TestCase.assertNotNull( refs );
+        TestCase.assertEquals( 1, refs.length );
+        final ComponentFactory factory = ( ComponentFactory ) bundleContext.getService( refs[0] );
+        TestCase.assertNotNull( factory );
+
+        // create an instance
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
+        final ComponentInstance instance = factory.newInstance( props );
+        TestCase.assertNotNull( instance );
+
+        final Object instanceObject = instance.getInstance();
+        TestCase.assertNotNull( instanceObject );
+        TestCase.assertEquals( SimpleComponent.INSTANCE, instanceObject );
+        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
+        TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );                        
+
+        final Map<?, ?> instanceMap = ( Map<?, ?> ) getFieldValue( component, "m_componentInstances" );
+        TestCase.assertNotNull( instanceMap );
+        TestCase.assertEquals( 1, instanceMap.size() );
+
+        final Object instanceManager = getComponentManagerFromExtComponentInstance( instance );
+        TestCase.assertTrue( instanceMap.containsValue( instanceManager ) );
+
+        // delete config, ensure factory is not active anymore and component instance not changed
+        deleteConfig( componentname );
+        delay();
+        TestCase.assertEquals( Component.STATE_UNSATISFIED, component.getState() );
+
+        TestCase.assertNotNull( instance.getInstance() );
+        TestCase.assertEquals( SimpleComponent.INSTANCE, instance.getInstance() );
+        TestCase.assertEquals( instanceObject, instance.getInstance() );
+        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
+        TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+
+        instance.dispose();
+        TestCase.assertNull( SimpleComponent.INSTANCE ); // component is deactivated
+        TestCase.assertNull( instance.getInstance() ); // SCR 112.12.6.2
+
+        // with removal of the factory, the created instance should also be removed
+        TestCase.assertEquals( 0, instanceMap.size() );
+        TestCase.assertFalse( instanceMap.containsValue( instanceManager ) );
+    }
+
+    @Test
+    public void test_component_factory_reference() throws InvalidSyntaxException
+    {
+        final String componentname = "factory.component.reference";
+        final String componentfactory = "factory.component.factory.reference";
+
+        SimpleServiceImpl.create( bundleContext, "ignored" ).setFilterProperty( "ignored" );
+
+        final Component component = findComponentByName( componentname );
+
+        TestCase.assertNotNull( component );
+        TestCase.assertFalse( component.isDefaultEnabled() );
+
+        TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        component.enable();
+        delay();
+
+        // missing reference, persistent -> created anyway
+        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        // register a service : filterprop=match
+        SimpleServiceImpl match = SimpleServiceImpl.create( bundleContext, "required" ).setFilterProperty( "required" );
+        delay();
+
+        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        final ServiceReference[] refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(), "("
+            + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
+        TestCase.assertNotNull( refs );
+        TestCase.assertEquals( 1, refs.length );
+        final ComponentFactory factory = ( ComponentFactory ) bundleContext.getService( refs[0] );
+        TestCase.assertNotNull( factory );
+
+        // non-overwrite filterprop
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
+        final ComponentInstance instance = factory.newInstance( props );
+        TestCase.assertNotNull( instance );
+
+        TestCase.assertNotNull( instance.getInstance() );
+        TestCase.assertEquals( SimpleComponent.INSTANCE, instance.getInstance() );
+        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
+        TestCase.assertEquals( 1, SimpleComponent.INSTANCE.m_multiRef.size() );
+        TestCase.assertTrue( SimpleComponent.INSTANCE.m_multiRef.contains( match ) );
+
+        final Map<?, ?> instanceMap = ( Map<?, ?> ) getFieldValue( component, "m_componentInstances" );
+        TestCase.assertNotNull( instanceMap );
+        TestCase.assertEquals( 1, instanceMap.size() );
+
+        final Object instanceManager = getComponentManagerFromExtComponentInstance( instance );
+        TestCase.assertTrue( instanceMap.containsValue( instanceManager ) );
+
+        // check registered components
+        final Component[] allFactoryComponents = findComponentsByName( componentname );
+        TestCase.assertNotNull( allFactoryComponents );
+        TestCase.assertEquals( 2, allFactoryComponents.length );
+        for ( int i = 0; i < allFactoryComponents.length; i++ )
+        {
+            final Component c = allFactoryComponents[i];
+            if ( c.getId() == component.getId() )
+            {
+                TestCase.assertEquals( Component.STATE_FACTORY, c.getState() );
+            }
+            else if ( c.getId() == SimpleComponent.INSTANCE.m_id )
+            {
+                TestCase.assertEquals( Component.STATE_ACTIVE, c.getState() );
+            }
+            else
+            {
+                TestCase.fail( "Unexpected Component " + c );
+            }
+        }
+
+        instance.dispose();
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( instance.getInstance() ); // SCR 112.12.6.2
+
+        TestCase.assertEquals( 0, instanceMap.size() );
+        TestCase.assertFalse( instanceMap.containsValue( instanceManager ) );
+
+        // overwritten filterprop
+        Hashtable<String, String> propsNonMatch = new Hashtable<String, String>();
+        propsNonMatch.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
+        propsNonMatch.put( "ref.target", "(filterprop=nomatch)" );
+        final ComponentInstance instanceNonMatch = factory.newInstance( propsNonMatch ); //works even without required dependency
+
+        final SimpleServiceImpl noMatch = SimpleServiceImpl.create( bundleContext, "nomatch" ).setFilterProperty(
+            "nomatch" );
+        delay();
+
+        TestCase.assertNotNull( instanceNonMatch );
+
+        TestCase.assertNotNull( instanceNonMatch.getInstance() );
+        TestCase.assertEquals( SimpleComponent.INSTANCE, instanceNonMatch.getInstance() );
+        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
+
+        TestCase.assertEquals( 1, SimpleComponent.INSTANCE.m_multiRef.size() );
+        TestCase.assertTrue( SimpleComponent.INSTANCE.m_multiRef.contains( noMatch ) );
+
+        // check registered components
+        final Component[] allFactoryComponents2 = findComponentsByName( componentname );
+        TestCase.assertNotNull( allFactoryComponents2 );
+        TestCase.assertEquals( 2, allFactoryComponents2.length );
+        for ( int i = 0; i < allFactoryComponents2.length; i++ )
+        {
+            final Component c = allFactoryComponents2[i];
+            if ( c.getId() == component.getId() )
+            {
+                TestCase.assertEquals( Component.STATE_FACTORY, c.getState() );
+            }
+            else if ( c.getId() == SimpleComponent.INSTANCE.m_id )
+            {
+                TestCase.assertEquals( Component.STATE_ACTIVE, c.getState() );
+            }
+            else
+            {
+                TestCase.fail( "Unexpected Component " + c + " id: " + c.getId() + " current: " + SimpleComponent.INSTANCE.m_id );
+            }
+        }
+
+        match.getRegistration().unregister();
+        delay();
+
+        // check registered components (ComponentFactory aint no longer)
+        final Component[] allFactoryComponents3 = findComponentsByName( componentname );
+        TestCase.assertNotNull( allFactoryComponents3 );
+        TestCase.assertEquals( 2, allFactoryComponents3.length );
+        long lastId = SimpleComponent.INSTANCE.m_id;
+        for ( int i = 0; i < allFactoryComponents3.length; i++ )
+        {
+            final Component c = allFactoryComponents3[i];
+            if ( c.getId() == component.getId() )
+            {
+                TestCase.assertEquals( Component.STATE_UNSATISFIED, c.getState() );
+            }
+            else if ( c.getId() == lastId )
+            {
+                TestCase.assertEquals( Component.STATE_ACTIVE, c.getState() );
+            }
+            else
+            {
+                TestCase.fail( "Unexpected Component " + c );
+            }
+        }
+
+        //it has already been deactivated.... this should cause an exception?
+        noMatch.getRegistration().unregister();
+        delay();
+
+        // check registered components (ComponentFactory is still present)
+        final Component[] allFactoryComponents4 = findComponentsByName( componentname );
+        TestCase.assertNotNull( allFactoryComponents4 );
+        TestCase.assertEquals( 2, allFactoryComponents4.length );
+        for ( int i = 0; i < allFactoryComponents4.length; i++ )
+        {
+            final Component c = allFactoryComponents4[i];
+            if ( c.getId() == component.getId() )
+            {
+                TestCase.assertEquals( Component.STATE_UNSATISFIED, c.getState() );
+            }
+            else if ( c.getId() == lastId )
+            {
+                TestCase.assertEquals( Component.STATE_UNSATISFIED, c.getState() );
+            }
+            else
+            {
+                TestCase.fail( "Unexpected Component " + c );
+            }
+        }
+
+        // deactivated due to unsatisfied reference
+        TestCase.assertNull( instanceNonMatch.getInstance() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        //Check that calling dispose on a deactivated instance has no effect
+        instanceNonMatch.dispose();
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( instanceNonMatch.getInstance() ); // SCR 112.12.6.2
+    }
+
+    @Test
+    public void test_component_factory_referredTo() throws InvalidSyntaxException
+    {
+        //set up the component that refers to the service the factory will create.
+        final String referringComponentName = "ComponentReferringToFactoryObject";
+        final Component referringComponent = findComponentByName( referringComponentName );
+        TestCase.assertNotNull( referringComponent );
+        referringComponent.enable();
+        delay();
+
+        //make sure it's unsatisfied (service is not yet available
+        TestCase.assertEquals( Component.STATE_UNSATISFIED, referringComponent.getState() );
+
+
+        final String componentname = "factory.component.referred";
+        final String componentfactory = "factory.component.factory.referred";
+
+        final Component component = findComponentByName( componentname );
+
+        TestCase.assertNotNull( component );
+        TestCase.assertFalse( component.isDefaultEnabled() );
+
+        TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        component.enable();
+        delay();
+
+        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        final ServiceReference[] refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(), "("
+            + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
+        TestCase.assertNotNull( refs );
+        TestCase.assertEquals( 1, refs.length );
+        final ComponentFactory factory = ( ComponentFactory ) bundleContext.getService( refs[0] );
+        TestCase.assertNotNull( factory );
+
+        // create the factory instance
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put( "service.pid", "myFactoryInstance" );
+        final ComponentInstance instance = factory.newInstance( props );
+        TestCase.assertNotNull( instance );
+
+        TestCase.assertNotNull( instance.getInstance() );
+
+        //The referring service should now be active
+        TestCase.assertEquals( Component.STATE_ACTIVE, referringComponent.getState() );
+
+        instance.dispose();
+        TestCase.assertNull( instance.getInstance() ); // SCR 112.12.6.2
+
+        //make sure it's unsatisfied (service is no longer available)
+        TestCase.assertEquals( Component.STATE_UNSATISFIED, referringComponent.getState() );
+    }
+
+    @Test
+    public void test_component_factory_with_target_filters() throws InvalidSyntaxException
+    {
+        final String componentfactory = "factory.component.reference.targetfilter";
+        final Component component = findComponentByName( componentfactory );
+
+        TestCase.assertNotNull( component );
+        TestCase.assertFalse( component.isDefaultEnabled() );
+
+        TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        component.enable();
+        delay();
+
+        SimpleServiceImpl s1 = SimpleServiceImpl.create(bundleContext, "service1");
+        SimpleServiceImpl s2 = SimpleServiceImpl.create(bundleContext, "service2");
+
+        // supply configuration now and ensure active
+        configure( componentfactory );
+        delay();        
+
+        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+        
+        final ServiceReference[] refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(), "("
+            + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
+        TestCase.assertNotNull( refs );
+        TestCase.assertEquals( 1, refs.length );
+        final ComponentFactory factory = ( ComponentFactory ) bundleContext.getService( refs[0] );
+        TestCase.assertNotNull( factory );
+
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put( PROP_NAME_FACTORY, PROP_NAME_FACTORY );
+        props.put("ref.target", "(value=service2)");
+        final ComponentInstance instance = factory.newInstance( props );
+        TestCase.assertNotNull( instance );
+
+        TestCase.assertNotNull( instance.getInstance() );
+        TestCase.assertEquals( SimpleComponent.INSTANCE, instance.getInstance() );
+        TestCase.assertEquals( PROP_NAME_FACTORY, SimpleComponent.INSTANCE.getProperty( PROP_NAME_FACTORY ) );
+
+        log.log(LogService.LOG_WARNING, "Bound Services: " +  SimpleComponent.INSTANCE.m_multiRef);
+        TestCase.assertFalse( SimpleComponent.INSTANCE.m_multiRef.contains( s1 ) );
+        TestCase.assertTrue( SimpleComponent.INSTANCE.m_multiRef.contains( s2 ) );
+
+        instance.dispose();
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+        TestCase.assertNull( instance.getInstance() ); // SCR 112.12.6.2
+        
+        s2.drop();
+        s1.drop();
+    }
+    
+    @Test
+    public void test_component_factory_set_bundle_location_null() throws Exception
+    {
+        final String componentfactory = "factory.component.reference.targetfilter";
+        final Component component = findComponentByName( componentfactory );
+
+        TestCase.assertNotNull( component );
+        TestCase.assertFalse( component.isDefaultEnabled() );
+
+        TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        component.enable();
+        delay();
+
+        SimpleServiceImpl s1 = SimpleServiceImpl.create(bundleContext, "service1");
+
+        ConfigurationAdmin ca = getConfigurationAdmin();
+        org.osgi.service.cm.Configuration config = ca.getConfiguration( componentfactory, null );
+        config.setBundleLocation( null );
+        delay();
+        if ( isAtLeastR5() )
+        {
+            //check that ConfigurationSupport got a Location changed event and set the bundle location
+            TestCase.assertNotNull( config.getBundleLocation() );
+        } 
+        // supply configuration now and ensure active
+        configure( componentfactory );
+        delay();        
+
+        TestCase.assertEquals( Component.STATE_FACTORY, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+        
+        final ServiceReference[] refs = bundleContext.getServiceReferences( ComponentFactory.class.getName(), "("
+            + ComponentConstants.COMPONENT_FACTORY + "=" + componentfactory + ")" );
+        TestCase.assertNotNull( refs );
+        TestCase.assertEquals( 1, refs.length );
+        final ComponentFactory factory = ( ComponentFactory ) bundleContext.getService( refs[0] );
+        TestCase.assertNotNull( factory );
+        
+        s1.drop();
+    }
+    
+    private Object getComponentManagerFromExtComponentInstance( Object extIinstance )
+    {
+        return getFieldValue( extIinstance, "cm");
+    }
+
+
+}
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/ServiceComponentTest.java b/scr/src/test/java/org/apache/felix/scr/integration/ServiceComponentTest.java
index 5c6b017..9f1c7ba 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/ServiceComponentTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/ServiceComponentTest.java
@@ -42,7 +42,7 @@
     static
     {
         // uncomment to enable debugging of this test class
-        // paxRunnerVmOption = DEBUG_VM_OPTION;
+//         paxRunnerVmOption = DEBUG_VM_OPTION;
     }
 
 
@@ -181,17 +181,17 @@
     public void test_DelayedSimpleComponent_service_keep_instance() throws IOException
     {
         // configure SCR to keep instances
-        Configuration scrConfig = getConfigurationAdmin().getConfiguration( ScrConfiguration.PID, null );
-        Dictionary props = scrConfig.getProperties();
-        if ( props == null )
-        {
-            props = new Hashtable();
-        }
-        props.put( ScrConfiguration.PROP_DELAYED_KEEP_INSTANCES, Boolean.TRUE.toString() );
-        scrConfig.update( props );
-        delay();
+//        Configuration scrConfig = getConfigurationAdmin().getConfiguration( ScrConfiguration.PID, null );
+//        Dictionary props = scrConfig.getProperties();
+//        if ( props == null )
+//        {
+//            props = new Hashtable();
+//        }
+//        props.put( ScrConfiguration.PROP_DELAYED_KEEP_INSTANCES, Boolean.TRUE.toString() );
+//        scrConfig.update( props );
+//        delay();
 
-        final String pid = "DelayedServiceComponent";
+        final String pid = "DelayedKeepInstancesServiceComponent";
 
         // one single component exists without configuration
         final Component component = findComponentByName( pid );
@@ -228,6 +228,6 @@
         TestCase.assertNotNull( SimpleComponent.INSTANCE );
 
         // delete the SCR configuration again
-        scrConfig.delete();
+//        scrConfig.delete();
     }
 }
diff --git a/scr/src/test/resources/integration_test_persistent_factory_components.xml b/scr/src/test/resources/integration_test_persistent_factory_components.xml
new file mode 100644
index 0000000..816e0b1
--- /dev/null
+++ b/scr/src/test/resources/integration_test_persistent_factory_components.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"         
+        xmlns:felix="http://felix.apache.org/xmlns/scr/extensions/v1.0.0">
+
+    <!-- Component Factory Instances -->
+    <scr:component name="factory.component" 
+        felix:persistentFactoryComponent="true"
+        enabled="false"
+        factory="factory.component.factory" >
+        <implementation class="org.apache.felix.scr.integration.components.SimpleComponent" />
+    </scr:component>
+    
+    <!-- Component Factory Instances, requiring configuration -->
+    <scr:component name="factory.component.configuration"
+        felix:persistentFactoryComponent="true"
+        enabled="false"
+        configuration-policy="require"
+        factory="factory.component.factory.configuration" >
+        <implementation class="org.apache.felix.scr.integration.components.SimpleComponent" />
+    </scr:component>
+    
+    <!-- Component Factory Instances, requiring configuration -->
+    <scr:component name="factory.component.reference"
+        felix:persistentFactoryComponent="true"
+        enabled="false"
+        configuration-policy="ignore"
+        factory="factory.component.factory.reference" >
+        <implementation class="org.apache.felix.scr.integration.components.SimpleComponent" />
+        <reference
+            name="ref"
+            interface="org.apache.felix.scr.integration.components.SimpleService"
+            cardinality="1..n"
+            policy="static"
+            bind="bindSimpleService"
+            unbind="unbindSimpleService"
+            target="(filterprop=required)"
+        />
+    </scr:component>
+
+    <!-- Component Factory Instances, instance is referred to by another component -->
+    <scr:component name="factory.component.referred"
+        felix:persistentFactoryComponent="true"
+        enabled="false"
+        factory="factory.component.factory.referred" >
+        <implementation class="org.apache.felix.scr.integration.components.SimpleServiceImpl" />
+        <service>
+            <provide interface="org.apache.felix.scr.integration.components.SimpleService" />
+        </service>
+    </scr:component>
+
+    <!-- component has a reference to service created by the factory.component.referred factory component-->
+    <scr:component name="ComponentReferringToFactoryObject"
+        enabled="false"
+        immediate="true">
+        <implementation class="org.apache.felix.scr.integration.components.SimpleComponent" />
+        <property name="service.pid" value="ComponentReferringToFactoryObject" />
+        <reference
+            name="ref"
+            interface="org.apache.felix.scr.integration.components.SimpleService"
+            cardinality="1..1"
+            policy="dynamic"
+            bind="bindSimpleService"
+            unbind="unbindSimpleService"
+            target="(service.pid=myFactoryInstance)"
+        />
+    </scr:component>
+
+    <!-- Component Factory Instance, requiring configuration + 1 specific Reference -->
+    <scr:component name="factory.component.reference.targetfilter"
+        felix:persistentFactoryComponent="true"
+        enabled="false"
+        configuration-policy="require"
+        factory="factory.component.reference.targetfilter" >
+        <implementation class="org.apache.felix.scr.integration.components.SimpleComponent" />
+        <reference
+            name="ref"
+            interface="org.apache.felix.scr.integration.components.SimpleService"
+            cardinality="1..1"
+            policy="dynamic"
+            bind="bindSimpleService"
+            unbind="unbindSimpleService"
+        />
+    </scr:component>
+
+</components>
diff --git a/scr/src/test/resources/integration_test_simple_components.xml b/scr/src/test/resources/integration_test_simple_components.xml
index 3907051..07de31a 100644
--- a/scr/src/test/resources/integration_test_simple_components.xml
+++ b/scr/src/test/resources/integration_test_simple_components.xml
@@ -121,5 +121,17 @@
         </service>
     </scr:component>
 
+    <scr:component name="DelayedKeepInstancesServiceComponent"
+        enabled="false" immediate="false"
+        configuration-policy="ignore" 
+        xmlns:felix="http://felix.apache.org/xmlns/scr/extensions/v1.0.0"
+        felix:delayedKeepInstances="true" >
+        <implementation class="org.apache.felix.scr.integration.components.SimpleComponent"/>
+        <property name="service.pid" value="ServiceComponent" />
+        <service>
+            <provide interface="java.lang.Object" />
+        </service>
+    </scr:component>
+
 
 </components>