FELIX-341 Intermittent exception during Felix shutdown

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@571194 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 d9f49bd..15df450 100644
--- a/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java
@@ -31,6 +31,7 @@
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.component.ComponentInstance;
+import org.osgi.service.log.LogService;
 
 
 /**
@@ -97,7 +98,7 @@
         m_state = STATE_DISABLED;
         m_dependencyManagers = new ArrayList();
 
-        Activator.trace( "Component created", m_componentMetadata );
+        getActivator().log( LogService.LOG_DEBUG, "Component created", m_componentMetadata, null );
     }
 
 
@@ -150,7 +151,8 @@
      */
     public final void reconfigure()
     {
-        Activator.trace( "Deactivating and Activating to reconfigure", m_componentMetadata );
+        getActivator().log( LogService.LOG_DEBUG, "Deactivating and Activating to reconfigure", m_componentMetadata,
+            null );
         reactivate();
     }
 
@@ -159,16 +161,19 @@
      * Cycles this component by deactivating it and - if still satisfied -
      * activating it again.
      * <p>
-     * This method schedules the reactivation for asynchronous execution.
+     * This method immediately deactivates the component to prevent action
+     * with old configuration/references and schedules the reactivation for
+     * asynchronous execution.
      */
     public final void reactivate()
     {
+        // synchronously deactivate and schedule activation asynchronously
+        deactivateInternal();
+
         getActivator().schedule( new Runnable()
         {
             public void run()
             {
-                deactivateInternal();
-                Activator.trace( "Dependency Manager: RECREATING", m_componentMetadata );
                 activateInternal();
             }
         } );
@@ -178,17 +183,14 @@
     /**
      * Deactivates the component.
      * <p>
-     * This method schedules the deactivation for asynchronous execution.
+     * This method unlike other state change methods immediately takes
+     * action and deactivates the component. The reason for this is, that this
+     * method is called when a required service is not available any more and
+     * hence the component cannot work.
      */
     public final void deactivate()
     {
-        getActivator().schedule( new Runnable()
-        {
-            public void run()
-            {
-                deactivateInternal();
-            }
-        } );
+        deactivateInternal();
     }
 
 
@@ -239,16 +241,17 @@
 
         if ( getState() == STATE_DESTROYED )
         {
-            Activator.error( "Destroyed Component cannot be enabled", m_componentMetadata );
+            getActivator().log( LogService.LOG_ERROR, "Destroyed Component cannot be enabled", m_componentMetadata,
+                null );
             return;
         }
         else if ( getState() != STATE_DISABLED )
         {
-            Activator.trace( "Component is already enabled", m_componentMetadata );
+            getActivator().log( LogService.LOG_DEBUG, "Component is already enabled", m_componentMetadata, null );
             return;
         }
 
-        Activator.trace( "Enabling component", m_componentMetadata );
+        getActivator().log( LogService.LOG_DEBUG, "Enabling component", m_componentMetadata, null );
 
         try
         {
@@ -270,14 +273,14 @@
             // enter enabled state before trying to activate
             setState( STATE_ENABLED );
 
-            Activator.trace( "Component enabled", m_componentMetadata );
+            getActivator().log( LogService.LOG_DEBUG, "Component enabled", m_componentMetadata, null );
 
             // immediately activate the compopnent, no need to schedule again
             activateInternal();
         }
         catch ( Exception ex )
         {
-            Activator.exception( "Failed enabling Component", m_componentMetadata, ex );
+            getActivator().log( LogService.LOG_ERROR, "Failed enabling Component", m_componentMetadata, ex );
 
             // ensure we get back to DISABLED state
             // immediately disable, no need to schedule again
@@ -298,19 +301,24 @@
      */
     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 )
+        // CONCURRENCY NOTE: This method is only called from within the
+        //     ComponentActorThread to enable, activate or reactivate the
+        //     component. Still we use the setStateConditional to not create
+        //     a race condition with the deactivateInternal method
+        if ( !setStateConditional( STATE_ENABLED | STATE_UNSATISFIED, STATE_ACTIVATING ) )
         {
-            // This state can only be entered from the ENABLED (in the enable()
-            // method) or UNSATISFIED (missing references) states
             return;
         }
 
-        // go to the activating state
-        setState( STATE_ACTIVATING );
+        // we cannot activate if the component activator is shutting down
+        if ( !isActive() )
+        {
+            getActivator().log( LogService.LOG_DEBUG,
+                "Component cannot be activated because the Activator is being disposed", m_componentMetadata, null );
+            return;
+        }
 
-        Activator.trace( "Activating component", m_componentMetadata );
+        getActivator().log( LogService.LOG_DEBUG, "Activating component", m_componentMetadata, null );
 
         // Before creating the implementation object, we are going to
         // test if all the mandatory dependencies are satisfied
@@ -321,7 +329,8 @@
             if ( !dm.isValid() )
             {
                 // at least one dependency is not satisfied
-                Activator.trace( "Dependency not satisfied: " + dm.getName(), m_componentMetadata );
+                getActivator().log( LogService.LOG_DEBUG, "Dependency not satisfied: " + dm.getName(),
+                    m_componentMetadata, null );
                 setState( STATE_UNSATISFIED );
                 return;
             }
@@ -334,7 +343,8 @@
         if ( !createComponent() )
         {
             // component creation failed, not active now
-            Activator.error( "Component instance could not be created, activation failed", m_componentMetadata );
+            getActivator().log( LogService.LOG_ERROR, "Component instance could not be created, activation failed",
+                m_componentMetadata, null );
 
             // set state to unsatisfied
             setState( STATE_UNSATISFIED );
@@ -350,7 +360,7 @@
         // 5. Register provided services
         m_serviceRegistration = registerComponentService();
 
-        Activator.trace( "Component activated", m_componentMetadata );
+        getActivator().log( LogService.LOG_DEBUG, "Component activated", m_componentMetadata, null );
     }
 
 
@@ -364,19 +374,18 @@
     **/
     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 )
+        // CONCURRENCY NOTE: This method may be called either from the
+        //     ComponentActorThread to handle application induced disabling or
+        //     as a result of an unsatisfied service dependency leading to
+        //     component deactivation. We therefore have to guard against
+        //     paralell state changes.from application
+        if ( !setStateConditional( STATE_ACTIVATING | STATE_ACTIVE | STATE_REGISTERED | STATE_FACTORY,
+            STATE_DEACTIVATING ) )
         {
-            // This state can only be entered from the ACTIVATING (if activation
-            // fails), ACTIVE, REGISTERED or FACTORY states
             return;
         }
 
-        // start deactivation by resetting the state
-        setState( STATE_DEACTIVATING );
-
-        Activator.trace( "Deactivating component", m_componentMetadata );
+        getActivator().log( LogService.LOG_DEBUG, "Deactivating component", m_componentMetadata, null );
 
         // 0.- Remove published services from the registry
         unregisterComponentService();
@@ -391,7 +400,7 @@
         // reset to state UNSATISFIED
         setState( STATE_UNSATISFIED );
 
-        Activator.trace( "Component deactivated", m_componentMetadata );
+        getActivator().log( LogService.LOG_DEBUG, "Component deactivated", m_componentMetadata, null );
     }
 
 
@@ -403,7 +412,7 @@
         // deactivate first, this does nothing if not active/registered/factory
         deactivateInternal();
 
-        Activator.trace( "Disabling component", m_componentMetadata );
+        getActivator().log( LogService.LOG_DEBUG, "Disabling component", m_componentMetadata, null );
 
         // close all service listeners now, they are recreated on enable
         // Stop the dependency managers to listen to events...
@@ -418,7 +427,7 @@
         // we are now disabled, ready for re-enablement or complete destroyal
         setState( STATE_DISABLED );
 
