KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > servlet > ParanoidCocoonServlet


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.servlet;
17
18 import java.io.File JavaDoc;
19 import java.io.FileReader JavaDoc;
20 import java.io.FilenameFilter JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.io.LineNumberReader JavaDoc;
23 import java.lang.reflect.Constructor JavaDoc;
24 import java.lang.reflect.InvocationTargetException JavaDoc;
25 import java.net.MalformedURLException JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.List JavaDoc;
29
30 import javax.servlet.Servlet JavaDoc;
31 import javax.servlet.ServletConfig JavaDoc;
32 import javax.servlet.ServletException JavaDoc;
33 import javax.servlet.ServletRequest JavaDoc;
34 import javax.servlet.ServletResponse JavaDoc;
35 import javax.servlet.http.HttpServlet JavaDoc;
36
37 /**
38  * This servlet builds a classloading sandbox and runs another servlet inside
39  * that sandbox. The purpose is to shield the libraries and classes shipped with
40  * the web application from any other classes with the same name that may exist
41  * in the system, such as Xerces and Xalan versions included in JDK 1.4.
42  * <p>
43  * This servlet propagates all initialisation parameters to the sandboxed
44  * servlet, and accepts the parameters <code>servlet-class</code> and
45  * <code>paranoid-classpath</code>.
46  * <ul>
47  * <li><code>servlet-class</code> defines the sandboxed servlet class, the
48  * default is {@link CocoonServlet}
49  * <li><code>paranoid-classpath</code> expects the name of a text file that
50  * can contain lines begining with
51  * <code>class-dir:<code> (directory containing classes),
52  * <code>lib-dir:<code> (directory containing JAR or ZIP libraries) and <code>#</code>
53  * (for comments). <br/>
54  * All other lines are considered as URLs.
55  * <br/>
56  * It is also possible to use a the pseudo protocol prefix<code>context:/<code> which
57  * is resolved to the basedir of the servlet context.
58  * </ul>
59  *
60  * @author <a HREF="mailto:bloritsch@apache.org">Berin Loritsch</a>
61  * @author <a HREF="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
62  * @author <a HREF="mailto:tcurdt@apache.org">Torsten Curdt</a>
63  * @version CVS $Id: ParanoidCocoonServlet.java 125257 2005-01-15 07:59:07Z antonio $
64  */

