Search in sources :

Example 1 with FieldDef

use of aQute.bnd.osgi.Clazz.FieldDef 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)

Aggregations

DeclarativeServicesAnnotationError (aQute.bnd.component.error.DeclarativeServicesAnnotationError)1 FieldDef (aQute.bnd.osgi.Clazz.FieldDef)1 MethodDef (aQute.bnd.osgi.Clazz.MethodDef)1 TypeRef (aQute.bnd.osgi.Descriptors.TypeRef)1 Matcher (java.util.regex.Matcher)1