You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2012/03/27 21:20:10 UTC

svn commit: r1305965 - /tomcat/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java

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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org