1 16 package org.apache.cocoon.servlet; 17 18 import java.io.File ; 19 import java.io.FileReader ; 20 import java.io.FilenameFilter ; 21 import java.io.IOException ; 22 import java.io.LineNumberReader ; 23 import java.lang.reflect.Constructor ; 24 import java.lang.reflect.InvocationTargetException ; 25 import java.net.MalformedURLException ; 26 import java.net.URL ; 27 import java.util.ArrayList ; 28 import java.util.List ; 29 30 import javax.servlet.Servlet ; 31 import javax.servlet.ServletConfig ; 32 import javax.servlet.ServletException ; 33 import javax.servlet.ServletRequest ; 34 import javax.servlet.ServletResponse ; 35 import javax.servlet.http.HttpServlet ; 36 37 65 66 public class ParanoidCocoonServlet extends HttpServlet { 67 68 71 public static final String DEFAULT_SERVLET_CLASS = "org.apache.cocoon.servlet.CocoonServlet"; 72 73 protected static final String CONTEXT_PREFIX = "context:"; 74 75 protected static final String FILE_PREFIX = "file:"; 76 77 protected Servlet servlet; 78 79 protected ClassLoader classloader; 80 81 public void init(ServletConfig config) throws ServletException { 82 83 super.init(config); 84 85 final String externalClasspath = config.getInitParameter("paranoid-classpath"); 90 final URL [] classPath = (externalClasspath == null) 91 ? getClassPath(getContextDir()) 92 : getClassPath(externalClasspath, getContextDir()); 93 94 95 final String 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 servletName = config.getInitParameter("servlet-class"); 103 if (servletName == null) { 104 servletName = DEFAULT_SERVLET_CLASS; 105 } 106 log("Loading servlet class " + servletName); 107 108 109 try { 111 112 Class servletClass = this.classloader.loadClass(servletName); 113 this.servlet = (Servlet ) servletClass.newInstance(); 114 115 } catch (Exception e) { 116 throw new ServletException ("Cannot load servlet " + servletName, e); 117 } 118 119 final ClassLoader old = Thread.currentThread().getContextClassLoader(); 123 try { 124 Thread.currentThread().setContextClassLoader(this.classloader); 125 126 this.initServlet(); 128 } finally { 129 Thread.currentThread().setContextClassLoader(old); 130 } 131 132 } 133 134 140 protected void initServlet() throws ServletException { 141 this.servlet.init(this.getServletConfig()); 142 } 143 144 150 protected File getContextDir() throws ServletException { 151 String result = getServletContext().getRealPath("/"); 152 if (result == null) { 153 throw new ServletException (this.getClass().getName() + " cannot run in an undeployed WAR file"); 154 } 155 return new File (result); 156 } 157 158 protected URL [] getClassPath(final File contextDir) throws ServletException { 159 List urlList = new ArrayList (); 160 161 try { 162 File classDir = new File (contextDir + "/WEB-INF/classes"); 163 if (classDir.exists()) { 164 if (!classDir.isDirectory()) { 165 throw new ServletException (classDir + " exists but is not a directory"); 166 } 167 168 URL classURL = classDir.toURL(); 169 log("Adding class directory " + classURL); 170 urlList.add(classURL); 171 172 } 173 174 File libDir = new File (contextDir + "/WEB-INF/lib"); 176 File [] libraries = libDir.listFiles(new JarFileFilter()); 177 178 for (int i = 0; i < libraries.length; i++) { 179 URL lib = libraries[i].toURL(); 180 log("Adding class library " + lib); 181 urlList.add(lib); 182 } 183 } catch (MalformedURLException mue) { 184 throw new ServletException (mue); 185 } 186 187 URL [] urls = (URL []) urlList.toArray(new URL [urlList.size()]); 188 189 return urls; 190 } 191 192 protected URL [] getClassPath(final String externalClasspath, final File contextDir) throws ServletException { 193 final List urlList = new ArrayList (); 194 195 File file = new File (externalClasspath); 196 if (!file.isAbsolute()) { 197 file = new File (contextDir, externalClasspath); 198 } 199 200 log("Adding classpath from " + file); 201 try { 202 FileReader fileReader = new FileReader (file); 203 LineNumberReader lineReader = new LineNumberReader (fileReader); 204 205 String 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 url = new File (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 dir = new File (line); 224 File [] 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 url = libraries[i].toURL(); 228 urlList.add(url); 229 } 230 } else if (line.startsWith("#")) { 231 } else { 233 final URL 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 entry = new File (line); 240 lib = entry.toURL(); 241 } else { 242 lib = new URL (line); 243 } 244 log("Adding class URL " + lib); 245 urlList.add(lib); 246 } 247 } 248 } while (line != null); 249 lineReader.close(); 250 } catch (IOException io) { 251 throw new ServletException (io); 252 } 253 254 URL [] urls = (URL []) urlList.toArray(new URL [urlList.size()]); 255 256 return urls; 257 } 258 259 protected ClassLoader createClassLoader(final String className, final URL [] classPath) throws ServletException { 260 if (className != null) { 261 try { 262 final Class classLoaderClass = Class.forName(className); 263 final Class [] parameterClasses = new Class [] { ClassLoader .class }; 264 final Constructor constructor = classLoaderClass.getConstructor(parameterClasses); 265 final Object [] parameters = new Object [] { this.getClass().getClassLoader() }; 266 final ClassLoader classloader = (ClassLoader ) constructor.newInstance(parameters); 267 return classloader; 268 } catch (InstantiationException e) { 269 throw new ServletException ("", e); 270 } catch (IllegalAccessException e) { 271 throw new ServletException ("", e); 272 } catch (ClassNotFoundException e) { 273 throw new ServletException ("", e); 274 } catch (SecurityException e) { 275 throw new ServletException ("", e); 276 } catch (NoSuchMethodException e) { 277 throw new ServletException ("", e); 278 } catch (IllegalArgumentException e) { 279 throw new ServletException ("", e); 280 } catch (InvocationTargetException e) { 281 throw new ServletException ("", e); 282 } 283 } else { 284 return ParanoidClassLoader.newInstance(classPath, this.getClass().getClassLoader()); 285 } 286 } 287 288 289 295 protected ClassLoader getClassLoader(File contextDir) throws ServletException { 296 return createClassLoader(null, getClassPath(contextDir)); 297 } 298 299 304 protected ClassLoader getClassLoader(final String externalClasspath, final File contextDir) throws ServletException { 305 return createClassLoader(null, getClassPath(externalClasspath, contextDir)); 306 } 307 308 311 public void service(ServletRequest request, ServletResponse response) throws ServletException , IOException { 312 313 final ClassLoader 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 325 public void destroy() { 326 327 if (this.servlet != null) { 328 final ClassLoader 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 { 341 public boolean accept(File dir, String name) { 342 return name.endsWith(".zip") || name.endsWith(".jar"); 343 } 344 } 345 346 } 347 348 | Popular Tags |