You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by fm...@apache.org on 2009/07/09 14:26:59 UTC

svn commit: r792527 - in /felix/trunk/scr/src: main/java/org/apache/felix/scr/impl/ test/java/org/apache/felix/scr/impl/

Author: fmeschbe
Date: Thu Jul  9 12:26:58 2009
New Revision: 792527

URL: http://svn.apache.org/viewvc?rev=792527&view=rev
Log:
FELIX-925 Add support for new activate/deactivate method signatures and
for the deactivation reason

Modified:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/AbstractComponentManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentFactoryImpl.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/DelayedComponentManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/DependencyManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ImmediateComponentManager.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ReflectionHelper.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ServiceFactoryComponentManager.java
    felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/ReflectionHelperTest.java

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/AbstractComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/AbstractComponentManager.java?rev=792527&r1=792526&r2=792527&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/AbstractComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/AbstractComponentManager.java Thu Jul  9 12:26:58 2009
@@ -31,6 +31,7 @@
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.component.ComponentInstance;
 import org.osgi.service.log.LogService;
 
@@ -133,11 +134,10 @@
                     acm.getComponentMetadata(), null);
         }
 
-        void deactivateInternal( AbstractComponentManager acm )
+        void deactivateInternal( AbstractComponentManager acm, int reason )
         {
-            acm.log( LogService.LOG_DEBUG,
-                    "Current state: " + m_name + ", Event: deactivate",
-                    acm.getComponentMetadata(), null );
+            acm.log( LogService.LOG_DEBUG, "Current state: " + m_name + ", Event: deactivate (reason: " + reason + ")",
+                acm.getComponentMetadata(), null );
         }
 
         void disposeInternal( AbstractComponentManager acm )
@@ -361,17 +361,26 @@
             return sr == null ? null : sr.getReference();
         }
 
-        void deactivateInternal( AbstractComponentManager acm )
+        void deactivateInternal( AbstractComponentManager acm, int reason )
         {
             acm.changeState(Deactivating.getInstance());
 
             ComponentMetadata componentMetadata = acm.getComponentMetadata();
             acm.log( LogService.LOG_DEBUG, "Deactivating component", componentMetadata, null );
 
-            acm.unregisterComponentService();
-            acm.deleteComponent();
-            acm.changeState( Unsatisfied.getInstance() );
+            // 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", componentMetadata, t );
+            }
 
+            acm.changeState( Unsatisfied.getInstance() );
             acm.log( LogService.LOG_DEBUG, "Component deactivated", componentMetadata, null );
         }
     }
@@ -398,7 +407,7 @@
             }
             else
             {
-                deactivateInternal( dcm );
+                deactivateInternal( dcm, ComponentConstants.DEACTIVATION_REASON_UNSPECIFIED );
                 return null;
             }
         }
@@ -496,12 +505,18 @@
         {
             public void doRun()
             {
-                deactivateInternal();
+                deactivateInternal( ComponentConstants.DEACTIVATION_REASON_DISABLED );
                 disableInternal();
             }
         });
     }
 
+    // implements the ComponentInstance.dispose() method
+    public void dispose()
+    {
+        dispose( ComponentConstants.DEACTIVATION_REASON_DISPOSED );
+    }
+
     /**
      * Disposes off this component deactivating and disabling it first as
      * required. After disposing off the component, it may not be used anymore.
@@ -511,9 +526,9 @@
      * method has to actually complete before other actions like bundle stopping
      * may continue.
      */
-    public void dispose()
+    public void dispose( int reason )
     {
-        disposeInternal();
+        disposeInternal( reason );
     }
 
     //---------- Component interface ------------------------------------------
@@ -604,14 +619,14 @@
         m_state.activateInternal( this );
     }
 
-    synchronized final void deactivateInternal()
+    synchronized final void deactivateInternal( int reason )
     {
-        m_state.deactivateInternal( this );
+        m_state.deactivateInternal( this, reason );
     }
 
