FELIX-1229 : Support DS 1.0 and 1.1; only use new namespace if new features are used; rewrite error/warning handling.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@784126 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/Constants.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/Constants.java
index e77dbc5..9983e98 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/Constants.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/Constants.java
@@ -25,6 +25,13 @@
*/
public class Constants {
+ /** Version 1.0 (R4.1) */
+ public static final int VERSION_1_0 = 0;
+
+ /** Version 1.1 (R4.2) */
+ public static final int VERSION_1_1 = 1;
+
+
public static final String COMPONENT = "scr.component";
public static final String COMPONENT_NAME = "name";
@@ -49,6 +56,12 @@
public static final String COMPONENT_CREATE_PID = "create-pid";
+ // The component configuration policy (V1.1)
+ public static final String COMPONENT_CONFIG_POLICY = "policy";
+ public static final String COMPONENT_CONFIG_POLICY_OPTIONAL = "optional";
+ public static final String COMPONENT_CONFIG_POLICY_REQUIRE = "require";
+ public static final String COMPONENT_CONFIG_POLICY_IGNORE = "ignore";
+
public static final String PROPERTY = "scr.property";
public static final String PROPERTY_NAME = "name";
@@ -68,10 +81,18 @@
/** Property for multi value fields using references. */
public static final String PROPERTY_MULTIVALUE_REF_PREFIX = "valueRefs";
- /** @deprecated */
- public static final String OLD_PROPERTY_MULTIVALUE_REF_PREFIX = "refValues";
-
+ // property type
public static final String PROPERTY_TYPE = "type";
+ public static final String PROPERTY_TYPE_STRING = "String";
+ public static final String PROPERTY_TYPE_LONG = "Long";
+ public static final String PROPERTY_TYPE_DOUBLE = "Double";
+ public static final String PROPERTY_TYPE_FLOAT = "Float";
+ public static final String PROPERTY_TYPE_INTEGER = "Integer";
+ public static final String PROPERTY_TYPE_BYTE = "Bye";
+ public static final String PROPERTY_TYPE_CHAR = "Char";
+ public static final String PROPERTY_TYPE_CHAR_1_1 = "Character";
+ public static final String PROPERTY_TYPE_BOOLEAN = "Boolean";
+ public static final String PROPERTY_TYPE_SHORT = "Short";
public static final String PROPERTY_CARDINALITY = "cardinality";
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/IssueLog.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/IssueLog.java
new file mode 100644
index 0000000..3453ef1
--- /dev/null
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/IssueLog.java
@@ -0,0 +1,64 @@
+/*
+ * 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.scrplugin;
+
+import java.util.*;
+
+/**
+ * Utility class for handling errors and warnings
+ */
+public class IssueLog {
+
+ private final List<String> errors;
+
+ private final List<String> warnings;
+
+ public IssueLog(final boolean strictMode) {
+ this.errors = new ArrayList<String>();
+ if ( strictMode ) {
+ this.warnings = this.errors;
+ } else {
+ this.warnings = new ArrayList<String>();
+ }
+ }
+
+ public void addError(final String e) {
+ errors.add(e);
+ }
+
+ public void addWarning(final String e) {
+ warnings.add(e);
+ }
+
+ public int getNumberOfErrors() {
+ return this.errors.size();
+ }
+
+ public List<String> getErrors() {
+ return this.errors;
+ }
+
+ @SuppressWarnings("unchecked")
+ public List<String> getWarnings() {
+ if ( this.errors == this.warnings ) {
+ return Collections.EMPTY_LIST;
+ }
+ return this.warnings;
+ }
+}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/PropertyHandler.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/PropertyHandler.java
index a9169dd..1671831 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/PropertyHandler.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/PropertyHandler.java
@@ -61,7 +61,7 @@
protected void processProperty(JavaTag tag,
String name,
JavaField javaField,
- final List<String> warnings)
+ final IssueLog iLog)
throws MojoExecutionException {
final Property prop = new Property(tag);
prop.setName(name);
@@ -84,14 +84,7 @@
final String key = entry.getKey();
if (key.startsWith(Constants.PROPERTY_MULTIVALUE_PREFIX) ) {
values.add(entry.getValue());
- } else if ( key.startsWith(Constants.PROPERTY_MULTIVALUE_REF_PREFIX)
- || key.startsWith(Constants.OLD_PROPERTY_MULTIVALUE_REF_PREFIX) ) {
- if ( key.startsWith(Constants.OLD_PROPERTY_MULTIVALUE_REF_PREFIX) ) {
- warnings.add("@" + tag.getName() + ": " + "Deprecated attribute '" +
- Constants.OLD_PROPERTY_MULTIVALUE_REF_PREFIX + "' used, use '" +
- Constants.PROPERTY_MULTIVALUE_REF_PREFIX + "' instead "
- + " (" + tag.getSourceLocation() + ")");
- }
+ } else if ( key.startsWith(Constants.PROPERTY_MULTIVALUE_REF_PREFIX) ) {
final String[] stringValues = this.getPropertyValueRef(tag, prop, entry.getValue());
if ( stringValues != null ) {
for(int i=0; i<stringValues.length; i++) {
@@ -279,23 +272,23 @@
if ( prop.getType() == null ) {
final String type = field.getType();
if ( "java.lang.String".equals(type) ) {
- prop.setType("String");
+ prop.setType(Constants.PROPERTY_TYPE_STRING);
} else if ("java.lang.Long".equals(type) || "long".equals(type) ) {
- prop.setType("Long");
+ prop.setType(Constants.PROPERTY_TYPE_LONG);
} else if ("java.lang.Double".equals(type) || "double".equals(type) ) {
- prop.setType("Double");
+ prop.setType(Constants.PROPERTY_TYPE_DOUBLE);
} else if ("java.lang.Float".equals(type) || "float".equals(type) ) {
- prop.setType("Float");
+ prop.setType(Constants.PROPERTY_TYPE_FLOAT);
} else if ("java.lang.Integer".equals(type) || "int".equals(type) ) {
- prop.setType("Integer");
+ prop.setType(Constants.PROPERTY_TYPE_INTEGER);
} else if ("java.lang.Byte".equals(type) || "byte".equals(type) ) {
- prop.setType("Byte");
+ prop.setType(Constants.PROPERTY_TYPE_BYTE);
} else if ("java.lang.Character".equals(type) || "char".equals(type) ) {
- prop.setType("Char");
+ prop.setType(Constants.PROPERTY_TYPE_CHAR_1_1);
} else if ("java.lang.Boolean".equals(type) || "boolean".equals(type) ) {
- prop.setType("Boolean");
+ prop.setType(Constants.PROPERTY_TYPE_BOOLEAN);
} else if ("java.lang.Short".equals(type) || "short".equals(type) ) {
- prop.setType("Short");
+ prop.setType(Constants.PROPERTY_TYPE_SHORT);
}
}
@@ -341,20 +334,18 @@
/**
* Process all found properties for the component.
* @param globalProperties Global properties are set on all components.
- * @param errors List of occured errors.
- * @param warnings List of occured warnings
+ * @param iLog The issue log.
* @throws MojoExecutionException
*/
public void processProperties(final Map<String, String> globalProperties,
- final List<String> errors,
- final List<String> warnings)
+ final IssueLog iLog)
throws MojoExecutionException {
final Iterator<Map.Entry<String, PropertyDescription>> propIter = properties.entrySet().iterator();
while ( propIter.hasNext() ) {
final Map.Entry<String, PropertyDescription> entry = propIter.next();
final String propName = entry.getKey();
final PropertyDescription desc = entry.getValue();
- this.processProperty(desc.propertyTag, propName, desc.field, warnings);
+ this.processProperty(desc.propertyTag, propName, desc.field, iLog);
}
// apply pre configured global properties
if ( globalProperties != null ) {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorMojo.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorMojo.java
index bd99ec2..d82a01f 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorMojo.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/SCRDescriptorMojo.java
@@ -134,23 +134,23 @@
this.getLog().debug("..parsing javadocs: " + this.parseJavadoc);
this.getLog().debug("..processing annotations: " + this.processAnnotations);
- boolean hasFailures = false;
-
JavaClassDescriptorManager jManager = new JavaClassDescriptorManager(this.getLog(),
this.project,
this.annotationTagProviders,
this.sourceExcludes,
this.parseJavadoc,
this.processAnnotations);
+ final IssueLog iLog = new IssueLog(this.strictMode);
+
+ final MetaData metaData = new MetaData();
+ metaData.setLocalization(MetaTypeService.METATYPE_DOCUMENTS_LOCATION + "/metatype");
+
// iterate through all source classes and check for component tag
final JavaClassDescription[] javaSources = jManager.getSourceDescriptions();
Arrays.sort(javaSources, new JavaClassDescriptionInheritanceComparator());
- final Components components = new Components();
- final Components abstractComponents = new Components();
- final MetaData metaData = new MetaData();
- metaData.setLocalization(MetaTypeService.METATYPE_DOCUMENTS_LOCATION + "/metatype");
-
+ int specVersion = Constants.VERSION_1_0;
+ final List<Component> scannedComponents = new ArrayList<Component>();
for (int i = 0; i < javaSources.length; i++) {
this.getLog().debug("Testing source " + javaSources[i].getName());
final JavaTag tag = javaSources[i].getTagByName(Constants.COMPONENT);
@@ -158,31 +158,52 @@
this.getLog().debug("Processing service class " + javaSources[i].getName());
// check if there is more than one component tag!
if ( javaSources[i].getTagsByName(Constants.COMPONENT, false).length > 1 ) {
- hasFailures = true;
- this.getLog().error("Class " + javaSources[i].getName() + " has more than one " + Constants.COMPONENT + " tag." +
+ iLog.addError("Class " + javaSources[i].getName() + " has more than one " + Constants.COMPONENT + " tag." +
" Merge the tags to a single tag.");
} else {
- final Component comp = this.createComponent(javaSources[i], tag, metaData);
- if (comp != null) {
- if ( !comp.isDs() ) {
- getLog().debug("Not adding descriptor " + comp);
- } else if ( comp.isAbstract() ) {
- this.getLog().debug("Adding abstract descriptor " + comp);
- abstractComponents.addComponent(comp);
- } else {
- this.getLog().debug("Adding descriptor " + comp);
- components.addComponent(comp);
- abstractComponents.addComponent(comp);
- }
- } else {
- hasFailures = true;
+ final Component comp = this.createComponent(javaSources[i], tag, metaData, iLog);
+ if ( comp.getSpecVersion() > specVersion ) {
+ specVersion = comp.getSpecVersion();
}
+ scannedComponents.add(comp);
}
}
}
+ // now check for abstract components and fill components objects
+ final Components components = new Components();
+ final Components abstractComponents = new Components();
+ components.setSpecVersion(specVersion);
+ abstractComponents.setSpecVersion(specVersion);
+
+ for(final Component comp : scannedComponents ) {
+ final int errorCount = iLog.getNumberOfErrors();
+ comp.validate(specVersion, iLog);
+ // ignore component if it has errors
+ if ( iLog.getNumberOfErrors() == errorCount ) {
+ if ( !comp.isDs() ) {
+ getLog().debug("Ignoring descriptor " + comp);
+ } else if ( comp.isAbstract() ) {
+ this.getLog().debug("Adding abstract descriptor " + comp);
+ abstractComponents.addComponent(comp);
+ } else {
+ this.getLog().debug("Adding descriptor " + comp);
+ components.addComponent(comp);
+ abstractComponents.addComponent(comp);
+ }
+ }
+ }
+
+ // now log warnings and errors (warnings first)
+ for(String warn : iLog.getWarnings()) {
+ this.getLog().warn(warn);
+ }
+ for(String err : iLog.getErrors()) {
+ this.getLog().error(err);
+ }
+
// after checking all classes, throw if there were any failures
- if (hasFailures) {
+ if (iLog.getNumberOfErrors() > 0 ) {
throw new MojoFailureException("SCR Descriptor parsing had failures (see log)");
}
@@ -280,11 +301,11 @@
* @return The generated component descriptor or null if any error occurs.
* @throws MojoExecutionException
*/
- protected Component createComponent(JavaClassDescription description, JavaTag componentTag, MetaData metaData)
+ protected Component createComponent(JavaClassDescription description,
+ JavaTag componentTag,
+ MetaData metaData,
+ final IssueLog iLog)
throws MojoExecutionException {
- // two lists for errors and warnings
- final List<String> errors = new ArrayList<String>();
- final List<String> warnings = new ArrayList<String>();
// create a new component
final Component component = new Component(componentTag);
@@ -330,7 +351,7 @@
} while (inherited && currentDescription != null);
// process properties
- propertyHandler.processProperties(this.properties, errors, warnings);
+ propertyHandler.processProperties(this.properties, iLog);
// process references
final Iterator<Map.Entry<String, Object[]>> refIter = references.entrySet().iterator();
@@ -359,24 +380,7 @@
pid.setValue(component.getName());
}
}
-
- component.validate(errors, warnings);
-
- // now log warnings and errors (warnings first)
- // FELIX-997: In strictMode all warnings are regarded as errors
- if ( this.strictMode ) {
- errors.addAll(warnings);
- warnings.clear();
- }
- for(String warn : warnings) {
- this.getLog().warn(warn);
- }
- for(String err : errors) {
- this.getLog().error(err);
- }
-
- // return nothing if validation fails
- return errors.size() == 0 ? component : null;
+ return component;
}
/**
@@ -412,6 +416,12 @@
Constants.COMPONENT_IMMEDIATE, true)));
}
+ // check for V1.1 attributes
+ if ( tag.getNamedParameter(Constants.COMPONENT_CONFIG_POLICY) != null ) {
+ component.setSpecVersion(Constants.VERSION_1_1);
+ component.setConfigurationPolicy(tag.getNamedParameter(Constants.COMPONENT_CONFIG_POLICY));
+ }
+
// whether metatype information is to generated for the component
final String metaType = tag.getNamedParameter(Constants.COMPONENT_METATYPE);
final boolean hasMetaType = metaType == null || "yes".equalsIgnoreCase(metaType)
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java
index 20f5f0c..8b2049a 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Component.java
@@ -21,6 +21,8 @@
import java.util.ArrayList;
import java.util.List;
+import org.apache.felix.scrplugin.Constants;
+import org.apache.felix.scrplugin.IssueLog;
import org.apache.felix.scrplugin.tags.*;
import org.apache.maven.plugin.MojoExecutionException;
@@ -61,6 +63,12 @@
/** Is this a descriptor to be ignored ? */
protected boolean isDs;
+ /** Configuration policy. (V1.1) */
+ protected String configurationPolicy;
+
+ /** The spec version. */
+ protected int specVersion;
+
/**
* Default constructor.
*/
@@ -76,6 +84,20 @@
}
/**
+ * Get the spec version.
+ */
+ public int getSpecVersion() {
+ return this.specVersion;
+ }
+
+ /**
+ * Set the spec version.
+ */
+ public void setSpecVersion(int value) {
+ this.specVersion = value;
+ }
+
+ /**
* Return the associated java class description
*/
public JavaClassDescription getJavaClassDescription() {
@@ -181,9 +203,9 @@
* If errors occur a message is added to the issues list,
* warnings can be added to the warnings list.
*/
- public void validate(List<String> issues, List<String> warnings)
+ public void validate(final int specVersion, final IssueLog iLog)
throws MojoExecutionException {
- final int currentIssueCount = issues.size();
+ final int currentIssueCount = iLog.getNumberOfErrors();
// nothing to check if this is ignored
if (!isDs()) {
@@ -192,24 +214,24 @@
final JavaClassDescription javaClass = this.tag.getJavaClassDescription();
if (javaClass == null) {
- issues.add(this.getMessage("Tag not declared in a Java Class"));
+ iLog.addError(this.getMessage("Tag not declared in a Java Class"));
} else {
// if the service is abstract, we do not validate everything
if ( !this.isAbstract ) {
// ensure non-abstract, public class
if (!javaClass.isPublic()) {
- issues.add(this.getMessage("Class must be public: " + javaClass.getName()));
+ iLog.addError(this.getMessage("Class must be public: " + javaClass.getName()));
}
if (javaClass.isAbstract() || javaClass.isInterface()) {
- issues.add(this.getMessage("Class must be concrete class (not abstract or interface) : " + javaClass.getName()));
+ iLog.addError(this.getMessage("Class must be concrete class (not abstract or interface) : " + javaClass.getName()));
}
// no errors so far, let's continue
- if ( issues.size() == currentIssueCount ) {
+ if ( iLog.getNumberOfErrors() == currentIssueCount ) {
// check activate and deactivate methods
- this.checkLifecycleMethod(javaClass, "activate", warnings);
- this.checkLifecycleMethod(javaClass, "deactivate", warnings);
+ this.checkLifecycleMethod(javaClass, "activate", iLog);
+ this.checkLifecycleMethod(javaClass, "deactivate", iLog);
// ensure public default constructor
boolean constructorFound = true;
@@ -228,42 +250,53 @@
}
}
if (!constructorFound) {
- issues.add(this.getMessage("Class must have public default constructor: " + javaClass.getName()));
+ iLog.addError(this.getMessage("Class must have public default constructor: " + javaClass.getName()));
}
// verify properties
for(final Property prop : this.getProperties()) {
- prop.validate(issues, warnings);
+ prop.validate(specVersion, iLog);
}
// verify service
boolean isServiceFactory = false;
if (this.getService() != null) {
if ( this.getService().getInterfaces().size() == 0 ) {
- issues.add(this.getMessage("Service interface information is missing for @scr.service tag"));
+ iLog.addError(this.getMessage("Service interface information is missing for @scr.service tag"));
}
- this.getService().validate(issues, warnings);
+ this.getService().validate(specVersion, iLog);
isServiceFactory = this.getService().isServicefactory();
}
// serviceFactory must not be true for immediate of component factory
if (isServiceFactory && this.isImmediate() != null && this.isImmediate().booleanValue() && this.getFactory() != null) {
- issues.add(this.getMessage("Component must not be a ServiceFactory, if immediate and/or component factory: " + javaClass.getName()));
+ iLog.addError(this.getMessage("Component must not be a ServiceFactory, if immediate and/or component factory: " + javaClass.getName()));
}
// immediate must not be true for component factory
if (this.isImmediate() != null && this.isImmediate().booleanValue() && this.getFactory() != null) {
- issues.add(this.getMessage("Component must not be immediate if component factory: " + javaClass.getName()));
+ iLog.addError(this.getMessage("Component must not be immediate if component factory: " + javaClass.getName()));
}
}
}
- if ( issues.size() == currentIssueCount ) {
+ if ( iLog.getNumberOfErrors() == currentIssueCount ) {
// verify references
for(final Reference ref : this.getReferences()) {
- ref.validate(issues, warnings, this.isAbstract);
+ ref.validate(specVersion, this.isAbstract, iLog);
}
}
}
+ // check additional stuff if version is 1.1
+ if ( specVersion == Constants.VERSION_1_1 ) {
+ final String cp = this.getConfigurationPolicy();
+ if ( cp != null
+ && !Constants.COMPONENT_CONFIG_POLICY_IGNORE.equals(cp)
+ && !Constants.COMPONENT_CONFIG_POLICY_REQUIRE.equals(cp)
+ && !Constants.COMPONENT_CONFIG_POLICY_OPTIONAL.equals(cp) ) {
+ iLog.addError(this.getMessage("Component has an unknown value for configuration policy: " + cp));
+ }
+
+ }
}
/**
@@ -272,15 +305,15 @@
* @param methodName The method name.
* @param warnings The list of warnings used to add new warnings.
*/
- protected void checkLifecycleMethod(JavaClassDescription javaClass, String methodName, List<String> warnings)
+ protected void checkLifecycleMethod(JavaClassDescription javaClass, String methodName, final IssueLog iLog)
throws MojoExecutionException {
final JavaMethod method = javaClass.getMethodBySignature(methodName, new String[] {"org.osgi.service.component.ComponentContext"});
if ( method != null ) {
// check protected
if (method.isPublic()) {
- warnings.add(this.getMessage("Lifecycle method " + method.getName() + " should be declared protected"));
+ iLog.addWarning(this.getMessage("Lifecycle method " + method.getName() + " should be declared protected"));
} else if (!method.isProtected()) {
- warnings.add(this.getMessage("Lifecycle method " + method.getName() + " has wrong qualifier, public or protected required"));
+ iLog.addWarning(this.getMessage("Lifecycle method " + method.getName() + " has wrong qualifier, public or protected required"));
}
} else {
// if no method is found, we check for any method with that name
@@ -289,12 +322,26 @@
if ( methodName.equals(methods[i].getName()) ) {
if ( methods[i].getParameters().length != 1 ) {
- warnings.add(this.getMessage("Lifecycle method " + methods[i].getName() + " has wrong number of arguments"));
+ iLog.addWarning(this.getMessage("Lifecycle method " + methods[i].getName() + " has wrong number of arguments"));
} else {
- warnings.add(this.getMessage("Lifecycle method " + methods[i].getName() + " has wrong argument " + methods[i].getParameters()[0].getType()));
+ iLog.addWarning(this.getMessage("Lifecycle method " + methods[i].getName() + " has wrong argument " + methods[i].getParameters()[0].getType()));
}
}
}
}
}
+
+ /**
+ * Return the configuration policy.
+ */
+ public String getConfigurationPolicy() {
+ return this.configurationPolicy;
+ }
+
+ /**
+ * Set the configuration policy.
+ */
+ public void setConfigurationPolicy(final String value) {
+ this.configurationPolicy = value;
+ }
}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Components.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Components.java
index 05f2944..208bdc9 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Components.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Components.java
@@ -28,6 +28,9 @@
*/
public class Components {
+ /** The spec version. */
+ private int specVersion;
+
/** The list of {@link Component}s. */
protected List<Component> components = new ArrayList<Component>();
@@ -51,4 +54,18 @@
public void addComponent(Component component) {
this.components.add(component);
}
+
+ /**
+ * Get the spec version.
+ */
+ public int getSpecVersion() {
+ return this.specVersion;
+ }
+
+ /**
+ * Set the spec version.
+ */
+ public void setSpecVersion(int value) {
+ this.specVersion = value;
+ }
}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Interface.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Interface.java
index 956c3b1..d3997ba 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Interface.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Interface.java
@@ -18,8 +18,7 @@
*/
package org.apache.felix.scrplugin.om;
-import java.util.List;
-
+import org.apache.felix.scrplugin.IssueLog;
import org.apache.felix.scrplugin.tags.JavaClassDescription;
import org.apache.felix.scrplugin.tags.JavaTag;
import org.apache.maven.plugin.MojoExecutionException;
@@ -59,16 +58,16 @@
* If errors occur a message is added to the issues list,
* warnings can be added to the warnings list.
*/
- public void validate(List<String> issues, List<String> warnings)
+ public void validate(final int specVersion, final IssueLog iLog)
throws MojoExecutionException {
final JavaClassDescription javaClass = this.tag.getJavaClassDescription();
if (javaClass == null) {
- issues.add(this.getMessage("Must be declared in a Java class"));
+ iLog.addError(this.getMessage("Must be declared in a Java class"));
} else {
if ( !javaClass.isA(this.getInterfacename()) ) {
// interface not implemented
- issues.add(this.getMessage("Class must implement provided interface " + this.getInterfacename()));
+ iLog.addError(this.getMessage("Class must implement provided interface " + this.getInterfacename()));
}
}
}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java
index 265b35d..7ba0703 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Property.java
@@ -18,8 +18,8 @@
*/
package org.apache.felix.scrplugin.om;
-import java.util.List;
-
+import org.apache.felix.scrplugin.Constants;
+import org.apache.felix.scrplugin.IssueLog;
import org.apache.felix.scrplugin.tags.JavaTag;
/**
@@ -91,11 +91,32 @@
* If errors occur a message is added to the issues list,
* warnings can be added to the warnings list.
*/
- public void validate(List<String> issues, List<String> warnings) {
+ public void validate(final int specVersion, final IssueLog iLog) {
if ( name == null || name.trim().length() == 0 ) {
- issues.add(this.getMessage("Property name can not be empty."));
+ iLog.addError(this.getMessage("Property name can not be empty."));
}
- // might want to check type (and value)
+ if ( type != null ) {
+ if ( !type.equals(Constants.PROPERTY_TYPE_BOOLEAN)
+ && !type.equals(Constants.PROPERTY_TYPE_BYTE )
+ && !type.equals(Constants.PROPERTY_TYPE_CHAR )
+ && !type.equals(Constants.PROPERTY_TYPE_CHAR_1_1 )
+ && !type.equals(Constants.PROPERTY_TYPE_DOUBLE )
+ && !type.equals(Constants.PROPERTY_TYPE_FLOAT )
+ && !type.equals(Constants.PROPERTY_TYPE_INTEGER )
+ && !type.equals(Constants.PROPERTY_TYPE_LONG )
+ && !type.equals(Constants.PROPERTY_TYPE_STRING )
+ && !type.equals(Constants.PROPERTY_TYPE_SHORT ) ) {
+ iLog.addError(this.getMessage("Property " + name + " has unknown type: " + type));
+ }
+ // now check for old and new char
+ if ( specVersion == Constants.VERSION_1_0 && type.equals(Constants.PROPERTY_TYPE_CHAR_1_1) ) {
+ type = Constants.PROPERTY_TYPE_CHAR;
+ }
+ if ( specVersion == Constants.VERSION_1_1 && type.equals(Constants.PROPERTY_TYPE_CHAR) ) {
+ type = Constants.PROPERTY_TYPE_CHAR_1_1;
+ }
+ }
+ // TODO might want to check value
}
public boolean isPrivate() {
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java
index 3bf26f3..c8367f4 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Reference.java
@@ -18,8 +18,7 @@
*/
package org.apache.felix.scrplugin.om;
-import java.util.List;
-
+import org.apache.felix.scrplugin.IssueLog;
import org.apache.felix.scrplugin.tags.*;
import org.apache.maven.plugin.MojoExecutionException;
import org.codehaus.plexus.util.StringUtils;
@@ -149,22 +148,24 @@
* If errors occur a message is added to the issues list,
* warnings can be added to the warnings list.
*/
- public void validate(List<String> issues, List<String> warnings, boolean componentIsAbstract)
+ public void validate(final int specVersion,
+ final boolean componentIsAbstract,
+ final IssueLog iLog)
throws MojoExecutionException {
// if this reference is already checked, return immediately
if ( this.checked ) {
return;
}
- final int currentIssueCount = issues.size();
+ final int currentIssueCount = iLog.getNumberOfErrors();
// validate name
if (StringUtils.isEmpty(this.name)) {
- issues.add(this.getMessage("Reference has no name"));
+ iLog.addError(this.getMessage("Reference has no name"));
}
// validate interface
if (StringUtils.isEmpty(this.interfacename)) {
- issues.add(this.getMessage("Missing interface name"));
+ iLog.addError(this.getMessage("Missing interface name"));
}
// validate cardinality
@@ -172,30 +173,30 @@
this.cardinality = "1..1";
} else if (!"0..1".equals(this.cardinality) && !"1..1".equals(this.cardinality)
&& !"0..n".equals(this.cardinality) && !"1..n".equals(this.cardinality)) {
- issues.add(this.getMessage("Invalid Cardinality specification " + this.cardinality));
+ iLog.addError(this.getMessage("Invalid Cardinality specification " + this.cardinality));
}
// validate policy
if (this.policy == null) {
this.policy = "static";
} else if (!"static".equals(this.policy) && !"dynamic".equals(this.policy)) {
- issues.add(this.getMessage("Invalid Policy specification " + this.policy));
+ iLog.addError(this.getMessage("Invalid Policy specification " + this.policy));
}
// validate strategy
if (this.strategy == null) {
this.strategy = "event";
} else if (!"event".equals(this.strategy) && !"lookup".equals(this.strategy)) {
- issues.add(this.getMessage("Invalid startegy type " + this.strategy));
+ iLog.addError(this.getMessage("Invalid startegy type " + this.strategy));
}
// validate bind and unbind methods
if (!isLookupStrategy()) {
final String oldBind = this.bind;
final String oldUnbind = this.unbind;
- this.bind = this.validateMethod(this.bind, issues, warnings, componentIsAbstract);
- this.unbind = this.validateMethod(this.unbind, issues, warnings, componentIsAbstract);
- if ( issues.size() == currentIssueCount ) {
+ this.bind = this.validateMethod(this.bind, componentIsAbstract, iLog);
+ this.unbind = this.validateMethod(this.unbind, componentIsAbstract, iLog);
+ if ( iLog.getNumberOfErrors() == currentIssueCount ) {
if ( this.bind != null && this.unbind != null ) {
// no errors, so we're checked
this.checked = true;
@@ -214,23 +215,22 @@
}
}
- protected String validateMethod(String methodName,
- List<String> issues,
- List<String> warnings,
- boolean componentIsAbstract)
+ protected String validateMethod(String methodName,
+ boolean componentIsAbstract,
+ final IssueLog iLog)
throws MojoExecutionException {
final JavaMethod method = this.findMethod(methodName);
if (method == null) {
if ( !componentIsAbstract ) {
- issues.add(this.getMessage("Missing method " + methodName + " for reference " + this.getName()));
+ iLog.addError(this.getMessage("Missing method " + methodName + " for reference " + this.getName()));
}
return null;
}
if (method.isPublic()) {
- warnings.add(this.getMessage("Method " + method.getName() + " should be declared protected"));
+ iLog.addWarning(this.getMessage("Method " + method.getName() + " should be declared protected"));
} else if (!method.isProtected()) {
- issues.add(this.getMessage("Method " + method.getName() + " has wrong qualifier, public or protected required"));
+ iLog.addError(this.getMessage("Method " + method.getName() + " has wrong qualifier, public or protected required"));
return null;
}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Service.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Service.java
index aa18742..7d80258 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Service.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/om/Service.java
@@ -20,6 +20,7 @@
import java.util.*;
+import org.apache.felix.scrplugin.IssueLog;
import org.apache.maven.plugin.MojoExecutionException;
/**
@@ -90,10 +91,10 @@
* If errors occur a message is added to the issues list,
* warnings can be added to the warnings list.
*/
- public void validate(List<String> issues, List<String> warnings)
+ public void validate(final int specVersion, final IssueLog iLog)
throws MojoExecutionException {
for(final Interface interf : this.getInterfaces()) {
- interf.validate(issues, warnings);
+ interf.validate(specVersion, iLog);
}
}
diff --git a/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java b/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
index 1468522..ddee994 100644
--- a/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
+++ b/scrplugin/src/main/java/org/apache/felix/scrplugin/xml/ComponentDescriptorIO.java
@@ -24,6 +24,7 @@
import javax.xml.transform.TransformerException;
+import org.apache.felix.scrplugin.Constants;
import org.apache.felix.scrplugin.om.*;
import org.apache.maven.plugin.MojoExecutionException;
import org.xml.sax.*;
@@ -38,18 +39,30 @@
*/
public class ComponentDescriptorIO {
- public static final String NAMESPACE_URI = "http://www.osgi.org/xmlns/scr/v1.0.0";
+ /** The namespace for R4.1 - Version 1.0 */
+ public static final String NAMESPACE_URI_1_0 = "http://www.osgi.org/xmlns/scr/v1.0.0";
+ /** The namespace for R4.2 - Version 1.1 */
+ public static final String NAMESPACE_URI_1_1 = "http://www.osgi.org/xmlns/scr/v1.1.0";
+
+ /** The inner namespace - used for all inner elements. */
public static final String INNER_NAMESPACE_URI = "";
+ /** The prefix used for the namespace. */
private static final String PREFIX = "scr";
+ /** The root element. */
private static final String COMPONENTS = "components";
+ /** The component element. */
private static final String COMPONENT = "component";
+ /** The qualified component element. */
private static final String COMPONENT_QNAME = PREFIX + ':' + COMPONENT;
+ /** The policy attribute. */
+ private static final String COMPONENT_ATTR_POLICY = "configuration-policy";
+
private static final String IMPLEMENTATION = "implementation";
private static final String IMPLEMENTATION_QNAME = IMPLEMENTATION;
@@ -111,15 +124,24 @@
*/
protected static void generateXML(Components components, ContentHandler contentHandler, boolean isScrPrivateFile)
throws SAXException {
+ // detect namespace to use
+ final String namespace;
+ if ( components.getSpecVersion() == Constants.VERSION_1_0 ) {
+ namespace = NAMESPACE_URI_1_0;
+ } else {
+ namespace = NAMESPACE_URI_1_1;
+ }
contentHandler.startDocument();
- contentHandler.startPrefixMapping(PREFIX, NAMESPACE_URI);
+ contentHandler.startPrefixMapping(PREFIX, namespace);
// wrapper element to generate well formed xml
contentHandler.startElement("", ComponentDescriptorIO.COMPONENTS, ComponentDescriptorIO.COMPONENTS, new AttributesImpl());
IOUtils.newline(contentHandler);
for(final Component component : components.getComponents()) {
- generateXML(component, contentHandler, isScrPrivateFile);
+ if ( component.isDs() ) {
+ generateXML(namespace, component, contentHandler, isScrPrivateFile);
+ }
}
// end wrapper element
contentHandler.endElement("", ComponentDescriptorIO.COMPONENTS, ComponentDescriptorIO.COMPONENTS);
@@ -134,7 +156,10 @@
* @param contentHandler
* @throws SAXException
*/
- protected static void generateXML(Component component, ContentHandler contentHandler, boolean isScrPrivateFile)
+ protected static void generateXML(final String namespace,
+ final Component component,
+ final ContentHandler contentHandler,
+ final boolean isScrPrivateFile)
throws SAXException {
final AttributesImpl ai = new AttributesImpl();
IOUtils.addAttribute(ai, "enabled", component.isEnabled());
@@ -142,8 +167,13 @@
IOUtils.addAttribute(ai, "name", component.getName());
IOUtils.addAttribute(ai, "factory", component.getFactory());
+ // attributes new in 1.1
+ if ( NAMESPACE_URI_1_1.equals(namespace) ) {
+ IOUtils.addAttribute(ai, COMPONENT_ATTR_POLICY, component.getConfigurationPolicy());
+ }
+
IOUtils.indent(contentHandler, 1);
- contentHandler.startElement(NAMESPACE_URI, ComponentDescriptorIO.COMPONENT, ComponentDescriptorIO.COMPONENT_QNAME, ai);
+ contentHandler.startElement(namespace, ComponentDescriptorIO.COMPONENT, ComponentDescriptorIO.COMPONENT_QNAME, ai);
IOUtils.newline(contentHandler);
generateXML(component.getImplementation(), contentHandler);
if ( component.getService() != null ) {
@@ -160,7 +190,7 @@
}
}
IOUtils.indent(contentHandler, 1);
- contentHandler.endElement(NAMESPACE_URI, ComponentDescriptorIO.COMPONENT, ComponentDescriptorIO.COMPONENT_QNAME);
+ contentHandler.endElement(namespace, ComponentDescriptorIO.COMPONENT, ComponentDescriptorIO.COMPONENT_QNAME);
IOUtils.newline(contentHandler);
}
@@ -320,7 +350,7 @@
if ( this.firstElement ) {
this.firstElement = false;
if ( localName.equals(COMPONENT) && "".equals(uri) ) {
- this.overrideNamespace = NAMESPACE_URI;
+ this.overrideNamespace = NAMESPACE_URI_1_0;
}
}
@@ -332,11 +362,15 @@
// of a component are unqualified, so they don't have
// the namespace - we allow both: with or without namespace!
if ( this.isComponent && "".equals(uri) ) {
- uri = NAMESPACE_URI;
+ uri = NAMESPACE_URI_1_0;
}
// from here on, uri has the namespace regardless of the used xml format
- if ( NAMESPACE_URI.equals(uri) ) {
+ if ( NAMESPACE_URI_1_0.equals(uri) || NAMESPACE_URI_1_1.equals(uri) ) {
+
+ if ( NAMESPACE_URI_1_1.equals(uri) ) {
+ components.setSpecVersion(Constants.VERSION_1_1);
+ }
if (localName.equals(COMPONENT)) {
this.isComponent = true;
@@ -430,10 +464,10 @@
}
if ( this.isComponent && "".equals(uri) ) {
- uri = NAMESPACE_URI;
+ uri = NAMESPACE_URI_1_0;
}
- if ( NAMESPACE_URI.equals(uri) ) {
+ if ( NAMESPACE_URI_1_0.equals(uri) || NAMESPACE_URI_1_1.equals(uri) ) {
if (localName.equals(COMPONENT) ) {
this.components.addComponent(this.currentComponent);
this.currentComponent = null;