FELIX-1443 Unify method selection and invocation mechanisms on the
basis of Alin Dreghiciu's implementation for FELIX 924.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@800496 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
new file mode 100644
index 0000000..70000cd
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java
@@ -0,0 +1,243 @@
+/*
+ * 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.helper;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.apache.felix.scr.impl.manager.AbstractComponentManager;
+import org.osgi.service.component.ComponentContext;
+
+
+public class ActivateMethod extends BaseMethod
+{
+
+ public ActivateMethod( final AbstractComponentManager componentManager, String methodName, Class componentClass )
+ {
+ super( componentManager, methodName, componentClass );
+ }
+
+
+ protected Method doFindMethod( Class targetClass, boolean acceptPrivate, boolean acceptPackage )
+ throws SuitableMethodNotAccessibleException, InvocationTargetException
+ {
+
+ boolean suitableMethodNotAccessible = false;
+
+ try
+ {
+ return getSingleParameterMethod( targetClass, acceptPrivate, acceptPackage );
+ }
+ catch ( NoSuchMethodException nsme )
+ {
+ // ignore for now
+ }
+ catch ( SuitableMethodNotAccessibleException smnae )
+ {
+ suitableMethodNotAccessible = true;
+ }
+
+ if ( isDS11() )
+ {
+ // check methods with MethodTester
+ Method[] methods = targetClass.getDeclaredMethods();
+ for ( int i = 0; i < methods.length; i++ )
+ {
+ if ( methods[i].getName().equals( getMethodName() ) && isSuitable( methods[i] ) )
+ {
+ if ( accept( methods[i], acceptPrivate, acceptPackage ) )
+ {
+ // check modifiers etc.
+ return methods[i];
+ }
+
+ // method is suitable but not accessible, flag it
+ suitableMethodNotAccessible = true;
+ }
+ }
+
+ // finally check method with no arguments
+ if ( acceptEmpty() )
+ {
+ try
+ {
+ // find the declared method in this class
+ return getMethod( targetClass, getMethodName(), null, acceptPrivate, acceptPackage );
+ }
+ catch ( NoSuchMethodException nsme )
+ {
+ // ignore for now
+ }
+ catch ( SuitableMethodNotAccessibleException smnae )
+ {
+ suitableMethodNotAccessible = true;
+ }
+ }
+ }
+
+ if ( suitableMethodNotAccessible )
+ {
+ throw new SuitableMethodNotAccessibleException();
+ }
+
+ return null;
+ }
+
+
+ protected Object[] getParameters( Method method, Object rawParameter )
+ {
+ final Class[] parameterTypes = method.getParameterTypes();
+ final ActivatorParameter ap = ( ActivatorParameter ) rawParameter;
+ final Object[] param = new Object[parameterTypes.length];
+ for ( int i = 0; i < param.length; i++ )
+ {
+ if ( parameterTypes[i] == COMPONENT_CONTEXT_CLASS )
+ {
+ param[i] = ap.getComponentContext();
+ }
+ else if ( parameterTypes[i] == BUNDLE_CONTEXT_CLASS )
+ {
+ param[i] = ap.getComponentContext().getBundleContext();
+ }
+ else if ( parameterTypes[i] == MAP_CLASS )
+ {
+ // note: getProperties() returns a ReadOnlyDictionary which is a Map
+ param[i] = ap.getComponentContext().getProperties();
+ }
+ else if ( parameterTypes[i] == INTEGER_CLASS || parameterTypes[i] == Integer.TYPE )
+ {
+ param[i] = new Integer( ap.getReason() );
+ }
+ }
+
+ return param;
+ }
+
+
+ private Method getSingleParameterMethod( final Class targetClass, final boolean acceptPrivate,
+ final boolean acceptPackage ) throws SuitableMethodNotAccessibleException, InvocationTargetException,
+ NoSuchMethodException
+ {
+ SuitableMethodNotAccessibleException ex = null;
+ final Class[] acceptedTypes = getAcceptedParameterTypes();
+ for ( int i = 0; i < acceptedTypes.length; i++ )
+ {
+ try
+ {
+ // find the declared method in this class
+ return getMethod( targetClass, getMethodName(), new Class[]
+ { acceptedTypes[i] }, acceptPrivate, acceptPackage );
+ }
+ catch ( NoSuchMethodException nsme )
+ {
+ // ignore for now
+ }
+ catch ( SuitableMethodNotAccessibleException thrown )
+ {
+ ex = thrown;
+ }
+
+ }
+
+ if ( ex != null )
+ {
+ throw ex;
+ }
+
+ throw new NoSuchMethodException();
+ }
+
+
+ private boolean isSuitable( Method method )
+ {
+ // require two or more arguments
+ final Class[] types = method.getParameterTypes();
+ if ( types.length < 2 )
+ {
+ return false;
+ }
+
+ // check for argument types
+ final Class[] acceptedTypes = getAcceptedParameterTypes();
+ OUTER: for ( int i = 0; i < types.length; i++ )
+ {
+ final Class type = types[i];
+ for ( int j = 0; j < acceptedTypes.length; j++ )
+ {
+ if ( type == acceptedTypes[j] )
+ {
+ continue OUTER;
+ }
+ }
+
+ // get here if type is not contained in the array
+ return false;
+ }
+
+ // all parameters are acceptable
+ return true;
+ }
+
+
+ protected Class[] getAcceptedParameterTypes()
+ {
+ if ( isDS11() )
+ {
+ return new Class[]
+ { COMPONENT_CONTEXT_CLASS, BUNDLE_CONTEXT_CLASS, MAP_CLASS };
+ }
+
+ return new Class[]
+ { COMPONENT_CONTEXT_CLASS };
+ }
+
+
+ protected boolean acceptEmpty()
+ {
+ return isDS11();
+ }
+
+ //---------- Helper class for method call parameters
+
+ public static final class ActivatorParameter
+ {
+ private final ComponentContext m_componentContext;
+ private final int m_reason;
+
+
+ public ActivatorParameter( ComponentContext componentContext, int reason )
+ {
+ this.m_componentContext = componentContext;
+ this.m_reason = reason;
+ }
+
+
+ public ComponentContext getComponentContext()
+ {
+ return m_componentContext;
+ }
+
+
+ public int getReason()
+ {
+ return m_reason;
+ }
+ }
+}
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
new file mode 100644
index 0000000..99f3596
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java
@@ -0,0 +1,439 @@
+/*
+ * 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.helper;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Map;
+
+import org.apache.felix.scr.impl.helper.SuitableMethodNotAccessibleException;
+import org.apache.felix.scr.impl.manager.AbstractComponentManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.log.LogService;
+
+
+/**
+ * Component method to be invoked on service (un)binding.
+ */
+abstract class BaseMethod
+{
+
+ // class references to simplify parameter checking
+ protected static final Class COMPONENT_CONTEXT_CLASS = ComponentContext.class;
+ protected static final Class BUNDLE_CONTEXT_CLASS = BundleContext.class;
+ protected static final Class SERVICE_REFERENCE_CLASS = ServiceReference.class;
+ protected static final Class MAP_CLASS = Map.class;
+ protected static final Class INTEGER_CLASS = Integer.class;
+
+ private final AbstractComponentManager m_componentManager;
+
+ private final String m_methodName;
+ private final Class m_componentClass;
+
+ private Method m_method = null;
+
+ private State m_state;
+
+
+ protected BaseMethod( final AbstractComponentManager componentManager, final String methodName,
+ final Class componentClass )
+ {
+ m_componentManager = componentManager;
+ m_methodName = methodName;
+ m_componentClass = componentClass;
+ if ( m_methodName == null )
+ {
+ m_state = new NotApplicable();
+ }
+ else
+ {
+ m_state = new NotResolved();
+ }
+ }
+
+
+ protected final AbstractComponentManager getComponentManager()
+ {
+ return m_componentManager;
+ }
+
+
+ protected final boolean isDS11()
+ {
+ return getComponentManager().getComponentMetadata().isDS11();
+ }
+
+
+ protected final String getMethodName()
+ {
+ return m_methodName;
+ }
+
+
+ protected final Class getComponentClass()
+ {
+ return m_componentClass;
+ }
+
+
+ /**
+ * Finds the method named in the {@link #m_methodName} field in the given
+ * <code>targetClass</code>. If the target class has no acceptable method
+ * the class hierarchy is traversed until a method is found or the root
+ * of the class hierarchy is reached without finding a method.
+ *
+ * @param targetClass The class in which to look for the method
+ * @param acceptPrivate <code>true</code> if private methods should be
+ * considered.
+ * @param acceptPackage <code>true</code> if package private methods should
+ * be considered.
+ * @return The requested method or <code>null</code> if no acceptable method
+ * can be found in the target class or any super class.
+ * @throws InvocationTargetException If an unexpected Throwable is caught
+ * trying to find the requested method.
+ */
+ private Method findMethod() throws InvocationTargetException
+ {
+ boolean acceptPrivate = isDS11();
+ boolean acceptPackage = isDS11();
+
+ final Class targetClass = getComponentClass();
+ final ClassLoader targetClasslLoader = targetClass.getClassLoader();
+ final String targetPackage = getPackageName( targetClass );
+
+ for ( Class theClass = targetClass; theClass != null; )
+ {
+
+ try
+ {
+ Method method = doFindMethod( theClass, acceptPrivate, acceptPackage );
+ if ( method != null )
+ {
+ return method;
+ }
+ }
+ catch ( SuitableMethodNotAccessibleException ex )
+ {
+ // log and return null
+ getComponentManager().log( LogService.LOG_ERROR,
+ "DependencyManager : Suitable but non-accessible method found in class " + targetClass.getName(),
+ null, null );
+ break;
+ }
+
+ // if we get here, we have no method, so check the super class
+ theClass = theClass.getSuperclass();
+ if ( theClass == null )
+ {
+ break;
+ }
+
+ // super class method check ignores private methods and accepts
+ // package methods only if in the same package and package
+ // methods are (still) allowed
+ acceptPackage &= targetClasslLoader == theClass.getClassLoader()
+ && targetPackage.equals( getPackageName( theClass ) );
+
+ // private methods will not be accepted any more in super classes
+ acceptPrivate = false;
+ }
+
+ // nothing found after all these years ...
+ return null;
+ }
+
+
+ protected abstract Method doFindMethod( final Class targetClass, final boolean acceptPrivate,
+ final boolean acceptPackage ) throws SuitableMethodNotAccessibleException, InvocationTargetException;
+
+
+ private boolean invokeMethod( final Object componentInstance, final Object rawParameter )
+ {
+ try
+ {
+ final Object[] params = getParameters( m_method, rawParameter );
+ m_method.invoke( componentInstance, params );
+ }
+ catch ( IllegalStateException ise )
+ {
+ getComponentManager().log( LogService.LOG_INFO, ise.getMessage(), null, null );
+ return false;
+ }
+ catch ( IllegalAccessException ex )
+ {
+ // 112.3.1 If the method is not is not declared protected or
+ // public, SCR must log an error message with the log service,
+ // if present, and ignore the method
+ getComponentManager().log( LogService.LOG_DEBUG, "Method " + m_methodName + " cannot be called", null, ex );
+ }
+ 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 " + getMethodName() + " method has thrown an exception", null, ex.getCause() );
+ return false;
+ }
+ catch ( Throwable t )
+ {
+ // anything else went wrong, log the message and fail the invocation
+ getComponentManager().log( LogService.LOG_ERROR, "The " + getMethodName() + " method could not be called",
+ null, t );
+
+ // method invocation threw, so it was a failure
+ return false;
+ }
+
+ // assume success (also if the mehotd is not available or accessible)
+ return true;
+ }
+
+
+ /**
+ * Returns the parameter array created from the <code>rawParameter</code>
+ * using the actual parameter type list of the <code>method</code>.
+ * @param method
+ * @param rawParameter
+ * @return
+ * @throws IllegalStateException If the required parameters cannot be
+ * extracted from the <code>rawParameter</code>
+ */
+ protected abstract Object[] getParameters( Method method, Object rawParameter );
+
+
+ protected String getMethodNamePrefix()
+ {
+ return "";
+ }
+
+
+ //---------- Helpers
+
+ /**
+ * Finds the named public or protected method in the given class or any
+ * super class. If such a method is found, its accessibility is enfored by
+ * calling the <code>Method.setAccessible</code> method if required and
+ * the method is returned. Enforcing accessibility is required to support
+ * invocation of protected methods.
+ *
+ * @param clazz The <code>Class</code> which provides the method.
+ * @param name The name of the method.
+ * @param parameterTypes The parameters to the method. Passing
+ * <code>null</code> is equivalent to using an empty array.
+ *
+ * @return The named method with enforced accessibility
+ *
+ * @throws NoSuchMethodException If no public or protected method with
+ * the given name can be found in the class or any of its super classes.
+ * @throws SuitableMethodNotAccessibleException If method with the given
+ * name taking the parameters is found in the class but the method
+ * is not accessible.
+ * @throws InvocationTargetException If an unexpected Throwable is caught
+ * trying to access the desired method.
+ */
+ public static Method getMethod( Class clazz, String name, Class[] parameterTypes, boolean acceptPrivate,
+ boolean acceptPackage ) throws NoSuchMethodException, SuitableMethodNotAccessibleException,
+ InvocationTargetException
+ {
+ try
+ {
+ // find the declared method in this class
+ Method method = clazz.getDeclaredMethod( name, parameterTypes );
+
+ // accept public and protected methods only and ensure accessibility
+ if ( accept( method, acceptPrivate, acceptPackage ) )
+ {
+ return method;
+ }
+ }
+ catch ( NoSuchMethodException nsme )
+ {
+ // forward to caller
+ throw nsme;
+ }
+ 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 );
+ }
+
+ // suitable method found which is not accessible
+ throw new SuitableMethodNotAccessibleException();
+ }
+
+
+ /**
+ * Returns <code>true</code> if the method is acceptable to be returned from the
+ * {@link #getMethod(Class, String, Class[], boolean, boolean)} and also
+ * makes the method accessible.
+ * <p>
+ * This method returns <code>true</code> iff:
+ * <ul>
+ * <li>The method has <code>void</code> return type</li>
+ * <li>Is not static</li>
+ * <li>Is public or protected</li>
+ * <li>Is private and <code>acceptPrivate</code> is <code>true</code></li>
+ * <li>Is package private and <code>acceptPackage</code> is <code>true</code></li>
+ * </ul>
+ * <p>
+ * This method is package private for unit testing purposes. It is not
+ * meant to be called from client code.
+ *
+ * @param method The method to check
+ * @param acceptPrivate Whether a private method is acceptable
+ * @param acceptPackage Whether a package private method is acceptable
+ * @return
+ */
+ protected static boolean accept( Method method, boolean acceptPrivate, boolean acceptPackage )
+ {
+ // method must be void
+ if ( Void.TYPE != method.getReturnType() )
+ {
+ return false;
+ }
+
+ // check modifiers now
+ int mod = method.getModifiers();
+
+ // no static method
+ if ( Modifier.isStatic( mod ) )
+ {
+ return false;
+ }
+
+ // 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 ) )
+ {
+ if ( acceptPrivate )
+ {
+ method.setAccessible( acceptPrivate );
+ return true;
+ }
+
+ return false;
+ }
+
+ // accept default (package)
+ if ( acceptPackage )
+ {
+ method.setAccessible( true );
+ return true;
+ }
+
+ // else don't accept
+ return false;
+ }
+
+
+ /**
+ * Returns the name of the package to which the class belongs or an
+ * empty string if the class is in the default package.
+ */
+ public static String getPackageName( Class clazz )
+ {
+ String name = clazz.getName();
+ int dot = name.lastIndexOf( '.' );
+ return ( dot > 0 ) ? name.substring( 0, dot ) : "";
+ }
+
+
+ //---------- State management ------------------------------------
+
+ public boolean invoke( final Object componentInstance, final Object rawParameter )
+ {
+ return m_state.invoke( componentInstance, rawParameter );
+ }
+
+ private static interface State
+ {
+
+ boolean invoke( final Object componentInstance, final Object rawParameter );
+ }
+
+ private static class NotApplicable implements State
+ {
+
+ public boolean invoke( final Object componentInstance, final Object rawParameter )
+ {
+ return true;
+ }
+ }
+
+ private class NotResolved implements State
+ {
+
+ public boolean invoke( final Object componentInstance, final Object rawParameter )
+ {
+ getComponentManager().log( LogService.LOG_DEBUG,
+ "getting " + getMethodNamePrefix() + "bind: " + m_methodName, null, null );
+ try
+ {
+ m_method = findMethod();
+ m_state = ( m_method == null ) ? ( State ) new NotFound() : new Resolved();
+ return m_state.invoke( componentInstance, rawParameter );
+ }
+ catch ( InvocationTargetException ex )
+ {
+ m_state = new NotFound();
+ // We can safely ignore this one
+ getComponentManager().log( LogService.LOG_WARNING, getMethodName() + " cannot be found", null,
+ ex.getTargetException() );
+ }
+ return true;
+ }
+ }
+
+ private class NotFound implements State
+ {
+
+ public boolean invoke( final Object componentInstance, final Object rawParameter )
+ {
+ // 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
+ getComponentManager().log( LogService.LOG_ERROR,
+ getMethodNamePrefix() + "bind method [" + m_methodName + "] not found", null, null );
+ return true;
+ }
+ }
+
+ private class Resolved implements State
+ {
+
+ public boolean invoke( final Object componentInstance, final Object rawParameter )
+ {
+ getComponentManager().log( LogService.LOG_DEBUG,
+ "invoking " + getMethodNamePrefix() + "bind: " + m_methodName, null, null );
+ return invokeMethod( componentInstance, rawParameter );
+ }
+ }
+
+}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/BindMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
similarity index 70%
rename from scr/src/main/java/org/apache/felix/scr/impl/manager/BindMethod.java
rename to scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
index 384d101..209255c 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/BindMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
@@ -16,15 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.scr.impl.manager;
+package org.apache.felix.scr.impl.helper;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import org.apache.felix.scr.impl.helper.ReadOnlyDictionary;
-import org.apache.felix.scr.impl.helper.ReflectionHelper;
-import org.apache.felix.scr.impl.helper.SuitableMethodNotAccessibleException;
-import org.osgi.framework.Constants;
+
+import org.apache.felix.scr.impl.manager.AbstractComponentManager;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;
@@ -32,37 +30,19 @@
/**
* Component method to be invoked on service (un)binding.
*/
-class BindMethod
+public class BindMethod extends BaseMethod
{
- private final boolean m_isDS11;
- private final String m_methodName;
- private final Class m_componentClass;
private final String m_referenceName;
private final String m_referenceClassName;
- private final Logger m_logger;
-
- private Method m_method = null;
- private State m_state;
- BindMethod( final boolean isDS11, final String methodName, final Class componentClass, final String referenceName,
- final String referenceClassName, final Logger logger )
+ public BindMethod( final AbstractComponentManager componentManager, final String methodName,
+ final Class componentClass, final String referenceName, final String referenceClassName )
{
- m_isDS11 = isDS11;
- m_methodName = methodName;
- m_componentClass = componentClass;
+ super( componentManager, methodName, componentClass );
m_referenceName = referenceName;
m_referenceClassName = referenceClassName;
- m_logger = logger;
- if ( m_methodName == null )
- {
- m_state = new NotApplicable();
- }
- else
- {
- m_state = new NotResolved();
- }
}
@@ -82,8 +62,8 @@
* @throws InvocationTargetException If an unexpected Throwable is caught
* trying to find the requested method.
*/
- private Method findMethod( final Class targetClass, final boolean acceptPrivate, final boolean acceptPackage )
- throws InvocationTargetException
+ protected Method doFindMethod( Class targetClass, boolean acceptPrivate, boolean acceptPackage )
+ throws SuitableMethodNotAccessibleException, InvocationTargetException
{
// 112.3.1 The method is searched for using the following priority
// 1 - Service reference parameter
@@ -144,7 +124,7 @@
}
// signatures taking a map are only supported starting with DS 1.1
- if ( m_isDS11 )
+ if ( isDS11() )
{
// Case 4 - same as case 2, but + Map param (DS 1.1 only)
@@ -182,25 +162,16 @@
// if at least one suitable method could be found but none of
// the suitable methods are accessible, we have to terminate
- if (suitableMethodNotAccessible )
+ if ( suitableMethodNotAccessible )
{
- m_logger.log( LogService.LOG_ERROR,
- "DependencyManager : Suitable but non-accessible method found in class " + targetClass.getName() );
- return null;
+ getComponentManager().log( LogService.LOG_ERROR,
+ "DependencyManager : Suitable but non-accessible method found in class " + targetClass.getName(), null,
+ null );
+ throw new SuitableMethodNotAccessibleException();
}
- // if we get here, we have no method, so check the super class
- final Class superClass = targetClass.getSuperclass();
- if (superClass == null) {
- return null;
- }
-
- // super class method check ignores private methods and accepts
- // package methods only if in the same package and package
- // methods are (still) allowed
- final boolean withPackage = acceptPackage && targetClass.getClassLoader() == superClass.getClassLoader()
- && ReflectionHelper.getPackageName( targetClass ).equals( ReflectionHelper.getPackageName( superClass ) );
- return findMethod( superClass, false, withPackage);
+ // no method found
+ return null;
}
@@ -264,8 +235,8 @@
{
try
{
- return ReflectionHelper.getMethod( targetClass, m_methodName, new Class[]
- { ReflectionHelper.SERVICE_REFERENCE_CLASS }, acceptPrivate, acceptPackage );
+ return getMethod( targetClass, getMethodName(), new Class[]
+ { SERVICE_REFERENCE_CLASS }, acceptPrivate, acceptPackage );
}
catch ( NoSuchMethodException e )
{
@@ -299,7 +270,7 @@
{
try
{
- return ReflectionHelper.getMethod( targetClass, m_methodName, new Class[]
+ return getMethod( targetClass, getMethodName(), new Class[]
{ parameterClass }, acceptPrivate, acceptPackage );
}
catch ( NoSuchMethodException nsme )
@@ -346,7 +317,7 @@
// Select only the methods that receive a single
// parameter
// and a matching name
- if ( parameters.length == 1 && method.getName().equals( m_methodName ) )
+ if ( parameters.length == 1 && method.getName().equals( getMethodName() ) )
{
// Get the parameter type
@@ -357,7 +328,7 @@
// reference's interface attribute
if ( theParameter.isAssignableFrom( parameterClass ) )
{
- if ( ReflectionHelper.accept( method, acceptPrivate, acceptPackage ) )
+ if ( accept( method, acceptPrivate, acceptPackage ) )
{
return method;
}
@@ -404,8 +375,8 @@
{
try
{
- return ReflectionHelper.getMethod( targetClass, m_methodName, new Class[]
- { parameterClass, ReflectionHelper.MAP_CLASS }, acceptPrivate, acceptPackage );
+ return getMethod( targetClass, getMethodName(), new Class[]
+ { parameterClass, MAP_CLASS }, acceptPrivate, acceptPackage );
}
catch ( NoSuchMethodException nsme )
{
@@ -446,13 +417,13 @@
{
final Method method = candidateBindMethods[i];
final Class[] parameters = method.getParameterTypes();
- if ( parameters.length == 2 && method.getName().equals( m_methodName ) )
+ if ( parameters.length == 2 && method.getName().equals( getMethodName() ) )
{
// parameters must be refclass,map
- if ( parameters[0].isAssignableFrom( parameterClass ) && parameters[1] == ReflectionHelper.MAP_CLASS )
+ if ( parameters[0].isAssignableFrom( parameterClass ) && parameters[1] == MAP_CLASS )
{
- if ( ReflectionHelper.accept( method, acceptPrivate, acceptPackage ) )
+ if ( accept( method, acceptPrivate, acceptPackage ) )
{
return method;
}
@@ -475,17 +446,18 @@
}
- private boolean invokeMethod( final Object componentInstance, final Service service )
+ protected Object[] getParameters( Method method, Object rawParameter )
{
- final Class[] paramTypes = m_method.getParameterTypes();
+ final Service service = ( Service ) rawParameter;
+ final Class[] paramTypes = method.getParameterTypes();
final Object[] params = new Object[paramTypes.length];
for ( int i = 0; i < params.length; i++ )
{
- if ( paramTypes[i] == ReflectionHelper.SERVICE_REFERENCE_CLASS )
+ if ( paramTypes[i] == SERVICE_REFERENCE_CLASS )
{
params[i] = service.getReference();
}
- else if ( paramTypes[i] == ReflectionHelper.MAP_CLASS )
+ else if ( paramTypes[i] == MAP_CLASS )
{
params[i] = new ReadOnlyDictionary( service.getReference() );
}
@@ -494,34 +466,13 @@
params[i] = service.getInstance();
if ( params[i] == null )
{
- m_logger.log( LogService.LOG_INFO, "Dependency Manager: Service " + service.getReference()
+ throw new IllegalStateException( "Dependency Manager: Service " + service.getReference()
+ " has already gone, not " + getMethodNamePrefix() + "binding" );
- return false;
}
}
}
- try
- {
- m_method.invoke( componentInstance, params );
- m_logger.log( LogService.LOG_DEBUG, getMethodNamePrefix() + "bound: " + m_referenceName + "/"
- + service.getReference().getProperty( Constants.SERVICE_ID ) );
- }
- catch ( IllegalAccessException ex )
- {
- // 112.3.1 If the method is not is not declared protected or
- // public, SCR must log an error message with the log service,
- // if present, and ignore the method
- m_logger.log( LogService.LOG_ERROR, getMethodNamePrefix() + "bind method " + m_methodName + "] cannot be called",
- ex );
- }
- catch ( InvocationTargetException ex )
- {
- // 112.5.7 If a bind method throws an exception, SCR must log an
- // error message containing the exception [...]
- m_logger.log( LogService.LOG_ERROR, "DependencyManager : exception while invoking " + m_methodName + "()",
- ex.getCause() );
- }
- return true;
+
+ return params;
}
@@ -530,88 +481,9 @@
return "";
}
-
- //---------- State management ------------------------------------
-
- boolean invoke( final Object componentInstance, final Service service )
- {
- return m_state.invoke( componentInstance, service );
- }
-
- private static interface State
- {
-
- boolean invoke( final Object componentInstance, final Service service );
- }
-
- private static class NotApplicable implements State
- {
-
- public boolean invoke( final Object componentInstance, final Service service )
- {
- return true;
- }
- }
-
- private class NotResolved implements State
- {
-
- public boolean invoke( final Object componentInstance, final Service service )
- {
- m_logger.log( LogService.LOG_DEBUG, "getting " + getMethodNamePrefix() + "bind: " + m_methodName );
- try
- {
- // if the owning component is declared with the DS 1.1 namespace
- // (or newer), private and package private methods are accepted
- m_method = findMethod( m_componentClass, m_isDS11, m_isDS11 );
- if ( m_method == null )
- {
- m_state = new NotFound();
- }
- else
- {
- m_state = new Resolved();
- }
- return m_state.invoke( componentInstance, service );
- }
- catch ( InvocationTargetException ex )
- {
- m_state = new NotFound();
- // 112.5.7 If a bind method throws an exception, SCR must log an
- // error message containing the exception [...]
- m_logger.log( LogService.LOG_ERROR, "DependencyManager : exception while finding " + m_methodName
- + "()", ex.getCause() );
- }
- return true;
- }
- }
-
- private class NotFound implements State
- {
-
- public boolean invoke( final Object componentInstance, final Service service )
- {
- // 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
- m_logger.log( LogService.LOG_ERROR, getMethodNamePrefix() + "bind method [" + m_methodName + "] not found" );
- return true;
- }
- }
-
- private class Resolved implements State
- {
-
- public boolean invoke( final Object componentInstance, final Service service )
- {
- m_logger.log( LogService.LOG_DEBUG, "invoking " + getMethodNamePrefix() + "bind: " + m_methodName );
- return invokeMethod( componentInstance, service );
- }
- }
-
//---------- Service abstraction ------------------------------------
- static interface Service
+ public static interface Service
{
ServiceReference getReference();
@@ -621,16 +493,4 @@
}
- //---------- Logger ------------------------------------
-
- static interface Logger
- {
-
- void log( int level, String message );
-
-
- void log( int level, String message, Throwable ex );
-
- }
-
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/DeactivateMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/DeactivateMethod.java
new file mode 100644
index 0000000..2d88d28
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/DeactivateMethod.java
@@ -0,0 +1,45 @@
+/*
+ * 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.helper;
+
+
+import org.apache.felix.scr.impl.manager.AbstractComponentManager;
+
+
+public class DeactivateMethod extends ActivateMethod
+{
+
+ public DeactivateMethod( final AbstractComponentManager componentManager, String methodName, Class componentClass )
+ {
+ super( componentManager, methodName, componentClass );
+ }
+
+
+ protected Class[] getAcceptedParameterTypes()
+ {
+ if ( isDS11() )
+ {
+ return new Class[]
+ { COMPONENT_CONTEXT_CLASS, BUNDLE_CONTEXT_CLASS, MAP_CLASS, Integer.TYPE, INTEGER_CLASS };
+ }
+
+ return new Class[]
+ { COMPONENT_CONTEXT_CLASS };
+ }
+}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/MethodNameException.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/ModifiedMethod.java
similarity index 66%
rename from scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/MethodNameException.java
rename to scr/src/main/java/org/apache/felix/scr/impl/helper/ModifiedMethod.java
index 8745490..3e954f1 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/MethodNameException.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/ModifiedMethod.java
@@ -16,17 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.scr.impl.metadata.instances;
+package org.apache.felix.scr.impl.helper;
-public final class MethodNameException extends RuntimeException
+import org.apache.felix.scr.impl.manager.AbstractComponentManager;
+
+
+public class ModifiedMethod extends ActivateMethod
{
- private static final long serialVersionUID = 1L;
-
-
- public MethodNameException( String message )
+ public ModifiedMethod( final AbstractComponentManager componentManager, String methodName, Class componentClass )
{
- super( message );
+ super( componentManager, methodName, componentClass );
+ }
+
+
+ protected boolean acceptEmpty()
+ {
+ return false;
}
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/ReflectionHelper.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/ReflectionHelper.java
deleted file mode 100644
index 9bdf532..0000000
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/ReflectionHelper.java
+++ /dev/null
@@ -1,489 +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.helper;
-
-
-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.framework.ServiceReference;
-import org.osgi.service.component.ComponentContext;
-
-
-/**
- * The <code>ReflectionHelper</code> class provides utility methods to find out
- * about binding and activation methods in components.
- */
-public final class ReflectionHelper
-{
-
- // Method instance to implement tristate behaviour on method fields:
- // unchecked (SENTINEL), no method (null), valid method (method object)
- public static final Method SENTINEL;
-
- // class references to simplify parameter checking
- public static final Class COMPONENT_CONTEXT_CLASS = ComponentContext.class;
- public static final Class BUNDLE_CONTEXT_CLASS = BundleContext.class;
- public static final Class SERVICE_REFERENCE_CLASS = ServiceReference.class;
- public static final Class MAP_CLASS = Map.class;
- public static final Class INTEGER_CLASS = Integer.class;
-
- // Helper used to find the best matching activate and modified methods (DS 1.1 and newer)
- public static final MethodTester ACTIVATE_ACCEPTED_PARAMETERS = new ActivatorMethodTester( new Class[]
- { COMPONENT_CONTEXT_CLASS, BUNDLE_CONTEXT_CLASS, MAP_CLASS } );
-
- // Helper used to find the best matching deactivate method (DS 1.1 and newer)
- public static final MethodTester DEACTIVATE_ACCEPTED_PARAMETERS = new ActivatorMethodTester( new Class[]
- { COMPONENT_CONTEXT_CLASS, BUNDLE_CONTEXT_CLASS, MAP_CLASS, Integer.TYPE, INTEGER_CLASS } );
-
- // Helper used to find the best matching activate/deactivate method (DS 1.0)
- public static final MethodTester ACTIVATOR_10_ACCEPTED_PARAMETERS = new ActivatorMethodTester10();
-
- static
- {
- Method tmpSentinel = null;
- try
- {
- tmpSentinel = ReflectionHelper.class.getDeclaredMethod( "sentinel", null );
- }
- catch ( Throwable t )
- {
- // don't care for the reason
- }
-
- SENTINEL = tmpSentinel;
- }
-
-
- // sentinel method used to assign to the SENTINEL field
- private static final void sentinel()
- {
- }
-
-
- /**
- * Finds the named public or protected method in the given class or any
- * super class. If such a method is found, its accessibility is enfored by
- * calling the <code>Method.setAccessible</code> method if required and
- * the method is returned. Enforcing accessibility is required to support
- * invocation of protected methods.
- *
- * @param objectClass The <code>Class</code> at which to start looking for
- * a matching method
- * @param name The name of the method.
- * @param parameterTypes The list of suitable parmameters. Each class is
- * is asked for a declared method of the given name with parameters
- * from this list.
- * @param only Whether to only look at the declared methods of the given
- * class or also inspect the super classes.
- *
- * @return The named method with enforced accessibility
- *
- * @throws NoSuchMethodException If no public or protected method with
- * the given name can be found in the class or any of its super classes.
- * @throws InvocationTargetException If an unexpected Throwable is caught
- * trying to access the desired method.
- */
- public static Method getMethod( final Class objectClass, final String name, final MethodTester tester )
- throws NoSuchMethodException, InvocationTargetException
- {
- // whether we accept package private methods
- boolean acceptPackage = tester.acceptPackage();
- final String packageName = getPackageName( objectClass );
- final Class[] parameterTypesList = tester.getParameterLists();
-
- // flag indicating a suitable but inaccessible method has been found
- boolean suitableMethodNotAccessible = false;
-
- // lookup methods until there is no more super class or a class would
- // have at least one suitable method but none is accessible
- for ( Class clazz = objectClass; clazz != null && !suitableMethodNotAccessible; clazz = clazz.getSuperclass() )
- {
- // turns false on first package not equal to the package of objectClass (or different class loader)
- acceptPackage &= packageName.equals( getPackageName( clazz ) )
- && clazz.getClassLoader() == objectClass.getClassLoader();
- final boolean acceptPrivate = tester.acceptPrivate() && clazz == objectClass;
-
-
- // check parameter types first
- for ( int i = 0; i < parameterTypesList.length; i++ )
- {
- Class[] parameterTypes = new Class[]
- { parameterTypesList[i] };
-
- try
- {
- // find the declared method in this class
- return getMethod( clazz, name, parameterTypes, acceptPrivate, acceptPackage );
- }
- catch ( NoSuchMethodException nsme )
- {
- // ignore for now
- }
- catch ( SuitableMethodNotAccessibleException smnae )
- {
- suitableMethodNotAccessible = true;
- }
- 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] ) )
- {
- if ( accept( methods[i], acceptPrivate, acceptPackage ) )
- {
- // check modifiers etc.
- return methods[i];
- }
-
- // method is suitable but not accessible, flag it
- suitableMethodNotAccessible = true;
- }
- }
-
- // finally check method with no arguments
- if ( tester.acceptEmpty() )
- {
- try
- {
- // find the declared method in this class
- return getMethod( clazz, name, null, acceptPrivate, acceptPackage );
- }
- catch ( NoSuchMethodException nsme )
- {
- // ignore for now
- }
- catch ( SuitableMethodNotAccessibleException smnae )
- {
- suitableMethodNotAccessible = true;
- }
- 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 );
- }
- }
- }
-
- // walked up the complete super class hierarchy and still not found
- // anything, sigh ...
- throw new NoSuchMethodException( name );
- }
-
-
- /**
- * Finds the named public or protected method in the given class or any
- * super class. If such a method is found, its accessibility is enfored by
- * calling the <code>Method.setAccessible</code> method if required and
- * the method is returned. Enforcing accessibility is required to support
- * invocation of protected methods.
- *
- * @param clazz The <code>Class</code> which provides the method.
- * @param name The name of the method.
- * @param parameterTypes The parameters to the method. Passing
- * <code>null</code> is equivalent to using an empty array.
- *
- * @return The named method with enforced accessibility
- *
- * @throws NoSuchMethodException If no public or protected method with
- * the given name can be found in the class or any of its super classes.
- * @throws SuitableMethodNotAccessibleException If method with the given
- * name taking the parameters is found in the class but the method
- * is not accessible.
- * @throws InvocationTargetException If an unexpected Throwable is caught
- * trying to access the desired method.
- */
- public static Method getMethod( Class clazz, String name, Class[] parameterTypes, boolean acceptPrivate,
- boolean acceptPackage ) throws NoSuchMethodException, SuitableMethodNotAccessibleException,
- InvocationTargetException
- {
- try
- {
- // find the declared method in this class
- Method method = clazz.getDeclaredMethod( name, parameterTypes );
-
- // accept public and protected methods only and ensure accessibility
- if ( accept( method, acceptPrivate, acceptPackage ) )
- {
- return method;
- }
- }
- catch ( NoSuchMethodException nsme )
- {
- // forward to caller
- throw nsme;
- }
- 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 );
- }
-
- // suitable method found which is not accessible
- throw new SuitableMethodNotAccessibleException();
- }
-
-
- /**
- * Returns <code>true</code> if the method is acceptable to be returned from the
- * {@link #getMethod(Class, String, Class[], boolean, boolean)} and also
- * makes the method accessible.
- * <p>
- * This method returns <code>true</code> iff:
- * <ul>
- * <li>The method has <code>void</code> return type</li>
- * <li>Is not static</li>
- * <li>Is public or protected</li>
- * <li>Is private and <code>acceptPrivate</code> is <code>true</code></li>
- * <li>Is package private and <code>acceptPackage</code> is <code>true</code></li>
- * </ul>
- * <p>
- * This method is package private for unit testing purposes. It is not
- * meant to be called from client code.
- *
- * @param method The method to check
- * @param acceptPrivate Whether a private method is acceptable
- * @param acceptPackage Whether a package private method is acceptable
- * @return
- */
- public static boolean accept( Method method, boolean acceptPrivate, boolean acceptPackage )
- {
- // method must be void
- if ( Void.TYPE != method.getReturnType() )
- {
- return false;
- }
-
- // check modifiers now
- int mod = method.getModifiers();
-
- // no static method
- if ( Modifier.isStatic( mod ) )
- {
- return false;
- }
-
- // 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 ) )
- {
- if ( acceptPrivate )
- {
- method.setAccessible( acceptPrivate );
- return true;
- }
-
- return false;
- }
-
- // accept default (package)
- if ( acceptPackage )
- {
- method.setAccessible( true );
- return true;
- }
-
- // else don't accept
- return false;
- }
-
-
- /**
- * Returns the name of the package to which the class belongs or an
- * empty string if the class is in the default package.
- */
- public static String getPackageName( Class clazz )
- {
- String name = clazz.getName();
- int dot = name.lastIndexOf( '.' );
- return ( dot > 0 ) ? name.substring( 0, dot ) : "";
- }
-
- //---------- inner classes
-
- public static interface MethodTester
- {
-
- /**
- * Returns <code>true</code> if methods without arguments are acceptable.
- */
- boolean acceptEmpty();
-
- /**
- * Returns <code>true</code> if private methods are allowed at all.
- */
- boolean acceptPrivate();
-
- /**
- * Returns <code>true</code> if package private methods are allowed at all.
- */
- boolean acceptPackage();
-
- /**
- * 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();
- }
-
- /**
- * The <code>ActivatorMethodTester</code> class implements the {@link MethodTester}
- * interface to test methods applicable for Components declared with the
- * SCR 1.1 (or newer) specification namespace.
- */
- public 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 acceptPrivate()
- {
- return true;
- }
-
-
- public boolean acceptPackage()
- {
- 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;
- }
-
- }
-
-
- /**
- * The <code>ActivatorMethodTester10</code> class implements the
- * {@link MethodTester} interface to test methods applicable for Components
- * declared with the original SCR 1.0 specification namespace.
- */
- public static final class ActivatorMethodTester10 implements ReflectionHelper.MethodTester
- {
-
- private static final Class[] PARAMETER_LIST =
- { COMPONENT_CONTEXT_CLASS };
-
-
- public boolean acceptEmpty()
- {
- // DS 1.0 activator methods only accept ComponentContext
- return false;
- }
-
-
- public boolean acceptPrivate()
- {
- // DS 1.0 activator methods may only be public or protected
- return true;
- }
-
-
- public boolean acceptPackage()
- {
- // DS 1.0 activator methods may only be public or protected
- return true;
- }
-
-
- public boolean isSuitable( Method m )
- {
- // DS 1.0 activator methods only accept ComponentContext
- Class[] types = m.getParameterTypes();
- return types.length == 1 && types[0] == COMPONENT_CONTEXT_CLASS;
- }
-
-
- public Class[] getParameterLists()
- {
- return PARAMETER_LIST;
- }
- }
-
-}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/UnbindMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/UnbindMethod.java
similarity index 68%
rename from scr/src/main/java/org/apache/felix/scr/impl/manager/UnbindMethod.java
rename to scr/src/main/java/org/apache/felix/scr/impl/helper/UnbindMethod.java
index e091f4e..1b5ea93 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/UnbindMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/UnbindMethod.java
@@ -16,19 +16,22 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.scr.impl.manager;
+package org.apache.felix.scr.impl.helper;
+
+
+import org.apache.felix.scr.impl.manager.AbstractComponentManager;
/**
* Component method to be invoked on service unbinding.
*/
-class UnbindMethod extends BindMethod
+public class UnbindMethod extends BindMethod
{
- UnbindMethod( final boolean isDS11, final String methodName, final Class componentClass,
- final String referenceName, final String referenceClassName, final Logger logger )
+ public UnbindMethod( final AbstractComponentManager componentManager, final String methodName,
+ final Class componentClass, final String referenceName, final String referenceClassName )
{
- super( isDS11, methodName, componentClass, referenceName, referenceClassName, logger );
+ super( componentManager, methodName, componentClass, referenceName, referenceClassName );
}
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 afca9fc..4015d08 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
@@ -774,7 +774,7 @@
}
- void log( int level, String message, ComponentMetadata metadata, Throwable ex )
+ public void log( int level, String message, ComponentMetadata metadata, Throwable ex )
{
BundleComponentActivator activator = getActivator();
if ( activator != 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 0328fc5..14c7174 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
@@ -27,6 +27,8 @@
import java.util.Map;
import org.apache.felix.scr.Reference;
+import org.apache.felix.scr.impl.helper.BindMethod;
+import org.apache.felix.scr.impl.helper.UnbindMethod;
import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
@@ -115,32 +117,17 @@
*/
private void initBindingMethods()
{
- BindMethod.Logger logger = new BindMethod.Logger()
- {
-
- public void log( int level, String message )
- {
- log( level, message, null );
- }
-
- public void log( int level, String message, Throwable ex )
- {
- m_componentManager.log( level, message, m_componentManager.getComponentMetadata(), ex );
- }
- };
- m_bind = new BindMethod( m_componentManager.getComponentMetadata().isDS11(),
+ m_bind = new BindMethod( m_componentManager,
m_dependencyMetadata.getBind(),
m_componentInstance.getClass(),
m_dependencyMetadata.getName(),
- m_dependencyMetadata.getInterface(),
- logger
+ m_dependencyMetadata.getInterface()
);
- m_unbind = new UnbindMethod( m_componentManager.getComponentMetadata().isDS11(),
+ m_unbind = new UnbindMethod( m_componentManager,
m_dependencyMetadata.getUnbind(),
m_componentInstance.getClass(),
m_dependencyMetadata.getName(),
- m_dependencyMetadata.getInterface(),
- logger
+ m_dependencyMetadata.getInterface()
);
}
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 3b2a17e..bcd5d4a 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
@@ -19,14 +19,14 @@
package org.apache.felix.scr.impl.manager;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.util.Dictionary;
import java.util.Iterator;
import java.util.List;
import org.apache.felix.scr.impl.BundleComponentActivator;
-import org.apache.felix.scr.impl.helper.ReflectionHelper;
+import org.apache.felix.scr.impl.helper.ActivateMethod;
+import org.apache.felix.scr.impl.helper.DeactivateMethod;
+import org.apache.felix.scr.impl.helper.ModifiedMethod;
import org.apache.felix.scr.impl.metadata.ComponentMetadata;
import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
import org.osgi.framework.ServiceRegistration;
@@ -49,13 +49,13 @@
private ComponentContext m_componentContext;
// the activate method
- private Method activateMethod = ReflectionHelper.SENTINEL;
+ private ActivateMethod m_activateMethod;
// the deactivate method
- private Method deactivateMethod = ReflectionHelper.SENTINEL;
+ private DeactivateMethod m_deactivateMethod;
// the modify method
- private Method modifyMethod = ReflectionHelper.SENTINEL;
+ private ModifiedMethod m_modifyMethod;
// optional properties provided in the ComponentFactory.newInstance method
private Dictionary m_factoryProperties;
@@ -139,7 +139,8 @@
protected Object createImplementationObject( ComponentContext componentContext )
{
- Object implementationObject;
+ final Class implementationObjectClass;
+ final Object implementationObject;
// 1. Load the component implementation class
// 2. Create the component instance and component context
@@ -147,12 +148,12 @@
try
{
// 112.4.4 The class is retrieved with the loadClass method of the component's bundle
- Class c = getActivator().getBundleContext().getBundle().loadClass(
+ implementationObjectClass = getActivator().getBundleContext().getBundle().loadClass(
getComponentMetadata().getImplementationClassName() );
// 112.4.4 The class must be public and have a public constructor without arguments so component instances
// may be created by the SCR with the newInstance method on Class
- implementationObject = c.newInstance();
+ implementationObject = implementationObjectClass.newInstance();
}
catch ( Exception ex )
{
@@ -188,23 +189,14 @@
}
// get the method
- if ( activateMethod == ReflectionHelper.SENTINEL )
+ if ( m_activateMethod == null)
{
- // FELIX-1437: New signatures only with DS 1.1 namespace declaration
- if ( getComponentMetadata().isDS11() )
- {
- activateMethod = getMethod( implementationObject, getComponentMetadata().getActivate(),
- ReflectionHelper.ACTIVATE_ACCEPTED_PARAMETERS );
- }
- else
- {
- activateMethod = getMethod( implementationObject, getComponentMetadata().getActivate(),
- ReflectionHelper.ACTIVATOR_10_ACCEPTED_PARAMETERS );
- }
+ m_activateMethod = new ActivateMethod( this, getComponentMetadata().getActivate(), implementationObjectClass );
}
// 4. Call the activate method, if present
- if ( activateMethod != null && !invokeMethod( activateMethod, implementationObject, componentContext, -1 ) )
+ if ( !m_activateMethod.invoke( implementationObject,
+ new ActivateMethod.ActivatorParameter( 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
@@ -215,7 +207,7 @@
dm.close();
}
- implementationObject = null;
+ return null;
}
return implementationObject;
@@ -227,29 +219,18 @@
{
// get the method
- if ( deactivateMethod == ReflectionHelper.SENTINEL )
+ if ( m_deactivateMethod == null )
{
- // FELIX-1437: New signatures only with DS 1.1 namespace declaration
- if ( getComponentMetadata().isDS11() )
- {
- deactivateMethod = getMethod( implementationObject, getComponentMetadata().getDeactivate(),
- ReflectionHelper.DEACTIVATE_ACCEPTED_PARAMETERS );
- }
- else
- {
- deactivateMethod = getMethod( implementationObject, getComponentMetadata().getDeactivate(),
- ReflectionHelper.ACTIVATOR_10_ACCEPTED_PARAMETERS );
- }
+ m_deactivateMethod = new DeactivateMethod( this, getComponentMetadata().getDeactivate(), implementationObject
+ .getClass() );
}
// 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
- if ( deactivateMethod != null )
- {
- invokeMethod( deactivateMethod, implementationObject, componentContext, reason );
- }
+ m_deactivateMethod.invoke( implementationObject, new ActivateMethod.ActivatorParameter( componentContext,
+ reason ) );
// 2. Unbind any bound services
Iterator it = getDependencyManagers();
@@ -410,13 +391,9 @@
// invariant: we have a modified method name
// 2. get and check configured method
- Method modifyMethod = getModifyMethod();
- if ( modifyMethod == null )
+ if ( m_modifyMethod == null )
{
- // log an error if the declared method cannot be found
- log( LogService.LOG_ERROR, "Declared modify method '" + getComponentMetadata().getModified()
- + "' cannot be found, configuring by reactivation", getComponentMetadata(), null );
- return false;
+ m_modifyMethod = new ModifiedMethod( this, getComponentMetadata().getModified(), getInstance().getClass() );
}
// invariant: modify method is configured and found
@@ -438,7 +415,13 @@
// invariant: modify method existing and no static bound service changes
// 4. call method (nothing to do when failed, since it has already been logged)
- invokeMethod( modifyMethod, m_implementationObject, m_componentContext, -1 );
+ if ( !m_modifyMethod.invoke( getInstance(), new ActivateMethod.ActivatorParameter( m_componentContext, -1 ) ) )
+ {
+ // log an error if the declared method cannot be found
+ log( LogService.LOG_ERROR, "Declared modify method '" + getComponentMetadata().getModified()
+ + "' cannot be found, configuring by reactivation", getComponentMetadata(), null );
+ return false;
+ }
// 5. update the target filter on the services now, this may still
// result in unsatisfied dependencies, in which case we abort
@@ -481,139 +464,4 @@
// 7. everything set and done, the component has been udpated
return true;
}
-
-
- /**
- * Returns the configured modify method or <code>null</code> if the
- * configured method cannot be found.
- */
- private Method getModifyMethod()
- {
- // ensure the method object is known
- if ( modifyMethod == ReflectionHelper.SENTINEL )
- {
- modifyMethod = getMethod( m_implementationObject, getComponentMetadata().getModified(),
- ReflectionHelper.ACTIVATE_ACCEPTED_PARAMETERS );
- }
-
- return modifyMethod;
- }
-
-
- /**
- * Find the method with the given name in the class hierarchy of the
- * implementation object's class. This method looks for methods which have
- * one of the parameter lists of the {@link #ACTIVATE_PARAMETER_LIST} array.
- *
- * @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,
- final ReflectionHelper.MethodTester methodTester )
- {
- try
- {
- return ReflectionHelper.getMethod( implementationObject.getClass(), methodName, methodTester );
- }
- catch ( InvocationTargetException ite )
- {
- // We can safely ignore this one
- log( LogService.LOG_WARNING, methodName + " cannot be found", getComponentMetadata(), ite
- .getTargetException() );
- }
- catch ( NoSuchMethodException ex )
- {
- // We can safely ignore this one
- log( LogService.LOG_DEBUG, methodName + " method is not implemented", getComponentMetadata(), null );
- }
-
- return null;
- }
-
-
- /**
- * Invokes the given method on the <code>implementationObject</code> using
- * the <code>componentContext</code> as the base to create method argument
- * list.
- *
- * @param method The method to call. This method must already have been
- * made accessible by calling
- * <code>Method.setAccessible(boolean)</code>.
- * @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
- * an exception.
- *
- * @throws NullPointerException if any of the parameters is <code>null</code>.
- */
- private boolean invokeMethod( final Method method, final Object implementationObject,
- final ComponentContext componentContext, int reason )
- {
- final String methodName = method.getName();
- try
- {
- // build argument list
- Class[] paramTypes = method.getParameterTypes();
- Object[] param = new Object[paramTypes.length];
- for ( int i = 0; i < param.length; i++ )
- {
- if ( paramTypes[i] == ReflectionHelper.COMPONENT_CONTEXT_CLASS )
- {
- param[i] = componentContext;
- }
- else if ( paramTypes[i] == ReflectionHelper.BUNDLE_CONTEXT_CLASS )
- {
- param[i] = componentContext.getBundleContext();
- }
- else if ( paramTypes[i] == ReflectionHelper.MAP_CLASS )
- {
- // note: getProperties() returns a ReadOnlyDictionary 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, param );
- }
- catch ( IllegalAccessException ex )
- {
- // Ignored, but should it be logged?
- log( LogService.LOG_DEBUG, methodName + " 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
- log( LogService.LOG_ERROR, "The " + methodName + " method has thrown an exception", getComponentMetadata(),
- ex.getCause() );
-
- // 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;
- }
}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/helper/ReflectionHelperTest.java b/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java
similarity index 74%
rename from scr/src/test/java/org/apache/felix/scr/impl/helper/ReflectionHelperTest.java
rename to scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java
index e9212b5..bc7faa8 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/helper/ReflectionHelperTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java
@@ -19,25 +19,30 @@
package org.apache.felix.scr.impl.helper;
-import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.util.Hashtable;
import junit.framework.TestCase;
-import org.apache.felix.scr.impl.helper.ReflectionHelper;
+import org.apache.felix.scr.impl.manager.ImmediateComponentManager;
+import org.apache.felix.scr.impl.metadata.ComponentMetadata;
import org.apache.felix.scr.impl.metadata.instances.AcceptMethod;
import org.apache.felix.scr.impl.metadata.instances.BaseObject;
import org.apache.felix.scr.impl.metadata.instances.Level1Object;
import org.apache.felix.scr.impl.metadata.instances.Level3Object;
-import org.apache.felix.scr.impl.metadata.instances.MethodNameException;
import org.apache.felix.scr.impl.metadata.instances2.Level2Object;
+import org.easymock.EasyMock;
+import org.osgi.service.component.ComponentContext;
-public class ReflectionHelperTest extends TestCase
+public class ActivateMethodTest extends TestCase
{
private static final Class ACCEPT_METHOD_CLASS = AcceptMethod.class;
+ private ComponentContext m_ctx;
+
BaseObject base = new BaseObject();
Level1Object level1 = new Level1Object();
@@ -46,10 +51,15 @@
Level3Object level3 = new Level3Object();
-
- public void test_sentinel() throws Exception
+ protected void setUp() throws Exception
{
- assertNotNull( "Sentinel is null", ReflectionHelper.SENTINEL );
+ super.setUp();
+
+ m_ctx = ( ComponentContext ) EasyMock.createNiceMock( ComponentContext.class );
+ EasyMock.expect( m_ctx.getProperties() ).andReturn( new Hashtable() ).anyTimes();
+ EasyMock.replay( new Object[]
+ { m_ctx } );
+
}
@@ -138,9 +148,9 @@
public void test_getPackage() throws Exception
{
Class dpc = getClass().getClassLoader().loadClass( "DefaultPackageClass" );
- assertEquals( "", ReflectionHelper.getPackageName( dpc ) );
+ assertEquals( "", BaseMethod.getPackageName( dpc ) );
- assertEquals( "org.apache.felix.scr.impl.metadata.instances", ReflectionHelper.getPackageName( base.getClass() ) );
+ assertEquals( "org.apache.felix.scr.impl.metadata.instances", BaseMethod.getPackageName( base.getClass() ) );
}
@@ -195,13 +205,7 @@
// this must fail to find a method, since Level2Object's activate_suitable
// is private and terminates the search for Level3Object
- try {
- checkMethod( level3, "activate_suitable" );
- fail("Level3Object must not find activate_suitable method");
- } catch (NoSuchMethodException nsme) {
- // expecting method lookup abort on suitable private
- // method in Level2Object class
- }
+ ensureMethodNotFoundMethod( level3, "activate_suitable" );
}
@@ -215,22 +219,22 @@
* @param obj
* @param methodName
*/
- private void checkMethod( Object obj, String methodName ) throws NoSuchMethodException, InvocationTargetException,
- IllegalAccessException
+ private void checkMethod( BaseObject obj, String methodName )
{
- Method method = ReflectionHelper.getMethod( obj.getClass(), methodName,
- ReflectionHelper.ACTIVATE_ACCEPTED_PARAMETERS );
- try
+ ComponentMetadata metadata = new ComponentMetadata( 0 )
{
- method.invoke( obj, new Object[method.getParameterTypes().length] );
- fail( "Expected MethodNameException being thrown" );
- }
- catch ( InvocationTargetException ite )
- {
- Throwable target = ite.getTargetException();
- assertTrue( "Expected MethodNameException", target instanceof MethodNameException );
- assertEquals( methodName, target.getMessage() );
- }
+ public boolean isDS11()
+ {
+ return true;
+ }
+ };
+ ImmediateComponentManager icm = new ImmediateComponentManager( null, metadata );
+ ActivateMethod am = new ActivateMethod( icm, methodName, obj.getClass() );
+ am.invoke( obj, new ActivateMethod.ActivatorParameter( m_ctx, -1 ) );
+ Method m = get(am, "m_method");
+ assertNotNull( m );
+ assertEquals( methodName, m.getName() );
+ assertEquals( methodName, obj.getCalledMethod() );
}
@@ -243,18 +247,20 @@
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
- private void ensureMethodNotFoundMethod( Object obj, String methodName ) throws InvocationTargetException,
- IllegalAccessException
+ private void ensureMethodNotFoundMethod( BaseObject obj, String methodName )
{
- try
+ ComponentMetadata metadata = new ComponentMetadata( 0 )
{
- checkMethod( obj, methodName );
- fail( "Expected to not find method " + methodName + " for " + obj.getClass() );
- }
- catch ( NoSuchMethodException nsme )
- {
- // expected not to find a method
- }
+ public boolean isDS11()
+ {
+ return true;
+ }
+ };
+ ImmediateComponentManager icm = new ImmediateComponentManager( null, metadata );
+ ActivateMethod am = new ActivateMethod( icm, methodName, obj.getClass() );
+ am.invoke( obj, new ActivateMethod.ActivatorParameter( m_ctx, -1 ) );
+ assertNull( get( am, "m_method" ) );
+ assertNull( obj.getCalledMethod() );
}
@@ -262,7 +268,30 @@
throws NoSuchMethodException
{
Method method = ACCEPT_METHOD_CLASS.getDeclaredMethod( methodName, null );
- boolean accepted = ReflectionHelper.accept( method, acceptPrivate, acceptPackage );
+ boolean accepted = BaseMethod.accept( method, acceptPrivate, acceptPackage );
assertEquals( expected, accepted );
}
+
+
+ private static Method get( final BaseMethod baseMethod, final String fieldName )
+ {
+ try
+ {
+ Field field = BaseMethod.class.getDeclaredField( fieldName );
+ field.setAccessible( true );
+ Object value = field.get( baseMethod );
+ if ( value == null || value instanceof Method )
+ {
+ return ( Method ) value;
+ }
+ fail( "Field " + field + " is not of type Method" );
+ }
+ catch ( Throwable t )
+ {
+ fail( "Failure accessing field " + fieldName + " in " + baseMethod + ": " + t );
+ }
+
+ // Compiler does not know about fail()
+ return null;
+ }
}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/manager/BindMethodTest.java b/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java
similarity index 94%
rename from scr/src/test/java/org/apache/felix/scr/impl/manager/BindMethodTest.java
rename to scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java
index 6d4ae02..e09ef07 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/manager/BindMethodTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/helper/BindMethodTest.java
@@ -16,16 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.scr.impl.manager;
+package org.apache.felix.scr.impl.helper;
import junit.framework.TestCase;
+import org.apache.felix.scr.impl.helper.BindMethod;
+import org.apache.felix.scr.impl.manager.ImmediateComponentManager;
import org.apache.felix.scr.impl.manager.components.FakeService;
import org.apache.felix.scr.impl.manager.components.T1;
import org.apache.felix.scr.impl.manager.components.T1a;
import org.apache.felix.scr.impl.manager.components.T3;
import org.apache.felix.scr.impl.manager.components2.T2;
+import org.apache.felix.scr.impl.metadata.ComponentMetadata;
import org.easymock.EasyMock;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
@@ -431,33 +434,15 @@
private void testMethod( final String methodName, final T1 component, final boolean isDS11,
final String expectCallPerformed )
{
- BindMethod bm = new BindMethod( isDS11, methodName, component.getClass(), "reference", FakeService.class
- .getName(), new SysOutLogger() );
+ ComponentMetadata metadata = new ComponentMetadata( 0 ) {
+ public boolean isDS11() {
+ return isDS11;
+ }
+ };
+ ImmediateComponentManager icm = new ImmediateComponentManager( null, metadata );
+ BindMethod bm = new BindMethod( icm, methodName, component.getClass(), "reference",
+ FakeService.class.getName() );
bm.invoke( component, m_service );
assertEquals( expectCallPerformed, component.callPerformed );
}
-
- private static class SysOutLogger implements BindMethod.Logger
- {
-
- private static final String[] LEVELS = new String[]
- { "ERROR", "WARNING", "INFO", "DEBUG" };
-
-
- public void log( int level, String message )
- {
- log( level, message, null );
- }
-
-
- public void log( int level, String message, Throwable ex )
- {
- System.out.println( LEVELS[level - 1] + " - " + message );
- if ( ex != null )
- {
- System.out.println( ex.getClass().getName() + "-" + ex.getMessage() );
- }
- }
- }
-
}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/BaseObject.java b/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/BaseObject.java
index 59fd9fa..7c8dd0f 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/BaseObject.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/BaseObject.java
@@ -31,26 +31,41 @@
public class BaseObject
{
+ private String m_calledMethod;
+
+
+ public String getCalledMethod()
+ {
+ String cm = m_calledMethod;
+ m_calledMethod = null;
+ return cm;
+ }
+
+
+ protected void setCalledMethod(String calledMethod) {
+ m_calledMethod = calledMethod;
+ }
+
private void activate_no_arg()
{
- throw new MethodNameException( "activate_no_arg" );
+ setCalledMethod( "activate_no_arg" );
}
protected void activate_comp( ComponentContext ctx )
{
- throw new MethodNameException( "activate_comp" );
+ setCalledMethod( "activate_comp" );
}
void activate_comp_bundle( ComponentContext ctx, BundleContext bundle )
{
- throw new MethodNameException( "activate_comp_bundle" );
+ setCalledMethod( "activate_comp_bundle" );
}
protected void activate_suitable( ComponentContext ctx )
{
- throw new MethodNameException( "activate_suitable" );
+ setCalledMethod( "activate_suitable" );
}
}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/Level1Object.java b/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/Level1Object.java
index 4082b3e..199ca7f 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/Level1Object.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/Level1Object.java
@@ -29,13 +29,13 @@
private void activate_level1_bundle( BundleContext ctx )
{
- throw new MethodNameException("activate_level1_bundle");
+ setCalledMethod("activate_level1_bundle");
}
protected void activate_level1_map( Map props )
{
- throw new MethodNameException("activate_level1_map");
+ setCalledMethod("activate_level1_map");
}
}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/Level3Object.java b/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/Level3Object.java
index 72c3236..27efc6a 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/Level3Object.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances/Level3Object.java
@@ -30,7 +30,7 @@
private void activate_comp_map( ComponentContext ctx, Map map )
{
- throw new MethodNameException("activate_comp_map");
+ setCalledMethod("activate_comp_map");
}
@@ -38,12 +38,12 @@
// Map has higher precedence
public void activate_collision()
{
- throw new MethodNameException("not_expected_to_be_found");
+ setCalledMethod("not_expected_to_be_found");
}
public void activate_collision( Map map )
{
- throw new MethodNameException("activate_collision");
+ setCalledMethod("activate_collision");
}
}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances2/Level2Object.java b/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances2/Level2Object.java
index 510f941..64a24ba 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances2/Level2Object.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/metadata/instances2/Level2Object.java
@@ -22,7 +22,6 @@
import java.util.Map;
import org.apache.felix.scr.impl.metadata.instances.Level1Object;
-import org.apache.felix.scr.impl.metadata.instances.MethodNameException;
import org.osgi.service.component.ComponentContext;
@@ -31,7 +30,7 @@
private void activate_comp_map( ComponentContext ctx, Map map )
{
- throw new MethodNameException( "activate_comp_map" );
+ setCalledMethod( "activate_comp_map" );
}
@@ -39,18 +38,18 @@
// Map has higher precedence
public void activate_collision()
{
- throw new MethodNameException( "not_expected_to_be_found" );
+ setCalledMethod( "not_expected_to_be_found" );
}
public void activate_collision( Map map )
{
- throw new MethodNameException( "activate_collision" );
+ setCalledMethod( "activate_collision" );
}
private void activate_suitable( Map map )
{
- throw new MethodNameException( "activate_suitable" );
+ setCalledMethod( "activate_suitable" );
}
}