-    synchronized final void disposeInternal()
+    synchronized final void disposeInternal( int reason )
     {
-        m_state.deactivateInternal( this );
+        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"
@@ -655,7 +670,7 @@
      */
     protected abstract boolean createComponent();
 
-    protected abstract void deleteComponent();
+    protected abstract void deleteComponent( int reason );
 
     /**
      * Returns the service object to be registered if the service element is
@@ -710,7 +725,7 @@
         m_serviceRegistration = registerService();
     }
 
-    protected void unregisterComponentService()
+    protected final void unregisterComponentService()
     {
 
         if ( m_serviceRegistration != null )
@@ -769,11 +784,10 @@
      * activation the new configuration data is retrieved from the Configuration
      * Admin Service.
      */
-    public final void reconfigure()
+    public final void reconfigure( final int reason )
     {
-        log( LogService.LOG_DEBUG, "Deactivating and Activating to reconfigure",
-                m_componentMetadata, null );
-        reactivate();
+        log( LogService.LOG_DEBUG, "Deactivating and Activating to reconfigure", m_componentMetadata, null );
+        reactivate( reason );
     }
 
     /**
@@ -783,16 +797,17 @@
      * This method schedules the deactivation and reactivation for asynchronous
      * execution.
      */
-    public final void reactivate()
+    public final void reactivate( final int reason )
     {
-        getActivator().schedule(new ComponentActivatorTask( "Reactivate", this ) {
+        getActivator().schedule( new ComponentActivatorTask( "Reactivate", this )
+        {
 
             public void doRun()
             {
-                deactivateInternal();
+                deactivateInternal( reason );
                 activateInternal();
             }
-        });
+        } );
     }
 
     public String toString() {

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java?rev=792527&r1=792526&r2=792527&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java Thu Jul  9 12:26:58 2009
@@ -32,6 +32,7 @@
 import org.osgi.framework.BundleEvent;
 import org.osgi.framework.Constants;
 import org.osgi.framework.SynchronousBundleListener;
+import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.log.LogService;
 import org.osgi.util.tracker.ServiceTracker;
 
@@ -261,7 +262,7 @@
         {
             try
             {
-                ga.dispose();
+                ga.dispose( ComponentConstants.DEACTIVATION_REASON_BUNDLE_STOPPED );
             }
             catch ( Exception e )
             {
@@ -280,7 +281,7 @@
             BundleComponentActivator ga = ( BundleComponentActivator ) it.next();
             try
             {
-                ga.dispose();
+                ga.dispose( ComponentConstants.DEACTIVATION_REASON_DISPOSED );
             }
             catch ( Exception e )
             {

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java?rev=792527&r1=792526&r2=792527&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/BundleComponentActivator.java Thu Jul  9 12:26:58 2009
@@ -252,7 +252,7 @@
     * Dispose of this component activator instance and all the component
     * managers.
     */
-    void dispose()
+    void dispose( int reason )
     {
         if ( m_context == null )
         {
@@ -271,7 +271,7 @@
             try
             {
                 m_managers.remove( manager );
-                manager.dispose();
+                manager.dispose( reason );
             }
             catch ( Exception e )
             {
@@ -337,7 +337,7 @@
      * configuration data for components managed by this activator or
      * <code>null</code> if no Configuration Admin Service is available in the
      * framework.
-	 */
+     */
     protected ConfigurationAdmin getConfigurationAdmin()
     {
         return ( ConfigurationAdmin ) m_configurationAdmin.getService();

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentFactoryImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentFactoryImpl.java?rev=792527&r1=792526&r2=792527&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentFactoryImpl.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentFactoryImpl.java Thu Jul  9 12:26:58 2009
@@ -48,7 +48,7 @@
 
     // Actually we only use the identity key stuff, but there is
     // no IdentityHashSet and HashSet internally uses a HashMap anyway
-    private Map m_createdComponents;
+    private final Map m_createdComponents;
 
 
     ComponentFactoryImpl( BundleComponentActivator activator, ComponentMetadata metadata,
@@ -76,9 +76,14 @@
     }
 
 
-    protected void deleteComponent()
+    protected void deleteComponent( int reason )
     {
-        // nothing to delete
+        // though we have nothing to delete really, we have to remove all
+        // references to the components created for configuration
+        m_createdComponents.clear();
+        if (m_configuredServices != null) {
+            m_configuredServices = null;
+        }
     }
 
 
@@ -178,7 +183,7 @@
                 log( LogService.LOG_DEBUG, "Disposing component after configuration deletion", getComponentMetadata(),
                         null );
 
-                disposeComponentManager( cm );
+                disposeComponentManager( cm, ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_DELETED );
             }
         }
 
@@ -239,7 +244,7 @@
         return cm;
     }
 
-    private void disposeComponentManager( ImmediateComponentManager cm )
+    private void disposeComponentManager( ImmediateComponentManager cm, int reason )
     {
         // remove from created components
         m_createdComponents.remove( cm );
@@ -248,6 +253,6 @@
         getActivator().getInstanceReferences().remove( cm );
 
         // finally dispose it
-        cm.dispose();
+        cm.dispose( reason );
     }
 }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java?rev=792527&r1=792526&r2=792527&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java Thu Jul  9 12:26:58 2009
@@ -155,7 +155,7 @@
         {
             cm = getComponent( factoryPid );
         }
-        
+
         if (cm == null) {
             // this configuration is not for a SCR component
             return;

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/DelayedComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/DelayedComponentManager.java?rev=792527&r1=792526&r2=792527&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/DelayedComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/DelayedComponentManager.java Thu Jul  9 12:26:58 2009
@@ -50,12 +50,12 @@
     }
 
 
-    protected void deleteComponent()
+    protected void deleteComponent( int reason )
     {
         // only have to delete, if there is actually an instance
         if ( getInstance() != null )
         {
-            super.deleteComponent();
+            super.deleteComponent( reason );
         }
     }
 

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/DependencyManager.java?rev=792527&r1=792526&r2=792527&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/DependencyManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/DependencyManager.java Thu Jul  9 12:26:58 2009
@@ -37,6 +37,7 @@
 import org.osgi.framework.ServiceEvent;
 import org.osgi.framework.ServiceListener;
 import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.log.LogService;
 
 
@@ -228,7 +229,7 @@
                         + m_dependencyMetadata.getName() + " registered, reactivate component", m_componentManager
                         .getComponentMetadata(), null );
 
-                    m_componentManager.reactivate();
+                    m_componentManager.reactivate( ComponentConstants.DEACTIVATION_REASON_REFERENCE );
                 }
                 else
                 {
@@ -242,7 +243,7 @@
                             + m_dependencyMetadata.getName() + " with higher ranking registered, reactivate component",
                             m_componentManager.getComponentMetadata(), null );
 
-                        m_componentManager.reactivate();
+                        m_componentManager.reactivate( ComponentConstants.DEACTIVATION_REASON_REFERENCE );
                     }
                 }
             }
