1 package org.apache.commons.digester3.annotations;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import static org.apache.commons.digester3.annotations.utils.AnnotationUtils.getAnnotationsArrayValue;
23
24 import java.lang.annotation.Annotation;
25 import java.lang.reflect.AnnotatedElement;
26 import java.lang.reflect.Constructor;
27 import java.lang.reflect.Field;
28 import java.lang.reflect.Method;
29 import java.security.AccessController;
30 import java.security.PrivilegedAction;
31
32 import org.apache.commons.digester3.Rule;
33 import org.apache.commons.digester3.annotations.reflect.MethodArgument;
34 import org.apache.commons.digester3.binder.AbstractRulesModule;
35
36
37
38
39
40
41
42 public abstract class FromAnnotationsRuleModule
43 extends AbstractRulesModule
44 {
45
46 private static final String JAVA_PACKAGE = "java";
47
48 private static final AnnotationHandlerFactory DEFAULT_HANDLER_FACTORY = new DefaultAnnotationHandlerFactory();
49
50 private AnnotationHandlerFactory annotationHandlerFactory = DEFAULT_HANDLER_FACTORY;
51
52 private WithMemoryRulesBinder rulesBinder;
53
54
55
56
57 @Override
58 protected final void configure()
59 {
60 if ( rulesBinder == null )
61 {
62 rulesBinder = new WithMemoryRulesBinder( rulesBinder() );
63 }
64
65 try
66 {
67 configureRules();
68 }
69 finally
70 {
71 rulesBinder = null;
72 }
73 }
74
75
76
77
78 protected abstract void configureRules();
79
80
81
82
83
84
85
86 protected final void useAnnotationHandlerFactory( AnnotationHandlerFactory annotationHandlerFactory )
87 {
88 if ( annotationHandlerFactory == null )
89 {
90 throw new IllegalArgumentException( "Argument 'annotationHandlerFactory' must be not null" );
91 }
92
93 this.annotationHandlerFactory = annotationHandlerFactory;
94 }
95
96
97
98
99 protected final void useDefaultAnnotationHandlerFactory()
100 {
101 useAnnotationHandlerFactory( DEFAULT_HANDLER_FACTORY );
102 }
103
104
105
106
107
108
109
110 protected final void bindRulesFrom( final Class<?> type )
111 {
112 if ( type == null || type.getPackage().getName().startsWith( JAVA_PACKAGE )
113 || rulesBinder.isAlreadyBound( type ) )
114 {
115 return;
116 }
117
118
119 visitElements( type );
120
121 if ( !type.isInterface() )
122 {
123
124 visitElements( new PrivilegedAction<Constructor<?>[]>()
125 {
126 public Constructor<?>[] run()
127 {
128 return type.getDeclaredConstructors();
129 }
130 } );
131
132
133 visitElements( new PrivilegedAction<Field[]>()
134 {
135 public Field[] run()
136 {
137 return type.getDeclaredFields();
138 }
139 } );
140 }
141
142
143 visitElements( new PrivilegedAction<Method[]>()
144 {
145 public Method[] run()
146 {
147 return type.getDeclaredMethods();
148 }
149 } );
150
151 rulesBinder.markAsBound( type );
152 bindRulesFrom( type.getSuperclass() );
153 }
154
155
156
157
158
159
160
161 private <AE extends AnnotatedElement> void visitElements( PrivilegedAction<AE[]> action )
162 {
163 AE[] annotatedElements = null;
164 if ( System.getSecurityManager() != null )
165 {
166 annotatedElements = AccessController.doPrivileged( action );
167 }
168 else
169 {
170 annotatedElements = action.run();
171 }
172 visitElements( annotatedElements );
173 }
174
175
176
177
178
179
180 private void visitElements( AnnotatedElement... annotatedElements )
181 {
182 for ( AnnotatedElement element : annotatedElements )
183 {
184 for ( Annotation annotation : element.getAnnotations() )
185 {
186 handle( annotation, element );
187 }
188
189 if ( element instanceof Constructor || element instanceof Method )
190 {
191 Annotation[][] parameterAnnotations;
192 Class<?>[] parameterTypes;
193
194 if ( element instanceof Constructor )
195 {
196
197 Constructor<?> construcotr = (Constructor<?>) element;
198 parameterAnnotations = construcotr.getParameterAnnotations();
199 parameterTypes = construcotr.getParameterTypes();
200 }
201 else
202 {
203
204 Method method = (Method) element;
205 parameterAnnotations = method.getParameterAnnotations();
206 parameterTypes = method.getParameterTypes();
207 }
208
209 for ( int i = 0; i < parameterTypes.length; i++ )
210 {
211 visitElements( new MethodArgument( i, parameterTypes[i], parameterAnnotations[i] ) );
212 }
213 }
214 }
215 }
216
217
218
219
220
221
222
223
224 @SuppressWarnings( "unchecked" )
225 private <A extends Annotation, E extends AnnotatedElement, R extends Rule> void handle( A annotation, E element )
226 {
227 Class<?> annotationType = annotation.annotationType();
228
229
230 if ( annotationType.isAnnotationPresent( DigesterRuleList.class ) )
231 {
232 Annotation[] annotations = getAnnotationsArrayValue( annotation );
233 if ( annotations != null && annotations.length > 0 )
234 {
235
236 for ( Annotation ptr : annotations )
237 {
238 handle( ptr, element );
239 }
240 }
241 }
242 else if ( annotationType.isAnnotationPresent( DigesterRule.class ) )
243 {
244 DigesterRule digesterRule = annotationType.getAnnotation( DigesterRule.class );
245
246
247 Class<? extends AnnotationHandler<Annotation, AnnotatedElement>> handlerType =
248 (Class<? extends AnnotationHandler<Annotation, AnnotatedElement>>) digesterRule.handledBy();
249 try
250 {
251 AnnotationHandler<Annotation, AnnotatedElement> handler =
252 annotationHandlerFactory.newInstance( handlerType );
253
254
255 handler.handle( annotation, element, this.rulesBinder );
256 }
257 catch ( Exception e )
258 {
259 rulesBinder.addError( e );
260 }
261 }
262 }
263
264 }