felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fmesc...@apache.org
Subject svn commit: r830886 - in /felix/trunk/scr: ./ src/main/java/org/apache/felix/scr/ src/main/java/org/apache/felix/scr/impl/ src/main/java/org/apache/felix/scr/impl/manager/
Date Thu, 29 Oct 2009 10:47:13 GMT
Author: fmeschbe
Date: Thu Oct 29 10:47:12 2009
New Revision: 830886

URL: http://svn.apache.org/viewvc?rev=830886&view=rev
Log:
FELIX-1658 Removing Enabled state (folded into Unsatisfied state) and
introduced transient states to be able to remove synchronization on the
internal state changing methods. The transient states just prevent any
further state changes while the actual state is taking place.
Also set the exported package version to 1.2 explicitly.

Modified:
    felix/trunk/scr/pom.xml
    felix/trunk/scr/src/main/java/org/apache/felix/scr/Component.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentActivatorTask.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java

Modified: felix/trunk/scr/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/scr/pom.xml?rev=830886&r1=830885&r2=830886&view=diff
==============================================================================
--- felix/trunk/scr/pom.xml (original)
+++ felix/trunk/scr/pom.xml Thu Oct 29 10:47:12 2009
@@ -157,7 +157,7 @@
                             org.apache.felix.scr.impl.Activator
                         </Bundle-Activator>
                         <Export-Package>
-                            org.apache.felix.scr;version=${pom.version},
+                            org.apache.felix.scr;version=1.2,
                             org.osgi.service.component
                         </Export-Package>
                         <Private-Package>

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/Component.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/Component.java?rev=830886&r1=830885&r2=830886&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/Component.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/Component.java Thu Oct 29 10:47:12 2009
@@ -40,8 +40,18 @@
     static final int STATE_DISABLED = 1;
 
     /**
+     * The Component is being enabled (value is 512). After the component has
+     * been enabled it enters the {@link #STATE_UNSATISFIED} state.
+     * @since 1.2
+     */
+    static final int STATE_ENABLING = 512;
+
+    /**
      * The Component has been enabled and is now going to be activated (value
      * is 2).
+     * @deprecated as of version 1.2 the enabled state is collapsed into the
+     *      {@link #STATE_UNSATISFIED} state. This status code is never returned
+     *      from the {@link #getState()} method.
      */
     static final int STATE_ENABLED = 2;
 
@@ -88,12 +98,38 @@
     static final int STATE_DEACTIVATING = 128;
 
     /**
+     * The Component is being disabled (value is 1024). After the component has
+     * been disabled it enters the {@link #STATE_DISABLED} state.
+     * @since 1.2
+     */
+    static final int STATE_DISABLING = 1024;
+
+    /**
+     * The Component is being disposed off (value is 2048). After the component
+     * has been disposed off it enters the {@link #STATE_DESTROYED} state.
+     * @since 1.2
+     */
+    static final int STATE_DISPOSING = 2048;
+
+    /**
      * The Component has been destroyed and cannot be used any more (value is
      * 256). This state is only used when the bundle declaring the component
      * is being stopped and all components have to be removed.
+     * @deprecated as of version 1.2 this constant has been renamed to
+     *      {@link #STATE_DISPOSED}.
      */
     static final int STATE_DESTROYED = 256;
 
+    /**
+     * The Component has been disposed off and cannot be used any more (value is
+     * 256). This state is used when the bundle declaring the component
+     * is being stopped and all components have to be removed. This status is
+     * also the final status of a component after the
+     * <code>ComponentInstance.dispose()</code> method has been called.
+     * @since 1.2
+     */
+    static final int STATE_DISPOSED = 256;
+
 
     /**
      * Returns the component ID of this component. This ID is managed by the

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentActivatorTask.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentActivatorTask.java?rev=830886&r1=830885&r2=830886&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentActivatorTask.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentActivatorTask.java Thu Oct 29 10:47:12 2009
@@ -50,12 +50,12 @@
     public void run()
     {
         // fail, if the bundle is not active
-        if ( component.getState() == Component.STATE_DESTROYED )
+        if ( component.getState() == Component.STATE_DISPOSED )
         {
             // cannot use bundle to log because it is not accessible from the
             // component if the component is destroyed
             Activator.log( LogService.LOG_WARNING, null, "Cannot run task '" + this
-                + "': Component has already been destroyed", null );
+                + "': Component has already been disposed", null );
         }
         else if ( !ComponentRegistry.isBundleActive( component.getBundle() ) )
         {

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java?rev=830886&r1=830885&r2=830886&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ScrCommand.java Thu Oct 29 10:47:12 2009
@@ -308,9 +308,9 @@
             return;
         }
 
-        if ( component.getState() == Component.STATE_DESTROYED )
+        if ( component.getState() == Component.STATE_DISPOSED )
         {
-            err.println( "Component " + component.getName() + " already destroyed, cannot change state" );
+            err.println( "Component " + component.getName() + " already disposed, cannot change state" );
         }
         else if ( enable )
         {
@@ -420,6 +420,8 @@
         {
             case Component.STATE_DISABLED:
                 return "disabled";
+            case Component.STATE_ENABLING:
+                return "enabling";
             case Component.STATE_ENABLED:
                 return "enabled";
             case Component.STATE_UNSATISFIED:
@@ -434,8 +436,12 @@
                 return "factory";
             case Component.STATE_DEACTIVATING:
                 return "deactivating";
-            case Component.STATE_DESTROYED:
-                return "destroyed";
+            case Component.STATE_DISABLING:
+                return "disabling";
+            case Component.STATE_DISPOSING:
+                return "disposing";
+            case Component.STATE_DISPOSED:
+                return "disposed";
             default:
                 return String.valueOf( state );
         }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java?rev=830886&r1=830885&r2=830886&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java Thu Oct 29 10:47:12 2009
@@ -19,6 +19,7 @@
 package org.apache.felix.scr.impl.manager;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.Hashtable;
@@ -65,998 +66,1084 @@
     // The ServiceRegistration
     private volatile ServiceRegistration m_serviceRegistration;
 
+
     /**
-     * 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>
+     * The constructor receives both the activator and the metadata
+     *
+     * @param activator
+     * @param metadata
      */
