FELIX-4403 Implement parameter checking and setting for lifecycle methods
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1616079 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java
index ac59407..1d7e7db 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/ActivateMethod.java
@@ -21,28 +21,36 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
import org.apache.felix.scr.impl.metadata.DSVersion;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
import org.osgi.service.log.LogService;
public class ActivateMethod extends BaseMethod<ActivatorParameter>
{
- private static final Class[] ACTIVATE_TYPES_DS11 =
- { COMPONENT_CONTEXT_CLASS, BUNDLE_CONTEXT_CLASS, MAP_CLASS };
- static final Class[] ACTIVATE_TYPES_DS10 =
- { COMPONENT_CONTEXT_CLASS };
+ protected static final Class<?> COMPONENT_CONTEXT_CLASS = ComponentContext.class;
+ protected static final Class<?> BUNDLE_CONTEXT_CLASS = BundleContext.class;
+ protected static final Class<?> INTEGER_CLASS = Integer.class;
+
+ protected final boolean m_supportsInterfaces = false; //TODO configure
public ActivateMethod( final String methodName,
- final boolean methodRequired, final Class componentClass, final DSVersion dsVersion, final boolean configurableServiceProperties )
+ final boolean methodRequired, final Class<?> componentClass, final DSVersion dsVersion, final boolean configurableServiceProperties )
{
super( methodName, methodRequired, componentClass, dsVersion, configurableServiceProperties );
}
- protected Method doFindMethod( Class targetClass, boolean acceptPrivate, boolean acceptPackage, SimpleLogger logger )
+ protected Method doFindMethod( Class<?> targetClass, boolean acceptPrivate, boolean acceptPackage, SimpleLogger logger )
throws SuitableMethodNotAccessibleException, InvocationTargetException
{
@@ -50,54 +58,109 @@
try
{
- final Method method = getSingleParameterMethod( targetClass, acceptPrivate, acceptPackage, logger );
+ // find the declared method in this class
+ final Method method = getMethod( targetClass, getMethodName(), new Class[]
+ { COMPONENT_CONTEXT_CLASS }, acceptPrivate, acceptPackage, logger );
if ( method != null )
{
return method;
}
}
- catch ( SuitableMethodNotAccessibleException smnae )
+ catch ( SuitableMethodNotAccessibleException thrown )
{
+ logger.log( LogService.LOG_DEBUG, "SuitableMethodNotAccessible", thrown );
suitableMethodNotAccessible = true;
}
-
- if ( getDSVersion().isDS11() )
+ if (getDSVersion().isDS11())
{
- // check methods with MethodTester
- Method[] methods = targetClass.getDeclaredMethods();
- for ( int i = 0; i < methods.length; i++ )
+ List<Method> methods = getSortedMethods( targetClass);
+ for (Method m: methods)
{
- if ( methods[i].getName().equals( getMethodName() ) && isSuitable( methods[i] ) )
+ final Class<?>[] parameterTypes = m.getParameterTypes();
+ if (parameterTypes.length == 1)
{
- if ( accept( methods[i], acceptPrivate, acceptPackage, returnValue() ) )
+ Class<?> type = parameterTypes[0];
+ //single parameter method with parameter ComponentContext will already have been found.
+ if (type == BUNDLE_CONTEXT_CLASS)
{
- // check modifiers etc.
- return methods[i];
+ if ( accept( m, acceptPrivate, acceptPackage, returnValue() ) )
+ {
+ return m;
+ }
+ suitableMethodNotAccessible = true;
}
-
- // method is suitable but not accessible, flag it
- suitableMethodNotAccessible = true;
+ if (getDSVersion().isDS13() && isAnnotation(type))
+ {
+ if ( accept( m, acceptPrivate, acceptPackage, returnValue() ) )
+ {
+ return m;
+ }
+ suitableMethodNotAccessible = true;
+ }
+ if (type == MAP_CLASS)
+ {
+ if ( accept( m, acceptPrivate, acceptPackage, returnValue() ) )
+ {
+ return m;
+ }
+ suitableMethodNotAccessible = true;
+ }
+ if (type == int.class)
+ {
+ if ( accept( m, acceptPrivate, acceptPackage, returnValue() ) )
+ {
+ return m;
+ }
+ suitableMethodNotAccessible = true;
+ }
+ if (type == Integer.class)
+ {
+ if ( accept( m, acceptPrivate, acceptPackage, returnValue() ) )
+ {
+ return m;
+ }
+ suitableMethodNotAccessible = true;
+ }
+
}
- }
-
- // finally check method with no arguments
- if ( acceptEmpty() )
- {
- try
+ else if (parameterTypes.length > 1)
{
- // find the declared method in this class
- Method m = getMethod( targetClass, getMethodName(), null, acceptPrivate, acceptPackage, logger );
- if ( m != null ) {
+ boolean accept = true;
+ for (Class<?> type: parameterTypes)
+ {
+ accept = type == COMPONENT_CONTEXT_CLASS
+ || type == BUNDLE_CONTEXT_CLASS
+ || type == MAP_CLASS
+ || ( isDeactivate() && ( type == int.class || type == Integer.class))
+ || ( getDSVersion().isDS13() && isAnnotation(type));
+ if ( !accept )
+ {
+ break;
+ }
+
+ }
+ if (accept)
+ {
+ if ( accept( m, acceptPrivate, acceptPackage, returnValue() ) )
+ {
+ return m;
+ }
+ suitableMethodNotAccessible = true;
+ }
+
+ }
+ else //no parameters
+ {
+ if ( accept( m, acceptPrivate, acceptPackage, returnValue() ) )
+ {
return m;
}
+ suitableMethodNotAccessible = true;
}
- catch ( SuitableMethodNotAccessibleException smnae )
- {
- suitableMethodNotAccessible = true;
- }
+
}
}
-
+
if ( suitableMethodNotAccessible )
{
throw new SuitableMethodNotAccessibleException();
@@ -107,9 +170,77 @@
}
+ boolean isDeactivate()
+ {
+ return false;
+ }
+
+
+ /**
+ * returns the declared methods of the target class, with the correct name, sorted by number of parameters ( no parameters last)
+ * @param targetClass class to examine methods of
+ * @return sorted methods of correct name;
+ */
+ List<Method> getSortedMethods(Class<?> targetClass)
+ {
+ List<Method> result = new ArrayList<Method>();
+ Method[] methods = targetClass.getDeclaredMethods();
+ for (Method m: methods)
+ {
+ if (m.getName().equals(getMethodName()))
+ {
+ result.add(m);
+ }
+ }
+ Collections.sort(result, new Comparator<Method>(){
+
+ public int compare(Method m1, Method m2)
+ {
+ final int l1 = m1.getParameterTypes().length;
+ final int l2 = m2.getParameterTypes().length;
+ if ( l1 == 0)
+ {
+ return l2;
+ }
+ if ( l2 == 0)
+ {
+ return -l1;
+ }
+ if (l1 == 1 && l2 == 1)
+ {
+ final Class<?> t1 = m1.getParameterTypes()[0];
+ final Class<?> t2 = m2.getParameterTypes()[0];
+ //t1, t2 can't be equal
+ if (t1 == COMPONENT_CONTEXT_CLASS) return -1;
+ if (t2 == COMPONENT_CONTEXT_CLASS) return 1;
+ if (t1 == BUNDLE_CONTEXT_CLASS) return -1;
+ if (t2 == BUNDLE_CONTEXT_CLASS) return 1;
+ if (isAnnotation(t1)) return isAnnotation(t2)? 0: -1;
+ if (isAnnotation(t2)) return 1;
+ if (t1 == MAP_CLASS) return -1;
+ if (t2 == MAP_CLASS) return 1;
+ if (t1 == int.class) return -1;
+ if (t2 == int.class) return 1;
+ if (t1 == Integer.class) return -1;
+ if (t2 == Integer.class) return 1;
+ return 0;
+ }
+ return l1 - l2;
+ }
+
+ });
+ return result;
+ }
+
+ private boolean isAnnotation(final Class<?> t1)
+ {
+ return t1.isAnnotation() || (m_supportsInterfaces && t1.isInterface() && !(t1 == MAP_CLASS));
+ }
+
+
protected Object[] getParameters( Method method, ActivatorParameter rawParameter )
{
- final Class[] parameterTypes = method.getParameterTypes();
+ 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++ )
@@ -130,6 +261,12 @@
else if ( parameterTypes[i] == INTEGER_CLASS || parameterTypes[i] == Integer.TYPE )
{
param[i] = ap.getReason();
+ }
+ else
+ {
+ param[i] = Annotations.toObject(parameterTypes[i],
+ (Map<String, Object>) ap.getComponentContext().getProperties(),
+ ap.getComponentContext().getBundleContext().getBundle());
}
}
@@ -151,99 +288,4 @@
return null;
}
- /**
- * Returns a method taking a single parameter of one of the
- * {@link #getAcceptedParameterTypes()} 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.
- * @param logger
- * @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
- * @throws InvocationTargetException If an unexpected Throwable is caught
- * trying to find the requested method.
- */
- private Method getSingleParameterMethod( final Class targetClass, final boolean acceptPrivate,
- final boolean acceptPackage, SimpleLogger logger ) throws SuitableMethodNotAccessibleException, InvocationTargetException
- {
- SuitableMethodNotAccessibleException ex = null;
- Method singleParameterMethod = null;
- final Class[] acceptedTypes = getAcceptedParameterTypes();
- for ( int i = 0; singleParameterMethod == null && i < acceptedTypes.length; i++ )
- {
- try
- {
- // find the declared method in this class
- singleParameterMethod = getMethod( targetClass, getMethodName(), new Class[]
- { acceptedTypes[i] }, acceptPrivate, acceptPackage, logger );
- }
- catch ( SuitableMethodNotAccessibleException thrown )
- {
- logger.log( LogService.LOG_DEBUG, "SuitableMethodNotAccessible", thrown );
- ex = thrown;
- }
- }
-
- // rethrow if we looked for all method signatures and only found
- // one or more which would be suitable but not accessible
- if ( singleParameterMethod == null && ex != null )
- {
- throw ex;
- }
-
- // no method with a matching single parameter has been found
- return singleParameterMethod;
- }
-
-
- 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()
- {
- return getDSVersion().isDS11() ? ACTIVATE_TYPES_DS11 : ACTIVATE_TYPES_DS10;
- }
-
-
- protected boolean acceptEmpty()
- {
- return getDSVersion().isDS11();
- }
-
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/Annotations.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/Annotations.java
index 8e5b3e8..ae7fbf3 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/Annotations.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/Annotations.java
@@ -29,7 +29,7 @@
public class Annotations
{
- public <T> T toObject(Class<T> clazz, Map<String, Object> props, Bundle b )
+ static public <T> T toObject(Class<T> clazz, Map<String, Object> props, Bundle b )
{
Map<String, Object> m = new HashMap<String, Object>();
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java
index f12e370..05ec96b 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/BaseMethod.java
@@ -41,10 +41,7 @@
{
// 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<?> MAP_CLASS = Map.class;
- protected static final Class<?> INTEGER_CLASS = Integer.class;
private final DSVersion dsVersion;
private final boolean configurableServiceProperties;
@@ -100,7 +97,7 @@
return m_methodName;
}
- protected final Method getMethod()
+ final Method getMethod()
{
return m_method;
}
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
index d5b7754..6040dbd 100644
--- 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
@@ -24,8 +24,11 @@
public class DeactivateMethod extends ActivateMethod
{
- private static final Class[] DEACTIVATE_TYPES_DS11 =
- { COMPONENT_CONTEXT_CLASS, BUNDLE_CONTEXT_CLASS, MAP_CLASS, Integer.TYPE, INTEGER_CLASS };
+ @Override
+ boolean isDeactivate()
+ {
+ return true;
+ }
public DeactivateMethod( final String methodName,
@@ -34,13 +37,6 @@
super( methodName, methodRequired, componentClass, dsVersion, configurableServiceProperties );
}
-
- protected Class[] getAcceptedParameterTypes()
- {
- return getDSVersion().isDS11() ? DEACTIVATE_TYPES_DS11 : ACTIVATE_TYPES_DS10;
- }
-
-
protected String getMethodNamePrefix()
{
return "deactivate";
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java b/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java
index 5cd7af1..93214af 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/helper/ActivateMethodTest.java
@@ -22,6 +22,8 @@
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
import junit.framework.TestCase;
@@ -36,7 +38,10 @@
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.instances2.Level2Object;
+import org.apache.felix.scr.integration.components.ActivatorComponent;
import org.easymock.EasyMock;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
@@ -58,11 +63,15 @@
protected void setUp() throws Exception
{
super.setUp();
+ Bundle bundle = ( Bundle ) EasyMock.createNiceMock( Bundle.class );
+ BundleContext context = ( BundleContext ) EasyMock.createNiceMock( BundleContext.class );
+ EasyMock.expect( context.getBundle() ).andReturn( bundle ).anyTimes();
m_ctx = (ComponentContext) EasyMock.createNiceMock(ComponentContext.class);
EasyMock.expect( m_ctx.getProperties() ).andReturn( new Hashtable() ).anyTimes();
+ EasyMock.expect( m_ctx.getBundleContext() ).andReturn( context ).anyTimes();
EasyMock.replay( new Object[]
- { m_ctx } );
+ { m_ctx, context } );
}
@@ -224,7 +233,7 @@
public void test_precedence() throws Exception
{
- //All tested methods are only in base. They differ in argurments and visibility.
+ //All tested methods are only in base. They differ in arguments and visibility.
//R4.2 compendium 112.5.8
//private method, arg ComponentContext
checkMethod( base, "activate_precedence_1", "activate_precedence_1_comp" );
@@ -253,7 +262,7 @@
*/
private void checkMethod( BaseObject obj, String methodName )
{
- checkMethod( obj, methodName, methodName );
+ checkMethod( obj, methodName, methodName, DSVersion.DS11 );
}
/**
@@ -267,11 +276,27 @@
*/
private void checkMethod( BaseObject obj, String methodName, String methodDesc )
{
- ComponentContainer container = newContainer();
- SingleComponentManager icm = new SingleComponentManager( container, new ComponentMethods() );
- ActivateMethod am = new ActivateMethod( methodName, methodName != null, obj.getClass(), DSVersion.DS11, false );
+ checkMethod(obj, methodName, methodDesc, DSVersion.DS11);
+ }
+
+
+ /**
+ * Checks whether a method with the given name can be found for the
+ * activate/deactivate method parameter list and whether the method returns
+ * the expected description when called.
+ *
+ * @param obj
+ * @param methodName
+ * @param methodDesc
+ * @param version DSVersion tested
+ */
+ private void checkMethod( BaseObject obj, String methodName, String methodDesc, DSVersion version )
+ {
+ ComponentContainer<?> container = newContainer();
+ SingleComponentManager<?> icm = new SingleComponentManager( container, new ComponentMethods() );
+ ActivateMethod am = new ActivateMethod( methodName, methodName != null, obj.getClass(), version, false );
am.invoke( obj, new ActivatorParameter( m_ctx, -1 ), null, icm );
- Method m = get(am, "m_method");
+ Method m = am.getMethod();
assertNotNull( m );
assertEquals( methodName, m.getName() );
assertEquals( methodDesc, obj.getCalledMethod() );
@@ -322,11 +347,28 @@
*/
private void ensureMethodNotFoundMethod( BaseObject obj, String methodName )
{
+ ensureMethodNotFoundMethod(obj, methodName, DSVersion.DS11);
+ }
+
+
+ /**
+ * Ensures no method with the given name accepting any of the
+ * activate/deactive method parameters can be found.
+ *
+ * @param obj
+ * @param methodName
+ * @param version DS version tested
+ * @throws InvocationTargetException
+ * @throws IllegalAccessException
+ */
+ private void ensureMethodNotFoundMethod( BaseObject obj, String methodName, DSVersion version )
+ {
ComponentContainer container = newContainer();
SingleComponentManager icm = new SingleComponentManager( container, new ComponentMethods() );
- ActivateMethod am = new ActivateMethod( methodName, methodName != null, obj.getClass(), DSVersion.DS11, false );
+ ActivateMethod am = new ActivateMethod( methodName, methodName != null, obj.getClass(), version, false );
am.invoke( obj, new ActivatorParameter( m_ctx, -1 ), null, icm );
- assertNull( get( am, "m_method" ) );
+ Method m = am.getMethod();
+ assertNull( m );
assertNull( obj.getCalledMethod() );
}
@@ -338,27 +380,45 @@
boolean accepted = BaseMethod.accept( method, acceptPrivate, acceptPackage, false );
assertEquals( expected, accepted );
}
-
-
- private static Method get( final BaseMethod baseMethod, final String fieldName )
+
+ private static @interface Ann{}
+ private static class Sort
{
- 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;
+ public void a(Ann ann) {};
+ public void a(int c) {};
+ public void a(Integer c) {};
+ public void a(BundleContext c) {};
+ public void a(Map m) {};
+ public void a() {};
+ public void a(ComponentContext cc) {};
+ public void a(ComponentContext cc, BundleContext c) {};
+ public void b() {};
+
}
+ public void testMethodSorting() throws Exception
+ {
+ ActivateMethod am = new ActivateMethod( "a", true, Sort.class, DSVersion.DS11, false );
+ List<Method> ms = am.getSortedMethods(Sort.class);
+ assertEquals(8, ms.size());
+ assertEquals(1, ms.get(0).getParameterTypes().length);
+ assertEquals(ComponentContext.class, ms.get(0).getParameterTypes()[0]);
+ assertEquals(1, ms.get(1).getParameterTypes().length);
+ assertEquals(BundleContext.class, ms.get(1).getParameterTypes()[0]);
+ assertEquals(1, ms.get(2).getParameterTypes().length);
+ assertEquals(Ann.class, ms.get(2).getParameterTypes()[0]);
+ assertEquals(1, ms.get(3).getParameterTypes().length);
+ assertEquals(Map.class, ms.get(3).getParameterTypes()[0]);
+ assertEquals(1, ms.get(4).getParameterTypes().length);
+ assertEquals(int.class, ms.get(4).getParameterTypes()[0]);
+ assertEquals(1, ms.get(5).getParameterTypes().length);
+ assertEquals(Integer.class, ms.get(5).getParameterTypes()[0]);
+ assertEquals(2, ms.get(6).getParameterTypes().length);
+ assertEquals(0, ms.get(7).getParameterTypes().length);
+ }
+
+ public void test_13_annos() throws Exception
+ {
+ checkMethod(base, "activate_13_2_annotations", "activate_13_2_annotations", DSVersion.DS13 );
+ }
+
}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/helper/AnnotationTest.java b/scr/src/test/java/org/apache/felix/scr/impl/helper/AnnotationTest.java
index a515d65..a2d228c 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/helper/AnnotationTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/helper/AnnotationTest.java
@@ -54,7 +54,7 @@
{
Map<String, Object> values = allValues();
- Object o = new Annotations().toObject( A1.class, values, mockBundle());
+ Object o = Annotations.toObject( A1.class, values, mockBundle());
assertTrue("expected an A1", o instanceof A1);
A1 a = (A1) o;
@@ -103,7 +103,7 @@
{
Map<String, Object> values = allValues();
- Object o = new Annotations().toObject( A2.class, values, mockBundle());
+ Object o = Annotations.toObject( A2.class, values, mockBundle());
assertTrue("expected an A2", o instanceof A2);
A2 a = (A2) o;
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 81b194c..98fa63d 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
@@ -104,4 +104,10 @@
}
+ public @interface Ann1 { }
+ public @interface Ann2 { }
+
+ void activate_13_2_annotations(ComponentContext cc, Ann1 a1, BundleContext c, Ann2 a2, Map<String, Object> map, ComponentContext cc2) {
+ setCalledMethod("activate_13_2_annotations");
+ }
}