You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by fm...@apache.org on 2009/10/29 15:44:55 UTC

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

Author: fmeschbe
Date: Thu Oct 29 14:44:54 2009
New Revision: 830970

URL: http://svn.apache.org/viewvc?rev=830970&view=rev
Log:
FELIX-1825 Deactivate component instances of delayed components which
are not referenced any more

Modified:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java
    felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/ServiceComponentTest.java
    felix/trunk/scr/src/test/resources/integration_test_simple_components.xml

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java?rev=830970&r1=830969&r2=830970&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java Thu Oct 29 14:44:54 2009
@@ -777,6 +777,12 @@
         }
 
 
+        void ungetService( DelayedComponentManager dcm )
+        {
+            log( dcm, "ungetService" );
+        }
+
+
         void enable( AbstractComponentManager acm )
         {
             log( acm, "enable" );
@@ -1032,6 +1038,13 @@
         {
             return dcm.getInstance();
         }
+
+
+        void ungetService( DelayedComponentManager dcm )
+        {
+            dcm.deleteComponent( ComponentConstants.DEACTIVATION_REASON_UNSPECIFIED );
+            dcm.changeState( Registered.getInstance() );
+        }
     }
 
     protected static final class Registered extends Satisfied

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java?rev=830970&r1=830969&r2=830970&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DelayedComponentManager.java Thu Oct 29 14:44:54 2009
@@ -19,6 +19,9 @@
 package org.apache.felix.scr.impl.manager;
 
 
+import java.util.HashSet;
+import java.util.Set;
+
 import org.apache.felix.scr.impl.BundleComponentActivator;
 import org.apache.felix.scr.impl.config.ComponentHolder;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
@@ -33,6 +36,9 @@
 public class DelayedComponentManager extends ImmediateComponentManager implements ServiceFactory
 {
 
+    // keep the using bundles as reference "counters" for instance deactivation
+    private final Set usingBundles = new HashSet();
+
     /**
      * @param activator
      * @param metadata
@@ -59,6 +65,9 @@
         {
             super.deleteComponent( reason );
         }
+
+        // ensure the refence set is also clear
+        usingBundles.clear();
     }
 
 
@@ -72,17 +81,23 @@
 
     public synchronized Object getService( Bundle bundle, ServiceRegistration sr )
     {
-        return state().getService(this);
+        usingBundles.add(bundle);
+        return state().getService( this );
     }
 
-	protected boolean createRealComponent()
-	{
-		return super.createComponent();
-	}
 
-    public void ungetService( Bundle arg0, ServiceRegistration arg1, Object arg2 )
+    protected boolean createRealComponent()
     {
-        // nothing to do here
+        return super.createComponent();
     }
 
+
+    public void ungetService( Bundle bundle, ServiceRegistration sr, Object service )
+    {
+        usingBundles.remove( bundle );
+        if ( usingBundles.isEmpty() )
+        {
+            state().ungetService( this );
+        }
+    }
 }

Modified: felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/ServiceComponentTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/ServiceComponentTest.java?rev=830970&r1=830969&r2=830970&view=diff
==============================================================================
--- felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/ServiceComponentTest.java (original)
+++ felix/trunk/scr/src/test/java/org/apache/felix/scr/integration/ServiceComponentTest.java Thu Oct 29 14:44:54 2009
@@ -26,6 +26,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 
 
@@ -84,4 +85,89 @@
                 && !propKey.startsWith( "." ) );
         }
     }
+
+
+    @Test
+    public void test_DelayedSimpleComponent_service_single_use()
+    {
+        final String pid = "DelayedServiceComponent";
+
+        // one single component exists without configuration
+        final Component component = findComponentByName( pid );
+        TestCase.assertNotNull( component );
+        TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+
+        component.enable();
+        delay();
+
+        // the delayed service is expected to only be registered before use
+        TestCase.assertEquals( Component.STATE_REGISTERED, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        // get the service
+        ServiceReference reference = bundleContext.getServiceReference( "java.lang.Object" );
+        TestCase.assertNotNull( reference );
+        try
+        {
+            final Object theService = bundleContext.getService( reference );
+
+            // service must now be active
+            TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+
+            // and of course we expect the instance
+            TestCase.assertEquals( SimpleComponent.INSTANCE, theService );
+        }
+        finally
+        {
+            bundleContext.ungetService( reference );
+        }
+
+        // service is not used anymore, ensure REGISTERED state and INSTANCE==null
+        TestCase.assertEquals( Component.STATE_REGISTERED, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+    }
+
+
+    @Test
+    public void test_DelayedSimpleComponent_service_multi_use()
+    {
+        final String pid = "DelayedServiceComponent";
+
+        // one single component exists without configuration
+        final Component component = findComponentByName( pid );
+        TestCase.assertNotNull( component );
+        TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+
+        component.enable();
+        delay();
+
+        // the delayed service is expected to only be registered before use
+        TestCase.assertEquals( Component.STATE_REGISTERED, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+
+        // get the service once
+        final ServiceReference reference1 = bundleContext.getServiceReference( "java.lang.Object" );
+        TestCase.assertNotNull( reference1 );
+        bundleContext.getService( reference1 );
+        TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+        TestCase.assertNotNull( SimpleComponent.INSTANCE );
+
+        // get the service a second time
+        final BundleContext bundleContext2 = bundle.getBundleContext();
+        final ServiceReference reference2 = bundleContext2.getServiceReference( "java.lang.Object" );
+        TestCase.assertNotNull( reference2 );
+        bundleContext2.getService( reference2 );
+        TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+        TestCase.assertNotNull( SimpleComponent.INSTANCE );
+
+        // unget the service once -- must still be active !
+        bundleContext2.ungetService( reference2 );
+        TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+        TestCase.assertNotNull( SimpleComponent.INSTANCE );
+
+        // unget the service second time -- must be registered and null now
+        bundleContext.ungetService( reference1 );
+        TestCase.assertEquals( Component.STATE_REGISTERED, component.getState() );
+        TestCase.assertNull( SimpleComponent.INSTANCE );
+    }
 }

Modified: felix/trunk/scr/src/test/resources/integration_test_simple_components.xml
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/resources/integration_test_simple_components.xml?rev=830970&r1=830969&r2=830970&view=diff
==============================================================================
--- felix/trunk/scr/src/test/resources/integration_test_simple_components.xml (original)
+++ felix/trunk/scr/src/test/resources/integration_test_simple_components.xml Thu Oct 29 14:44:54 2009
@@ -58,7 +58,7 @@
         <property name="service.pid" value="FactoryConfigurationComponent" />
     </scr:component>
 
-    <!-- component is a stupid service to verify non-use of private props -->
+    <!-- component is a simple service to verify non-use of private props -->
     <scr:component name="ServiceComponent"
         enabled="false" immediate="true"
         configuration-policy="ignore" >
@@ -71,6 +71,17 @@
         </service>
     </scr:component>
 
+    <!-- component is a simple service to verify deactivation when not being used any longer -->
+    <scr:component name="DelayedServiceComponent"
+        enabled="false" immediate="false"
+        configuration-policy="ignore" >
+        <implementation class="org.apache.felix.scr.integration.components.SimpleComponent" />
+        <property name="service.pid" value="ServiceComponent" />
+        <service>
+            <provide interface="java.lang.Object" />
+        </service>
+    </scr:component>
+
     <!-- Component Factory Instances -->
     <scr:component name="factory.component"
         enabled="false"