65
66 public class ParanoidCocoonServlet extends HttpServlet JavaDoc {
67
68     /**
69      * The name of the actual servlet class.
70      */

71     public static final String JavaDoc DEFAULT_SERVLET_CLASS = "org.apache.cocoon.servlet.CocoonServlet";
72
73     protected static final String JavaDoc CONTEXT_PREFIX = "context:";
74
75     protected static final String JavaDoc FILE_PREFIX = "file:";
76
77     protected Servlet JavaDoc servlet;
78
79     protected ClassLoader JavaDoc classloader;
80
81     public void init(ServletConfig JavaDoc config) throws ServletException JavaDoc {
82
83         super.init(config);
84
85         // Create the classloader in which we will load the servlet
86
// this can either be specified by an external file configured
87
// as a parameter in web.xml or (the default) all jars and
88
// classes from WEB-INF/lib and WEB-INF/classes are used.
89
final String JavaDoc externalClasspath = config.getInitParameter("paranoid-classpath");
90         final URL JavaDoc[] classPath = (externalClasspath == null)
91             ? getClassPath(getContextDir())
92             : getClassPath(externalClasspath, getContextDir());
93
94             
95         final String JavaDoc classLoaderName = config.getInitParameter("classloader-class");
96         if (classLoaderName != null) {
97             log("Using classloader " + classLoaderName);
98         }
99         this.classloader = createClassLoader(classLoaderName, classPath);
100
101         
102         String JavaDoc servletName = config.getInitParameter("servlet-class");
103         if (servletName == null) {
104             servletName = DEFAULT_SERVLET_CLASS;
105         }
106         log("Loading servlet class " + servletName);
107
108         
109         // Create the servlet
110
try {
111
112             Class JavaDoc servletClass = this.classloader.loadClass(servletName);
113             this.servlet = (Servlet JavaDoc) servletClass.newInstance();
114
115         } catch (Exception JavaDoc e) {
116             throw new ServletException JavaDoc("Cannot load servlet " + servletName, e);
117         }
118
119         // Always set the context classloader. JAXP uses it to find a
120
// ParserFactory,
121
// and thus fails if it's not set to the webapp classloader.
122
final ClassLoader JavaDoc old = Thread.currentThread().getContextClassLoader();
123         try {
124             Thread.currentThread().setContextClassLoader(this.classloader);
125
126             // Inlitialize the actual servlet
127
this.initServlet();
128         } finally {
129             Thread.currentThread().setContextClassLoader(old);
130         }
131
132     }
133
134     /**
135      * Initialize the wrapped servlet. Subclasses (see {@link BootstrapServlet}
136      * change the <code>ServletConfig</code> given to the servlet.
137      *
138      * @throws ServletException
139      */

140     protected void initServlet() throws ServletException JavaDoc {
141         this.servlet.init(this.getServletConfig());
142     }
143
144     /**
145      * Get the web application context directory.
146      *
147      * @return the context dir
148      * @throws ServletException
149      */

150     protected File JavaDoc getContextDir() throws ServletException JavaDoc {
151         String JavaDoc result = getServletContext().getRealPath("/");
152         if (result == null) {
153             throw new ServletException JavaDoc(this.getClass().getName() + " cannot run in an undeployed WAR file");
154         }
155         return new File JavaDoc(result);
156     }
157
158     protected URL JavaDoc[] getClassPath(final File JavaDoc contextDir) throws ServletException JavaDoc {
159         List JavaDoc urlList = new ArrayList JavaDoc();
160
161         try {
162             File JavaDoc classDir = new File JavaDoc(contextDir + "/WEB-INF/classes");
163             if (classDir.exists()) {
164                 if (!classDir.isDirectory()) {
165                     throw new ServletException JavaDoc(classDir + " exists but is not a directory");
166                 }
167
168                 URL JavaDoc classURL = classDir.toURL();
169                 log("Adding class directory " + classURL);
170                 urlList.add(classURL);
171
172             }
173
174             // List all .jar and .zip
175
File JavaDoc libDir = new File JavaDoc(contextDir + "/WEB-INF/lib");
176             File JavaDoc[] libraries = libDir.listFiles(new JarFileFilter());
177
178             for (int i = 0; i < libraries.length; i++) {
179                 URL JavaDoc lib = libraries[i].toURL();
180                 log("Adding class library " + lib);
181                 urlList.add(lib);
182             }
183         } catch (MalformedURLException JavaDoc mue) {
184             throw new ServletException JavaDoc(mue);
185         }
186
187         URL JavaDoc[] urls = (URL JavaDoc[]) urlList.toArray(new URL JavaDoc[urlList.size()]);
188
189         return urls;
190     }
191     
192     protected URL JavaDoc[] getClassPath(final String JavaDoc externalClasspath, final File JavaDoc contextDir) throws ServletException JavaDoc {
193         final List JavaDoc urlList = new ArrayList JavaDoc();
194
195         File JavaDoc file = new File JavaDoc(externalClasspath);
196         if (!file.isAbsolute()) {
197             file = new File JavaDoc(contextDir, externalClasspath);
198         }
199
200         log("Adding classpath from " + file);
201         try {
202             FileReader JavaDoc fileReader = new FileReader JavaDoc(file);
203             LineNumberReader JavaDoc lineReader = new LineNumberReader JavaDoc(fileReader);
204
205             String JavaDoc line;
206             do {
207                 line = lineReader.readLine();
208                 if (line != null) {
209                     if (line.startsWith("class-dir:")) {
210                         line = line.substring("class-dir:".length()).trim();
211                         if (line.startsWith(CONTEXT_PREFIX)) {
212                             line = contextDir + line.substring(CONTEXT_PREFIX.length());
213                         }
214                         URL JavaDoc url = new File JavaDoc(line).toURL();
215                         log("Adding class directory " + url);
216                         urlList.add(url);
217
218                     } else if (line.startsWith("lib-dir:")) {
219                         line = line.substring("lib-dir:".length()).trim();
220                         if (line.startsWith(CONTEXT_PREFIX)) {
221                             line = contextDir + line.substring(CONTEXT_PREFIX.length());
222                         }
223                         File JavaDoc dir = new File JavaDoc(line);
224                         File JavaDoc[] libraries = dir.listFiles(new JarFileFilter());
225                         log("Adding " + libraries.length + " libraries from " + dir.toURL());
226                         for (int i = 0; i < libraries.length; i++) {
227                             URL JavaDoc url = libraries[i].toURL();
228                             urlList.add(url);
229                         }
230                     } else if (line.startsWith("#")) {
231                         // skip it (consider it as comment)
232
} else {
233                         // Consider it as a URL
234
final URL JavaDoc lib;
235                         if (line.startsWith(CONTEXT_PREFIX)) {
236                             line = FILE_PREFIX + "/" + contextDir + line.substring(CONTEXT_PREFIX.length()).trim();
237                         }
238                         if (line.indexOf(':') == -1) {
239                             File JavaDoc entry = new File JavaDoc(line);
240                             lib = entry.toURL();
241                         } else {
242                             lib = new URL JavaDoc(line);
243                         }
244                         log("Adding class URL " + lib);
245                         urlList.add(lib);
246                     }
247                 }
248             } while (line != null);
249             lineReader.close();
250         } catch (IOException JavaDoc io) {
251             throw new ServletException JavaDoc(io);
252         }
253
254         URL JavaDoc[] urls = (URL JavaDoc[]) urlList.toArray(new URL JavaDoc[urlList.size()]);
255
256         return urls;
257     }
258
259     protected ClassLoader JavaDoc createClassLoader(final String JavaDoc className, final URL JavaDoc[] classPath) throws ServletException JavaDoc {
260         if (className != null) {
261             try {
262                 final Class JavaDoc classLoaderClass = Class.forName(className);
263                 final Class JavaDoc[] parameterClasses = new Class JavaDoc[] { ClassLoader JavaDoc.class };
264                 final Constructor JavaDoc constructor = classLoaderClass.getConstructor(parameterClasses);
265                 final Object JavaDoc[] parameters = new Object JavaDoc[] { this.getClass().getClassLoader() };
266                 final ClassLoader JavaDoc classloader = (ClassLoader JavaDoc) constructor.newInstance(parameters);
267                 return classloader;
268             } catch (InstantiationException JavaDoc e) {
269                 throw new ServletException JavaDoc("", e);
270             } catch (IllegalAccessException JavaDoc e) {
271                 throw new ServletException JavaDoc("", e);
272             } catch (ClassNotFoundException JavaDoc e) {
273                 throw new ServletException JavaDoc("", e);
274             } catch (SecurityException JavaDoc e) {
275                 throw new ServletException JavaDoc("", e);
276             } catch (NoSuchMethodException JavaDoc e) {
277                 throw new ServletException JavaDoc("", e);
278             } catch (IllegalArgumentException JavaDoc e) {
279                 throw new ServletException JavaDoc("", e);
280             } catch (InvocationTargetException JavaDoc e) {
281                 throw new ServletException JavaDoc("", e);
282             }
283         } else {
284             return ParanoidClassLoader.newInstance(classPath, this.getClass().getClassLoader());
285         }
286     }
287
288     
289     /**
290      * Get the classloader that will be used to create the actual servlet. Its
291      * classpath is defined by the WEB-INF/classes and WEB-INF/lib directories
292      * in the context dir.
293      * @deprecated
294      */

295     protected ClassLoader JavaDoc getClassLoader(File JavaDoc contextDir) throws ServletException JavaDoc {
296         return createClassLoader(null, getClassPath(contextDir));
297     }
298
299     /**
300      * Get the classloader that will be used to create the actual servlet. Its
301      * classpath is defined by an external file.
302      * @deprecated
303      */

304     protected ClassLoader JavaDoc getClassLoader(final String JavaDoc externalClasspath, final File JavaDoc contextDir) throws ServletException JavaDoc {
305         return createClassLoader(null, getClassPath(externalClasspath, contextDir));
306     }
307
308     /**
309      * Service the request by delegating the call to the real servlet
310      */

311     public void service(ServletRequest JavaDoc request, ServletResponse JavaDoc response) throws ServletException JavaDoc, IOException JavaDoc {
312
313         final ClassLoader JavaDoc old = Thread.currentThread().getContextClassLoader();
314         try {
315             Thread.currentThread().setContextClassLoader(this.classloader);
316             this.servlet.service(request, response);
317         } finally {
318             Thread.currentThread().setContextClassLoader(old);
319         }
320     }
321
322     /**
323      * Destroy the actual servlet
324      */

325     public void destroy() {
326
327         if (this.servlet != null) {
328             final ClassLoader JavaDoc old = Thread.currentThread().getContextClassLoader();
329             try {
330                 Thread.currentThread().setContextClassLoader(this.classloader);
331                 this.servlet.destroy();
332             } finally {
333                 Thread.currentThread().setContextClassLoader(old);
334             }
335         }
336
337         super.destroy();
338     }
339
340     private static class JarFileFilter implements FilenameFilter JavaDoc {
341         public boolean accept(File JavaDoc dir, String JavaDoc name) {
342             return name.endsWith(".zip") || name.endsWith(".jar");
343         }
344     }
345
346 }
347
348
Popular Tags