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);
}
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;
}
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);
}
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;
}
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);
}
Aggregations