Search in sources :

Example 1 with DeclarativeServicesAnnotationError

use of aQute.bnd.component.error.DeclarativeServicesAnnotationError in project bnd by bndtools.

the class AnnotationReader method doDeactivate.

/**
	 * 
	 */
protected void doDeactivate() {
    String methodDescriptor = member.getDescriptor().toString();
    DeclarativeServicesAnnotationError details = new DeclarativeServicesAnnotationError(className.getFQN(), member.getName(), methodDescriptor, ErrorType.DEACTIVATE_SIGNATURE_ERROR);
    if (!(member instanceof MethodDef)) {
        analyzer.error("Deactivate annotation on a field %s.%s", clazz, member.getDescriptor()).details(details);
        return;
    }
    boolean hasMapReturnType = false;
    Matcher m = LIFECYCLEDESCRIPTORDS10.matcher(methodDescriptor);
    if ("deactivate".equals(member.getName()) && m.matches()) {
        component.deactivate = member.getName();
        hasMapReturnType = m.group(3) != null;
        if (!member.isProtected())
            component.updateVersion(V1_1);
    } else {
        m = DEACTIVATEDESCRIPTORDS11.matcher(methodDescriptor);
        if (m.matches()) {
            component.deactivate = member.getName();
            component.updateVersion(V1_1);
            hasMapReturnType = m.group(8) != null;
        } else {
            m = DEACTIVATEDESCRIPTORDS13.matcher(methodDescriptor);
            if (m.matches()) {
                component.deactivate = member.getName();
                component.updateVersion(V1_3);
                hasMapReturnType = m.group(6) != null;
                processAnnotationArguments(methodDescriptor, details);
            } else
                analyzer.error("Deactivate method for %s descriptor %s is not acceptable.", clazz, member.getDescriptor()).details(details);
        }
    }
    checkMapReturnType(hasMapReturnType, details);
}
Also used : MethodDef(aQute.bnd.osgi.Clazz.MethodDef) Matcher(java.util.regex.Matcher) DeclarativeServicesAnnotationError(aQute.bnd.component.error.DeclarativeServicesAnnotationError)

Example 2 with DeclarativeServicesAnnotationError

use of aQute.bnd.component.error.DeclarativeServicesAnnotationError in project bnd by bndtools.

the class AnnotationReader method determineReferenceType.

private String determineReferenceType(String methodDescriptor, ReferenceDef def, String annoService, String signature) {
    String inferredService = null;
    String plainType = null;
    boolean hasMapReturnType;
    Version minVersion = null;
    DeclarativeServicesAnnotationError details = getDetails(def, ErrorType.REFERENCE);
    // We have to find the type of the current method to
    // link it to the referenced service.
    Matcher m = BINDDESCRIPTORDS10.matcher(methodDescriptor);
    if (m.matches()) {
        inferredService = Descriptors.binaryToFQN(m.group(1));
        // ServiceReference (group 3) is always OK, match is always OK
        if (m.group(3) == null && noMatch(annoService, inferredService)) {
            if (m.group(7) == null) {
                // single arg of recognized Map, Map.Entry or ServiceObjects
                // so we must be V3.
                minVersion = V1_3;
            }
        }
        if (m.group(3) != null) {
            plainType = "Lorg/osgi/framework/ServiceReference<";
            inferredService = null;
        } else if (m.group(4) != null) {
            plainType = "Lorg/osgi/service/component/ComponentServiceObjects<";
            inferredService = null;
        } else if (m.group(5) != null) {
            plainType = "Ljava/util/Map$Entry<Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;";
            inferredService = null;
        } else if (m.group(6) != null) {
            // we cannot infer the service from just a map.
            inferredService = null;
        }
        hasMapReturnType = m.group(9) != null;
    } else {
        m = BINDDESCRIPTORDS11.matcher(methodDescriptor);
        if (m.matches()) {
            inferredService = Descriptors.binaryToFQN(m.group(1));
            minVersion = V1_1;
            hasMapReturnType = m.group(4) != null;
        } else {
            m = BINDDESCRIPTORDS13.matcher(methodDescriptor);
            if (m.matches()) {
                inferredService = m.group(7);
                if (inferredService != null)
                    inferredService = Descriptors.binaryToFQN(inferredService);
                minVersion = V1_3;
                if (ReferenceScope.PROTOTYPE != def.scope && m.group(3) != null) {
                    analyzer.error("In component %s, to use ComponentServiceObjects the scope must be 'prototype'", component.implementation, "").details(details);
                }
                if (annoService == null)
                    if (m.group(2) != null)
                        plainType = "Lorg/osgi/framework/ServiceReference<";
                    else if (m.group(3) != null)
                        plainType = "Lorg/osgi/service/component/ComponentServiceObjects<";
                    else if (m.group(5) != null)
                        plainType = "Ljava/util/Map$Entry<Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;";
                hasMapReturnType = m.group(9) != null;
            } else {
                return null;
            }
        }
    }
    String service = annoService;
    if (inferredService == null && signature != null && plainType != null) {
        int start = signature.indexOf(plainType);
        if (start > -1) {
            start += plainType.length();
            String[] sigs = signature.substring(start).split("[<;>]");
            if (sigs.length > 0) {
                String sig = sigs[0];
                if (sig.startsWith("-")) {
                    inferredService = Object.class.getName();
                } else {
                    int index = sig.startsWith("+") ? 2 : 1;
                    inferredService = sig.substring(index).replace('/', '.');
                }
            }
        }
    }
    // be a superclass of the specified service.
    if (!analyzer.assignable(annoService, inferredService)) {
        return null;
    }
    if (service == null)
        service = inferredService;
    checkMapReturnType(hasMapReturnType, details);
    if (minVersion != null)
        def.updateVersion(minVersion);
    return service;
}
Also used : Version(aQute.bnd.version.Version) Matcher(java.util.regex.Matcher) DeclarativeServicesAnnotationError(aQute.bnd.component.error.DeclarativeServicesAnnotationError)

