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 2010/03/24 10:22:40 UTC

svn commit: r926986 - /felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java

Author: fmeschbe
Date: Wed Mar 24 09:22:39 2010
New Revision: 926986

URL: http://svn.apache.org/viewvc?rev=926986&view=rev
Log:
FELIX-2231 Ensure components for cannot be loaded twice: Access to the map of loaded components per bundle was not synchronized. In addition, there was a relatively big window between the check whether a bundle's components have been loaded and the actual registration of the loaded components. This has now been closed using a flag set early and replaced with the actual loaded components.

Modified:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java?rev=926986&r1=926985&r2=926986&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java Wed Mar 24 09:22:39 2010
@@ -21,7 +21,6 @@ package org.apache.felix.scr.impl;
 
 import java.io.PrintStream;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
 
 import org.apache.felix.scr.impl.config.ConfigurationComponentRegistry;
@@ -214,22 +213,40 @@ public class Activator implements Bundle
             return;
         }
 
+        // there should be components, load them with a bundle context
+        BundleContext context = bundle.getBundleContext();
+        if ( context == null )
+        {
+            log( LogService.LOG_ERROR, m_context.getBundle(), "Cannot get BundleContext of bundle "
+                + bundle.getSymbolicName() + "/" + bundle.getBundleId(), null );
+            return;
+        }
+
         // FELIX-1666 method is called for the LAZY_ACTIVATION event and
         // the started event. Both events cause this method to be called;
         // so we have to make sure to not load components twice
-        if ( m_componentBundles.containsKey( new Long( bundle.getBundleId() ) ) )
+        // FELIX-2231 Mark bundle loaded early to prevent concurrent loading
+        // if LAZY_ACTIVATION and STARTED event are fired at the same time
+        final boolean loaded;
+        final Long bundleId = new Long( bundle.getBundleId() );
+        synchronized ( m_componentBundles )
         {
-            log( LogService.LOG_DEBUG, m_context.getBundle(), "Components for bundle  " + bundle.getSymbolicName()
-                + "/" + bundle.getBundleId() + " already loaded. Nothing to do.", null );
-            return;
+            if ( m_componentBundles.containsKey( bundleId ) )
+            {
+                loaded = true;
+            }
+            else
+            {
+                m_componentBundles.put( bundleId, bundleId );
+                loaded = false;
+            }
         }
 
-        // there should be components, load them with a bundle context
-        BundleContext context = bundle.getBundleContext();
-        if ( context == null )
+        // terminate if already loaded (or currently being loaded)
+        if ( loaded )
         {
-            log( LogService.LOG_ERROR, m_context.getBundle(), "Cannot get BundleContext of bundle "
-                + bundle.getSymbolicName() + "/" + bundle.getBundleId(), null );
+            log( LogService.LOG_DEBUG, m_context.getBundle(), "Components for bundle  " + bundle.getSymbolicName()
+                + "/" + bundle.getBundleId() + " already loaded. Nothing to do.", null );
             return;
         }
 
@@ -237,10 +254,22 @@ public class Activator implements Bundle
         {
             BundleComponentActivator ga = new BundleComponentActivator( m_componentRegistry, m_componentActor, context,
                 m_configuration );
-            m_componentBundles.put( new Long( bundle.getBundleId() ), ga );
+
+            // replace bundle activator in the map
+            synchronized ( m_componentBundles )
+            {
+                m_componentBundles.put( bundleId, ga );
+            }
         }
         catch ( Exception e )
         {
+            // remove the bundle id from the bundles map to ensure it is
+            // not marked as being loaded
+            synchronized ( m_componentBundles )
+            {
+                m_componentBundles.remove( bundleId );
+            }
+
             if ( e instanceof IllegalStateException && bundle.getState() != Bundle.ACTIVE )
             {
                 log(
@@ -268,13 +297,17 @@ public class Activator implements Bundle
      */
     private void disposeComponents( Bundle bundle )
     {
-        BundleComponentActivator ga = ( BundleComponentActivator ) m_componentBundles.remove( new Long( bundle
-            .getBundleId() ) );
-        if ( ga != null )
+        final Object ga;
+        synchronized ( m_componentBundles )
+        {
+            ga = m_componentBundles.remove( new Long( bundle.getBundleId() ) );
+        }
+
+        if ( ga instanceof BundleComponentActivator )
         {
             try
             {
-                ga.dispose( ComponentConstants.DEACTIVATION_REASON_BUNDLE_STOPPED );
+                ( ( BundleComponentActivator ) ga ).dispose( ComponentConstants.DEACTIVATION_REASON_BUNDLE_STOPPED );
             }
             catch ( Exception e )
             {
@@ -288,19 +321,29 @@ public class Activator implements Bundle
     // Unloads all components registered with the SCR
     private void disposeAllComponents()
     {
-        for ( Iterator it = m_componentBundles.values().iterator(); it.hasNext(); )
+        final Object[] activators;
+        synchronized ( m_componentBundles )
         {
-            BundleComponentActivator ga = ( BundleComponentActivator ) it.next();
-            try
-            {
-                ga.dispose( ComponentConstants.DEACTIVATION_REASON_DISPOSED );
-            }
-            catch ( Exception e )
+            activators = m_componentBundles.values().toArray();
+            m_componentBundles.clear();
+        }
+
+        for ( int i = 0; i < activators.length; i++ )
+        {
+            if ( activators[i] instanceof BundleComponentActivator )
             {
-                log( LogService.LOG_ERROR, m_context.getBundle(), "Error while disposing components of bundle "
-                    + ga.getBundleContext().getBundle().getSymbolicName(), e );
+                final BundleComponentActivator ga = ( BundleComponentActivator ) activators[i];
+                final Bundle bundle = ga.getBundleContext().getBundle();
+                try
+                {
+                    ga.dispose( ComponentConstants.DEACTIVATION_REASON_DISPOSED );
+                }
+                catch ( Exception e )
+                {
+                    log( LogService.LOG_ERROR, m_context.getBundle(), "Error while disposing components of bundle "
+                        + bundle.getSymbolicName() + "/" + bundle.getBundleId(), e );
+                }
             }
-            it.remove();
         }
     }