View | Details | Raw Unified | Return to bug 48600
Collapse All | Expand All

(-)java/org/apache/catalina/util/DefaultAnnotationProcessor.java (-163 / +190 lines)
Lines 23-28 Link Here
23
import java.lang.reflect.Modifier;
23
import java.lang.reflect.Modifier;
24
import java.security.AccessController;
24
import java.security.AccessController;
25
import java.security.PrivilegedAction;
25
import java.security.PrivilegedAction;
26
import java.util.ArrayList;
27
import java.util.HashMap;
26
28
27
import javax.annotation.PostConstruct;
29
import javax.annotation.PostConstruct;
28
import javax.annotation.PreDestroy;
30
import javax.annotation.PreDestroy;
Lines 42-53 Link Here
42
 *
44
 *
43
 * @author Fabien Carrion
45
 * @author Fabien Carrion
44
 * @author Remy Maucherat
46
 * @author Remy Maucherat
47
 * @author Philippe Prados
45
 * @version $Revision$, $Date$
48
 * @version $Revision$, $Date$
46
 */
49
 */
47
public class DefaultAnnotationProcessor implements AnnotationProcessor {
50
public class DefaultAnnotationProcessor implements AnnotationProcessor {
48
    
51
    
49
    protected javax.naming.Context context = null;
52
    protected javax.naming.Context context = null;
50
    
53
    
54
    /**
55
     * Introspection caches.
56
     * All methods and attributes with candidate annotation.
57
     */
58
    private static class CachedAnnotations {
59
    	ArrayList<Field> fields = new ArrayList<Field>(4);
60
    	ArrayList<Method> methods = new ArrayList<Method>(4);
61
    };
62
    
63
    /**
64
     * Cached values in the context.
65
     */
66
    private HashMap<Class,CachedAnnotations> cachedIntrospections = new HashMap<Class,CachedAnnotations>(11);
67
    
51
    public DefaultAnnotationProcessor(javax.naming.Context context) {
68
    public DefaultAnnotationProcessor(javax.naming.Context context) {
52
        this.context = context;
69
        this.context = context;
53
    }
70
    }
Lines 60-104 Link Here
60
        throws IllegalAccessException, InvocationTargetException {
77
        throws IllegalAccessException, InvocationTargetException {
61
        
78
        
62
        Class<?> clazz = instance.getClass();
79
        Class<?> clazz = instance.getClass();
63
        
80
    	CachedAnnotations cachedValues = getCachedValues(clazz);
64
        while (clazz != null) {
81
    	for (Method m:cachedValues.methods)
65
            Method[] methods = null;
82
    	{
66
            if (Globals.IS_SECURITY_ENABLED) {
83
            if (m.isAnnotationPresent(PostConstruct.class)) {
67
                final Class<?> clazz2 = clazz;
84
                if ((m.getParameterTypes().length != 0)
68
                methods = AccessController.doPrivileged(
85
                        || (Modifier.isStatic(m.getModifiers())) 
69
                        new PrivilegedAction<Method[]>(){
86
                        || (m.getExceptionTypes().length > 0)
70
                    public Method[] run(){
87
                        || (!m.getReturnType().getName().equals("void"))) {
71
                        return clazz2.getDeclaredMethods();
88
                    throw new IllegalArgumentException("Invalid PostConstruct annotation");
72
                    }
73
                });
74
            } else {
75
                methods = clazz.getDeclaredMethods();
76
            }
77
            Method postConstruct = null;
78
            for (int i = 0; i < methods.length; i++) {
79
                if (methods[i].isAnnotationPresent(PostConstruct.class)) {
80
                    if ((postConstruct != null) 
81
                            || (methods[i].getParameterTypes().length != 0)
82
                            || (Modifier.isStatic(methods[i].getModifiers())) 
83
                            || (methods[i].getExceptionTypes().length > 0)
84
                            || (!methods[i].getReturnType().getName().equals("void"))) {
85
                        throw new IllegalArgumentException("Invalid PostConstruct annotation");
86
                    }
87
                    postConstruct = methods[i];
88
                }
89
                }
90
                boolean accessibility = m.isAccessible();
91
                m.setAccessible(true);
92
                m.invoke(instance);
93
                m.setAccessible(accessibility);
89
            }
94
            }
90
    
95
    	}
91
            // At the end the postconstruct annotated 
92
            // method is invoked
93
            if (postConstruct != null) {
94
                boolean accessibility = postConstruct.isAccessible();
95
                postConstruct.setAccessible(true);
96
                postConstruct.invoke(instance);
97
                postConstruct.setAccessible(accessibility);
98
            }
99
        
100
            clazz = clazz.getSuperclass();
101
        }
102
    }
96
    }
103
    
97
    
104
    
98
    
Lines 109-158 Link Here
109
        throws IllegalAccessException, InvocationTargetException {
103
        throws IllegalAccessException, InvocationTargetException {
110
        
104
        
111
        Class<?> clazz = instance.getClass();
105
        Class<?> clazz = instance.getClass();
112
        
106
    	CachedAnnotations cachedValues = getCachedValues(clazz);
113
        while (clazz != null) {
107
    	for (Method m:cachedValues.methods)
114
            Method[] methods;
108
    	{
115
            // Hack so PrivilegedAction can access clazz object
109
            if (m.isAnnotationPresent(PreDestroy.class)) {
116
            final Class<?> clazz2 = clazz;
110
                if ((m.getParameterTypes().length != 0)
117
            if (Globals.IS_SECURITY_ENABLED) {
111
                        || (Modifier.isStatic(m.getModifiers())) 
118
                methods = AccessController.doPrivileged(
112
                        || (m.getExceptionTypes().length > 0)
119
                        new PrivilegedAction<Method[]>(){
113
                        || (!m.getReturnType().getName().equals("void"))) {
120
                            public Method[] run(){
114
                    throw new IllegalArgumentException("Invalid PreDestroy annotation");
121
                                return clazz2.getDeclaredMethods();
122
                            }
123
                        });
124
            } else {
125
                methods = clazz.getDeclaredMethods();
126
            }
127
128
            Method preDestroy = null;
129
            for (int i = 0; i < methods.length; i++) {
130
                if (methods[i].isAnnotationPresent(PreDestroy.class)) {
131
                    if ((preDestroy != null) 
132
                            || (methods[i].getParameterTypes().length != 0)
133
                            || (Modifier.isStatic(methods[i].getModifiers())) 
134
                            || (methods[i].getExceptionTypes().length > 0)
135
                            || (!methods[i].getReturnType().getName().equals("void"))) {
136
                        throw new IllegalArgumentException("Invalid PreDestroy annotation");
137
                    }
138
                    preDestroy = methods[i];
139
                }
115
                }
116
                boolean accessibility = m.isAccessible();
117
                m.setAccessible(true);
118
                m.invoke(instance);
119
                m.setAccessible(accessibility);
140
            }
120
            }
141
    
121
    	}
142
            // At the end the postconstruct annotated 
143
            // method is invoked
144
            if (preDestroy != null) {
145
                boolean accessibility = preDestroy.isAccessible();
146
                preDestroy.setAccessible(true);
147
                preDestroy.invoke(instance);
148
                preDestroy.setAccessible(accessibility);
149
            }
150
151
            clazz = clazz.getSuperclass();
152
        }
153
    }
122
    }
154
    
123
    
155
    
156
    /**
124
    /**
157
     * Inject resources in specified instance.
125
     * Inject resources in specified instance.
158
     */
126
     */
Lines 165-266 Link Here
165
        }
133
        }