-    protected static abstract class State
+    protected AbstractComponentManager( BundleComponentActivator activator, ComponentMetadata metadata )
     {
-        private final String m_name;
-        private final int m_state;
+        m_activator = activator;
+        m_componentMetadata = metadata;
 
-        protected State( String name, int state )
-        {
-            m_name = name;
-            m_state = state;
-        }
+        // for some testing, the activator may be null
+        m_componentId = ( activator != null ) ? activator.registerComponentId( this ) : -1;
 
-        public String toString()
-        {
-            return m_name;
-        }
+        m_state = Disabled.getInstance();
+        loadDependencyManagers( metadata );
 
-        int getState()
+        // dump component details
+        if ( isLogEnabled( LogService.LOG_DEBUG ) )
         {
-            return m_state;
-        }
+            log(
+                LogService.LOG_DEBUG,
+                "Component {0} created: DS={1}, implementation={2}, immediate={3}, default-enabled={4}, factory={5}, configuration-policy={6}, activate={7}, deactivate={8}, modified={9}",
+                new Object[]
+                    { metadata.getName(), new Integer( metadata.getNamespaceCode() ),
+                        metadata.getImplementationClassName(), Boolean.valueOf( metadata.isImmediate() ),
+                        Boolean.valueOf( metadata.isEnabled() ), metadata.getFactoryIdentifier(),
+                        metadata.getConfigurationPolicy(), metadata.getActivate(), metadata.getDeactivate(),
+                        metadata.getModified() }, null );
 
-        ServiceReference getServiceReference( AbstractComponentManager acm )
-        {
-            return null;
-        }
+            if ( metadata.getServiceMetadata() != null )
+            {
+                log( LogService.LOG_DEBUG, "Component {0} Services: servicefactory={1}, services={2}", new Object[]
+                    { metadata.getName(), Boolean.valueOf( metadata.getServiceMetadata().isServiceFactory() ),
+                        Arrays.asList( metadata.getServiceMetadata().getProvides() ) }, null );
+            }
 
-        void enableInternal( AbstractComponentManager acm )
-        {
-            acm.log( LogService.LOG_DEBUG,
-                    "Current state: " + m_name + ", Event: enable",
-                    null );
+            if ( metadata.getProperties() != null )
+            {
+                log( LogService.LOG_DEBUG, "Component {0} Properties: {1}", new Object[]
+                    { metadata.getName(), metadata.getProperties() }, null );
+            }
         }
+    }
 
-        void disableInternal( AbstractComponentManager acm )
-        {
-            acm.log( LogService.LOG_DEBUG,
-                    "Current state: " + m_name + ", Event: disable",
-                    null );
-        }
 
-        void activateInternal( AbstractComponentManager acm )
-        {
-            acm.log(LogService.LOG_DEBUG,
-                    "Current state: " + m_name + ", Event: activate",
-                    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
+     * disabled.
+     * <p>
+     * This method ignores the <i>enabled</i> flag of the component metadata
+     * and just enables as requested.
+     * <p>
+     * This method schedules the enablement for asynchronous execution.
+     */
+    public final void enable()
+    {
+        enableInternal();
 
-        void deactivateInternal( AbstractComponentManager acm, int reason )
+        getActivator().schedule( new ComponentActivatorTask( "Enable", this )
         {
-            acm.log( LogService.LOG_DEBUG, "Current state: " + m_name + ", Event: deactivate (reason: " + reason + ")",
-                null );
-        }
+            public void doRun()
+            {
+                activateInternal();
+            }
+        });
+    }
 
-        void disposeInternal( AbstractComponentManager acm )
+    /**
+     * 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()
+    {
+        getActivator().schedule( new ComponentActivatorTask( "Disable", this )
         {
-            acm.log( LogService.LOG_DEBUG,
-                    "Current state: " + m_name + ", Event: dispose",
-                    null );
-        }
+            public void doRun()
+            {
+                deactivateInternal( ComponentConstants.DEACTIVATION_REASON_DISABLED );
+                disableInternal();
+            }
+        });
+    }
 
-        Object getService( DelayedComponentManager dcm )
-        {
-            dcm.log( LogService.LOG_DEBUG,
-                    "Current state: " + m_name + ", Event: getService",
-                    null );
-            return null;
-        }
+    /**
+     * Get the object that is implementing this descriptor
+     *
+     * @return the object that implements the services
+     */
+    abstract Object getInstance();
+
+    // supports the ComponentInstance.dispose() method
+    void dispose()
+    {
+        dispose( ComponentConstants.DEACTIVATION_REASON_DISPOSED );
     }
 
-    protected static final class Destroyed extends State
+    /**
+     * 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.
+     */
+    public void dispose( int reason )
     {
-        private static final Destroyed m_inst = new Destroyed();
+        disposeInternal( reason );
+    }
 
-        private Destroyed()
-        {
-            super( "Destroyed", STATE_DESTROYED );
-        }
+    //---------- Component interface ------------------------------------------
 
-        static State getInstance()
-        {
-            return m_inst;
-        }
+    public long getId()
+    {
+        return m_componentId;
     }
 
-    protected static final class Disabled extends State
+    public String getName() {
+        return m_componentMetadata.getName();
+    }
+
+    public Bundle getBundle()
     {
-        private static final Disabled m_inst = new Disabled();
+        return getActivator().getBundleContext().getBundle();
+    }
 
-        private Disabled()
-        {
-            super( "Disabled", STATE_DISABLED );
-        }
+    public String getClassName()
+    {
+        return m_componentMetadata.getImplementationClassName();
+    }
 
-        static State getInstance()
+    public String getFactory()
+    {
+        return m_componentMetadata.getFactoryIdentifier();
+    }
+
+    public Reference[] getReferences()
+    {
+        if ( m_dependencyManagers != null && m_dependencyManagers.size() > 0 )
         {
-            return m_inst;
+            return (Reference[]) m_dependencyManagers.toArray(
+                    new Reference[m_dependencyManagers.size()] );
         }
 
-        void enableInternal( AbstractComponentManager acm )
-        {
-            acm.changeState( Enabled.getInstance() );
+        return null;
+    }
 
-            acm.log( LogService.LOG_DEBUG, "Component enabled", null );
-        }
+    public boolean isImmediate()
+    {
+        return m_componentMetadata.isImmediate();
 
-        void disposeInternal( AbstractComponentManager acm )
-        {
-            acm.clear();
-            acm.changeState( Destroyed.getInstance() );
-        }
     }
 
-    protected static final class Enabled extends State
+    public boolean isDefaultEnabled()
     {
-        private static final Enabled m_inst = new Enabled();
+        return m_componentMetadata.isEnabled();
+    }
 
-        private Enabled()
-        {
-            super( "Enabled", STATE_ENABLED );
-        }
 
-        static State getInstance()
-        {
-            return m_inst;
-        }
+    public String getActivate()
+    {
+        return m_componentMetadata.getActivate();
+    }
 
-        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", e );
-                acm.disposeDependencyManagers();
-                acm.loadDependencyManagers( acm.getComponentMetadata() );
-            }
-        }
+    public boolean isActivateDeclared()
+    {
+        return m_componentMetadata.isActivateDeclared();
+    }
 
-        void disableInternal( AbstractComponentManager acm )
-        {
-            acm.changeState( Disabled.getInstance() );
 
-            acm.log( LogService.LOG_DEBUG, "Component disabled", null );
-        }
+    public String getDeactivate()
+    {
+        return m_componentMetadata.getDeactivate();
+    }
 
-        void disposeInternal( AbstractComponentManager acm )
-        {
-            acm.clear();
-            acm.changeState( Destroyed.getInstance() );
 
-            acm.log( LogService.LOG_DEBUG, "Component disposed", null );
-        }
+    public boolean isDeactivateDeclared()
+    {
+        return m_componentMetadata.isDeactivateDeclared();
     }
 