Example 3 with DeclarativeServicesAnnotationError

use of aQute.bnd.component.error.DeclarativeServicesAnnotationError in project bnd by bndtools.

the class AnnotationReader method doReference.

/**
	 * @param reference @Reference proxy backed by raw.
	 * @param raw @Reference contents
	 * @throws Exception
	 */
protected void doReference(Reference reference, Annotation raw) throws Exception {
    ReferenceDef def;
    if (member == null)
        def = new ReferenceDef(finder);
    else if (referencesByMember.containsKey(member))
        def = referencesByMember.get(member);
    else {
        def = new ReferenceDef(finder);
        referencesByMember.put(member, def);
    }
    def.className = className.getFQN();
    def.name = reference.name();
    def.bind = reference.bind();
    def.unbind = reference.unbind();
    def.updated = reference.updated();
    def.field = reference.field();
    def.fieldOption = reference.fieldOption();
    def.cardinality = reference.cardinality();
    def.policy = reference.policy();
    def.policyOption = reference.policyOption();
    def.scope = reference.scope();
    // Check if we have a target, this must be a filter
    def.target = reference.target();
    DeclarativeServicesAnnotationError details = getDetails(def, ErrorType.REFERENCE);
    if (def.target != null) {
        String error = Verifier.validateFilter(def.target);
        if (error != null)
            analyzer.error("Invalid target filter %s for %s: %s", def.target, def.name, error).details(getDetails(def, ErrorType.INVALID_TARGET_FILTER));
    }
    String annoService = null;
    TypeRef annoServiceTR = raw.get("service");
    if (annoServiceTR != null)
        annoService = annoServiceTR.getFQN();
    if (member != null) {
        if (member instanceof MethodDef) {
            def.bindDescriptor = member.getDescriptor().toString();
            if (!member.isProtected())
                def.updateVersion(V1_1);
            def.bind = member.getName();
            if (def.name == null) {
                Matcher m = BINDNAME.matcher(member.getName());
                if (m.matches())
                    def.name = m.group(2);
                else
                    analyzer.error("Invalid name for bind method %s", member.getName()).details(getDetails(def, ErrorType.INVALID_REFERENCE_BIND_METHOD_NAME));
            }
            def.service = determineReferenceType(def.bindDescriptor, def, annoService, member.getSignature());
            if (def.service == null)
                analyzer.error("In component %s, method %s,  cannot recognize the signature of the descriptor: %s", component.effectiveName(), def.name, member.getDescriptor());
        } else if (member instanceof FieldDef) {
            def.updateVersion(V1_3);
            def.field = member.getName();
            if (def.name == null)
                def.name = def.field;
            if (def.policy == null && member.isVolatile())
                def.policy = ReferencePolicy.DYNAMIC;
            String sig = member.getSignature();
            if (sig == null)
                // no generics, the descriptor will be the class name.
                sig = member.getDescriptor().toString();
            String[] sigs = sig.split("[<;>]");
            int sigLength = sigs.length;
            int index = 0;
            boolean isCollection = false;
            if ("Ljava/util/Collection".equals(sigs[index]) || "Ljava/util/List".equals(sigs[index])) {
                index++;
                isCollection = true;
            }
            // Along with determining the FieldCollectionType, the following
            // code positions index to read the service type.
            FieldCollectionType fieldCollectionType = null;
            if (sufficientGenerics(index, sigLength, def, sig)) {
                if ("Lorg/osgi/framework/ServiceReference".equals(sigs[index])) {
                    if (sufficientGenerics(index++, sigLength, def, sig)) {
                        fieldCollectionType = FieldCollectionType.reference;
                    }
                } else if ("Lorg/osgi/service/component/ComponentServiceObjects".equals(sigs[index])) {
                    if (sufficientGenerics(index++, sigLength, def, sig)) {
                        fieldCollectionType = FieldCollectionType.serviceobjects;
                    }
                } else if ("Ljava/util/Map".equals(sigs[index])) {
                    if (sufficientGenerics(index++, sigLength, def, sig)) {
                        fieldCollectionType = FieldCollectionType.properties;
                    }
                } else if ("Ljava/util/Map$Entry".equals(sigs[index]) && sufficientGenerics(index++ + 5, sigLength, def, sig)) {
                    if ("Ljava/util/Map".equals(sigs[index++]) && "Ljava/lang/String".equals(sigs[index++])) {
                        if ("Ljava/lang/Object".equals(sigs[index]) || "+Ljava/lang/Object".equals(sigs[index])) {
                            fieldCollectionType = FieldCollectionType.tuple;
                            // ;>;
                            index += 3;
                        } else if ("*".equals(sigs[index])) {
                            fieldCollectionType = FieldCollectionType.tuple;
                            // >;
                            index += 2;
                        } else {
                            // no idea what service might
                            index = sigLength;
                        // be.
                        }
                    }
                } else {
                    fieldCollectionType = FieldCollectionType.service;
                }
            }
            if (isCollection) {
                if (def.cardinality == null)
                    def.cardinality = ReferenceCardinality.MULTIPLE;
                def.fieldCollectionType = fieldCollectionType;
            }
            if (def.policy == ReferencePolicy.DYNAMIC && (def.cardinality == ReferenceCardinality.MULTIPLE || def.cardinality == ReferenceCardinality.AT_LEAST_ONE) && member.isFinal()) {
                if (def.fieldOption == FieldOption.REPLACE)
                    analyzer.error("In component %s, collection type field: %s is final and dynamic but marked with 'replace' fieldOption. Changing this to 'update'.", className, def.field).details(getDetails(def, ErrorType.DYNAMIC_FINAL_FIELD_WITH_REPLACE));
                def.fieldOption = FieldOption.UPDATE;
            }
            if (annoService == null && index < sigs.length) {
                annoService = sigs[index].substring(1).replace('/', '.');
            }
            def.service = annoService;
            if (def.service == null)
                analyzer.error("In component %s, method %s,  cannot recognize the signature of the descriptor: %s", component.effectiveName(), def.name, member.getDescriptor()).details(details);
        }
    // end field
    } else {
        // not a member
        def.service = annoService;
        if (def.name == null) {
            analyzer.error("Name must be supplied for a @Reference specified in the @Component annotation. Service: %s", def.service).details(getDetails(def, ErrorType.MISSING_REFERENCE_NAME));
            return;
        }
    }
    if (component.references.containsKey(def.name))
        analyzer.error("In component %s, multiple references with the same name: %s. Previous def: %s, this def: %s", className, component.references.get(def.name), def.service, "").details(getDetails(def, ErrorType.MULTIPLE_REFERENCES_SAME_NAME));
    else
        component.references.put(def.name, def);
}
Also used : FieldDef(aQute.bnd.osgi.Clazz.FieldDef) MethodDef(aQute.bnd.osgi.Clazz.MethodDef) Matcher(java.util.regex.Matcher) DeclarativeServicesAnnotationError(aQute.bnd.component.error.DeclarativeServicesAnnotationError) TypeRef(aQute.bnd.osgi.Descriptors.TypeRef)