-        Activator.trace( "Component disabled", m_componentMetadata );
+        getActivator().log( LogService.LOG_DEBUG, "Component disabled", m_componentMetadata, null );
     }
 
 
@@ -436,11 +445,11 @@
         // this component must not be used any more
         setState( STATE_DESTROYED );
 
+        getActivator().log( LogService.LOG_DEBUG, "Component disposed", m_componentMetadata, null );
+
         // release references (except component metadata for logging purposes)
         m_activator = null;
         m_dependencyManagers = null;
-
-        Activator.trace( "Component disposed", m_componentMetadata );
     }
 
 
@@ -508,7 +517,7 @@
     {
         if ( getComponentMetadata().getServiceMetadata() != null )
         {
-            Activator.trace( "registering services", getComponentMetadata() );
+            getActivator().log( LogService.LOG_DEBUG, "registering services", getComponentMetadata(), null );
 
             // get a copy of the component properties as service properties
             Dictionary serviceProperties = copyTo( null, getProperties() );
@@ -528,7 +537,7 @@
             m_serviceRegistration.unregister();
             m_serviceRegistration = null;
 
-            Activator.trace( "unregistering the services", getComponentMetadata() );
+            getActivator().log( LogService.LOG_DEBUG, "unregistering the services", getComponentMetadata(), null );
         }
     }
 
@@ -541,6 +550,19 @@
     }
 
 