-    protected static final class Unsatisfied extends State
+
+    public String getModified()
     {
-        private static final Unsatisfied m_inst = new Unsatisfied();
+        return m_componentMetadata.getModified();
+    }
 
-        private Unsatisfied()
-        {
-            super( "Unsatisfied", STATE_UNSATISFIED );
-        }
 
-        static State getInstance()
+    public String getConfigurationPolicy()
+    {
+        return m_componentMetadata.getConfigurationPolicy();
+    }
+
+
+    public boolean isServiceFactory()
+    {
+        return m_componentMetadata.getServiceMetadata() != null
+                && m_componentMetadata.getServiceMetadata().isServiceFactory();
+    }
+
+    public String[] getServices()
+    {
+        if ( m_componentMetadata.getServiceMetadata() != null )
         {
-            return m_inst;
+            return m_componentMetadata.getServiceMetadata().getProvides();
         }
 
-        void activateInternal( AbstractComponentManager acm )
-        {
-            acm.changeState( Activating.getInstance() );
+        return null;
+    }
 
-            ComponentMetadata componentMetadata = acm.getComponentMetadata();
-            acm.log( LogService.LOG_DEBUG, "Activating component", null );
+    //-------------- atomic transition methods -------------------------------
 
-            // Before creating the implementation object, we are going to
-            // test if we have configuration if such is required
-            if ( !acm.hasConfiguration() && acm.getComponentMetadata().isConfigurationRequired() )
-            {
-                acm.log( LogService.LOG_INFO, "Missing required configuration, cannot activate", null );
-                acm.changeState( Unsatisfied.getInstance() );
-                return;
-            }
+    final void enableInternal()
+    {
+        m_state.enable( this );
+    }
 
-            // 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", null );
-                acm.changeState( Unsatisfied.getInstance() );
-                return;
-            }
+    final void activateInternal()
+    {
+        m_state.activate( this );
+    }
 
-            // 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",
-                        null );
+    final void deactivateInternal( int reason )
+    {
+        m_state.deactivate( this, reason );
+    }
 
-                // set state to unsatisfied
-                acm.changeState( Unsatisfied.getInstance() );
-                return;
-            }
+    final void disableInternal()
+    {
+        m_state.disable( this );
+    }
 
-            acm.changeState( acm.getSatisfiedState() );
+    /**
+     * 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.
+     */
+    final void disposeInternal( int reason )
+    {
+        m_state.deactivate( this, reason );
+        m_state.disable( this );
+        m_state.dispose( this );
+    }
 
-            acm.registerComponentService();
-        }
 
-        void disableInternal( AbstractComponentManager acm )
+    final ServiceReference getServiceReference()
+    {
+        // This method is not synchronized even though it accesses the state.
+        // The reason for this is that we just want to have the state return
+        // the service reference which comes from the service registration.
+        // The only thing that may happen is that the service registration is
+        // still set on this instance but the service has already been
+        // unregistered. In this case an IllegalStateException may be thrown
+        // which we just catch and ignore returning null
+        State state = m_state;
+        try
         {
-            ComponentMetadata componentMetadata = acm.getComponentMetadata();
-            acm.log( LogService.LOG_DEBUG, "Disabling component", null );
+            return state.getServiceReference( this );
+        }
+        catch ( IllegalStateException ise )
+        {
+            // may be thrown if the service has already been unregistered but
+            // the service registration is still set on this component manager
+            // we ignore this exception and assume there is no service reference
+        }
 
-            // dispose and recreate dependency managers
-            acm.disposeDependencyManagers();
-            acm.loadDependencyManagers( componentMetadata );
+        return null;
+    }
 
-            // we are now disabled, ready for re-enablement or complete destroyal
-            acm.changeState( Disabled.getInstance() );
+    //---------- 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.
+     */
+    protected abstract boolean createComponent();
 
-            acm.log( LogService.LOG_DEBUG, "Component disabled", null );
+    protected abstract void deleteComponent( int reason );
+
+    /**
+     * 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.
+     *
+     * @return
+     */
+    protected abstract Object getService();
+
+
+    final State getSatisfiedState()
+    {
+        if ( m_componentMetadata.isFactory() )
+        {
+            return Factory.getInstance();
+        }
+        else if ( m_componentMetadata.isImmediate() )
+        {
+            return Active.getInstance();
+        }
+        else
+        {
+            return Registered.getInstance();
         }
+    }
+
 
-        void disposeInternal( AbstractComponentManager acm )
+    protected ServiceRegistration registerService()
+    {
+        if ( getComponentMetadata().getServiceMetadata() != null )
         {
-            acm.disposeDependencyManagers();
-            acm.clear();
-            acm.changeState( Destroyed.getInstance() );
+            log( LogService.LOG_DEBUG, "registering services", null );
 
-            acm.log( LogService.LOG_DEBUG, "Component disposed", null );
+            // get a copy of the component properties as service properties
+            final Dictionary serviceProperties = getServiceProperties();
+
+            return getActivator().getBundleContext().registerService(
+                    getComponentMetadata().getServiceMetadata().getProvides(),
+                    getService(), serviceProperties );
         }
+
+        return null;
     }
 
-    protected static final class Activating extends State
+    // 5. Register provided services
+    protected void registerComponentService()
     {
-        private static final Activating m_inst = new Activating();
+        m_serviceRegistration = registerService();
+    }
 
-        private Activating() {
-            super( "Activating", STATE_ACTIVATING );
-        }
+    protected final void unregisterComponentService()
+    {
 
-        static State getInstance()
+        if ( m_serviceRegistration != null )
         {
-            return m_inst;
+            log( LogService.LOG_DEBUG, "unregistering the services", null );
+
+            m_serviceRegistration.unregister();
+            m_serviceRegistration = null;
         }
     }
 
-    protected static final class Deactivating extends State
+    //**********************************************************************************************************
+    public BundleComponentActivator getActivator()
     {
-        private static final Deactivating m_inst = new Deactivating();
+        return m_activator;
+    }
 
-        private Deactivating() {
-            super( "Deactivating", STATE_DEACTIVATING );
-        }
+    final ServiceRegistration getServiceRegistration()
+    {
+        return m_serviceRegistration;
+    }
 
