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]