Example 4 with DeclarativeServicesAnnotationError

use of aQute.bnd.component.error.DeclarativeServicesAnnotationError in project bnd by bndtools.

the class AnnotationReader method getDef.

private ComponentDef getDef() throws Exception {
    clazz.parseClassFileWithCollector(this);
    if (component.implementation == null)
        return null;
    if (options.contains(Options.inherit)) {
        baseclass = false;
        while (extendsClass != null) {
            if (extendsClass.isJava())
                break;
            Clazz ec = analyzer.findClass(extendsClass);
            if (ec == null) {
                analyzer.error("Missing super class for DS annotations: %s from %s", extendsClass, clazz.getClassName()).details(new DeclarativeServicesAnnotationError(className.getFQN(), null, null, ErrorType.UNABLE_TO_LOCATE_SUPER_CLASS));
                break;
            } else {
                ec.parseClassFileWithCollector(this);
            }
        }
    }
    for (ReferenceDef rdef : component.references.values()) {
        if (rdef.bind != null) {
            rdef.unbind = referredMethod(analyzer, rdef, rdef.unbind, "add(.*)", "remove$1", "(.*)", "un$1");
            rdef.updated = referredMethod(analyzer, rdef, rdef.updated, "(add|set|bind)(.*)", "updated$2", "(.*)", "updated$1");
            if (rdef.policy == ReferencePolicy.DYNAMIC && rdef.unbind == null)
                analyzer.error("In component class %s, reference %s is dynamic but has no unbind method.", className.getFQN(), rdef.name).details(getDetails(rdef, ErrorType.DYNAMIC_REFERENCE_WITHOUT_UNBIND));
        }
    }
    return component;
}
Also used : DeclarativeServicesAnnotationError(aQute.bnd.component.error.DeclarativeServicesAnnotationError) Clazz(aQute.bnd.osgi.Clazz)

