FELIX-1686 Record in the component metadata whether the activate/deactivate
method was declared or not to be able to decide whether the activate/deactivate
method must be present (if declared) or may be present (if not declared).
This allows failing the component activation if the declared method is missing.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@822285 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/Component.java b/scr/src/main/java/org/apache/felix/scr/Component.java
index b32aec0..269b461 100644
--- a/scr/src/main/java/org/apache/felix/scr/Component.java
+++ b/scr/src/main/java/org/apache/felix/scr/Component.java
@@ -22,6 +22,7 @@
import java.util.Dictionary;
import org.osgi.framework.Bundle;
+import org.osgi.service.component.ComponentInstance;
/**
@@ -191,6 +192,69 @@
/**
+ * Returns the <code>org.osgi.service.component.ComponentInstance</code>
+ * representing this component or <code>null</code> if this component
+ * is not been activated yet.
+ */
+ ComponentInstance getComponentInstance();
+
+
+ /**
+ * Returns the name of the method to be called when the component is being
+ * activated.
+ * <p>
+ * This method never returns <code>null</code>, that is, if this method is
+ * not declared in the component descriptor this method returns the
+ * default value <i>activate</i>.
+ */
+ String getActivate();
+
+
+ /**
+ * Returns <code>true</code> if the name of the method to be called on
+ * component activation (see {@link #getActivate()} is declared in the
+ * component descriptor or not.
+ * <p>
+ * For a component declared in a Declarative Services 1.0 descriptor, this
+ * method always returns <code>false</code>.
+ */
+ boolean isActivateDeclared();
+
+
+ /**
+ * Returns the name of the method to be called when the component is being
+ * deactivated.
+ * <p>
+ * This method never returns <code>null</code>, that is, if this method is
+ * not declared in the component descriptor this method returns the
+ * default value <i>deactivate</i>.
+ */
+ String getDeactivate();
+
+
+ /**
+ * Returns <code>true</code> if the name of the method to be called on
+ * component deactivation (see {@link #getDeactivate()} is declared in the
+ * component descriptor or not.
+ * <p>
+ * For a component declared in a Declarative Services 1.0 descriptor, this
+ * method always returns <code>false</code>.
+ */
+ boolean isDeactivateDeclared();
+
+
+ /**
+ * Returns the name of the method to be called when the component
+ * configuration has been updated or <code>null</code> if such a method is
+ * not declared in the component descriptor.
+ * <p>
+ * For a component declared in a Declarative Services 1.0 descriptor, this
+ * method always returns <code>null</code>.
+ */
+ String getModified();
+
+
+ /**
* Enables this Component if it is disabled. If the Component is not
* currently {@link #STATE_DISABLED disabled} this method has no effect. If
* the Component is {@link #STATE_DESTROYED destroyed}, this method throws
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 70000cd..adb80a4 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
@@ -28,10 +28,10 @@
public class ActivateMethod extends BaseMethod
{
-
- public ActivateMethod( final AbstractComponentManager componentManager, String methodName, Class componentClass )
+ public ActivateMethod( final AbstractComponentManager componentManager, final String methodName,
+ final boolean methodRequired, final Class componentClass )
{
- super( componentManager, methodName, componentClass );
+ super( componentManager, methodName, methodRequired, componentClass );
}
@@ -131,6 +131,18 @@
}
+ protected String getMethodNamePrefix()
+ {
+ return "activate";
+ }
+
+
+ public boolean invoke( Object componentInstance, Object rawParameter )
+ {
+ return methodExists() && super.invoke( componentInstance, rawParameter );
+ }
+
+
private Method getSingleParameterMethod( final Class targetClass, final boolean acceptPrivate,
final boolean acceptPackage ) throws SuitableMethodNotAccessibleException, InvocationTargetException,
NoSuchMethodException
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 1f5c123..839779c 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
@@ -52,22 +52,32 @@
private Method m_method = null;
+ private final boolean m_methodRequired;
+
private State m_state;
protected BaseMethod( final AbstractComponentManager componentManager, final String methodName,
final Class componentClass )
{
+ this( componentManager, methodName, methodName != null, componentClass );
+ }
+
+
+ protected BaseMethod( final AbstractComponentManager componentManager, final String methodName,
+ final boolean methodRequired, final Class componentClass )
+ {
m_componentManager = componentManager;
m_methodName = methodName;
+ m_methodRequired = methodRequired;
m_componentClass = componentClass;
if ( m_methodName == null )
{
- m_state = new NotApplicable();
+ m_state = NotApplicable.INSTANCE;
}
else
{
- m_state = new NotResolved();
+ m_state = NotResolved.INSTANCE;
}
}
@@ -96,6 +106,34 @@
}
+ synchronized void setMethod( Method method )
+ {
+ this.m_method = method;
+
+ if ( method != null )
+ {
+ m_state = Resolved.INSTANCE;
+ }
+ else if ( m_methodRequired )
+ {
+ m_state = NotFound.INSTANCE;
+ }
+ else
+ {
+ // optional method not found, log as DEBUG and ignore
+ getComponentManager().log( LogService.LOG_DEBUG,
+ getMethodNamePrefix() + " method [" + getMethodName() + "] not found, ignoring", null );
+ m_state = NotApplicable.INSTANCE;
+ }
+ }
+
+
+ State getState()
+ {
+ return m_state;
+ }
+
+
/**
* Finds the method named in the {@link #m_methodName} field in the given
* <code>targetClass</code>. If the target class has no acceptable method
@@ -184,7 +222,7 @@
// 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", ex );
+ getComponentManager().log( LogService.LOG_DEBUG, "Method " + getMethodName() + " cannot be called", ex );
}
catch ( InvocationTargetException ex )
{
@@ -369,70 +407,121 @@
public boolean invoke( final Object componentInstance, final Object rawParameter )
{
- return m_state.invoke( componentInstance, rawParameter );
+ return m_state.invoke( this, componentInstance, rawParameter );
+ }
+
+
+ public boolean methodExists()
+ {
+ return m_state.methodExists( this );
}
private static interface State
{
- boolean invoke( final Object componentInstance, final Object rawParameter );
+ boolean invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter );
+
+
+ boolean methodExists( final BaseMethod baseMethod );
}
private static class NotApplicable implements State
{
- public boolean invoke( final Object componentInstance, final Object rawParameter )
+ private static final State INSTANCE = new NotApplicable();
+
+
+ public boolean invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
+ {
+ return true;
+ }
+
+
+ public boolean methodExists( final BaseMethod baseMethod )
{
return true;
}
}
- private class NotResolved implements State
+ private static class NotResolved implements State
{
+ private static final State INSTANCE = new NotResolved();
- public boolean invoke( final Object componentInstance, final Object rawParameter )
+
+ private void resolve( final BaseMethod baseMethod )
{
- getComponentManager().log( LogService.LOG_DEBUG,
- "getting " + getMethodNamePrefix() + "bind: " + m_methodName, null );
+ baseMethod.getComponentManager().log( LogService.LOG_DEBUG,
+ "getting " + baseMethod.getMethodNamePrefix() + ": " + baseMethod.getMethodName(), null );
+
+ // resolve the method
+ Method method;
try
{
- m_method = findMethod();
- m_state = ( m_method == null ) ? ( State ) new NotFound() : new Resolved();
- return m_state.invoke( componentInstance, rawParameter );
+ method = baseMethod.findMethod();
}
catch ( InvocationTargetException ex )
{
- m_state = new NotFound();
- // We can safely ignore this one
- getComponentManager().log( LogService.LOG_WARNING, getMethodName() + " cannot be found", ex.getTargetException() );
+ method = null;
+ baseMethod.getComponentManager().log( LogService.LOG_WARNING,
+ baseMethod.getMethodName() + " cannot be found", ex.getTargetException() );
}
- return true;
+
+ baseMethod.setMethod( method );
+ }
+
+
+ public boolean invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
+ {
+ resolve( baseMethod );
+ return baseMethod.getState().invoke( baseMethod, componentInstance, rawParameter );
+ }
+
+
+ public boolean methodExists( final BaseMethod baseMethod )
+ {
+ resolve( baseMethod );
+ return baseMethod.getState().methodExists( baseMethod );
}
}
- private class NotFound implements State
+ private static class NotFound implements State
{
+ private static final State INSTANCE = new NotFound();
- public boolean invoke( final Object componentInstance, final Object rawParameter )
+
+ public boolean invoke( final BaseMethod baseMethod, 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 );
+ baseMethod.getComponentManager().log( LogService.LOG_ERROR,
+ baseMethod.getMethodNamePrefix() + " method [" + baseMethod.getMethodName() + "] not found", null );
+ return false;
+ }
+
+
+ public boolean methodExists( final BaseMethod baseMethod )
+ {
+ return false;
+ }
+ }
+
+ private static class Resolved implements State
+ {
+ private static final State INSTANCE = new Resolved();
+
+
+ public boolean invoke( final BaseMethod baseMethod, final Object componentInstance, final Object rawParameter )
+ {
+ baseMethod.getComponentManager().log( LogService.LOG_DEBUG,
+ "invoking " + baseMethod.getMethodNamePrefix() + ": " + baseMethod.getMethodName(), null );
+ return baseMethod.invokeMethod( componentInstance, rawParameter );
+ }
+
+
+ public boolean methodExists( final BaseMethod baseMethod )
+ {
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 );
- return invokeMethod( componentInstance, rawParameter );
- }
- }
-
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
index c7418a5..7701c79 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/BindMethod.java
@@ -466,7 +466,7 @@
if ( params[i] == null )
{
throw new IllegalStateException( "Dependency Manager: Service " + service.getReference()
- + " has already gone, not " + getMethodNamePrefix() + "binding" );
+ + " has already gone, will not " + getMethodNamePrefix() );
}
}
}
@@ -477,7 +477,7 @@
protected String getMethodNamePrefix()
{
- return "";
+ return "bind";
}
//---------- Service abstraction ------------------------------------
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 2d88d28..e67c6e7 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
@@ -25,9 +25,10 @@
public class DeactivateMethod extends ActivateMethod
{
- public DeactivateMethod( final AbstractComponentManager componentManager, String methodName, Class componentClass )
+ public DeactivateMethod( final AbstractComponentManager componentManager, final String methodName,
+ final boolean methodRequired, final Class componentClass )
{
- super( componentManager, methodName, componentClass );
+ super( componentManager, methodName, methodRequired, componentClass );
}
@@ -42,4 +43,10 @@
return new Class[]
{ COMPONENT_CONTEXT_CLASS };
}
+
+
+ protected String getMethodNamePrefix()
+ {
+ return "deactivate";
+ }
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/ModifiedMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/ModifiedMethod.java
index 3e954f1..c228fa1 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/ModifiedMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/ModifiedMethod.java
@@ -25,9 +25,10 @@
public class ModifiedMethod extends ActivateMethod
{
- public ModifiedMethod( final AbstractComponentManager componentManager, String methodName, Class componentClass )
+ public ModifiedMethod( final AbstractComponentManager componentManager, final String methodName,
+ final Class componentClass )
{
- super( componentManager, methodName, componentClass );
+ super( componentManager, methodName, methodName != null, componentClass );
}
@@ -35,4 +36,10 @@
{
return false;
}
+
+
+ protected String getMethodNamePrefix()
+ {
+ return "modified";
+ }
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/UnbindMethod.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/UnbindMethod.java
index 1b5ea93..4c4150b 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/UnbindMethod.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/UnbindMethod.java
@@ -37,7 +37,7 @@
protected String getMethodNamePrefix()
{
- return "un";
+ return "unbind";
}
}
\ No newline at end of file
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 be69718..4a8ff63 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
@@ -155,7 +155,7 @@
}
- ComponentInstance getComponentInstance()
+ public ComponentInstance getComponentInstance()
{
return m_componentContext;
}
@@ -228,7 +228,8 @@
// get the method
if ( m_activateMethod == null)
{
- m_activateMethod = new ActivateMethod( this, getComponentMetadata().getActivate(), implementationObjectClass );
+ m_activateMethod = new ActivateMethod( this, getComponentMetadata().getActivate(), getComponentMetadata()
+ .isActivateDeclared(), implementationObjectClass );
}
// 4. Call the activate method, if present
@@ -258,8 +259,8 @@
// get the method
if ( m_deactivateMethod == null )
{
- m_deactivateMethod = new DeactivateMethod( this, getComponentMetadata().getDeactivate(), implementationObject
- .getClass() );
+ m_deactivateMethod = new DeactivateMethod( this, getComponentMetadata().getDeactivate(),
+ getComponentMetadata().isDeactivateDeclared(), implementationObject.getClass() );
}
// 1. Call the deactivate method, if present
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java b/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java
index fc4b9fb..d6356a5 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java
@@ -79,9 +79,15 @@
// 112.5.8 activate can be specified (since DS 1.1)
private String m_activate = null;
+ // 112.5.8 whether activate has been specified
+ private boolean m_activateDeclared = false;
+
// 112.5.12 deactivate can be specified (since DS 1.1)
private String m_deactivate = null;
+ // 112.5.12 whether deactivate has been specified
+ private boolean m_deactivateDeclared = false;
+
// 112.??.?? modified method (configuration update, since DS 1.1)
private String m_modified = null;
@@ -234,6 +240,7 @@
return;
}
m_activate = activate;
+ m_activateDeclared = true;
}
@@ -250,6 +257,7 @@
return;
}
m_deactivate = deactivate;
+ m_deactivateDeclared = true;
}
@@ -448,6 +456,20 @@
/**
+ * Returns whether the activate method has been declared in the descriptor
+ * or not.
+ *
+ * @return whether the activate method has been declared in the descriptor
+ * or not.
+ * @since 1.2.0 (DS 1.1)
+ */
+ public boolean isActivateDeclared()
+ {
+ return m_activateDeclared;
+ }
+
+
+ /**
* Returns the name of the deactivate method
*
* @return the name of the deactivate method
@@ -460,6 +482,20 @@
/**
+ * Returns whether the deactivate method has been declared in the descriptor
+ * or not.
+ *
+ * @return whether the deactivate method has been declared in the descriptor
+ * or not.
+ * @since 1.2.0 (DS 1.1)
+ */
+ public boolean isDeactivateDeclared()
+ {
+ return m_deactivateDeclared;
+ }
+
+
+ /**
* Returns the name of the modified method
*
* @return the name of the modified method
@@ -614,9 +650,11 @@
}
else if ( m_namespaceCode < XmlHandler.DS_VERSION_1_1 )
{
+ // DS 1.0 cannot declare the activate method, assume default and undeclared
logger.log( LogService.LOG_WARNING,
"Ignoring activate method declaration, DS 1.1 or later namespace required", this, null );
m_activate = "activate";
+ m_activateDeclared = false;
}
// 112.5.12 deactivate can be specified (since DS 1.1)
@@ -627,9 +665,11 @@
}
else if ( m_namespaceCode < XmlHandler.DS_VERSION_1_1 )
{
+ // DS 1.0 cannot declare the deactivate method, assume default and undeclared
logger.log( LogService.LOG_WARNING,
"Ignoring deactivate method declaration, DS 1.1 or later namespace required", this, null );
m_deactivate = "deactivate";
+ m_deactivateDeclared = false;
}
// 112.??.?? modified can be specified (since DS 1.1)
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 788e872..d4c7dae 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
@@ -229,7 +229,7 @@
}
};
ImmediateComponentManager icm = new ImmediateComponentManager( null, null, metadata );
- ActivateMethod am = new ActivateMethod( icm, methodName, obj.getClass() );
+ ActivateMethod am = new ActivateMethod( icm, methodName, methodName != null, obj.getClass() );
am.invoke( obj, new ActivateMethod.ActivatorParameter( m_ctx, -1 ) );
Method m = get(am, "m_method");
assertNotNull( m );
@@ -257,7 +257,7 @@
}
};
ImmediateComponentManager icm = new ImmediateComponentManager( null, null, metadata );
- ActivateMethod am = new ActivateMethod( icm, methodName, obj.getClass() );
+ ActivateMethod am = new ActivateMethod( icm, methodName, methodName != null, obj.getClass() );
am.invoke( obj, new ActivateMethod.ActivatorParameter( m_ctx, -1 ) );
assertNull( get( am, "m_method" ) );
assertNull( obj.getCalledMethod() );
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentMetadataTest.java b/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentMetadataTest.java
index ba4b78a..5a1dd86 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentMetadataTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/metadata/ComponentMetadataTest.java
@@ -279,11 +279,13 @@
final ComponentMetadata cm1 = createComponentMetadata( Boolean.TRUE, null );
cm1.validate( logger );
assertEquals( "Activate method name", "activate", cm1.getActivate() );
+ assertFalse( "Activate method expected to not be declared", cm1.isActivateDeclared() );
final ComponentMetadata cm2 = createComponentMetadata( Boolean.TRUE, null );
cm2.setActivate( "someMethod" );
cm2.validate( logger );
assertEquals( "Activate method name", "activate", cm2.getActivate() );
+ assertFalse( "Activate method expected to not be declared", cm2.isActivateDeclared() );
}
@@ -292,11 +294,13 @@
final ComponentMetadata cm1 = createComponentMetadata11( Boolean.TRUE, null );
cm1.validate( logger );
assertEquals( "Activate method name", "activate", cm1.getActivate() );
+ assertFalse( "Activate method expected to not be declared", cm1.isActivateDeclared() );
final ComponentMetadata cm2 = createComponentMetadata11( Boolean.TRUE, null );
cm2.setActivate( "someMethod" );
cm2.validate( logger );
assertEquals( "Activate method name", "someMethod", cm2.getActivate() );
+ assertTrue( "Activate method expected to be declared", cm2.isActivateDeclared() );
}
@@ -305,11 +309,13 @@
final ComponentMetadata cm1 = createComponentMetadata( Boolean.TRUE, null );
cm1.validate( logger );
assertEquals( "Deactivate method name", "deactivate", cm1.getDeactivate() );
+ assertFalse( "Deactivate method expected to not be declared", cm1.isDeactivateDeclared() );
final ComponentMetadata cm2 = createComponentMetadata( Boolean.TRUE, null );
cm2.setDeactivate( "someMethod" );
cm2.validate( logger );
assertEquals( "Deactivate method name", "deactivate", cm2.getDeactivate() );
+ assertFalse( "Deactivate method expected to not be declared", cm2.isDeactivateDeclared() );
}
@@ -318,11 +324,13 @@
final ComponentMetadata cm1 = createComponentMetadata11( Boolean.TRUE, null );
cm1.validate( logger );
assertEquals( "Deactivate method name", "deactivate", cm1.getDeactivate() );
+ assertFalse( "Deactivate method expected to not be declared", cm1.isDeactivateDeclared() );
final ComponentMetadata cm2 = createComponentMetadata11( Boolean.TRUE, null );
cm2.setDeactivate( "someMethod" );
cm2.validate( logger );
assertEquals( "Deactivate method name", "someMethod", cm2.getDeactivate() );
+ assertTrue( "Deactivate method expected to be declared", cm2.isDeactivateDeclared() );
}
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java b/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java
index d8bed49..79106b3 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/metadata/XmlHandlerTest.java
@@ -72,7 +72,9 @@
assertEquals( "DS Version 1.0", XmlHandler.DS_VERSION_1_0, cm10.getNamespaceCode() );
assertFalse( "DS Version 1.0", cm10.isDS11() );
assertEquals( "Expected Activate Method not set", "activate", cm10.getActivate() );
+ assertFalse( "Activate method expected to not be declared", cm10.isActivateDeclared() );
assertEquals( "Expected Deactivate Method not set", "deactivate", cm10.getDeactivate() );
+ assertFalse( "Deactivate method expected to not be declared", cm10.isDeactivateDeclared() );
assertNull( "Expected Modified Method not set", cm10.getModified() );
assertEquals( "Expected Configuration Policy not set", ComponentMetadata.CONFIGURATION_POLICY_OPTIONAL, cm10
.getConfigurationPolicy() );
@@ -83,7 +85,9 @@
cm11.validate( logger );
assertEquals( "DS Version 1.1", XmlHandler.DS_VERSION_1_1, cm11.getNamespaceCode() );
assertEquals( "Expected Activate Method set", "myactivate", cm11.getActivate() );
+ assertTrue( "Activate method expected to be declared", cm11.isActivateDeclared() );
assertEquals( "Expected Deactivate Method set", "mydeactivate", cm11.getDeactivate() );
+ assertTrue( "Activate method expected to be declared", cm11.isDeactivateDeclared() );
assertEquals( "Expected Modified Method set", "mymodified", cm11.getModified() );
assertEquals( "Expected Configuration Policy set", ComponentMetadata.CONFIGURATION_POLICY_IGNORE, cm11
.getConfigurationPolicy() );
@@ -158,7 +162,9 @@
// ds 1.1 elements
assertEquals( "activate method", "myactivate", cm10.getActivate() );
assertEquals( "deactivate method", "mydeactivate", cm10.getDeactivate() );
+ assertTrue( "Activate method expected to be declared", cm10.isActivateDeclared() );
assertEquals( "modified method", "mymodified", cm10.getModified() );
+ assertTrue( "Deactivate method expected to be declared", cm10.isDeactivateDeclared() );
assertEquals( "configuration policy", "ignore", cm10.getConfigurationPolicy() );
// from the implementation element
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/ComponentActivationTest.java b/scr/src/test/java/org/apache/felix/scr/integration/ComponentActivationTest.java
new file mode 100644
index 0000000..510764c
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/integration/ComponentActivationTest.java
@@ -0,0 +1,188 @@
+/*
+ * 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.integration;
+
+
+import junit.framework.TestCase;
+
+import org.apache.felix.scr.Component;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+
+
+@RunWith(JUnit4TestRunner.class)
+public class ComponentActivationTest extends ComponentTestBase
+{
+
+ static
+ {
+ // use different components
+ descriptorFile = "/integration_test_activation_components.xml";
+
+ // uncomment to enable debugging of this test class
+ // paxRunnerVmOption = DEBUG_VM_OPTION;
+ }
+
+
+ @Test
+ public void test_activator_not_declared()
+ {
+ final String componentname = "ActivatorComponent.no.decl";
+
+ final Component component = findComponentByName( componentname );
+
+ TestCase.assertNotNull( component );
+ TestCase.assertFalse( component.isDefaultEnabled() );
+
+ TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+
+ component.enable();
+ delay();
+
+ TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+
+ component.disable();
+
+ delay();
+ TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+ }
+
+
+ @Test
+ public void test_activate_missing()
+ {
+ final String componentname = "ActivatorComponent.activate.missing";
+
+ final Component component = findComponentByName( componentname );
+
+ TestCase.assertNotNull( component );
+ TestCase.assertFalse( component.isDefaultEnabled() );
+
+ TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+
+ component.enable();
+ delay();
+
+ // activate must fail
+ TestCase.assertEquals( Component.STATE_UNSATISFIED, component.getState() );
+
+ component.disable();
+
+ delay();
+ TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+ }
+
+
+ @Test
+ public void test_deactivate_missing()
+ {
+ final String componentname = "ActivatorComponent.deactivate.missing";
+
+ final Component component = findComponentByName( componentname );
+
+ TestCase.assertNotNull( component );
+ TestCase.assertFalse( component.isDefaultEnabled() );
+
+ TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+
+ component.enable();
+ delay();
+
+ TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+
+ component.disable();
+
+ delay();
+ TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+ }
+
+
+ @Test
+ public void test_activator_declared()
+ {
+ final String componentname = "ActivatorComponent.decl";
+
+ final Component component = findComponentByName( componentname );
+
+ TestCase.assertNotNull( component );
+ TestCase.assertFalse( component.isDefaultEnabled() );
+
+ TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+
+ component.enable();
+ delay();
+
+ TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+
+ component.disable();
+
+ delay();
+ TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+ }
+
+
+ @Test
+ public void test_activate_fail()
+ {
+ final String componentname = "ActivatorComponent.activate.fail";
+
+ final Component component = findComponentByName( componentname );
+
+ TestCase.assertNotNull( component );
+ TestCase.assertFalse( component.isDefaultEnabled() );
+
+ TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+
+ component.enable();
+ delay();
+
+ // activate has failed
+ TestCase.assertEquals( Component.STATE_UNSATISFIED, component.getState() );
+
+ component.disable();
+
+ delay();
+ TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+ }
+
+
+ @Test
+ public void test_deactivate_fail()
+ {
+ final String componentname = "ActivatorComponent.deactivate.fail";
+
+ final Component component = findComponentByName( componentname );
+
+ TestCase.assertNotNull( component );
+ TestCase.assertFalse( component.isDefaultEnabled() );
+
+ TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+
+ component.enable();
+ delay();
+
+ TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+
+ component.disable();
+
+ delay();
+ TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+ }
+}
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/components/ActivatorComponent.java b/scr/src/test/java/org/apache/felix/scr/integration/components/ActivatorComponent.java
new file mode 100644
index 0000000..0aa747f
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/integration/components/ActivatorComponent.java
@@ -0,0 +1,51 @@
+/*
+ * 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.integration.components;
+
+
+import java.util.Map;
+
+
+public class ActivatorComponent
+{
+
+ public static final String FLAG_FAIL_ACTIVATE = "failActivate";
+
+ public static final String FLAG_FAIL_DEACTIVATE = "failDeactivate";
+
+
+ @SuppressWarnings("unused")
+ private void myActivate( Map<?, ?> configuration )
+ {
+ if ( configuration.containsKey( FLAG_FAIL_ACTIVATE ) )
+ {
+ throw new IllegalStateException( "myActivate fails" );
+ }
+ }
+
+
+ @SuppressWarnings("unused")
+ private void myDeactivate( Map<?, ?> configuration )
+ {
+ if ( configuration.containsKey( FLAG_FAIL_DEACTIVATE ) )
+ {
+ throw new IllegalStateException( "myDeactivate fails" );
+ }
+ }
+}
diff --git a/scr/src/test/resources/integration_test_activation_components.xml b/scr/src/test/resources/integration_test_activation_components.xml
new file mode 100644
index 0000000..00ccba9
--- /dev/null
+++ b/scr/src/test/resources/integration_test_activation_components.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0">
+
+ <!--
+ Components used for the ComponentActivationTest integration test.
+ This tests components with and without activate/deactivate method
+ configured and with and without activate/deactivate methods present
+ -->
+
+ <!-- no declaration of activate/deactivate methods -->
+ <scr:component name="ActivatorComponent.no.decl"
+ enabled="false">
+ <implementation class="org.apache.felix.scr.integration.components.ActivatorComponent" />
+ </scr:component>
+
+ <!-- wrong declaration of activate method -->
+ <scr:component name="ActivatorComponent.activate.missing"
+ enabled="false"
+ activate="nonExistingActivate">
+ <implementation class="org.apache.felix.scr.integration.components.ActivatorComponent" />
+ </scr:component>
+
+ <!-- wrong declaration of deactivate method -->
+ <scr:component name="ActivatorComponent.deactivate.missing"
+ enabled="false"
+ deactivate="nonExistingDeactivate">
+ <implementation class="org.apache.felix.scr.integration.components.ActivatorComponent" />
+ </scr:component>
+
+ <!-- correct declaration of activate and deactivate method -->
+ <scr:component name="ActivatorComponent.decl"
+ enabled="false"
+ activate="myActivate"
+ deactivate="myDeactivate">
+ <implementation class="org.apache.felix.scr.integration.components.ActivatorComponent" />
+ </scr:component>
+
+ <!-- correct declaration of activate and deactivate method, activate failure -->
+ <scr:component name="ActivatorComponent.activate.fail"
+ enabled="false"
+ activate="myActivate"
+ deactivate="myDeactivate">
+ <implementation class="org.apache.felix.scr.integration.components.ActivatorComponent" />
+ <property name="failActivate" value="true" />
+ </scr:component>
+
+ <!-- correct declaration of activate and deactivate method, deactivate failure -->
+ <scr:component name="ActivatorComponent.deactivate.fail"
+ enabled="false"
+ activate="myActivate"
+ deactivate="myDeactivate">
+ <implementation class="org.apache.felix.scr.integration.components.ActivatorComponent" />
+ <property name="failDeactivate" value="true" />
+ </scr:component>
+</components>