001 package org.beanlet.web;
002
003 import java.io.BufferedReader;
004 import java.io.InputStreamReader;
005 import java.lang.reflect.Constructor;
006 import java.lang.reflect.Modifier;
007 import java.net.URL;
008 import java.security.AccessController;
009 import java.security.PrivilegedActionException;
010 import java.security.PrivilegedExceptionAction;
011 import java.util.Enumeration;
012 import javax.servlet.ServletRequestEvent;
013 import javax.servlet.ServletRequestListener;
014 import org.beanlet.BeanletApplicationException;
015
016 /**
017 * Add the following configuration to the web application's {@code web.xml} file
018 * to support the {@code Request} and {@code Session} beanlet scopes.
019 * </br>
020 * Not required for Servlet 3.0 containers.
021 * </br>
022 * <pre>
023 * <web-app>
024 * ...
025 * <listener>
026 * <listener-class>org.beanlet.web.RequestContextListener<listener-class>
027 * </listener>
028 * ...
029 * </web-app>
030 * </pre>
031 *
032 * @see Request
033 * @see Session
034 * @author Leon van Zantvoort
035 */
036 public class RequestContextListener implements ServletRequestListener {
037
038 private static class LazyHolder {
039 static final Constructor<ServletRequestListener> delegate;
040 static {
041 try {
042 try {
043 Constructor constructor = AccessController.doPrivileged(
044 new PrivilegedExceptionAction<Constructor>() {
045 public Constructor run() throws Exception {
046 String path = "META-INF/services/" +
047 RequestContextListener.class.getName();
048
049 // PERMISSION: java.lang.RuntimePermission getClassLoader
050 ClassLoader loader = Thread.currentThread().
051 getContextClassLoader();
052 final Enumeration<URL> urls;
053 if (loader == null) {
054 urls = RequestContextListener.class.
055 getClassLoader().getResources(path);
056 } else {
057 urls = loader.getResources(path);
058 }
059 while (urls.hasMoreElements()) {
060 URL url = urls.nextElement();
061 BufferedReader reader = new BufferedReader(new InputStreamReader(
062 url.openStream()));
063 try {
064 String className = null;
065 while ((className = reader.readLine()) != null) {
066 final String name = className.trim();
067 if (!name.startsWith("#") && !name.startsWith(";") &&
068 !name.startsWith("//")) {
069 final Class<?> cls;
070 if (loader == null) {
071 cls = Class.forName(name);
072 } else {
073 cls = Class.forName(name, true, loader);
074 }
075 int m = cls.getModifiers();
076 if (ServletRequestListener.class.isAssignableFrom(cls) &&
077 !Modifier.isAbstract(m) &&
078 !Modifier.isInterface(m)) {
079 // PERMISSION: java.lang.RuntimePermission accessDeclaredMembers
080 Constructor constructor = cls.getDeclaredConstructor();
081 // PERMISSION: java.lang.reflect.ReflectPermission suppressAccessChecks
082 if (!Modifier.isPublic(constructor.getModifiers())) {
083 constructor.setAccessible(true);
084 }
085 return constructor;
086 } else {
087 throw new ClassCastException(cls.getName());
088 }
089 }
090 }
091 } finally {
092 reader.close();
093 }
094 }
095 throw new BeanletApplicationException("No " +
096 "ServletRequestListener implementation " +
097 "found.");
098 }
099 });
100 @SuppressWarnings("unchecked")
101 Constructor<ServletRequestListener> tmp =
102 (Constructor<ServletRequestListener>) constructor;
103 delegate = tmp;
104 } catch (PrivilegedActionException e) {
105 throw e.getException();
106 }
107 } catch (BeanletApplicationException e) {
108 throw e;
109 } catch (RuntimeException e) {
110 throw new BeanletApplicationException(e);
111 } catch (Error e) {
112 throw e;
113 } catch (Throwable t) {
114 throw new BeanletApplicationException(t);
115 }
116 }
117 }
118
119 private final ServletRequestListener delegate;
120
121 public RequestContextListener() {
122 try {
123 try {
124 delegate = LazyHolder.delegate.newInstance();
125 } catch (ExceptionInInitializerError e) {
126 try {
127 throw e.getException();
128 } catch (Throwable t) {
129 throw new BeanletApplicationException(t);
130 }
131 }
132 } catch (BeanletApplicationException e) {
133 throw e;
134 } catch (RuntimeException e) {
135 throw e;
136 } catch (Error e) {
137 throw e;
138 } catch (Exception e) {
139 throw new BeanletApplicationException(e);
140 }
141 }
142
143 public void requestInitialized(ServletRequestEvent event) {
144 delegate.requestInitialized(event);
145 }
146
147 public void requestDestroyed(ServletRequestEvent event) {
148 delegate.requestDestroyed(event);
149 }
150 }