* Validate the component description. If errors occur a message is added to
* the issues list, warnings can be added to the warnings list.
*/
public void validate()
throws SCRDescriptorException {
final ComponentDescription component = this.container.getComponentDescription();
// nothing to check if this is ignored
if (!component.isCreateDs()) {
return;
}
final int currentIssueCount = iLog.getNumberOfErrors();
// if the component is abstract, we do not validate everything
if (!component.isAbstract()) {
// if configuration pid is set and different from name, we need 1.2
if ( component.getConfigurationPid() != null && !component.getConfigurationPid().equals(component.getName())
&& options.getSpecVersion().ordinal() < SpecVersion.VERSION_1_2.ordinal() ) {
this.logError(component, "Different configuration pid requires "
+ SpecVersion.VERSION_1_2.getName() + " or higher.");
}
// ensure non-abstract, public class
if (!Modifier.isPublic(this.container.getClassDescription().getDescribedClass().getModifiers())) {
this.logError(component, "Class must be public: "
+ this.container.getClassDescription().getDescribedClass().getName());
}
if (Modifier.isAbstract(this.container.getClassDescription().getDescribedClass().getModifiers())
|| this.container.getClassDescription().getDescribedClass().isInterface()) {
this.logError(component, "Class must be concrete class (not abstract or interface) : "
+ this.container.getClassDescription().getDescribedClass().getName());
}
// no errors so far, let's continue
if (iLog.getNumberOfErrors() == currentIssueCount) {
final String activateName = component.getActivate() == null ? "activate" : component.getActivate();
final String deactivateName = component.getDeactivate() == null ? "deactivate" : component.getDeactivate();
// check activate and deactivate methods
this.checkLifecycleMethod(activateName, true, component.getActivate() != null);
this.checkLifecycleMethod(deactivateName, false, component.getDeactivate() != null);
if (component.getModified() != null) {
if ( this.options.getSpecVersion().ordinal() >= SpecVersion.VERSION_1_1.ordinal() ) {
this.checkLifecycleMethod(component.getModified(), true, true);
} else {
this.logError(component, "If modified version is specified, spec version must be " +
SpecVersion.VERSION_1_1.name() + " or higher : " + component.getModified());
}
}
// ensure public default constructor
boolean constructorFound = true;
Constructor<?>[] constructors = this.container.getClassDescription().getDescribedClass().getDeclaredConstructors();
for (int i = 0; constructors != null && i < constructors.length; i++) {
// if public default, succeed
if (Modifier.isPublic(constructors[i].getModifiers())
&& (constructors[i].getParameterTypes() == null || constructors[i].getParameterTypes().length == 0)) {
constructorFound = true;
break;
}
// non-public/non-default constructor found, must have
// explicit
constructorFound = false;
}
if (!constructorFound) {
this.logError(component, "Class must have public default constructor: " + this.container.getClassDescription().getDescribedClass().getName());
}
// verify properties
for (final PropertyDescription prop : this.container.getProperties().values()) {
this.validateProperty(prop);
}
// verify service
boolean isServiceFactory = false;
if (this.container.getServiceDescription() != null) {
if (this.container.getServiceDescription().getInterfaces().size() == 0) {
this.logError(component, "Service interface information is missing!");
}
this.validateService(this.container.getServiceDescription());
isServiceFactory = this.container.getServiceDescription().isServiceFactory();
}
// serviceFactory must not be true for immediate of component factory
if (isServiceFactory && component.getImmediate() != null && component.getImmediate().booleanValue()
&& component.getFactory() != null) {
this.logError(component,
"Component must not be a ServiceFactory, if immediate and/or component factory: "
+ this.container.getClassDescription().getDescribedClass().getName());
}
// immediate must not be true for component factory
if (component.getImmediate() != null && component.getImmediate().booleanValue() && component.getFactory() != null) {
this.logError(component,
"Component must not be immediate if component factory: " + this.container.getClassDescription().getDescribedClass().getName());
}
}
// additional check for metatype (FELIX-4035)
if ( this.container.getMetatypeContainer() != null ) {
if ( this.container.getMetatypeContainer().getProperties().size() == 0 ) {
this.logWarn(component, "Component is defined to generate metatype information, however no properties have been " +
"defined; in case no properties are wanted, consider to use 'metatype=false'");
}
}
if (iLog.getNumberOfErrors() == currentIssueCount) {
// verify references
for (final ReferenceDescription ref : this.container.getReferences().values()) {
this.validateReference(ref, component.isAbstract());
}
}
}
}