+    /**
+     * Returns <code>true</code> if this instance has not been disposed off
+     * yet and the BundleComponentActivator is still active. If the Bundle
+     * Component Activator is being disposed off as a result of stopping the
+     * owning bundle, this method returns <code>false</code>.
+     */
+    private boolean isActive()
+    {
+        BundleComponentActivator bca = getActivator();
+        return bca != null && bca.isActive();
+    }
+
+
     Iterator getDependencyManagers()
     {
         return m_dependencyManagers.iterator();
@@ -636,13 +658,39 @@
     **/
     protected synchronized void setState( int newState )
     {
-        Activator.trace( "State transition : " + stateToString( m_state ) + " -> " + stateToString( newState ),
-            m_componentMetadata );
+        getActivator().log( LogService.LOG_DEBUG,
+            "State transition : " + stateToString( m_state ) + " -> " + stateToString( newState ), m_componentMetadata,
+            null );
 
         m_state = newState;
     }
 
 
+    /**
+     * If the state is currently one of the <code>requiredStates</code>, the
+     * state is set to <code>newState</code> and <code>true</code> is returned.
+     * Otherwise the state is not changed and <code>false</code> is returned.
+     * <p>
+     * This method atomically checks the current state and sets the new state.
+     * 
+     * @param requiredStates The set of states required for the state change to
+     *          happen.
+     * @param newState The new state to go into.
+     * @return <code>true</code> if the state was one of the required states and
+     *          the new state has now been entered.
+     */
+    protected synchronized boolean setStateConditional( int requiredStates, int newState )
+    {
+        if ( ( getState() & requiredStates ) != 0 )
+        {
+            setState( newState );
+            return true;
+        }
+
+        return false;
+    }
+
+
     public String stateToString( int state )
     {
         switch ( state )
diff --git a/scr/src/main/java/org/apache/felix/scr/Activator.java b/scr/src/main/java/org/apache/felix/scr/Activator.java
index aaeddf5..22becf7 100644
--- a/scr/src/main/java/org/apache/felix/scr/Activator.java
+++ b/scr/src/main/java/org/apache/felix/scr/Activator.java
@@ -18,6 +18,7 @@
  */
 package org.apache.felix.scr;
 
+
 import java.io.PrintStream;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -34,6 +35,7 @@
 import org.osgi.service.log.LogService;
 import org.osgi.util.tracker.ServiceTracker;
 
+
 /**
  * This activator is used to cover requirement described in section 112.8.1 @@ -27,14
  * 37,202 @@ in active bundles.
@@ -42,20 +44,17 @@
 public class Activator implements BundleActivator, SynchronousBundleListener
 {
     //  name of the LogService class (this is a string to not create a reference to the class)
-    private static final String LOGSERVICE_CLASS = "org.osgi.service.log.LogService";    
-    
-    // Flag that sets tracing messages
-    private static boolean m_trace = true;
-    
+    static final String LOGSERVICE_CLASS = "org.osgi.service.log.LogService";
+
     // Flag that sets error messages
-    private static boolean m_error = true;
+    private static int m_logLevel = LogService.LOG_ERROR;
 
     // this bundle's context
     private BundleContext m_context;
-    
+
     // the log service to log messages to
     private static ServiceTracker m_logService;
-    
+
     // map of BundleComponentActivator instances per Bundle indexed by Bundle symbolic
     // name
     private Map m_componentBundles;
@@ -65,7 +64,8 @@
 
     //  thread acting upon configurations
     private ComponentActorThread m_componentActor;
-    
+
+
     /**
      * Registers this instance as a (synchronous) bundle listener and loads the
      * components of already registered bundles.
@@ -73,23 +73,22 @@
      * @param context The <code>BundleContext</code> of the SCR implementation
      *      bundle.
      */
-    public void start(BundleContext context) throws Exception
+    public void start( BundleContext context ) throws Exception
     {
         m_context = context;
         m_componentBundles = new HashMap();
         m_componentRegistry = new ComponentRegistry( m_context );
 
         // require the log service
-        m_logService = new ServiceTracker(context, LOGSERVICE_CLASS, null);
+        m_logService = new ServiceTracker( context, LOGSERVICE_CLASS, null );
         m_logService.open();
-        
+
         // configure logging from context properties
-        m_trace = "true".equalsIgnoreCase( context.getProperty( "ds.showtrace" ) );
-        m_error = !"false".equalsIgnoreCase( context.getProperty( "ds.showerrors" ) );
+        m_logLevel = getLogLevel( context );
         if ( "true".equalsIgnoreCase( context.getProperty( "ds.showversion" ) ) )
         {
-            trace( context.getBundle().getSymbolicName() + "[ Version = "
-                + context.getBundle().getHeaders().get( Constants.BUNDLE_VERSION ) + " ]", null );
+            log( LogService.LOG_INFO, context.getBundle(), " Version = "
+                + context.getBundle().getHeaders().get( Constants.BUNDLE_VERSION ), null );
         }
 
         // create and start the component actor 
@@ -97,12 +96,13 @@
         m_componentActor.start();
 
         // register for bundle updates
-        context.addBundleListener(this);
+        context.addBundleListener( this );
 
         // 112.8.2 load all components of active bundles
-        loadAllComponents(context);
+        loadAllComponents( context );
     }
 
+
     /**
      * Unregisters this instance as a bundle listener and unloads all components
      * which have been registered during the active life time of the SCR
@@ -140,6 +140,7 @@
         }
     }
 
+
     // ---------- BundleListener Interface -------------------------------------
 
     /**
@@ -150,34 +151,36 @@
      * @param event The <code>BundleEvent</code> representing the bundle state
      *      change.
      */
-    public void bundleChanged(BundleEvent event)
+    public void bundleChanged( BundleEvent event )
     {
-        if (event.getType() == BundleEvent.STARTED)
+        if ( event.getType() == BundleEvent.STARTED )
         {
-            loadComponents(event.getBundle());
+            loadComponents( event.getBundle() );
         }
-        else if (event.getType() == BundleEvent.STOPPING)
+        else if ( event.getType() == BundleEvent.STOPPING )
         {
-            disposeComponents(event.getBundle());
+            disposeComponents( event.getBundle() );
         }
     }
 
+
     //---------- Component Management -----------------------------------------
 
     // Loads the components of all bundles currently active.
-    private void loadAllComponents(BundleContext context)
+    private void loadAllComponents( BundleContext context )
     {
         Bundle[] bundles = context.getBundles();
-        for (int i = 0; i < bundles.length; i++)
+        for ( int i = 0; i < bundles.length; i++ )
         {
             Bundle bundle = bundles[i];
-            if (bundle.getState() == Bundle.ACTIVE)
+            if ( bundle.getState() == Bundle.ACTIVE )
             {
-                loadComponents(bundle);
+                loadComponents( bundle );
             }
         }
     }
 
+
     /**
      * Loads the components of the given bundle. If the bundle has no
      * <i>Service-Component</i> header, this method has no effect. The
@@ -187,77 +190,80 @@
      * the <code>BundleContext</code> of the bundle. If the context cannot be
      * found, this method does not load components for the bundle.
      */
-    private void loadComponents(Bundle bundle)
+    private void loadComponents( Bundle bundle )
     {
-        if (bundle.getHeaders().get("Service-Component") == null)
+        if ( bundle.getHeaders().get( "Service-Component" ) == null )
         {
             // no components in the bundle, abandon
             return;
         }
 
         // there should be components, load them with a bundle context
-        BundleContext context = getBundleContext(bundle);
-        if (context == null)
+        BundleContext context = getBundleContext( bundle );
+        if ( context == null )
         {
-            error( "Cannot get BundleContext of bundle " + bundle.getSymbolicName(), null );
+            log( LogService.LOG_ERROR, m_context.getBundle(), "Cannot get BundleContext of bundle "
+                + bundle.getSymbolicName(), null );
             return;
         }
 
         try
         {
-            BundleComponentActivator ga = new BundleComponentActivator( m_componentRegistry, m_componentActor, context );
-            m_componentBundles.put(bundle.getSymbolicName(), ga);
+            BundleComponentActivator ga = new BundleComponentActivator( m_componentRegistry, m_componentActor, context,
+                m_logLevel );
+            m_componentBundles.put( bundle.getSymbolicName(), ga );
         }
-        catch (Exception e)
+        catch ( Exception e )
         {
-            exception("Error while loading components "
-                + "of bundle " + bundle.getSymbolicName(), null, e);
+            log( LogService.LOG_ERROR, m_context.getBundle(), "Error while loading components of bundle "
+                + bundle.getSymbolicName(), e );
         }
     }
 
+
     /**
      * Unloads components of the given bundle. If no components have been loaded
      * for the bundle, this method has no effect.
      */
-    private void disposeComponents(Bundle bundle)
+    private void disposeComponents( Bundle bundle )
     {
         String name = bundle.getSymbolicName();
-        BundleComponentActivator ga = (BundleComponentActivator) m_componentBundles.remove(name);
-        if (ga != null)
+        BundleComponentActivator ga = ( BundleComponentActivator ) m_componentBundles.remove( name );
+        if ( ga != null )
         {
             try
             {
                 ga.dispose();
             }
-            catch (Exception e)
+            catch ( Exception e )
             {
-                exception("Error while disposing components "
-                    + "of bundle " + name, null, e);
+                log( LogService.LOG_ERROR, m_context.getBundle(), "Error while disposing components of bundle " + name,
+                    e );
             }
         }
     }
 
+
     // Unloads all components registered with the SCR
     private void disposeAllComponents()
     {
-        for (Iterator it = m_componentBundles.values().iterator(); it.hasNext();)
+        for ( Iterator it = m_componentBundles.values().iterator(); it.hasNext(); )
         {
-            BundleComponentActivator ga = (BundleComponentActivator) it.next();
+            BundleComponentActivator ga = ( BundleComponentActivator ) it.next();
             try
             {
                 ga.dispose();
             }
-            catch (Exception e)
+            catch ( Exception e )
             {
-                exception(
-                    "Error while disposing components of bundle "
-                        + ga.getBundleContext().getBundle().getSymbolicName(),
-                    null, e);
+                log( LogService.LOG_ERROR, m_context.getBundle(), "Error while disposing components of bundle "
+                    + ga.getBundleContext().getBundle().getSymbolicName(), e );
             }
             it.remove();
         }
     }
 
+
     /**
      * Returns the <code>BundleContext</code> of the bundle.
      * <p>
@@ -271,7 +277,7 @@
      *         <code>null</code> if no <code>getContext</code> method
      *         returning a <code>BundleContext</code> can be found.
      */
-    private BundleContext getBundleContext(Bundle bundle)
+    private BundleContext getBundleContext( Bundle bundle )
     {
         try
         {
@@ -288,32 +294,34 @@
             // ignore any other Throwable, most prominently NoSuchMethodError
             // which is called in a pre-OSGI 4.1 environment
         }
-        
+
         BundleContext context = null;
-        for (Class clazz = bundle.getClass(); context == null && clazz != null; clazz = clazz.getSuperclass())
+        for ( Class clazz = bundle.getClass(); context == null && clazz != null; clazz = clazz.getSuperclass() )
         {
             try
             {
                 context = getBundleContext( clazz, bundle, "getBundleContext" );
-                if (context == null) {
+                if ( context == null )
+                {
                     context = getBundleContext( clazz, bundle, "getContext" );
                 }
             }
-            catch (NoSuchMethodException nsme)
+            catch ( NoSuchMethodException nsme )
             {
                 // don't actually care, just try super class
             }
-            catch (Throwable t)
+            catch ( Throwable t )
             {
-                exception("Cannot get BundleContext for "
-                    + bundle.getSymbolicName(), null, t);
+                log( LogService.LOG_ERROR, m_context.getBundle(), "Cannot get BundleContext for "
+                    + bundle.getSymbolicName(), t );
             }
         }
 
         // return what we found
         return context;
     }
-    
+
+
     private BundleContext getBundleContext( Class clazz, Bundle bundle, String methodName )
         throws NoSuchMethodException, InvocationTargetException, IllegalAccessException
     {
@@ -323,74 +331,59 @@
             m.setAccessible( true );
             return ( BundleContext ) m.invoke( bundle, null );
         }
-        
+
         // method exists but has wrong return type
         return null;
     }
-    
-    /**
-     * Method to display traces
-     *
-     * @param message a string to be displayed
-     * @param metadata ComponentMetadata associated to the message (can be null)
-     **/
-    static void trace( String message, ComponentMetadata metadata )
+
+
+    private static int getLogLevel( BundleContext bundleContext )
     {
-        if ( m_trace )
+        String levelString = bundleContext.getProperty( "ds.loglevel" );
+        if ( levelString != null )
         {
-            StringBuffer msg = new StringBuffer( "--- " );
-            if ( metadata != null )
+            try
             {
-                msg.append( "[" ).append( metadata.getName() ).append( "] " );
+                return Integer.parseInt( levelString );
             }
-            msg.append( message );
+            catch ( NumberFormatException nfe )
+            {
+                // might be a descriptive name
+            }
 
-            log( LogService.LOG_DEBUG, msg.toString(), null );
+            if ( "debug".equalsIgnoreCase( levelString ) )
+            {
+                return LogService.LOG_DEBUG;
+            }
+            else if ( "info".equalsIgnoreCase( levelString ) )
+            {
+                return LogService.LOG_INFO;
+            }
+            else if ( "warn".equalsIgnoreCase( levelString ) )
+            {
+                return LogService.LOG_WARNING;
+            }
+            else if ( "error".equalsIgnoreCase( levelString ) )
+            {
+                return LogService.LOG_ERROR;
+            }
         }
-    }
 
-
-    /**
-     * Method to display errors
-     *
-     * @param message a string to be displayed
-     * @param metadata optional metadata providing more information to log
-     **/
-    static void error( String message, ComponentMetadata metadata )
-    {
-        if ( m_error )
+        // check ds.showtrace property
+        levelString = bundleContext.getProperty( "ds.trace" );
+        if ( "true".equalsIgnoreCase( bundleContext.getProperty( "ds.showtrace" ) ) )
         {
-            StringBuffer msg = new StringBuffer( "### " );
-            if ( metadata != null )
-            {
-                msg.append( "[" ).append( metadata.getName() ).append( "] " );
-            }
-            msg.append( message );
-
-            log( LogService.LOG_ERROR, msg.toString(), null );
+            return LogService.LOG_DEBUG;
         }
-    }
 
-
-    /**
-     * Method to display exceptions
-     *
-     * @param ex an exception
-     **/
-    static void exception( String message, ComponentMetadata metadata, Throwable ex )
-    {
-        if ( m_error )
+        // next check ds.showerrors property
+        if ( "false".equalsIgnoreCase( bundleContext.getProperty( "ds.showerrors" ) ) )
         {
-            StringBuffer msg = new StringBuffer( "--- " );
-            if ( metadata != null )
-            {
-                msg.append( "[" ).append( metadata.getName() ).append( "] " );
-            }
-            msg.append( "Exception with component : " );
-            msg.append( message ).append( " ---" );
-
-            log( LogService.LOG_ERROR, msg.toString(), ex );
+            return -1; // no logging at all !!
         }
+
+        // default log level (errors only)
+        return LogService.LOG_ERROR;
     }
 
 
@@ -404,22 +397,63 @@
      * @param ex An optional <code>Throwable</code> whose stack trace is written,
      *      or <code>null</code> to not log a stack trace.
      */
-    static void log( int level, String message, Throwable ex )
+    static void log( int level, Bundle bundle, String message, Throwable ex )
     {
-
-        Object logger = m_logService.getService();
-        if ( logger == null )
+        if ( m_logLevel >= level )
         {
-            PrintStream out = ( level == LogService.LOG_ERROR ) ? System.err : System.out;
-            out.println( message );
-            if ( ex != null )
+            Object logger = ( m_logService != null ) ? m_logService.getService() : null;
+            if ( logger == null )
             {
-                ex.printStackTrace( out );
+                // output depending on level
+                PrintStream out = ( level == LogService.LOG_ERROR ) ? System.err : System.out;
+
+                // level as a string
+                StringBuffer buf = new StringBuffer();
+                switch ( level )
+                {
+                    case ( LogService.LOG_DEBUG     ):
+                        buf.append( "DEBUG: " );
+                        break;
+                    case ( LogService.LOG_INFO     ):
+                        buf.append( "INFO : " );
+                        break;
+                    case ( LogService.LOG_WARNING     ):
+                        buf.append( "WARN : " );
+                        break;
+                    case ( LogService.LOG_ERROR     ):
+                        buf.append( "ERROR: " );
+                        break;
+                    default:
+                        buf.append( "UNK  : " );
+                        break;
+                }
+
+                // bundle information
+                if ( bundle != null )
+                {
+                    buf.append( bundle.getSymbolicName() );
+                    buf.append( " (" );
+                    buf.append( bundle.getBundleId() );
+                    buf.append( "): " );
+                }
+
+                // the message
+                buf.append( message );
+
+                // keep the message and the stacktrace together
+                synchronized ( out)
+                {
+                    out.println( buf );
+                    if ( ex != null )
+                    {
+                        ex.printStackTrace( out );
+                    }
+                }
             }
-        }
-        else
-        {
-            ( ( LogService ) logger ).log( level, message, ex );
+            else
+            {
+                ( ( LogService ) logger ).log( level, message, ex );
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/scr/src/main/java/org/apache/felix/scr/BundleComponentActivator.java b/scr/src/main/java/org/apache/felix/scr/BundleComponentActivator.java
index 7dde6fd..3080aa3 100644
--- a/scr/src/main/java/org/apache/felix/scr/BundleComponentActivator.java
+++ b/scr/src/main/java/org/apache/felix/scr/BundleComponentActivator.java
@@ -18,6 +18,7 @@
  */
 package org.apache.felix.scr;
 
+
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
@@ -35,28 +36,39 @@
 import org.osgi.service.log.LogService;
 import org.osgi.util.tracker.ServiceTracker;
 
+
 /**
  * The BundleComponentActivator is helper class to load and unload Components of
  * a single bundle. It will read information from the metadata.xml file
  * descriptors and create the corresponding managers.
  */
 class BundleComponentActivator
-{	
+{
     // global component registration
     private ComponentRegistry m_componentRegistry;
-    
-	// The bundle context owning the registered component
+
+    // The bundle context owning the registered component
     private BundleContext m_context = null;
-    
+
     // This is a list of component instance managers that belong to a particular bundle
     private List m_managers = new ArrayList();
 
     // The Configuration Admin tracker providing configuration for components
     private ServiceTracker m_configurationAdmin;
 
+    // The Configuration Admin tracker providing configuration for components
+    private ServiceTracker m_logService;
+
     // thread acting upon configurations
     private ComponentActorThread m_componentActor;
-    
+
+    // true as long as the dispose method is not called
+    private boolean m_active;
+
+    // the logging level
+    private int m_logLevel;
+
+
     /**
      * Called upon starting of the bundle. This method invokes initialize() which
      * parses the metadata and creates the instance managers
@@ -69,17 +81,25 @@
      * @throws ComponentException if any error occurrs initializing this class
      */
     BundleComponentActivator( ComponentRegistry componentRegistry, ComponentActorThread componentActor,
-        BundleContext context ) throws ComponentException
+        BundleContext context, int logLevel ) throws ComponentException
     {
         // keep the parameters for later
         m_componentRegistry = componentRegistry;
         m_componentActor = componentActor;
         m_context = context;
 
+        // mark this instance active
+        m_active = true;
+
         // have the Configuration Admin Service handy (if available)
         m_configurationAdmin = new ServiceTracker( context, ConfigurationAdmin.class.getName(), null );
         m_configurationAdmin.open();
 
+        // have the LogService handy (if available)
+        m_logService = new ServiceTracker( context, Activator.LOGSERVICE_CLASS, null );
+        m_logService.open();
+        m_logLevel = logLevel;
+
         // Get the Metadata-Location value from the manifest
         String descriptorLocations = ( String ) m_context.getBundle().getHeaders().get( "Service-Component" );
         if ( descriptorLocations == null )
@@ -90,6 +110,7 @@
         initialize( descriptorLocations );
     }
 
+
     /**
      * Gets the MetaData location, parses the meta data and requests the processing
      * of binder instances
@@ -99,50 +120,55 @@
      *      
      * @throws IllegalStateException If the bundle has already been uninstalled.
      */
-    private void initialize(String descriptorLocations) {
+    private void initialize( String descriptorLocations )
+    {
 
         // 112.4.1: The value of the the header is a comma separated list of XML entries within the Bundle 
-		StringTokenizer st = new StringTokenizer(descriptorLocations, ", ");
-        
-		while (st.hasMoreTokens()) {
-			String descriptorLocation = st.nextToken();
-			
-            URL descriptorURL = m_context.getBundle().getResource(descriptorLocation);
-            if (descriptorURL == null)
+        StringTokenizer st = new StringTokenizer( descriptorLocations, ", " );
+
+        while ( st.hasMoreTokens() )
+        {
+            String descriptorLocation = st.nextToken();
+
+            URL descriptorURL = m_context.getBundle().getResource( descriptorLocation );
+            if ( descriptorURL == null )
             {
                 // 112.4.1 If an XML document specified by the header cannot be located in the bundle and its attached
                 // fragments, SCR must log an error message with the Log Service, if present, and continue.
-                Activator.error( "Component descriptor entry '" + descriptorLocation + "' not found", null );
+                log( LogService.LOG_ERROR, "Component descriptor entry '" + descriptorLocation + "' not found", null,
+                    null );
                 continue;
             }
 
             InputStream stream = null;
-			try {
-				stream = descriptorURL.openStream();
+            try
+            {
+                stream = descriptorURL.openStream();
 
-				BufferedReader in = new BufferedReader(new InputStreamReader(stream)); 
-	            XmlHandler handler = new XmlHandler(); 
-	            KXml2SAXParser parser;
+                BufferedReader in = new BufferedReader( new InputStreamReader( stream ) );
+                XmlHandler handler = new XmlHandler();
+                KXml2SAXParser parser;
 
-	            parser = new KXml2SAXParser(in); 
+                parser = new KXml2SAXParser( in );
 
-		        parser.parseXML(handler);
+                parser.parseXML( handler );
 
-		        // 112.4.2 Component descriptors may contain a single, root component element
-		        // or one or more component elements embedded in a larger document
-		        Iterator i = handler.getComponentMetadataList().iterator();
-		        while (i.hasNext()) {
-                    ComponentMetadata metadata = (ComponentMetadata) i.next();
-                	try
+                // 112.4.2 Component descriptors may contain a single, root component element
+                // or one or more component elements embedded in a larger document
+                Iterator i = handler.getComponentMetadataList().iterator();
+                while ( i.hasNext() )
+                {
+                    ComponentMetadata metadata = ( ComponentMetadata ) i.next();
+                    try
                     {
                         // check and reserve the component name
                         m_componentRegistry.checkComponentName( metadata.getName() );
-                        
+
                         // validate the component metadata
                         metadata.validate();
-    		        	
-    	                // Request creation of the component manager
-    	                ComponentManager manager;
+
+                        // Request creation of the component manager
+                        ComponentManager manager;
                         if ( metadata.isFactory() )
                         {
                             // 112.2.4 SCR must register a Component Factory
@@ -155,41 +181,40 @@
                             manager = ManagerFactory.createManager( this, metadata, m_componentRegistry
                                 .createComponentId() );
                         }
-                		
+
                         // register the component after validation
                         m_componentRegistry.registerComponent( metadata.getName(), manager );
                         m_managers.add( manager );
-                        
+
                         // enable the component
                         if ( metadata.isEnabled() )
                         {
                             manager.enable();
                         }
                     }
-                    catch (Throwable t)
+                    catch ( Throwable t )
                     {
-						// There is a problem with this particular component, we'll log the error
-	                	// and proceed to the next one
-                        Activator.exception("Cannot register Component", metadata, t);
-                        
+                        // There is a problem with this particular component, we'll log the error
+                        // and proceed to the next one
+                        log( LogService.LOG_ERROR, "Cannot register Component", metadata, t );
+
                         // make sure the name is not reserved any more
                         m_componentRegistry.unregisterComponent( metadata.getName() );
-					}
-		        }
-			}
-			catch ( IOException ex )
+                    }
+                }
+            }
+            catch ( IOException ex )
             {
-				// 112.4.1 If an XML document specified by the header cannot be located in the bundle and its attached
-				// fragments, SCR must log an error message with the Log Service, if present, and continue.
-				
-				Activator.exception("Problem reading descriptor entry '"
-                    + descriptorLocation + "'", null, ex);
-			}
-			catch (Exception ex)
+                // 112.4.1 If an XML document specified by the header cannot be located in the bundle and its attached
+                // fragments, SCR must log an error message with the Log Service, if present, and continue.
+
+                log( LogService.LOG_ERROR, "Problem reading descriptor entry '" + descriptorLocation + "'", null, ex );
+            }
+            catch ( Exception ex )
             {
-                Activator.exception("General problem with descriptor entry '"
-                    + descriptorLocation + "'", null, ex);
-			}
+                log( LogService.LOG_ERROR, "General problem with descriptor entry '" + descriptorLocation + "'", null,
+                    ex );
+            }
             finally
             {
                 if ( stream != null )
@@ -203,64 +228,83 @@
                     }
                 }
             }
-		}
+        }
     }
 
+
     /**
     * Dispose of this component activator instance and all the component
     * managers.
     */
     void dispose()
     {
-        if (m_context == null) {
+        if ( m_context == null )
+        {
             return;
         }
 
-        Activator.trace("BundleComponentActivator : Bundle ["
-            + m_context.getBundle().getBundleId() + "] will destroy "
-            + m_managers.size() + " instances", null);
+        // mark instance inactive (no more component activations)
+        m_active = false;
 
-        while (m_managers.size() !=0 )
+        log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [" + m_context.getBundle().getBundleId()
+            + "] will destroy " + m_managers.size() + " instances", null, null );
+
+        while ( m_managers.size() != 0 )
         {
-            ComponentManager manager = (ComponentManager) m_managers.get(0);
+            ComponentManager manager = ( ComponentManager ) m_managers.get( 0 );
             try
             {
-                m_managers.remove(manager);
+                m_managers.remove( manager );
                 manager.dispose();
             }
-            catch(Exception e)
+            catch ( Exception e )
             {
-                Activator.exception("BundleComponentActivator : Exception invalidating",
-                    manager.getComponentMetadata(), e);
+                log( LogService.LOG_ERROR, "BundleComponentActivator : Exception invalidating", manager
+                    .getComponentMetadata(), e );
             }
             finally
             {
                 m_componentRegistry.unregisterComponent( manager.getComponentMetadata().getName() );
             }
-            
+
         }
 
         // close the Configuration Admin tracker
-        if (m_configurationAdmin != null) {
+        if ( m_configurationAdmin != null )
+        {
             m_configurationAdmin.close();
         }
-        
-        Activator.trace("BundleComponentActivator : Bundle ["
-            + m_context.getBundle().getBundleId() + "] STOPPED", null);
+
+        log( LogService.LOG_DEBUG, "BundleComponentActivator : Bundle [" + m_context.getBundle().getBundleId()
+            + "] STOPPED", null, null );
 
         m_context = null;
     }
 
-   /**
-    * Returns the list of instance references currently associated to this activator
-    *
-    * @return the list of instance references
-    */
+
+    /**
+     * Returns <true> if this instance is active, that is if components may be
+     * activated for this component. As soon as the {@link #dispose()} is called
+     * which means this instance is being shutdown. After the call to <code>dispose</code>
+     * this method always returns <code>false</code>.
+     */
+    boolean isActive()
+    {
+        return m_active;
+    }
+
+
+    /**
+     * Returns the list of instance references currently associated to this activator
+     *
+     * @return the list of instance references
+     */
     protected List getInstanceReferences()
     {
         return m_managers;
     }
 
+
     /**
     * Returns the BundleContext
     *
@@ -271,16 +315,19 @@
         return m_context;
     }
 
+
     /**
      * Returns the <code>ConfigurationAdmin</code> service used to retrieve
      * configuration data for components managed by this activator or
      * <code>null</code> if no Configuration Admin Service is available in the
      * framework.
      */
-    protected ConfigurationAdmin getConfigurationAdmin() {
-        return (ConfigurationAdmin) m_configurationAdmin.getService();
+    protected ConfigurationAdmin getConfigurationAdmin()
+    {
+        return ( ConfigurationAdmin ) m_configurationAdmin.getService();
     }
-    
+
+
     /**
      * Implements the <code>ComponentContext.enableComponent(String)</code>
      * method by first finding the component(s) for the <code>name</code> and
@@ -292,10 +339,10 @@
      * @param name The name of the component to enable or <code>null</code> to
      *      enable all components.
      */
-    void enableComponent(String name)
+    void enableComponent( String name )
     {
-        final ComponentManager[] cm = getSelectedComponents(name);
-        if (cm == null)
+        final ComponentManager[] cm = getSelectedComponents( name );
+        if ( cm == null )
         {
             return;
         }
@@ -308,11 +355,12 @@
             }
             catch ( Throwable t )
             {
-                Activator.exception( "Cannot enable component", cm[i].getComponentMetadata(), t );
+                log( LogService.LOG_ERROR, "Cannot enable component", cm[i].getComponentMetadata(), t );
             }
         }
     }
-    
+
+
     /**
      * Implements the <code>ComponentContext.disableComponent(String)</code>
      * method by first finding the component(s) for the <code>name</code> and
@@ -324,14 +372,14 @@
      * @param name The name of the component to disable or <code>null</code> to
      *      disable all components.
      */
-    void disableComponent(String name)
+    void disableComponent( String name )
     {
-        final ComponentManager[] cm = getSelectedComponents(name);
-        if (cm == null)
+        final ComponentManager[] cm = getSelectedComponents( name );
+        if ( cm == null )
         {
             return;
         }
-        
+
         for ( int i = 0; i < cm.length; i++ )
         {
             try
@@ -340,11 +388,12 @@
             }
             catch ( Throwable t )
             {
-                Activator.exception( "Cannot disable component", cm[i].getComponentMetadata(), t );
+                log( LogService.LOG_ERROR, "Cannot disable component", cm[i].getComponentMetadata(), t );
             }
         }
     }
-    
+
+
     /**
      * Returns an array of {@link ComponentManager} instances which match the
      * <code>name</code>. If the <code>name</code> is <code>null</code> an
@@ -360,58 +409,104 @@
      *      to the <code>name</code> parameter or <code>null</code> if no
      *      component manager with the given name is currently registered.
      */
-    private ComponentManager[] getSelectedComponents(String name) {
+    private ComponentManager[] getSelectedComponents( String name )
+    {
         // if all components are selected
-        if (name == null)
+        if ( name == null )
         {
-            return (ComponentManager[]) m_managers.toArray(new ComponentManager[m_managers.size()]);
+            return ( ComponentManager[] ) m_managers.toArray( new ComponentManager[m_managers.size()] );
         }
-        
+
         if ( m_componentRegistry.getComponent( name ) != null )
         {
             // otherwise just find it
             Iterator it = m_managers.iterator();
-            while (it.hasNext())
+            while ( it.hasNext() )
             {
-                ComponentManager cm = (ComponentManager) it.next();
-                if (name.equals(cm.getComponentMetadata().getName())) {
-                    return new ComponentManager[]{ cm  };
+                ComponentManager cm = ( ComponentManager ) it.next();
+                if ( name.equals( cm.getComponentMetadata().getName() ) )
+                {
+                    return new ComponentManager[]
+                        { cm };
                 }
             }
         }
-        
+
         // if the component is not known
         return null;
     }
 
+
     //---------- Asynchronous Component Handling ------------------------------
 
     /**
      * Schedules the given <code>task</code> for asynchrounous execution or
-     * synchronously runs the task if the thread is not running.
+     * synchronously runs the task if the thread is not running. If this instance
+     * is {@link #isActive() not active}, the task is not executed.
      * 
      * @param task The component task to execute
      */
     void schedule( Runnable task )
     {
-        ComponentActorThread cat = m_componentActor;
-        if ( cat != null )
+        if ( isActive() )
         {
-            cat.schedule( task );
+            ComponentActorThread cat = m_componentActor;
+            if ( cat != null )
+            {
+                cat.schedule( task );
+            }
+            else
+            {
+                log( LogService.LOG_INFO, "Component Actor Thread not running, calling synchronously", null, null );
+                try
+                {
+                    synchronized ( this )
+                    {
+                        task.run();
+                    }
+                }
+                catch ( Throwable t )
+                {
+                    log( LogService.LOG_INFO, "Unexpected problem executing task", null, t );
+                }
+            }
         }
         else
         {
-            Activator.log( LogService.LOG_INFO, "Component Actor Thread not running, calling synchronously", null );
-            try
+            log( LogService.LOG_INFO, "BundleComponentActivator is not active; not scheduling " + task, null, null );
+        }
+    }
+
+
+    /**
+     * Method to actually emit the log message. If the LogService is available,
+     * the message will be logged through the LogService. Otherwise the message
+     * is logged to stdout (or stderr in case of LOG_ERROR level messages),
+     * 
+     * @param level The log level to log the message at
+     * @param message The message to log
+     * @param ex An optional <code>Throwable</code> whose stack trace is written,
+     *      or <code>null</code> to not log a stack trace.
+     */
+    void log( int level, String message, ComponentMetadata metadata, Throwable ex )
+    {
+
+        if ( m_logLevel >= level )
+        {
+            // prepend the metadata name to the message
+            if ( metadata != null )
             {
-                synchronized ( this )
-                {
-                    task.run();
-                }
+                message = "[" + metadata.getName() + "] " + message;
             }
-            catch ( Throwable t )
+
+            Object logger = m_logService.getService();
+            if ( logger == null )
             {
-                Activator.log( LogService.LOG_INFO, "Unexpected problem executing task", t );
+                Activator.log( level, getBundleContext().getBundle(), message, ex );
+            }
+            else
+            {
+                ( ( LogService ) logger ).log( level, message, ex );
             }
         }
     }
diff --git a/scr/src/main/java/org/apache/felix/scr/ComponentActorThread.java b/scr/src/main/java/org/apache/felix/scr/ComponentActorThread.java
index e11b501..5c7a4d9 100644
--- a/scr/src/main/java/org/apache/felix/scr/ComponentActorThread.java
+++ b/scr/src/main/java/org/apache/felix/scr/ComponentActorThread.java
@@ -21,6 +21,8 @@
 
 import java.util.LinkedList;
 
+import org.osgi.service.log.LogService;
+
 
 /**
  * The <code>ComponentActorThread</code> is the thread used to act upon registered
@@ -72,17 +74,19 @@
             // return if the task is this thread itself
             if ( task == this )
             {
+                Activator.log( LogService.LOG_DEBUG, null, "Shutting down ComponentActorThread", null );
                 return;
             }
 
             // otherwise execute the task, log any issues
             try
             {
+                Activator.log( LogService.LOG_DEBUG, null, "Running task [" + task + "]", null );
                 task.run();
             }
             catch ( Throwable t )
             {
-                Activator.exception( "Unexpected problem executing task", null, t );
+                Activator.log( LogService.LOG_ERROR, null, "Unexpected problem executing task", t );
             }
         }
     }
@@ -104,6 +108,9 @@
             // append to the task queue
             tasks.add( task );
 
+            Activator.log( LogService.LOG_DEBUG, null, "Adding task [" + task + "] as #" + tasks.size()
+                + " in the queue", null );
+            
             // notify the waiting thread
             tasks.notifyAll();
         }
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 c18143c..1851ecd 100644
--- a/scr/src/main/java/org/apache/felix/scr/ComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/ComponentFactoryImpl.java
@@ -31,6 +31,9 @@
 import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.component.ComponentFactory;
 import org.osgi.service.component.ComponentInstance;
+import org.osgi.service.log.LogService;
+
+import sun.security.action.GetBooleanAction;
 
 
 /**
@@ -87,7 +90,7 @@
 
     protected ServiceRegistration registerComponentService()
     {
-        Activator.trace( "registering component factory", getComponentMetadata() );
+        getActivator().log( LogService.LOG_DEBUG, "registering component factory", getComponentMetadata(), null );
 
         Dictionary serviceProperties = getProperties();
         return getActivator().getBundleContext().registerService( new String[]
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 c4c3ad9..d239315 100644
--- a/scr/src/main/java/org/apache/felix/scr/DelayedComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/DelayedComponentManager.java
@@ -22,6 +22,7 @@
 import org.osgi.framework.Bundle;
 import org.osgi.framework.ServiceFactory;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.log.LogService;
 
 
 /**
@@ -72,7 +73,9 @@
 
     public Object getService( Bundle arg0, ServiceRegistration arg1 )
     {
-        Activator.trace( "DelayedComponentServiceFactory.getService()", getComponentMetadata() );
+        getActivator().log( LogService.LOG_DEBUG, "DelayedComponentServiceFactory.getService()",
+            getComponentMetadata(), null );
+        
         // When the getServiceMethod is called, the implementation object must be created
         // unless another bundle has already retrievd it
 
@@ -83,10 +86,7 @@
             // if component creation failed, we were deactivated and the state
             // is not REGISTERED any more. Otherwise go to standard ACTIVE
             // state now
-            if ( getState() == STATE_REGISTERED )
-            {
-                setState( STATE_ACTIVE );
-            }
+            setStateConditional( STATE_REGISTERED, STATE_ACTIVE );
         }
 
         return getInstance();
diff --git a/scr/src/main/java/org/apache/felix/scr/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/DependencyManager.java
index a3c165d..26dfff0 100644
--- a/scr/src/main/java/org/apache/felix/scr/DependencyManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/DependencyManager.java
@@ -32,6 +32,7 @@
 import org.osgi.framework.ServiceEvent;
 import org.osgi.framework.ServiceListener;
 import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
 
 
 /**
@@ -289,8 +290,9 @@
                 if ( retval == false && ( max == 1 ) )
                 {
                     // There was an exception when calling the bind method
-                    Activator.error( "Dependency Manager: Possible exception in the bind method during initialize()",
-                        m_componentManager.getComponentMetadata() );
+                    m_componentManager.getActivator().log( LogService.LOG_ERROR,
+                        "Dependency Manager: Possible exception in the bind method during initialize()",
+                        m_componentManager.getComponentMetadata(), null );
                     return false;
                 }
             }
@@ -425,8 +427,9 @@
             }
             catch ( ClassNotFoundException ex2 )
             {
-                Activator.exception( "Cannot load class used as parameter " + parameterClassName, m_componentManager
-                    .getComponentMetadata(), ex2 );
+                m_componentManager.getActivator().log( LogService.LOG_ERROR,
+                    "Cannot load class used as parameter " + parameterClassName,
+                    m_componentManager.getComponentMetadata(), ex2 );
             }
         }
 
@@ -457,18 +460,18 @@
             try
             {
                 // Get the bind method
-                Activator.trace( "getting bind: " + m_dependencyMetadata.getBind(), m_componentManager
-                    .getComponentMetadata() );
+                m_componentManager.getActivator().log( LogService.LOG_DEBUG,
+                    "getting bind: " + m_dependencyMetadata.getBind(), m_componentManager.getComponentMetadata(), null );
                 Method bindMethod = getBindingMethod( m_dependencyMetadata.getBind(), implementationObject.getClass(),
                     m_dependencyMetadata.getInterface() );
 
                 if ( bindMethod == null )
                 {
                     // 112.3.1 If the method is not found , SCR must log an
-                    // error
-                    // message with the log service, if present, and ignore the
-                    // method
-                    Activator.error( "bind() method not found", m_componentManager.getComponentMetadata() );
+                    // error message with the log service, if present, and
+                    // ignore the method
+                    m_componentManager.getActivator().log( LogService.LOG_ERROR, "bind() method not found",
+                        m_componentManager.getComponentMetadata(), null );
                     return false;
                 }
 
@@ -488,7 +491,8 @@
                 bindMethod.invoke( implementationObject, new Object[]
                     { parameter } );
 
-                Activator.trace( "bound: " + getName(), m_componentManager.getComponentMetadata() );
+                m_componentManager.getActivator().log( LogService.LOG_DEBUG, "bound: " + getName(),
+                    m_componentManager.getComponentMetadata(), null );
 
                 return true;
             }
@@ -498,13 +502,15 @@
                 // public, SCR must log an error
                 // message with the log service, if present, and ignore the
                 // method
-                Activator.exception( "bind() method cannot be called", m_componentManager.getComponentMetadata(), ex );
+                m_componentManager.getActivator().log( LogService.LOG_ERROR, "bind() method cannot be called",
+                    m_componentManager.getComponentMetadata(), ex );
                 return false;
             }
             catch ( InvocationTargetException ex )
             {
-                Activator.exception( "DependencyManager : exception while invoking " + m_dependencyMetadata.getBind()
-                    + "()", m_componentManager.getComponentMetadata(), ex );
+                m_componentManager.getActivator().log( LogService.LOG_ERROR,
+                    "DependencyManager : exception while invoking " + m_dependencyMetadata.getBind() + "()",
+                    m_componentManager.getComponentMetadata(), ex );
                 return false;
             }
         }
@@ -537,8 +543,9 @@
         {
             try
             {
-                Activator.trace( "getting unbind: " + m_dependencyMetadata.getUnbind(), m_componentManager
-                    .getComponentMetadata() );
+                m_componentManager.getActivator().log( LogService.LOG_DEBUG,
+                    "getting unbind: " + m_dependencyMetadata.getUnbind(), m_componentManager.getComponentMetadata(),
+                    null );
                 Method unbindMethod = getBindingMethod( m_dependencyMetadata.getUnbind(), implementationObject
                     .getClass(), m_dependencyMetadata.getInterface() );
 
@@ -561,14 +568,16 @@
                     // error
                     // message with the log service, if present, and ignore the
                     // method
-                    Activator.error( "unbind() method not found", m_componentManager.getComponentMetadata() );
+                    m_componentManager.getActivator().log( LogService.LOG_ERROR, "unbind() method not found",
+                        m_componentManager.getComponentMetadata(), null );
                     return false;
                 }
 
                 unbindMethod.invoke( implementationObject, new Object[]
                     { parameter } );
 
-                Activator.trace( "unbound: " + getName(), m_componentManager.getComponentMetadata() );
+                m_componentManager.getActivator().log( LogService.LOG_DEBUG, "unbound: " + getName(),
+                    m_componentManager.getComponentMetadata(), null );
 
                 return true;
             }
@@ -578,13 +587,15 @@
                 // public, SCR must log an error
                 // message with the log service, if present, and ignore the
                 // method
-                Activator.exception( "unbind() method cannot be called", m_componentManager.getComponentMetadata(), ex );
+                m_componentManager.getActivator().log( LogService.LOG_ERROR, "unbind() method cannot be called",
+                    m_componentManager.getComponentMetadata(), ex );
                 return false;
             }
             catch ( InvocationTargetException ex )
             {
-                Activator.exception( "DependencyManager : exception while invoking " + m_dependencyMetadata.getUnbind()
-                    + "()", m_componentManager.getComponentMetadata(), ex );
+                m_componentManager.getActivator().log( LogService.LOG_ERROR,
+                    "DependencyManager : exception while invoking " + m_dependencyMetadata.getUnbind() + "()",
+                    m_componentManager.getComponentMetadata(), ex.getCause() );
                 return false;
             }
 
@@ -667,14 +678,17 @@
                 // setStateDependency(DependencyChangeEvent.DEPENDENCY_INVALID);
                 try
                 {
-                    Activator.trace( "Dependency Manager: Static dependency is broken", m_componentManager
-                        .getComponentMetadata() );
+                    m_componentManager.getActivator().log(
+                        LogService.LOG_DEBUG,
+                        "Dependency Manager: Static dependency on " + m_dependencyMetadata.getName() + "/"
+                            + m_dependencyMetadata.getInterface() + " is broken",
+                        m_componentManager.getComponentMetadata(), null );
                     m_componentManager.reactivate();
                 }
                 catch ( Exception ex )
                 {
-                    Activator.exception( "Exception while recreating dependency ", m_componentManager
-                        .getComponentMetadata(), ex );
+                    m_componentManager.getActivator().log( LogService.LOG_ERROR,
+                        "Exception while recreating dependency ", m_componentManager.getComponentMetadata(), ex );
                 }
             }
             // dynamic dependency
@@ -702,11 +716,13 @@
                     {
                         if ( !m_dependencyMetadata.isOptional() )
                         {
-                            Activator
-                                .trace(
-                                    "Dependency Manager: Mandatory dependency not fullfilled and no replacements available... unregistering service...",
-                                    m_componentManager.getComponentMetadata() );
-                            m_componentManager.reactivate();
+                            m_componentManager.getActivator().log(
+                                LogService.LOG_DEBUG,
+                                "Dependency Manager: Deactivating component due to mandatory dependency on "
+                                    + m_dependencyMetadata.getName() + "/" + m_dependencyMetadata.getInterface()
+                                    + " not fullfilled and no replacement(s) available",
+                                m_componentManager.getComponentMetadata(), null );
+                            m_componentManager.deactivate();
                         }
                     }
                 }
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 14decb8..1311cdd 100644
--- a/scr/src/main/java/org/apache/felix/scr/ImmediateComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/ImmediateComponentManager.java
@@ -29,6 +29,7 @@
 import org.osgi.service.cm.ConfigurationAdmin;
 import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.component.ComponentContext;
+import org.osgi.service.log.LogService;
 
 
 /**
@@ -134,7 +135,8 @@
         catch ( Exception ex )
         {
             // failed to instantiate, return null
-            Activator.exception( "Error during instantiation of the implementation object", getComponentMetadata(), ex );
+            getActivator().log( LogService.LOG_ERROR, "Error during instantiation of the implementation object",
+                getComponentMetadata(), ex );
             return null;
         }
 
@@ -148,8 +150,9 @@
             DependencyManager dm = ( DependencyManager ) it.next();
             if ( !dm.bind( implementationObject ) )
             {
-                Activator.error( "Cannot create component instance due to failure to bind reference " + dm.getName(),
-                    getComponentMetadata() );
+                getActivator().log( LogService.LOG_ERROR,
+                    "Cannot create component instance due to failure to bind reference " + dm.getName(),
+                    getComponentMetadata(), null );
 
                 // make sure, we keep no bindings
                 it = getDependencyManagers();
@@ -175,18 +178,21 @@
         catch ( NoSuchMethodException ex )
         {
             // We can safely ignore this one
-            Activator.trace( "activate() method is not implemented", getComponentMetadata() );
+            getActivator().log( LogService.LOG_DEBUG, "activate() method is not implemented", getComponentMetadata(),
+                null );
         }
         catch ( IllegalAccessException ex )
         {
             // Ignored, but should it be logged?
-            Activator.trace( "activate() method cannot be called", getComponentMetadata() );
+            getActivator().log( LogService.LOG_DEBUG, "activate() method cannot be called", getComponentMetadata(),
+                null );
         }
         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 and activation fails
-            Activator.exception( "The activate method has thrown an exception", getComponentMetadata(), ex );
+            getActivator().log( LogService.LOG_ERROR, "The activate method has thrown an exception",
+                getComponentMetadata(), ex.getCause() );
 
             // make sure, we keep no bindings
             it = getDependencyManagers();
@@ -217,18 +223,21 @@
         catch ( NoSuchMethodException ex )
         {
             // We can safely ignore this one
-            Activator.trace( "deactivate() method is not implemented", getComponentMetadata() );
+            getActivator().log( LogService.LOG_DEBUG, "deactivate() method is not implemented", getComponentMetadata(),
+                null );
         }
         catch ( IllegalAccessException ex )
         {
             // Ignored, but should it be logged?
-            Activator.trace( "deactivate() method cannot be called", getComponentMetadata() );
+            getActivator().log( LogService.LOG_DEBUG, "deactivate() method cannot be called", getComponentMetadata(),
+                null );
         }
         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", getComponentMetadata(), ex );
+            getActivator().log( LogService.LOG_ERROR, "The deactivate method has thrown an exception",
+                getComponentMetadata(), ex.getCause() );
         }
 
         // 2. Unbind any bound services
@@ -299,7 +308,8 @@
                 }
                 catch ( IOException ioe )
                 {
-                    Activator.exception( "Problem getting Configuration", getComponentMetadata(), ioe );
+                    getActivator().log( LogService.LOG_ERROR, "Problem getting Configuration", getComponentMetadata(),
+                        ioe );
                 }
             }
 
diff --git a/scr/src/main/java/org/apache/felix/scr/ManagerFactory.java b/scr/src/main/java/org/apache/felix/scr/ManagerFactory.java
index f326a0f..21b204b 100644
--- a/scr/src/main/java/org/apache/felix/scr/ManagerFactory.java
+++ b/scr/src/main/java/org/apache/felix/scr/ManagerFactory.java
@@ -18,6 +18,8 @@
  */

 package org.apache.felix.scr;

 

+import org.osgi.service.log.LogService;

+

 

 /**

  * This factory allows other types of ComponentManagers to be provided.

@@ -30,7 +32,7 @@
     static ComponentManager createManager( BundleComponentActivator activator, ComponentMetadata metadata,

         long componentId )

     {

-        Activator.trace( "ManagerFactory.createManager", metadata );

+        activator.log( LogService.LOG_DEBUG, "ManagerFactory.createManager", metadata, null );

         if ( metadata.isImmediate() )

         {

             return new ImmediateComponentManager( activator, metadata, componentId );

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 2d870a6..49921ee 100644
--- a/scr/src/main/java/org/apache/felix/scr/ServiceFactoryComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/ServiceFactoryComponentManager.java
@@ -26,6 +26,7 @@
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.ComponentInstance;
+import org.osgi.service.log.LogService;
 
 
 /**
@@ -91,7 +92,9 @@
      */
     public Object getService( Bundle bundle, ServiceRegistration registration )
     {
-        Activator.trace( "DelayedServiceFactoryServiceFactory.getService()", getComponentMetadata() );
+        getActivator().log( LogService.LOG_DEBUG, "DelayedServiceFactoryServiceFactory.getService()",
+            getComponentMetadata(), null );
+
         // When the getServiceMethod is called, the implementation object must be created
 
         // private ComponentContext and implementation instances
@@ -105,10 +108,7 @@
             serviceContexts.put( service, serviceContext );
 
             // if this is the first use of this component, switch to ACTIVE state
-            if ( getState() == STATE_REGISTERED )
-            {
-                setState( STATE_ACTIVE );
-            }
+            setStateConditional( STATE_REGISTERED, STATE_ACTIVE );
         }
 
         return service;
@@ -120,7 +120,9 @@
      */
     public void ungetService( Bundle bundle, ServiceRegistration registration, Object service )
     {
-        Activator.trace( "DelayedServiceFactoryServiceFactory.ungetService()", getComponentMetadata() );
+        getActivator().log( LogService.LOG_DEBUG, "DelayedServiceFactoryServiceFactory.ungetService()",
+            getComponentMetadata(), null );
+
         // When the ungetServiceMethod is called, the implementation object must be deactivated
 
         // private ComponentContext and implementation instances
@@ -128,9 +130,9 @@
         disposeImplementationObject( service, serviceContext );
 
         // if this was the last use of the component, go back to REGISTERED state
-        if ( serviceContexts.isEmpty() && getState() == STATE_ACTIVE )
+        if ( serviceContexts.isEmpty() )
         {
-            setState( STATE_REGISTERED );
+            setStateConditional( STATE_ACTIVE, STATE_REGISTERED );
         }
     }