| 1 17 18 19 package org.apache.catalina.core; 20 21 import java.lang.reflect.Method ; 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.io.PrintStream ; 25 import java.util.ArrayList ; 26 import java.util.Enumeration ; 27 import java.util.HashMap ; 28 import java.util.HashSet ; 29 import java.util.Properties ; 30 import java.util.Stack ; 31 import java.security.AccessController ; 32 import java.security.PrivilegedActionException ; 33 import java.security.PrivilegedExceptionAction ; 34 import javax.servlet.Servlet ; 35 import javax.servlet.ServletConfig ; 36 import javax.servlet.ServletContext ; 37 import javax.servlet.ServletException ; 38 import javax.servlet.ServletRequest ; 39 import javax.servlet.ServletResponse ; 40 import javax.servlet.SingleThreadModel ; 41 import javax.servlet.UnavailableException ; 42 import javax.management.ListenerNotFoundException ; 43 import javax.management.MBeanNotificationInfo ; 44 import javax.management.Notification ; 45 import javax.management.NotificationBroadcasterSupport ; 46 import javax.management.NotificationEmitter ; 47 import javax.management.NotificationFilter ; 48 import javax.management.NotificationListener ; 49 import javax.management.ObjectName ; 50 51 import org.apache.PeriodicEventListener; 52 import org.apache.catalina.Container; 53 import org.apache.catalina.ContainerServlet; 54 import org.apache.catalina.Context; 55 import org.apache.catalina.InstanceEvent; 56 import org.apache.catalina.InstanceListener; 57 import org.apache.catalina.LifecycleException; 58 import org.apache.catalina.Loader; 59 import org.apache.catalina.Wrapper; 60 import org.apache.catalina.security.SecurityUtil; 61 import org.apache.catalina.util.Enumerator; 62 import org.apache.catalina.util.InstanceSupport; 63 import org.apache.tomcat.util.IntrospectionUtils; 64 import org.apache.tomcat.util.log.SystemLogHandler; 65 import org.apache.tomcat.util.modeler.Registry; 66 67 76 public class StandardWrapper 77 extends ContainerBase 78 implements ServletConfig , Wrapper, NotificationEmitter { 79 80 protected static org.apache.commons.logging.Log log= 81 org.apache.commons.logging.LogFactory.getLog( StandardWrapper.class ); 82 83 protected static final String [] DEFAULT_SERVLET_METHODS = new String [] { 84 "GET", "HEAD", "POST" }; 85 86 88 89 92 public StandardWrapper() { 93 94 super(); 95 swValve=new StandardWrapperValve(); 96 pipeline.setBasic(swValve); 97 broadcaster = new NotificationBroadcasterSupport (); 98 99 if (restrictedServlets == null) { 100 restrictedServlets = new Properties (); 101 try { 102 InputStream is = 103 this.getClass().getClassLoader().getResourceAsStream 104 ("org/apache/catalina/core/RestrictedServlets.properties"); 105 if (is != null) { 106 restrictedServlets.load(is); 107 } else { 108 log.error(sm.getString("standardWrapper.restrictedServletsResource")); 109 } 110 } catch (IOException e) { 111 log.error(sm.getString("standardWrapper.restrictedServletsResource"), e); 112 } 113 } 114 115 } 116 117 118 120 121 127 protected long available = 0L; 128 129 132 protected NotificationBroadcasterSupport broadcaster = null; 133 134 138 protected int countAllocated = 0; 139 140 141 144 protected StandardWrapperFacade facade = 145 new StandardWrapperFacade(this); 146 147 148 151 protected static final String info = 152 "org.apache.catalina.core.StandardWrapper/1.0"; 153 154 155 158 protected Servlet instance = null; 159 160 161 164 protected InstanceSupport instanceSupport = new InstanceSupport(this); 165 166 167 170 protected String jspFile = null; 171 172 173 177 protected int loadOnStartup = -1; 178 179 180 183 protected ArrayList mappings = new ArrayList (); 184 185 186 190 protected HashMap parameters = new HashMap (); 191 192 193 198 protected HashMap references = new HashMap (); 199 200 201 204 protected String runAs = null; 205 206 209 protected long sequenceNumber = 0; 210 211 214 protected String servletClass = null; 215 216 217 220 protected boolean singleThreadModel = false; 221 222 223 226 protected boolean unloading = false; 227 228 229 232 protected int maxInstances = 20; 233 234 235 238 protected int nInstances = 0; 239 240 241 244 protected Stack instancePool = null; 245 246 247 250 protected long unloadDelay = 2000; 251 252 253 256 protected boolean isJspServlet; 257 258 259 262 protected ObjectName jspMonitorON; 263 264 265 268 protected boolean swallowOutput = false; 269 270 protected StandardWrapperValve swValve; 272 protected long loadTime=0; 273 protected int classLoadTime=0; 274 275 279 protected static Class [] classType = new Class []{ServletConfig .class}; 280 281 282 286 protected static Class [] classTypeUsedInService = new Class []{ 287 ServletRequest .class, 288 ServletResponse .class}; 289 290 293 protected static Properties restrictedServlets = null; 294 295 296 298 299 307 public long getAvailable() { 308 309 return (this.available); 310 311 } 312 313 314 323 public void setAvailable(long available) { 324 325 long oldAvailable = this.available; 326 if (available > System.currentTimeMillis()) 327 this.available = available; 328 else 329 this.available = 0L; 330 support.firePropertyChange("available", new Long (oldAvailable), 331 new Long (this.available)); 332 333 } 334 335 336 341 public int getCountAllocated() { 342 343 return (this.countAllocated); 344 345 } 346 347 348 public String getEngineName() { 349 return ((StandardContext)getParent()).getEngineName(); 350 } 351 352 353 358 public String getInfo() { 359 360 return (info); 361 362 } 363 364 365 368 public InstanceSupport getInstanceSupport() { 369 370 return (this.instanceSupport); 371 372 } 373 374 375 378 public String getJspFile() { 379 380 return (this.jspFile); 381 382 } 383 384 385 390 public void setJspFile(String jspFile) { 391 392 String oldJspFile = this.jspFile; 393 this.jspFile = jspFile; 394 support.firePropertyChange("jspFile", oldJspFile, this.jspFile); 395 396 isJspServlet = true; 400 401 } 402 403 404 408 public int getLoadOnStartup() { 409 410 if (isJspServlet && loadOnStartup < 0) { 411 416 return Integer.MAX_VALUE; 417 } else { 418 return (this.loadOnStartup); 419 } 420 } 421 422 423 429 public void setLoadOnStartup(int value) { 430 431 int oldLoadOnStartup = this.loadOnStartup; 432 this.loadOnStartup = value; 433 support.firePropertyChange("loadOnStartup", 434 new Integer (oldLoadOnStartup), 435 new Integer (this.loadOnStartup)); 436 437 } 438 439 440 441 449 public void setLoadOnStartupString(String value) { 450 451 try { 452 setLoadOnStartup(Integer.parseInt(value)); 453 } catch (NumberFormatException e) { 454 setLoadOnStartup(0); 455 } 456 } 457 458 public String getLoadOnStartupString() { 459 return Integer.toString( getLoadOnStartup()); 460 } 461 462 463 467 public int getMaxInstances() { 468 469 return (this.maxInstances); 470 471 } 472 473 474 480 public void setMaxInstances(int maxInstances) { 481 482 int oldMaxInstances = this.maxInstances; 483 this.maxInstances = maxInstances; 484 support.firePropertyChange("maxInstances", oldMaxInstances, 485 this.maxInstances); 486 487 } 488 489 490 495 public void setParent(Container container) { 496 497 if ((container != null) && 498 !(container instanceof Context )) 499 throw new IllegalArgumentException  500 (sm.getString("standardWrapper.notContext")); 501 if (container instanceof StandardContext) { 502 swallowOutput = ((StandardContext)container).getSwallowOutput(); 503 unloadDelay = ((StandardContext)container).getUnloadDelay(); 504 } 505 super.setParent(container); 506 507 } 508 509 510 513 public String getRunAs() { 514 515 return (this.runAs); 516 517 } 518 519 520 525 public void setRunAs(String runAs) { 526 527 String oldRunAs = this.runAs; 528 this.runAs = runAs; 529 support.firePropertyChange("runAs", oldRunAs, this.runAs); 530 531 } 532 533 534 537 public String getServletClass() { 538 539 return (this.servletClass); 540 541 } 542 543 544 549 public void setServletClass(String servletClass) { 550 551 String oldServletClass = this.servletClass; 552 this.servletClass = servletClass; 553 support.firePropertyChange("servletClass", oldServletClass, 554 this.servletClass); 555 if (Constants.JSP_SERVLET_CLASS.equals(servletClass)) { 556 isJspServlet = true; 557 } 558 } 559 560 561 562 570 public void setServletName(String name) { 571 572 setName(name); 573 574 } 575 576 577 581 public boolean isSingleThreadModel() { 582 583 try { 584 loadServlet(); 585 } catch (Throwable t) { 586 ; 587 } 588 return (singleThreadModel); 589 590 } 591 592 593 596 public boolean isUnavailable() { 597 598 if (available == 0L) 599 return (false); 600 else if (available <= System.currentTimeMillis()) { 601 available = 0L; 602 return (false); 603 } else 604 return (true); 605 606 } 607 608 609 619 public String [] getServletMethods() throws ServletException { 620 621 Class servletClazz = loadServlet().getClass(); 622 if (!javax.servlet.http.HttpServlet .class.isAssignableFrom( 623 servletClazz)) { 624 return DEFAULT_SERVLET_METHODS; 625 } 626 627 HashSet allow = new HashSet (); 628 allow.add("TRACE"); 629 allow.add("OPTIONS"); 630 631 Method [] methods = getAllDeclaredMethods(servletClazz); 632 for (int i=0; methods != null && i<methods.length; i++) { 633 Method m = methods[i]; 634 635 if (m.getName().equals("doGet")) { 636 allow.add("GET"); 637 allow.add("HEAD"); 638 } else if (m.getName().equals("doPost")) { 639 allow.add("POST"); 640 } else if (m.getName().equals("doPut")) { 641 allow.add("PUT"); 642 } else if (m.getName().equals("doDelete")) { 643 allow.add("DELETE"); 644 } 645 } 646 647 String [] methodNames = new String [allow.size()]; 648 return (String []) allow.toArray(methodNames); 649 650 } 651 652 653 655 656 661 public void backgroundProcess() { 662 super.backgroundProcess(); 663 664 if (!started) 665 return; 666 667 if (getServlet() != null && (getServlet() instanceof PeriodicEventListener)) { 668 ((PeriodicEventListener) getServlet()).periodicEvent(); 669 } 670 } 671 672 673 678 public static Throwable getRootCause(ServletException e) { 679 Throwable rootCause = e; 680 Throwable rootCauseCheck = null; 681 int loops = 0; 683 do { 684 loops++; 685 rootCauseCheck = rootCause.getCause(); 686 if (rootCauseCheck != null) 687 rootCause = rootCauseCheck; 688 } while (rootCauseCheck != null && (loops < 20)); 689 return rootCause; 690 } 691 692 693 699 public void addChild(Container child) { 700 701 throw new IllegalStateException  702 (sm.getString("standardWrapper.notChild")); 703 704 } 705 706 707 713 public void addInitParameter(String name, String value) { 714 715 synchronized (parameters) { 716 parameters.put(name, value); 717 } 718 fireContainerEvent("addInitParameter", name); 719 720 } 721 722 723 728 public void addInstanceListener(InstanceListener listener) { 729 730 instanceSupport.addInstanceListener(listener); 731 732 } 733 734 735 740 public void addMapping(String mapping) { 741 742 synchronized (mappings) { 743 mappings.add(mapping); 744 } 745 fireContainerEvent("addMapping", mapping); 746 747 } 748 749 750 757 public void addSecurityReference(String name, String link) { 758 759 synchronized (references) { 760 references.put(name, link); 761 } 762 fireContainerEvent("addSecurityReference", name); 763 764 } 765 766 767 770 public Servlet getServlet() { 771 return instance; 772 } 773 774 775 788 public Servlet allocate() throws ServletException { 789 790 if (unloading) 792 throw new ServletException  793 (sm.getString("standardWrapper.unloading", getName())); 794 795 if (!singleThreadModel) { 797 798 if (instance == null) { 800 synchronized (this) { 801 if (instance == null) { 802 try { 803 if (log.isDebugEnabled()) 804 log.debug("Allocating non-STM instance"); 805 806 instance = loadServlet(); 807 } catch (ServletException e) { 808 throw e; 809 } catch (Throwable e) { 810 throw new ServletException  811 (sm.getString("standardWrapper.allocate"), e); 812 } 813 } 814 } 815 } 816 817 if (!singleThreadModel) { 818 if (log.isTraceEnabled()) 819 log.trace(" Returning non-STM instance"); 820 countAllocated++; 821 return (instance); 822 } 823 824 } 825 826 synchronized (instancePool) { 827 828 while (countAllocated >= nInstances) { 829 if (nInstances < maxInstances) { 831 try { 832 instancePool.push(loadServlet()); 833 nInstances++; 834 } catch (ServletException e) { 835 throw e; 836 } catch (Throwable e) { 837 throw new ServletException  838 (sm.getString("standardWrapper.allocate"), e); 839 } 840 } else { 841 try { 842 instancePool.wait(); 843 } catch (InterruptedException e) { 844 ; 845 } 846 } 847 } 848 if (log.isTraceEnabled()) 849 log.trace(" Returning allocated STM instance"); 850 countAllocated++; 851 return (Servlet ) instancePool.pop(); 852 853 } 854 855 } 856 857 858 867 public void deallocate(Servlet servlet) throws ServletException { 868 869 if (!singleThreadModel) { 871 countAllocated--; 872 return; 873 } 874 875 synchronized (instancePool) { 877 countAllocated--; 878 instancePool.push(servlet); 879 instancePool.notify(); 880 } 881 882 } 883 884 885 891 public String findInitParameter(String name) { 892 893 synchronized (parameters) { 894 return ((String ) parameters.get(name)); 895 } 896 897 } 898 899 900 904 public String [] findInitParameters() { 905 906 synchronized (parameters) { 907 String results[] = new |