FELIX-2521 Support separation between "no method to be called" and "method execution failure" situations to handle according specification:
- activate method failure is logged and must cause activation failure
- deactivate method failure is just logged
- modified method failure is just logged
- bind method failure is just logged
- unbind method failure is just logged
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@982605 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java
index b722013..515557a 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java
@@ -24,10 +24,18 @@
import org.apache.felix.scr.impl.manager.AbstractComponentManager;
import org.osgi.service.component.ComponentContext;
+import org.osgi.service.log.LogService;
public class ActivateMethod extends BaseMethod
{
+
+ Class[] ACTIVATE_TYPES_DS11 =
+ { COMPONENT_CONTEXT_CLASS, BUNDLE_CONTEXT_CLASS, MAP_CLASS };
+ Class[] ACTIVATE_TYPES_DS10 =
+ { COMPONENT_CONTEXT_CLASS };
+
+
public ActivateMethod( final AbstractComponentManager componentManager, final String methodName,
final boolean methodRequired, final Class componentClass )
{
@@ -133,9 +141,9 @@
}
- public boolean invoke( Object componentInstance, Object rawParameter )
+ public boolean invoke( Object componentInstance, Object rawParameter, final boolean methodCallFailureResult )
{
- return methodExists() && super.invoke( componentInstance, rawParameter );
+ return methodExists() && super.invoke( componentInstance, rawParameter, methodCallFailureResult );
}
@@ -173,9 +181,9 @@
}
catch ( SuitableMethodNotAccessibleException thrown )
{
+ getComponentManager().log( LogService.LOG_DEBUG, "SuitableMethodNotAccessible", thrown );
ex = thrown;
}
-
}
// rethrow if we looked for all method signatures and only found
@@ -223,14 +231,7 @@
protected Class[] getAcceptedParameterTypes()
{
- if ( isDS11() )
- {
- return new Class[]
- { COMPONENT_CONTEXT_CLASS, BUNDLE_CONTEXT_CLASS, MAP_CLASS };
- }
-
- return new Class[]
- { COMPONENT_CONTEXT_CLASS };
+ return isDS11() ? ACTIVATE_TYPES_DS11 : ACTIVATE_TYPES_DS10;
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java
index a1208ac..e2029be 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java
@@ -22,6 +22,7 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.util.Arrays;
import java.util.Map;
import org.apache.felix.scr.impl.manager.AbstractComponentManager;
@@ -49,7 +50,7 @@
private final String m_methodName;
private final Class m_componentClass;
- private Method m_method = null;
+ private Method m_method;
private final boolean m_methodRequired;
@@ -112,10 +113,15 @@
if ( method != null )
{
m_state = Resolved.INSTANCE;
+ getComponentManager().log( LogService.LOG_DEBUG, "Found {0} method: {1}", new Object[]
+ { getMethodNamePrefix(), method }, null );
}
else if ( m_methodRequired )
{
m_state = NotFound.INSTANCE;
+ getComponentManager().log( LogService.LOG_DEBUG, "{0} method [{1}] not found, will not invoke",
+ new Object[]
+ { getMethodNamePrefix(), getMethodName() }, null );
}
else
{
@@ -161,6 +167,12 @@
for ( Class theClass = targetClass; theClass != null; )
{
+ if ( getComponentManager().isLogEnabled( LogService.LOG_DEBUG ) )
+ {
+ getComponentManager().log( LogService.LOG_DEBUG,
+ "Locating method " + getMethodName() + " in class " + theClass.getName(), null );
+ }
+
try
{
Method method = doFindMethod( theClass, acceptPrivate, acceptPackage );
@@ -205,6 +217,7 @@
private boolean invokeMethod( final Object componentInstance, final Object rawParameter )
+ throws InvocationTargetException
{
try
{
@@ -235,20 +248,11 @@
}
catch ( InvocationTargetException ex )
{
- // 112.5.7 If a bind method throws an exception, SCR must log an
- // error message containing the exception [...]
- getComponentManager().log( LogService.LOG_ERROR, "The {0} method has thrown an exception", new Object[]
- { getMethodName() }, ex.getCause() );
- return false;
+ throw ex;
}
catch ( Throwable t )
{
- // anything else went wrong, log the message and fail the invocation
- getComponentManager().log( LogService.LOG_ERROR, "The {0} method could not be called", new Object[]
- { getMethodName() }, t );
-
- // method invocation threw, so it was a failure
- return false;
+ throw new InvocationTargetException( t );
}
// assume success (also if the mehotd is not available or accessible)
@@ -319,6 +323,12 @@
{
// thrown if no method is declared with the given name and
// parameters
+ if ( getComponentManager().isLogEnabled( LogService.LOG_DEBUG ) )
+ {
+ String argList = ( parameterTypes != null ) ? Arrays.asList( parameterTypes ).toString() : "";
+ getComponentManager().log( LogService.LOG_DEBUG, "Declared Method {0}.{1}({2}) not found", new Object[]
+ { clazz.getName(), name, argList }, null );
+ }
}
catch ( NoClassDefFoundError cdfe )
{
@@ -437,9 +447,37 @@
//---------- State management ------------------------------------
- public boolean invoke( final Object componentInstance, final Object rawParameter )
+ /**
+ * Calls the declared method on the given component with the provided
+ * method call arguments.
+ *
+ * @param componentInstance The component instance on which to call the
+ * method
+ * @param rawParameter The parameter container providing the actual
+ * parameters to provide to the called method
+ * @param methodCallFailureResult The result to return from this method if
+ * calling the method resulted in an exception.
+ *
+ * @return <code>true</code> if the method was called successfully or the
+ * method was not found and was not required. <code>false</code> if
+ * the method was not found but required.
+ * <code>methodCallFailureResult</code> is returned if the method was
+ * found and called, but the method threw an exception.
+ */
+ public boolean invoke( final Object componentInstance, final Object rawParameter,
+ final boolean methodCallFailureResult )
{
- return m_state.invoke( this, componentInstance, rawParameter );
+ try
+ {
+ return m_state.invoke( this, componentInstance, rawParameter );
+ }
+ catch ( InvocationTargetException ite )
+ {
+ getComponentManager().log( LogService.LOG_ERROR, "The {0} method has thrown an exception", new Object[]
+ { getMethodName() }, ite.getCause() );
+ }
+
+ return methodCallFailureResult;
}
@@ -451,7 +489,8 @@
private static interface State
{
- boolean invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter );
+ boolean invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
+ throws InvocationTargetException;
boolean methodExists( final BaseMethod baseMethod );
@@ -485,24 +524,25 @@
baseMethod.getComponentManager().log( LogService.LOG_DEBUG, "getting {0}: {1}", new Object[]
{ baseMethod.getMethodNamePrefix(), baseMethod.getMethodName() }, null );
- // resolve the method
- Method method;
- try
- {
- method = baseMethod.findMethod();
- }
- catch ( InvocationTargetException ex )
- {
- method = null;
- baseMethod.getComponentManager().log( LogService.LOG_WARNING, "{0} cannot be found", new Object[]
- { baseMethod.getMethodName() }, ex.getTargetException() );
- }
+ // resolve the method
+ Method method;
+ try
+ {
+ method = baseMethod.findMethod();
+ }
+ catch ( InvocationTargetException ex )
+ {
+ method = null;
+ baseMethod.getComponentManager().log( LogService.LOG_WARNING, "{0} cannot be found", new Object[]
+ { baseMethod.getMethodName() }, ex.getTargetException() );
+ }
- baseMethod.setMethod( method );
- }
+ baseMethod.setMethod( method );
+ }
public boolean invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
+ throws InvocationTargetException
{
resolve( baseMethod );
return baseMethod.getState().invoke( baseMethod, componentInstance, rawParameter );
@@ -544,6 +584,7 @@
public boolean invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
+ throws InvocationTargetException
{
baseMethod.getComponentManager().log( LogService.LOG_DEBUG, "invoking {0}: {1}", new Object[]
{ baseMethod.getMethodNamePrefix(), baseMethod.getMethodName() }, null );
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 c5aa5e3..c98a516 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
@@ -1025,22 +1025,20 @@
// null. This is valid for both immediate and delayed components
if( m_componentInstance != null )
{
- return m_bind.invoke(
- m_componentInstance,
- new BindMethod.Service()
+ return m_bind.invoke( m_componentInstance, new BindMethod.Service()
+ {
+ public ServiceReference getReference()
{
- public ServiceReference getReference()
- {
- bindService( ref );
- return ref;
- }
-
- public Object getInstance()
- {
- return getService( ref );
- }
+ bindService( ref );
+ return ref;
}
- );
+
+
+ public Object getInstance()
+ {
+ return getService( ref );
+ }
+ }, true );
}
else if ( !m_componentManager.getComponentMetadata().isImmediate() )
{
@@ -1099,7 +1097,7 @@
{
return getService( ref );
}
- } );
+ }, true );
}
else
{
@@ -1128,21 +1126,19 @@
// null. This is valid for both immediate and delayed components
if ( m_componentInstance != null )
{
- m_unbind.invoke(
- m_componentInstance,
- new BindMethod.Service()
+ m_unbind.invoke( m_componentInstance, new BindMethod.Service()
+ {
+ public ServiceReference getReference()
{
- public ServiceReference getReference()
- {
- return ref;
- }
-
- public Object getInstance()
- {
- return getService( ref );
- }
+ return ref;
}
- );
+
+
+ public Object getInstance()
+ {
+ return getService( ref );
+ }
+ }, true );
}
else
{
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 d7ea67b..be42530 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
@@ -224,7 +224,7 @@
// 4. Call the activate method, if present
if ( !m_activateMethod.invoke( implementationObject,
- new ActivateMethod.ActivatorParameter( componentContext, 1 ) ) )
+ new ActivateMethod.ActivatorParameter( componentContext, 1 ), false ) )
{
// 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
@@ -258,7 +258,7 @@
// method throws an exception, SCR must log an error message containing the
// exception with the Log Service and continue) has already been logged
m_deactivateMethod.invoke( implementationObject, new ActivateMethod.ActivatorParameter( componentContext,
- reason ) );
+ reason ), true );
// 2. Unbind any bound services
Iterator it = getDependencyManagers();
@@ -415,6 +415,7 @@
}
else if ( !modify() )
{
+ // SCR 112.7.1 - deactivate if configuration is deleted or no modified method declared
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;
@@ -467,10 +468,11 @@
// invariant: modify method existing and no static bound service changes
// 4. call method (nothing to do when failed, since it has already been logged)
- if ( !m_modifyMethod.invoke( getInstance(), new ActivateMethod.ActivatorParameter( m_componentContext, -1 ) ) )
+ if ( !m_modifyMethod.invoke( getInstance(), new ActivateMethod.ActivatorParameter( m_componentContext, -1 ),
+ true ) )
{
// log an error if the declared method cannot be found
- log( LogService.LOG_ERROR, "Declared modify method '{0}' cannot be found, configuring by reactivation",
+ log( LogService.LOG_ERROR, "Declared modify method ''{0}'' cannot be found, configuring by reactivation",
new Object[]
{ getComponentMetadata().getModified() }, null );
return false;
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java b/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java
index d4c7dae..13f7639 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java
@@ -230,7 +230,7 @@
};
ImmediateComponentManager icm = new ImmediateComponentManager( null, null, metadata );
ActivateMethod am = new ActivateMethod( icm, methodName, methodName != null, obj.getClass() );
- am.invoke( obj, new ActivateMethod.ActivatorParameter( m_ctx, -1 ) );
+ am.invoke( obj, new ActivateMethod.ActivatorParameter( m_ctx, -1 ), false );
Method m = get(am, "m_method");
assertNotNull( m );
assertEquals( methodName, m.getName() );
@@ -258,7 +258,7 @@
};
ImmediateComponentManager icm = new ImmediateComponentManager( null, null, metadata );
ActivateMethod am = new ActivateMethod( icm, methodName, methodName != null, obj.getClass() );
- am.invoke( obj, new ActivateMethod.ActivatorParameter( m_ctx, -1 ) );
+ am.invoke( obj, new ActivateMethod.ActivatorParameter( m_ctx, -1 ), false );
assertNull( get( am, "m_method" ) );
assertNull( obj.getCalledMethod() );
}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java b/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java
index 2938bf3..0a9aead 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java
@@ -441,7 +441,7 @@
ImmediateComponentManager icm = new ImmediateComponentManager( null, null, metadata );
BindMethod bm = new BindMethod( icm, methodName, component.getClass(), "reference",
FakeService.class.getName() );
- bm.invoke( component, m_service );
+ bm.invoke( component, m_service, true );
assertEquals( expectCallPerformed, component.callPerformed );
}
}