Author: markt
Date: Tue Mar 27 19:27:39 2012
New Revision: 1305971

URL: http://svn.apache.org/viewvc?rev=1305971&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/tc7.0.x/trunk/   (props changed)
    tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java
    tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml

Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
  Merged /tomcat/trunk:r1305965

Modified: 
tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java?rev=1305971&r1=1305970&r2=1305971&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java 
(original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/startup/WebAnnotationSet.java 
Tue Mar 27 19:27:39 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.core.StandardWrapper;
+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;
@@ -43,8 +50,9 @@ 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,32 +115,27 @@ public class WebAnnotationSet {
      */
     protected static void loadApplicationServletAnnotations(Context context) {
         
-        ClassLoader classLoader = context.getLoader().getClassLoader();
-        StandardWrapper wrapper = null;
+        Wrapper wrapper = null;
         Class<?> classClass = null;
         
         Container[] children = context.findChildren();
         for (int i = 0; i < children.length; i++) {
-            if (children[i] instanceof StandardWrapper) {
+            if (children[i] instanceof Wrapper) {
                 
-                wrapper = (StandardWrapper) children[i];
+                wrapper = (Wrapper) children[i];
                 if (wrapper.getServletClass() == null) {
                     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) {
-        
-        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")) {
-            
+        addResource(context, annotation, null, null);
+    }
+
+    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;
+    }
 }

Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1305971&r1=1305970&r2=1305971&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Tue Mar 27 19:27:39 2012
@@ -142,6 +142,11 @@
         <bug>52958</bug>: Fix MBean descriptors for
         <code>org.apache.catalina.realm</code> package. (markt)
       </fix>
+      <fix>
+        <bug>52974</bug>: Fix <code>NameNotFoundException</code> when
+        field/method is annotated with <code>@Resource</code> annotation. Patch
+        provided by Violet Agg. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to