-        static State getInstance() {
-            return m_inst;
+
+    void clear()
+    {
+        // for some testing, the activator may be null
+        if ( m_activator != null )
+        {
+            m_activator.unregisterComponentId( this );
+            m_activator = null;
         }
+
+        m_dependencyManagers.clear();
     }
 
-    protected static abstract class Satisfied extends State
+
+    /**
+     * Returns <code>true</code> if logging for the given level is enabled.
+     */
+    public boolean isLogEnabled( int level )
     {
-        protected Satisfied( String name, int state )
+        BundleComponentActivator activator = getActivator();
+        if ( activator != null )
         {
-            super( name, state );
+            return activator.isLogEnabled( level );
         }
 
-        ServiceReference getServiceReference( AbstractComponentManager acm )
+        // bundle activator has already been removed, so no logging
+        return false;
+    }
+
+
+    public void log( int level, String message, Throwable ex )
+    {
+        BundleComponentActivator activator = getActivator();
+        if ( activator != null )
         {
-            ServiceRegistration sr = acm.getServiceRegistration();
-            return sr == null ? null : sr.getReference();
+            activator.log( level, message, getComponentMetadata(), ex );
         }
+    }
 
-        void deactivateInternal( AbstractComponentManager acm, int reason )
+    public void log( int level, String message, Object[] arguments, Throwable ex )
+    {
+        BundleComponentActivator activator = getActivator();
+        if ( activator != null )
         {
-            acm.changeState(Deactivating.getInstance());
-
-            ComponentMetadata componentMetadata = acm.getComponentMetadata();
-            acm.log( LogService.LOG_DEBUG, "Deactivating component", null );
+            activator.log( level, message, arguments, getComponentMetadata(), ex );
+        }
+    }
 
-            // catch any problems from deleting the component to prevent the
-            // component to remain in the deactivating state !
-            try
+    /**
+     * Activates this component if satisfied. If any of the dependencies is
+     * not met, the component is not activated and remains unsatisfied.
+     * <p>
+     * This method schedules the activation for asynchronous execution.
+     */
+    public final void activate()
+    {
+        getActivator().schedule( new ComponentActivatorTask( "Activate", this ) {
+            public void doRun()
             {
-                acm.unregisterComponentService();
-                acm.deleteComponent( reason );
+                activateInternal();
             }
-            catch ( Throwable t )
+        });
+    }
+
+    /**
+     * 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( final int reason )
+    {
+        getActivator().schedule( new ComponentActivatorTask( "Reactivate", this )
+        {
+
+            public void doRun()
             {
-                acm.log( LogService.LOG_WARNING, "Component deactivation threw an exception", t );
+                deactivateInternal( reason );
+                activateInternal();
             }
+        } );
+    }
 
-            acm.changeState( Unsatisfied.getInstance() );
-            acm.log( LogService.LOG_DEBUG, "Component deactivated", null );
-        }
+    public String toString() {
+        return "Component: " + getName() + " (" + getId() + ")";
     }
 
-    protected static final class Registered extends Satisfied
+    private void loadDependencyManagers( ComponentMetadata metadata )
     {
-        private static final Registered m_inst = new Registered();
-
-        private Registered() {
-            super( "Registered", STATE_REGISTERED );
-        }
+        List depMgrList = new ArrayList();
 
-        static State getInstance()
+        // If this component has got dependencies, create dependency managers for each one of them.
+        if ( metadata.getDependencies().size() != 0 )
         {
-            return m_inst;
-        }
+            Iterator dependencyit = metadata.getDependencies().iterator();
 
-        Object getService(DelayedComponentManager dcm)
-        {
-            if ( dcm.createRealComponent() )
+            while ( dependencyit.hasNext() )
             {
-                dcm.changeState( Active.getInstance() );
-                return dcm.getInstance();
+                ReferenceMetadata currentdependency = (ReferenceMetadata) dependencyit.next();
+
+                DependencyManager depmanager = new DependencyManager( this, currentdependency );
+
+                depMgrList.add( depmanager );
             }
+        }
 
-            super.deactivateInternal( dcm, ComponentConstants.DEACTIVATION_REASON_UNSPECIFIED );
-            return null;
+        m_dependencyManagers = depMgrList;
+    }
+
+    private void enableDependencyManagers() throws InvalidSyntaxException
+    {
+        Iterator it = getDependencyManagers();
+        while ( it.hasNext() )
+        {
+            DependencyManager dm = (DependencyManager) it.next();
+            dm.enable();
         }
     }
 
-    protected static final class Factory extends Satisfied
+    protected boolean verifyDependencyManagers( Dictionary properties )
     {
-        private static final Factory m_inst = new Factory();
+        // indicates whether all dependencies are satisfied
+        boolean satisfied = true;
 
-        private Factory()
+        Iterator it = getDependencyManagers();
+        while ( it.hasNext() )
         {
-            super( "Factory", STATE_FACTORY );
-        }
+            DependencyManager dm = (DependencyManager) it.next();
 
-        static State getInstance()
-        {
-            return m_inst;
+            // ensure the target filter is correctly set
+            dm.setTargetFilter( properties );
+
+            // check whether the service is satisfied
+            if ( !dm.isSatisfied() )
+            {
+                // at least one dependency is not satisfied
+                log( LogService.LOG_INFO, "Dependency not satisfied: " + dm.getName(), null );
+                satisfied = false;
+            }
         }
+
+        return satisfied;
     }
 
-    protected static final class Active extends Satisfied
+    Iterator getDependencyManagers()
     {
-        private static final Active m_inst = new Active();
+        return m_dependencyManagers.iterator();
+    }
 
-        private Active()
+    DependencyManager getDependencyManager(String name)
+    {
+        Iterator it = getDependencyManagers();
+        while ( it.hasNext() )
         {
-            super( "Active", STATE_ACTIVE );
+            DependencyManager dm = (DependencyManager) it.next();
+            if ( name.equals(dm.getName()) )
+            {
+                return dm;
+            }
         }
 
-        static State getInstance()
-        {
-            return m_inst;
-        }
+        // not found
+        return null;
+    }
 
-        Object getService( DelayedComponentManager dcm )
+    private void disableDependencyManagers()
+    {
+        Iterator it = getDependencyManagers();
+        while ( it.hasNext() )
         {
-            return dcm.getInstance();
+            DependencyManager dm = (DependencyManager) it.next();
+            dm.disable();
         }
     }
 
+    public abstract boolean hasConfiguration();
+
+    public abstract Dictionary getProperties();
+
     /**
-     * The constructor receives both the activator and the metadata
-     *
-     * @param activator
-     * @param metadata
+     * Returns the subset of component properties to be used as service
+     * properties. These properties are all component properties where property
+     * name does not start with dot (.), properties which are considered
+     * private.
      */
-    protected AbstractComponentManager( BundleComponentActivator activator, ComponentMetadata metadata )
+    public Dictionary getServiceProperties()
     {
-        m_activator = activator;
-        m_componentMetadata = metadata;
-
-        // for some testing, the activator may be null
-        m_componentId = ( activator != null ) ? activator.registerComponentId( this ) : -1;
-
-        m_state = Disabled.getInstance();
-        loadDependencyManagers( metadata );
-
-        log( LogService.LOG_DEBUG, "Component created", null );
+        return copyTo( null, getProperties(), false);
     }
 
-
-    //---------- 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
-     * disabled.
-     * <p>
-     * This method ignores the <i>enabled</i> flag of the component metadata
-     * and just enables as requested.
-     * <p>
-     * This method schedules the enablement for asynchronous execution.
+     * Copies the properties from the <code>source</code> <code>Dictionary</code>
+     * into the <code>target</code> <code>Dictionary</code>.
+     *
+     * @param target The <code>Dictionary</code> into which to copy the
+     *      properties. If <code>null</code> a new <code>Hashtable</code> is
+     *      created.
+     * @param source The <code>Dictionary</code> providing the properties to
+     *      copy. If <code>null</code> or empty, nothing is copied.
+     *
+     * @return The <code>target</code> is returned, which may be empty if
+     *      <code>source</code> is <code>null</code> or empty and
+     *      <code>target</code> was <code>null</code>.
      */
-    public final void enable()
+    protected static Dictionary copyTo( Dictionary target, Dictionary source )
     {
-        enableInternal();
-
-        getActivator().schedule( new ComponentActivatorTask( "Enable", this )
-        {
-            public void doRun()
-            {
-                activateInternal();
-            }
-        });
+        return copyTo( target, source, true );
     }
 
     /**
-     * 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.
+     * Copies the properties from the <code>source</code> <code>Dictionary</code>
+     * into the <code>target</code> <code>Dictionary</code> except for private
+     * properties (whose name has a leading dot) which are only copied if the
+     * <code>allProps</code> parameter is <code>true</code>.
+     *
+     * @param target    The <code>Dictionary</code> into which to copy the
+     *                  properties. If <code>null</code> a new <code>Hashtable</code> is
+     *                  created.
+     * @param source    The <code>Dictionary</code> providing the properties to
+     *                  copy. If <code>null</code> or empty, nothing is copied.
+     * @param allProps  Whether all properties (<code>true</code>) or only the
+     *                  public properties (<code>false</code>) are to be copied.
+     *
+     * @return The <code>target</code> is returned, which may be empty if
+     *         <code>source</code> is <code>null</code> or empty and
+     *         <code>target</code> was <code>null</code> or all properties are
+     *         private and had not to be copied
      */
-    public final void disable()
+    protected static Dictionary copyTo( Dictionary target, final Dictionary source, final boolean allProps )
     {
-        getActivator().schedule( new ComponentActivatorTask( "Disable", this )
+        if ( target == null )
         {
-            public void doRun()
+            target = new Hashtable();
+        }
+
+        if ( source != null && !source.isEmpty() )
+        {
+            for ( Enumeration ce = source.keys(); ce.hasMoreElements(); )
             {
-                deactivateInternal( ComponentConstants.DEACTIVATION_REASON_DISABLED );
-                disableInternal();
+                // cast is save, because key must be a string as per the spec
+                String key = ( String ) ce.nextElement();
+                if ( allProps || key.charAt( 0 ) != '.' )
+                {
+                    target.put( key, source.get( key ) );
+                }
             }
-        });
+        }
+
+        return target;
     }
 
