Author: remm
Date: Sun Apr  9 09:38:09 2006
New Revision: 392775

URL: http://svn.apache.org/viewcvs?rev=392775&view=rev
Log:
- Add resource injection (note: most annotations are not supported, including 
web services,
  JPA, EJB, etc), as well as PostCreate and PreDestroy.
- If I understand the spec correctly, if using metadata-complete = true, then 
even PostCreate and
  PreDestroy must be ignored.
- Not tested yet (but it doesn't break when not using annotations).
- Based on a patch submitted by Fabien Carrion.

Added:
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/util/AnnotationProcessor.java
Modified:
    
tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/ApplicationFilterConfig.java
    
tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/NamingContextListener.java
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardContext.java
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardWrapper.java

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/ApplicationFilterConfig.java
URL: 
http://svn.apache.org/viewcvs/tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/ApplicationFilterConfig.java?rev=392775&r1=392774&r2=392775&view=diff
==============================================================================
--- 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/ApplicationFilterConfig.java 
(original)
+++ 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/ApplicationFilterConfig.java 
Sun Apr  9 09:38:09 2006
@@ -19,10 +19,12 @@
 
 
 import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.Map;
 
+import javax.naming.NamingException;
 import javax.servlet.Filter;
 import javax.servlet.FilterConfig;
 import javax.servlet.ServletContext;
@@ -31,6 +33,7 @@
 import org.apache.catalina.Context;
 import org.apache.catalina.deploy.FilterDef;
 import org.apache.catalina.security.SecurityUtil;
+import org.apache.catalina.util.AnnotationProcessor;
 import org.apache.catalina.util.Enumerator;
 import org.apache.tomcat.util.log.SystemLogHandler;
 
@@ -66,11 +69,13 @@
      * @exception InstantiationException if an exception occurs while
      *  instantiating the filter object
      * @exception ServletException if thrown by the filter's init() method
+     * @throws NamingException 
+     * @throws InvocationTargetException 
      */
     public ApplicationFilterConfig(Context context, FilterDef filterDef)
         throws ClassCastException, ClassNotFoundException,
                IllegalAccessException, InstantiationException,
-               ServletException {
+               ServletException, InvocationTargetException, NamingException {
 
         super();
         this.context = context;
@@ -186,9 +191,12 @@
      * @exception InstantiationException if an exception occurs while
      *  instantiating the filter object
      * @exception ServletException if thrown by the filter's init() method
+     * @throws NamingException 
+     * @throws InvocationTargetException 
      */
     Filter getFilter() throws ClassCastException, ClassNotFoundException,
-        IllegalAccessException, InstantiationException, ServletException {
+        IllegalAccessException, InstantiationException, ServletException, 
+        InvocationTargetException, NamingException {
 
         // Return the existing filter instance, if any
         if (this.filter != null)
@@ -208,8 +216,16 @@
         // Instantiate a new instance of this filter and return it
         Class clazz = classLoader.loadClass(filterClass);
         this.filter = (Filter) clazz.newInstance();
+        if (!context.getIgnoreAnnotations()) {
+            if (context instanceof StandardContext 
+                    && ((StandardContext) context).getNamingContextListener() 
!= null) {
+                AnnotationProcessor.injectNamingResources
+                    (((StandardContext) 
context).getNamingContextListener().getEnvContext(), this.filter);
+            }
+            AnnotationProcessor.postConstruct(this.filter);
+        }
         if (context instanceof StandardContext &&
-            ((StandardContext)context).getSwallowOutput()) {
+            ((StandardContext) context).getSwallowOutput()) {
             try {
                 SystemLogHandler.startCapture();
                 filter.init(this);
@@ -244,8 +260,8 @@
     void release() {
 
         if (this.filter != null){
-             if( System.getSecurityManager() != null) {
-                try{
+            if (System.getSecurityManager() != null) {
+                try {
                     SecurityUtil.doAsPrivilege("destroy", filter); 
                 } catch(java.lang.Exception ex){                    
                     
context.getLogger().error("ApplicationFilterConfig.doAsPrivilege", ex);
@@ -254,6 +270,13 @@
             } else { 
                 filter.destroy();
             }
+            if (!context.getIgnoreAnnotations()) {
+                try {
+                    AnnotationProcessor.preDestroy(this.filter);
+                } catch (Exception e) {
+                    
context.getLogger().error("ApplicationFilterConfig.preDestroy", e);
+                }
+            }
         }
         this.filter = null;
 
@@ -274,18 +297,20 @@
      * @exception InstantiationException if an exception occurs while
      *  instantiating the filter object
      * @exception ServletException if thrown by the filter's init() method
+     * @throws NamingException 
+     * @throws InvocationTargetException 
      */
     void setFilterDef(FilterDef filterDef)
         throws ClassCastException, ClassNotFoundException,
                IllegalAccessException, InstantiationException,
-               ServletException {
+               ServletException, InvocationTargetException, NamingException {
 
         this.filterDef = filterDef;
         if (filterDef == null) {
 
             // Release any previously allocated filter instance
             if (this.filter != null){
-                 if( System.getSecurityManager() != null) {
+                if( System.getSecurityManager() != null) {
                     try{
                         SecurityUtil.doAsPrivilege("destroy", filter);  
                     } catch(java.lang.Exception ex){    
@@ -294,6 +319,13 @@
                     SecurityUtil.remove(filter);
                 } else { 
                     filter.destroy();
+                }
+                if (!context.getIgnoreAnnotations()) {
+                    try {
+                        AnnotationProcessor.preDestroy(this.filter);
+                    } catch (Exception e) {
+                        
context.getLogger().error("ApplicationFilterConfig.preDestroy", e);
+                    }
                 }
             }
             this.filter = null;

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/NamingContextListener.java
URL: 
http://svn.apache.org/viewcvs/tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/NamingContextListener.java?rev=392775&r1=392774&r2=392775&view=diff
==============================================================================
--- 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/NamingContextListener.java 
(original)
+++ 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/NamingContextListener.java 
Sun Apr  9 09:38:09 2006
@@ -165,6 +165,14 @@
             log.debug( "setName " + name);
     }
 
+    
+    /**
+     * Return the env context.
+     */
+    public javax.naming.Context getEnvContext() {
+        return this.envCtx;
+    }
+    
 
     /**
      * Return the associated naming context.

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardContext.java
URL: 
http://svn.apache.org/viewcvs/tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardContext.java?rev=392775&r1=392774&r2=392775&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardContext.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardContext.java Sun 
Apr  9 09:38:09 2006
@@ -84,6 +84,7 @@
 import org.apache.catalina.session.StandardManager;
 import org.apache.catalina.startup.ContextConfig;
 import org.apache.catalina.startup.TldConfig;
+import org.apache.catalina.util.AnnotationProcessor;
 import org.apache.catalina.util.CharsetMapper;
 import org.apache.catalina.util.ExtensionValidator;
 import org.apache.catalina.util.RequestUtil;
@@ -3710,6 +3711,14 @@
             try {
                 Class clazz = loader.loadClass(listeners[i]);
                 results[i] = clazz.newInstance();
+                // Annotation processing
+                if (!getIgnoreAnnotations()) {
+                    if (getNamingContextListener() != null) {
+                        AnnotationProcessor.injectNamingResources
+                            (getNamingContextListener().getEnvContext(), 
results[i]);
+                    }
+                    AnnotationProcessor.postConstruct(results[i]);
+                }
             } catch (Throwable t) {
                 getLogger().error
                     (sm.getString("standardContext.applicationListener",
@@ -3787,31 +3796,60 @@
 
         boolean ok = true;
         Object listeners[] = getApplicationLifecycleListeners();
-        if (listeners == null)
-            return (ok);
-        ServletContextEvent event =
-          new ServletContextEvent(getServletContext());
-        for (int i = 0; i < listeners.length; i++) {
-            int j = (listeners.length - 1) - i;
-            if (listeners[j] == null)
-                continue;
-            if (!(listeners[j] instanceof ServletContextListener))
-                continue;
-            ServletContextListener listener =
-                (ServletContextListener) listeners[j];
-            try {
-                fireContainerEvent("beforeContextDestroyed", listener);
-                listener.contextDestroyed(event);
-                fireContainerEvent("afterContextDestroyed", listener);
-            } catch (Throwable t) {
-                fireContainerEvent("afterContextDestroyed", listener);
-                getLogger().error
-                    (sm.getString("standardContext.listenerStop",
-                                  listeners[j].getClass().getName()), t);
-                ok = false;
+        if (listeners != null) {
+            ServletContextEvent event =
+                new ServletContextEvent(getServletContext());
+            for (int i = 0; i < listeners.length; i++) {
+                int j = (listeners.length - 1) - i;
+                if (listeners[j] == null)
+                    continue;
+                if (listeners[j] instanceof ServletContextListener) {
+                    ServletContextListener listener =
+                        (ServletContextListener) listeners[j];
+                    try {
+                        fireContainerEvent("beforeContextDestroyed", listener);
+                        listener.contextDestroyed(event);
+                        fireContainerEvent("afterContextDestroyed", listener);
+                    } catch (Throwable t) {
+                        fireContainerEvent("afterContextDestroyed", listener);
+                        getLogger().error
+                            (sm.getString("standardContext.listenerStop",
+                                listeners[j].getClass().getName()), t);
+                        ok = false;
+                    }
+                }
+                // Annotation processing
+                if (!getIgnoreAnnotations()) {
+                    try {
+                        AnnotationProcessor.preDestroy(listeners[j]);
+                    } catch (Throwable t) {
+                        getLogger().error
+                            (sm.getString("standardContext.listenerStop",
+                                listeners[j].getClass().getName()), t);
+                        ok = false;
+                    }
+                }
             }
         }
 
+        // Annotation processing
+        listeners = getApplicationEventListeners();
+        if (!getIgnoreAnnotations() && listeners != null) {
+            for (int i = 0; i < listeners.length; i++) {
+                int j = (listeners.length - 1) - i;
+                if (listeners[j] == null)
+                    continue;
+                try {
+                    AnnotationProcessor.preDestroy(listeners[j]);
+                } catch (Throwable t) {
+                    getLogger().error
+                        (sm.getString("standardContext.listenerStop",
+                            listeners[j].getClass().getName()), t);
+                    ok = false;
+                }
+            }
+        }
+        
         setApplicationEventListeners(null);
         setApplicationLifecycleListeners(null);
 
@@ -4794,6 +4832,14 @@
     return namingContextName;
     }
 
+    
+    /**
+     * Naming context listener accessor.
+     */
+    public NamingContextListener getNamingContextListener() {
+        return namingContextListener;
+    }
+    
 
     /**
      * Return the request processing paused flag for this Context.

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardWrapper.java
URL: 
http://svn.apache.org/viewcvs/tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardWrapper.java?rev=392775&r1=392774&r2=392775&view=diff
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardWrapper.java 
(original)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/StandardWrapper.java Sun 
Apr  9 09:38:09 2006
@@ -53,6 +53,7 @@
 import org.apache.catalina.Loader;
 import org.apache.catalina.Wrapper;
 import org.apache.catalina.security.SecurityUtil;
+import org.apache.catalina.util.AnnotationProcessor;
 import org.apache.catalina.util.Enumerator;
 import org.apache.catalina.util.InstanceSupport;
 import org.apache.tomcat.util.IntrospectionUtils;
@@ -1053,6 +1054,15 @@
             // Instantiate and initialize an instance of the servlet class 
itself
             try {
                 servlet = (Servlet) classClass.newInstance();
+                // Annotation processing
+                if (!((Context) getParent()).getIgnoreAnnotations()) {
+                    if (getParent() instanceof StandardContext 
+                            && ((StandardContext) 
getParent()).getNamingContextListener() != null) {
+                        AnnotationProcessor.injectNamingResources
+                            (((StandardContext) 
getParent()).getNamingContextListener().getEnvContext(), servlet);
+                    }
+                    AnnotationProcessor.postConstruct(servlet);
+                }
             } catch (ClassCastException e) {
                 unavailable(null);
                 // Restore the context ClassLoader
@@ -1330,9 +1340,15 @@
             } else {
                 instance.destroy();
             }
-
+            
             instanceSupport.fireInstanceEvent
               (InstanceEvent.AFTER_DESTROY_EVENT, instance);
+
+            // Annotation processing
+            if (!((Context) getParent()).getIgnoreAnnotations()) {
+                AnnotationProcessor.preDestroy(instance);
+            }
+
         } catch (Throwable t) {
             instanceSupport.fireInstanceEvent
               (InstanceEvent.AFTER_DESTROY_EVENT, instance, t);
@@ -1367,12 +1383,16 @@
             try {
                 Thread.currentThread().setContextClassLoader(classLoader);
                 while (!instancePool.isEmpty()) {
-                    if( System.getSecurityManager() != null) {
-                        SecurityUtil.doAsPrivilege("destroy",
-                                                   ((Servlet) 
instancePool.pop()));
+                    Servlet s = (Servlet) instancePool.pop();
+                    if (System.getSecurityManager() != null) {
+                        SecurityUtil.doAsPrivilege("destroy", s);
                         SecurityUtil.remove(instance);                         
  
                     } else {
-                        ((Servlet) instancePool.pop()).destroy();
+                        s.destroy();
+                    }
+                    // Annotation processing
+                    if (!((Context) getParent()).getIgnoreAnnotations()) {
+                        AnnotationProcessor.preDestroy(s);
                     }
                 }
             } catch (Throwable t) {

Added: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/util/AnnotationProcessor.java
URL: 
http://svn.apache.org/viewcvs/tomcat/tc6.0.x/trunk/java/org/apache/catalina/util/AnnotationProcessor.java?rev=392775&view=auto
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/util/AnnotationProcessor.java 
(added)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/util/AnnotationProcessor.java 
Sun Apr  9 09:38:09 2006
@@ -0,0 +1,205 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.catalina.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import javax.naming.NamingException;
+
+import org.apache.tomcat.util.IntrospectionUtils;
+
+
+/**
+ * Verify the annotation and Process it.
+ *
+ * @author    Fabien Carrion
+ * @version   $Revision: 303236 $, $Date: 2006-03-09 16:46:52 -0600 (Thu, 09 
Mar 2006) $
+ */
+public class AnnotationProcessor {
+    
+
+    /**
+     * Call postConstruct method on the specified instance.
+     */
+    public static void postConstruct(Object instance)
+        throws IllegalAccessException, InvocationTargetException {
+        
+        Method[] methods = IntrospectionUtils.findMethods(instance.getClass());
+        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];
+            }
+        }
+
+        // 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);
+        }
+        
+    }
+    
+    
+    /**
+     * Call preDestroy method on the specified instance.
+     */
+    public static void preDestroy(Object instance)
+        throws IllegalAccessException, InvocationTargetException {
+        
+        Method[] methods = IntrospectionUtils.findMethods(instance.getClass());
+        Method preDestroy = null;
+        for (int i = 0; i < methods.length; i++) {
+            if (methods[i].isAnnotationPresent(PostConstruct.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];
+            }
+        }
+
+        // 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);
+        }
+        
+    }
+    
+    
+    /**
+     * Inject resources in specified instance.
+     */
+    public static void injectNamingResources(javax.naming.Context context, 
Object instance)
+        throws IllegalAccessException, InvocationTargetException, 
NamingException {
+        
+        // Initialize fields annotations
+        Field[] fields = instance.getClass().getFields();
+        for (int i = 0; i < fields.length; i++) {
+            if (fields[i].isAnnotationPresent(Resource.class)) {
+                Resource annotation = (Resource) 
fields[i].getAnnotation(Resource.class);
+                lookupFieldResource(context, instance, fields[i], 
annotation.name());
+            }
+            /*
+            if (f.isAnnotationPresent(EJB.class)) {
+                EJB annotation = (EJB) f.getAnnotation(EJB.class);
+                lookupOnFieldResource(f, annotation.name());
+            }
+            
+            if (f.isAnnotationPresent(WebServiceRef.class)) {
+                WebServiceRef annotation = (WebServiceRef) 
+                f.getAnnotation(WebServiceRef.class);
+                lookupOnFieldResource(f, annotation.name());
+            }
+            */
+        }
+        
+        // Initialize methods annotations
+        Method[] methods = IntrospectionUtils.findMethods(instance.getClass());
+        for (int i = 0; i < methods.length; i++) {
+            if (methods[i].isAnnotationPresent(Resource.class)) {
+                Resource annotation = (Resource) 
methods[i].getAnnotation(Resource.class);
+                lookupMethodResource(context, instance, methods[i], 
annotation.name());
+            }
+            /*
+            if (m.isAnnotationPresent(EJB.class)) {
+                EJB annotation = (EJB) m.getAnnotation(EJB.class);
+                lookupOnMethodResource(m, annotation.name());
+            }
+            if (m.isAnnotationPresent(WebServiceRef.class)) {
+                WebServiceRef annotation = (WebServiceRef) 
+                m.getAnnotation(WebServiceRef.class);
+                lookupOnMethodResource(m, annotation.name());
+            }
+            */
+        }            
+
+    }
+    
+    
+    protected static void lookupFieldResource(javax.naming.Context context, 
+            Object instance, Field f, String name)
+        throws NamingException, IllegalAccessException {
+    
+        Object lookedupResource = null;
+        boolean accessibility = false;
+        
+        if ((name != null) &&
+                (name.length() > 0)) {
+            lookedupResource = context.lookup(name);
+        } else {
+            lookedupResource = context.lookup(instance.getClass().getName() + 
"/" + f.getName());
+        }
+        
+        accessibility = f.isAccessible();
+        f.setAccessible(true);
+        f.set(instance, lookedupResource);
+        f.setAccessible(accessibility);
+    }
+
+
+    protected static void lookupMethodResource(javax.naming.Context context, 
+            Object instance, Method method, String name)
+        throws NamingException, IllegalAccessException, 
InvocationTargetException {
+        
+        if (!method.getName().startsWith("set") 
+                || method.getParameterTypes().length != 1
+                || !method.getReturnType().getName().equals("void")) {
+            throw new IllegalArgumentException("Invalid method resource 
injection annotation");
+        }
+        
+        Object lookedupResource = null;
+        boolean accessibility = false;
+        
+        if ((name != null) &&
+                (name.length() > 0)) {
+            lookedupResource = context.lookup(name);
+        } else {
+            lookedupResource = 
+                context.lookup(instance.getClass().getName() + "/" + 
method.getName().substring(3));
+        }
+        
+        accessibility = method.isAccessible();
+        method.setAccessible(true);
+        method.invoke(instance, lookedupResource);
+        method.setAccessible(accessibility);
+    }
+    
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to