You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by dj...@apache.org on 2012/10/16 21:33:51 UTC

svn commit: r1398942 - in /felix/trunk/scr/src: main/java/org/apache/felix/scr/impl/ main/java/org/apache/felix/scr/impl/manager/ test/java/org/apache/felix/scr/integration/

Author: djencks
Date: Tue Oct 16 19:33:51 2012
New Revision: 1398942

URL: http://svn.apache.org/viewvc?rev=1398942&view=rev
Log:
FELIX-3557 resolve-circular-dependencies-later implementation

Modified:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
    felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/CircularReferenceTest.java

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java?rev=1398942&r1=1398941&r2=1398942&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java Tue Oct 16 19:33:51 2012
@@ -35,11 +35,13 @@ import org.apache.felix.scr.impl.config.
 import org.apache.felix.scr.impl.config.ScrConfiguration;
 import org.apache.felix.scr.impl.helper.Logger;
 import org.apache.felix.scr.impl.manager.AbstractComponentManager;
+import org.apache.felix.scr.impl.manager.DependencyManager;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.apache.felix.scr.impl.metadata.XmlHandler;
 import org.apache.felix.scr.impl.parser.KXml2SAXParser;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
 import org.osgi.service.component.ComponentException;
 import org.osgi.service.log.LogService;
 import org.osgi.util.tracker.ServiceTracker;
@@ -597,4 +599,13 @@ public class BundleComponentActivator im
         }
     }
 
+    public void missingServicePresent( ServiceReference serviceReference )
+    {
+        m_componentRegistry.missingServicePresent( serviceReference, m_componentActor );
+    }
+
+    public void registerMissingDependency( DependencyManager dependencyManager, ServiceReference serviceReference )
+    {
+        m_componentRegistry.registerMissingDependency(dependencyManager, serviceReference);
+    }
 }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java?rev=1398942&r1=1398941&r2=1398942&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java Tue Oct 16 19:33:51 2012
@@ -38,6 +38,7 @@ import org.apache.felix.scr.impl.config.
 import org.apache.felix.scr.impl.manager.AbstractComponentManager;
 import org.apache.felix.scr.impl.manager.ComponentFactoryImpl;
 import org.apache.felix.scr.impl.manager.ConfigurationComponentFactoryImpl;
+import org.apache.felix.scr.impl.manager.DependencyManager;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -47,6 +48,7 @@ import org.osgi.framework.ServiceEvent;
 import org.osgi.framework.ServiceListener;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.component.ComponentException;
 
 
@@ -128,6 +130,8 @@ public class ComponentRegistry implement
     // the ConfigurationAdmin service
     private ConfigurationSupport configurationSupport;
 
+    private final Map m_missingDependencies = new HashMap( );
+
     protected ComponentRegistry( BundleContext context )
     {
         m_bundleContext = context;
@@ -648,4 +652,41 @@ public class ComponentRegistry implement
             this.configurationSupport = null;
         }
     }
+
+    public void missingServicePresent( final ServiceReference serviceReference, ComponentActorThread actor )
+    {
+        final List dependencyManagers = ( List ) m_missingDependencies.remove( serviceReference );
+        if ( dependencyManagers != null )
+        {
+            actor.schedule( new Runnable()
+            {
+
+                public void run()
+                {
+                    for ( Iterator i = dependencyManagers.iterator(); i.hasNext(); )
+                    {
+                        DependencyManager dm = ( DependencyManager ) i.next();
+                        dm.invokeBindMethodLate( serviceReference );
+                    }
+                }
+            } );
+        }
+    }
+
+    public synchronized void registerMissingDependency( DependencyManager dependencyManager, ServiceReference serviceReference )
+    {
+        //check that the service reference is from scr
+        if ( serviceReference.getProperty( ComponentConstants.COMPONENT_NAME ) == null || serviceReference.getProperty( ComponentConstants.COMPONENT_ID ) == null )
+        {
+            return;
+        }
+        List dependencyManagers = ( List ) m_missingDependencies.get( serviceReference );
+        if ( dependencyManagers == null )
+        {
+            dependencyManagers = new ArrayList();
+            m_missingDependencies.put( serviceReference, dependencyManagers );
+        }
+        dependencyManagers.add( dependencyManager );
+    }
+
 }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java?rev=1398942&r1=1398941&r2=1398942&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java Tue Oct 16 19:33:51 2012
@@ -1059,7 +1059,7 @@ public class DependencyManager implement
             return true;
         }
 
-        Map result = new HashMap(); //<ServiceReference, Object[]>
+        Map result = new HashMap(); //<ServiceReference, RefPair>
         // assume success to begin with: if the dependency is optional,
         // we don't care, whether we can bind a service. Otherwise, we
         // require at least one service to be bound, thus we require
