FELIX-4622 : Regression: SCR spec version detection incorrect for activate method
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1675609 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
index 2268c7b..43345f3 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/SCRDescriptorGenerator.java
@@ -292,7 +292,8 @@
* Create the SCR objects based on the descriptions
*/
private ComponentContainer createComponent(final ClassDescription desc,
- final IssueLog iLog) {
+ final IssueLog iLog)
+ throws SCRDescriptorException {
final ComponentDescription componentDesc = desc.getDescription(ComponentDescription.class);
final SpecVersion intitialComponentSpecVersion = componentDesc.getSpecVersion();
@@ -440,6 +441,20 @@
container.getProperties().put(org.osgi.framework.Constants.SERVICE_PID, pid);
}
+ // check lifecycle methods
+ if ( componentDesc.getActivate() == null ) {
+ final Validator.MethodResult result = Validator.findLifecycleMethod(project, container, "activate", true);
+ if ( result.method != null ) {
+ componentDesc.setSpecVersion(result.requiredSpecVersion);
+ }
+ }
+ if ( componentDesc.getDeactivate() == null ) {
+ final Validator.MethodResult result = Validator.findLifecycleMethod(project, container, "deactivate", false);
+ if ( result.method != null ) {
+ componentDesc.setSpecVersion(result.requiredSpecVersion);
+ }
+ }
+
// check if component has spec version configured but requires a higher one
if ( intitialComponentSpecVersion != null && componentDesc.getSpecVersion().ordinal() > intitialComponentSpecVersion.ordinal() ) {
iLog.addError("Component " + container + " requires spec version " + container.getComponentDescription().getSpecVersion().name()
diff --git a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/Validator.java b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/Validator.java
index da58ad2..e94f063 100644
--- a/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/Validator.java
+++ b/scrplugin/generator/src/main/java/org/apache/felix/scrplugin/helper/Validator.java
@@ -205,7 +205,9 @@
private static final String TYPE_INT = "int";
private static final String TYPE_INTEGER = "java.lang.Integer";
- private Method getMethod(final String name, final String[] sig)
+ private static Method getMethod(final Project project,
+ final ComponentContainer container,
+ final String name, final String[] sig)
throws SCRDescriptorException {
Class<?>[] classSig = (sig == null ? null : new Class<?>[sig.length]);
if ( sig != null ) {
@@ -214,14 +216,107 @@
if ( sig[i].equals("int") ) {
classSig[i] = int.class;
} else {
- classSig[i] = this.project.getClassLoader().loadClass(sig[i]);
+ classSig[i] = project.getClassLoader().loadClass(sig[i]);
}
} catch (final ClassNotFoundException e) {
throw new SCRDescriptorException("Unable to load class.", e);
}
}
}
- return getMethod(this.container.getClassDescription(), name, classSig);
+ return getMethod(container.getClassDescription(), name, classSig);
+ }
+
+ /**
+ * Find a lifecycle methods.
+ *
+ * @param methodName
+ * The method name.
+ * @param isActivate Whether this is the activate or deactivate method.
+ */
+ public static MethodResult findLifecycleMethod(
+ final Project project,
+ final ComponentContainer container,
+ final String methodName,
+ final boolean isActivate)
+ throws SCRDescriptorException {
+ final MethodResult result = new MethodResult();
+ result.requiredSpecVersion = SpecVersion.VERSION_1_0;
+
+ // first candidate is (de)activate(ComponentContext)
+ result.method = getMethod(project, container, methodName, new String[] { TYPE_COMPONENT_CONTEXT });
+ if (result.method == null) {
+ // Spec 1.1 or higher required
+ result.requiredSpecVersion = SpecVersion.VERSION_1_1;
+ // second candidate is (de)activate(BundleContext)
+ result.method = getMethod(project, container, methodName, new String[] { TYPE_BUNDLE_CONTEXT });
+ if (result.method == null) {
+ // third candidate is (de)activate(Map)
+ result.method = getMethod(project, container, methodName, new String[] { TYPE_MAP });
+
+ if (result.method == null) {
+ // if this is a deactivate method, we have two
+ // additional possibilities
+ // a method with parameter of type int and one of type
+ // Integer
+ if (!isActivate) {
+ result.method = getMethod(project, container, methodName, new String[] { TYPE_INT });
+ if (result.method == null) {
+ result.method = getMethod(project, container, methodName, new String[] { TYPE_INTEGER });
+ }
+ }
+ }
+
+ if (result.method == null) {
+ // fourth candidate is (de)activate with two or three
+ // arguments (type must be BundleContext, ComponentCtx
+ // and Map)
+ // as we have to iterate now and the fifth candidate is
+ // zero arguments
+ // we already store this option
+ Method zeroArgMethod = null;
+ Method found = result.method;
+ final Method[] methods = container.getClassDescription().getDescribedClass().getDeclaredMethods();
+ int i = 0;
+ while (i < methods.length) {
+ if (methodName.equals(methods[i].getName())) {
+
+ if (methods[i].getParameterTypes() == null || methods[i].getParameterTypes().length == 0) {
+ zeroArgMethod = methods[i];
+ } else if (methods[i].getParameterTypes().length >= 2) {
+ boolean valid = true;
+ for (int m = 0; m < methods[i].getParameterTypes().length; m++) {
+ final String type = methods[i].getParameterTypes()[m].getName();
+ if (!type.equals(TYPE_BUNDLE_CONTEXT) && !type.equals(TYPE_COMPONENT_CONTEXT)
+ && !type.equals(TYPE_MAP)) {
+ // if this is deactivate, int and
+ // integer are possible as well
+ if (isActivate || (!type.equals(TYPE_INT) && !type.equals(TYPE_INTEGER))) {
+ valid = false;
+ }
+ }
+ }
+ if (valid) {
+ if (found == null) {
+ found = methods[i];
+ } else {
+ // print warning
+ result.additionalWarning = "Lifecycle method " + methods[i].getName()
+ + " occurs several times with different matching signature.";
+ }
+ }
+ }
+ }
+ i++;
+ }
+ if (found != null) {
+ result.method = found;
+ } else {
+ result.method = zeroArgMethod;
+ }
+ }
+ }
+ }
+ return result;
}
/**
@@ -237,82 +332,13 @@
final boolean isActivate,
final boolean isSpecified)
throws SCRDescriptorException {
- // first candidate is (de)activate(ComponentContext)
- Method method = this.getMethod(methodName, new String[] { TYPE_COMPONENT_CONTEXT });
- if (method == null) {
- if (this.options.getSpecVersion().ordinal() >= SpecVersion.VERSION_1_1.ordinal() ) {
- // second candidate is (de)activate(BundleContext)
- method = this.getMethod(methodName, new String[] { TYPE_BUNDLE_CONTEXT });
- if (method == null) {
- // third candidate is (de)activate(Map)
- method = this.getMethod(methodName, new String[] { TYPE_MAP });
-
- if (method == null) {
- // if this is a deactivate method, we have two
- // additional possibilities
- // a method with parameter of type int and one of type
- // Integer
- if (!isActivate) {
- method = this.getMethod(methodName, new String[] { TYPE_INT });
- if (method == null) {
- method = this.getMethod(methodName, new String[] { TYPE_INTEGER });
- }
- }
- }
-
- if (method == null) {
- // fourth candidate is (de)activate with two or three
- // arguments (type must be BundleContext, ComponentCtx
- // and Map)
- // as we have to iterate now and the fifth candidate is
- // zero arguments
- // we already store this option
- Method zeroArgMethod = null;
- Method found = method;
- final Method[] methods = this.container.getClassDescription().getDescribedClass().getDeclaredMethods();
- int i = 0;
- while (i < methods.length) {
- if (methodName.equals(methods[i].getName())) {
-
- if (methods[i].getParameterTypes() == null || methods[i].getParameterTypes().length == 0) {
- zeroArgMethod = methods[i];
- } else if (methods[i].getParameterTypes().length >= 2) {
- boolean valid = true;
- for (int m = 0; m < methods[i].getParameterTypes().length; m++) {
- final String type = methods[i].getParameterTypes()[m].getName();
- if (!type.equals(TYPE_BUNDLE_CONTEXT) && !type.equals(TYPE_COMPONENT_CONTEXT)
- && !type.equals(TYPE_MAP)) {
- // if this is deactivate, int and
- // integer are possible as well
- if (isActivate || (!type.equals(TYPE_INT) && !type.equals(TYPE_INTEGER))) {
- valid = false;
- }
- }
- }
- if (valid) {
- if (found == null) {
- found = methods[i];
- } else {
- // print warning
- this.logWarn(this.container.getComponentDescription(), "Lifecycle method " + methods[i].getName()
- + " occurs several times with different matching signature.");
- }
- }
- }
- }
- i++;
- }
- if (found != null) {
- method = found;
- } else {
- method = zeroArgMethod;
- }
- }
- }
- }
+ final MethodResult result = findLifecycleMethod(this.project, this.container, methodName, isActivate);
+ if ( result.additionalWarning != null ) {
+ this.logWarn(this.container.getComponentDescription(), result.additionalWarning);
}
+
// if no method is found, we check for any method with that name to print some warnings or errors!
- if (method == null) {
+ if (result.method == null) {
final Method[] methods = this.container.getClassDescription().getDescribedClass().getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
if (methodName.equals(methods[i].getName())) {
@@ -337,12 +363,12 @@
}
// method must be protected for version 1.0
- if (method != null && options.getSpecVersion() == SpecVersion.VERSION_1_0) {
+ if (result.method != null && options.getSpecVersion() == SpecVersion.VERSION_1_0) {
// check protected
- if (Modifier.isPublic(method.getModifiers())) {
- this.logWarn(container.getComponentDescription(), "Lifecycle method " + method.getName() + " should be declared protected");
- } else if (!Modifier.isProtected(method.getModifiers())) {
- this.logWarn(container.getComponentDescription(), "Lifecycle method " + method.getName() +
+ if (Modifier.isPublic(result.method.getModifiers())) {
+ this.logWarn(container.getComponentDescription(), "Lifecycle method " + result.method.getName() + " should be declared protected");
+ } else if (!Modifier.isProtected(result.method.getModifiers())) {
+ this.logWarn(container.getComponentDescription(), "Lifecycle method " + result.method.getName() +
" has wrong qualifier, public or protected required");
}
}
@@ -582,6 +608,7 @@
public static final class MethodResult {
public Method method;
public SpecVersion requiredSpecVersion;
+ public String additionalWarning;
}
/**