FELIX-3559 Change immediate component manager to register service, then create implementation per spec

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1351039 13f79535-47bb-0310-9956-ffa450edef68
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 2874ef4..0938825 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
@@ -1020,7 +1020,7 @@
         }
 
 
-        Object getService( DelayedComponentManager dcm )
+        Object getService( ImmediateComponentManager dcm )
         {
 //            log( dcm, "getService" );
 //            return null;
@@ -1225,21 +1225,21 @@
                 return;
             }
 
+            acm.registerComponentService();
+
             // 1. Load the component implementation class
             // 2. Create the component instance and component context
             // 3. Bind the target services
             // 4. Call the activate method, if present
-            if ( !acm.createComponent() )
+            if ( ( acm.isImmediate() || acm.getComponentMetadata().isFactory() ) && !acm.createComponent() )
             {
                 // component creation failed, not active now
                 acm.log( LogService.LOG_ERROR, "Component instance could not be created, activation failed", null );
 
                 // set state to unsatisfied
                 acm.changeState( Unsatisfied.getInstance() );
-                return;
             }
 
-            acm.registerComponentService();
         }
 
 
@@ -1329,7 +1329,7 @@
         }
 
 
-        Object getService( DelayedComponentManager dcm )
+        Object getService( ImmediateComponentManager dcm )
         {
             return dcm.getInstance();
         }
@@ -1365,9 +1365,9 @@
         }
 
 
-        Object getService( DelayedComponentManager dcm )
+        Object getService( ImmediateComponentManager dcm )
         {
-            if ( dcm.createRealComponent() )
+            if ( dcm.createComponent() )
             {
                 dcm.changeState( Active.getInstance() );
                 return dcm.getInstance();
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java
index f8c70bf..a0524eb 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java
@@ -30,7 +30,7 @@
 /**
  * The <code>DelayedComponentManager</code> TODO
  */
-public class DelayedComponentManager extends ImmediateComponentManager implements ServiceFactory
+public class DelayedComponentManager extends ImmediateComponentManager
 {
 
     // keep the using bundles as reference "counters" for instance deactivation
@@ -48,15 +48,6 @@
         this.m_useCount = 0;
     }
 
-
-    protected boolean createComponent()
-    {
-        // nothing to do here for a delayed component, will be done in the
-        // getService method for the first bundle acquiring the component
-        return true;
-    }
-
-
     protected void deleteComponent( int reason )
     {
         // only have to delete, if there is actually an instance
@@ -69,12 +60,6 @@
         m_useCount = 0;
     }
 
-
-    protected Object getService()
-    {
-        return this;
-    }
-
     State getSatisfiedState()
     {
         return Registered.getInstance();
@@ -96,13 +81,6 @@
         }
     }
 
-
-    protected boolean createRealComponent()
-    {
-        return super.createComponent();
-    }
-
-
     public void ungetService( Bundle bundle, ServiceRegistration sr, Object service )
     {
         obtainStateLock();
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
index bf77da3..eda4d75 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
@@ -33,6 +33,8 @@
 import org.apache.felix.scr.impl.helper.ModifiedMethod;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceFactory;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.component.ComponentContext;
@@ -44,7 +46,7 @@
  * The default ComponentManager. Objects of this class are responsible for managing
  * implementation object's lifecycle.
  */
-public class ImmediateComponentManager extends AbstractComponentManager
+public class ImmediateComponentManager extends AbstractComponentManager implements ServiceFactory
 {
 
     // The object that implements the service and that is bound to other services
@@ -113,18 +115,21 @@
     // also be overwritten
     protected boolean createComponent()
     {
-        ComponentContextImpl tmpContext = new ComponentContextImpl( this );
-        Object tmpComponent = createImplementationObject( tmpContext );
-
-        // if something failed creating the component instance, return false
-        if ( tmpComponent == null )
+        if ( m_implementationObject == null )
         {
-            return false;
-        }
+            ComponentContextImpl tmpContext = new ComponentContextImpl( this );
+            Object tmpComponent = createImplementationObject( tmpContext );
 
-        // otherwise set the context and component instance and return true
-        m_componentContext = tmpContext;
-        m_implementationObject = tmpComponent;
+            // if something failed creating the component instance, return false
+            if ( tmpComponent == null )
+            {
+                return false;
+            }
+
+            // otherwise set the context and component instance and return true
+            m_componentContext = tmpContext;
+            m_implementationObject = tmpComponent;
+        }
         return true;
     }
 
@@ -286,7 +291,7 @@
      */
     protected Object getService()
     {
-        return m_implementationObject;
+        return this;
     }
 
     State getSatisfiedState()
@@ -593,4 +598,26 @@
         }
         return regProps.equals( props );
     }
+
+    public Object getService( Bundle bundle, ServiceRegistration serviceRegistration )
+    {
+        obtainStateLock();
+        try
+        {
+            if (m_implementationObject != null)
+            {
+                return m_implementationObject;
+            }
+//            m_useCount++;
+            return Registered.getInstance().getService( this );
+        }
+        finally
+        {
+            releaseStateLock();
+        }
+    }
+
+    public void ungetService( Bundle bundle, ServiceRegistration serviceRegistration, Object o )
+    {
+    }
 }
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
index df0a417..050fefe 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
@@ -37,7 +37,7 @@
  * The <code>ServiceFactoryComponentManager</code> for components specified with &lt;service serviceFactory='true'/&gt;
  * in the xml metadata. The component must be delayed, not immediate or factory.
  */
-public class ServiceFactoryComponentManager extends ImmediateComponentManager implements ServiceFactory
+public class ServiceFactoryComponentManager extends ImmediateComponentManager
 {
 
     // maintain the map of ComponentContext objects created for the
@@ -76,12 +76,6 @@
     }
 
 
-    protected Object getService()
-    {
-        return this;
-    }
-
-
     /* (non-Javadoc)
      * @see org.apache.felix.scr.AbstractComponentManager#getInstance()
      */
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/CircularReferenceTest.java b/scr/src/test/java/org/apache/felix/scr/integration/CircularReferenceTest.java
index 59a460c..eabc57e 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/CircularReferenceTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/CircularReferenceTest.java
@@ -86,8 +86,7 @@
         TestCase.assertNotNull( componentB );
         TestCase.assertEquals( Component.STATE_ACTIVE, componentB.getState() );
         B b = ( B ) componentB.getComponentInstance().getInstance();
-        //Currently felix binds A.  I think this is wrong.
-//        assertEquals( 0, b.getAs().size() );
+        assertEquals( 0, b.getAs().size() );
     }
     /**
      * A > 1.1 > B > 0..n > A Both should start (B first), and B should have an A reference.