@@ -1083,6 +1083,10 @@ public class DependencyManager implement
                         // of course, we have success if the service is bound
                         success = true;
                     }
+                    else
+                    {
+                        m_componentManager.getActivator().registerMissingDependency(this, refs[index]);
+                    }
                 }
             }
         }
@@ -1100,6 +1104,10 @@ public class DependencyManager implement
                     // of course, we have success if the service is bound
                     success = true;
                 }
+                else if ( isOptional() )
+                {
+                    m_componentManager.getActivator().registerMissingDependency(this, ref);
+                }
             }
         }
 
@@ -1249,6 +1257,33 @@ public class DependencyManager implement
         }
     }
 
+    public void invokeBindMethodLate( final ServiceReference ref )
+    {
+        if ( !isSatisfied() )
+        {
+            return;
+        }
+        if ( !isMultiple() )
+        {
+            ServiceReference[] refs = getFrameworkServiceReferences();
+            if ( refs == null )
+            {
+                return; // should not happen, we have one!
+            }
+            // find the service with the highest ranking
+            for ( int i = 1; i < refs.length; i++ )
+            {
+                ServiceReference test = refs[i];
+                if ( test.compareTo( ref ) > 0 )
+                {
+                    return; //another ref is better
+                }
+            }
+        }
+        //TODO static and dynamic reluctant
+        m_componentManager.invokeBindMethod( this, ref );
+    }
+
     /**
      * Calls the bind method. In case there is an exception while calling the
      * bind method, the service is not considered to be bound to the instance

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java?rev=1398942&r1=1398941&r2=1398942&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java Tue Oct 16 19:33:51 2012
@@ -78,7 +78,6 @@ public class ImmediateComponentManager e
     // this is null, if none exist or none are provided
     private Dictionary m_configurationProperties;
 
-
     /**
      * The constructor receives both the activator and the metadata
      *
@@ -132,6 +131,9 @@ public class ImmediateComponentManager e
             m_componentContext = tmpContext;
             m_implementationObject = tmpComponent;
             log( LogService.LOG_DEBUG, "Set implementation object for component {0}", new Object[] { getName() },  null );
+
+            //notify that component was successfully created so any optional circular dependencies can be retried
+            getActivator().missingServicePresent(getServiceReference());
         }
         return true;
     }

Modified: felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/CircularReferenceTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/CircularReferenceTest.java?rev=1398942&r1=1398941&r2=1398942&view=diff
==============================================================================
--- felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/CircularReferenceTest.java (original)
+++ felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/CircularReferenceTest.java Tue Oct 16 19:33:51 2012
@@ -86,7 +86,7 @@ public class CircularReferenceTest exten
         TestCase.assertNotNull( componentB );
         TestCase.assertEquals( Component.STATE_ACTIVE, componentB.getState() );
         B b = ( B ) componentB.getComponentInstance().getInstance();
-        assertEquals( 0, b.getAs().size() );
+        assertEquals( 1, b.getAs().size() );
     }
     /**
      * A > 1.1 > B > 0..n > A Both should start (B first), and B should have an A reference.
@@ -130,11 +130,12 @@ public class CircularReferenceTest exten
         Object service = bundleContext.getService( serviceReference );
         assertNotNull( service );
 
+        delay();
 
         A a = ( A ) componentA.getComponentInstance().getInstance();
         assertEquals( 1, a.getBs().size() );
         B b = ( B ) componentB.getComponentInstance().getInstance();
-        assertEquals( 0, b.getAs().size() );
+        assertEquals( 1, b.getAs().size() );
     }
     /**
      * A > 1.1 > B > 0..n > A Both should start, but B should not have an A reference.
@@ -164,11 +165,11 @@ public class CircularReferenceTest exten
         Object serviceA = bundleContext.getService( serviceReferenceA );
         assertNotNull( serviceA );
 
-
+        delay();
         A a = ( A ) componentA.getComponentInstance().getInstance();
         assertEquals( 1, a.getBs().size() );
         B b = ( B ) componentB.getComponentInstance().getInstance();
-        assertEquals( 0, b.getAs().size() );
+        assertEquals( 1, b.getAs().size() );
 
 
         //disabling (removing the A service registration) and re-enabling will
@@ -207,7 +208,7 @@ public class CircularReferenceTest exten
         TestCase.assertNotNull( componentB );
         TestCase.assertEquals( Component.STATE_ACTIVE, componentB.getState() );
         B b = ( B ) componentB.getComponentInstance().getInstance();
-        assertEquals( 0, b.getAs().size() );
+        assertEquals( 1, b.getAs().size() );
     }
     /**
      * A > 1.1 > B > 0..1 > A Both should start (B first), and B should have an A reference.