Index: java/org/apache/catalina/util/DefaultAnnotationProcessor.java =================================================================== --- java/org/apache/catalina/util/DefaultAnnotationProcessor.java (révision 905680) +++ java/org/apache/catalina/util/DefaultAnnotationProcessor.java (copie de travail) @@ -23,6 +23,8 @@ import java.lang.reflect.Modifier; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.HashMap; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @@ -42,12 +44,27 @@ * * @author Fabien Carrion * @author Remy Maucherat + * @author Philippe Prados * @version $Revision$, $Date$ */ public class DefaultAnnotationProcessor implements AnnotationProcessor { protected javax.naming.Context context = null; + /** + * Introspection caches. + * All methods and attributes with candidate annotation. + */ + private static class CachedAnnotations { + ArrayList fields = new ArrayList(4); + ArrayList methods = new ArrayList(4); + }; + + /** + * Cached values in the context. + */ + private HashMap cachedIntrospections = new HashMap(11); + public DefaultAnnotationProcessor(javax.naming.Context context) { this.context = context; } @@ -60,45 +77,22 @@ throws IllegalAccessException, InvocationTargetException { Class clazz = instance.getClass(); - - while (clazz != null) { - Method[] methods = null; - if (Globals.IS_SECURITY_ENABLED) { - final Class clazz2 = clazz; - methods = AccessController.doPrivileged( - new PrivilegedAction(){ - public Method[] run(){ - return clazz2.getDeclaredMethods(); - } - }); - } else { - methods = clazz.getDeclaredMethods(); - } - Method postConstruct = null; - for (int i = 0; i < methods.length; i++) { - if (methods[i].isAnnotationPresent(PostConstruct.class)) { - if ((postConstruct != null) - || (methods[i].getParameterTypes().length != 0) - || (Modifier.isStatic(methods[i].getModifiers())) - || (methods[i].getExceptionTypes().length > 0) - || (!methods[i].getReturnType().getName().equals("void"))) { - throw new IllegalArgumentException("Invalid PostConstruct annotation"); - } - postConstruct = methods[i]; + CachedAnnotations cachedValues = getCachedValues(clazz); + for (Method m:cachedValues.methods) + { + if (m.isAnnotationPresent(PostConstruct.class)) { + if ((m.getParameterTypes().length != 0) + || (Modifier.isStatic(m.getModifiers())) + || (m.getExceptionTypes().length > 0) + || (!m.getReturnType().getName().equals("void"))) { + throw new IllegalArgumentException("Invalid PostConstruct annotation"); } + boolean accessibility = m.isAccessible(); + m.setAccessible(true); + m.invoke(instance); + m.setAccessible(accessibility); } - - // At the end the postconstruct annotated - // method is invoked - if (postConstruct != null) { - boolean accessibility = postConstruct.isAccessible(); - postConstruct.setAccessible(true); - postConstruct.invoke(instance); - postConstruct.setAccessible(accessibility); - } - - clazz = clazz.getSuperclass(); - } + } } @@ -109,50 +103,24 @@ throws IllegalAccessException, InvocationTargetException { Class clazz = instance.getClass(); - - while (clazz != null) { - Method[] methods; - // Hack so PrivilegedAction can access clazz object - final Class clazz2 = clazz; - if (Globals.IS_SECURITY_ENABLED) { - methods = AccessController.doPrivileged( - new PrivilegedAction(){ - public Method[] run(){ - return clazz2.getDeclaredMethods(); - } - }); - } else { - methods = clazz.getDeclaredMethods(); - } - - Method preDestroy = null; - for (int i = 0; i < methods.length; i++) { - if (methods[i].isAnnotationPresent(PreDestroy.class)) { - if ((preDestroy != null) - || (methods[i].getParameterTypes().length != 0) - || (Modifier.isStatic(methods[i].getModifiers())) - || (methods[i].getExceptionTypes().length > 0) - || (!methods[i].getReturnType().getName().equals("void"))) { - throw new IllegalArgumentException("Invalid PreDestroy annotation"); - } - preDestroy = methods[i]; + CachedAnnotations cachedValues = getCachedValues(clazz); + for (Method m:cachedValues.methods) + { + if (m.isAnnotationPresent(PreDestroy.class)) { + if ((m.getParameterTypes().length != 0) + || (Modifier.isStatic(m.getModifiers())) + || (m.getExceptionTypes().length > 0) + || (!m.getReturnType().getName().equals("void"))) { + throw new IllegalArgumentException("Invalid PreDestroy annotation"); } + boolean accessibility = m.isAccessible(); + m.setAccessible(true); + m.invoke(instance); + m.setAccessible(accessibility); } - - // At the end the postconstruct annotated - // method is invoked - if (preDestroy != null) { - boolean accessibility = preDestroy.isAccessible(); - preDestroy.setAccessible(true); - preDestroy.invoke(instance); - preDestroy.setAccessible(accessibility); - } - - clazz = clazz.getSuperclass(); - } + } } - /** * Inject resources in specified instance. */ @@ -165,102 +133,161 @@ } Class clazz = instance.getClass(); - - while (clazz != null) { - // Initialize fields annotations - Field[] fields = null; - if (Globals.IS_SECURITY_ENABLED) { - final Class clazz2 = clazz; - fields = AccessController.doPrivileged( - new PrivilegedAction(){ - public Field[] run(){ - return clazz2.getDeclaredFields(); - } - }); - } else { - fields = clazz.getDeclaredFields(); + CachedAnnotations cachedValues = getCachedValues(clazz); + + // Step 2. Use cached values + for (Field f:cachedValues.fields) { + if (f.isAnnotationPresent(Resource.class)) { + Resource annotation = + f.getAnnotation(Resource.class); + lookupFieldResource(context, instance, f, + annotation.name(), clazz); } - for (int i = 0; i < fields.length; i++) { - if (fields[i].isAnnotationPresent(Resource.class)) { - Resource annotation = - fields[i].getAnnotation(Resource.class); - lookupFieldResource(context, instance, fields[i], - annotation.name(), clazz); - } - if (fields[i].isAnnotationPresent(EJB.class)) { - EJB annotation = fields[i].getAnnotation(EJB.class); - lookupFieldResource(context, instance, fields[i], - annotation.name(), clazz); - } - if (fields[i].isAnnotationPresent(WebServiceRef.class)) { - WebServiceRef annotation = - fields[i].getAnnotation(WebServiceRef.class); - lookupFieldResource(context, instance, fields[i], - annotation.name(), clazz); - } - if (fields[i].isAnnotationPresent(PersistenceContext.class)) { - PersistenceContext annotation = - fields[i].getAnnotation(PersistenceContext.class); - lookupFieldResource(context, instance, fields[i], - annotation.name(), clazz); - } - if (fields[i].isAnnotationPresent(PersistenceUnit.class)) { - PersistenceUnit annotation = - fields[i].getAnnotation(PersistenceUnit.class); - lookupFieldResource(context, instance, fields[i], - annotation.name(), clazz); - } + if (f.isAnnotationPresent(EJB.class)) { + EJB annotation = f.getAnnotation(EJB.class); + lookupFieldResource(context, instance, f, + annotation.name(), clazz); } - - // Initialize methods annotations - Method[] methods = null; - if (Globals.IS_SECURITY_ENABLED) { - final Class clazz2 = clazz; - methods = AccessController.doPrivileged( - new PrivilegedAction(){ - public Method[] run(){ - return clazz2.getDeclaredMethods(); - } - }); - } else { - methods = clazz.getDeclaredMethods(); + if (f.isAnnotationPresent(WebServiceRef.class)) { + WebServiceRef annotation = + f.getAnnotation(WebServiceRef.class); + lookupFieldResource(context, instance, f, + annotation.name(), clazz); } - for (int i = 0; i < methods.length; i++) { - if (methods[i].isAnnotationPresent(Resource.class)) { - Resource annotation = methods[i].getAnnotation(Resource.class); - lookupMethodResource(context, instance, methods[i], - annotation.name(), clazz); + if (f.isAnnotationPresent(PersistenceContext.class)) { + PersistenceContext annotation = + f.getAnnotation(PersistenceContext.class); + lookupFieldResource(context, instance, f, + annotation.name(), clazz); + } + if (f.isAnnotationPresent(PersistenceUnit.class)) { + PersistenceUnit annotation = + f.getAnnotation(PersistenceUnit.class); + lookupFieldResource(context, instance, f, + annotation.name(), clazz); + } + } + for (Method m:cachedValues.methods) { + if (m.isAnnotationPresent(Resource.class)) { + Resource annotation = m.getAnnotation(Resource.class); + lookupMethodResource(context, instance, m, + annotation.name(), clazz); + } + if (m.isAnnotationPresent(EJB.class)) { + EJB annotation = m.getAnnotation(EJB.class); + lookupMethodResource(context, instance, m, + annotation.name(), clazz); + } + if (m.isAnnotationPresent(WebServiceRef.class)) { + WebServiceRef annotation = + m.getAnnotation(WebServiceRef.class); + lookupMethodResource(context, instance, m, + annotation.name(), clazz); + } + if (m.isAnnotationPresent(PersistenceContext.class)) { + PersistenceContext annotation = + m.getAnnotation(PersistenceContext.class); + lookupMethodResource(context, instance, m, + annotation.name(), clazz); + } + if (m.isAnnotationPresent(PersistenceUnit.class)) { + PersistenceUnit annotation = + m.getAnnotation(PersistenceUnit.class); + lookupMethodResource(context, instance, m, + annotation.name(), clazz); + } + + } + } + + /** + * Return a cache version with methods and attributes using annotations. + * @param initialClazz Class to analyze + * @return The cached version. + */ + private CachedAnnotations getCachedValues(final Class initialClazz) + { + CachedAnnotations cachedValues = cachedIntrospections.get(initialClazz); + if (cachedValues == null) { + cachedValues = new CachedAnnotations(); + // Step 1: Feeling the cache + Class clazz = initialClazz; + while (clazz != null) { + + // Initialize fields annotations + Field[] fields = null; + if (Globals.IS_SECURITY_ENABLED) { + final Class clazz2 = clazz; + fields = AccessController.doPrivileged( + new PrivilegedAction(){ + public Field[] run(){ + return clazz2.getDeclaredFields(); + } + }); + } else { + fields = clazz.getDeclaredFields(); } - if (methods[i].isAnnotationPresent(EJB.class)) { - EJB annotation = methods[i].getAnnotation(EJB.class); - lookupMethodResource(context, instance, methods[i], - annotation.name(), clazz); + for (int i = 0; i < fields.length; i++) { + if (fields[i].isAnnotationPresent(Resource.class)) { + cachedValues.fields.add(fields[i]); + } + if (fields[i].isAnnotationPresent(EJB.class)) { + cachedValues.fields.add(fields[i]); + } + if (fields[i].isAnnotationPresent(WebServiceRef.class)) { + cachedValues.fields.add(fields[i]); + } + if (fields[i].isAnnotationPresent(PersistenceContext.class)) { + cachedValues.fields.add(fields[i]); + } + if (fields[i].isAnnotationPresent(PersistenceUnit.class)) { + cachedValues.fields.add(fields[i]); + } } - if (methods[i].isAnnotationPresent(WebServiceRef.class)) { - WebServiceRef annotation = - methods[i].getAnnotation(WebServiceRef.class); - lookupMethodResource(context, instance, methods[i], - annotation.name(), clazz); + + // Initialize methods annotations + Method[] methods = null; + if (Globals.IS_SECURITY_ENABLED) { + final Class clazz2 = clazz; + methods = AccessController.doPrivileged( + new PrivilegedAction(){ + public Method[] run(){ + return clazz2.getDeclaredMethods(); + } + }); + } else { + methods = clazz.getDeclaredMethods(); } - if (methods[i].isAnnotationPresent(PersistenceContext.class)) { - PersistenceContext annotation = - methods[i].getAnnotation(PersistenceContext.class); - lookupMethodResource(context, instance, methods[i], - annotation.name(), clazz); + for (int i = 0; i < methods.length; i++) { + if (methods[i].isAnnotationPresent(Resource.class)) { + cachedValues.methods.add(methods[i]); + } + if (methods[i].isAnnotationPresent(EJB.class)) { + cachedValues.methods.add(methods[i]); + } + if (methods[i].isAnnotationPresent(WebServiceRef.class)) { + cachedValues.methods.add(methods[i]); + } + if (methods[i].isAnnotationPresent(PersistenceContext.class)) { + cachedValues.methods.add(methods[i]); + } + if (methods[i].isAnnotationPresent(PersistenceUnit.class)) { + cachedValues.methods.add(methods[i]); + } + if (methods[i].isAnnotationPresent(PreDestroy.class)) { + cachedValues.methods.add(methods[i]); + } + if (methods[i].isAnnotationPresent(PostConstruct.class)) { + cachedValues.methods.add(methods[i]); + } } - if (methods[i].isAnnotationPresent(PersistenceUnit.class)) { - PersistenceUnit annotation = - methods[i].getAnnotation(PersistenceUnit.class); - lookupMethodResource(context, instance, methods[i], - annotation.name(), clazz); - } - } - - clazz = clazz.getSuperclass(); + clazz = clazz.getSuperclass(); + } + cachedIntrospections.put(initialClazz, cachedValues); } + return cachedValues; } - /** * Inject resources in specified field. */