Example 5 with DeclarativeServicesAnnotationError

use of aQute.bnd.component.error.DeclarativeServicesAnnotationError in project bnd by bndtools.

the class AnnotationReader method handleMixedUsageError.

private void handleMixedUsageError(Annotation annotation) throws Exception {
    DeclarativeServicesAnnotationError errorDetails;
    String fqn = annotation.getName().getFQN();
    switch(annotation.getElementType()) {
        case METHOD:
            errorDetails = new DeclarativeServicesAnnotationError(className.getFQN(), member.getName(), member.getDescriptor().toString(), ErrorType.MIXED_USE_OF_DS_ANNOTATIONS_STD);
            break;
        case FIELD:
            errorDetails = new DeclarativeServicesAnnotationError(className.getFQN(), member.getName(), ErrorType.MIXED_USE_OF_DS_ANNOTATIONS_STD);
            break;
        default:
            errorDetails = new DeclarativeServicesAnnotationError(className.getFQN(), null, ErrorType.MIXED_USE_OF_DS_ANNOTATIONS_STD);
    }
    List<DeclarativeServicesAnnotationError> errors = mismatchedAnnotations.get(fqn);
    if (errors == null) {
        errors = new ArrayList<DeclarativeServicesAnnotationError>();
        mismatchedAnnotations.put(fqn, errors);
    }
    errors.add(errorDetails);
}
Also used : DeclarativeServicesAnnotationError(aQute.bnd.component.error.DeclarativeServicesAnnotationError)

Aggregations

DeclarativeServicesAnnotationError (aQute.bnd.component.error.DeclarativeServicesAnnotationError)11 Matcher (java.util.regex.Matcher)7 MethodDef (aQute.bnd.osgi.Clazz.MethodDef)4 TypeRef (aQute.bnd.osgi.Descriptors.TypeRef)4 ArrayList (java.util.ArrayList)4 Clazz (aQute.bnd.osgi.Clazz)2 HashMap (java.util.HashMap)2 List (java.util.List)2 Annotation (aQute.bnd.osgi.Annotation)1 FieldDef (aQute.bnd.osgi.Clazz.FieldDef)1 Version (aQute.bnd.version.Version)1 Map (java.util.Map)1 MarkerData (org.bndtools.build.api.MarkerData)1 IJavaProject (org.eclipse.jdt.core.IJavaProject)1 Reference (org.osgi.service.component.annotations.Reference)1