Search in sources :

Example 1 with ReferenceDescription

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));
}
Also used : ReferenceDescription(org.apache.felix.scrplugin.description.ReferenceDescription) ScannedClass(org.apache.felix.scrplugin.annotations.ScannedClass)

Example 2 with ReferenceDescription

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);
            }
        }
    }
}
Also used : ReferenceDescription(org.apache.felix.scrplugin.description.ReferenceDescription)

Example 3 with ReferenceDescription

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!
            }
        }
    }
}
Also used : ReferenceDescription(org.apache.felix.scrplugin.description.ReferenceDescription) Validator(org.apache.felix.scrplugin.helper.Validator)

Example 4 with ReferenceDescription

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());
            }
        }
    }
}
Also used : PropertyDescription(org.apache.felix.scrplugin.description.PropertyDescription) ComponentDescription(org.apache.felix.scrplugin.description.ComponentDescription) Constructor(java.lang.reflect.Constructor) ReferenceDescription(org.apache.felix.scrplugin.description.ReferenceDescription)

Example 5 with ReferenceDescription

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);
    }
}
Also used : ReferenceDescription(org.apache.felix.scrplugin.description.ReferenceDescription) FieldAnnotation(org.apache.felix.scrplugin.annotations.FieldAnnotation) ScannedAnnotation(org.apache.felix.scrplugin.annotations.ScannedAnnotation)

Aggregations

ReferenceDescription (org.apache.felix.scrplugin.description.ReferenceDescription)6 ComponentDescription (org.apache.felix.scrplugin.description.ComponentDescription)2 PropertyDescription (org.apache.felix.scrplugin.description.PropertyDescription)2 Constructor (java.lang.reflect.Constructor)1 FieldAnnotation (org.apache.felix.scrplugin.annotations.FieldAnnotation)1 ScannedAnnotation (org.apache.felix.scrplugin.annotations.ScannedAnnotation)1 ScannedClass (org.apache.felix.scrplugin.annotations.ScannedClass)1 Validator (org.apache.felix.scrplugin.helper.Validator)1 AttributesImpl (org.xml.sax.helpers.AttributesImpl)1