+
     /**
-     * Get the object that is implementing this descriptor
      *
-     * @return the object that implements the services
      */
-    abstract Object getInstance();
-
-    // supports the ComponentInstance.dispose() method
-    void dispose()
+    public ComponentMetadata getComponentMetadata()
     {
-        dispose( ComponentConstants.DEACTIVATION_REASON_DISPOSED );
+        return m_componentMetadata;
     }
 
-    /**
-     * 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.
-     */
-    public void dispose( int reason )
+    public int getState()
     {
-        disposeInternal( reason );
+        return m_state.getState();
     }
 
-    //---------- Component interface ------------------------------------------
-    public long getId()
+    protected State state()
     {
-        return m_componentId;
-    }
-
-    public String getName() {
-        return m_componentMetadata.getName();
+        return m_state;
     }
 
-    public Bundle getBundle()
+    /**
+     * sets the state of the manager
+     */
+    void changeState( State newState )
     {
-        return getActivator().getBundleContext().getBundle();
+        log( LogService.LOG_DEBUG, "State transition : " + m_state + " -> " + newState, null );
+        m_state = newState;
     }
 
-    public String getClassName()
-    {
-        return m_componentMetadata.getImplementationClassName();
-    }
+    //--------- State classes
 
-    public String getFactory()
+    /**
+     * There are 12 states in all. They are: Disabled, Unsatisfied,
+     * Registered, Factory, Active, Disposed, as well as the transient states
+     * Enabling, Activating, Deactivating, Disabling, and Disposing.
+     * The Registered, Factory and Active states are the "Satisfied" state in
+     * concept. The tansient states will be changed to other states
+     * automatically when work is done.
+     * <p>
+     * The transition cases are listed below.
+     * <ul>
+     * <li>Disabled -(enable/ENABLING) -> Unsatisifed</li>
+     * <li>Disabled -(dispose/DISPOSING)-> Disposed</li>
+     * <li>Unsatisfied -(activate/ACTIVATING, SUCCESS) -> Satisfied(Registered, Factory or Active)</li>
+     * <li>Unsatisfied -(activate/ACTIVATING, FAIL) -> Unsatisfied</li>
+     * <li>Unsatisfied -(disable/DISABLING) -> Disabled</li>
+     * <li>Registered -(getService, SUCCESS) -> Active</li>
+     * <li>Registered -(getService, FAIL) -> Unsatisfied</li>
+     * <li>Satisfied -(deactivate/DEACTIVATING)-> Unsatisfied</li>
+     * </ul>
+     */
+    protected static abstract class State
     {
-        return m_componentMetadata.getFactoryIdentifier();
-    }
+        private final String m_name;
+        private final int m_state;
 
-    public Reference[] getReferences()
-    {
-        if ( m_dependencyManagers != null && m_dependencyManagers.size() > 0 )
+
+        protected State( String name, int state )
         {
-            return (Reference[]) m_dependencyManagers.toArray(
-                    new Reference[m_dependencyManagers.size()] );
+            m_name = name;
+            m_state = state;
+        }
+
+
+        public String toString()
+        {
+            return m_name;
+        }
+
+
+        int getState()
+        {
+            return m_state;
+        }
+
+
+        ServiceReference getServiceReference( AbstractComponentManager acm )
+        {
+            return null;
+        }
+
+
+        Object getService( DelayedComponentManager dcm )
+        {
+            log( dcm, "getService" );
+            return null;
+        }
+
+
+        void enable( AbstractComponentManager acm )
+        {
+            log( acm, "enable" );
+        }
+
+
+        void activate( AbstractComponentManager acm )
+        {
+            log( acm, "activate" );
         }
 
-        return null;
-    }
 
-    public boolean isImmediate()
-    {
-        return m_componentMetadata.isImmediate();
+        void deactivate( AbstractComponentManager acm, int reason )
+        {
+            log( acm, "deactivate (reason: " + reason + ")" );
+        }
 
-    }
 
-    public boolean isDefaultEnabled()
-    {
-        return m_componentMetadata.isEnabled();
-    }
+        void disable( AbstractComponentManager acm )
+        {
+            log( acm, "disable" );
+        }
 
 
-    public String getActivate()
-    {
-        return m_componentMetadata.getActivate();
-    }
+        void dispose( AbstractComponentManager acm )
+        {
+            log( acm, "dispose" );
+        }
 
 
-    public boolean isActivateDeclared()
-    {
-        return m_componentMetadata.isActivateDeclared();
+        private void log( AbstractComponentManager acm, String event )
+        {
+            acm.log( LogService.LOG_DEBUG, "Current state: {0}, Event: {1}", new Object[]
+                { m_name, event }, null );
+        }
     }
 
