use of org.apache.felix.scrplugin.annotations.ScannedAnnotation in project felix by apache.
the class ClassScanner method extractAnnotation.
/**
* Extract annotations
*/
private final List<ScannedAnnotation> extractAnnotation(final ClassNode classNode, final Class<?> annotatedClass) throws SCRDescriptorException {
final List<ScannedAnnotation> descriptions = new ArrayList<ScannedAnnotation>();
// first parse class annotations
@SuppressWarnings("unchecked") final List<AnnotationNode> annotations = getAllAnnotations(classNode.invisibleAnnotations, classNode.visibleAnnotations);
if (annotations != null) {
for (final AnnotationNode annotation : annotations) {
this.parseAnnotation(descriptions, annotation, annotatedClass);
}
// second parse method annotations
@SuppressWarnings("unchecked") final List<MethodNode> methods = classNode.methods;
if (methods != null) {
for (final MethodNode method : methods) {
final String name = method.name;
// check for constructor
if (!"<init>".equals(name)) {
@SuppressWarnings("unchecked") final List<AnnotationNode> annos = getAllAnnotations(method.invisibleAnnotations, method.visibleAnnotations);
if (annos != null) {
final Type[] signature = Type.getArgumentTypes(method.desc);
final Method[] allMethods = annotatedClass.getDeclaredMethods();
Method found = null;
for (final Method m : allMethods) {
if (m.getName().equals(name)) {
if (m.getParameterTypes().length == 0 && (signature == null || signature.length == 0)) {
found = m;
}
if (m.getParameterTypes().length > 0 && signature != null && m.getParameterTypes().length == signature.length) {
found = m;
for (int index = 0; index < m.getParameterTypes().length; index++) {
String parameterTypeName = m.getParameterTypes()[index].getName();
// Name of array parameters is returned with syntax [L<name>;, convert to <name>[]
Matcher matcher = ARRAY_PARAM_TYPE_NAME.matcher(parameterTypeName);
if (matcher.matches()) {
parameterTypeName = matcher.group(1) + "[]";
}
if (!parameterTypeName.equals(signature[index].getClassName()) && !m.getParameterTypes()[index].getSimpleName().equals(signature[index].getClassName())) {
found = null;
}
}
}
// if method is found return it now, to avoid resetting 'found' to null if next method has same name but different parameters
if (found != null) {
break;
}
}
}
if (found == null) {
throw new SCRDescriptorException("Annotated method " + name + " not found.", annotatedClass.getName());
}
for (final AnnotationNode annotation : annos) {
parseAnnotation(descriptions, annotation, found);
}
}
}
}
}
// third parse field annotations
@SuppressWarnings("unchecked") final List<FieldNode> fields = classNode.fields;
if (fields != null) {
for (final FieldNode field : fields) {
@SuppressWarnings("unchecked") final List<AnnotationNode> annos = getAllAnnotations(field.invisibleAnnotations, field.visibleAnnotations);
if (annos != null) {
final String name = field.name;
final Field[] allFields = annotatedClass.getDeclaredFields();
Field found = null;
for (final Field f : allFields) {
if (f.getName().equals(name)) {
found = f;
break;
}
}
if (found == null) {
throw new SCRDescriptorException("Annotated field " + name + " not found.", annotatedClass.getName());
}
for (final AnnotationNode annotation : annos) {
parseAnnotation(descriptions, annotation, found);
}
}
}
}
}
return descriptions;
}
use of org.apache.felix.scrplugin.annotations.ScannedAnnotation in project felix by apache.
the class SCRAnnotationProcessor method createProperties.
/**
* Create properties descriptions
*
* @throws SCRDescriptorException
* @throws SCRDescriptorFailureException
*/
private void createProperties(final List<? extends ScannedAnnotation> descs, final ClassDescription describedClass) throws SCRDescriptorFailureException, SCRDescriptorException {
for (final ScannedAnnotation ad : descs) {
final PropertyDescription prop = new PropertyDescription(ad);
// check for field annotation
final FieldAnnotation fieldAnnotation;
if (ad instanceof FieldAnnotation) {
fieldAnnotation = (FieldAnnotation) ad;
} else {
fieldAnnotation = null;
}
// Detect values from annotation
String type = null;
String[] values = null;
int index = 0;
while (type == null && index < PROPERTY_VALUE_PROCESSING.length) {
final String propType = PROPERTY_VALUE_PROCESSING[index];
final String propName = PROPERTY_VALUE_PROCESSING[index + 1];
final Object propValue = ad.getValue(propName);
if (propValue != null && propValue.getClass().isArray()) {
type = propType;
values = new String[Array.getLength(propValue)];
for (int i = 0; i < values.length; i++) {
values[i] = Array.get(propValue, i).toString();
}
}
index += 2;
}
String name = ad.getStringValue("name", null);
if (values != null) {
prop.setType(PropertyType.valueOf(type));
if (values.length == 1) {
prop.setValue(values[0]);
} else {
prop.setMultiValue(values);
}
if (name == null) {
final Object value = fieldAnnotation.getAnnotatedFieldValue();
if (value != null) {
name = value.toString();
}
}
} else if (fieldAnnotation != null) {
// Detect values from field
if (name != null) {
final Object value = fieldAnnotation.getAnnotatedFieldValue();
if (value != null) {
if (value.getClass().isArray()) {
final String[] newValues = new String[Array.getLength(value)];
for (int i = 0; i < newValues.length; i++) {
newValues[i] = Array.get(value, i).toString();
}
prop.setMultiValue(newValues);
prop.setType(PropertyType.from(fieldAnnotation.getAnnotatedField().getType().getComponentType()));
} else {
prop.setType(PropertyType.from(value.getClass()));
prop.setValue(value.toString());
}
}
} else {
if (Modifier.isStatic(fieldAnnotation.getAnnotatedField().getModifiers())) {
final Object value = fieldAnnotation.getAnnotatedFieldValue();
if (value != null) {
name = value.toString();
}
} else {
// non static, no name, no value (FELIX-4393)
name = fieldAnnotation.getAnnotatedField().getName();
final Object value = fieldAnnotation.getAnnotatedFieldValue();
if (value != null) {
if (value.getClass().isArray()) {
final String[] newValues = new String[Array.getLength(value)];
for (int i = 0; i < newValues.length; i++) {
newValues[i] = Array.get(value, i).toString();
}
prop.setMultiValue(newValues);
prop.setType(PropertyType.from(fieldAnnotation.getAnnotatedField().getType().getComponentType()));
} else {
prop.setType(PropertyType.from(value.getClass()));
prop.setValue(value.toString());
}
}
}
}
}
prop.setName(name);
prop.setLabel(ad.getStringValue("label", null));
prop.setDescription(ad.getStringValue("description", null));
// check type
if (prop.getType() == null) {
prop.setType(PropertyType.String);
}
// private
if (ad.getValue("propertyPrivate") != null) {
prop.setPrivate(ad.getBooleanValue("propertyPrivate", false));
}
// cardinality handling
final PropertyUnbounded pu = PropertyUnbounded.valueOf(ad.getEnumValue("unbounded", PropertyUnbounded.DEFAULT.name()));
prop.setUnbounded(pu);
if (pu == PropertyUnbounded.DEFAULT) {
prop.setCardinality(ad.getIntegerValue("cardinality", 0));
if (prop.getMultiValue() != null && prop.getCardinality() == 0) {
prop.setUnbounded(PropertyUnbounded.ARRAY);
}
} else {
prop.setCardinality(0);
}
if (prop.getValue() != null) {
if (prop.getUnbounded() == PropertyUnbounded.ARRAY || prop.getUnbounded() == PropertyUnbounded.VECTOR) {
prop.setMultiValue(new String[] { prop.getValue() });
} else if (prop.getCardinality() < -1 || prop.getCardinality() > 1) {
prop.setMultiValue(new String[] { prop.getValue() });
}
}
// options
final ScannedAnnotation[] options = (ScannedAnnotation[]) ad.getValue("options");
if (options != null) {
final List<String> propertyOptions = new ArrayList<String>();
for (final ScannedAnnotation po : options) {
propertyOptions.add(po.getStringValue("name", ""));
propertyOptions.add(po.getStringValue("value", ""));
}
prop.setOptions(propertyOptions.toArray(new String[propertyOptions.size()]));
}
describedClass.add(prop);
}
}
use of org.apache.felix.scrplugin.annotations.ScannedAnnotation 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);
}
}
use of org.apache.felix.scrplugin.annotations.ScannedAnnotation in project felix by apache.
the class ClassScanner method processClass.
/**
* Scan a single class.
*/
private ClassDescription processClass(final Class<?> annotatedClass, final String location) throws SCRDescriptorFailureException, SCRDescriptorException {
log.debug("Processing " + annotatedClass.getName());
try {
// get the class file for ASM
final String pathToClassFile = annotatedClass.getName().replace('.', '/') + ".class";
final InputStream input = project.getClassLoader().getResourceAsStream(pathToClassFile);
final ClassReader classReader;
try {
classReader = new ClassReader(input);
} finally {
if (input != null) {
input.close();
}
}
final ClassNode classNode = new ClassNode();
classReader.accept(classNode, SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES);
// create descriptions
final List<ScannedAnnotation> annotations = extractAnnotation(classNode, annotatedClass);
if (annotations.size() > 0) {
// process annotations and create descriptions
final ClassDescription desc = new ClassDescription(annotatedClass, location);
aProcessor.process(new ScannedClass(annotations, annotatedClass), desc);
log.debug("Found descriptions " + desc + " in " + annotatedClass.getName());
return desc;
}
} catch (final IllegalArgumentException ioe) {
throw new SCRDescriptorException("Unable to scan class files: " + annotatedClass.getName() + " (Class file format probably not supported by ASM ?)", location, ioe);
} catch (final IOException ioe) {
throw new SCRDescriptorException("Unable to scan class files: " + annotatedClass.getName(), location, ioe);
}
return null;
}
use of org.apache.felix.scrplugin.annotations.ScannedAnnotation in project felix by apache.
the class ClassScanner method parseAnnotation.
/**
* Parse annotation and create a description.
*/
private void parseAnnotation(final List<ScannedAnnotation> descriptions, final AnnotationNode annotation, final Object annotatedObject) {
// desc has the format 'L' + className.replace('.', '/') + ';'
final String name = annotation.desc.substring(1, annotation.desc.length() - 1).replace('/', '.');
Map<String, Object> values = null;
if (annotation.values != null) {
values = new HashMap<String, Object>();
final Iterator<?> i = annotation.values.iterator();
while (i.hasNext()) {
final Object vName = i.next();
Object value = i.next();
// convert type to class name string
if (value instanceof Type) {
value = ((Type) value).getClassName();
} else if (value instanceof List<?>) {
final List<?> objects = (List<?>) value;
if (objects.size() > 0) {
if (objects.get(0) instanceof Type) {
final String[] classNames = new String[objects.size()];
int index = 0;
for (final Object v : objects) {
classNames[index] = ((Type) v).getClassName();
index++;
}
value = classNames;
} else if (objects.get(0) instanceof AnnotationNode) {
final List<ScannedAnnotation> innerDesc = new ArrayList<ScannedAnnotation>();
for (final Object v : objects) {
parseAnnotation(innerDesc, (AnnotationNode) v, annotatedObject);
}
if (annotatedObject instanceof Method) {
value = innerDesc.toArray(new MethodAnnotation[innerDesc.size()]);
} else if (annotatedObject instanceof Field) {
value = innerDesc.toArray(new FieldAnnotation[innerDesc.size()]);
} else {
value = innerDesc.toArray(new ClassAnnotation[innerDesc.size()]);
}
} else {
value = convertToArray(objects, objects.get(0).getClass());
}
} else {
value = null;
}
}
values.put(vName.toString(), value);
}
}
final ScannedAnnotation a;
if (annotatedObject instanceof Method) {
a = new MethodAnnotation(name, values, (Method) annotatedObject);
((Method) annotatedObject).setAccessible(true);
} else if (annotatedObject instanceof Field) {
a = new FieldAnnotation(name, values, (Field) annotatedObject);
((Field) annotatedObject).setAccessible(true);
} else {
a = new ClassAnnotation(name, values);
}
descriptions.add(a);
}
Aggregations