1 23 24 package com.sun.enterprise.web.jsp; 25 26 import javax.servlet.Servlet ; 27 import javax.servlet.ServletContext ; 28 import javax.servlet.ServletConfig ; 29 import javax.servlet.ServletException ; 30 import javax.servlet.SingleThreadModel ; 31 import javax.servlet.http.HttpServlet ; 32 import javax.servlet.http.HttpServletRequest ; 33 import javax.servlet.http.HttpServletResponse ; 34 import javax.servlet.jsp.JspFactory ; 35 36 import java.util.Map ; 37 import java.util.HashMap ; 38 import java.util.Hashtable ; 39 import java.util.Iterator ; 40 import java.io.File ; 41 import java.io.PrintWriter ; 42 import java.io.IOException ; 43 import java.io.FileNotFoundException ; 44 import java.io.FilePermission ; 45 import java.lang.RuntimePermission ; 46 import java.net.URL ; 47 import java.net.URLClassLoader ; 48 import java.net.MalformedURLException ; 49 import java.security.AccessController ; 50 import java.security.CodeSource ; 51 import java.security.PermissionCollection ; 52 import java.security.Policy ; 53 import java.security.PrivilegedAction ; 54 55 import org.apache.jasper.JasperException; 56 import org.apache.jasper.Constants; 57 import org.apache.jasper.Options; 58 import org.apache.jasper.EmbededServletOptions; 59 import org.apache.jasper.JspCompilationContext; 60 import org.apache.jasper.JspEngineContext; 61 import org.apache.jasper.compiler.JspMangler; 62 import org.apache.jasper.compiler.Compiler; 63 import org.apache.jasper.runtime.JspFactoryImpl; 64 import org.apache.jasper.servlet.JasperLoader; 65 import org.apache.jasper.logging.Logger; 66 import org.apache.jasper.logging.DefaultLogger; 67 68 77 public class JspServlet extends HttpServlet { 78 protected ServletContext context = null; 79 protected Map jsps = null; 80 protected ServletConfig config; 81 protected Options options; 82 protected URLClassLoader parentClassLoader; 83 private PermissionCollection permissionCollection = null; 84 private CodeSource codeSource = null; 85 86 private long reloadInterval = 0L; 88 89 private boolean checkJSPmods = true; 92 93 private boolean debugLogEnabled = false; 95 96 String outputDir = null; 98 99 URL [] loaderURLs = null; 101 102 static boolean firstTime = true; 103 104 public void init(ServletConfig config) 105 throws ServletException { 106 107 super.init(config); 108 this.config = config; 109 this.context = config.getServletContext(); 110 111 Constants.jasperLog = new DefaultLogger(this.context); 112 Constants.jasperLog.setName("JASPER_LOG"); 113 Constants.jasperLog.setTimestamp("false"); 114 Constants.jasperLog.setVerbosityLevel( 115 config.getInitParameter("logVerbosityLevel")); 116 117 debugLogEnabled = Constants.jasperLog.matchVerbosityLevel(Logger.DEBUG); 118 119 String interval = config.getInitParameter("reload-interval"); 125 if (interval != null) { 126 try { 127 this.reloadInterval = Integer.parseInt(interval) * 1000; 128 if (this.reloadInterval < 0) { 129 checkJSPmods = false; 130 Constants.message("jsp.message.recompile.disabled", 131 Logger.INFORMATION ); 132 } else if (this.reloadInterval > 0) { 133 Constants.message("jsp.message.reload.interval", 134 new Object [] {interval}, Logger.INFORMATION ); 135 } 136 } catch (NumberFormatException nfe) { 137 Constants.message("jsp.warning.interval.invalid", 138 new Object [] {interval}, Logger.WARNING ); 139 } 140 } 141 142 if (checkJSPmods) 147 jsps = new HashMap (); 148 else 149 jsps = new Hashtable (); 150 151 options = new EmbededServletOptions(config, context); 152 153 outputDir = options.getScratchDir().toString(); 154 155 File f = new File (outputDir); 158 159 if (f.exists() == false) { 164 f.mkdirs(); 165 } 166 167 loaderURLs = new URL [1]; 168 try { 169 loaderURLs[0] = f.toURL(); 170 } catch(MalformedURLException mfe) { 171 throw new ServletException (mfe); 172 } 173 174 parentClassLoader = 178 (URLClassLoader ) Thread.currentThread().getContextClassLoader(); 179 if (parentClassLoader == null) 180 parentClassLoader = (URLClassLoader )this.getClass().getClassLoader(); 181 String loaderString = "<none>"; 182 if (parentClassLoader != null) 183 loaderString = parentClassLoader.toString(); 184 185 if (debugLogEnabled) 186 Constants.message("jsp.message.parent_class_loader_is", 187 new Object [] {loaderString}, Logger.DEBUG); 188 189 Policy policy = Policy.getPolicy(); 194 if( policy != null ) { 195 try { 196 String contextDir = context.getRealPath("/"); 198 if( contextDir == null ) 199 contextDir = outputDir; 200 URL url = new URL ("file:" + contextDir); 201 codeSource = new CodeSource (url,null); 202 permissionCollection = policy.getPermissions(codeSource); 203 if (contextDir.endsWith(File.separator)) 205 contextDir = contextDir + "-"; 206 else 207 contextDir = contextDir + File.separator + "-"; 208 permissionCollection.add( new FilePermission (contextDir,"read") ); 209 permissionCollection.add( new RuntimePermission ( 211 "accessClassInPackage.org.apache.jasper.runtime") ); 212 if (parentClassLoader instanceof URLClassLoader ) { 213 URL [] urls = parentClassLoader.getURLs(); 214 String jarUrl = null; 215 String jndiUrl = null; 216 for (int i=0; i<urls.length; i++) { 217 if (jndiUrl == null && urls[i].toString().startsWith("jndi:") ) { 218 jndiUrl = urls[i].toString() + "-"; 219 } 220 if (jarUrl == null && urls[i].toString().startsWith("jar:jndi:") ) { 221 jarUrl = urls[i].toString(); 222 jarUrl = jarUrl.substring(0,jarUrl.length() - 2); 223 jarUrl = jarUrl.substring(0,jarUrl.lastIndexOf('/')) + "/-"; 224 } 225 } 226 if (jarUrl != null) { 227 permissionCollection.add( new FilePermission (jarUrl,"read") ); 228 permissionCollection.add( new FilePermission (jarUrl.substring(4),"read") ); 229 } 230 if (jndiUrl != null) 231 permissionCollection.add( new FilePermission (jndiUrl,"read") ); 232 } 233 } catch(MalformedURLException mfe) {} 234 } 235 236 if (firstTime) { 237 firstTime = false; 238 if( System.getSecurityManager() != null ) { 239 String apacheBase = "org.apache.jasper."; 243 String iplanetBase = "com.sun.enterprise.web.jsp."; 244 try { 245 parentClassLoader.loadClass( apacheBase + 246 "runtime.JspFactoryImpl$PrivilegedGetPageContext"); 247 parentClassLoader.loadClass( apacheBase + 248 "runtime.JspFactoryImpl$PrivilegedReleasePageContext"); 249 parentClassLoader.loadClass( apacheBase + 250 "runtime.JspRuntimeLibrary"); 251 parentClassLoader.loadClass( apacheBase + 252 "runtime.JspRuntimeLibrary$PrivilegedIntrospectHelper"); 253 parentClassLoader.loadClass( apacheBase + 254 "runtime.ServletResponseWrapperInclude"); 255 this.getClass().getClassLoader().loadClass( iplanetBase + 256 "JspServlet$JspServletWrapper"); 257 } catch (ClassNotFoundException ex) { 258 Constants.jasperLog.log( 259 Constants.getString("jsp.message.preload.failure"), 260 ex, Logger.WARNING); 261 } 262 } 263 Constants.message("jsp.message.scratch.dir.is", 264 new Object [] {outputDir}, Logger.INFORMATION ); 265 Constants.message("jsp.message.dont.modify.servlets", Logger.INFORMATION); 266 JspFactory.setDefaultFactory(new JspFactoryImpl()); 267 } 268 } 269 270 public void service(HttpServletRequest request, 271 HttpServletResponse response) 272 throws ServletException , IOException { 273 try { 274 String jspUri; 275 String includeUri 276 = (String ) request.getAttribute(Constants.INC_SERVLET_PATH); 277 278 if (includeUri == null) 279 jspUri = request.getServletPath(); 280 else 281 jspUri = includeUri; 282 283 String jspFile = (String ) request.getAttribute(Constants.JSP_FILE); 284 if (jspFile != null) 285 jspUri = jspFile; 286 287 if (debugLogEnabled) { 288 Logger jasperLog = Constants.jasperLog; 289 jasperLog.log("JspEngine --> "+jspUri); 290 jasperLog.log(" ServletPath: "+request.getServletPath()); 291 jasperLog.log(" PathInfo: "+request.getPathInfo()); 292 jasperLog.log(" RealPath: "+context.getRealPath(jspUri)); 293 jasperLog.log(" RequestURI: "+request.getRequestURI()); 294 jasperLog.log(" QueryString: "+request.getQueryString()); 295 } 296 297 serviceJspFile(request, response, jspUri); 298 299 } catch (RuntimeException e) { 300 throw e; 301 } catch (ServletException e) { 302 throw e; 303 } catch (IOException e) { 304 throw e; 305 } catch (Throwable e) { 306 throw new ServletException (e); 307 } 308 } 309 310 316 private void serviceJspFile(HttpServletRequest request, 317 HttpServletResponse response, String jspUri) 318 throws ServletException , IOException { 319 320 JspServletWrapper wrapper = null; 321 try { 322 if (checkJSPmods) { 323 wrapper = getWrapper(jspUri); 325 if (wrapper == null) { 326 synchronized (this) { 328 wrapper = getWrapper(jspUri); 329 if (wrapper == null) { 330 wrapper = new JspServletWrapper(jspUri); 332 wrapper.loadJSP(request, response); 333 334 putWrapper(jspUri, wrapper); 337 } 338 } 339 } else if (wrapper.isJspFileModified()) { 340 JspServletWrapper newWrapper = 342 new JspServletWrapper(jspUri); 343 newWrapper.loadJSP(request, response); 344 345 putWrapper(jspUri, newWrapper); 348 349 releaseWrapper(wrapper); 351 wrapper = newWrapper; 352 } 353 } else { 354 wrapper = (JspServletWrapper) jsps.get(jspUri); 355 if (wrapper == null) { 356 synchronized (this) { 358 wrapper = (JspServletWrapper) jsps.get(jspUri); 359 if (wrapper == null) { 360 wrapper = new JspServletWrapper(jspUri); 362 wrapper.loadJSP(request, response); 363 364 jsps.put(jspUri, wrapper); 366 } 367 } 368 } 369 } 370 371 JasperException compileException = wrapper.getCompileException(); 373 if (compileException != null) 374 throw compileException; 375 376 if (!preCompile(request)) 378 wrapper.service(request, response); 379 380 } catch (FileNotFoundException ex) { 381 if (checkJSPmods) 385 removeWrapper(jspUri); 386 387 String includeRequestUri = (String ) 388 request.getAttribute("javax.servlet.include.request_uri"); 389 if (includeRequestUri != null) { 390 throw new ServletException (ex); 394 } else { 395 try { 396 response.sendError(HttpServletResponse.SC_NOT_FOUND, 397 ex.getMessage()); 398 } catch (IllegalStateException ise) { 399 Constants.jasperLog.log(Constants.getString 400 ("jsp.error.file.not.found", 401 new Object [] {ex.getMessage()}), 402 ex, Logger.ERROR); 403 } 404 } 405 } finally { 406 if (checkJSPmods) 408 releaseWrapper(wrapper); 409 } 410 } 411 412 417 private synchronized JspServletWrapper getWrapper(String jspUri) { 418 JspServletWrapper wrapper = (JspServletWrapper) jsps.get(jspUri); 419 if (wrapper != null) 420 wrapper.incrementRefCount(); 421 return wrapper; 422 } 423 424 private synchronized void releaseWrapper(JspServletWrapper wrapper) { 425 if (wrapper != null) 426 wrapper.decrementRefCount(); 427 } 428 429 private synchronized void putWrapper(String jspUri, 430 JspServletWrapper wrapper) { 431 wrapper.incrementRefCount(); 432 JspServletWrapper replaced = 433 (JspServletWrapper)jsps.put(jspUri, wrapper); 434 435 if (replaced != null) 437 replaced.tryDestroy(); 438 } 439 440 private synchronized void removeWrapper(String jspUri) { 441 JspServletWrapper removed = (JspServletWrapper)jsps.remove(jspUri); 442 443 if (removed != null) 445 removed.tryDestroy(); 446 } 447 448 461 boolean preCompile(HttpServletRequest request) 462 throws ServletException { 463 464 String queryString = request.getQueryString(); 465 if (queryString == null) 466 return (false); 467 int start = queryString.indexOf(Constants.PRECOMPILE); 468 if (start < 0) 469 return (false); 470 queryString = 471 queryString.substring(start + Constants.PRECOMPILE.length()); 472 if (queryString.length() == 0) 473 return (true); if (queryString.startsWith("&")) 475 return (true); if (!queryString.startsWith("=")) 477 return (false); int limit = queryString.length(); 479 int ampersand = queryString.indexOf("&"); 480 if (ampersand > 0) 481 limit = ampersand; 482 String value = queryString.substring(1, limit); 483 if (value.equals("true")) 484 return (true); else if (value.equals("false")) 486 return (true); else 488 throw new ServletException ("Cannot have request parameter " + 489 Constants.PRECOMPILE + " set to " + 490 value); 491 } 492 493 public void destroy() { 494 if (Constants.jasperLog != null) 495 Constants.jasperLog.log("JspServlet.destroy()", Logger.INFORMATION); 496 497 synchronized (this) { 499 Iterator iter = jsps.values().iterator(); 500 while (iter.hasNext()) 501 ((JspServletWrapper)iter.next()).destroy(); 502 503 jsps.clear(); 504 } 505 } 506 507 511 class JspServletWrapper { 512 String jspUri; 513 File jspFile = null; 514 boolean jspFileExists = true; 515 516 String jspClassName = null; 517 Class servletClass = null; 518 Servlet theServlet = null; 519 520 int refCount = 0; 522 boolean markedForDestroy = false; 523 524 URLClassLoader loader = null; 525 526 volatile long lastCheckedTime = 0L; 528 volatile long jspLastModifiedTime = 0L; 529 530 JasperException compileException = null; 532 533 JspServletWrapper(String jspUri) 534 throws ServletException , FileNotFoundException { 535 this.jspUri = jspUri; 536 537 String jspFileName = context.getRealPath(jspUri); 538 if (jspFileName == null) 539 throw new FileNotFoundException (jspUri); 540 541 jspFile = new File (jspFileName); 542 jspFileExists = jspFile.exists(); 543 if (checkJSPmods && !jspFileExists) 544 throw new FileNotFoundException (jspUri); 545 546 JspMangler mangler = new JspMangler(jspUri, outputDir); 547 this.jspClassName = mangler.getPackageName() + "." + 548 mangler.getClassName(); 549 } 550 551 public void service(HttpServletRequest request, 552 HttpServletResponse response) 553 throws ServletException , IOException { 554 555 if (theServlet instanceof SingleThreadModel ) { 556 synchronized (this) { 559 theServlet.service(request, response); 560 } 561 } else { 562 theServlet.service(request, response); 563 } 564 } 565 566 572 private boolean isJspFileModified() 573 throws FileNotFoundException { 574 575 boolean res = false; 576 577 long currTime = System.currentTimeMillis(); 578 if (currTime >= (reloadInterval + lastCheckedTime)) { 579 580 long lastModTime = jspFile.lastModified(); 581 582 if (lastModTime == 0L) 584 throw new FileNotFoundException (jspUri); 585 586 if (lastModTime != jspLastModifiedTime) { 588 synchronized (this) { 590 if (lastModTime != jspLastModifiedTime) { 591 jspLastModifiedTime = lastModTime; 594 res = true; 595 } 596 } 597 } 598 599 lastCheckedTime = currTime; 601 } 602 return res; 603 } 604 605 608 private void loadJSP(HttpServletRequest req, 609 HttpServletResponse res) 610 throws ServletException , FileNotFoundException { 611 612 if (!checkJSPmods && !jspFileExists) { 613 try { 616 loadAndInit(); 617 } catch (JasperException ex) { 618 Constants.jasperLog.log(ex.getMessage(), ex.getRootCause(), 619 Logger.INFORMATION); 620 throw new FileNotFoundException (jspUri); 621 } 622 return; 623 } 624 625 String classpath = 628 (String ) context.getAttribute(Constants.SERVLET_CLASSPATH); 629 630 if (debugLogEnabled) 631 Constants.message("jsp.message.context.classpath", 632 new Object [] { 633 classpath == null ? "<none>" : classpath 634 }, Logger.DEBUG); 635 636 JspCompilationContext ctxt = new JspEngineContext(parentClassLoader, 637 classpath, context, jspUri, 638 false, options, 639 req, res); 640 Compiler compiler = ctxt.createCompiler(); 641 642 if (checkJSPmods) { 643 lastCheckedTime = System.currentTimeMillis(); 646 jspLastModifiedTime = jspFile.lastModified(); 647 } 648 649 try { 651 compiler.compile(); 652 loadAndInit(); 653 } catch (JasperException ex) { 654 compileException = ex; 655 } catch (FileNotFoundException ex) { 656 compiler.removeGeneratedFiles(); 657 throw ex; 658 } catch (Exception ex) { 659 compileException = new JasperException( 660 Constants.getString("jsp.error.unable.compile"), ex); 661 } 662 } 663 664 private void loadAndInit() 665 throws JasperException, ServletException { 666 667 try { 668 loader = new JasperLoader(loaderURLs, jspClassName, 669 parentClassLoader, 670 permissionCollection, 671 codeSource); 672 servletClass = loader.loadClass(jspClassName); 673 } catch (ClassNotFoundException cnfe) { 674 throw new JasperException( 675 Constants.getString("jsp.error.unable.load"), cnfe); 676 } 677 678 try { 679 theServlet = (Servlet ) servletClass.newInstance(); 680 } catch (Exception ex) { 681 throw new JasperException(ex); 682 } 683 theServlet.init(JspServlet.this.config); 684 } 685 686 private JasperException getCompileException() { 688 return compileException; 689 } 690 691 private void incrementRefCount() { 692 refCount++; 693 } 694 695 private void decrementRefCount() { 696 refCount--; 697 if ((refCount == 0) && markedForDestroy) 698 destroy(); 699 } 700 701 private void tryDestroy() { 704 if (refCount == 0) 705 destroy(); 706 markedForDestroy = true; 707 } 708 709 private void destroy() { 710 if (theServlet != null) 711 theServlet.destroy(); 712 713 servletClass = null; 714 theServlet = null; 715 716 jspFile = null; 717 loader = null; 718 } 719 } 720 } 721 | Popular Tags |