-
-    public String getDeactivate()
+    protected static final class Disabled extends State
     {
-        return m_componentMetadata.getDeactivate();
-    }
+        private static final Disabled m_inst = new Disabled();
 
 
-    public boolean isDeactivateDeclared()
-    {
-        return m_componentMetadata.isDeactivateDeclared();
-    }
+        private Disabled()
+        {
+            super( "Disabled", STATE_DISABLED );
+        }
 
 
-    public String getModified()
-    {
-        return m_componentMetadata.getModified();
-    }
+        static State getInstance()
+        {
+            return m_inst;
+        }
 
 
-    public String getConfigurationPolicy()
-    {
-        return m_componentMetadata.getConfigurationPolicy();
-    }
+        void enable( AbstractComponentManager acm )
+        {
+            acm.changeState( Enabling.getInstance() );
 
+            try
+            {
+                acm.enableDependencyManagers();
+                acm.changeState( Unsatisfied.getInstance() );
+                acm.log( LogService.LOG_DEBUG, "Component enabled", null );
+            }
+            catch ( InvalidSyntaxException ise )
+            {
+                // one of the reference target filters is invalid, fail
+                acm.log( LogService.LOG_ERROR, "Failed enabling Component", ise );
+                acm.disableDependencyManagers();
+                acm.changeState( Disabled.getInstance() );
+            }
+        }
 
-    public boolean isServiceFactory()
-    {
-        return m_componentMetadata.getServiceMetadata() != null
-                && m_componentMetadata.getServiceMetadata().isServiceFactory();
-    }
 
-    public String[] getServices()
-    {
-        if ( m_componentMetadata.getServiceMetadata() != null )
+        void dispose( AbstractComponentManager acm )
         {
-            return m_componentMetadata.getServiceMetadata().getProvides();
-        }
+            acm.changeState( Disposing.getInstance() );
+            acm.log( LogService.LOG_DEBUG, "Disposing component", null );
+            acm.clear();
+            acm.changeState( Disposed.getInstance() );
 
-        return null;
+            acm.log( LogService.LOG_DEBUG, "Component disposed", null );
+        }
     }
 
-    //-------------- atomic transition methods -------------------------------
-    /**
-     * 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.
-     */
-    synchronized final void enableInternal()
+    protected static final class Enabling extends State
     {
-        m_state.enableInternal( this );
-    }
+        private static final Enabling m_inst = new Enabling();
 
-    synchronized final void disableInternal()
-    {
-        m_state.disableInternal( this );
-    }
 
-    synchronized final void activateInternal()
-    {
-        m_state.activateInternal( this );
-    }
+        private Enabling()
+        {
+            super( "Enabling", STATE_ENABLING );
+        }
 
-    synchronized final void deactivateInternal( int reason )
-    {
-        m_state.deactivateInternal( this, reason );
+
+        static State getInstance()
+        {
+            return m_inst;
+        }
     }
 
-    synchronized final void disposeInternal( int reason )
+    protected static final class Unsatisfied extends State
     {
-        m_state.deactivateInternal( this, reason );
-        // 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 );
-    }
+        private static final Unsatisfied m_inst = new Unsatisfied();
 
 
-    final ServiceReference getServiceReference()
-    {
-        // This method is not synchronized even though it accesses the state.
-        // The reason for this is that we just want to have the state return
-        // the service reference which comes from the service registration.
-        // The only thing that may happen is that the service registration is
-        // still set on this instance but the service has already been
-        // unregistered. In this case an IllegalStateException may be thrown
-        // which we just catch and ignore returning null
-        State state = m_state;
-        try
+        private Unsatisfied()
         {
-            return state.getServiceReference( this );
+            super( "Unsatisfied", STATE_UNSATISFIED );
         }
-        catch ( IllegalStateException ise )
+
+
+        static State getInstance()
         {
-            // may be thrown if the service has already been unregistered but
-            // the service registration is still set on this component manager
-            // we ignore this exception and assume there is no service reference
+            return m_inst;
         }
 
-        return null;
-    }
 
-    //---------- 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.
-     */
-    protected abstract boolean createComponent();
+        void activate( AbstractComponentManager acm )
+        {
+            acm.changeState( Activating.getInstance() );
 
-    protected abstract void deleteComponent( int reason );
+            acm.log( LogService.LOG_DEBUG, "Activating component", null );
 
-    /**
-     * 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.
-     *
-     * @return
-     */
-    protected abstract Object getService();
+            // Before creating the implementation object, we are going to
+            // test if we have configuration if such is required
+            if ( !acm.hasConfiguration() && acm.getComponentMetadata().isConfigurationRequired() )
+            {
+                acm.log( LogService.LOG_INFO, "Missing required configuration, cannot activate", null );
+                acm.changeState( Unsatisfied.getInstance() );
+                return;
+            }
+
+            // 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", 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", null );
 
-    final State getSatisfiedState()
-    {
-        if ( m_componentMetadata.isFactory() )
+                // set state to unsatisfied
+                acm.changeState( Unsatisfied.getInstance() );
+                return;
+            }
+
+            acm.changeState( acm.getSatisfiedState() );
+
+            acm.registerComponentService();
+        }
+
+
+        void disable( AbstractComponentManager acm )
         {
-            return Factory.getInstance();
+            acm.changeState( Disabling.getInstance() );
+
+            acm.log( LogService.LOG_DEBUG, "Disabling component", null );
+
+            // dispose and recreate dependency managers
+            acm.disableDependencyManagers();
+
+            // we are now disabled, ready for re-enablement or complete destroyal
+            acm.changeState( Disabled.getInstance() );
+
+            acm.log( LogService.LOG_DEBUG, "Component disabled", null );
         }
-        else if ( m_componentMetadata.isImmediate() )
+    }
+
+    protected static final class Activating extends State
+    {
+        private static final Activating m_inst = new Activating();
+
+
+        private Activating()
         {
-            return Active.getInstance();
+            super( "Activating", STATE_ACTIVATING );
         }
-        else
+
+
+        static State getInstance()
         {
-            return Registered.getInstance();
+            return m_inst;
         }
     }
 
-
-    protected ServiceRegistration registerService()
+    protected static abstract class Satisfied extends State
     {
-        if ( getComponentMetadata().getServiceMetadata() != null )
+        protected Satisfied( String name, int state )
         {
-            log( LogService.LOG_DEBUG, "registering services", null );
+            super( name, state );
+        }
 
-            // get a copy of the component properties as service properties
-            final Dictionary serviceProperties = getServiceProperties();
 
-            return getActivator().getBundleContext().registerService(
-                    getComponentMetadata().getServiceMetadata().getProvides(),
-                    getService(), serviceProperties );
+        ServiceReference getServiceReference( AbstractComponentManager acm )
+        {
+            ServiceRegistration sr = acm.getServiceRegistration();
+            return sr == null ? null : sr.getReference();
         }
 
-        return null;
-    }
 
