Author: markt Date: Tue Mar 27 19:20:10 2012 New Revision: 1305965 URL: http://svn.apache.org/viewvc?rev=1305965&view=rev Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=52974 Fix NameNotFoundException when field/method is annotated with @Resource annotation Patch provided by Violet Agg.
Modified: tomcat/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java Modified: tomcat/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java?rev=1305965&r1=1305964&r2=1305965&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java Tue Mar 27 19:20:10 2012 @@ -19,6 +19,11 @@ package org.apache.catalina.startup; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; + import javax.annotation.Resource; import javax.annotation.Resources; import javax.annotation.security.DeclareRoles; @@ -26,7 +31,9 @@ import javax.annotation.security.RunAs; import org.apache.catalina.Container; import org.apache.catalina.Context; +import org.apache.catalina.Globals; import org.apache.catalina.Wrapper; +import org.apache.catalina.core.DefaultInstanceManager; import org.apache.catalina.deploy.ContextEnvironment; import org.apache.catalina.deploy.ContextResource; import org.apache.catalina.deploy.ContextResourceEnvRef; @@ -44,6 +51,7 @@ import org.apache.catalina.deploy.Messag public class WebAnnotationSet { + private static final String SEPARATOR = "/"; // --------------------------------------------------------- Public Methods @@ -68,9 +76,17 @@ public class WebAnnotationSet { * Process the annotations for the listeners. */ protected static void loadApplicationListenerAnnotations(Context context) { + Class<?> classClass = null; String[] applicationListeners = context.findApplicationListeners(); for (int i = 0; i < applicationListeners.length; i++) { - loadClassAnnotation(context, applicationListeners[i]); + classClass = loadClass(context, applicationListeners[i]); + if (classClass == null) { + continue; + } + + loadClassAnnotation(context, classClass); + loadFieldsAnnotation(context, classClass); + loadMethodsAnnotation(context, classClass); } } @@ -79,9 +95,17 @@ public class WebAnnotationSet { * Process the annotations for the filters. */ protected static void loadApplicationFilterAnnotations(Context context) { + Class<?> classClass = null; FilterDef[] filterDefs = context.findFilterDefs(); for (int i = 0; i < filterDefs.length; i++) { - loadClassAnnotation(context, (filterDefs[i]).getFilterClass()); + classClass = loadClass(context, (filterDefs[i]).getFilterClass()); + if (classClass == null) { + continue; + } + + loadClassAnnotation(context, classClass); + loadFieldsAnnotation(context, classClass); + loadMethodsAnnotation(context, classClass); } } @@ -91,7 +115,6 @@ public class WebAnnotationSet { */ protected static void loadApplicationServletAnnotations(Context context) { - ClassLoader classLoader = context.getLoader().getClassLoader(); Wrapper wrapper = null; Class<?> classClass = null; @@ -104,19 +127,15 @@ public class WebAnnotationSet { continue; } - try { - classClass = classLoader.loadClass(wrapper.getServletClass()); - } catch (ClassNotFoundException e) { - // We do nothing - } catch (NoClassDefFoundError e) { - // We do nothing - } - + classClass = loadClass(context, wrapper.getServletClass()); if (classClass == null) { continue; } - loadClassAnnotation(context, wrapper.getServletClass()); + loadClassAnnotation(context, classClass); + loadFieldsAnnotation(context, classClass); + loadMethodsAnnotation(context, classClass); + /* Process RunAs annotation which can be only on servlets. * Ref JSR 250, equivalent to the run-as element in * the deployment descriptor @@ -135,25 +154,9 @@ public class WebAnnotationSet { /** * Process the annotations on a context for a given className. */ - protected static void loadClassAnnotation(Context context, String fileString) { - - ClassLoader classLoader = context.getLoader().getClassLoader(); - Class<?> classClass = null; - - try { - classClass = classLoader.loadClass(fileString); - } catch (ClassNotFoundException e) { - // We do nothing - } catch (NoClassDefFoundError e) { - // We do nothing - } - - if (classClass == null) { - return; - } - + protected static void loadClassAnnotation(Context context, + Class<?> classClass) { // Initialize the annotations - if (classClass.isAnnotationPresent(Resource.class)) { Resource annotation = classClass.getAnnotation(Resource.class); addResource(context, annotation); @@ -245,11 +248,49 @@ public class WebAnnotationSet { context.addSecurityRole(annotation.value()[i]); } } + } + protected static void loadFieldsAnnotation(Context context, + Class<?> classClass) { + // Initialize the annotations + Field[] fields = getDeclaredFields(classClass); + if (fields != null && fields.length > 0) { + for (Field field : fields) { + if (field.isAnnotationPresent(Resource.class)) { + Resource annotation = field.getAnnotation(Resource.class); + String defaultName = + classClass.getName() + SEPARATOR + field.getName(); + String defaultType = field.getType().getCanonicalName(); + addResource(context, annotation, defaultName, defaultType); + } + } + } } + protected static void loadMethodsAnnotation(Context context, + Class<?> classClass) { + // Initialize the annotations + Method[] methods = getDeclaredMethods(classClass); + if (methods != null && methods.length > 0) { + for (Method method : methods) { + if (method.isAnnotationPresent(Resource.class)) { + Resource annotation = method.getAnnotation(Resource.class); + + checkBeanNamingConventions(method); + + String defaultName = classClass.getName() + SEPARATOR + + DefaultInstanceManager.getName(method); + + String defaultType = + (method.getParameterTypes()[0]).getCanonicalName(); + addResource(context, annotation, defaultName, defaultType); + } + } + } + } + /** * Process a Resource annotation to set up a Resource. * Ref JSR 250, equivalent to the resource-ref, @@ -257,22 +298,29 @@ public class WebAnnotationSet { * or service-ref element in the deployment descriptor. */ protected static void addResource(Context context, Resource annotation) { + addResource(context, annotation, null, null); + } - if (annotation.type().getCanonicalName().equals("java.lang.String") || - annotation.type().getCanonicalName().equals("java.lang.Character") || - annotation.type().getCanonicalName().equals("java.lang.Integer") || - annotation.type().getCanonicalName().equals("java.lang.Boolean") || - annotation.type().getCanonicalName().equals("java.lang.Double") || - annotation.type().getCanonicalName().equals("java.lang.Byte") || - annotation.type().getCanonicalName().equals("java.lang.Short") || - annotation.type().getCanonicalName().equals("java.lang.Long") || - annotation.type().getCanonicalName().equals("java.lang.Float")) { + protected static void addResource(Context context, Resource annotation, + String defaultName, String defaultType) { + String name = getName(annotation, defaultName); + String type = getType(annotation, defaultType); + + if (type.equals("java.lang.String") || + type.equals("java.lang.Character") || + type.equals("java.lang.Integer") || + type.equals("java.lang.Boolean") || + type.equals("java.lang.Double") || + type.equals("java.lang.Byte") || + type.equals("java.lang.Short") || + type.equals("java.lang.Long") || + type.equals("java.lang.Float")) { // env-ref element ContextEnvironment resource = new ContextEnvironment(); - resource.setName(annotation.name()); - resource.setType(annotation.type().getCanonicalName()); + resource.setName(name); + resource.setType(type); resource.setDescription(annotation.description()); @@ -280,37 +328,34 @@ public class WebAnnotationSet { context.getNamingResources().addEnvironment(resource); - } else if (annotation.type().getCanonicalName().equals("javax.xml.rpc.Service")) { + } else if (type.equals("javax.xml.rpc.Service")) { // service-ref element ContextService service = new ContextService(); - service.setName(annotation.name()); + service.setName(name); service.setWsdlfile(annotation.mappedName()); - service.setType(annotation.type().getCanonicalName()); + service.setType(type); service.setDescription(annotation.description()); context.getNamingResources().addService(service); - } else if (annotation.type().getCanonicalName().equals("javax.sql.DataSource") || - annotation.type().getCanonicalName().equals("javax.jms.ConnectionFactory") || - annotation.type().getCanonicalName() - .equals("javax.jms.QueueConnectionFactory") || - annotation.type().getCanonicalName() - .equals("javax.jms.TopicConnectionFactory") || - annotation.type().getCanonicalName().equals("javax.mail.Session") || - annotation.type().getCanonicalName().equals("java.net.URL") || - annotation.type().getCanonicalName() - .equals("javax.resource.cci.ConnectionFactory") || - annotation.type().getCanonicalName().equals("org.omg.CORBA_2_3.ORB") || - annotation.type().getCanonicalName().endsWith("ConnectionFactory")) { + } else if (type.equals("javax.sql.DataSource") || + type.equals("javax.jms.ConnectionFactory") || + type.equals("javax.jms.QueueConnectionFactory") || + type.equals("javax.jms.TopicConnectionFactory") || + type.equals("javax.mail.Session") || + type.equals("java.net.URL") || + type.equals("javax.resource.cci.ConnectionFactory") || + type.equals("org.omg.CORBA_2_3.ORB") || + type.endsWith("ConnectionFactory")) { // resource-ref element ContextResource resource = new ContextResource(); - resource.setName(annotation.name()); - resource.setType(annotation.type().getCanonicalName()); + resource.setName(name); + resource.setType(type); if (annotation.authenticationType() == Resource.AuthenticationType.CONTAINER) { @@ -327,31 +372,29 @@ public class WebAnnotationSet { context.getNamingResources().addResource(resource); - } else if (annotation.type().getCanonicalName().equals("javax.jms.Queue") || - annotation.type().getCanonicalName().equals("javax.jms.Topic")) { + } else if (type.equals("javax.jms.Queue") || + type.equals("javax.jms.Topic")) { // message-destination-ref MessageDestinationRef resource = new MessageDestinationRef(); - resource.setName(annotation.name()); - resource.setType(annotation.type().getCanonicalName()); + resource.setName(name); + resource.setType(type); resource.setUsage(annotation.mappedName()); resource.setDescription(annotation.description()); context.getNamingResources().addMessageDestinationRef(resource); - } else if (annotation.type().getCanonicalName() - .equals("javax.resource.cci.InteractionSpec") || - annotation.type().getCanonicalName() - .equals("javax.transaction.UserTransaction") || + } else if (type.equals("javax.resource.cci.InteractionSpec") || + type.equals("javax.transaction.UserTransaction") || true) { // resource-env-ref ContextResourceEnvRef resource = new ContextResourceEnvRef(); - resource.setName(annotation.name()); - resource.setType(annotation.type().getCanonicalName()); + resource.setName(name); + resource.setType(type); resource.setProperty("mappedName", annotation.mappedName()); resource.setDescription(annotation.description()); @@ -359,9 +402,87 @@ public class WebAnnotationSet { context.getNamingResources().addResourceEnvRef(resource); } + } + + + private static void checkBeanNamingConventions(Method method) { + if (!method.getName().startsWith("set") + || method.getName().length() < 4 + || method.getParameterTypes().length != 1 + || !method.getReturnType().getName().equals("void")) { + throw new IllegalArgumentException("Invalid method resource injection annotation."); + } + } + + + private static String getType(Resource annotation, String defaultType) { + String type = annotation.type().getCanonicalName(); + if (type == null || type.equals("java.lang.Object")) { + if (defaultType != null) { + type = defaultType; + } + } + return type; + } + + + private static String getName(Resource annotation, String defaultName) { + String name = annotation.name(); + if (name == null || name.equals("")) { + if (defaultName != null) { + name = defaultName; + } + } + return name; + } + + + private static Field[] getDeclaredFields(Class<?> classClass) { + Field[] fields = null; + if (Globals.IS_SECURITY_ENABLED) { + final Class<?> clazz = classClass; + fields = AccessController.doPrivileged( + new PrivilegedAction<Field[]>(){ + @Override + public Field[] run(){ + return clazz.getDeclaredFields(); + } + }); + } else { + fields = classClass.getDeclaredFields(); + } + return fields; + } + private static Method[] getDeclaredMethods(Class<?> classClass) { + Method[] methods = null; + if (Globals.IS_SECURITY_ENABLED) { + final Class<?> clazz = classClass; + methods = AccessController.doPrivileged( + new PrivilegedAction<Method[]>(){ + @Override + public Method[] run(){ + return clazz.getDeclaredMethods(); + } + }); + } else { + methods = classClass.getDeclaredMethods(); + } + return methods; } + private static Class<?> loadClass(Context context, String fileString) { + ClassLoader classLoader = context.getLoader().getClassLoader(); + Class<?> classClass = null; + try { + classClass = classLoader.loadClass(fileString); + } catch (ClassNotFoundException e) { + // We do nothing + } catch (NoClassDefFoundError e) { + // We do nothing + } + return classClass; + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org