use of org.apache.felix.scrplugin.description.ReferenceDescription in project felix by apache.
the class DSAnnotationProcessor method processReference.
/**
* Process a reference
*/
private void processReference(final ClassDescription describedClass, final MethodAnnotation ad) {
final ReferenceDescription ref = new ReferenceDescription(ad);
describedClass.add(ref);
ref.setStrategy(ReferenceStrategy.EVENT);
final String methodName = ad.getAnnotatedMethod().getName();
final String defaultUnbindMethodName;
final String refNameByMethod;
if (methodName.startsWith("add")) {
refNameByMethod = methodName.substring(3);
defaultUnbindMethodName = "remove" + refNameByMethod;
} else if (methodName.startsWith("set")) {
refNameByMethod = methodName.substring(3);
defaultUnbindMethodName = "unset" + refNameByMethod;
} else if (methodName.startsWith("bind")) {
refNameByMethod = methodName.substring(4);
defaultUnbindMethodName = "unbind" + refNameByMethod;
} else {
refNameByMethod = methodName;
defaultUnbindMethodName = "un" + refNameByMethod;
}
final String defaultUpdateMethodName = "updated" + refNameByMethod;
// bind method
ref.setBind(ad.getAnnotatedMethod().getName());
// unbind method
final String unbind = ad.getStringValue("unbind", this.hasMethod(describedClass, defaultUnbindMethodName) ? defaultUnbindMethodName : "-");
if (!unbind.equals("-")) {
ref.setUnbind(unbind);
}
// update method
final String updated = ad.getStringValue("updated", this.hasMethod(describedClass, defaultUpdateMethodName) ? defaultUpdateMethodName : "-");
if (!updated.equals("-")) {
ref.setUpdated(updated);
}
// name
ref.setName(ad.getStringValue("name", refNameByMethod));
// service
final String serviceName = ad.getStringValue("service", null);
if (serviceName != null) {
ref.setInterfaceName(serviceName);
} else {
final Class<?>[] params = ad.getAnnotatedMethod().getParameterTypes();
if (params != null && params.length > 0) {
ref.setInterfaceName(params[0].getName());
}
}
// cardinality
final String cardinality = ad.getEnumValue("cardinality", "MANDATORY");
if (cardinality.equals("OPTIONAL")) {
ref.setCardinality(ReferenceCardinality.OPTIONAL_UNARY);
} else if (cardinality.equals("MULTIPLE")) {
ref.setCardinality(ReferenceCardinality.OPTIONAL_MULTIPLE);
} else if (cardinality.equals("AT_LEAST_ONE")) {
ref.setCardinality(ReferenceCardinality.MANDATORY_MULTIPLE);
} else {
ref.setCardinality(ReferenceCardinality.MANDATORY_UNARY);
}
// policy
ref.setPolicy(ReferencePolicy.valueOf(ad.getEnumValue("policy", ReferencePolicy.STATIC.name())));
// policy option
ref.setPolicyOption(ReferencePolicyOption.valueOf(ad.getEnumValue("policyOption", ReferencePolicyOption.RELUCTANT.name())));
// target
ref.setTarget(ad.getStringValue("target", null));
}
use of org.apache.felix.scrplugin.description.ReferenceDescription in project felix by apache.
the class SCRDescriptorGenerator method generateMethods.
private void generateMethods(final ComponentContainer container) throws SCRDescriptorException {
for (final ReferenceDescription ref : container.getReferences().values()) {
// skip refs without a interface name (validate will be called next)
if (StringUtils.isEmpty(ref.getInterfaceName())) {
continue;
}
// and create them if they are not availabe
if (ref.getStrategy() != ReferenceStrategy.LOOKUP && ref.getField() != null && ref.getField().getDeclaringClass().getName().equals(container.getClassDescription().getDescribedClass().getName()) && (ref.getCardinality() == ReferenceCardinality.OPTIONAL_UNARY || ref.getCardinality() == ReferenceCardinality.MANDATORY_UNARY)) {
final String bindValue = ref.getBind();
final String unbindValue = ref.getUnbind();
final String name = ref.getName();
final String type = ref.getInterfaceName();
boolean createBind = false;
boolean createUnbind = false;
// Only create method if no bind name has been specified
if (bindValue == null && Validator.findMethod(this.project, this.options, container.getClassDescription(), ref, "bind") == null) {
// create bind method
createBind = true;
}
if (unbindValue == null && Validator.findMethod(this.project, this.options, container.getClassDescription(), ref, "unbind") == null) {
// create unbind method
createUnbind = true;
}
if (createBind || createUnbind) {
// logging
if (createBind && createUnbind) {
this.logger.debug("Generating bind and unbind method for " + name + " in " + container.getClassDescription().getDescribedClass().getName());
} else if (createBind) {
this.logger.debug("Generating bind method for " + name + " in " + container.getClassDescription().getDescribedClass().getName());
} else {
this.logger.debug("Generating unbind method for " + name + " in " + container.getClassDescription().getDescribedClass().getName());
}
ClassModifier.addMethods(container.getClassDescription().getDescribedClass().getName(), name, type, ref.getField().getName(), ref.getField().getType().getName(), createBind, createUnbind, this.project.getClassLoader(), this.project.getClassesDirectory(), this.logger);
// set a flag for validation
ref.setBindMethodCreated(createBind);
ref.setUnbindMethodCreated(createUnbind);
}
}
}
}
use of org.apache.felix.scrplugin.description.ReferenceDescription in project felix by apache.
the class SCRDescriptorGenerator method processReferences.
/**
* Process reference directives
* @throws SCRDescriptorException
*/
private void processReferences(final ClassDescription current, final ComponentContainer component) {
for (final ReferenceDescription rd : current.getDescriptions(ReferenceDescription.class)) {
if (rd.getPolicyOption() != ReferencePolicyOption.RELUCTANT) {
component.getComponentDescription().setSpecVersion(SpecVersion.VERSION_1_2);
}
if (rd.getUpdated() != null) {
// updated requires 1.2 or 1.1_FELIX, if nothing is set, we use 1.2
if (component.getComponentDescription().getSpecVersion() == null || component.getComponentDescription().getSpecVersion().ordinal() < SpecVersion.VERSION_1_1_FELIX.ordinal()) {
component.getComponentDescription().setSpecVersion(SpecVersion.VERSION_1_2);
}
}
this.testReference(current, component.getReferences(), rd, component.getClassDescription() == current);
// check for method signature - if interface name is set (empty interface name will fail during validate)
if (!StringUtils.isEmpty(rd.getInterfaceName())) {
try {
final Validator.MethodResult bindMethod = Validator.findMethod(this.project, this.options, current, rd, rd.getBind() == null ? "bind" : rd.getBind());
if (bindMethod != null) {
component.getComponentDescription().setSpecVersion(bindMethod.requiredSpecVersion);
}
final Validator.MethodResult unbindMethod = Validator.findMethod(this.project, this.options, current, rd, rd.getUnbind() == null ? "unbind" : rd.getUnbind());
if (unbindMethod != null) {
component.getComponentDescription().setSpecVersion(unbindMethod.requiredSpecVersion);
}
} catch (final SCRDescriptorException sde) {
// this happens only if a class not found exception occurs, so we can ignore this at this point!
}
}
}
}
use of org.apache.felix.scrplugin.description.ReferenceDescription in project felix by apache.
the class Validator method validate.
/**
* 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.logError(component, "Component is defined to generate metatype information, however no properties or only private properties have been " + "defined; in case no properties or only private 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());
}
}
}
}
use of org.apache.felix.scrplugin.description.ReferenceDescription in project felix by apache.
the class SCRAnnotationProcessor method createReferences.
/**
* Create reference descriptions
*
* @param descs
* List of reference annotations.s
* @param describedClass
* The described class.
*/
private void createReferences(final List<? extends ScannedAnnotation> descs, final ClassDescription describedClass) {
for (final ScannedAnnotation ad : descs) {
final ReferenceDescription ref = new ReferenceDescription(ad);
// check for field annotation
final FieldAnnotation fieldAnnotation;
if (ad instanceof FieldAnnotation) {
fieldAnnotation = (FieldAnnotation) ad;
ref.setField(fieldAnnotation.getAnnotatedField());
} else {
fieldAnnotation = null;
}
ref.setName(ad.getStringValue("name", (fieldAnnotation != null ? fieldAnnotation.getAnnotatedField().getName() : null)));
String defaultInterfaceName = null;
if (fieldAnnotation != null) {
if (fieldAnnotation.getAnnotatedField().getType().isArray()) {
defaultInterfaceName = fieldAnnotation.getAnnotatedField().getType().getComponentType().getName();
} else {
defaultInterfaceName = fieldAnnotation.getAnnotatedField().getType().getName();
}
}
ref.setInterfaceName(ad.getStringValue("referenceInterface", defaultInterfaceName));
ref.setTarget(ad.getStringValue("target", null));
ref.setCardinality(ReferenceCardinality.valueOf(ad.getEnumValue("cardinality", ReferenceCardinality.MANDATORY_UNARY.name())));
ref.setPolicy(ReferencePolicy.valueOf(ad.getEnumValue("policy", ReferencePolicy.STATIC.name())));
ref.setPolicyOption(ReferencePolicyOption.valueOf(ad.getEnumValue("policyOption", ReferencePolicyOption.RELUCTANT.name())));
ref.setStrategy(ReferenceStrategy.valueOf(ad.getEnumValue("strategy", ReferenceStrategy.EVENT.name())));
ref.setBind(ad.getStringValue("bind", null));
ref.setUnbind(ad.getStringValue("unbind", null));
ref.setUpdated(ad.getStringValue("updated", null));
describedClass.add(ref);
}
}
Aggregations