@@ -324,7 +325,7 @@
                             + " not satisfied", m_componentManager.getComponentMetadata(), null );
 
                 // deactivate the component now
-                m_componentManager.deactivateInternal();
+                m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE );
             }
 
             // if the dependency is static, we have to reactivate the component
@@ -336,8 +337,8 @@
                     m_componentManager.log( LogService.LOG_DEBUG, "Dependency Manager: Static dependency on "
                         + m_dependencyMetadata.getName() + "/" + m_dependencyMetadata.getInterface() + " is broken",
                         m_componentManager.getComponentMetadata(), null );
-                    m_componentManager.deactivateInternal();
-					m_componentManager.activate();
+                    m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE );
+                    m_componentManager.activate();
                 }
                 catch ( Exception ex )
                 {
@@ -362,7 +363,7 @@
                             "Dependency Manager: Deactivating component due to mandatory dependency on "
                                 + m_dependencyMetadata.getName() + "/" + m_dependencyMetadata.getInterface()
                                 + " not satisfied", m_componentManager.getComponentMetadata(), null );
-                        m_componentManager.deactivateInternal();
+                        m_componentManager.deactivateInternal( ComponentConstants.DEACTIVATION_REASON_REFERENCE );
 
                         // abort here we do not need to do more
                         return;

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ImmediateComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ImmediateComponentManager.java?rev=792527&r1=792526&r2=792527&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ImmediateComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ImmediateComponentManager.java Thu Jul  9 12:26:58 2009
@@ -24,9 +24,7 @@
 import java.util.Dictionary;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 
-import org.osgi.framework.BundleContext;
 import org.osgi.service.cm.Configuration;
 import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.component.ComponentContext;
