FELIX-2368 make component enablement, activation, deactivation, and disablement synchronous instead of asynchronous

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@949317 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
index 2d6df6a..31de35e 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
@@ -384,7 +384,7 @@
      * @param name The name of the component to enable or <code>null</code> to
      *      enable all components.
      */
-    public void enableComponent( String name )
+    public void enableComponent( final String name )
     {
         final ComponentHolder[] holder = getSelectedComponents( name );
         if ( holder == null )
@@ -392,17 +392,35 @@
             return;
         }
 
-        for ( int i = 0; i < holder.length; i++ )
+		// FELIX-2368; schedule for asynchronous enablement. According to
+        //    112.5.1 the enabled state should be changed immediately but
+        //    the component(s) should be activated asynchronously. Since
+        //    we do not really handle the enabled state separately we
+        //    schedule enablement and activation for asynchronous execution.
+        schedule( new Runnable()
         {
-            try
+            public void run()
             {
-                holder[i].enableComponents();
+                for ( int i = 0; i < holder.length; i++ )
+                {
+                    try
+                    {
+                        log( LogService.LOG_DEBUG, "Enabling Component", holder[i].getComponentMetadata(), null );
+                        holder[i].enableComponents();
+                    }
+                    catch ( Throwable t )
+                    {
+                        log( LogService.LOG_ERROR, "Cannot enable component", holder[i].getComponentMetadata(), t );
+                    }
+                }
             }
-            catch ( Throwable t )
+
+
+            public String toString()
             {
-                log( LogService.LOG_ERROR, "Cannot enable component", holder[i].getComponentMetadata(), t );
+                return "enableComponent(" + name + ")";
             }
-        }
+        } );
     }
 
 
@@ -417,7 +435,7 @@
      * @param name The name of the component to disable or <code>null</code> to
      *      disable all components.
      */
-    public void disableComponent( String name )
+    public void disableComponent( final String name )
     {
         final ComponentHolder[] holder = getSelectedComponents( name );
         if ( holder == null )
@@ -425,18 +443,35 @@
             return;
         }
 
-        for ( int i = 0; i < holder.length; i++ )
+        // FELIX-2368; schedule for asynchronous enablement. According to
+        //    112.5.1 the enabled state should be changed immediately but
+        //    the component(s) should be deactivated asynchronously. Since
+        //    we do not really handle the enabled state separately we
+        //    schedule disablement and deactivation for asynchronous execution.
+        schedule( new Runnable()
         {
-            try
+            public void run()
             {
-                log( LogService.LOG_DEBUG, "Disabling Component", holder[i].getComponentMetadata(), null );
-                holder[i].disableComponents();
+                for ( int i = 0; i < holder.length; i++ )
+                {
+                    try
+                    {
+                        log( LogService.LOG_DEBUG, "Disabling Component", holder[i].getComponentMetadata(), null );
+                        holder[i].disableComponents();
+                    }
+                    catch ( Throwable t )
+                    {
+                        log( LogService.LOG_ERROR, "Cannot disable component", holder[i].getComponentMetadata(), t );
+                    }
+                }
             }
-            catch ( Throwable t )
+
+
+            public String toString()
             {
-                log( LogService.LOG_ERROR, "Cannot disable component", holder[i].getComponentMetadata(), t );
+                return "disableComponent(" + name + ")";
             }
-        }
+        } );
     }
 
 
@@ -502,7 +537,7 @@
      *
      * @param task The component task to execute
      */
