FELIX-1185 Apply state machine patch by Agemo Cui (thanks alot!)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@781045 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/AbstractComponentManager.java
index a4789b4..30ee2df 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/AbstractComponentManager.java
@@ -18,16 +18,24 @@
*/
package org.apache.felix.scr.impl;
-
-import java.lang.reflect.*;
-import java.util.*;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
import org.apache.felix.scr.Reference;
-import org.osgi.framework.*;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentInstance;
import org.osgi.service.log.LogService;
-
/**
* The default ComponentManager. Objects of this class are responsible for managing
* implementation object's lifecycle.
@@ -39,10 +47,7 @@
private long m_componentId;
// The state of this instance manager
- private int m_state;
-
- // Flag indicating whether scheduled component deactivation is pending
- private boolean m_pendingDeactivate;
+ private State m_state;
// The metadata
private ComponentMetadata m_componentMetadata;
@@ -56,34 +61,406 @@
// The ServiceRegistration
private ServiceRegistration m_serviceRegistration;
- // lock object used by service registration locking
- private Object serviceRegistrationLock = new Object();
+ /**
+ * There are 9 states in all. They are: Disabled, Enabled, Unsatisfied,
+ * Registered, Factory, Active, Destroyed, Activating and Deactivating.
+ * State Enabled is right State Unsatisfied. State Registered, Factory
+ * and Active are the "Satisfied" state in concept. State Activating and
+ * Deactivating are transition states. They will be changed to other state
+ * automatically when work is done.
+ * <p>
+ * The transition cases are listed below.
+ * <ul>
+ * <li>Disabled -(enable)-> Enabled</li>
+ * <li>Disabled -(dispose)-> Destoryed</li>
+ * <li>Enabled -(activate, SUCCESS)-> Satisfied(Registered, Factory or Active)</li>
+ * <li>Enabled -(activate, FAIL)-> Unsatisfied</li>
+ * <li>Enabled -(disable)-> Disabled</li>
+ * <li>Enabled -(dispose)-> Destroyed</li>
+ * <li>Unsatisfied -(activate, SUCCESS)-> Satisfied(Registered, Factory or Active)</li>
+ * <li>Unsatisfied -(activate, FAIL)-> Unsatisfied</li>
+ * <li>Unsatisfied -(disable)-> Disabled</li>
+ * <li>Unsatisfied -(dispose)-> Destroyed</li>
+ * <li>Registered -(getService, SUCCESS)-> Active</li>
+ * <li>Registered -(getService, FAIL)-> Unsatisfied</li>
+ * <li>Satisfied -(deactivate)-> Unsatisfied</li>
+ * </ul>
+ */
+ protected static abstract class State
+ {
+ private final String m_name;
+ private final int m_state;
- // the field set to the owner of the lock
- private Thread serviceRegistrationLockOwner;
+ protected State( String name, int state )
+ {
+ m_name = name;
+ m_state = state;
+ }
+
+ public String toString()
+ {
+ return m_name;
+ }
+
+ int getState()
+ {
+ return m_state;
+ }
+
+ ServiceReference getServiceReference( AbstractComponentManager acm )
+ {
+ return null;
+ }
+
+ void enableInternal( AbstractComponentManager acm )
+ {
+ acm.log( LogService.LOG_DEBUG,
+ "Current state: " + m_state + ", Event: enable",
+ acm.getComponentMetadata(), null );
+ }
+
+ void disableInternal( AbstractComponentManager acm )
+ {
+ acm.log( LogService.LOG_DEBUG,
+ "Current state: " + m_state + ", Event: disable",
+ acm.getComponentMetadata(), null );
+ }
+
+ void activateInternal( AbstractComponentManager acm )
+ {
+ acm.log(LogService.LOG_DEBUG,
+ "Current state: " + m_state + ", Event: activate",
+ acm.getComponentMetadata(), null);
+ }
+
+ void deactivateInternal( AbstractComponentManager acm )
+ {
+ acm.log( LogService.LOG_DEBUG,
+ "Current state: " + m_state + ", Event: deactivate",
+ acm.getComponentMetadata(), null );
+ }
+
+ void disposeInternal( AbstractComponentManager acm )
+ {
+ acm.log( LogService.LOG_DEBUG,
+ "Current state: " + m_state + ", Event: dispose",
+ acm.getComponentMetadata(), null );
+ }
+
+ Object getService( DelayedComponentManager dcm )
+ {
+ dcm.log( LogService.LOG_DEBUG,
+ "Current state: " + m_state + ", Event: getService",
+ dcm.getComponentMetadata(), null );
+ return null;
+ }
+ }
+
+ protected static final class Destroyed extends State
+ {
+ private static final Destroyed m_inst = new Destroyed();
+
+ private Destroyed()
+ {
+ super( "Destroyed", STATE_DESTROYED );
+ }
+
+ static State getInstance()
+ {
+ return m_inst;
+ }
+ }
+
+ protected static final class Disabled extends State
+ {
+ private static final Disabled m_inst = new Disabled();
+
+ private Disabled()
+ {
+ super( "Disabled", STATE_DISABLED );
+ }
+
+ static State getInstance()
+ {
+ return m_inst;
+ }
+
+ void enableInternal( AbstractComponentManager acm )
+ {
+ acm.changeState( Enabled.getInstance() );
+
+ acm.log( LogService.LOG_DEBUG, "Component enabled", acm.getComponentMetadata(), null );
+ }
+
+ void disposeInternal( AbstractComponentManager acm )
+ {
+ acm.clear();
+ acm.changeState( Destroyed.getInstance() );
+ }
+ }
+
+ protected static final class Enabled extends State
+ {
+ private static final Enabled m_inst = new Enabled();
+
+ private Enabled()
+ {
+ super( "Enabled", STATE_ENABLED );
+ }
+
+ static State getInstance()
+ {
+ return m_inst;
+ }
+
+ void activateInternal( AbstractComponentManager acm )
+ {
+ ComponentMetadata componentMetadata = acm.getComponentMetadata();
+
+ try
+ {
+ acm.enableDependencyManagers();
+ Unsatisfied.getInstance().activateInternal(acm);
+ }
+ catch (Exception e)
+ {
+ acm.log( LogService.LOG_ERROR, "Failed enabling Component", componentMetadata, e );
+ acm.disposeDependencyManagers();
+ acm.loadDependencyManagers( acm.getComponentMetadata() );
+ }
+ }
+
+ void disableInternal( AbstractComponentManager acm )
+ {
+ acm.changeState( Disabled.getInstance() );
+
+ acm.log( LogService.LOG_DEBUG, "Component disabled", acm.getComponentMetadata(), null );
+ }
+
+ void disposeInternal( AbstractComponentManager acm )
+ {
+ acm.clear();
+ acm.changeState( Destroyed.getInstance() );
+
+ acm.log( LogService.LOG_DEBUG, "Component disposed", acm.getComponentMetadata(), null );
+ }
+ }
+
+ protected static final class Unsatisfied extends State
+ {
+ private static final Unsatisfied m_inst = new Unsatisfied();
+
+ private Unsatisfied()
+ {
+ super( "Unsatisfied", STATE_UNSATISFIED );
+ }
+
+ static State getInstance()
+ {
+ return m_inst;
+ }
+
+ void activateInternal( AbstractComponentManager acm )
+ {
+ acm.changeState( Activating.getInstance() );
+
+ ComponentMetadata componentMetadata = acm.getComponentMetadata();
+ acm.log( LogService.LOG_DEBUG, "Activating component", componentMetadata, null );
+
+ // Before creating the implementation object, we are going to
+ // test if all the mandatory dependencies are satisfied
+ if ( !acm.verifyDependencyManagers( acm.getProperties()) )
+ {
+ acm.log( LogService.LOG_INFO, "Not all dependencies satisified, cannot activate", componentMetadata, null );
+ acm.changeState( Unsatisfied.getInstance() );
+ return;
+ }
+
+ // 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() )
+ {
+ // component creation failed, not active now
+ acm.log( LogService.LOG_ERROR, "Component instance could not be created, activation failed",
+ componentMetadata, null );
+
+ // set state to unsatisfied
+ acm.changeState( Unsatisfied.getInstance() );
+ return;
+ }
+
+ acm.changeState( acm.getSatisfiedState() );
+
+ acm.registerComponentService();
+ }
+
+ void disableInternal( AbstractComponentManager acm )
+ {
+ ComponentMetadata componentMetadata = acm.getComponentMetadata();
+ acm.log( LogService.LOG_DEBUG, "Disabling component", componentMetadata, null );
+
+ // dispose and recreate dependency managers
+ acm.disposeDependencyManagers();
+ acm.loadDependencyManagers( componentMetadata );
+
+ // we are now disabled, ready for re-enablement or complete destroyal
+ acm.changeState( Disabled.getInstance() );
+
+ acm.log( LogService.LOG_DEBUG, "Component disabled", componentMetadata, null );
+ }
+
+ void disposeInternal( AbstractComponentManager acm )
+ {
+ acm.disposeDependencyManagers();
+ acm.clear();
+ acm.changeState( Destroyed.getInstance() );
+
+ acm.log( LogService.LOG_DEBUG, "Component disposed", acm.getComponentMetadata(), null );
+ }
+ }
+
+ protected static final class Activating extends State
+ {
+ private static final Activating m_inst = new Activating();
+
+ private Activating() {
+ super( "Activating", STATE_ACTIVATING );
+ }
+
+ static State getInstance()
+ {
+ return m_inst;
+ }
+ }
+
+ protected static final class Deactivating extends State
+ {
+ private static final Deactivating m_inst = new Deactivating();
+
+ private Deactivating() {
+ super( "Deactivating", STATE_DEACTIVATING );
+ }
+
+ static State getInstance() {
+ return m_inst;
+ }
+ }
+
+ protected static abstract class Satisfied extends State
+ {
+ protected Satisfied( String name, int state )
+ {
+ super( name, state );
+ }
+
+ ServiceReference getServiceReference( AbstractComponentManager acm )
+ {
+ ServiceRegistration sr = acm.getServiceRegistration();
+ return sr == null ? null : sr.getReference();
+ }
+
+ void deactivateInternal( AbstractComponentManager acm )
+ {
+ acm.changeState(Deactivating.getInstance());
+
+ ComponentMetadata componentMetadata = acm.getComponentMetadata();
+ acm.log( LogService.LOG_DEBUG, "Deactivating component", componentMetadata, null );
+
+ acm.unregisterComponentService();
+ acm.deleteComponent();
+ acm.changeState( Unsatisfied.getInstance() );
+
+ acm.log( LogService.LOG_DEBUG, "Component deactivated", componentMetadata, null );
+ }
+ }
+
+ protected static final class Registered extends Satisfied
+ {
+ private static final Registered m_inst = new Registered();
+
+ private Registered() {
+ super( "Registered", STATE_REGISTERED );
+ }
+
+ static State getInstance()
+ {
+ return m_inst;
+ }
+
+ Object getService(DelayedComponentManager dcm)
+ {
+ if ( dcm.createRealComponent() )
+ {
+ dcm.changeState( Active.getInstance() );
+ return dcm.getInstance();
+ }
+ else
+ {
+ deactivateInternal( dcm );
+ return null;
+ }
+ }
+ }
+
+ protected static final class Factory extends Satisfied
+ {
+ private static final Factory m_inst = new Factory();
+
+ private Factory()
+ {
+ super( "Factory", STATE_FACTORY );
+ }
+
+ static State getInstance()
+ {
+ return m_inst;
+ }
+ }
+
+ protected static final class Active extends Satisfied
+ {
+ private static final Active m_inst = new Active();
+
+ private Active()
+ {
+ super( "Active", STATE_ACTIVE );
+ }
+
+ static State getInstance()
+ {
+ return m_inst;
+ }
+
+ Object getService( DelayedComponentManager dcm )
+ {
+ return dcm.getInstance();
+ }
+ }
/**
* The constructor receives both the activator and the metadata
*
* @param activator
* @param metadata
+ * @param componentId
*/
- protected AbstractComponentManager( BundleComponentActivator activator, ComponentMetadata metadata, long componentId )
+ protected AbstractComponentManager( BundleComponentActivator activator,
+ ComponentMetadata metadata, long componentId )
{
m_activator = activator;
m_componentMetadata = metadata;
m_componentId = componentId;
- m_state = STATE_DISABLED;
- m_pendingDeactivate = false;
+ m_state = Disabled.getInstance();
loadDependencyManagers( metadata );
- log( LogService.LOG_DEBUG, "Component created", m_componentMetadata, null );
+ log( LogService.LOG_DEBUG, "Component created", metadata, null );
}
//---------- Asynchronous frontend to state change methods ----------------
-
/**
* Enables this component and - if satisfied - also activates it. If
* enabling the component fails for any reason, the component ends up
@@ -96,153 +473,17 @@
*/
public final void enable()
{
- getActivator().schedule( new ComponentActivatorTask("Enable", this)
- {
- public void doRun()
- {
- enableInternal();
- }
- } );
- }
+ enableInternal();
-
- /**
- * Enables this component and - if satisfied - also activates it
- * synchronously or asynchronously. If enabling the component fails for
- * any reason, the component ends up disabled.
- * <p>
- * This method ignores the <i>enabled</i> flag of the component metadata
- * and just enables as requested.
- *
- * @param synchronous If <code>true</code> the component is immediately
- * enabled synchronously. Otherwise the component enabled is scheduled
- * for asynchronous enabled by calling {@link #enable()}.
- */
- protected final void enable( boolean synchronous )
- {
- if ( synchronous )
- {
- enableInternal();
- }
- else
- {
- enable();
- }
- }
-
-
- /**
- * Activates this component if satisfied. If any of the dependencies is
- * not met, the component is not activated and remains unsatisifed.
- * <p>
- * This method schedules the activation for asynchronous execution.
- */
- public final void activate()
- {
- // clear the deactivation pending flag, since activation is now pending
- setPendingDeactivate( false );
-
- getActivator().schedule( new ComponentActivatorTask("Activate", this)
+ getActivator().schedule( new ComponentActivatorTask( "Enable", this )
{
public void doRun()
{
activateInternal();
}
- } );
+ });
}
-
- /**
- * Reconfigures this component by deactivating and activating it. During
- * activation the new configuration data is retrieved from the Configuration
- * Admin Service.
- */
- public final void reconfigure()
- {
- log( LogService.LOG_DEBUG, "Deactivating and Activating to reconfigure", m_componentMetadata, null );
- reactivate();
- }
-
-
- /**
- * Cycles this component by deactivating it and - if still satisfied -
- * activating it again asynchronously.
- * <p>
- * This method schedules the deactivation and reactivation for asynchronous
- * execution.
- */
- public final void reactivate()
- {
- getActivator().schedule( new ComponentActivatorTask( "Reactivate", this )
- {
- public void doRun()
- {
- deactivateInternal();
- activateInternal();
- }
- } );
- }
-
-
- /**
- * Deactivates the component.
- * <p>
- * Deactivation of the component happens when a service is unregistered
- * (or modified). Since such a service change may take place while a bundle
- * is being stopped and the bundle lock is held, we have to be careful and
- * schedule the deactivation for asynchronous execution.
- * <p>
- * The drawback is, that the user of the removed (or modified) service is
- * still bound to the old service for a small amount of time and thus may
- * run into issues. But weighing this against the deadlock possibility, it
- * is more important to be deadlock save.
- * <p>
- * If services have a problem with this delayed deactivation, they should
- * consider marking the reference as optional and dynamic and be prepared
- * to the service not being present, since service bind and unbind will
- * always be synchronous.
- */
- public final void deactivate()
- {
- // do nothing if deactivation is already pending
- if ( isPendingDeactivate() )
- {
- log( LogService.LOG_DEBUG, "Deactivation already scheduled, nothing to do", m_componentMetadata, null );
- return;
- }
-
- // we are pending deactivation
- setPendingDeactivate( true );
-
- getActivator().schedule( new ComponentActivatorTask( "Deactivate", this )
- {
- public void doRun()
- {
- deactivateInternal();
- }
- } );
- }
-
-
- /**
- * Returns <code>true</code> if the deactivation of the component has been
- * scheduled but not yet run.
- */
- public final boolean isPendingDeactivate()
- {
- return m_pendingDeactivate;
- }
-
-
- /**
- * Sets the pending deactivate flag to the given value
- */
- public final void setPendingDeactivate( boolean pendingDeactivate )
- {
- m_pendingDeactivate = pendingDeactivate;
- }
-
-
/**
* Disables this component and - if active - first deactivates it. The
* component may be reenabled by calling the {@link #enable()} method.
@@ -251,16 +492,16 @@
*/
public final void disable()
{
- getActivator().schedule( new ComponentActivatorTask("Disable", this)
+ getActivator().schedule( new ComponentActivatorTask( "Disable", this )
{
public void doRun()
{
+ deactivateInternal();
disableInternal();
}
- } );
+ });
}
-
/**
* Disposes off this component deactivating and disabling it first as
* required. After disposing off the component, it may not be used anymore.
@@ -275,71 +516,59 @@
disposeInternal();
}
-
//---------- Component interface ------------------------------------------
-
public long getId()
{
return m_componentId;
}
-
- public String getName()
- {
+ public String getName() {
return m_componentMetadata.getName();
}
-
public Bundle getBundle()
{
return getActivator().getBundleContext().getBundle();
}
-
public String getClassName()
{
return m_componentMetadata.getImplementationClassName();
}
-
public String getFactory()
{
return m_componentMetadata.getFactoryIdentifier();
}
-
public Reference[] getReferences()
{
if ( m_dependencyManagers != null && m_dependencyManagers.size() > 0 )
{
- return ( org.apache.felix.scr.Reference[] ) m_dependencyManagers
- .toArray( new Reference[m_dependencyManagers.size()] );
+ return (Reference[]) m_dependencyManagers.toArray(
+ new Reference[m_dependencyManagers.size()] );
}
return null;
}
-
public boolean isImmediate()
{
return m_componentMetadata.isImmediate();
}
-
public boolean isDefaultEnabled()
{
return m_componentMetadata.isEnabled();
}
-
public boolean isServiceFactory()
{
return m_componentMetadata.getServiceMetadata() != null
- && m_componentMetadata.getServiceMetadata().isServiceFactory();
+ && m_componentMetadata.getServiceMetadata().isServiceFactory();
}
-
public String[] getServices()
{
if ( m_componentMetadata.getServiceMetadata() != null )
@@ -350,285 +579,64 @@
return null;
}
-
- //---------- internal immediate state change methods ----------------------
- // these methods must only be called from a separate thread by calling
- // the respective asynchronous (public) method
-
+ //-------------- atomic transition methods -------------------------------
/**
- * Enable this component
- *
+ * Disposes off this component deactivating and disabling it first as
+ * required. After disposing off the component, it may not be used anymore.
+ * <p>
+ * This method unlike the other state change methods immediately takes
+ * action and disposes the component. The reason for this is, that this
+ * method has to actually complete before other actions like bundle stopping
+ * may continue.
*/
- private void enableInternal()
+ synchronized final void enableInternal()
{
-
- if ( getState() == STATE_DESTROYED )
- {
- log( LogService.LOG_ERROR, "Destroyed Component cannot be enabled", m_componentMetadata, null );
- return;
- }
- else if ( getState() != STATE_DISABLED )
- {
- log( LogService.LOG_DEBUG, "Component is already enabled", m_componentMetadata, null );
- return;
- }
-
- log( LogService.LOG_DEBUG, "Enabling component", m_componentMetadata, null );
-
- try
- {
- // enable the dependency managers of this component
- enableDependencyManagers();
-
- // enter enabled state before trying to activate
- setState( STATE_ENABLED );
-
- log( LogService.LOG_DEBUG, "Component enabled", m_componentMetadata, null );
-
- // immediately activate the compopnent, no need to schedule again
- activateInternal();
- }
- catch ( Exception ex )
- {
- log( LogService.LOG_ERROR, "Failed enabling Component", m_componentMetadata, ex );
-
- // ensure we get back to DISABLED state
- // immediately disable, no need to schedule again
- disableInternal();
- }
+ m_state.enableInternal( this );
}
-
- /**
- * Activate this Instance manager.
- *
- * 112.5.6 Activating a component configuration consists of the following steps
- * 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
- * [5. Register provided services]
- */
- private void activateInternal()
+ synchronized final void disableInternal()
{
- synchronized ( this )
- {
- // CONCURRENCY NOTE: This method is only called from within the
- // ComponentActorThread to enable, activate or reactivate the
- // component. Still we use the setStateConditional to not create
- // a race condition with the deactivateInternal method
- if ( !setStateConditional( STATE_ENABLED | STATE_UNSATISFIED, STATE_ACTIVATING ) )
- {
- return;
- }
-
- // we cannot activate if the component activator is shutting down
- if ( !isActive() )
- {
- log( LogService.LOG_DEBUG, "Component cannot be activated because the Activator is being disposed",
- m_componentMetadata, null );
- setState( STATE_UNSATISFIED );
- return;
- }
-
- log( LogService.LOG_DEBUG, "Activating component", m_componentMetadata, null );
-
- // Before creating the implementation object, we are going to
- // test if all the mandatory dependencies are satisfied
- if ( !verifyDependencyManagers( getProperties() ) )
- {
- log( LogService.LOG_INFO, "Not all dependencies satisified, cannot activate", m_componentMetadata, null );
- setState( STATE_UNSATISFIED );
- return;
- }
-
- // 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 ( !createComponent() )
- {
- // component creation failed, not active now
- log( LogService.LOG_ERROR, "Component instance could not be created, activation failed",
- m_componentMetadata, null );
-
- // set state to unsatisfied
- setState( STATE_UNSATISFIED );
-
- return;
- }
-
- // set the service registration guard before we actually set our
- // state to satisfied. If we would set this after setting the
- // state to satisified, there would be a theoretical window
- // between this state setting and service locking
- lockServiceRegistration();
-
- // Validation occurs before the services are provided, otherwhise the
- // service provider's service may be called by a service requester
- // while it is still ACTIVATING
- setState( getSatisfiedState() );
- }
-
- // 5. Register provided services
- // call this outside of the synchronization to prevent a possible
- // deadlock if service registration tries to lock the framework or
- // owning bundle during registration (see FELIX-384)
- try
- {
- m_serviceRegistration = registerComponentService();
- log( LogService.LOG_DEBUG, "Component activated", m_componentMetadata, null );
- }
- catch ( IllegalStateException ise )
- {
- // thrown by service registration if the bundle is stopping
- // we just log this at debug level but ignore it
- log( LogService.LOG_DEBUG, "Component activation failed while registering the service",
- m_componentMetadata, ise );
- }
- finally
- {
- // reset the service registration guard
- unlockServiceRegistration();
- }
-
+ m_state.disableInternal( this );
}
-
- /**
- * This method deactivates the manager, performing the following steps
- *
- * [0. Remove published services from the registry]
- * 1. Call the deactivate() method, if present
- * 2. Unbind any bound services
- * 3. Release references to the component instance and component context
- **/
- private synchronized void deactivateInternal()
+ synchronized final void activateInternal()
{
- // CONCURRENCY NOTE: This method may be called either from the
- // ComponentActorThread to handle application induced disabling or
- // as a result of an unsatisfied service dependency leading to
- // component deactivation. We therefore have to guard against
- // paralell state changes.
- if ( !setStateConditional( STATE_ACTIVATING | STATE_ACTIVE | STATE_REGISTERED | STATE_FACTORY,
- STATE_DEACTIVATING ) )
- {
- return;
- }
-
- log( LogService.LOG_DEBUG, "Deactivating component", m_componentMetadata, null );
-
- // 0.- Remove published services from the registry
- boolean unregistered = unregisterComponentService();
- if ( !unregistered )
- {
- log( LogService.LOG_INFO, "Service could not be unregistered. Retrying after component deletion",
- m_componentMetadata, null );
- }
-
- // 1.- Call the deactivate method, if present
- // 2. Unbind any bound services
- // 3. Release references to the component instance and component context
- deleteComponent();
-
- // reset to state UNSATISFIED
- setState( STATE_UNSATISFIED );
-
- // clear the pending deactivation flag
- setPendingDeactivate( false );
-
- // safety belt: try again to unregister the service if not done already
- if ( !unregistered )
- {
- if ( !unregisterComponentService() )
- {
- log( LogService.LOG_INFO, "Service could still not be unregistered - Restart bundle " + getBundle()
- + " as a workaround", m_componentMetadata, null );
- }
- }
-
- log( LogService.LOG_DEBUG, "Component deactivated", m_componentMetadata, null );
+ m_state.activateInternal( this );
}
-
- private void disableInternal()
+ synchronized final void deactivateInternal()
{
- // CONCURRENCY NOTE: This method is only called from the BundleComponentActivator or by application logic
- // but not by the dependency managers
-
- // if the component is already disabled or destroyed, we have
- // nothing to do
- if ( ( getState() & ( STATE_DISABLED | STATE_DESTROYED ) ) != 0 )
- {
- log( LogService.LOG_DEBUG, "Component already disabled", m_componentMetadata, null );
- return;
- }
-
- // deactivate first, this does nothing if not active/registered/factory
- deactivateInternal();
-
- log( LogService.LOG_DEBUG, "Disabling component", m_componentMetadata, null );
-
- // dispose and recreate dependency managers
- disposeDependencyManagers();
- loadDependencyManagers( m_componentMetadata );
-
- // we are now disabled, ready for re-enablement or complete destroyal
- setState( STATE_DISABLED );
-
- log( LogService.LOG_DEBUG, "Component disabled", m_componentMetadata, null );
+ m_state.deactivateInternal( this );
}
-
- /**
- *
- */
- private void disposeInternal()
+ synchronized final void disposeInternal()
{
- // CONCURRENCY NOTE: This method is only called from the BundleComponentActivator or by application logic
- // but not by the dependency managers
-
- // if the component is already destroyed, we have nothing to do
- if ( getState() == STATE_DESTROYED )
- {
- log( LogService.LOG_DEBUG, "Component already destroyed", m_componentMetadata, null );
- return;
- }
-
- // disable first to clean up correctly
- disableInternal();
-
- // this component must not be used any more
- setState( STATE_DESTROYED );
-
- log( LogService.LOG_DEBUG, "Component disposed", m_componentMetadata, null );
-
- // release references (except component metadata for logging purposes)
- m_activator = null;
- m_dependencyManagers.clear();
+ m_state.deactivateInternal( this );
+ // For the sake of the performance(no need to loadDependencyManagers again),
+ // the disable transition is integrated into the destroy transition.
+ // That is to say, state "Enabled" goes directly into state "Desctroyed"
+ // in the event "dipose".
+ m_state.disposeInternal( this );
}
+ synchronized final ServiceReference getServiceReference()
+ {
+ return m_state.getServiceReference( this );
+ }
//---------- Component handling methods ----------------------------------
-
/**
- * Method is called by {@link #activate()} in STATE_ACTIVATING or by
- * {@link DelayedComponentManager#getService(Bundle, ServiceRegistration)}
- * in STATE_REGISTERED.
- *
- * @return <code>true</code> if creation of the component succeeded. If
- * <code>false</code> is returned, the cause should have been logged.
- */
+ * Method is called by {@link #activate()} in STATE_ACTIVATING or by
+ * {@link DelayedComponentManager#getService(Bundle, ServiceRegistration)}
+ * in STATE_REGISTERED.
+ *
+ * @return <code>true</code> if creation of the component succeeded. If
+ * <code>false</code> is returned, the cause should have been logged.
+ */
protected abstract boolean createComponent();
-
- /**
- * Method is called by {@link #deactivate()} in STATE_DEACTIVATING
- *
- */
protected abstract void deleteComponent();
-
/**
* Returns the service object to be registered if the service element is
* specified.
@@ -636,208 +644,64 @@
* Extensions of this class may overwrite this method to return a
* ServiceFactory to register in the case of a delayed or a service
* factory component.
- */
- protected abstract Object getService();
-
-
- /**
- * Returns the state value to set, when the component is satisfied. The
- * return value depends on the kind of the component:
- * <dl>
- * <dt>Immediate</dt><dd><code>STATE_ACTIVE</code></dd>
- * <dt>Delayed</dt><dd><code>STATE_REGISTERED</code></dd>
- * <dt>Component Factory</dt><dd><code>STATE_FACTORY</code></dd>
- * </dl>
*
* @return
*/
- private int getSatisfiedState()
- {
- if ( m_componentMetadata.isFactory() )
- {
- return STATE_FACTORY;
- }
- else if ( m_componentMetadata.isImmediate() )
- {
- return STATE_ACTIVE;
- }
- else
- {
- return STATE_REGISTERED;
- }
- }
+ protected abstract Object getService();
+ protected abstract State getSatisfiedState();
- // 5. Register provided services
- protected ServiceRegistration registerComponentService()
+ protected ServiceRegistration registerService()
{
if ( getComponentMetadata().getServiceMetadata() != null )
{
- log( LogService.LOG_DEBUG, "registering services", getComponentMetadata(), null );
+ log( LogService.LOG_DEBUG, "registering services", m_componentMetadata, null );
// get a copy of the component properties as service properties
Dictionary serviceProperties = copyTo( null, getProperties() );
return getActivator().getBundleContext().registerService(
- getComponentMetadata().getServiceMetadata().getProvides(), getService(), serviceProperties );
+ getComponentMetadata().getServiceMetadata().getProvides(),
+ getService(), serviceProperties );
}
return null;
}
-
- /**
- * Unregisters the component as a service if it has been registered at all.
- * <p>
- * This method tries to acquire the service registration lock before
- * unregistering the service. If the lock is not available, it cannot be
- * securely checked whether the service needs to be unregistered or not. In
- * this case the method return <code>true</code> only if the service
- * registration field is not currently set.
- *
- * @return <code>true</code> if the service could be unregistered or if the
- * component was not registered as a service in the first place.
- * Otherwise <code>false</code> is returned.
- */
- protected boolean unregisterComponentService()
+ // 5. Register provided services
+ protected void registerComponentService()
{
- // outside of try-finally to not trigger inadvertend unlock
- try {
- lockServiceRegistration();
- } catch (IllegalStateException ise) {
- // cannot acquire the lock, thus use insecure field check
- log( LogService.LOG_DEBUG, "Cannot unregister service reference: " + ise.getMessage(), m_componentMetadata,
- null );
-
- // if there was no service registration in the first place, this
- // is not a problem. Otherwise the service will not be unregistered
- return m_serviceRegistration == null;
- }
-
- try
- {
- if ( m_serviceRegistration != null )
- {
- m_serviceRegistration.unregister();
- m_serviceRegistration = null;
-
- log( LogService.LOG_DEBUG, "unregistering the services", getComponentMetadata(), null );
- }
- }
- finally
- {
- unlockServiceRegistration();
- }
-
- // there is no service registered any more
- return true;
+ m_serviceRegistration = registerService();
}
- //----------- Service Registration Locking --------------------------------
- // Implementation note for service registration locking
- // ----------------------------------------------------
- // The activateInternal method sets the component state to satisfied (aka
- // ready) before the component is registered as a service and the internal
- // service registration field is set.
- // If now in the time between setting the state to satisified and the
- // service registration field being set, the component is deactivated --
- // possibly through reconfiguration -- the service may not be unregistered
- // because the field is not set, but re-activation of the component may
- // register the service again thus resulting in two services being
- // registered, the active and the deactivated. Which of both is being used
- // is framework implementation dependent but chances are, the wrong is
- // used resulting in system failure.
- // To fix this, all access to the service registration field is guarded by
- // a lock. Only if a thread is able to set the lock flag, can the service
- // registration field be accessed.
- // To circumvent the above mentioned situation, the activateInternal method
- // locks the field _before_ setting the component satisfied. This prevents
- // the deactivateInternal method from deactivating the component until the
- // service has been registered and the lock been freed. Only then can the
- // deactivateInternal method start its deactivation task by unregistering
- // the service.
- // See FELIX-550 for more information.
-
- /**
- * Locks service registration by waiting for the registration to not be
- * locked and then locking it. If the lock does not get released within
- * 10 seconds an IllegalStateException is thrown. If the method terminates
- * normally, the service lock is now held by the current thread.
- *
- * @throws IllegalStateException if the service registration lock cannot be
- * acquired within 10 seconds. The message contains a human-readable
- * message mentioning the thread currently owning the lock.
- */
- private void lockServiceRegistration()
+ protected void unregisterComponentService()
{
- synchronized ( serviceRegistrationLock )
+
+ if ( m_serviceRegistration != null )
{
- if ( serviceRegistrationLockOwner != null )
- {
- log( LogService.LOG_INFO, "Waiting for Service Registration owned by " + serviceRegistrationLockOwner,
- m_componentMetadata, null );
+ log( LogService.LOG_DEBUG, "unregistering the services", m_componentMetadata, null );
- int waitGuard = 10;
- while ( serviceRegistrationLockOwner != null && waitGuard > 0 )
- {
- // wait at most one second
- try
- {
- serviceRegistrationLock.wait( 1000L );
- }
- catch ( InterruptedException ie )
- {
- // don't care
- }
- waitGuard--;
- }
-
- // timedout waiting for the service registration lock
- if ( waitGuard <= 0 )
- {
- throw new IllegalStateException( "Cannot get Service Registration, owned by "
- + serviceRegistrationLockOwner );
- }
-
- log( LogService.LOG_INFO, "Service Registration is now ready", m_componentMetadata, null );
- }
-
- serviceRegistrationLockOwner = Thread.currentThread();
- }
- }
-
-
- /**
- * Unlocks the service registration. This should only be called by the
- * thread actually holding the lock.
- */
- private void unlockServiceRegistration()
- {
- synchronized ( serviceRegistrationLock )
- {
- Thread current = Thread.currentThread();
- if ( serviceRegistrationLockOwner == current )
- {
- serviceRegistrationLockOwner = null;
-
- // notify threads waiting to lock service registration
- serviceRegistrationLock.notifyAll();
- }
- else
- {
- log( LogService.LOG_DEBUG, "Not releasing Service Registration by " + current + ", owner is "
- + serviceRegistrationLockOwner, m_componentMetadata, null );
- }
+ m_serviceRegistration.unregister();
+ m_serviceRegistration = null;
}
}
//**********************************************************************************************************
-
BundleComponentActivator getActivator()
{
return m_activator;
}
+ final ServiceRegistration getServiceRegistration()
+ {
+ return m_serviceRegistration;
+ }
+
+ void clear()
+ {
+ m_activator = null;
+ m_dependencyManagers.clear();
+ }
void log( int level, String message, ComponentMetadata metadata, Throwable ex )
{
@@ -848,25 +712,56 @@
}
}
-
- public String toString()
+ /**
+ * Activates this component if satisfied. If any of the dependencies is
+ * not met, the component is not activated and remains unsatisifed.
+ * <p>
+ * This method schedules the activation for asynchronous execution.
+ */
+ public final void activate()
{
- return "Component: " + getName() + " (" + getId() + ")";
+ getActivator().schedule( new ComponentActivatorTask( "Activate", this ) {
+ public void doRun()
+ {
+ activateInternal();
+ }
+ });
}
-
/**
- * Returns <code>true</code> if this instance has not been disposed off
- * yet and the BundleComponentActivator is still active. If the Bundle
- * Component Activator is being disposed off as a result of stopping the
- * owning bundle, this method returns <code>false</code>.
+ * Reconfigures this component by deactivating and activating it. During
+ * activation the new configuration data is retrieved from the Configuration
+ * Admin Service.
*/
- private boolean isActive()
+ public final void reconfigure()
{
- BundleComponentActivator bca = getActivator();
- return bca != null && bca.isActive();
+ log( LogService.LOG_DEBUG, "Deactivating and Activating to reconfigure",
+ m_componentMetadata, null );
+ reactivate();
}
+ /**
+ * Cycles this component by deactivating it and - if still satisfied -
+ * activating it again asynchronously.
+ * <p>
+ * This method schedules the deactivation and reactivation for asynchronous
+ * execution.
+ */
+ public final void reactivate()
+ {
+ getActivator().schedule(new ComponentActivatorTask( "Reactivate", this ) {
+
+ public void doRun()
+ {
+ deactivateInternal();
+ activateInternal();
+ }
+ });
+ }
+
+ public String toString() {
+ return "Component: " + getName() + " (" + getId() + ")";
+ }
private void loadDependencyManagers( ComponentMetadata metadata )
{
@@ -879,7 +774,7 @@
while ( dependencyit.hasNext() )
{
- ReferenceMetadata currentdependency = ( ReferenceMetadata ) dependencyit.next();
+ ReferenceMetadata currentdependency = (ReferenceMetadata) dependencyit.next();
DependencyManager depmanager = new DependencyManager( this, currentdependency );
@@ -890,18 +785,16 @@
m_dependencyManagers = depMgrList;
}
-
private void enableDependencyManagers() throws InvalidSyntaxException
{
Iterator it = getDependencyManagers();
while ( it.hasNext() )
{
- DependencyManager dm = ( DependencyManager ) it.next();
+ DependencyManager dm = (DependencyManager) it.next();
dm.enable();
}
}
-
private boolean verifyDependencyManagers( Dictionary properties )
{
// indicates whether all dependencies are satisfied
@@ -910,7 +803,7 @@
Iterator it = getDependencyManagers();
while ( it.hasNext() )
{
- DependencyManager dm = ( DependencyManager ) it.next();
+ DependencyManager dm = (DependencyManager) it.next();
// ensure the target filter is correctly set
dm.setTargetFilter( properties );
@@ -927,20 +820,18 @@
return satisfied;
}
-
Iterator getDependencyManagers()
{
return m_dependencyManagers.iterator();
}
-
- DependencyManager getDependencyManager( String name )
+ DependencyManager getDependencyManager(String name)
{
Iterator it = getDependencyManagers();
while ( it.hasNext() )
{
- DependencyManager dm = ( DependencyManager ) it.next();
- if ( name.equals( dm.getName() ) )
+ DependencyManager dm = (DependencyManager) it.next();
+ if ( name.equals(dm.getName()) )
{
return dm;
}
@@ -950,18 +841,16 @@
return null;
}
-
private void disposeDependencyManagers()
{
Iterator it = getDependencyManagers();
while ( it.hasNext() )
{
- DependencyManager dm = ( DependencyManager ) it.next();
+ DependencyManager dm = (DependencyManager) it.next();
dm.dispose();
}
}
-
/**
* Get the object that is implementing this descriptor
*
@@ -969,10 +858,8 @@
*/
public abstract Object getInstance();
-
public abstract Dictionary getProperties();
-
/**
* Copies the properties from the <code>source</code> <code>Dictionary</code>
* into the <code>target</code> <code>Dictionary</code>.
@@ -1006,33 +893,6 @@
return target;
}
-
- ServiceReference getServiceReference()
- {
- // outside of try-finally to not trigger inadvertend unlock
- try
- {
- lockServiceRegistration();
- }
- catch ( IllegalStateException ise )
- {
- // cannot acquire the lock, thus assume no service registration
- log( LogService.LOG_DEBUG, "Cannot return service reference: " + ise.getMessage(), m_componentMetadata,
- null );
- return null;
- }
-
- try
- {
- return ( m_serviceRegistration != null ) ? m_serviceRegistration.getReference() : null;
- }
- finally
- {
- unlockServiceRegistration();
- }
- }
-
-
/**
*
*/
@@ -1041,79 +901,28 @@
return m_componentMetadata;
}
-
public int getState()
{
+ return m_state.getState();
+ }
+
+ protected State state()
+ {
return m_state;
}
-
/**
* sets the state of the manager
- **/
- protected synchronized void setState( int newState )
+ **/
+ void changeState( State newState )
{
log( LogService.LOG_DEBUG,
- "State transition : " + stateToString( m_state ) + " -> " + stateToString( newState ), m_componentMetadata,
- null );
+ "State transition : " + m_state + " -> " + newState,
+ m_componentMetadata, null );
m_state = newState;
}
-
- /**
- * If the state is currently one of the <code>requiredStates</code>, the
- * state is set to <code>newState</code> and <code>true</code> is returned.
- * Otherwise the state is not changed and <code>false</code> is returned.
- * <p>
- * This method atomically checks the current state and sets the new state.
- *
- * @param requiredStates The set of states required for the state change to
- * happen.
- * @param newState The new state to go into.
- * @return <code>true</code> if the state was one of the required states and
- * the new state has now been entered.
- */
- protected synchronized boolean setStateConditional( int requiredStates, int newState )
- {
- if ( ( getState() & requiredStates ) != 0 )
- {
- setState( newState );
- return true;
- }
-
- return false;
- }
-
-
- public String stateToString( int state )
- {
- switch ( state )
- {
- case STATE_DESTROYED:
- return "Destroyed";
- case STATE_DISABLED:
- return "Disabled";
- case STATE_ENABLED:
- return "Enabled";
- case STATE_UNSATISFIED:
- return "Unsatisfied";
- case STATE_ACTIVATING:
- return "Activating";
- case STATE_ACTIVE:
- return "Active";
- case STATE_REGISTERED:
- return "Registered";
- case STATE_FACTORY:
- return "Factory";
- case STATE_DEACTIVATING:
- return "Deactivating";
- default:
- return String.valueOf( state );
- }
- }
-
-
/**
* Finds the named public or protected method in the given class or any
* super class. If such a method is found, its accessibility is enfored by
@@ -1136,7 +945,7 @@
* trying to access the desired method.
*/
static Method getMethod( Class clazz, String name, Class[] parameterTypes, boolean only )
- throws NoSuchMethodException, InvocationTargetException
+ throws NoSuchMethodException, InvocationTargetException
{
for ( ; clazz != null; clazz = clazz.getSuperclass() )
{
@@ -1146,7 +955,7 @@
Method method = clazz.getDeclaredMethod( name, parameterTypes );
// accept public and protected methods only and ensure accessibility
- if ( Modifier.isPublic( method.getModifiers() ) || Modifier.isProtected( method.getModifiers() ) )
+ if ( Modifier.isPublic( method.getModifiers() ) || Modifier.isProtected( method.getModifiers()) )
{
method.setAccessible( true );
return method;
@@ -1166,7 +975,8 @@
{
// unexpected problem accessing the method, don't let everything
// blow up in this situation, just throw a declared exception
- throw new InvocationTargetException( throwable, "Unexpected problem trying to get method " + name );
+ throw new InvocationTargetException( throwable,
+ "Unexpected problem trying to get method " + name );
}
}
@@ -1174,5 +984,4 @@
// anything, sigh ...
throw new NoSuchMethodException( name );
}
-
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
index ee62499..b537330 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
@@ -321,7 +321,7 @@
* configuration data for components managed by this activator or
* <code>null</code> if no Configuration Admin Service is available in the
* framework.
- */
+ */
protected ConfigurationAdmin getConfigurationAdmin()
{
return ( ConfigurationAdmin ) m_configurationAdmin.getService();
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/ComponentFactoryImpl.java
index 966dd35..163c65c 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/ComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/ComponentFactoryImpl.java
@@ -18,22 +18,24 @@
*/
package org.apache.felix.scr.impl;
-
-import java.util.*;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.Map;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ManagedServiceFactory;
-import org.osgi.service.component.*;
+import org.osgi.service.component.ComponentConstants;
+import org.osgi.service.component.ComponentFactory;
+import org.osgi.service.component.ComponentInstance;
import org.osgi.service.log.LogService;
-
/**
* The <code>ComponentFactoryImpl</code> TODO
- *
- * @author fmeschbe
*/
-public class ComponentFactoryImpl extends AbstractComponentManager implements ComponentFactory, ManagedServiceFactory
+class ComponentFactoryImpl extends AbstractComponentManager implements ComponentFactory, ManagedServiceFactory
{
// The component registry used to retrieve component IDs
@@ -79,8 +81,11 @@
// nothing to delete
}
+ protected State getSatisfiedState() {
+ return Factory.getInstance();
+ }
- protected ServiceRegistration registerComponentService()
+ protected ServiceRegistration registerService()
{
log( LogService.LOG_DEBUG, "registering component factory", getComponentMetadata(), null );
@@ -154,7 +159,6 @@
}
}
-
public void deleted( String pid )
{
if ( m_configuredServices != null )
@@ -163,7 +167,7 @@
if ( cm != null )
{
log( LogService.LOG_DEBUG, "Disposing component after configuration deletion", getComponentMetadata(),
- null );
+ null );
disposeComponentManager( cm );
}
@@ -179,7 +183,6 @@
//---------- internal -----------------------------------------------------
-
/**
* ComponentManager instances created by this method are not registered
* with the ComponentRegistry. Therefore, any configuration update to these
@@ -212,21 +215,22 @@
if ( isNewInstance )
{
cm.setFactoryProperties( configuration );
+ // enable synchronously
+ cm.enableInternal();
+ cm.activateInternal();
}
else
{
// this should not call component reactivation because it is
// not active yet
cm.reconfigure( configuration );
+ // enable asynchronously
+ cm.enable();
}
- // enable synchronously or asynchronously depending on the flag
- cm.enable( isNewInstance );
-
return cm;
}
-
private void disposeComponentManager( ComponentManager cm )
{
// remove from created components
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/DelayedComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/DelayedComponentManager.java
index 9529a85..e2abdf3 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/DelayedComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/DelayedComponentManager.java
@@ -22,16 +22,12 @@
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.log.LogService;
/**
* The <code>DelayedComponentManager</code> TODO
- *
- * @author fmeschbe
- * @version $Rev$, $Date$
*/
-public class DelayedComponentManager extends ImmediateComponentManager implements ServiceFactory
+class DelayedComponentManager extends ImmediateComponentManager implements ServiceFactory
{
/**
@@ -45,6 +41,12 @@
}
+ protected State getSatisfiedState()
+ {
+ return Registered.getInstance();
+ }
+
+
protected boolean createComponent()
{
// nothing to do here for a delayed component, will be done in the
@@ -71,26 +73,15 @@
//---------- ServiceFactory interface -------------------------------------
- public Object getService( Bundle arg0, ServiceRegistration arg1 )
+ public synchronized Object getService( Bundle bundle, ServiceRegistration sr )
{
- log( LogService.LOG_DEBUG, "DelayedComponentServiceFactory.getService()", getComponentMetadata(), null );
-
- // When the getServiceMethod is called, the implementation object must be created
- // unless another bundle has already retrievd it
-
- if ( getInstance() == null )
- {
- super.createComponent();
-
- // if component creation failed, we were deactivated and the state
- // is not REGISTERED any more. Otherwise go to standard ACTIVE
- // state now
- setStateConditional( STATE_REGISTERED, STATE_ACTIVE );
- }
-
- return getInstance();
+ return state().getService(this);
}
+ protected boolean createRealComponent()
+ {
+ return super.createComponent();
+ }
public void ungetService( Bundle arg0, ServiceRegistration arg1, Object arg2 )
{
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/impl/DependencyManager.java
index ba52a86..031e6cb 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/DependencyManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/DependencyManager.java
@@ -203,8 +203,7 @@
// if the component is currently unsatisfied, it may become satisfied
// by adding this service, try to activate (also schedule activation
// if the component is pending deactivation)
- if ( m_componentManager.getState() == AbstractComponentManager.STATE_UNSATISFIED
- || m_componentManager.isPendingDeactivate() )
+ if ( m_componentManager.getState() == AbstractComponentManager.STATE_ENABLED )
{
m_componentManager.log( LogService.LOG_INFO, "Dependency Manager: Service "
+ m_dependencyMetadata.getName() + " registered, activate component", m_componentManager
@@ -263,9 +262,10 @@
else
{
- m_componentManager.log( LogService.LOG_DEBUG, "Dependency Manager: Ignoring service addition, wrong state "
- + m_componentManager.stateToString( m_componentManager.getState() ), m_componentManager
- .getComponentMetadata(), null );
+ m_componentManager.log( LogService.LOG_DEBUG,
+ "Dependency Manager: Ignoring service addition, wrong state "
+ + m_componentManager.state(),
+ m_componentManager.getComponentMetadata(), null );
}
}
@@ -309,7 +309,7 @@
+ " not satisfied", m_componentManager.getComponentMetadata(), null );
// deactivate the component now
- m_componentManager.deactivate();
+ m_componentManager.deactivateInternal();
}
// if the dependency is static, we have to reactivate the component
@@ -321,7 +321,8 @@
m_componentManager.log( LogService.LOG_DEBUG, "Dependency Manager: Static dependency on "
+ m_dependencyMetadata.getName() + "/" + m_dependencyMetadata.getInterface() + " is broken",
m_componentManager.getComponentMetadata(), null );
- m_componentManager.reactivate();
+ m_componentManager.deactivateInternal();
+ m_componentManager.activate();
}
catch ( Exception ex )
{
@@ -346,7 +347,7 @@
"Dependency Manager: Deactivating component due to mandatory dependency on "
+ m_dependencyMetadata.getName() + "/" + m_dependencyMetadata.getInterface()
+ " not satisfied", m_componentManager.getComponentMetadata(), null );
- m_componentManager.deactivate();
+ m_componentManager.deactivateInternal();
// abort here we do not need to do more
return;
@@ -366,9 +367,10 @@
else
{
- m_componentManager.log( LogService.LOG_DEBUG, "Dependency Manager: Ignoring service removal, wrong state "
- + m_componentManager.stateToString( m_componentManager.getState() ), m_componentManager
- .getComponentMetadata(), null );
+ m_componentManager.log( LogService.LOG_DEBUG,
+ "Dependency Manager: Ignoring service removal, wrong state "
+ + m_componentManager.state(),
+ m_componentManager.getComponentMetadata(), null );
}
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ImmediateComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/ImmediateComponentManager.java
index 3a24675..68f73fd 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/ImmediateComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/ImmediateComponentManager.java
@@ -37,7 +37,6 @@
/**
* The default ComponentManager. Objects of this class are responsible for managing
* implementation object's lifecycle.
- *
*/
class ImmediateComponentManager extends AbstractComponentManager
{
@@ -101,7 +100,7 @@
* Before doing real disposal, we also have to unregister the managed
* service which was registered when the instance was created.
*/
- public void dispose()
+ public synchronized void dispose()
{
if ( m_managedServiceRegistration != null )
{
@@ -117,7 +116,7 @@
}
// really dispose off this manager instance
- super.dispose();
+ disposeInternal();
}
@@ -153,6 +152,11 @@
m_properties = null;
}
+ protected State getSatisfiedState()
+ {
+ return Active.getInstance();
+ }
+
//**********************************************************************************************************
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ServiceFactoryComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/ServiceFactoryComponentManager.java
index 7978573..8cdf007 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/ServiceFactoryComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/ServiceFactoryComponentManager.java
@@ -32,7 +32,7 @@
/**
* The <code>ServiceFactoryComponentManager</code> TODO
*/
-public class ServiceFactoryComponentManager extends ImmediateComponentManager implements ServiceFactory
+class ServiceFactoryComponentManager extends ImmediateComponentManager implements ServiceFactory
{
// maintain the map of ComponentContext objects created for the
@@ -42,7 +42,8 @@
/**
* @param activator
- * @param metadata
+ * @param metadata
+ * @param componentId
*/
public ServiceFactoryComponentManager( BundleComponentActivator activator, ComponentMetadata metadata,
long componentId )
@@ -51,6 +52,12 @@
}
+ protected State getSatisfiedState()
+ {
+ return Factory.getInstance();
+ }
+
+
/* (non-Javadoc)
* @see org.apache.felix.scr.AbstractComponentManager#createComponent()
*/
@@ -107,7 +114,16 @@
serviceContexts.put( service, serviceContext );
// if this is the first use of this component, switch to ACTIVE state
- setStateConditional( STATE_REGISTERED, STATE_ACTIVE );
+ if (getState() == STATE_FACTORY)
+ {
+ synchronized(this)
+ {
+ if (getState() == STATE_FACTORY)
+ {
+ changeState(Active.getInstance());
+ }
+ }
+ }
}
return service;
@@ -130,7 +146,16 @@
// if this was the last use of the component, go back to REGISTERED state
if ( serviceContexts.isEmpty() )
{
- setStateConditional( STATE_ACTIVE, STATE_REGISTERED );
+ if (getState() == STATE_ACTIVE)
+ {
+ synchronized(this)
+ {
+ if (getState() == STATE_ACTIVE)
+ {
+ changeState(Factory.getInstance());
+ }
+ }
+ }
}
}