@@ -39,38 +37,6 @@
  */
 class ImmediateComponentManager extends AbstractComponentManager
 {
-    private static final Class COMPONENT_CONTEXT_CLASS = ComponentContext.class;
-
-    private static final Class BUNDLE_CONTEXT_CLASS = BundleContext.class;
-
-    private static final Class MAP_CLASS = Map.class;
-
-    // this is an internal field made available only to the unit tests
-    static final Class[][] ACTIVATE_PARAMETER_LIST = {
-        { COMPONENT_CONTEXT_CLASS },
-        { BUNDLE_CONTEXT_CLASS },
-        { MAP_CLASS },
-
-        { COMPONENT_CONTEXT_CLASS, BUNDLE_CONTEXT_CLASS },
-        { COMPONENT_CONTEXT_CLASS, MAP_CLASS },
-
-        { BUNDLE_CONTEXT_CLASS, COMPONENT_CONTEXT_CLASS },
-        { BUNDLE_CONTEXT_CLASS, MAP_CLASS },
-
-        { MAP_CLASS, COMPONENT_CONTEXT_CLASS },
-        { MAP_CLASS, BUNDLE_CONTEXT_CLASS },
-
-        { COMPONENT_CONTEXT_CLASS, BUNDLE_CONTEXT_CLASS, MAP_CLASS },
-        { COMPONENT_CONTEXT_CLASS, MAP_CLASS, BUNDLE_CONTEXT_CLASS },
-
-        { BUNDLE_CONTEXT_CLASS, COMPONENT_CONTEXT_CLASS, MAP_CLASS },
-        { BUNDLE_CONTEXT_CLASS, MAP_CLASS, COMPONENT_CONTEXT_CLASS },
-
-        { MAP_CLASS, COMPONENT_CONTEXT_CLASS, BUNDLE_CONTEXT_CLASS },
-        { MAP_CLASS, BUNDLE_CONTEXT_CLASS, COMPONENT_CONTEXT_CLASS },
-
-        {}
-    };
 
     // The object that implements the service and that is bound to other services
     private Object m_implementationObject;
@@ -124,10 +90,10 @@
      * Before doing real disposal, we also have to unregister the managed
      * service which was registered when the instance was created.
      */
-    public synchronized void dispose()
+    public synchronized void dispose( final int reason )
     {
         // really dispose off this manager instance
-        disposeInternal();
+        disposeInternal( reason );
     }
 
 
@@ -155,9 +121,9 @@
     }
 
 
