FELIX-927 Complete bind/unbind method signature extension for
methods with service object assignable plus Map and support
for private/default methods. Plust test cases in BindMethodTest
FELIX-1437 Only support new signatures and private/package support
for DS 1.1 declared components
FELIX-1440 Add SuitableMethodNotAccessibleException to support
method lookup termination if a class provides suitable methods
which are not accessible. Plus test case in BindMethodTest
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@800244 13f79535-47bb-0310-9956-ffa450edef68
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/manager/BindMethod.java
index 9ecbb27..524ffc3 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/BindMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/BindMethod.java
@@ -21,9 +21,7 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.HashMap;
-import java.util.Map;
+import org.apache.felix.scr.impl.helper.ReadOnlyDictionary;
import org.apache.felix.scr.impl.helper.ReflectionHelper;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
@@ -36,6 +34,7 @@
class BindMethod
{
+ private final boolean m_isDS11;
private final String m_methodName;
private final Class m_componentClass;
private final String m_referenceName;
@@ -46,9 +45,10 @@
private State m_state;
- BindMethod( final String methodName, final Class componentClass, final String referenceName,
+ BindMethod( final boolean isDS11, final String methodName, final Class componentClass, final String referenceName,
final String referenceClassName, final Logger logger )
{
+ m_isDS11 = isDS11;
m_methodName = methodName;
m_componentClass = componentClass;
m_referenceName = referenceName;
@@ -65,125 +65,383 @@
}
- private Method findMethod( final Class targetClass ) throws InvocationTargetException
+ /**
+ * 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.
+ * @throws SuitableMethodNotAccessibleException If a suitable method was
+ * found which is not accessible
+ */
+ private Method findMethod( final Class targetClass, final boolean acceptPrivate, final boolean acceptPackage )
+ throws InvocationTargetException//, SuitableMethodNotAccessibleException
{
- Class parameterClass = null;
-
// 112.3.1 The method is searched for using the following priority
// 1. The method's parameter type is org.osgi.framework.ServiceReference
// 2. The method's parameter type is the type specified by the
// reference's interface attribute
// 3. The method's parameter type is assignable from the type specified
// by the reference's interface attribute
- try
+
+ // Case 1 - Service reference parameter
+ Method method = getServiceReferenceMethod( targetClass, acceptPrivate, acceptPackage );
+ if ( method != null )
{
- // Case 1 - ServiceReference parameter
- return ReflectionHelper.getMethod( targetClass, m_methodName, new Class[]
- { ReflectionHelper.SERVICE_REFERENCE_CLASS }, false, // do not accept private methods
- false // do not accept package methods
- );
+ return method;
}
- catch ( NoSuchMethodException ex )
+
+ // for further methods we need the class of the service object
+ final Class parameterClass = getParameterClass( targetClass );
+ if ( parameterClass != null )
{
+ // Case2 - Service object parameter
+ method = getServiceObjectMethod( targetClass, parameterClass, acceptPrivate, acceptPackage );
+ if ( method != null )
+ {
+ return method;
+ }
+
+ // Case 3 - Service interface assignement compatible methods
+ SuitableMethodNotAccessibleException methodAccessibleEx = null;
try
{
- // Case2 - Service object parameter
-
- // need the class loader of the target class, which may be the
- // system classloader, which case getClassLoader may retur null
- ClassLoader loader = targetClass.getClassLoader();
- if ( loader == null )
+ method = getServiceObjectAssignableMethod( targetClass, parameterClass, acceptPrivate, acceptPackage );
+ if ( method != null )
{
- loader = ClassLoader.getSystemClassLoader();
+ return method;
}
-
- parameterClass = loader.loadClass( m_referenceClassName );
- return ReflectionHelper.getMethod( targetClass, m_methodName, new Class[]
- { parameterClass }, false, false );
}
- catch ( NoSuchMethodException ex2 )
+ catch ( SuitableMethodNotAccessibleException ex )
+ {
+ methodAccessibleEx = ex;
+ }
+
+ // signatures taking a map are only supported starting with DS 1.1
+ if ( m_isDS11 )
{
- // Case 3 - Service interface assignement compatible methods
-
- // Get all potential bind methods
- Method candidateBindMethods[] = targetClass.getDeclaredMethods();
-
- // Iterate over them
- for ( int i = 0; i < candidateBindMethods.length; i++ )
+ // Case 4: same as case 2, but + Map param (DS 1.1 only)
+ method = getServiceObjectWithMapMethod( targetClass, parameterClass, acceptPrivate, acceptPackage );
+ if ( method != null )
{
- Method method = candidateBindMethods[i];
-
- // Get the parameters for the current method
- Class[] parameters = method.getParameterTypes();
-
- // Select only the methods that receive a single
- // parameter
- // and a matching name
- if ( parameters.length == 1 && method.getName().equals( m_methodName ) )
- {
-
- // Get the parameter type
- Class theParameter = parameters[0];
-
- // Check if the parameter type is ServiceReference
- // or is assignable from the type specified by the
- // reference's interface attribute
- if ( theParameter.isAssignableFrom( parameterClass ) )
- {
-
- // Final check: it must be public or protected
- if ( Modifier.isPublic( method.getModifiers() )
- || Modifier.isProtected( method.getModifiers() ) )
- {
- if ( !method.isAccessible() )
- {
- method.setAccessible( true );
- }
- return method;
- }
- }
- }
+ return method;
}
- // Case 4: same as case 2, but + Map param
+ // Case 5: same as case 3, but + Map param (DS 1.1 only)
try
{
- // need the class loader of the target class, which may be the
- // system classloader, which case getClassLoader may retur null
- ClassLoader loader = targetClass.getClassLoader();
- if ( loader == null )
+ method = getServiceObjectAssignableWithMapMethod( targetClass, parameterClass, acceptPrivate,
+ acceptPackage );
+ if ( method != null )
{
- loader = ClassLoader.getSystemClassLoader();
+ return method;
}
-
- parameterClass = loader.loadClass( m_referenceClassName );
- return ReflectionHelper.getMethod( targetClass, m_methodName, new Class[]
- { parameterClass, Map.class }, false, false );
}
- catch ( NoSuchMethodException ex3 )
+ catch ( SuitableMethodNotAccessibleException ex )
{
+ methodAccessibleEx = ex;
+ }
- }
- catch ( ClassNotFoundException ex3 )
- {
- // if we can't load the class, perhaps the method is declared in a super class
- // so we try this class next
- }
}
- catch ( ClassNotFoundException ex2 )
+
+ // if at least one suitable method could be found but none of
+ // the suitable methods are accessible, we have to terminate
+ if ( methodAccessibleEx != null )
{
- // if we can't load the class, perhaps the method is declared in a super class
- // so we try this class next
+ m_logger.log( LogService.LOG_ERROR,
+ "DependencyManager : Suitable but non-accessible method found in class " + targetClass.getName() );
+ return null;
}
- // TODO: Case 5: same as case 3, but + Map param
}
// if we get here, we have no method, so check the super class
- Class superClass = targetClass.getSuperclass();
- return ( superClass != null ) ? findMethod( superClass ) : null;
+ 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);
+ }
+
+
+ /**
+ * Returns the class object representing the class of the service reference
+ * named by the {@link #m_referenceClassName} field. The class loader of
+ * the <code>targetClass</code> is used to load the service class.
+ * <p>
+ * It may well be possible, that the classloader of the target class cannot
+ * see the service object class, for example if the service reference is
+ * inherited from a component class of another bundle.
+ *
+ * @return The class object for the referred to service or <code>null</code>
+ * if the class loader of the <code>targetClass</code> cannot see that
+ * class.
+ */
+ private Class getParameterClass( final Class targetClass )
+ {
+ try
+ {
+ // need the class loader of the target class, which may be the
+ // system classloader, which case getClassLoader may retur null
+ ClassLoader loader = targetClass.getClassLoader();
+ if ( loader == null )
+ {
+ loader = ClassLoader.getSystemClassLoader();
+ }
+
+ return loader.loadClass( m_referenceClassName );
+
+ }
+ catch ( ClassNotFoundException cnfe )
+ {
+ // if we can't load the class, perhaps the method is declared in a
+ // super class so we try this class next
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Returns a method taking a single <code>ServiceReference</code> object
+ * as a parameter or <code>null</code> if no such method exists.
+ *
+ * @param targetClass The class in which to look for the method. Only this
+ * class is searched 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.
+ * @throws InvocationTargetException If an unexpected Throwable is caught
+ * trying to find the requested method.
+ */
+ private Method getServiceReferenceMethod( final Class targetClass, boolean acceptPrivate, boolean acceptPackage )
+ throws InvocationTargetException
+ {
+ try
+ {
+ return ReflectionHelper.getMethod( targetClass, m_methodName, new Class[]
+ { ReflectionHelper.SERVICE_REFERENCE_CLASS }, acceptPrivate, acceptPackage );
+ }
+ catch ( NoSuchMethodException e )
+ {
+ // the named method could not be found
+ }
+
+ // no method taking service reference
+ return null;
+ }
+
+
+ /**
+ * Returns a method taking a single parameter of the exact type declared
+ * for the service reference or <code>null</code> if no such method exists.
+ *
+ * @param targetClass The class in which to look for the method. Only this
+ * class is searched 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.
+ * @throws InvocationTargetException If an unexpected Throwable is caught
+ * trying to find the requested method.
+ */
+ private Method getServiceObjectMethod( final Class targetClass, final Class parameterClass, boolean acceptPrivate,
+ boolean acceptPackage ) throws InvocationTargetException
+ {
+ try
+ {
+ return ReflectionHelper.getMethod( targetClass, m_methodName, new Class[]
+ { parameterClass }, acceptPrivate, acceptPackage );
+ }
+ catch ( NoSuchMethodException nsme )
+ {
+ // no method taking service object
+ }
+
+ // no method taking service object
+ return null;
+ }
+
+
+ /**
+ * Returns a method taking a single object whose type is assignment
+ * compatible with the declared service type or <code>null</code> if no
+ * such method exists.
+ *
+ * @param targetClass The class in which to look for the method. Only this
+ * class is searched 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.
+ * @throws SuitableMethodNotAccessibleException If a suitable method was
+ * found which is not accessible
+ */
+ private Method getServiceObjectAssignableMethod( final Class targetClass, final Class parameterClass,
+ boolean acceptPrivate, boolean acceptPackage ) throws SuitableMethodNotAccessibleException
+ {
+ // Get all potential bind methods
+ Method candidateBindMethods[] = targetClass.getDeclaredMethods();
+ boolean suitableNotAccessible = false;
+
+ // Iterate over them
+ for ( int i = 0; i < candidateBindMethods.length; i++ )
+ {
+ Method method = candidateBindMethods[i];
+
+ // Get the parameters for the current method
+ Class[] parameters = method.getParameterTypes();
+
+ // Select only the methods that receive a single
+ // parameter
+ // and a matching name
+ if ( parameters.length == 1 && method.getName().equals( m_methodName ) )
+ {
+
+ // Get the parameter type
+ final Class theParameter = parameters[0];
+
+ // Check if the parameter type is ServiceReference
+ // or is assignable from the type specified by the
+ // reference's interface attribute
+ if ( theParameter.isAssignableFrom( parameterClass ) )
+ {
+ if ( ReflectionHelper.accept( method, acceptPrivate, acceptPackage ) )
+ {
+ return method;
+ }
+
+ // suitable method is not accessible, flag for exception
+ suitableNotAccessible = true;
+ }
+ }
+ }
+
+ // if one or more suitable methods which are not accessible is/are
+ // found an exception is thrown
+ if ( suitableNotAccessible )
+ {
+ throw new SuitableMethodNotAccessibleException();
+ }
+
+ // no method with assignment compatible argument found
+ return null;
+ }
+
+
+ /**
+ * Returns a method taking two parameters, the first being of the exact
+ * type declared for the service reference and the second being a
+ * <code>Map</code> or <code>null</code> if no such method exists.
+ *
+ * @param targetClass The class in which to look for the method. Only this
+ * class is searched 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.
+ * @throws InvocationTargetException If an unexpected Throwable is caught
+ * trying to find the requested method.
+ */
+ private Method getServiceObjectWithMapMethod( final Class targetClass, final Class parameterClass,
+ boolean acceptPrivate, boolean acceptPackage ) throws InvocationTargetException
+ {
+ try
+ {
+ return ReflectionHelper.getMethod( targetClass, m_methodName, new Class[]
+ { parameterClass, ReflectionHelper.MAP_CLASS }, acceptPrivate, acceptPackage );
+ }
+ catch ( NoSuchMethodException nsme )
+ {
+ // no method taking service object
+ }
+
+ // no method taking service object
+ return null;
+ }
+
+
+ /**
+ * Returns a method taking two parameters, the first being an object
+ * whose type is assignment compatible with the declared service type and
+ * the second being a <code>Map</code> or <code>null</code> if no such
+ * method exists.
+ *
+ * @param targetClass The class in which to look for the method. Only this
+ * class is searched 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.
+ * @throws SuitableMethodNotAccessibleException If a suitable method was
+ * found which is not accessible
+ */
+ private Method getServiceObjectAssignableWithMapMethod( final Class targetClass, final Class parameterClass,
+ boolean acceptPrivate, boolean acceptPackage ) throws SuitableMethodNotAccessibleException
+ {
+ // Get all potential bind methods
+ Method candidateBindMethods[] = targetClass.getDeclaredMethods();
+ boolean suitableNotAccessible = false;
+
+ // Iterate over them
+ for ( int i = 0; i < candidateBindMethods.length; i++ )
+ {
+ final Method method = candidateBindMethods[i];
+ final Class[] parameters = method.getParameterTypes();
+ if ( parameters.length == 2 && method.getName().equals( m_methodName ) )
+ {
+
+ // parameters must be refclass,map
+ if ( parameters[0].isAssignableFrom( parameterClass ) && parameters[1] == ReflectionHelper.MAP_CLASS )
+ {
+ if ( ReflectionHelper.accept( method, acceptPrivate, acceptPackage ) )
+ {
+ return method;
+ }
+
+ // suitable method is not accessible, flag for exception
+ suitableNotAccessible = true;
+ }
+ }
+ }
+
+ // if one or more suitable methods which are not accessible is/are
+ // found an exception is thrown
+ if ( suitableNotAccessible )
+ {
+ throw new SuitableMethodNotAccessibleException();
+ }
+
+ // no method with assignment compatible argument found
+ return null;
}
@@ -191,7 +449,6 @@
{
final Class[] paramTypes = m_method.getParameterTypes();
final Object[] params = new Object[paramTypes.length];
- Map properties = null;
for ( int i = 0; i < params.length; i++ )
{
if ( paramTypes[i] == ReflectionHelper.SERVICE_REFERENCE_CLASS )
@@ -200,21 +457,7 @@
}
else if ( paramTypes[i] == ReflectionHelper.MAP_CLASS )
{
- if ( properties == null )
- {
- final ServiceReference serviceReference = service.getReference();
- properties = new HashMap();
- final String[] keys = serviceReference.getPropertyKeys();
- if ( keys != null )
- {
- for ( int j = 0; j < keys.length; j++ )
- {
- final String key = keys[j];
- properties.put( key, serviceReference.getProperty( key ) );
- }
- }
- }
- params[i] = properties;
+ params[i] = new ReadOnlyDictionary( service.getReference() );
}
else
{
@@ -288,7 +531,9 @@
m_logger.log( LogService.LOG_DEBUG, "getting " + getMethodNamePrefix() + "bind: " + m_methodName );
try
{
- m_method = findMethod( m_componentClass );
+ // 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();
@@ -358,4 +603,10 @@
}
+ //---------- Logger ------------------------------------
+
+ static class SuitableMethodNotAccessibleException extends Exception
+ {
+ }
+
}
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/manager/BindMethodTest.java
index 9fd1acd..6d4ae02 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/manager/BindMethodTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/manager/BindMethodTest.java
@@ -19,10 +19,13 @@
package org.apache.felix.scr.impl.manager;
-import java.util.Map;
-
import junit.framework.TestCase;
+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.easymock.EasyMock;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
@@ -64,281 +67,374 @@
public void test_Unexistent()
{
- System.out.println();
- final T1 t1 = new T1();
- createMethod( "unexistent", T1.class ).invoke( t1, m_service );
- assertNull( t1.callPerformed );
+ testMethod( "unexistent", new T1(), false, null );
+ testMethod( "unexistent", new T1(), true, null );
+ testMethod( "unexistent", new T2(), false, null );
+ testMethod( "unexistent", new T2(), true, null );
+ testMethod( "unexistent", new T3(), false, null );
+ testMethod( "unexistent", new T3(), true, null );
}
public void test_privateT1()
{
- System.out.println();
- final T1 t1 = new T1();
- createMethod( "privateT1", T1.class ).invoke( t1, m_service );
- assertNull( t1.callPerformed );
+ testMethod( "privateT1", new T1(), false, null );
+ testMethod( "privateT1", new T1(), true, null );
+ testMethod( "privateT1", new T2(), false, null );
+ testMethod( "privateT1", new T2(), true, null );
+ testMethod( "privateT1", new T3(), false, null );
+ testMethod( "privateT1", new T3(), true, null );
+ }
+
+
+ public void test_privateT1SR()
+ {
+ testMethod( "privateT1SR", new T1(), false, null );
+ testMethod( "privateT1SR", new T1(), true, "privateT1SR" );
+ testMethod( "privateT1SR", new T2(), false, null );
+ testMethod( "privateT1SR", new T2(), true, null );
+ }
+
+
+ public void test_privateT1SI()
+ {
+ testMethod( "privateT1SI", new T1(), false, null );
+ testMethod( "privateT1SI", new T1(), true, "privateT1SI" );
+ testMethod( "privateT1SI", new T2(), false, null );
+ testMethod( "privateT1SI", new T2(), true, null );
+ }
+
+
+ public void test_privateT1SIMap()
+ {
+ testMethod( "privateT1SIMap", new T1(), false, null );
+ testMethod( "privateT1SIMap", new T1(), true, "privateT1SIMap" );
+ testMethod( "privateT1SIMap", new T2(), false, null );
+ testMethod( "privateT1SIMap", new T2(), true, null );
+ }
+
+
+ public void test_privateT1SSI()
+ {
+ testMethod( "privateT1SSI", new T1(), false, null );
+ testMethod( "privateT1SSI", new T1(), true, "privateT1SSI" );
+ testMethod( "privateT1SSI", new T2(), false, null );
+ testMethod( "privateT1SSI", new T2(), true, null );
+ }
+
+
+ public void test_privateT1SSIMap()
+ {
+ testMethod( "privateT1SSIMap", new T1(), false, null );
+ testMethod( "privateT1SSIMap", new T1(), true, "privateT1SSIMap" );
+ testMethod( "privateT1SSIMap", new T2(), false, null );
+ testMethod( "privateT1SSIMap", new T2(), true, null );
+ }
+
+
+ public void test_privateT2()
+ {
+ testMethod( "privateT2", new T1(), false, null );
+ testMethod( "privateT2", new T1(), true, null );
+ testMethod( "privateT2", new T2(), false, null );
+ testMethod( "privateT2", new T2(), true, null );
+ }
+
+
+ public void test_privateT2SR()
+ {
+ testMethod( "privateT2SR", new T1(), false, null );
+ testMethod( "privateT2SR", new T1(), true, null );
+ testMethod( "privateT2SR", new T2(), false, null );
+ testMethod( "privateT2SR", new T2(), true, "privateT2SR" );
+ }
+
+
+ public void test_privateT2SI()
+ {
+ testMethod( "privateT2SI", new T1(), false, null );
+ testMethod( "privateT2SI", new T1(), true, null );
+ testMethod( "privateT2SI", new T2(), false, null );
+ testMethod( "privateT2SI", new T2(), true, "privateT2SI" );
+ }
+
+
+ public void test_privateT2SIMap()
+ {
+ testMethod( "privateT2SIMap", new T1(), false, null );
+ testMethod( "privateT2SIMap", new T1(), true, null );
+ testMethod( "privateT2SIMap", new T2(), false, null );
+ testMethod( "privateT2SIMap", new T2(), true, "privateT2SIMap" );
+ }
+
+
+ public void test_privateT2SSI()
+ {
+ testMethod( "privateT2SSI", new T1(), false, null );
+ testMethod( "privateT2SSI", new T1(), true, null );
+ testMethod( "privateT2SSI", new T2(), false, null );
+ testMethod( "privateT2SSI", new T2(), true, "privateT2SSI" );
+ }
+
+
+ public void test_privateT2SSIMap()
+ {
+ testMethod( "privateT2SSIMap", new T1(), false, null );
+ testMethod( "privateT2SSIMap", new T1(), true, null );
+ testMethod( "privateT2SSIMap", new T2(), false, null );
+ testMethod( "privateT2SSIMap", new T2(), true, "privateT2SSIMap" );
+ }
+
+
+ public void test_packageT1()
+ {
+ testMethod( "packageT1", new T1(), false, null );
+ testMethod( "packageT1", new T1(), true, null );
+ testMethod( "packageT1", new T2(), false, null );
+ testMethod( "packageT1", new T2(), true, null );
+ testMethod( "packageT1", new T3(), false, null );
+ testMethod( "packageT1", new T3(), true, null );
+ testMethod( "packageT1", new T1a(), false, null );
+ testMethod( "packageT1", new T1a(), true, null );
+ }
+
+
+ public void test_packageT1SR()
+ {
+ testMethod( "packageT1SR", new T1(), false, null );
+ testMethod( "packageT1SR", new T1(), true, "packageT1SR" );
+ testMethod( "packageT1SR", new T2(), false, null );
+ testMethod( "packageT1SR", new T2(), true, null );
+ testMethod( "packageT1SR", new T3(), false, null );
+ testMethod( "packageT1SR", new T3(), true, null );
+ testMethod( "packageT1SR", new T1a(), false, null );
+ testMethod( "packageT1SR", new T1a(), true, "packageT1SR" );
+ }
+
+
+ public void test_packageT1SI()
+ {
+ testMethod( "packageT1SI", new T1(), false, null );
+ testMethod( "packageT1SI", new T1(), true, "packageT1SI" );
+ testMethod( "packageT1SI", new T2(), false, null );
+ testMethod( "packageT1SI", new T2(), true, null );
+ testMethod( "packageT1SI", new T3(), false, null );
+ testMethod( "packageT1SI", new T3(), true, null );
+ testMethod( "packageT1SI", new T1a(), false, null );
+ testMethod( "packageT1SI", new T1a(), true, "packageT1SI" );
+ }
+
+
+ public void test_packageT1SIMap()
+ {
+ testMethod( "packageT1SIMap", new T1(), false, null );
+ testMethod( "packageT1SIMap", new T1(), true, "packageT1SIMap" );
+ testMethod( "packageT1SIMap", new T2(), false, null );
+ testMethod( "packageT1SIMap", new T2(), true, null );
+ testMethod( "packageT1SIMap", new T3(), false, null );
+ testMethod( "packageT1SIMap", new T3(), true, null );
+ testMethod( "packageT1SIMap", new T1a(), false, null );
+ testMethod( "packageT1SIMap", new T1a(), true, "packageT1SIMap" );
+ }
+
+
+ public void test_packageT1SSI()
+ {
+ testMethod( "packageT1SSI", new T1(), false, null );
+ testMethod( "packageT1SSI", new T1(), true, "packageT1SSI" );
+ testMethod( "packageT1SSI", new T2(), false, null );
+ testMethod( "packageT1SSI", new T2(), true, null );
+ testMethod( "packageT1SSI", new T3(), false, null );
+ testMethod( "packageT1SSI", new T3(), true, null );
+ testMethod( "packageT1SSI", new T1a(), false, null );
+ testMethod( "packageT1SSI", new T1a(), true, "packageT1SSI" );
+ }
+
+
+ public void test_packageT1SSIMap()
+ {
+ testMethod( "packageT1SSIMap", new T1(), false, null );
+ testMethod( "packageT1SSIMap", new T1(), true, "packageT1SSIMap" );
+ testMethod( "packageT1SSIMap", new T2(), false, null );
+ testMethod( "packageT1SSIMap", new T2(), true, null );
+ testMethod( "packageT1SSIMap", new T3(), false, null );
+ testMethod( "packageT1SSIMap", new T3(), true, null );
+ testMethod( "packageT1SSIMap", new T1a(), false, null );
+ testMethod( "packageT1SSIMap", new T1a(), true, "packageT1SSIMap" );
+ }
+
+
+ public void test_packageT2()
+ {
+ testMethod( "packageT2", new T1(), false, null );
+ testMethod( "packageT2", new T1(), true, null );
+ testMethod( "packageT2", new T2(), false, null );
+ testMethod( "packageT2", new T2(), true, null );
+ }
+
+
+ public void test_packageT2SR()
+ {
+ testMethod( "packageT2SR", new T1(), false, null );
+ testMethod( "packageT2SR", new T1(), true, null );
+ testMethod( "packageT2SR", new T2(), false, null );
+ testMethod( "packageT2SR", new T2(), true, "packageT2SR" );
+ }
+
+
+ public void test_packageT2SI()
+ {
+ testMethod( "packageT2SI", new T1(), false, null );
+ testMethod( "packageT2SI", new T1(), true, null );
+ testMethod( "packageT2SI", new T2(), false, null );
+ testMethod( "packageT2SI", new T2(), true, "packageT2SI" );
+ }
+
+
+ public void test_packageT2SIMap()
+ {
+ testMethod( "packageT2SIMap", new T1(), false, null );
+ testMethod( "packageT2SIMap", new T1(), true, null );
+ testMethod( "packageT2SIMap", new T2(), false, null );
+ testMethod( "packageT2SIMap", new T2(), true, "packageT2SIMap" );
+ }
+
+
+ public void test_packageT2SSI()
+ {
+ testMethod( "packageT2SSI", new T1(), false, null );
+ testMethod( "packageT2SSI", new T1(), true, null );
+ testMethod( "packageT2SSI", new T2(), false, null );
+ testMethod( "packageT2SSI", new T2(), true, "packageT2SSI" );
+ }
+
+
+ public void test_packageT2SSIMap()
+ {
+ testMethod( "packageT2SSIMap", new T1(), false, null );
+ testMethod( "packageT2SSIMap", new T1(), true, null );
+ testMethod( "packageT2SSIMap", new T2(), false, null );
+ testMethod( "packageT2SSIMap", new T2(), true, "packageT2SSIMap" );
}
public void test_protectedT1()
{
- System.out.println();
- final T1 t1 = new T1();
- createMethod( "protectedT1", T1.class ).invoke( t1, m_service );
- assertNull( t1.callPerformed );
+ testMethod( "protectedT1", new T1(), false, null );
+ testMethod( "protectedT1", new T1(), true, null );
+ testMethod( "protectedT1", new T2(), false, null );
+ testMethod( "protectedT1", new T2(), true, null );
}
public void test_protectedT1SR()
{
- System.out.println();
- final T1 t1 = new T1();
- createMethod( "protectedT1SR", T1.class ).invoke( t1, m_service );
- assertEquals( "protectedT1SR", t1.callPerformed );
+ testMethod( "protectedT1SR", new T1(), false, "protectedT1SR" );
+ testMethod( "protectedT1SR", new T1(), true, "protectedT1SR" );
+ testMethod( "protectedT1SR", new T2(), false, "protectedT1SR" );
+ testMethod( "protectedT1SR", new T2(), true, "protectedT1SR" );
}
public void test_protectedT1SI()
{
- System.out.println();
- final T1 t1 = new T1();
- createMethod( "protectedT1SI", T1.class ).invoke( t1, m_service );
- assertEquals( "protectedT1SI", t1.callPerformed );
+ testMethod( "protectedT1SI", new T1(), false, "protectedT1SI" );
+ testMethod( "protectedT1SI", new T1(), true, "protectedT1SI" );
+ testMethod( "protectedT1SI", new T2(), false, "protectedT1SI" );
+ testMethod( "protectedT1SI", new T2(), true, "protectedT1SI" );
}
public void test_protectedT1SSI()
{
- System.out.println();
- final T1 t1 = new T1();
- createMethod( "protectedT1SSI", T1.class ).invoke( t1, m_service );
- assertEquals( "protectedT1SSI", t1.callPerformed );
- }
-
-
- public void test_protectedT1SSI_onT2()
- {
- System.out.println();
- final T2 t2 = new T2();
- createMethod( "protectedT1SSI", T2.class ).invoke( t2, m_service );
- assertEquals( "protectedT1SSI", t2.callPerformed );
+ testMethod( "protectedT1SSI", new T1(), false, "protectedT1SSI" );
+ testMethod( "protectedT1SSI", new T1(), true, "protectedT1SSI" );
+ testMethod( "protectedT1SSI", new T2(), false, "protectedT1SSI" );
+ testMethod( "protectedT1SSI", new T2(), true, "protectedT1SSI" );
}
public void test_publicT1()
{
- System.out.println();
- final T1 t1 = new T1();
- createMethod( "publicT1", T1.class ).invoke( t1, m_service );
- assertNull( t1.callPerformed );
+ testMethod( "publicT1", new T1(), false, null );
+ testMethod( "publicT1", new T1(), true, null );
+ testMethod( "publicT1", new T2(), false, null );
+ testMethod( "publicT1", new T2(), true, null );
}
public void test_publicT1SR()
{
- System.out.println();
- final T1 t1 = new T1();
- createMethod( "publicT1SR", T1.class ).invoke( t1, m_service );
- assertEquals( "publicT1SR", t1.callPerformed );
- }
-
-
- public void test_publicT1SR_onT2()
- {
- System.out.println();
- final T2 t2 = new T2();
- createMethod( "publicT1SR", T2.class ).invoke( t2, m_service );
- assertEquals( "publicT1SR", t2.callPerformed );
+ testMethod( "publicT1SR", new T1(), false, "publicT1SR" );
+ testMethod( "publicT1SR", new T1(), true, "publicT1SR" );
+ testMethod( "publicT1SR", new T2(), false, "publicT1SR" );
+ testMethod( "publicT1SR", new T2(), true, "publicT1SR" );
}
public void test_publicT1SI()
{
- System.out.println();
- final T1 t1 = new T1();
- createMethod( "publicT1SI", T1.class ).invoke( t1, m_service );
- assertEquals( "publicT1SI", t1.callPerformed );
+ testMethod( "publicT1SI", new T1(), false, "publicT1SI" );
+ testMethod( "publicT1SI", new T1(), true, "publicT1SI" );
+ testMethod( "publicT1SI", new T2(), false, "publicT1SI" );
+ testMethod( "publicT1SI", new T2(), true, "publicT1SI" );
}
public void test_publicT1SIMap()
{
- System.out.println();
- final T1 t1 = new T1();
- createMethod( "publicT1SIMap", T1.class ).invoke( t1, m_service );
- assertEquals( "publicT1SIMap", t1.callPerformed );
- }
-
-
- public void test_publicT1SI_onT2()
- {
- System.out.println();
- final T2 t2 = new T2();
- createMethod( "publicT1SI", T2.class ).invoke( t2, m_service );
- assertEquals( "publicT1SI", t2.callPerformed );
+ testMethod( "publicT1SIMap", new T1(), false, null );
+ testMethod( "publicT1SIMap", new T1(), true, "publicT1SIMap" );
+ testMethod( "publicT1SIMap", new T2(), false, null );
+ testMethod( "publicT1SIMap", new T2(), true, "publicT1SIMap" );
}
public void test_publicT1SSI()
{
- System.out.println();
- final T1 t1 = new T1();
- createMethod( "publicT1SSI", T1.class ).invoke( t1, m_service );
- assertEquals( "publicT1SSI", t1.callPerformed );
+ testMethod( "publicT1SSI", new T1(), false, "publicT1SSI" );
+ testMethod( "publicT1SSI", new T1(), true, "publicT1SSI" );
+ testMethod( "publicT1SSI", new T2(), false, "publicT1SSI" );
+ testMethod( "publicT1SSI", new T2(), true, "publicT1SSI" );
}
- public void test_publicT1SSI_onT2()
+ public void test_publicT1SSIMap()
{
- System.out.println();
- final T2 t2 = new T2();
- createMethod( "publicT1SSI", T2.class ).invoke( t2, m_service );
- assertEquals( "publicT1SSI", t2.callPerformed );
- }
-
- private static interface SuperFakeService
- {
-
- }
-
- private static interface FakeService extends SuperFakeService
- {
-
- }
-
- private static class T1
- {
-
- String callPerformed = null;
-
-
- private void privateT1()
- {
- callPerformed = "privateT1";
- }
-
-
- protected void protectedT1()
- {
- callPerformed = "protectedT1";
- }
-
-
- protected void protectedT1SR( ServiceReference sr )
- {
- if ( sr != null )
- {
- callPerformed = "protectedT1SR";
- }
- else
- {
- callPerformed = "protectedT1SR with null param";
- }
- }
-
-
- protected void protectedT1SI( FakeService si )
- {
- if ( si != null )
- {
- callPerformed = "protectedT1SI";
- }
- else
- {
- callPerformed = "protectedT1SI with null param";
- }
- }
-
-
- protected void protectedT1SSI( SuperFakeService si )
- {
- if ( si != null )
- {
- callPerformed = "protectedT1SSI";
- }
- else
- {
- callPerformed = "protectedT1SSI with null param";
- }
- }
-
-
- protected void publicT1()
- {
- callPerformed = "publicT1";
- }
-
-
- public void publicT1SR( ServiceReference sr )
- {
- if ( sr != null )
- {
- callPerformed = "publicT1SR";
- }
- else
- {
- callPerformed = "publicT1SR with null param";
- }
- }
-
-
- public void publicT1SI( FakeService si )
- {
- if ( si != null )
- {
- callPerformed = "publicT1SI";
- }
- else
- {
- callPerformed = "publicT1SI with null param";
- }
- }
-
-
- public void publicT1SIMap( FakeService si, Map props )
- {
- if ( si != null && props != null && props.size() > 0 )
- {
- callPerformed = "publicT1SIMap";
- }
- else if ( si == null )
- {
- callPerformed = "publicT1SIMap with null service instance";
- }
- else if ( props == null )
- {
- callPerformed = "publicT1SIMap with null props";
- }
- else
- {
- callPerformed = "publicT1SIMap with empty props";
- }
-
- }
-
-
- public void publicT1SSI( SuperFakeService si )
- {
- if ( si != null )
- {
- callPerformed = "publicT1SSI";
- }
- else
- {
- callPerformed = "publicT1SSI with null param";
- }
- }
- }
-
- private class T2 extends T1
- {
-
+ testMethod( "publicT1SSIMap", new T1(), false, null );
+ testMethod( "publicT1SSIMap", new T1(), true, "publicT1SSIMap" );
+ testMethod( "publicT1SSIMap", new T2(), false, null );
+ testMethod( "publicT1SSIMap", new T2(), true, "publicT1SSIMap" );
}
- public BindMethod createMethod( final String methodName, final Class componentClass )
+ public void test_suitable()
{
- return new BindMethod( methodName, componentClass, "reference", FakeService.class.getName(), new SysOutLogger() );
+ // T1 should use its own public implementation
+ testMethod( "suitable", new T1(), false, "suitableT1" );
+ testMethod( "suitable", new T1(), true, "suitableT1" );
+
+ // T2's private implementation is only visible for DS 1.1
+ testMethod( "suitable", new T2(), false, null );
+ testMethod( "suitable", new T2(), true, "suitableT2" );
+
+ // T3 extends T2 and cannot see T2's private method
+ testMethod( "suitable", new T3(), false, null );
+ testMethod( "suitable", new T3(), true, null );
+
+ // T1a extends T1 and uses T1's public method
+ testMethod( "suitable", new T1a(), false, "suitableT1" );
+ testMethod( "suitable", new T1a(), true, "suitableT1" );
+ }
+
+
+ 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() );
+ bm.invoke( component, m_service );
+ assertEquals( expectCallPerformed, component.callPerformed );
}
private static class SysOutLogger implements BindMethod.Logger
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/manager/components/FakeService.java b/scr/src/test/java/org/apache/felix/scr/impl/manager/components/FakeService.java
new file mode 100644
index 0000000..bf42066
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/impl/manager/components/FakeService.java
@@ -0,0 +1,25 @@
+/*
+ * 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.manager.components;
+
+
+public interface FakeService extends SuperFakeService
+{
+
+}
\ No newline at end of file
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/manager/components/SuperFakeService.java b/scr/src/test/java/org/apache/felix/scr/impl/manager/components/SuperFakeService.java
new file mode 100644
index 0000000..a754977
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/impl/manager/components/SuperFakeService.java
@@ -0,0 +1,24 @@
+/*
+ * 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.manager.components;
+
+public interface SuperFakeService
+{
+
+}
\ No newline at end of file
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/manager/components/T1.java b/scr/src/test/java/org/apache/felix/scr/impl/manager/components/T1.java
new file mode 100644
index 0000000..f4d7364
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/impl/manager/components/T1.java
@@ -0,0 +1,385 @@
+/*
+ * 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.manager.components;
+
+
+import java.util.Map;
+
+import org.osgi.framework.ServiceReference;
+
+
+public class T1
+{
+
+ public String callPerformed = null;
+
+
+ private void privateT1()
+ {
+ callPerformed = "privateT1";
+ }
+
+
+ private void privateT1SR( ServiceReference sr )
+ {
+ if ( sr != null )
+ {
+ callPerformed = "privateT1SR";
+ }
+ else
+ {
+ callPerformed = "privateT1SR with null param";
+ }
+ }
+
+
+ private void privateT1SI( FakeService si )
+ {
+ if ( si != null )
+ {
+ callPerformed = "privateT1SI";
+ }
+ else
+ {
+ callPerformed = "privateT1SI with null param";
+ }
+ }
+
+
+ private void privateT1SIMap( FakeService si, Map props )
+ {
+ if ( si != null && props != null && props.size() > 0 )
+ {
+ callPerformed = "privateT1SIMap";
+ }
+ else if ( si == null )
+ {
+ callPerformed = "privateT1SIMap with null service instance";
+ }
+ else if ( props == null )
+ {
+ callPerformed = "privateT1SIMap with null props";
+ }
+ else
+ {
+ callPerformed = "privateT1SIMap with empty props";
+ }
+ }
+
+
+ private void privateT1SSI( SuperFakeService si )
+ {
+ if ( si != null )
+ {
+ callPerformed = "privateT1SSI";
+ }
+ else
+ {
+ callPerformed = "privateT1SSI with null param";
+ }
+ }
+
+
+ private void privateT1SSIMap( SuperFakeService si, Map props )
+ {
+ if ( si != null && props != null && props.size() > 0 )
+ {
+ callPerformed = "privateT1SSIMap";
+ }
+ else if ( si == null )
+ {
+ callPerformed = "privateT1SSIMap with null service instance";
+ }
+ else if ( props == null )
+ {
+ callPerformed = "privateT1SSIMap with null props";
+ }
+ else
+ {
+ callPerformed = "privateT1SSIMap with empty props";
+ }
+ }
+
+
+ void packageT1()
+ {
+ callPerformed = "packageT1";
+ }
+
+
+ void packageT1SR( ServiceReference sr )
+ {
+ if ( sr != null )
+ {
+ callPerformed = "packageT1SR";
+ }
+ else
+ {
+ callPerformed = "packageT1SR with null param";
+ }
+ }
+
+
+ void packageT1SI( FakeService si )
+ {
+ if ( si != null )
+ {
+ callPerformed = "packageT1SI";
+ }
+ else
+ {
+ callPerformed = "packageT1SI with null param";
+ }
+ }
+
+
+ void packageT1SIMap( FakeService si, Map props )
+ {
+ if ( si != null && props != null && props.size() > 0 )
+ {
+ callPerformed = "packageT1SIMap";
+ }
+ else if ( si == null )
+ {
+ callPerformed = "packageT1SIMap with null service instance";
+ }
+ else if ( props == null )
+ {
+ callPerformed = "packageT1SIMap with null props";
+ }
+ else
+ {
+ callPerformed = "packageT1SIMap with empty props";
+ }
+ }
+
+
+ void packageT1SSI( SuperFakeService si )
+ {
+ if ( si != null )
+ {
+ callPerformed = "packageT1SSI";
+ }
+ else
+ {
+ callPerformed = "packageT1SSI with null param";
+ }
+ }
+
+
+ void packageT1SSIMap( SuperFakeService si, Map props )
+ {
+ if ( si != null && props != null && props.size() > 0 )
+ {
+ callPerformed = "packageT1SSIMap";
+ }
+ else if ( si == null )
+ {
+ callPerformed = "packageT1SSIMap with null service instance";
+ }
+ else if ( props == null )
+ {
+ callPerformed = "packageT1SSIMap with null props";
+ }
+ else
+ {
+ callPerformed = "packageT1SSIMap with empty props";
+ }
+ }
+
+
+ protected void protectedT1()
+ {
+ callPerformed = "protectedT1";
+ }
+
+
+ protected void protectedT1SR( ServiceReference sr )
+ {
+ if ( sr != null )
+ {
+ callPerformed = "protectedT1SR";
+ }
+ else
+ {
+ callPerformed = "protectedT1SR with null param";
+ }
+ }
+
+
+ protected void protectedT1SI( FakeService si )
+ {
+ if ( si != null )
+ {
+ callPerformed = "protectedT1SI";
+ }
+ else
+ {
+ callPerformed = "protectedT1SI with null param";
+ }
+ }
+
+
+ protected void protectedT1SIMap( FakeService si, Map props )
+ {
+ if ( si != null && props != null && props.size() > 0 )
+ {
+ callPerformed = "protectedT1SIMap";
+ }
+ else if ( si == null )
+ {
+ callPerformed = "protectedT1SIMap with null service instance";
+ }
+ else if ( props == null )
+ {
+ callPerformed = "protectedT1SIMap with null props";
+ }
+ else
+ {
+ callPerformed = "protectedT1SIMap with empty props";
+ }
+ }
+
+
+ protected void protectedT1SSI( SuperFakeService si )
+ {
+ if ( si != null )
+ {
+ callPerformed = "protectedT1SSI";
+ }
+ else
+ {
+ callPerformed = "protectedT1SSI with null param";
+ }
+ }
+
+
+ protected void protectedT1SSIMap( SuperFakeService si, Map props )
+ {
+ if ( si != null && props != null && props.size() > 0 )
+ {
+ callPerformed = "protectedT1SSIMap";
+ }
+ else if ( si == null )
+ {
+ callPerformed = "protectedT1SSIMap with null service instance";
+ }
+ else if ( props == null )
+ {
+ callPerformed = "protectedT1SSIMap with null props";
+ }
+ else
+ {
+ callPerformed = "protectedT1SSIMap with empty props";
+ }
+ }
+
+
+ public void publicT1()
+ {
+ callPerformed = "publicT1";
+ }
+
+
+ public void publicT1SR( ServiceReference sr )
+ {
+ if ( sr != null )
+ {
+ callPerformed = "publicT1SR";
+ }
+ else
+ {
+ callPerformed = "publicT1SR with null param";
+ }
+ }
+
+
+ public void publicT1SI( FakeService si )
+ {
+ if ( si != null )
+ {
+ callPerformed = "publicT1SI";
+ }
+ else
+ {
+ callPerformed = "publicT1SI with null param";
+ }
+ }
+
+
+ public void publicT1SIMap( FakeService si, Map props )
+ {
+ if ( si != null && props != null && props.size() > 0 )
+ {
+ callPerformed = "publicT1SIMap";
+ }
+ else if ( si == null )
+ {
+ callPerformed = "publicT1SIMap with null service instance";
+ }
+ else if ( props == null )
+ {
+ callPerformed = "publicT1SIMap with null props";
+ }
+ else
+ {
+ callPerformed = "publicT1SIMap with empty props";
+ }
+ }
+
+
+ public void publicT1SSI( SuperFakeService si )
+ {
+ if ( si != null )
+ {
+ callPerformed = "publicT1SSI";
+ }
+ else
+ {
+ callPerformed = "publicT1SSI with null param";
+ }
+ }
+
+
+ public void publicT1SSIMap( SuperFakeService si, Map props )
+ {
+ if ( si != null && props != null && props.size() > 0 )
+ {
+ callPerformed = "publicT1SSIMap";
+ }
+ else if ( si == null )
+ {
+ callPerformed = "publicT1SSIMap with null service instance";
+ }
+ else if ( props == null )
+ {
+ callPerformed = "publicT1SSIMap with null props";
+ }
+ else
+ {
+ callPerformed = "publicT1SSIMap with empty props";
+ }
+ }
+
+
+ public void suitable( ServiceReference sr )
+ {
+ callPerformed = "suitableT1";
+ }
+}
\ No newline at end of file
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/manager/components/T1a.java b/scr/src/test/java/org/apache/felix/scr/impl/manager/components/T1a.java
new file mode 100644
index 0000000..ffa6beb
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/impl/manager/components/T1a.java
@@ -0,0 +1,27 @@
+/*
+ * 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.manager.components;
+
+
+public class T1a extends T1
+{
+
+ // this class sees package private methods from T1
+
+}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/manager/components/T3.java b/scr/src/test/java/org/apache/felix/scr/impl/manager/components/T3.java
new file mode 100644
index 0000000..587c5e3
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/impl/manager/components/T3.java
@@ -0,0 +1,30 @@
+/*
+ * 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.manager.components;
+
+
+import org.apache.felix.scr.impl.manager.components2.T2;
+
+
+public class T3 extends T2
+{
+
+ // this class does not see any package private methods of other classes
+
+}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/manager/components2/T2.java b/scr/src/test/java/org/apache/felix/scr/impl/manager/components2/T2.java
new file mode 100644
index 0000000..a093af4
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/impl/manager/components2/T2.java
@@ -0,0 +1,211 @@
+/*
+ * 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.manager.components2;
+
+
+import java.util.Map;
+
+import org.apache.felix.scr.impl.manager.components.FakeService;
+import org.apache.felix.scr.impl.manager.components.SuperFakeService;
+import org.apache.felix.scr.impl.manager.components.T1;
+import org.osgi.framework.ServiceReference;
+
+
+public class T2 extends T1
+{
+ private void privateT2()
+ {
+ callPerformed = "privateT2";
+ }
+
+
+ private void privateT2SR( ServiceReference sr )
+ {
+ if ( sr != null )
+ {
+ callPerformed = "privateT2SR";
+ }
+ else
+ {
+ callPerformed = "privateT2SR with null param";
+ }
+ }
+
+
+ private void privateT2SI( FakeService si )
+ {
+ if ( si != null )
+ {
+ callPerformed = "privateT2SI";
+ }
+ else
+ {
+ callPerformed = "privateT2SI with null param";
+ }
+ }
+
+
+ private void privateT2SIMap( FakeService si, Map props )
+ {
+ if ( si != null && props != null && props.size() > 0 )
+ {
+ callPerformed = "privateT2SIMap";
+ }
+ else if ( si == null )
+ {
+ callPerformed = "privateT2SIMap with null service instance";
+ }
+ else if ( props == null )
+ {
+ callPerformed = "privateT2SIMap with null props";
+ }
+ else
+ {
+ callPerformed = "privateT2SIMap with empty props";
+ }
+ }
+
+
+ private void privateT2SSI( SuperFakeService si )
+ {
+ if ( si != null )
+ {
+ callPerformed = "privateT2SSI";
+ }
+ else
+ {
+ callPerformed = "privateT2SSI with null param";
+ }
+ }
+
+
+ private void privateT2SSIMap( SuperFakeService si, Map props )
+ {
+ if ( si != null && props != null && props.size() > 0 )
+ {
+ callPerformed = "privateT2SSIMap";
+ }
+ else if ( si == null )
+ {
+ callPerformed = "privateT2SSIMap with null service instance";
+ }
+ else if ( props == null )
+ {
+ callPerformed = "privateT2SSIMap with null props";
+ }
+ else
+ {
+ callPerformed = "privateT2SSIMap with empty props";
+ }
+ }
+
+
+ void packageT2()
+ {
+ callPerformed = "packageT2";
+ }
+
+
+ void packageT2SR( ServiceReference sr )
+ {
+ if ( sr != null )
+ {
+ callPerformed = "packageT2SR";
+ }
+ else
+ {
+ callPerformed = "packageT2SR with null param";
+ }
+ }
+
+
+ void packageT2SI( FakeService si )
+ {
+ if ( si != null )
+ {
+ callPerformed = "packageT2SI";
+ }
+ else
+ {
+ callPerformed = "packageT2SI with null param";
+ }
+ }
+
+
+ void packageT2SIMap( FakeService si, Map props )
+ {
+ if ( si != null && props != null && props.size() > 0 )
+ {
+ callPerformed = "packageT2SIMap";
+ }
+ else if ( si == null )
+ {
+ callPerformed = "packageT2SIMap with null service instance";
+ }
+ else if ( props == null )
+ {
+ callPerformed = "packageT2SIMap with null props";
+ }
+ else
+ {
+ callPerformed = "packageT2SIMap with empty props";
+ }
+ }
+
+
+ void packageT2SSI( SuperFakeService si )
+ {
+ if ( si != null )
+ {
+ callPerformed = "packageT2SSI";
+ }
+ else
+ {
+ callPerformed = "packageT2SSI with null param";
+ }
+ }
+
+
+ void packageT2SSIMap( SuperFakeService si, Map props )
+ {
+ if ( si != null && props != null && props.size() > 0 )
+ {
+ callPerformed = "packageT2SSIMap";
+ }
+ else if ( si == null )
+ {
+ callPerformed = "packageT2SSIMap with null service instance";
+ }
+ else if ( props == null )
+ {
+ callPerformed = "packageT2SSIMap with null props";
+ }
+ else
+ {
+ callPerformed = "packageT2SSIMap with empty props";
+ }
+ }
+
+
+ // this method must hide the T1#suitable method !
+ private void suitable( FakeService si )
+ {
+ callPerformed = "suitableT2";
+ }
+}
\ No newline at end of file