001: package org.objectweb.celtix.common.annotation;
002:
003: import java.lang.annotation.Annotation;
004: import java.lang.reflect.AnnotatedElement;
005: import java.lang.reflect.Field;
006: import java.lang.reflect.InvocationTargetException;
007: import java.lang.reflect.Method;
008: import java.util.List;
009: import java.util.logging.Level;
010: import java.util.logging.Logger;
011:
012: import org.objectweb.celtix.common.i18n.Message;
013: import org.objectweb.celtix.common.logging.LogUtils;
014:
015: /** Process instance of an annotated class. This is a visitable
016: * object that allows an caller to visit that annotated elements in
017: * this class definition. If a class level annotation is overridden
018: * by a member level annotation, only the visit method for the member
019: * level annotation
020: */
021: public class AnnotationProcessor {
022:
023: private static final Logger LOG = LogUtils
024: .getL7dLogger(AnnotationProcessor.class);
025:
026: private static Method visitClassMethod;
027: private static Method visitFieldMethod;
028: private static Method visitMethodMethod;
029:
030: static {
031: try {
032: visitClassMethod = AnnotationVisitor.class.getMethod(
033: "visitClass", Class.class, Annotation.class);
034: visitFieldMethod = AnnotationVisitor.class.getMethod(
035: "visitField", Field.class, Annotation.class);
036: visitMethodMethod = AnnotationVisitor.class.getMethod(
037: "visitMethod", Method.class, Annotation.class);
038:
039: } catch (NoSuchMethodException e) {
040: // ignore
041: }
042:
043: }
044:
045: private final Object target;
046: private List<Class<? extends Annotation>> annotationTypes;
047:
048: public AnnotationProcessor(Object o) {
049: if (o == null) {
050: throw new IllegalArgumentException(new Message(
051: "INVALID_CTOR_ARGS", LOG).toString());
052: }
053: target = o;
054: }
055:
056: /**
057: * Visits each of the annotated elements of the object.
058: *
059: * @param visitor a visitor
060: *
061: */
062: public void accept(AnnotationVisitor visitor) {
063:
064: if (visitor == null) {
065: throw new IllegalArgumentException();
066: }
067:
068: annotationTypes = visitor.getTargetAnnotations();
069: visitor.setTarget(target);
070: processClass(visitor);
071: processFields(visitor);
072: processMethods(visitor);
073: }
074:
075: private void processMethods(AnnotationVisitor visitor) {
076:
077: visitAnnotatedElement(target.getClass().getDeclaredMethods(),
078: visitor, visitMethodMethod);
079: }
080:
081: private void processFields(AnnotationVisitor visitor) {
082:
083: visitAnnotatedElement(target.getClass().getDeclaredFields(),
084: visitor, visitFieldMethod);
085: }
086:
087: private void processClass(AnnotationVisitor visitor) {
088: Class<?>[] classes = { target.getClass() };
089: visitAnnotatedElement(classes, visitor, visitClassMethod);
090: }
091:
092: private <U extends AnnotatedElement> void visitAnnotatedElement(
093: U[] elements, AnnotationVisitor visitor,
094: Method visitorMethod) {
095:
096: for (U element : elements) {
097: for (Class<? extends Annotation> clz : annotationTypes) {
098: Annotation ann = element.getAnnotation(clz);
099: if (ann != null) {
100: try {
101: visitorMethod.invoke(visitor, element, ann);
102: } catch (IllegalAccessException e) {
103: // ignore, we're invoking methods of a public interface
104: } catch (InvocationTargetException e) {
105: Throwable cause = e.getCause() == null ? e : e
106: .getCause();
107: LogUtils.log(LOG, Level.SEVERE,
108: "VISITOR_RAISED_EXCEPTION", cause,
109: visitor);
110: }
111: }
112: }
113: }
114: }
115: }
|