-    protected void deleteComponent()
+    protected void deleteComponent( int reason )
     {
-        disposeImplementationObject( m_implementationObject, m_componentContext );
+        disposeImplementationObject( m_implementationObject, m_componentContext, reason );
         m_implementationObject = null;
         m_componentContext = null;
         m_properties = null;
@@ -230,11 +196,12 @@
         // get the method
         if ( activateMethod == ReflectionHelper.SENTINEL )
         {
-            activateMethod = getMethod( implementationObject, getComponentMetadata().getActivate() );
+            activateMethod = getMethod( implementationObject, getComponentMetadata().getActivate(),
+                ReflectionHelper.ACTIVATE_ACCEPTED_PARAMETERS );
         }
 
         // 4. Call the activate method, if present
-        if ( activateMethod != null && !invokeMethod( activateMethod, implementationObject, componentContext ) )
+        if ( activateMethod != null && !invokeMethod( activateMethod, implementationObject, componentContext, -1 ) )
         {
             // 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
@@ -252,20 +219,25 @@
     }
 
 
-    protected void disposeImplementationObject( Object implementationObject, ComponentContext componentContext )
+    protected void disposeImplementationObject( Object implementationObject, ComponentContext componentContext,
+        int reason )
     {
 
         // get the method
         if ( deactivateMethod == ReflectionHelper.SENTINEL )
         {
-            deactivateMethod = getMethod( implementationObject, getComponentMetadata().getDeactivate() );
+            deactivateMethod = getMethod( implementationObject, getComponentMetadata().getDeactivate(),
+                ReflectionHelper.DEACTIVATE_ACCEPTED_PARAMETERS );
         }
 
         // 1. Call the deactivate method, if present
         // don't care for the result, the error (acccording to 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) has already been logged
-        invokeMethod( deactivateMethod, implementationObject, componentContext );
+        if ( deactivateMethod != null )
+        {
+            invokeMethod( deactivateMethod, implementationObject, componentContext, reason );
+        }
 
         // 2. Unbind any bound services
         Iterator it = getDependencyManagers();
@@ -386,7 +358,9 @@
         {
             log( LogService.LOG_DEBUG, "Deactivating and Activating to reconfigure from configuration",
                 getComponentMetadata(), null );
-            reactivate();
+            int reason = ( configuration == null ) ? ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_DELETED
+                : ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_DELETED;
+            reactivate( reason );
         }
     }
 
@@ -399,13 +373,16 @@
      * @param implementationObject The object whose class (and its super classes)
      *      may provide the method
      * @param methodName Name of the method to look for
+     * @param methodTester The {@link ReflectionHelper.MethodTester} instance
+     *      used to select the actual method.
      * @return The named method or <code>null</code> if no such method is available.
      */
-    private Method getMethod( final Object implementationObject, final String methodName )
+    private Method getMethod( final Object implementationObject, final String methodName,
+        final ReflectionHelper.MethodTester methodTester )
     {
         try
         {
-            return ReflectionHelper.getMethod( implementationObject.getClass(), methodName, ACTIVATE_PARAMETER_LIST );
+            return ReflectionHelper.getMethod( implementationObject.getClass(), methodName, methodTester );
         }
         catch ( InvocationTargetException ite )
         {
@@ -434,6 +411,10 @@
      * @param implementationObject The object on which to call the method.
      * @param componentContext The <code>ComponentContext</code> used to
      *      build the argument list
+     * @param reason The deactivation reason code. This should be one of the
+     *      values in the {@link ComponentConstants} interface. This parameter
+     *      is only of practical use for calling deactivate methods, which may
+     *      take a numeric argument indicating the deactivation reason.
      *
      * @return <code>true</code> if the method should be considered invoked
      *      successfully. <code>false</code> is returned if the method threw
@@ -442,7 +423,7 @@
      * @throws NullPointerException if any of the parameters is <code>null</code>.
      */
     private boolean invokeMethod( final Method method, final Object implementationObject,
-        final ComponentContext componentContext )
+        final ComponentContext componentContext, int reason )
     {
         final String methodName = method.getName();
         try
@@ -452,23 +433,26 @@
             Object[] param = new Object[paramTypes.length];
             for ( int i = 0; i < param.length; i++ )
             {
-                if ( paramTypes[i] == COMPONENT_CONTEXT_CLASS )
+                if ( paramTypes[i] == ReflectionHelper.COMPONENT_CONTEXT_CLASS )
                 {
                     param[i] = componentContext;
                 }
-                else if ( paramTypes[i] == BUNDLE_CONTEXT_CLASS )
+                else if ( paramTypes[i] == ReflectionHelper.BUNDLE_CONTEXT_CLASS )
                 {
                     param[i] = componentContext.getBundleContext();
                 }
-                else if ( paramTypes[i] == MAP_CLASS )
+                else if ( paramTypes[i] == ReflectionHelper.MAP_CLASS )
                 {
                     // note: getProperties() returns a Hashtable which is a Map
                     param[i] = componentContext.getProperties();
                 }
+                else if ( paramTypes[i] == ReflectionHelper.INTEGER_CLASS || paramTypes[i] == Integer.TYPE)
+                {
+                    param[i] = new Integer(reason);
+                }
             }
 
-            method.invoke( implementationObject, new Object[]
-                { componentContext } );
+            method.invoke( implementationObject, param );
         }
         catch ( IllegalAccessException ex )
         {
@@ -485,6 +469,14 @@
             // method threw, so it was a failure
             return false;
         }
+        catch ( Throwable t )
+        {
+            // anything else went wrong, log the message and fail the invocation
+            log( LogService.LOG_ERROR, "The " + methodName + " method could not be called", getComponentMetadata(), t );
+
+            // method invocation threw, so it was a failure
+            return false;
+        }
 
         // assume success (also if the method is not available or accessible)
         return true;

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ReflectionHelper.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ReflectionHelper.java?rev=792527&r1=792526&r2=792527&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ReflectionHelper.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ReflectionHelper.java Thu Jul  9 12:26:58 2009
@@ -22,6 +22,13 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
 
 
 /**
@@ -31,8 +38,24 @@
 final class ReflectionHelper
 {
 
+    // Method instance to implement tristate behaviour on method fields:
+    // unchecked (SENTINEL), no method (null), valid method (method object)
     static final Method SENTINEL;
 
+    // class references to simplify parameter checking
+    static final Class COMPONENT_CONTEXT_CLASS = ComponentContext.class;
+    static final Class BUNDLE_CONTEXT_CLASS = BundleContext.class;
+    static final Class MAP_CLASS = Map.class;
+    static final Class INTEGER_CLASS = Integer.class;
+
+    // Helper used to find the best matching activate and modified methods
+    static final ActivatorMethodTester ACTIVATE_ACCEPTED_PARAMETERS = new ActivatorMethodTester( new Class[]
+        { COMPONENT_CONTEXT_CLASS, BUNDLE_CONTEXT_CLASS, MAP_CLASS } );
+
+    // Helper used to find the best matching deactivate method
+    static final ActivatorMethodTester DEACTIVATE_ACCEPTED_PARAMETERS = new ActivatorMethodTester( new Class[]
+        { COMPONENT_CONTEXT_CLASS, BUNDLE_CONTEXT_CLASS, MAP_CLASS, Integer.TYPE, INTEGER_CLASS } );
+
     static
     {
         Method tmpSentinel = null;
@@ -78,26 +101,62 @@
      * @throws InvocationTargetException If an unexpected Throwable is caught
      *      trying to access the desired method.
      */
-    static Method getMethod( final Class objectClass, final String name, final Class[][] parameterTypesList )
+    static Method getMethod( final Class objectClass, final String name, final MethodTester tester )
         throws NoSuchMethodException, InvocationTargetException
     {
         // whether we accept package private methods
         boolean acceptPackage = true;
-        String packageName = getPackageName( objectClass );
+        final String packageName = getPackageName( objectClass );
+        final Class[] parameterTypesList = tester.getParameterLists();
 
         for ( Class clazz = objectClass; clazz != null; clazz = clazz.getSuperclass() )
         {
             // turns false on first package not equal to the package of objectClass
             acceptPackage &= packageName.equals( getPackageName( clazz ) );
+            final boolean acceptPrivate = clazz == objectClass;
 
+            // check parameter types first
             for ( int i = 0; i < parameterTypesList.length; i++ )
             {
-                Class[] parameterTypes = parameterTypesList[i];
+                Class[] parameterTypes = new Class[]
+                    { parameterTypesList[i] };
 
                 try
                 {
                     // find the declared method in this class
-                    return getMethod( clazz, name, parameterTypes, clazz == objectClass, acceptPackage );
+                    return getMethod( clazz, name, parameterTypes, acceptPrivate, acceptPackage );
+                }
+                catch ( NoSuchMethodException nsme )
+                {
+                    // ignore for now
+                }
+                catch ( Throwable throwable )
+                {
+                    // unexpected problem accessing the method, don't let everything
+                    // blow up in this situation, just throw a declared exception
+                    throw new InvocationTargetException( throwable, "Unexpected problem trying to get method " + name );
+                }
+            }
+
+            // check methods with MethodTester
+            Method[] methods = clazz.getDeclaredMethods();
+            for ( int i = 0; i < methods.length; i++ )
+            {
+                if ( methods[i].getName().equals( name ) && tester.isSuitable( methods[i] )
+                    && accept( methods[i], acceptPrivate, acceptPackage ) )
+                {
+                    // check modifiers etc.
+                    return methods[i];
+                }
+            }
+
+            // finally check method with no arguments
+            if ( tester.acceptEmpty() )
+            {
+                try
+                {
+                    // find the declared method in this class
+                    return getMethod( clazz, name, null, clazz == objectClass, acceptPackage );
                 }
                 catch ( NoSuchMethodException nsme )
                 {
@@ -148,7 +207,6 @@
             // accept public and protected methods only and ensure accessibility
             if ( accept( method, acceptPrivate, acceptPackage ) )
             {
-                method.setAccessible( true );
                 return method;
             }
         }
@@ -172,7 +230,8 @@
 
     /**
      * Returns <code>true</code> if the method is acceptable to be returned from the
-     * {@link #getMethod(Class, String, Class[], boolean, boolean)}.
+     * {@link #getMethod(Class, String, Class[], boolean, boolean)} and also
+     * makes the method accessible.
      * <p>
      * This method returns <code>true</code> iff:
      * <ul>
@@ -211,18 +270,26 @@
         // accept public and protected methods
         if ( Modifier.isPublic( mod ) || Modifier.isProtected( mod ) )
         {
+            method.setAccessible( true );
             return true;
         }
 
         // accept private if accepted
         if ( Modifier.isPrivate( mod ) )
         {
-            return acceptPrivate;
+            if ( acceptPrivate )
+            {
+                method.setAccessible( acceptPrivate );
+                return true;
+            }
+
+            return false;
         }
 
         // accept default (package)
         if ( acceptPackage )
         {
+            method.setAccessible( true );
             return true;
         }
 
@@ -241,4 +308,80 @@
         int dot = name.lastIndexOf( '.' );
         return ( dot > 0 ) ? name.substring( 0, dot ) : "";
     }
+
+    //---------- inner classes
+
+    static interface MethodTester
+    {
+
+        /**
+         * Returns <code>true</code> if methods without arguments are acceptable.
+         */
+        boolean acceptEmpty();
+
+
+        /**
+         * Returns <code>true</code> if the method <code>m</code> is suitable for
+         * this tester.
+         */
+        boolean isSuitable( Method m );
+
+
+        /**
+         * Returns an array of parameters which are acceptable as single parameter
+         * arguments to methods.
+         */
+        Class[] getParameterLists();
+    }
+
+    static final class ActivatorMethodTester implements ReflectionHelper.MethodTester
+    {
+        private final Class[] parameterLists;
+        private final Set methods;
+
+
+        ActivatorMethodTester( Class[] acceptedParameters )
+        {
+            parameterLists = acceptedParameters;
+            methods = new HashSet();
+            methods.addAll( Arrays.asList( acceptedParameters ) );
+        }
+
+
+        public boolean acceptEmpty()
+        {
+            return true;
+        }
+
+
+        public boolean isSuitable( Method m )
+        {
+            Class[] types = m.getParameterTypes();
+
+            // require two or more arguments
+            if ( types.length < 2 )
+            {
+                return false;
+            }
+
+            // check for argument types
+            for ( int i = 0; i < types.length; i++ )
+            {
+                if ( !methods.contains( types[i] ) )
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+
+        public Class[] getParameterLists()
+        {
+            return parameterLists;
+        }
+
+    }
+
 }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ServiceFactoryComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ServiceFactoryComponentManager.java?rev=792527&r1=792526&r2=792527&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ServiceFactoryComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ServiceFactoryComponentManager.java Thu Jul  9 12:26:58 2009
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
@@ -24,6 +24,7 @@
 import org.osgi.framework.Bundle;
 import org.osgi.framework.ServiceFactory;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.ComponentInstance;
 import org.osgi.service.log.LogService;
@@ -135,21 +136,21 @@
 
         // private ComponentContext and implementation instances
         ComponentContext serviceContext = ( ComponentContext ) serviceContexts.remove( service );
-        disposeImplementationObject( service, serviceContext );
+        disposeImplementationObject( service, serviceContext, ComponentConstants.DEACTIVATION_REASON_DISPOSED );
 
         // if this was the last use of the component, go back to REGISTERED state
         if ( serviceContexts.isEmpty() )
         {
-			if (getState() == STATE_ACTIVE)
-			{
-				synchronized(this)
-				{
-					if (getState() == STATE_ACTIVE)
-					{
-						changeState(Registered.getInstance());
-					}
-				}
-			}
+            if ( getState() == STATE_ACTIVE )
+            {
+                synchronized ( this )
+                {
+                    if ( getState() == STATE_ACTIVE )
+                    {
+                        changeState( Registered.getInstance() );
+                    }
+                }
+            }
         }
     }
 

Modified: felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/ReflectionHelperTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/ReflectionHelperTest.java?rev=792527&r1=792526&r2=792527&view=diff
==============================================================================
--- felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/ReflectionHelperTest.java (original)
+++ felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/ReflectionHelperTest.java Thu Jul  9 12:26:58 2009
@@ -197,7 +197,7 @@
         IllegalAccessException
     {
         Method method = ReflectionHelper.getMethod( obj.getClass(), methodName,
-            ImmediateComponentManager.ACTIVATE_PARAMETER_LIST );
+            ReflectionHelper.ACTIVATE_ACCEPTED_PARAMETERS );
         try
         {
             method.invoke( obj, new Object[method.getParameterTypes().length] );