-    // 5. Register provided services
-    protected void registerComponentService()
-    {
-        m_serviceRegistration = registerService();
+        void deactivate( AbstractComponentManager acm, int reason )
+        {
+            acm.changeState( Deactivating.getInstance() );
+
+            acm.log( LogService.LOG_DEBUG, "Deactivating component", null );
+
+            // catch any problems from deleting the component to prevent the
+            // component to remain in the deactivating state !
+            try
+            {
+                acm.unregisterComponentService();
+                acm.deleteComponent( reason );
+            }
+            catch ( Throwable t )
+            {
+                acm.log( LogService.LOG_WARNING, "Component deactivation threw an exception", t );
+            }
+
+            acm.changeState( Unsatisfied.getInstance() );
+            acm.log( LogService.LOG_DEBUG, "Component deactivated", null );
+        }
     }
 
-    protected final void unregisterComponentService()
+    protected static final class Active extends Satisfied
     {
+        private static final Active m_inst = new Active();
 
-        if ( m_serviceRegistration != null )
+
+        private Active()
         {
-            log( LogService.LOG_DEBUG, "unregistering the services", null );
+            super( "Active", STATE_ACTIVE );
+        }
 
-            m_serviceRegistration.unregister();
-            m_serviceRegistration = null;
+
+        static State getInstance()
+        {
+            return m_inst;
         }
-    }
 
-    //**********************************************************************************************************
-    public BundleComponentActivator getActivator()
-    {
-        return m_activator;
+
+        Object getService( DelayedComponentManager dcm )
+        {
+            return dcm.getInstance();
+        }
     }
 
-    final ServiceRegistration getServiceRegistration()
+    protected static final class Registered extends Satisfied
     {
-        return m_serviceRegistration;
-    }
+        private static final Registered m_inst = new Registered();
 
 
-    void clear()
-    {
-        // for some testing, the activator may be null
-        if ( m_activator != null )
+        private Registered()
         {
-            m_activator.unregisterComponentId( this );
-            m_activator = null;
+            super( "Registered", STATE_REGISTERED );
         }
 
-        m_dependencyManagers.clear();
-    }
-
 
-    public void log( int level, String message, Throwable ex )
-    {
-        BundleComponentActivator activator = getActivator();
-        if ( activator != null )
+        static State getInstance()
         {
-            activator.log( level, message, getComponentMetadata(), ex );
+            return m_inst;
         }
-    }
 
-    /**
-     * Activates this component if satisfied. If any of the dependencies is
-     * not met, the component is not activated and remains unsatisfied.
-     * <p>
-     * This method schedules the activation for asynchronous execution.
-     */
-    public final void activate()
-    {
-        getActivator().schedule( new ComponentActivatorTask( "Activate", this ) {
-            public void doRun()
-            {
-                activateInternal();
-            }
-        });
-    }
 
-    /**
-     * 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( final int reason )
-    {
-        getActivator().schedule( new ComponentActivatorTask( "Reactivate", this )
+        Object getService( DelayedComponentManager dcm )
         {
-
-            public void doRun()
+            if ( dcm.createRealComponent() )
             {
-                deactivateInternal( reason );
-                activateInternal();
+                dcm.changeState( Active.getInstance() );
+                return dcm.getInstance();
             }
-        } );
-    }
 
-    public String toString() {
-        return "Component: " + getName() + " (" + getId() + ")";
+            super.deactivate( dcm, ComponentConstants.DEACTIVATION_REASON_UNSPECIFIED );
+            return null;
+        }
     }
 
-    private void loadDependencyManagers( ComponentMetadata metadata )
+    protected static final class Factory extends Satisfied
     {
-        List depMgrList = new ArrayList();
-
-        // If this component has got dependencies, create dependency managers for each one of them.
-        if ( metadata.getDependencies().size() != 0 )
-        {
-            Iterator dependencyit = metadata.getDependencies().iterator();
-
-            while ( dependencyit.hasNext() )
-            {
-                ReferenceMetadata currentdependency = (ReferenceMetadata) dependencyit.next();
+        private static final Factory m_inst = new Factory();
 
-                DependencyManager depmanager = new DependencyManager( this, currentdependency );
 
-                depMgrList.add( depmanager );
-            }
+        private Factory()
+        {
+            super( "Factory", STATE_FACTORY );
         }
 
-        m_dependencyManagers = depMgrList;
-    }
 
-    private void enableDependencyManagers() throws InvalidSyntaxException
-    {
-        Iterator it = getDependencyManagers();
-        while ( it.hasNext() )
+        static State getInstance()
         {
-            DependencyManager dm = (DependencyManager) it.next();
-            dm.enable();
+            return m_inst;
         }
     }
 
-    protected boolean verifyDependencyManagers( Dictionary properties )
+    protected static final class Deactivating extends State
     {
-        // indicates whether all dependencies are satisfied
-        boolean satisfied = true;
+        private static final Deactivating m_inst = new Deactivating();
 
-        Iterator it = getDependencyManagers();
-        while ( it.hasNext() )
+
+        private Deactivating()
         {
-            DependencyManager dm = (DependencyManager) it.next();
+            super( "Deactivating", STATE_DEACTIVATING );
+        }
 
-            // ensure the target filter is correctly set
-            dm.setTargetFilter( properties );
 
-            // check whether the service is satisfied
-            if ( !dm.isSatisfied() )
-            {
-                // at least one dependency is not satisfied
-                log( LogService.LOG_INFO, "Dependency not satisfied: " + dm.getName(), null );
-                satisfied = false;
-            }
+        static State getInstance()
+        {
+            return m_inst;
         }
-
-        return satisfied;
     }
 
-    Iterator getDependencyManagers()
+    protected static final class Disabling extends State
     {
-        return m_dependencyManagers.iterator();
-    }
+        private static final Disabling m_inst = new Disabling();
 
-    DependencyManager getDependencyManager(String name)
-    {
-        Iterator it = getDependencyManagers();
-        while ( it.hasNext() )
+
+        private Disabling()
         {
-            DependencyManager dm = (DependencyManager) it.next();
-            if ( name.equals(dm.getName()) )
-            {
-                return dm;
-            }
+            super( "Disabling", STATE_DISABLING );
         }
 
-        // not found
-        return null;
-    }
 
-    private void disposeDependencyManagers()
-    {
-        Iterator it = getDependencyManagers();
-        while ( it.hasNext() )
+        static State getInstance()
         {
-            DependencyManager dm = (DependencyManager) it.next();
-            dm.dispose();
+            return m_inst;
         }
     }
 
-    public abstract boolean hasConfiguration();
-
-    public abstract Dictionary getProperties();
-
-    /**
-     * Returns the subset of component properties to be used as service
-     * properties. These properties are all component properties where property
-     * name does not start with dot (.), properties which are considered
-     * private.
-     */
-    public Dictionary getServiceProperties()
+    protected static final class Disposing extends State
     {
-        return copyTo( null, getProperties(), false);
-    }
+        private static final Disposing m_inst = new Disposing();
 