166
        
134
        
167
        Class<?> clazz = instance.getClass();
135
        Class<?> clazz = instance.getClass();
168
        
136
        CachedAnnotations cachedValues = getCachedValues(clazz);
169
        while (clazz != null) {
137
    	
170
            // Initialize fields annotations
138
        // Step 2. Use cached values
171
            Field[] fields = null;
139
        for (Field f:cachedValues.fields) {
172
            if (Globals.IS_SECURITY_ENABLED) {
140
            if (f.isAnnotationPresent(Resource.class)) {
173
                final Class<?> clazz2 = clazz;
141
                Resource annotation =
174
                fields = AccessController.doPrivileged(
142
                    f.getAnnotation(Resource.class);
175
                        new PrivilegedAction<Field[]>(){
143
                lookupFieldResource(context, instance, f,
176
                    public Field[] run(){
144
                        annotation.name(), clazz);
177
                        return clazz2.getDeclaredFields();
178
                    }
179
                });
180
            } else {
181
                fields = clazz.getDeclaredFields();
182
            }
145
            }
183
            for (int i = 0; i < fields.length; i++) {
146
            if (f.isAnnotationPresent(EJB.class)) {
184
                if (fields[i].isAnnotationPresent(Resource.class)) {
147
                EJB annotation = f.getAnnotation(EJB.class);
185
                    Resource annotation =
148
                lookupFieldResource(context, instance, f,
186
                        fields[i].getAnnotation(Resource.class);
149
                        annotation.name(), clazz);
187
                    lookupFieldResource(context, instance, fields[i],
188
                            annotation.name(), clazz);
189
                }
190
                if (fields[i].isAnnotationPresent(EJB.class)) {
191
                    EJB annotation = fields[i].getAnnotation(EJB.class);
192
                    lookupFieldResource(context, instance, fields[i],
193
                            annotation.name(), clazz);
194
                }
195
                if (fields[i].isAnnotationPresent(WebServiceRef.class)) {
196
                    WebServiceRef annotation =
197
                        fields[i].getAnnotation(WebServiceRef.class);
198
                    lookupFieldResource(context, instance, fields[i],
199
                            annotation.name(), clazz);
200
                }
201
                if (fields[i].isAnnotationPresent(PersistenceContext.class)) {
202
                    PersistenceContext annotation = 
203
                        fields[i].getAnnotation(PersistenceContext.class);
204
                    lookupFieldResource(context, instance, fields[i],
205
                            annotation.name(), clazz);
206
                }
207
                if (fields[i].isAnnotationPresent(PersistenceUnit.class)) {
208
                    PersistenceUnit annotation = 
209
                        fields[i].getAnnotation(PersistenceUnit.class);
210
                    lookupFieldResource(context, instance, fields[i],
211
                            annotation.name(), clazz);
212
                }
213
            }
150
            }
214
            
151
            if (f.isAnnotationPresent(WebServiceRef.class)) {
215
            // Initialize methods annotations
152
                WebServiceRef annotation =
216
            Method[] methods = null;
153
                    f.getAnnotation(WebServiceRef.class);
217
            if (Globals.IS_SECURITY_ENABLED) {
154
                lookupFieldResource(context, instance, f,
218
                final Class<?> clazz2 = clazz;
155
                        annotation.name(), clazz);
219
                methods = AccessController.doPrivileged(
220
                        new PrivilegedAction<Method[]>(){
221
                    public Method[] run(){
222
                        return clazz2.getDeclaredMethods();
223
                    }
224
                });
225
            } else {
226
                methods = clazz.getDeclaredMethods();
227
            }
156
            }
228
            for (int i = 0; i < methods.length; i++) {
157
            if (f.isAnnotationPresent(PersistenceContext.class)) {
229
                if (methods[i].isAnnotationPresent(Resource.class)) {
158
                PersistenceContext annotation = 
230
                    Resource annotation = methods[i].getAnnotation(Resource.class);
159
                    f.getAnnotation(PersistenceContext.class);
231
                    lookupMethodResource(context, instance, methods[i],
160
                lookupFieldResource(context, instance, f,
232
                            annotation.name(), clazz);
161
                        annotation.name(), clazz);
162
            }
163
            if (f.isAnnotationPresent(PersistenceUnit.class)) {
164
                PersistenceUnit annotation = 
165
                    f.getAnnotation(PersistenceUnit.class);
166
                lookupFieldResource(context, instance, f,
167
                        annotation.name(), clazz);
168
            }
169
        }
170
        for (Method m:cachedValues.methods) {
171
            if (m.isAnnotationPresent(Resource.class)) {
172
                Resource annotation = m.getAnnotation(Resource.class);
173
                lookupMethodResource(context, instance, m,
174
                        annotation.name(), clazz);
175
            }
176
            if (m.isAnnotationPresent(EJB.class)) {
177
                EJB annotation = m.getAnnotation(EJB.class);
178
                lookupMethodResource(context, instance, m,
179
                        annotation.name(), clazz);
180
            }
181
            if (m.isAnnotationPresent(WebServiceRef.class)) {
182
                WebServiceRef annotation = 
183
                    m.getAnnotation(WebServiceRef.class);
184
                lookupMethodResource(context, instance, m,
185
                        annotation.name(), clazz);
186
            }
187
            if (m.isAnnotationPresent(PersistenceContext.class)) {
188
                PersistenceContext annotation = 
189
                    m.getAnnotation(PersistenceContext.class);
190
                lookupMethodResource(context, instance, m,
191
                        annotation.name(), clazz);
192
            }
193
            if (m.isAnnotationPresent(PersistenceUnit.class)) {
194
                PersistenceUnit annotation = 
195
                    m.getAnnotation(PersistenceUnit.class);
196
                lookupMethodResource(context, instance, m,
197
                        annotation.name(), clazz);
198
            }
199
        	
200
        }        
201
    }
202
    
203
    /**
204
     * Return a cache version with methods and attributes using annotations.
205
     * @param initialClazz Class to analyze
206
     * @return The cached version.
207
     */
208
    private CachedAnnotations getCachedValues(final Class initialClazz)
209
    {
210
    	CachedAnnotations cachedValues = cachedIntrospections.get(initialClazz);
211
    	if (cachedValues == null) {
212
    		cachedValues = new CachedAnnotations();
213
    		// Step 1: Feeling the cache
214
    		Class clazz = initialClazz;
215
    		while (clazz != null) {
216
        	
217
                // Initialize fields annotations
218
                Field[] fields = null;
219
                if (Globals.IS_SECURITY_ENABLED) {
220
                    final Class<?> clazz2 = clazz;
221
                    fields = AccessController.doPrivileged(
222
                            new PrivilegedAction<Field[]>(){
223
                        public Field[] run(){
224
                            return clazz2.getDeclaredFields();
225
                        }
226
                    });
227
                } else {
228
                    fields = clazz.getDeclaredFields();
233
                }
229
                }
234
                if (methods[i].isAnnotationPresent(EJB.class)) {
230
                for (int i = 0; i < fields.length; i++) {
235
                    EJB annotation = methods[i].getAnnotation(EJB.class);
231
                    if (fields[i].isAnnotationPresent(Resource.class)) {
236
                    lookupMethodResource(context, instance, methods[i],
232
                        cachedValues.fields.add(fields[i]);
237
                            annotation.name(), clazz);
233
                    }
234
                    if (fields[i].isAnnotationPresent(EJB.class)) {
235
                        cachedValues.fields.add(fields[i]);
236
                    }
237
                    if (fields[i].isAnnotationPresent(WebServiceRef.class)) {
238
                        cachedValues.fields.add(fields[i]);
239
                    }
240
                    if (fields[i].isAnnotationPresent(PersistenceContext.class)) {
241
                        cachedValues.fields.add(fields[i]);
242
                    }
243
                    if (fields[i].isAnnotationPresent(PersistenceUnit.class)) {
244
                        cachedValues.fields.add(fields[i]);
245
                    }
238
                }
246
                }
239
                if (methods[i].isAnnotationPresent(WebServiceRef.class)) {
247
                
240
                    WebServiceRef annotation = 
248
                // Initialize methods annotations
241
                        methods[i].getAnnotation(WebServiceRef.class);
249
                Method[] methods = null;
242
                    lookupMethodResource(context, instance, methods[i],
250
                if (Globals.IS_SECURITY_ENABLED) {
243
                            annotation.name(), clazz);
251
                    final Class<?> clazz2 = clazz;
252
                    methods = AccessController.doPrivileged(
253
                            new PrivilegedAction<Method[]>(){
254
                        public Method[] run(){
255
                            return clazz2.getDeclaredMethods();
256
                        }
257
                    });
258
                } else {
259
                    methods = clazz.getDeclaredMethods();
244
                }
260
                }
245
                if (methods[i].isAnnotationPresent(PersistenceContext.class)) {
261
                for (int i = 0; i < methods.length; i++) {
246
                    PersistenceContext annotation = 
262
                    if (methods[i].isAnnotationPresent(Resource.class)) {
247
                        methods[i].getAnnotation(PersistenceContext.class);
263
                        cachedValues.methods.add(methods[i]);
248
                    lookupMethodResource(context, instance, methods[i],
264
                    }
249
                            annotation.name(), clazz);
265
                    if (methods[i].isAnnotationPresent(EJB.class)) {
266
                        cachedValues.methods.add(methods[i]);
267
                    }
268
                    if (methods[i].isAnnotationPresent(WebServiceRef.class)) {
269
                        cachedValues.methods.add(methods[i]);
270
                    }
271
                    if (methods[i].isAnnotationPresent(PersistenceContext.class)) {
272
                        cachedValues.methods.add(methods[i]);
273
                    }
274
                    if (methods[i].isAnnotationPresent(PersistenceUnit.class)) {
275
                        cachedValues.methods.add(methods[i]);
276
                    }
277
                    if (methods[i].isAnnotationPresent(PreDestroy.class)) {
278
                        cachedValues.methods.add(methods[i]);
279
                    }
280
                    if (methods[i].isAnnotationPresent(PostConstruct.class)) {
281
                        cachedValues.methods.add(methods[i]);
282
                    }
250
                }
283
                }
251
                if (methods[i].isAnnotationPresent(PersistenceUnit.class)) {
284
                clazz = clazz.getSuperclass();
252
                    PersistenceUnit annotation = 
285
        	}
253
                        methods[i].getAnnotation(PersistenceUnit.class);
286
    		cachedIntrospections.put(initialClazz, cachedValues);
254
                    lookupMethodResource(context, instance, methods[i],
255
                            annotation.name(), clazz);
256
                }
257
            }
258
            
259
            clazz = clazz.getSuperclass();
260
        }
287
        }
288
    	return cachedValues;
261
    }
289
    }
262
    
290
    
263
    
264
    /**
291
    /**
265
     * Inject resources in specified field.
292
     * Inject resources in specified field.
266
     */
293
     */

Return to bug 48600