[FELIX-4507] Implement new style component factory with modify method (turned off, no tests)

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1591418 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/component/ExtFactoryComponentInstance.java b/scr/src/main/java/org/apache/felix/scr/component/ExtFactoryComponentInstance.java
new file mode 100644
index 0000000..1c4c695
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/component/ExtFactoryComponentInstance.java
@@ -0,0 +1,30 @@
+/*
+ * 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.component;
+
+import java.util.Dictionary;
+
+import org.osgi.service.component.ComponentInstance;
+
+public interface ExtFactoryComponentInstance extends ComponentInstance
+{
+    
+    void modify( Dictionary<String, ?> properties );
+
+}
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 6709d45..010454e 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
@@ -28,6 +28,7 @@
 import java.util.Map;
 
 import org.apache.felix.scr.Component;
+import org.apache.felix.scr.component.ExtFactoryComponentInstance;
 import org.apache.felix.scr.impl.BundleComponentActivator;
 import org.apache.felix.scr.impl.TargetedPID;
 import org.apache.felix.scr.impl.config.ComponentHolder;
@@ -93,14 +94,30 @@
     
     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() );
         m_componentInstances = new IdentityHashMap<SingleComponentManager<S>, SingleComponentManager<S>>();
         m_configuration = new Hashtable<String, Object>();
+        m_nonPersistentFactory = true;
     }
 
 
+    protected boolean verifyDependencyManagers()
+    {
+        if (m_nonPersistentFactory)
+        {
+            return super.verifyDependencyManagers();
+        }
+        return true;    
+    }
+    
     @Override
     public boolean isFactory()
     {
@@ -126,7 +143,7 @@
         cm.activateInternal( getTrackingCount().get() );
 
         instance = cm.getComponentInstance();
-        if ( instance == null || instance.getInstance() == null )
+        if ( instance == null || (m_nonPersistentFactory && instance.getInstance() == null) )
         {
             // activation failed, clean up component manager
             cm.dispose( ComponentConstants.DEACTIVATION_REASON_DISPOSED );
@@ -137,9 +154,43 @@
         {
             m_componentInstances.put( cm, cm );
         }
+        
+        if ( !m_nonPersistentFactory ) 
+        {
+            instance = new ModifyComponentInstance(cm);
+        }
 
         return instance;
     }
+    
+    private static class ModifyComponentInstance implements ExtFactoryComponentInstance
+    {
+        private final SingleComponentManager cm;
+        private long changeCount = 0;
+
+        public ModifyComponentInstance(SingleComponentManager cm)
+        {
+            this.cm = cm;
+        }
+
+        public void dispose()
+        {
+            cm.getComponentInstance().dispose();            
+        }
+
+        public Object getInstance()
+        {
+            final ComponentInstance componentInstance = cm.getComponentInstance();
+            return componentInstance == null? null: componentInstance.getInstance();
+        }
+
+        public void modify(Dictionary<String, ?> properties)
+        {
+            cm.setFactoryProperties( properties );
+            cm.reconfigure();            
+        }
+        
+    }
 
     /**
      * Compares this {@code ComponentFactoryImpl} object to another object.
@@ -153,7 +204,7 @@
      *         {@code ComponentFactoryImpl} and is equal to this object;
      *         {@code false} otherwise.
      */
-   public boolean equals(Object object)
+    public boolean equals(Object object)
     {
         if (!(object instanceof ComponentFactoryImpl))
         {
@@ -234,7 +285,7 @@
         return props;
     }
     
-    public void setServiceProperties( Dictionary serviceProperties )
+    public void setServiceProperties( Dictionary<String, Object> serviceProperties )
     {
         throw new IllegalStateException( "ComponentFactory service properties are immutable" );
     }
@@ -492,7 +543,7 @@
      */
     private SingleComponentManager<S> createComponentManager()
     {
-        return new ComponentFactoryNewInstance<S>( getActivator(), this, getComponentMetadata(), getComponentMethods() );
+        return new SingleComponentManager<S>( getActivator(), this, getComponentMetadata(), getComponentMethods(), m_nonPersistentFactory );
     }
 
 
@@ -507,16 +558,6 @@
         }
     }
 