-    public void schedule( ComponentActivatorTask task )
+    public void schedule( Runnable task )
     {
         if ( isActive() )
         {
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ComponentActivatorTask.java b/scr/src/main/java/org/apache/felix/scr/impl/ComponentActivatorTask.java
deleted file mode 100644
index 25ec938..0000000
--- a/scr/src/main/java/org/apache/felix/scr/impl/ComponentActivatorTask.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.scr.impl;
-
-
-import org.apache.felix.scr.Component;
-import org.apache.felix.scr.impl.manager.AbstractComponentManager;
-import org.osgi.service.log.LogService;
-
-
-/**
- * The <code>ComponentActivatorTask</code> extends the <code>Runnable</code>
- * interface with the functionality to have a meaningful {@link #toString()}
- * implementation. This is mainly used when logging something around the task
- * being run or scheduled.
- */
-public abstract class ComponentActivatorTask implements Runnable
-{
-
-    private final String taskName;
-    private final AbstractComponentManager component;
-
-
-    protected ComponentActivatorTask( String taskName, AbstractComponentManager component )
-    {
-        this.taskName = taskName;
-        this.component = component;
-    }
-
-
-    protected abstract void doRun();
-
-
-    public void run()
-    {
-        // fail, if the bundle is not active
-        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 disposed", null );
-        }
-        else if ( !ComponentRegistry.isBundleActive( component.getBundle() ) )
-        {
-            Activator.log( LogService.LOG_WARNING, component.getBundle(), "Cannot run task '" + this
-                + "': Declaring bundle is not active", null );
-        }
-        else
-        {
-            doRun();
-        }
-    }
-
-
-    public String toString()
-    {
-        return taskName + " " + component;
-    }
-}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
index bab62cf..3a33e50 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
@@ -30,7 +30,6 @@
 import org.apache.felix.scr.Component;
 import org.apache.felix.scr.Reference;
 import org.apache.felix.scr.impl.BundleComponentActivator;
-import org.apache.felix.scr.impl.ComponentActivatorTask;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
 import org.apache.felix.scr.impl.metadata.ServiceMetadata;
@@ -126,37 +125,24 @@
      * 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.
+     * This method enables and activates the component immediately.
      */
     public final void enable()
     {
         enableInternal();
-
-        getActivator().schedule( new ComponentActivatorTask( "Enable", this )
-        {
-            public void doRun()
-            {
-                activateInternal();
-            }
-        });
+        activateInternal();
     }
 
     /**
      * 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.
+     * This method deactivates and disables the component immediately.
      */
     public final void disable()
     {
-        getActivator().schedule( new ComponentActivatorTask( "Disable", this )
-        {
-            public void doRun()
-            {
-                deactivateInternal( ComponentConstants.DEACTIVATION_REASON_DISABLED );
-                disableInternal();
-            }
-        });
+        deactivateInternal( ComponentConstants.DEACTIVATION_REASON_DISABLED );
+        disableInternal();
     }
 
     /**
@@ -522,42 +508,6 @@
         }
     }
 
-    /**
-     * 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 )
-        {
-
-            public void doRun()
-            {
-                deactivateInternal( reason );
-                activateInternal();
-            }
-        } );
-    }
-
 
     public String toString()
     {
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
index 54c9b79..69290d4 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
@@ -203,7 +203,8 @@
                                     "Dependency Manager: Service {0} registered, activate component", new Object[]
                                         { m_dependencyMetadata.getName() }, null );
 
-                                m_componentManager.activate();
+                                // immediately try to activate the component (FELIX-2368)
+                                m_componentManager.activateInternal();
                             }
                         }
                         else if ( isMultiple() )
@@ -278,7 +279,8 @@
                 "Dependency Manager: Service {0} registered, activate component", new Object[]
                     { m_dependencyMetadata.getName() }, null );
 
-            m_componentManager.activate();
+            // immediately try to activate the component (FELIX-2368)
+            m_componentManager.activateInternal();
         }
 
         // otherwise check whether the component is in a state to handle the event
@@ -365,7 +367,8 @@
                         "Dependency Manager: Static dependency on {0}/{1} is broken", new Object[]
                             { m_dependencyMetadata.getName(), m_dependencyMetadata.getInterface() }, null );
                     m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE );
-                    m_componentManager.activate();
+                    // FELIX-2368: immediately try to reactivate
+                    m_componentManager.activateInternal();
                 }
                 catch ( Exception ex )
                 {
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
index e6cd76b..68ec203 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ImmediateComponentManager.java
@@ -404,7 +404,12 @@
             log( LogService.LOG_DEBUG, "Deactivating and Activating to reconfigure from configuration", null );
             int reason = ( configuration == null ) ? ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_DELETED
                 : ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_MODIFIED;
-            reactivate( reason );
+
+            // FELIX-2368: cycle component immediately, reconfigure() is
+            //     called through ConfigurationListener API which itself is
+            //     called asynchronously by the Configuration Admin Service
+            deactivateInternal( reason );
+            activateInternal();
         }
     }