-    /**
-     * Copies the properties from the <code>source</code> <code>Dictionary</code>
-     * into the <code>target</code> <code>Dictionary</code>.
-     *
-     * @param target The <code>Dictionary</code> into which to copy the
-     *      properties. If <code>null</code> a new <code>Hashtable</code> is
-     *      created.
-     * @param source The <code>Dictionary</code> providing the properties to
-     *      copy. If <code>null</code> or empty, nothing is copied.
-     *
-     * @return The <code>target</code> is returned, which may be empty if
-     *      <code>source</code> is <code>null</code> or empty and
-     *      <code>target</code> was <code>null</code>.
-     */
-    protected static Dictionary copyTo( Dictionary target, Dictionary source )
-    {
-        return copyTo( target, source, true );
-    }
 
-    /**
-     * Copies the properties from the <code>source</code> <code>Dictionary</code>
-     * into the <code>target</code> <code>Dictionary</code> except for private
-     * properties (whose name has a leading dot) which are only copied if the
-     * <code>allProps</code> parameter is <code>true</code>.
-     *
-     * @param target    The <code>Dictionary</code> into which to copy the
-     *                  properties. If <code>null</code> a new <code>Hashtable</code> is
-     *                  created.
-     * @param source    The <code>Dictionary</code> providing the properties to
-     *                  copy. If <code>null</code> or empty, nothing is copied.
-     * @param allProps  Whether all properties (<code>true</code>) or only the
-     *                  public properties (<code>false</code>) are to be copied.
-     *
-     * @return The <code>target</code> is returned, which may be empty if
-     *         <code>source</code> is <code>null</code> or empty and
-     *         <code>target</code> was <code>null</code> or all properties are
-     *         private and had not to be copied
-     */
-    protected static Dictionary copyTo( Dictionary target, final Dictionary source, final boolean allProps )
-    {
-        if ( target == null )
+        private Disposing()
         {
-            target = new Hashtable();
+            super( "Disposing", STATE_DISPOSING );
         }
 
-        if ( source != null && !source.isEmpty() )
+
+        static State getInstance()
         {
-            for ( Enumeration ce = source.keys(); ce.hasMoreElements(); )
-            {
-                // cast is save, because key must be a string as per the spec
-                String key = ( String ) ce.nextElement();
-                if ( allProps || key.charAt( 0 ) != '.' )
-                {
-                    target.put( key, source.get( key ) );
-                }
-            }
+            return m_inst;
         }
-
-        return target;
     }
 
-
-    /**
-     *
-     */
-    public ComponentMetadata getComponentMetadata()
+    protected static final class Disposed extends State
     {
-        return m_componentMetadata;
-    }
+        private static final Disposed m_inst = new Disposed();
 
-    public int getState()
-    {
-        return m_state.getState();
-    }
 
-    protected State state()
-    {
-        return m_state;
-    }
+        private Disposed()
+        {
+            super( "Disposed", STATE_DISPOSED );
+        }
 
-    /**
-     * sets the state of the manager
-     **/
-    void changeState( State newState )
-    {
-        log( LogService.LOG_DEBUG,
-                "State transition : " + m_state + " -> " + newState,
-                null );
 
-        m_state = newState;
+        static State getInstance()
+        {
+            return m_inst;
+        }
     }
 }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java?rev=830886&r1=830885&r2=830886&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java Thu Oct 29 10:47:12 2009
@@ -104,7 +104,8 @@
 
         cm.setFactoryProperties( dictionary );
         cm.reconfigure( m_configuration );
-        // enable synchronously
+
+        // enable and activate immediately
         cm.enableInternal();
         cm.activateInternal();
 

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java?rev=830886&r1=830885&r2=830886&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java Thu Oct 29 10:47:12 2009
@@ -53,20 +53,17 @@
         | AbstractComponentManager.STATE_ACTIVATING | AbstractComponentManager.STATE_ACTIVE
         | AbstractComponentManager.STATE_REGISTERED | AbstractComponentManager.STATE_FACTORY;
 
-    // the ServiceReference class instance
-    private static final Class SERVICE_REFERENCE_CLASS = ServiceReference.class;
-
     // pseudo service to mark a bound service without actual service instance
     private static final Object BOUND_SERVICE_SENTINEL = new Object();
 
     // the component to which this dependency belongs
-    private AbstractComponentManager m_componentManager;
+    private final AbstractComponentManager m_componentManager;
 
     // Reference to the metadata
-    private ReferenceMetadata m_dependencyMetadata;
+    private final ReferenceMetadata m_dependencyMetadata;
 
     // The map of bound services indexed by their ServiceReference
-    private Map m_bound;
+    private final Map m_bound;
 
     // the number of matching services registered in the system
     private int m_size;
@@ -77,15 +74,9 @@
     // the bind method
     private BindMethod m_bind;
 
-    // whether the bind method takes a service reference
-    private boolean m_bindUsesReference;
-
     // the unbind method
     private UnbindMethod m_unbind;
 
-    // whether the unbind method takes a service reference
-    private boolean m_unbindUsesReference;
-
     // the target service filter string
     private String m_target;
 
@@ -107,8 +98,17 @@
         // setup the target filter from component descriptor
         setTargetFilter( m_dependencyMetadata.getTarget() );
 
-        m_componentManager.log( LogService.LOG_DEBUG, "Dependency Manager " + getName() + " created: filter="
-            + getTarget() + ", interface=" + m_dependencyMetadata.getInterface(), null );
+        // dump the reference information if DEBUG is enabled
+        if ( m_componentManager.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            m_componentManager
+                .log(
+                    LogService.LOG_DEBUG,
+                    "Dependency Manager {0} created: interface={1}, filter={2}, policy={3}, cardinality={4}, bind={5}, unbind={6}",
+                    new Object[]
+                        { getName(), dependency.getInterface(), dependency.getTarget(), dependency.getPolicy(),
+                            dependency.getCardinality(), dependency.getBind(), dependency.getUnbind() }, null );
+        }
     }
 
     /**
@@ -474,7 +474,7 @@
      * bound services. This list will not be empty if the service lookup
      * method is used by the component to access the service.
      */
-    void dispose()
+    void disable()
     {
         BundleContext context = m_componentManager.getActivator().getBundleContext();
         context.removeServiceListener( this );
@@ -490,6 +490,9 @@
                 ungetService( boundRefs[i] );
             }
         }
+
+        // reset the target filter from component descriptor
+        setTargetFilter( m_dependencyMetadata.getTarget() );
     }
 
 
@@ -825,6 +828,7 @@
             m_componentInstance = null;
             m_bind = null;
             m_unbind = null;
+            m_bound.clear();
 
         }
     }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java?rev=830886&r1=830885&r2=830886&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java Thu Oct 29 10:47:12 2009
@@ -88,17 +88,6 @@
     }
 
 
-    /**
-     * Before doing real disposal, we also have to unregister the managed
-     * service which was registered when the instance was created.
-     */
-    public synchronized void dispose( final int reason )
-    {
-        // really dispose off this manager instance
-        disposeInternal( reason );
-    }
-
-
     ComponentHolder getComponentHolder()
     {
         return m_componentHolder;



Mime
View raw message