1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.callbackparams.support.annotation;
18
19 import java.lang.annotation.Annotation;
20 import java.lang.annotation.Retention;
21 import java.lang.annotation.RetentionPolicy;
22 import java.lang.reflect.AnnotatedElement;
23 import java.lang.reflect.Field;
24 import java.lang.reflect.Modifier;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.List;
28 import org.callbackparams.support.ExceptionUtil;
29
30
31
32
33 public class AnnotationInjector
34 extends org.callbackparams.support.AnnotationInjector {
35
36 @Override
37 protected void injectAnnotationsInternal(Object target, Object enumConstant)
38 {
39 Field enumField = findEnumField(enumConstant);
40 if (null == enumField) {
41 return;
42 }
43 Class<?> enumClass = enumField.getDeclaringClass();
44 Package enumPackage = enumClass.getPackage();
45 AnnotatedElement[] annotatedElements = null == enumPackage
46 ? new AnnotatedElement[]{enumField, enumClass}
47 : new AnnotatedElement[]{enumField, enumClass, enumPackage};
48
49 Collection<Field> injectableFields =
50 findInjectableField(target.getClass());
51 checkForClassRetention(injectableFields);
52 for (Field f : injectableFields) {
53 Annotation a = findAnnotation(f.getType(), annotatedElements);
54
55 if (null != a) {
56 try {
57 f.setAccessible(true);
58 } catch (SecurityException ignoreAndContinueAnyway___) {}
59 try {
60 f.set(target, a);
61 } catch (Exception ex) {
62 throw ExceptionUtil.unchecked(ex);
63 }
64 }
65 }
66 }
67
68 private static Annotation findAnnotation(
69 Class<?> annotationClass, AnnotatedElement[] elements) {
70 Class<? extends Annotation> c =
71 annotationClass.asSubclass(Annotation.class);
72 for (AnnotatedElement ae : elements) {
73 Annotation a = ae.getAnnotation(c);
74 if (null != a) {
75 return a;
76 }
77 }
78 return null;
79 }
80
81 private static Field findEnumField(Object enumConstant) {
82 Class<? extends Enum> c = findEnumSuperClass(enumConstant.getClass());
83 if (null == c) {
84 return null;
85 } else {
86 try {
87 return c.getField(((Enum) enumConstant).name());
88 } catch (Exception ex) {
89 throw ExceptionUtil.unchecked(ex);
90 }
91 }
92 }
93
94 private static Class<? extends Enum> findEnumSuperClass(Class<?> c) {
95 if (c.isEnum()) {
96 return c.asSubclass(Enum.class);
97 } else if (Object.class == c) {
98 return null;
99 } else {
100 return findEnumSuperClass(c.getSuperclass());
101 }
102 }
103
104 private static Collection<Field> findInjectableField(Class<?> targetClass) {
105 if (Object.class == targetClass) {
106 return new ArrayList<Field>();
107 }
108
109 Collection<Field> injectableFields =
110 findInjectableField(targetClass.getSuperclass());
111 for (Field f : targetClass.getDeclaredFields()) {
112 if (isNonStaticAndNonFinal(f) && isAnnotationClass(f.getType())) {
113 injectableFields.add(f);
114 }
115 }
116 return injectableFields;
117 }
118
119 private static boolean isNonStaticAndNonFinal(Field f) {
120 int modifiers = f.getModifiers();
121 return false == Modifier.isStatic(modifiers)
122 && false == Modifier.isFinal(modifiers);
123 }
124
125 private static boolean isAnnotationClass(Class<?> c) {
126 Retention retention = c.getAnnotation(Retention.class);
127 return null == retention
128 ? c.isAnnotation()
129 : RetentionPolicy.RUNTIME == retention.value();
130 }
131
132 private static void checkForClassRetention(Collection<Field> injectableFields) {
133 List<Field> fieldsWithClassRetention = new ArrayList<Field>();
134 for (Field f : injectableFields) {
135 if (false == f.getType().isAnnotationPresent(Retention.class)) {
136 fieldsWithClassRetention.add(f);
137 }
138 }
139 if (false == fieldsWithClassRetention.isEmpty()) {
140 throw new Error("Annotation classes that are not annotated with "
141 + "@Retention(RetentionPolicy.RUNTIME) cannot be injected: "
142 + fieldsWithClassRetention);
143 }
144 }
145 }