-    static class ComponentFactoryNewInstance<S> extends SingleComponentManager<S> {
-
-        public ComponentFactoryNewInstance( BundleComponentActivator activator, ComponentHolder componentHolder,
-                ComponentMetadata metadata, ComponentMethods componentMethods )
-        {
-            super( activator, componentHolder, metadata, componentMethods, true );
-        }
-
-    }
-
     public TargetedPID getConfigurationTargetedPID(TargetedPID pid)
     {
         return m_targetedPID;
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 9536ede..9ddcdce 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
@@ -551,39 +551,44 @@
      */
     public void reconfigure( Dictionary<String, Object> configuration, long changeCount, TargetedPID targetedPID )
     {
+        if ( targetedPID == null || !targetedPID.equals( m_targetedPID ) )
+        {
+            m_targetedPID = targetedPID;
+            m_changeCount = -1;
+        }
+        if ( configuration != null )
+        {
+            if ( changeCount <= m_changeCount )
+            {
+                log( LogService.LOG_DEBUG,
+                        "ImmediateComponentHolder out of order configuration updated for pid {0} with existing count {1}, new count {2}",
+                        new Object[] { getConfigurationPid(), m_changeCount, changeCount }, null );
+                return;
+            }
+            m_changeCount = changeCount;
+        }
+        else 
+        {
+            m_changeCount = -1;
+        }
+        // nothing to do if there is no configuration (see FELIX-714)
+        if ( configuration == null && m_configurationProperties == null )
+        {
+            log( LogService.LOG_DEBUG, "No configuration provided (or deleted), nothing to do", null );
+            return;
+        }
+
+        // store the properties
+        m_configurationProperties = configuration;
+
+        reconfigure();
+    }
+
+    void reconfigure()
+    {
         CountDownLatch enableLatch = enableLatchWait();
         try
         {
-            if ( targetedPID == null || !targetedPID.equals( m_targetedPID ) )
-            {
-                m_targetedPID = targetedPID;
-                m_changeCount = -1;
-            }
-            if ( configuration != null )
-            {
-                if ( changeCount <= m_changeCount )
-                {
-                    log( LogService.LOG_DEBUG,
-                            "ImmediateComponentHolder out of order configuration updated for pid {0} with existing count {1}, new count {2}",
-                            new Object[] { getConfigurationPid(), m_changeCount, changeCount }, null );
-                    return;
-                }
-                m_changeCount = changeCount;
-            }
-            else 
-            {
-                m_changeCount = -1;
-            }
-            // nothing to do if there is no configuration (see FELIX-714)
-            if ( configuration == null && m_configurationProperties == null )
-            {
-                log( LogService.LOG_DEBUG, "No configuration provided (or deleted), nothing to do", null );
-                return;
-            }
-
-            // store the properties
-            m_configurationProperties = configuration;
-
             // clear the current properties to force using the configuration data
             m_properties = null;
 
@@ -600,7 +605,7 @@
 
             // if the configuration has been deleted but configuration is required
             // this component must be deactivated
-            if ( configuration == null && getComponentMetadata().isConfigurationRequired() )
+            if ( m_configurationProperties == null && getComponentMetadata().isConfigurationRequired() )
             {
                 //deactivate and remove service listeners
                 deactivateInternal( ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_DELETED, true, false );
@@ -628,7 +633,7 @@
                 {
                     // SCR 112.7.1 - deactivate if configuration is deleted or no modified method declared
                     log( LogService.LOG_DEBUG, "Deactivating and Activating to reconfigure from configuration", null );
-                    int reason = ( configuration == null ) ? ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_DELETED
+                    int reason = ( m_configurationProperties == null ) ? ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_DELETED
                             : ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_MODIFIED;
 
                     // FELIX-2368: cycle component immediately, reconfigure() is
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/ComponentFactoryTest.java b/scr/src/test/java/org/apache/felix/scr/integration/ComponentFactoryTest.java
index 3bc3081..edf7bb1 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/ComponentFactoryTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/ComponentFactoryTest.java
@@ -667,5 +667,11 @@
         
         s1.drop();
     }
+    
+    private Object getComponentManagerFromExtComponentInstance( Object extIinstance )
+    {
+        return getFieldValue( extIinstance, "cm");
+    }
+
 
 }