FELIX-341 Intermittent exception during Felix shutdown
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@568657 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java
index 91aa1d5..d9f49bd 100644
--- a/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java
@@ -18,6 +18,7 @@
*/
package org.apache.felix.scr;
+
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
@@ -27,7 +28,6 @@
import java.util.Iterator;
import java.util.List;
-import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentInstance;
@@ -61,7 +61,7 @@
// manager for a component factory has been registered
static final int STATE_FACTORY = 64;
- // manager is current deactivating
+ // manager is current deactivating
static final int STATE_DEACTIVATING = 128;
// manager has been destroyed and may not be used anymore
@@ -82,13 +82,14 @@
// The ServiceRegistration
private ServiceRegistration m_serviceRegistration;
+
/**
* The constructor receives both the activator and the metadata
*
* @param activator
* @param metadata
*/
- protected AbstractComponentManager(BundleComponentActivator activator, ComponentMetadata metadata)
+ protected AbstractComponentManager( BundleComponentActivator activator, ComponentMetadata metadata )
{
m_activator = activator;
m_componentMetadata = metadata;
@@ -96,9 +97,10 @@
m_state = STATE_DISABLED;
m_dependencyManagers = new ArrayList();
- Activator.trace("Component created", m_componentMetadata);
+ Activator.trace( "Component created", m_componentMetadata );
}
+
//---------- Asynchronous frontend to state change methods ----------------
/**
@@ -111,32 +113,36 @@
* <p>
* This method schedules the enablement for asynchronous execution.
*/
- public final void enable() {
- this.getActivator().schedule( new Runnable()
+ public final void enable()
+ {
+ getActivator().schedule( new Runnable()
{
public void run()
{
- AbstractComponentManager.this.enableInternal();
+ enableInternal();
}
} );
}
+
/**
* 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() {
- this.getActivator().schedule( new Runnable()
+ public final void activate()
+ {
+ getActivator().schedule( new Runnable()
{
public void run()
{
- AbstractComponentManager.this.activateInternal();
+ activateInternal();
}
} );
}
+
/**
* Reconfigures this component by deactivating and activating it. During
* activation the new configuration data is retrieved from the Configuration
@@ -145,58 +151,65 @@
public final void reconfigure()
{
Activator.trace( "Deactivating and Activating to reconfigure", m_componentMetadata );
- this.reactivate();
+ reactivate();
}
+
/**
* Cycles this component by deactivating it and - if still satisfied -
* activating it again.
* <p>
* This method schedules the reactivation for asynchronous execution.
*/
- public final void reactivate() {
- this.getActivator().schedule( new Runnable()
+ public final void reactivate()
+ {
+ getActivator().schedule( new Runnable()
{
public void run()
{
- AbstractComponentManager.this.deactivateInternal();
- Activator.trace( "Dependency Manager: RECREATING", AbstractComponentManager.this.m_componentMetadata );
- AbstractComponentManager.this.activateInternal();
+ deactivateInternal();
+ Activator.trace( "Dependency Manager: RECREATING", m_componentMetadata );
+ activateInternal();
}
} );
}
+
/**
* Deactivates the component.
* <p>
* This method schedules the deactivation for asynchronous execution.
*/
- public final void deactivate() {
- this.getActivator().schedule( new Runnable()
+ public final void deactivate()
+ {
+ getActivator().schedule( new Runnable()
{
public void run()
{
- AbstractComponentManager.this.deactivateInternal();
+ deactivateInternal();
}
} );
}
+
/**
* Disables this component and - if active - first deactivates it. The
* component may be reenabled by calling the {@link #enable()} method.
* <p>
* This method schedules the disablement for asynchronous execution.
*/
- public final void disable() {
- this.getActivator().schedule( new Runnable()
+ public final void disable()
+ {
+ getActivator().schedule( new Runnable()
{
public void run()
{
- AbstractComponentManager.this.disableInternal();
+ disableInternal();
}
} );
}
+
/**
* Disposes off this component deactivating and disabling it first as
* required. After disposing off the component, it may not be used anymore.
@@ -206,10 +219,12 @@
* method has to actually complete before other actions like bundle stopping
* may continue.
*/
- public final void dispose() {
- this.disposeInternal();
+ public final void dispose()
+ {
+ disposeInternal();
}
+
//---------- internal immediate state change methods ----------------------
// these methods must only be called from a separate thread by calling
// the respective asynchronous (public) method
@@ -219,56 +234,58 @@
*
* @return true if enabling was successful
*/
- private void enableInternal() {
+ private void enableInternal()
+ {
- if (this.getState() == STATE_DESTROYED)
+ if ( getState() == STATE_DESTROYED )
{
Activator.error( "Destroyed Component cannot be enabled", m_componentMetadata );
return;
}
- else if (this.getState() != STATE_DISABLED)
+ else if ( getState() != STATE_DISABLED )
{
Activator.trace( "Component is already enabled", m_componentMetadata );
return;
}
- Activator.trace("Enabling component", m_componentMetadata);
+ Activator.trace( "Enabling component", m_componentMetadata );
- try
- {
- // If this component has got dependencies, create dependency managers for each one of them.
- if (m_componentMetadata.getDependencies().size() != 0)
- {
- Iterator dependencyit = m_componentMetadata.getDependencies().iterator();
+ try
+ {
+ // If this component has got dependencies, create dependency managers for each one of them.
+ if ( m_componentMetadata.getDependencies().size() != 0 )
+ {
+ Iterator dependencyit = m_componentMetadata.getDependencies().iterator();
- while(dependencyit.hasNext())
- {
- ReferenceMetadata currentdependency = (ReferenceMetadata)dependencyit.next();
+ while ( dependencyit.hasNext() )
+ {
+ ReferenceMetadata currentdependency = ( ReferenceMetadata ) dependencyit.next();
- DependencyManager depmanager = new DependencyManager(this, currentdependency);
+ DependencyManager depmanager = new DependencyManager( this, currentdependency );
- m_dependencyManagers.add(depmanager);
- }
- }
+ m_dependencyManagers.add( depmanager );
+ }
+ }
// enter enabled state before trying to activate
- this.setState( STATE_ENABLED );
+ setState( STATE_ENABLED );
- Activator.trace("Component enabled", m_componentMetadata);
+ Activator.trace( "Component enabled", m_componentMetadata );
// immediately activate the compopnent, no need to schedule again
- this.activateInternal();
- }
- catch(Exception ex)
- {
- Activator.exception( "Failed enabling Component", m_componentMetadata, ex );
+ activateInternal();
+ }
+ catch ( Exception ex )
+ {
+ Activator.exception( "Failed enabling Component", m_componentMetadata, ex );
// ensure we get back to DISABLED state
// immediately disable, no need to schedule again
- this.disableInternal();
- }
+ disableInternal();
+ }
}
+
/**
* Activate this Instance manager.
*
@@ -279,233 +296,260 @@
* 4. Call the activate method, if present
* [5. Register provided services]
*/
- private void activateInternal()
- {
- // CONCURRENCY NOTE: This method is called either by the enable()
- // method or by the dependency managers or the reconfigure() method
- if ( (this.getState() & (STATE_ENABLED|STATE_UNSATISFIED)) == 0)
- {
- // This state can only be entered from the ENABLED (in the enable()
- // method) or UNSATISFIED (missing references) states
- return;
- }
+ private void activateInternal()
+ {
+ // CONCURRENCY NOTE: This method is called either by the enable()
+ // method or by the dependency managers or the reconfigure() method
+ if ( ( getState() & ( STATE_ENABLED | STATE_UNSATISFIED ) ) == 0 )
+ {
+ // This state can only be entered from the ENABLED (in the enable()
+ // method) or UNSATISFIED (missing references) states
+ return;
+ }
- // go to the activating state
- this.setState(STATE_ACTIVATING);
+ // go to the activating state
+ setState( STATE_ACTIVATING );
- Activator.trace("Activating component", m_componentMetadata);
+ Activator.trace( "Activating component", m_componentMetadata );
- // Before creating the implementation object, we are going to
- // test if all the mandatory dependencies are satisfied
- Iterator it = m_dependencyManagers.iterator();
- while (it.hasNext())
- {
- DependencyManager dm = (DependencyManager)it.next();
- if (!dm.isValid())
- {
- // at least one dependency is not satisfied
- Activator.trace( "Dependency not satisfied: " + dm.getName(), m_componentMetadata );
- this.setState(STATE_UNSATISFIED);
- return;
- }
- }
+ // Before creating the implementation object, we are going to
+ // test if all the mandatory dependencies are satisfied
+ Iterator it = m_dependencyManagers.iterator();
+ while ( it.hasNext() )
+ {
+ DependencyManager dm = ( DependencyManager ) it.next();
+ if ( !dm.isValid() )
+ {
+ // at least one dependency is not satisfied
+ Activator.trace( "Dependency not satisfied: " + dm.getName(), m_componentMetadata );
+ 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
- this.createComponent();
+ // 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
+ Activator.error( "Component instance could not be created, activation failed", m_componentMetadata );
- // 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
- this.setState(this.getSatisfiedState());
+ // set state to unsatisfied
+ setState( STATE_UNSATISFIED );
- // 5. Register provided services
- m_serviceRegistration = this.registerComponentService();
+ return;
+ }
- Activator.trace("Component activated", m_componentMetadata);
- }
+ // 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() );
- /**
- * 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 void deactivateInternal()
- {
- // CONCURRENCY NOTE: This method may be called either from application
- // code or by the dependency managers or reconfiguration
- if ((this.getState() & (STATE_ACTIVATING|STATE_ACTIVE|STATE_REGISTERED|STATE_FACTORY)) == 0)
- {
- // This state can only be entered from the ACTIVATING (if activation
- // fails), ACTIVE, REGISTERED or FACTORY states
- return;
- }
+ // 5. Register provided services
+ m_serviceRegistration = registerComponentService();
- // start deactivation by resetting the state
- this.setState( STATE_DEACTIVATING );
+ Activator.trace( "Component activated", m_componentMetadata );
+ }
- Activator.trace("Deactivating component", m_componentMetadata);
- // 0.- Remove published services from the registry
- this.unregisterComponentService();
+ /**
+ * 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 void deactivateInternal()
+ {
+ // CONCURRENCY NOTE: This method may be called either from application
+ // code or by the dependency managers or reconfiguration
+ if ( ( getState() & ( STATE_ACTIVATING | STATE_ACTIVE | STATE_REGISTERED | STATE_FACTORY ) ) == 0 )
+ {
+ // This state can only be entered from the ACTIVATING (if activation
+ // fails), ACTIVE, REGISTERED or FACTORY states
+ return;
+ }
- // 1.- Call the deactivate method, if present
- // 2. Unbind any bound services
- // 3. Release references to the component instance and component context
- this.deleteComponent();
+ // start deactivation by resetting the state
+ setState( STATE_DEACTIVATING );
- //Activator.trace("InstanceManager from bundle ["+ m_activator.getBundleContext().getBundle().getBundleId() + "] was invalidated.");
+ Activator.trace( "Deactivating component", m_componentMetadata );
- // reset to state UNSATISFIED
- this.setState( STATE_UNSATISFIED );
+ // 0.- Remove published services from the registry
+ unregisterComponentService();
- Activator.trace("Component deactivated", m_componentMetadata);
- }
+ // 1.- Call the deactivate method, if present
+ // 2. Unbind any bound services
+ // 3. Release references to the component instance and component context
+ deleteComponent();
- private void disableInternal()
- {
- // CONCURRENCY NOTE: This method is only called from the BundleComponentActivator or by application logic
- // but not by the dependency managers
+ //Activator.trace("InstanceManager from bundle ["+ m_activator.getBundleContext().getBundle().getBundleId() + "] was invalidated.");
- // deactivate first, this does nothing if not active/registered/factory
- this.deactivateInternal();
+ // reset to state UNSATISFIED
+ setState( STATE_UNSATISFIED );
- Activator.trace("Disabling component", m_componentMetadata);
+ Activator.trace( "Component deactivated", m_componentMetadata );
+ }
- // close all service listeners now, they are recreated on enable
- // Stop the dependency managers to listen to events...
- Iterator it = m_dependencyManagers.iterator();
- while (it.hasNext())
- {
- DependencyManager dm = (DependencyManager)it.next();
- dm.close();
- }
- m_dependencyManagers.clear();
- // we are now disabled, ready for re-enablement or complete destroyal
- this.setState( STATE_DISABLED );
-
- Activator.trace("Component disabled", m_componentMetadata);
- }
-
- /**
- *
- */
- private void disposeInternal()
- {
- // CONCURRENCY NOTE: This method is only called from the BundleComponentActivator or by application logic
+ private void disableInternal()
+ {
+ // CONCURRENCY NOTE: This method is only called from the BundleComponentActivator or by application logic
// but not by the dependency managers
- // disable first to clean up correctly
- this.disableInternal();
+ // deactivate first, this does nothing if not active/registered/factory
+ deactivateInternal();
- // this component must not be used any more
- this.setState( STATE_DESTROYED );
+ Activator.trace( "Disabling component", m_componentMetadata );
- // release references (except component metadata for logging purposes)
- m_activator = null;
- m_dependencyManagers = null;
+ // close all service listeners now, they are recreated on enable
+ // Stop the dependency managers to listen to events...
+ Iterator it = m_dependencyManagers.iterator();
+ while ( it.hasNext() )
+ {
+ DependencyManager dm = ( DependencyManager ) it.next();
+ dm.close();
+ }
+ m_dependencyManagers.clear();
- Activator.trace("Component disposed", m_componentMetadata);
- }
+ // we are now disabled, ready for re-enablement or complete destroyal
+ setState( STATE_DISABLED );
- //---------- Component handling methods ----------------------------------
+ Activator.trace( "Component disabled", m_componentMetadata );
+ }
- /**
- * Method is called by {@link #activate()} in STATE_ACTIVATING or by
- * {@link DelayedComponentManager#getService(Bundle, ServiceRegistration)}
- * in STATE_REGISTERED.
- */
- protected abstract void createComponent();
- /**
- * Method is called by {@link #deactivate()} in STATE_DEACTIVATING
- *
- */
- protected abstract void deleteComponent();
+ /**
+ *
+ */
+ private void disposeInternal()
+ {
+ // CONCURRENCY NOTE: This method is only called from the BundleComponentActivator or by application logic
+ // but not by the dependency managers
- /**
- * Returns the service object to be registered if the service element is
- * specified.
- * <p>
- * 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();
+ // disable first to clean up correctly
+ disableInternal();
- /**
- * 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;
- }
- }
+ // this component must not be used any more
+ setState( STATE_DESTROYED );
- // 5. Register provided services
- protected ServiceRegistration registerComponentService()
- {
- if ( this.getComponentMetadata().getServiceMetadata() != null )
- {
- Activator.trace( "registering services", this.getComponentMetadata() );
+ // release references (except component metadata for logging purposes)
+ m_activator = null;
+ m_dependencyManagers = null;
- // get a copy of the component properties as service properties
- Dictionary serviceProperties = this.copyTo( null, this.getProperties() );
+ Activator.trace( "Component disposed", m_componentMetadata );
+ }
- return this.getActivator().getBundleContext().registerService(
- this.getComponentMetadata().getServiceMetadata().getProvides(), this.getService(), serviceProperties );
- }
- return null;
- }
+ //---------- Component handling methods ----------------------------------
- protected void unregisterComponentService()
- {
- if ( m_serviceRegistration != null )
- {
- m_serviceRegistration.unregister();
- m_serviceRegistration = null;
+ /**
+ * 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();
- Activator.trace( "unregistering the services", this.getComponentMetadata() );
- }
- }
+
+ /**
+ * 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.
+ * <p>
+ * 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;
+ }
+ }
+
+
+ // 5. Register provided services
+ protected ServiceRegistration registerComponentService()
+ {
+ if ( getComponentMetadata().getServiceMetadata() != null )
+ {
+ Activator.trace( "registering services", getComponentMetadata() );
+
+ // get a copy of the component properties as service properties
+ Dictionary serviceProperties = copyTo( null, getProperties() );
+
+ return getActivator().getBundleContext().registerService(
+ getComponentMetadata().getServiceMetadata().getProvides(), getService(), serviceProperties );
+ }
+
+ return null;
+ }
+
+
+ protected void unregisterComponentService()
+ {
+ if ( m_serviceRegistration != null )
+ {
+ m_serviceRegistration.unregister();
+ m_serviceRegistration = null;
+
+ Activator.trace( "unregistering the services", getComponentMetadata() );
+ }
+ }
+
//**********************************************************************************************************
- BundleComponentActivator getActivator() {
+ BundleComponentActivator getActivator()
+ {
return m_activator;
}
- Iterator getDependencyManagers() {
+
+ Iterator getDependencyManagers()
+ {
return m_dependencyManagers.iterator();
}
+
DependencyManager getDependencyManager( String name )
{
- Iterator it = this.getDependencyManagers();
+ Iterator it = getDependencyManagers();
while ( it.hasNext() )
{
DependencyManager dm = ( DependencyManager ) it.next();
@@ -520,14 +564,18 @@
return null;
}
+
/**
* Get the object that is implementing this descriptor
*
* @return the object that implements the services
*/
public abstract Object getInstance();
+
+
protected abstract Dictionary getProperties();
+
/**
* Copies the properties from the <code>source</code> <code>Dictionary</code>
* into the <code>target</code> <code>Dictionary</code>.
@@ -561,33 +609,44 @@
return target;
}
- ServiceReference getServiceReference() {
+
+ ServiceReference getServiceReference()
+ {
return ( m_serviceRegistration != null ) ? m_serviceRegistration.getReference() : null;
}
+
/**
*
*/
- public ComponentMetadata getComponentMetadata() {
- return m_componentMetadata;
+ public ComponentMetadata getComponentMetadata()
+ {
+ return m_componentMetadata;
}
- int getState() {
+
+ int getState()
+ {
return m_state;
}
+
/**
* sets the state of the manager
**/
- protected synchronized void setState(int newState) {
- Activator.trace( "State transition : " + this.stateToString( m_state ) + " -> " + this.stateToString( newState ),
+ protected synchronized void setState( int newState )
+ {
+ Activator.trace( "State transition : " + stateToString( m_state ) + " -> " + stateToString( newState ),
m_componentMetadata );
m_state = newState;
}
- public String stateToString(int state) {
- switch (state) {
+
+ public String stateToString( int state )
+ {
+ switch ( state )
+ {
case STATE_DESTROYED:
return "Destroyed";
case STATE_DISABLED:
@@ -607,9 +666,11 @@
case STATE_DEACTIVATING:
return "Deactivating";
default:
- return String.valueOf(state);
+ 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
@@ -627,15 +688,14 @@
* @throws NoSuchMethodException If no public or protected method with
* the given name can be found in the class or any of its super classes.
*/
- static Method getMethod(Class clazz, String name, Class[] parameterTypes)
- throws NoSuchMethodException
+ static Method getMethod( Class clazz, String name, Class[] parameterTypes ) throws NoSuchMethodException
{
// try the default mechanism first, which only yields public methods
try
{
- return clazz.getMethod(name, parameterTypes);
+ return clazz.getMethod( name, parameterTypes );
}
- catch (NoSuchMethodException nsme)
+ catch ( NoSuchMethodException nsme )
{
// it is ok to not find a public method, try to find a protected now
}
@@ -643,21 +703,22 @@
// now use method declarations, requiring walking up the class
// hierarchy manually. this algorithm also returns protected methods
// which is, what we need here
- for ( ; clazz != null; clazz = clazz.getSuperclass())
+ for ( ; clazz != null; clazz = clazz.getSuperclass() )
{
try
{
- Method method = clazz.getDeclaredMethod(name, parameterTypes);
+ Method method = clazz.getDeclaredMethod( name, parameterTypes );
// only accept a protected method, a public method should
// have been found above and neither private nor package
// protected methods are acceptable here
- if (Modifier.isProtected(method.getModifiers())) {
- method.setAccessible(true);
+ if ( Modifier.isProtected( method.getModifiers() ) )
+ {
+ method.setAccessible( true );
return method;
}
}
- catch (NoSuchMethodException nsme)
+ catch ( NoSuchMethodException nsme )
{
// ignore for now
}
@@ -665,7 +726,7 @@
// walked up the complete super class hierarchy and still not found
// anything, sigh ...
- throw new NoSuchMethodException(name);
+ throw new NoSuchMethodException( name );
}
}
diff --git a/scr/src/main/java/org/apache/felix/scr/ComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/ComponentFactoryImpl.java
index 63afd4c..c18143c 100644
--- a/scr/src/main/java/org/apache/felix/scr/ComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/ComponentFactoryImpl.java
@@ -53,6 +53,7 @@
// no IdentityHashSet and HashSet internally uses a HashMap anyway
private Map m_createdComponents;
+
ComponentFactoryImpl( BundleComponentActivator activator, ComponentMetadata metadata,
ComponentRegistry componentRegistry )
{
@@ -67,15 +68,17 @@
*/
public ComponentInstance newInstance( Dictionary dictionary )
{
- return ( ComponentInstance ) this.createComponentManager( dictionary );
+ return ( ComponentInstance ) createComponentManager( dictionary );
}
- protected void createComponent()
+ protected boolean createComponent()
{
// not component to create, newInstance must be used instead
+ return true;
}
+
protected void deleteComponent()
{
// nothing to delete
@@ -84,11 +87,11 @@
protected ServiceRegistration registerComponentService()
{
- Activator.trace( "registering component factory", this.getComponentMetadata() );
+ Activator.trace( "registering component factory", getComponentMetadata() );
- Dictionary serviceProperties = this.getProperties();
- return this.getActivator().getBundleContext().registerService( new String[]
- { ComponentFactory.class.getName(), ManagedServiceFactory.class.getName() }, this.getService(),
+ Dictionary serviceProperties = getProperties();
+ return getActivator().getBundleContext().registerService( new String[]
+ { ComponentFactory.class.getName(), ManagedServiceFactory.class.getName() }, getService(),
serviceProperties );
}
@@ -105,11 +108,11 @@
Dictionary props = new Hashtable();
// 112.5.5 The Component Factory service must register with the following properties
- props.put( ComponentConstants.COMPONENT_NAME, this.getComponentMetadata().getName() );
- props.put( ComponentConstants.COMPONENT_FACTORY, this.getComponentMetadata().getFactoryIdentifier() );
+ props.put( ComponentConstants.COMPONENT_NAME, getComponentMetadata().getName() );
+ props.put( ComponentConstants.COMPONENT_FACTORY, getComponentMetadata().getFactoryIdentifier() );
// also register with the factory PID
- props.put( Constants.SERVICE_PID, this.getComponentMetadata().getName() );
+ props.put( Constants.SERVICE_PID, getComponentMetadata().getName() );
return props;
}
@@ -139,7 +142,7 @@
if ( cm == null )
{
// create a new instance with the current configuration
- cm = this.createComponentManager( configuration );
+ cm = createComponentManager( configuration );
// keep a reference for future updates
m_configuredServices.put( pid, cm );
@@ -165,7 +168,7 @@
ComponentManager cm = ( ComponentManager ) m_configuredServices.remove( pid );
if ( cm != null )
{
- this.disposeComponentManager( cm );
+ disposeComponentManager( cm );
}
}
@@ -174,7 +177,7 @@
public String getName()
{
- return "Component Factory " + this.getComponentMetadata().getName();
+ return "Component Factory " + getComponentMetadata().getName();
}
@@ -188,13 +191,14 @@
private ComponentManager createComponentManager( Dictionary configuration )
{
long componentId = m_componentRegistry.createComponentId();
- ComponentManager cm = ManagerFactory.createManager( this.getActivator(), this.getComponentMetadata(), componentId );
+ ComponentManager cm = ManagerFactory.createManager( getActivator(), getComponentMetadata(),
+ componentId );
// add the new component to the activators instances
- this.getActivator().getInstanceReferences().add( cm );
+ getActivator().getInstanceReferences().add( cm );
// register with the internal set of created components
- m_createdComponents.put(cm, cm);
+ m_createdComponents.put( cm, cm );
// inject configuration if possible
if ( cm instanceof ImmediateComponentManager )
@@ -208,12 +212,14 @@
return cm;
}
- private void disposeComponentManager(ComponentManager cm) {
+
+ private void disposeComponentManager( ComponentManager cm )
+ {
// remove from created components
m_createdComponents.remove( cm );
// remove from activators list
- this.getActivator().getInstanceReferences().remove( cm );
+ getActivator().getInstanceReferences().remove( cm );
// finally dispose it
cm.dispose();
diff --git a/scr/src/main/java/org/apache/felix/scr/DelayedComponentManager.java b/scr/src/main/java/org/apache/felix/scr/DelayedComponentManager.java
index b305729..c4c3ad9 100644
--- a/scr/src/main/java/org/apache/felix/scr/DelayedComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/DelayedComponentManager.java
@@ -18,15 +18,17 @@
*/
package org.apache.felix.scr;
+
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
+
/**
* The <code>DelayedComponentManager</code> TODO
*
* @author fmeschbe
- * @version $Rev: 538123 $, $Date$
+ * @version $Rev$, $Date$
*/
public class DelayedComponentManager extends ImmediateComponentManager implements ServiceFactory
{
@@ -41,48 +43,56 @@
super( activator, metadata, componentId );
}
- protected void createComponent()
+
+ protected boolean createComponent()
{
// nothing to do here for a delayed component, will be done in the
// getService method for the first bundle acquiring the component
+ return true;
}
+
protected void deleteComponent()
{
// only have to delete, if there is actually an instance
- if (this.getInstance() != null) {
+ if ( getInstance() != null )
+ {
super.deleteComponent();
}
}
+
protected Object getService()
{
return this;
}
+
//---------- ServiceFactory interface -------------------------------------
public Object getService( Bundle arg0, ServiceRegistration arg1 )
{
- Activator.trace("DelayedComponentServiceFactory.getService()", this.getComponentMetadata());
+ Activator.trace( "DelayedComponentServiceFactory.getService()", getComponentMetadata() );
// When the getServiceMethod is called, the implementation object must be created
// unless another bundle has already retrievd it
- if (this.getInstance() == null) {
+ 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
- if (this.getState() == STATE_REGISTERED)
+ if ( getState() == STATE_REGISTERED )
{
- this.setState( STATE_ACTIVE );
+ setState( STATE_ACTIVE );
}
}
- return this.getInstance();
+ return getInstance();
}
+
public void ungetService( Bundle arg0, ServiceRegistration arg1, Object arg2 )
{
// nothing to do here
diff --git a/scr/src/main/java/org/apache/felix/scr/ImmediateComponentManager.java b/scr/src/main/java/org/apache/felix/scr/ImmediateComponentManager.java
index 1c5e563..14decb8 100644
--- a/scr/src/main/java/org/apache/felix/scr/ImmediateComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/ImmediateComponentManager.java
@@ -18,6 +18,7 @@
*/
package org.apache.felix.scr;
+
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -52,15 +53,16 @@
// the component properties, also used as service properties
private Dictionary m_properties;
+
/**
* The constructor receives both the activator and the metadata
*
* @param activator
* @param metadata
*/
- ImmediateComponentManager(BundleComponentActivator activator, ComponentMetadata metadata, long componentId)
+ ImmediateComponentManager( BundleComponentActivator activator, ComponentMetadata metadata, long componentId )
{
- super(activator, metadata);
+ super( activator, metadata );
m_componentId = componentId;
}
@@ -72,21 +74,27 @@
// 4. Call the activate method, if present
// if this method is overwritten, the deleteComponent method should
// also be overwritten
- protected void createComponent()
+ protected boolean createComponent()
{
ComponentContext tmpContext = new ComponentContextImpl( this );
- Object tmpComponent = this.createImplementationObject( tmpContext );
+ Object tmpComponent = createImplementationObject( tmpContext );
- // if something failed craeating the object, we fell back to
- // unsatisfied !!
- if (tmpComponent != null) {
- m_componentContext = tmpContext;
- m_implementationObject = tmpComponent;
+ // if something failed creating the component instance, return false
+ if ( tmpComponent == null )
+ {
+ return false;
}
+
+ // otherwise set the context and component instance and return true
+ m_componentContext = tmpContext;
+ m_implementationObject = tmpComponent;
+ return true;
}
- protected void deleteComponent() {
- this.disposeImplementationObject( m_implementationObject, m_componentContext );
+
+ protected void deleteComponent()
+ {
+ disposeImplementationObject( m_implementationObject, m_componentContext );
m_implementationObject = null;
m_componentContext = null;
m_properties = null;
@@ -100,11 +108,14 @@
*
* @return the object that implements the services
*/
- public Object getInstance() {
+ public Object getInstance()
+ {
return m_implementationObject;
}
- protected Object createImplementationObject(ComponentContext componentContext) {
+
+ protected Object createImplementationObject( ComponentContext componentContext )
+ {
Object implementationObject;
// 1. Load the component implementation class
@@ -113,23 +124,22 @@
try
{
// 112.4.4 The class is retrieved with the loadClass method of the component's bundle
- Class c = this.getActivator().getBundleContext().getBundle().loadClass(this.getComponentMetadata().getImplementationClassName());
+ Class c = getActivator().getBundleContext().getBundle().loadClass(
+ getComponentMetadata().getImplementationClassName() );
// 112.4.4 The class must be public and have a public constructor without arguments so component instances
// may be created by the SCR with the newInstance method on Class
implementationObject = c.newInstance();
}
- catch (Exception ex)
+ catch ( Exception ex )
{
- // failed to instantiate, deactivate the component and return null
- Activator.exception( "Error during instantiation of the implementation object", this.getComponentMetadata(), ex );
- this.deactivate();
+ // failed to instantiate, return null
+ Activator.exception( "Error during instantiation of the implementation object", getComponentMetadata(), ex );
return null;
}
-
// 3. Bind the target services
- Iterator it = this.getDependencyManagers();
+ Iterator it = getDependencyManagers();
while ( it.hasNext() )
{
// if a dependency turned unresolved since the validation check,
@@ -139,8 +149,16 @@
if ( !dm.bind( implementationObject ) )
{
Activator.error( "Cannot create component instance due to failure to bind reference " + dm.getName(),
- this.getComponentMetadata() );
- this.deactivate();
+ getComponentMetadata() );
+
+ // make sure, we keep no bindings
+ it = getDependencyManagers();
+ while ( it.hasNext() )
+ {
+ dm = ( DependencyManager ) it.next();
+ dm.unbind( implementationObject );
+ }
+
return null;
}
}
@@ -157,23 +175,34 @@
catch ( NoSuchMethodException ex )
{
// We can safely ignore this one
- Activator.trace( "activate() method is not implemented", this.getComponentMetadata() );
+ Activator.trace( "activate() method is not implemented", getComponentMetadata() );
}
catch ( IllegalAccessException ex )
{
// Ignored, but should it be logged?
- Activator.trace( "activate() method cannot be called", this.getComponentMetadata() );
+ Activator.trace( "activate() method cannot be called", getComponentMetadata() );
}
catch ( InvocationTargetException ex )
{
// 112.5.8 If the activate method throws an exception, SCR must log an error message
- // containing the exception with the Log Service
- Activator.exception( "The activate method has thrown an exception", this.getComponentMetadata(), ex );
+ // containing the exception with the Log Service and activation fails
+ Activator.exception( "The activate method has thrown an exception", getComponentMetadata(), ex );
+
+ // make sure, we keep no bindings
+ it = getDependencyManagers();
+ while ( it.hasNext() )
+ {
+ DependencyManager dm = ( DependencyManager ) it.next();
+ dm.unbind( implementationObject );
+ }
+
+ return null;
}
return implementationObject;
}
+
protected void disposeImplementationObject( Object implementationObject, ComponentContext componentContext )
{
// 1. Call the deactivate method, if present
@@ -188,22 +217,22 @@
catch ( NoSuchMethodException ex )
{
// We can safely ignore this one
- Activator.trace( "deactivate() method is not implemented", this.getComponentMetadata() );
+ Activator.trace( "deactivate() method is not implemented", getComponentMetadata() );
}
catch ( IllegalAccessException ex )
{
// Ignored, but should it be logged?
- Activator.trace( "deactivate() method cannot be called", this.getComponentMetadata() );
+ Activator.trace( "deactivate() method cannot be called", getComponentMetadata() );
}
catch ( InvocationTargetException ex )
{
// 112.5.12 If the deactivate method throws an exception, SCR must log an error message
// containing the exception with the Log Service and continue
- Activator.exception( "The deactivate method has thrown an exception", this.getComponentMetadata(), ex );
+ Activator.exception( "The deactivate method has thrown an exception", getComponentMetadata(), ex );
}
// 2. Unbind any bound services
- Iterator it = this.getDependencyManagers();
+ Iterator it = getDependencyManagers();
while ( it.hasNext() )
{
@@ -215,6 +244,7 @@
// nothing to do, we keep no references on per-Bundle services
}
+
/**
* Returns the service object to be registered if the service element is
* specified.
@@ -223,14 +253,18 @@
* ServiceFactory to register in the case of a delayed or a service
* factory component.
*/
- protected Object getService() {
+ protected Object getService()
+ {
return m_implementationObject;
}
- protected void setFactoryProperties(Dictionary dictionary) {
- m_factoryProperties = this.copyTo( null, dictionary );
+
+ protected void setFactoryProperties( Dictionary dictionary )
+ {
+ m_factoryProperties = copyTo( null, dictionary );
}
+
/**
* Returns the (private copy) of the Component properties to be used
* for the ComponentContext as well as eventual service registration.
@@ -249,30 +283,31 @@
{
// 1. the properties from the component descriptor
- Dictionary props = this.copyTo( null, this.getComponentMetadata().getProperties() );
+ Dictionary props = copyTo( null, getComponentMetadata().getProperties() );
// 2. overlay with Configuration Admin properties
- ConfigurationAdmin ca = this.getActivator().getConfigurationAdmin();
+ ConfigurationAdmin ca = getActivator().getConfigurationAdmin();
if ( ca != null )
{
try
{
- Configuration cfg = ca.getConfiguration( this.getComponentMetadata().getName() );
- if (cfg != null) {
- this.copyTo( props, cfg.getProperties() );
+ Configuration cfg = ca.getConfiguration( getComponentMetadata().getName() );
+ if ( cfg != null )
+ {
+ copyTo( props, cfg.getProperties() );
}
}
catch ( IOException ioe )
{
- Activator.exception( "Problem getting Configuration", this.getComponentMetadata(), ioe );
+ Activator.exception( "Problem getting Configuration", getComponentMetadata(), ioe );
}
}
// 3. copy any component factory properties, not supported yet
- this.copyTo( props, m_factoryProperties );
+ copyTo( props, m_factoryProperties );
// 4. set component.name and component.id
- props.put( ComponentConstants.COMPONENT_NAME, this.getComponentMetadata().getName() );
+ props.put( ComponentConstants.COMPONENT_NAME, getComponentMetadata().getName() );
props.put( ComponentConstants.COMPONENT_ID, new Long( m_componentId ) );
m_properties = props;
diff --git a/scr/src/main/java/org/apache/felix/scr/ServiceFactoryComponentManager.java b/scr/src/main/java/org/apache/felix/scr/ServiceFactoryComponentManager.java
index 6c9cba1..2d870a6 100644
--- a/scr/src/main/java/org/apache/felix/scr/ServiceFactoryComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/ServiceFactoryComponentManager.java
@@ -53,9 +53,10 @@
/* (non-Javadoc)
* @see org.apache.felix.scr.AbstractComponentManager#createComponent()
*/
- protected void createComponent()
+ protected boolean createComponent()
{
// nothing to do, this is handled by getService
+ return true;
}
@@ -98,17 +99,18 @@
Object service = createImplementationObject( serviceContext );
// register the components component context if successfull
- if (service != null) {
+ if ( service != null )
+ {
serviceContext.setImplementationObject( service );
serviceContexts.put( service, serviceContext );
// if this is the first use of this component, switch to ACTIVE state
- if (getState() == STATE_REGISTERED)
+ if ( getState() == STATE_REGISTERED )
{
setState( STATE_ACTIVE );
}
}
-
+
return service;
}
@@ -124,7 +126,7 @@
// private ComponentContext and implementation instances
ComponentContext serviceContext = ( ComponentContext ) serviceContexts.remove( service );
disposeImplementationObject( service, serviceContext );
-
+
// if this was the last use of the component, go back to REGISTERED state
if ( serviceContexts.isEmpty() && getState() == STATE_ACTIVE )
{
@@ -132,39 +134,47 @@
}
}
- private static class BundleComponentContext extends ComponentContextImpl implements ComponentInstance {
-
+ private static class BundleComponentContext extends ComponentContextImpl implements ComponentInstance
+ {
+
private Bundle m_usingBundle;
private Object m_implementationObject;
- BundleComponentContext(AbstractComponentManager componentManager, Bundle usingBundle) {
- super(componentManager);
-
+
+ BundleComponentContext( AbstractComponentManager componentManager, Bundle usingBundle )
+ {
+ super( componentManager );
+
m_usingBundle = usingBundle;
}
-
+
+
private void setImplementationObject( Object implementationObject )
{
m_implementationObject = implementationObject;
}
-
+
+
public Bundle getUsingBundle()
{
return m_usingBundle;
}
-
+
+
public ComponentInstance getComponentInstance()
{
return this;
}
-
+
+
//---------- ComponentInstance interface ------------------------------
-
+
public Object getInstance()
{
return m_implementationObject;
}
-
+
+
public void dispose()
{
getComponentManager().dispose();