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();
}
}