1 16 package org.mortbay.http; 17 18 import java.io.File ; 19 import java.io.IOException ; 20 import java.io.Serializable ; 21 import java.net.InetAddress ; 22 import java.net.MalformedURLException ; 23 import java.net.Socket ; 24 import java.net.URL ; 25 import java.net.URLClassLoader ; 26 import java.net.UnknownHostException ; 27 import java.security.Permission ; 28 import java.security.PermissionCollection ; 29 import java.security.Permissions ; 30 import java.util.ArrayList ; 31 import java.util.Arrays ; 32 import java.util.Collections ; 33 import java.util.Enumeration ; 34 import java.util.HashMap ; 35 import java.util.Iterator ; 36 import java.util.LinkedList ; 37 import java.util.List ; 38 import java.util.Map ; 39 import java.util.StringTokenizer ; 40 41 import org.apache.commons.logging.Log; 42 import org.mortbay.log.LogFactory; 43 import org.mortbay.http.ResourceCache.ResourceMetaData; 44 import org.mortbay.http.handler.ErrorPageHandler; 45 import org.mortbay.util.Container; 46 import org.mortbay.util.EventProvider; 47 import org.mortbay.util.IO; 48 import org.mortbay.util.LazyList; 49 import org.mortbay.util.LifeCycle; 50 import org.mortbay.util.LogSupport; 51 import org.mortbay.util.MultiException; 52 import org.mortbay.util.Resource; 53 import org.mortbay.util.URI; 54 55 56 57 82 public class HttpContext extends Container 83 implements LifeCycle, 84 HttpHandler, 85 EventProvider, 86 Serializable 87 { 88 private static Log log = LogFactory.getLog(HttpContext.class); 89 90 91 96 public final static String __fileClassPathAttr= 97 "org.mortbay.http.HttpContext.FileClassPathAttribute"; 98 99 public final static String __ErrorHandler= 100 "org.mortbay.http.ErrorHandler"; 101 102 103 104 105 private String _contextPath; 108 private List _vhosts=new ArrayList (2); 109 private List _hosts=new ArrayList (2); 110 private List _handlers=new ArrayList (3); 111 private Map _attributes = new HashMap (3); 112 private boolean _redirectNullPath=true; 113 private boolean _statsOn=false; 114 private PermissionCollection _permissions; 115 private boolean _classLoaderJava2Compliant=true; 116 private ResourceCache _resources; 117 private String [] _systemClasses=new String [] {"java.","javax.servlet.","javax.xml.","org.mortbay.","org.xml.","org.w3c.","org.apache.commons.logging."}; 118 private String [] _serverClasses = new String [] {"-org.mortbay.http.PathMap","-org.mortbay.jetty.servlet.Invoker","-org.mortbay.jetty.servlet.JSR154Filter","-org.mortbay.jetty.servlet.Default","org.mortbay.jetty.Server","org.mortbay.http.","org.mortbay.start.","org.mortbay.stop."}; 119 120 121 private String _contextName; 122 private String _classPath; 123 private Map _initParams = new HashMap (11); 124 private UserRealm _userRealm; 125 private String _realmName; 126 private PathMap _constraintMap=new PathMap(); 127 private Authenticator _authenticator; 128 private RequestLog _requestLog; 129 130 131 private String [] _welcomes= 132 { 133 "welcome.html", 134 "index.html", 135 "index.htm", 136 "index.jsp" 137 }; 138 139 140 141 private transient boolean _gracefulStop; 142 private transient ClassLoader _parent; 143 private transient ClassLoader _loader; 144 private transient HttpServer _httpServer; 145 private transient File _tmpDir; 146 private transient HttpHandler[] _handlersArray; 147 private transient String [] _vhostsArray; 148 149 150 151 transient Object _statsLock=new Object [0]; 152 transient long _statsStartedAt; 153 transient int _requests; 154 transient int _requestsActive; 155 transient int _requestsActiveMax; 156 transient int _responses1xx; transient int _responses2xx; transient int _responses3xx; transient int _responses4xx; transient int _responses5xx; 162 163 164 166 public HttpContext() 167 { 168 setAttribute(__ErrorHandler, new ErrorPageHandler()); 169 _resources=new ResourceCache(); 170 addComponent(_resources); 171 } 172 173 174 178 public HttpContext(HttpServer httpServer,String contextPathSpec) 179 { 180 this(); 181 setHttpServer(httpServer); 182 setContextPath(contextPathSpec); 183 } 184 185 186 private void readObject(java.io.ObjectInputStream in) 187 throws IOException , ClassNotFoundException 188 { 189 in.defaultReadObject(); 190 _statsLock=new Object [0]; 191 getHandlers(); 192 for (int i=0;i<_handlersArray.length;i++) 193 _handlersArray[i].initialize(this); 194 } 195 196 197 202 public HttpConnection getHttpConnection() 203 { 204 return HttpConnection.getHttpConnection(); 205 } 206 207 208 void setHttpServer(HttpServer httpServer) 209 { 210 _httpServer=httpServer; 211 _contextName=null; 212 213 } 214 215 216 public HttpServer getHttpServer() 217 { 218 return _httpServer; 219 } 220 221 222 public void setStopGracefully(boolean graceful) 223 { 224 _gracefulStop=graceful; 225 } 226 227 228 public boolean getStopGracefully() 229 { 230 return _gracefulStop; 231 } 232 233 234 235 public static String canonicalContextPathSpec(String contextPathSpec) 236 { 237 if (contextPathSpec==null || 239 contextPathSpec.indexOf(',')>=0 || 240 contextPathSpec.startsWith("*")) 241 throw new IllegalArgumentException ("Illegal context spec:"+contextPathSpec); 242 243 if(!contextPathSpec.startsWith("/")) 244 contextPathSpec='/'+contextPathSpec; 245 246 if (contextPathSpec.length()>1) 247 { 248 if (contextPathSpec.endsWith("/")) 249 contextPathSpec+="*"; 250 else if (!contextPathSpec.endsWith("/*")) 251 contextPathSpec+="/*"; 252 } 253 254 return contextPathSpec; 255 } 256 257 258 public void setContextPath(String contextPathSpec) 259 { 260 if (_httpServer!=null) 261 _httpServer.removeMappings(this); 262 263 contextPathSpec=canonicalContextPathSpec(contextPathSpec); 264 265 if (contextPathSpec.length()>1) 266 _contextPath=contextPathSpec.substring(0,contextPathSpec.length()-2); 267 else 268 _contextPath="/"; 269 270 _contextName=null; 271 272 if (_httpServer!=null) 273 _httpServer.addMappings(this); 274 } 275 276 277 278 281 public String getContextPath() 282 { 283 return _contextPath; 284 } 285 286 287 288 293 public void addVirtualHost(String hostname) 294 { 295 if (!_vhosts.contains(hostname)) 297 { 298 _vhosts.add(hostname); 299 _contextName=null; 300 301 if (_httpServer!=null) 302 { 303 if (_vhosts.size()==1) 304 _httpServer.removeMapping(null,this); 305 _httpServer.addMapping(hostname,this); 306 } 307 _vhostsArray=null; 308 } 309 } 310 311 312 317 public void removeVirtualHost(String hostname) 318 { 319 if (_vhosts.remove(hostname)) 321 { 322 _contextName=null; 323 if (_httpServer!=null) 324 { 325 _httpServer.removeMapping(hostname,this); 326 if (_vhosts.size()==0) 327 _httpServer.addMapping(null,this); 328 } 329 _vhostsArray=null; 330 } 331 } 332 333 334 344 public void setVirtualHosts(String [] hosts) 345 { 346 List old = new ArrayList (_vhosts); 347 348 if (hosts!=null) 349 { 350 for (int i=0;i<hosts.length;i++) 351 { 352 boolean existing=old.remove(hosts[i]); 353 if (!existing) 354 addVirtualHost(hosts[i]); 355 } 356 } 357 358 for (int i=0;i<old.size();i++) 359 removeVirtualHost((String )old.get(i)); 360 } 361 362 363 373 public String [] getVirtualHosts() 374 { 375 if (_vhostsArray!=null) 376 return _vhostsArray; 377 if (_vhosts==null) 378 _vhostsArray=new String [0]; 379 else 380 { 381 _vhostsArray=new String [_vhosts.size()]; 382 _vhostsArray=(String [])_vhosts.toArray(_vhostsArray); 383 } 384 return _vhostsArray; 385 } 386 387 388 389 396 public void setHosts(String [] hosts) 397 throws UnknownHostException 398 { 399 if (hosts==null || hosts.length==0) 400 _hosts=null; 401 else 402 { 403 _hosts=new ArrayList (); 404 for (int i=0;i<hosts.length;i++) 405 if (hosts[i]!=null) 406 _hosts.add(InetAddress.getByName(hosts[i])); 407 } 408 409 } 410 411 412 414 public String [] getHosts() 415 { 416 if (_hosts==null || _hosts.size()==0) 417 return null; 418 String [] hosts=new String [_hosts.size()]; 419 for (int i=0;i<hosts.length;i++) 420 { 421 InetAddress a = (InetAddress )_hosts.get(i); 422 if (a!=null) 423 hosts[i]=a.getHostName(); 424 } 425 return hosts; 426 } 427 428 429 430 435 public void setSystemClasses(String [] classes) 436 { 437 _systemClasses=classes; 438 } 439 440 441 446 public String [] getSystemClasses() 447 { 448 return _systemClasses; 449 } 450 451 452 453 458 public void setServerClasses(String [] classes) 459 { 460 _serverClasses=classes; 461 } 462 463 464 469 public String [] getServerClasses() 470 { 471 return _serverClasses; 472 } 473 474 475 476 public void setHandlers(HttpHandler[] handlers) 477 { 478 List old = new ArrayList (_handlers); 479 480 if (handlers!=null) 481 { 482 for (int i=0;i<handlers.length;i++) 483 { 484 boolean existing=old.remove(handlers[i]); 485 if (!existing) 486 addHandler(handlers[i]); 487 } 488 } 489 490 for (int i=0;i<old.size();i++) 491 removeHandler((HttpHandler)old.get(i)); 492 } 493 494 495 498 public HttpHandler[] getHandlers() 499 { 500 if (_handlersArray!=null) 501 return _handlersArray; 502 if (_handlers==null) 503 _handlersArray=new HttpHandler[0]; 504 else 505 { 506 _handlersArray=new HttpHandler[_handlers.size()]; 507 _handlersArray=(HttpHandler[])_handlers.toArray(_handlersArray); 508 } 509 return _handlersArray; 510 } 511 512 513 514 518 public synchronized void addHandler(int i,HttpHandler handler) 519 { 520 _handlers.add(i,handler); 521 _handlersArray=null; 522 523 HttpContext context = handler.getHttpContext(); 524 if (context==null) 525 handler.initialize(this); 526 else if (context!=this) 527 throw new IllegalArgumentException ("Handler in another HttpContext"); 528 addComponent(handler); 529 } 530 531 532 535 public synchronized void addHandler(HttpHandler handler) 536 { 537 addHandler(_handlers.size(),handler); 538 } 539 540 541 545 public int getHandlerIndex(HttpHandler handler) 546 { 547 for (int h=0;h<_handlers.size();h++) 548 { 549 if ( handler == _handlers.get(h)) 550 return h; 551 } 552 return -1; 553 } 554 555 556 560 public synchronized HttpHandler getHandler(Class handlerClass) 561 { 562 for (int h=0;h<_handlers.size();h++) 563 { 564 HttpHandler handler = (HttpHandler)_handlers.get(h); 565 if (handlerClass.isInstance(handler)) 566 return handler; 567 } 568 return null; 569 } 570 571 572 576 public synchronized HttpHandler removeHandler(int i) 577 { 578 HttpHandler handler = _handlersArray[i]; 579 if (handler.isStarted()) 580 try{handler.stop();} catch (InterruptedException e){log.warn(LogSupport.EXCEPTION,e);} 581 _handlers.remove(i); 582 _handlersArray=null; 583 removeComponent(handler); 584 return handler; 585 } 586 587 588 591 public synchronized void removeHandler(HttpHandler handler) 592 { 593 if (handler.isStarted()) 594 try{handler.stop();} catch (InterruptedException e){log.warn(LogSupport.EXCEPTION,e);} 595 _handlers.remove(handler); 596 removeComponent(handler); 597 _handlersArray=null; 598 } 599 600 601 602 609 public void setInitParameter(String param, String value) 610 { 611 _initParams.put(param,value); 612 } 613 614 615 619 public String getInitParameter(String param) 620 { 621 return (String )_initParams.get(param); 622 } 623 624 625 628 public Enumeration getInitParameterNames() 629 { 630 return Collections.enumeration(_initParams.keySet()); 631 } 632 633 634 638 public synchronized void setAttribute(String name, Object value) 639 { 640 _attributes.put(name,value); 641 } 642 643 644 648 public Object getAttribute(String name) 649 { 650 return _attributes.get(name); 651 } 652 653 654 656 public Map getAttributes() 657 { 658 return _attributes; 659 } 660 661 662 664 public void setAttributes(Map attributes) 665 { 666 _attributes=attributes; 667 } 668 669 670 673 public Enumeration getAttributeNames() 674 { 675 return Collections.enumeration(_attributes.keySet()); 676 } 677 678 679 682 public synchronized void removeAttribute(String name) 683 { 684 _attributes.remove(name); 685 } 686 687 688 689 public void flushCache() 690 { 691 _resources.flushCache(); 692 } 693 694 695 public String [] getWelcomeFiles() 696 { 697 return _welcomes; 698 } 699 700 701 public void setWelcomeFiles(String [] welcomes) 702 { 703 if (welcomes==null) 704 _welcomes=new String [0]; 705 else 706 _welcomes=welcomes; 707 } 708 709 710 public void addWelcomeFile(String welcomeFile) 711 { 712 if (welcomeFile.startsWith("/") || 713 welcomeFile.startsWith(java.io.File.separator) || 714 welcomeFile.endsWith("/") || 715 welcomeFile.endsWith(java.io.File.separator)) 716 log.warn("Invalid welcome file: "+welcomeFile); 717 List list = new ArrayList (Arrays.asList(_welcomes)); 718 list.add(welcomeFile); 719 _welcomes=(String [])list.toArray(_welcomes); 720 } 721 722 723 public void removeWelcomeFile(String welcomeFile) 724 { 725 List list = new ArrayList (Arrays.asList(_welcomes)); 726 list.remove(welcomeFile); 727 _welcomes=(String [])list.toArray(_welcomes); 728 } 729 730 731 public String getWelcomeFile(Resource resource) 732 throws IOException 733 { 734 if (!resource.isDirectory()) 735 return null; 736 737 for (int i=0;i<_welcomes.length;i++) 738 { 739 Resource welcome=resource.addPath(_welcomes[i]); 740 if (welcome.exists()) 741 return _welcomes[i]; 742 } 743 744 return null; 745 } 746 747 748 749 759 public String getClassPath() 760 { 761 return _classPath; 762 } 763 764 765 775 public String getFileClassPath() 776 throws IllegalStateException 777 { 778 779 ClassLoader loader = getClassLoader(); 780 if (loader==null) 781 throw new IllegalStateException ("Context classloader not initialized"); 782 783 LinkedList paths =new LinkedList (); 784 LinkedList loaders=new LinkedList (); 785 786 while (loader !=null) 788 { 789 loaders.add(0,loader); 790 loader = loader.getParent(); 791 } 792 793 loader=getClassLoader(); 795 if (loader instanceof ContextLoader && !((ContextLoader)loader).isJava2Compliant()) 796 { 797 loaders.remove(loader); 798 loaders.add(0,loader); 799 } 800 801 for (int i=0;i<loaders.size();i++) 802 { 803 loader=(ClassLoader )loaders.get(i); 804 805 if (log.isDebugEnabled()) log.debug("extract paths from "+loader); 806 if (loader instanceof URLClassLoader ) 807 { 808 URL [] urls = ((URLClassLoader )loader).getURLs(); 809 for (int j=0;urls!=null && j<urls.length;j++) 810 { 811 try 812 { 813 Resource path = Resource.newResource(urls[j]); 814 if (log.isTraceEnabled()) log.trace("path "+path); 815 File file = path.getFile(); 816 if (file!=null) 817 paths.add(file.getAbsolutePath()); 818 } 819 catch(Exception e) 820 { 821 LogSupport.ignore(log,e); 822 } 823 } 824 } 825 } 826 827 String jcp=System.getProperty("java.class.path"); 829 if (jcp!=null) 830 { 831 StringTokenizer tok=new StringTokenizer (jcp,File.pathSeparator); 832 while (tok.hasMoreTokens()) 833 { 834 String path=tok.nextToken(); 835 if (!paths.contains(path)) 836 { 837 if(log.isTraceEnabled())log.trace("PATH="+path); 838 paths.add(path); 839 } 840 else 841 if(log.isTraceEnabled())log.trace("done="+path); 842 } 843 } 844 845 StringBuffer buf = new StringBuffer (); 846 Iterator iter = paths.iterator(); 847 while(iter.hasNext()) 848 { 849 if (buf.length()>0) 850 buf.append(File.pathSeparator); 851 buf.append(iter.next().toString()); 852 } 853 854 if (log.isDebugEnabled()) log.debug("fileClassPath="+buf); 855 return buf.toString(); 856 } 857 858 859 866 public void setClassPath(String classPath) 867 { 868 _classPath=classPath; 869 if (isStarted()) 870 log.warn("classpath set while started"); 871 } 872 873 874 881 public void addClassPath(String classPath) 882 { 883 if (_classPath==null || _classPath.length()==0) 884 _classPath=classPath; 885 else 886 _classPath+=","+classPath; 887 888 if (isStarted()) 889 log.warn("classpath set while started"); 890 } 891 892 893 900 public void addClassPaths(Resource lib) 901 { 902 if (isStarted()) 903 log.warn("classpaths set while started"); 904 905 if (lib.exists() && lib.isDirectory()) 906 { 907 String [] files=lib.list(); 908 for (int f=0;files!=null && f<files.length;f++) 909 { 910 try { 911 Resource fn=lib.addPath(files[f]); 912 String fnlc=fn.getName().toLowerCase(); 913 if (fnlc.endsWith(".jar") || fnlc.endsWith(".zip")) 914 { 915 addClassPath(fn.toString()); 916 } 917 } 918 catch (Exception ex) 919 { 920 log.warn(LogSupport.EXCEPTION,ex); 921 } 922 } 923 } 924 } 925 926 927 933 public boolean isClassLoaderJava2Compliant() 934 { 935 return _classLoaderJava2Compliant; 936 } 937 938 939 945 public void setClassLoaderJava2Compliant(boolean compliant) 946 { 947 _classLoaderJava2Compliant = compliant; 948 if (_loader!=null && (_loader instanceof ContextLoader)) 949 ((ContextLoader)_loader).setJava2Compliant(compliant); 950 } 951 952 953 957 public void setTempDirectory(File dir) 958 { 959 if (isStarted()) 960 throw new IllegalStateException ("Started"); 961 962 if (dir!=null) 963 { 964 try{dir=new File (dir.getCanonicalPath());} 965 catch (IOException e){log.warn(LogSupport.EXCEPTION,e);} 966 } 967 968 if (dir!=null && !dir.exists()) 969 { 970 dir.mkdir(); 971 dir.deleteOnExit(); 972 } 973 974 if (dir!=null && ( !dir.exists() || !dir.isDirectory() || !dir.canWrite())) 975 throw new IllegalArgumentException ("Bad temp directory: "+dir); 976 977 _tmpDir=dir; 978 setAttribute("javax.servlet.context.tempdir",_tmpDir); 979 } 980 981 982 989 public File getTempDirectory() 990 { 991 if (_tmpDir!=null) 992 return _tmpDir; 993 994 Object t = getAttribute("javax.servlet.context.tempdir"); 999 1000 if (t!=null && (t instanceof File )) 1001 { 1002 _tmpDir=(File )t; 1003 if (_tmpDir.isDirectory() && _tmpDir.canWrite()) 1004 return _tmpDir; 1005 } 1006 1007 if (t!=null && (t instanceof String )) 1008 { 1009 try 1010 { 1011 _tmpDir=new File ((String )t); 1012 1013 if (_tmpDir.isDirectory() && _tmpDir.canWrite()) 1014 { 1015 if(log.isDebugEnabled())log.debug("Converted to File "+_tmpDir+" for "+this); 1016 setAttribute("javax.servlet.context.tempdir",_tmpDir); 1017 return _tmpDir; 1018 } 1019 } 1020 catch(Exception e) 1021 { 1022 log.warn(LogSupport.EXCEPTION,e); 1023 } 1024 } 1025 1026 File work=null; 1028 try 1029 { 1030 work=new File (System.getProperty("jetty.home"),"work"); 1031 if (!work.exists() || !work.canWrite() || !work.isDirectory()) 1032 work=null; 1033 } 1034 catch(Exception e) 1035 { 1036 LogSupport.ignore(log,e); 1037 } 1038 1039 try 1041 { 1042 HttpListener httpListener=_httpServer.getListeners()[0]; 1043 1044 String vhost = null; 1045 for (int h=0;vhost==null && _vhosts!=null && h<_vhosts.size();h++) 1046 vhost=(String )_vhosts.get(h); 1047 String host=httpListener.getHost(); 1048 String temp="Jetty_"+ 1049 (host==null?"":host)+ 1050 "_"+ 1051 httpListener.getPort()+ 1052 "_"+ 1053 (vhost==null?"":vhost)+ 1054 getContextPath(); 1055 1056 temp=temp.replace('/','_'); 1057 temp=temp.replace('.','_'); 1058 temp=temp.replace('\\','_'); 1059 1060 1061 if (work!=null) 1062 _tmpDir=new File (work,temp); 1063 else 1064 { 1065 _tmpDir=new File (System.getProperty("java.io.tmpdir"),temp); 1066 1067 if (_tmpDir.exists()) 1068 { 1069 if(log.isDebugEnabled())log.debug("Delete existing temp dir "+_tmpDir+" for "+this); 1070 if (!IO.delete(_tmpDir)) 1071 { 1072 if(log.isDebugEnabled())log.debug("Failed to delete temp dir "+_tmpDir); 1073 } 1074 1075 if (_tmpDir.exists()) 1076 { 1077 String old=_tmpDir.toString(); 1078 _tmpDir=File.createTempFile(temp+"_",""); 1079 if (_tmpDir.exists()) 1080 _tmpDir.delete(); 1081 log.warn("Can't reuse "+old+", using "+_tmpDir); 1082 } 1083 } 1084 } 1085 1086 if (!_tmpDir.exists()) 1087 _tmpDir.mkdir(); 1088 if (work==null) 1089 _tmpDir.deleteOnExit(); 1090 if(log.isDebugEnabled())log.debug("Created temp dir "+_tmpDir+" for "+this); 1091 } 1092 catch(Exception e) 1093 { 1094 _tmpDir=null; 1095 LogSupport.ignore(log,e); 1096 } 1097 1098 if (_tmpDir==null) 1099 { 1100 try{ 1101 _tmpDir=File.createTempFile("JettyContext",""); 1103 if (_tmpDir.exists()) 1104 _tmpDir.delete(); 1105 _tmpDir.mkdir(); 1106 _tmpDir.deleteOnExit(); 1107 if(log.isDebugEnabled())log.debug("Created temp dir "+_tmpDir+" for "+this); 1108 } 1109 catch(IOException e) 1110 { 1111 log.fatal(e); System.exit(1); 1112 } 1113 } 1114 1115 setAttribute("javax.servlet.context.tempdir",_tmpDir); 1116 return _tmpDir; 1117 } 1118 1119 1120 1121 1122 1125 public synchronized void setClassLoader(ClassLoader loader) 1126 { 1127 if (isStarted()) 1128 throw new IllegalStateException ("Started"); 1129 _loader=loader; 1130 } 1131 1132 1133 1134 1146 public synchronized ClassLoader getClassLoader() 1147 { 1148 return _loader; 1149 } 1150 1151 1152 1159 public synchronized void setParentClassLoader(ClassLoader loader) 1160 { 1161 if (isStarted()) 1162 throw new IllegalStateException ("Started"); 1163 _parent=loader; 1164 } 1165 1166 1167 public ClassLoader getParentClassLoader() 1168 { 1169 return _parent; 1170 } 1171 1172 1173 1180 protected void initClassLoader(boolean forceContextLoader) 1181 throws MalformedURLException , IOException 1182 { 1183 ClassLoader parent=_parent; 1184 if (_loader==null) 1185 { 1186 if (parent==null) 1188 parent=Thread.currentThread().getContextClassLoader(); 1189 1190 if (parent==null) 1192 parent=this.getClass().getClassLoader(); 1193 1194 if(log.isDebugEnabled())log.debug("Init classloader from "+_classPath+ 1195 ", "+parent+" for "+this); 1196 1197 if (forceContextLoader || _classPath!=null || _permissions!=null) 1198 { 1199 ContextLoader loader=new ContextLoader(this,_classPath,parent,_permissions); 1200 loader.setJava2Compliant(_classLoaderJava2Compliant); 1201 _loader=loader; 1202 } 1203 else 1204 _loader=parent; 1205 } 1206 } 1207 1208 1209 public synchronized Class loadClass(String className) 1210 throws ClassNotFoundException 1211 { 1212 if (_loader==null) 1213 { 1214 try{initClassLoader(false);} 1215 catch(Exception e) 1216 { 1217 log.warn(LogSupport.EXCEPTION,e); 1218 return null; 1219 } 1220 } 1221 1222 if (className==null) 1223 return null; 1224 1225 if (_loader == null) 1226 return Class.forName(className); 1227 return _loader.loadClass(className); 1228 } 1229 1230 1231 1235 public void setRealmName(String realmName) 1236 { 1237 _realmName=realmName; 1238 } 1239 1240 1241 public String getRealmName() 1242 { 1243 return _realmName; 1244 } 1245 1246 1247 1249 public void setRealm(UserRealm realm) 1250 { 1251 _userRealm=realm; 1252 } 1253 1254 1255 public UserRealm getRealm() 1256 { 1257 return _userRealm; 1258 } 1259 1260 1261 public Authenticator getAuthenticator() 1262 { 1263 return _authenticator; 1264 } 1265 1266 1267 public void setAuthenticator(Authenticator authenticator) 1268 { 1269 _authenticator=authenticator; 1270 } 1271 1272 1273 public void addSecurityConstraint(String pathSpec, SecurityConstraint sc) 1274 { 1275 Object scs = _constraintMap.get(pathSpec); 1276 scs = LazyList.add(scs,sc); 1277 _constraintMap.put(pathSpec,scs); 1278 1279 if(log.isDebugEnabled())log.debug("added "+sc+" at "+pathSpec); 1280 } 1281 1282 1283 public void clearSecurityConstraints() 1284 { 1285 _constraintMap.clear(); 1286 } 1287 1288 1289 public boolean checkSecurityConstraints( 1290 String pathInContext, 1291 HttpRequest request, 1292 HttpResponse response) 1293 throws HttpException, IOException 1294 { 1295 UserRealm realm= getRealm(); 1296 1297 List scss= _constraintMap.getMatches(pathInContext); 1298 String pattern=null; 1299 if (scss != null && scss.size() > 0) 1300 { 1301 Object constraints= null; 1302 1303 loop: 1308 for (int m= 0; m < scss.size(); m++) 1309 { 1310 Map.Entry entry= (Map.Entry )scss.get(m); 1311 Object scs= entry.getValue(); 1312 String p=(String )entry.getKey(); 1313 for (int c=0;c<LazyList.size(scs);c++) 1314 { 1315 SecurityConstraint sc=(SecurityConstraint)LazyList.get(scs,c); 1316 if (!sc.forMethod(request.getMethod())) 1317 continue; 1318 1319 if (pattern!=null && !pattern.equals(p)) 1320 break loop; 1321 pattern=p; 1322 constraints= LazyList.add(constraints, sc); 1323 } 1324 } 1325 1326 return SecurityConstraint.check( 1327 LazyList.getList(constraints), 1328 _authenticator, 1329 realm, 1330 pathInContext, 1331 request, 1332 response); 1333 } 1334 request.setUserPrincipal(HttpRequest.__NOT_CHECKED); 1335 return true; 1336 } 1337 1338 1339 1343 public void setRedirectNullPath(boolean b) 1344 { 1345 _redirectNullPath=b; 1346 } 1347 1348 1349 1353 public boolean isRedirectNullPath() 1354 { 1355 return _redirectNullPath; 1356 } 1357 1358 1359 1360 1361 1368 public void setPermissions(PermissionCollection permissions) 1369 { 1370 _permissions=permissions; 1371 } 1372 1373 1374 1376 public PermissionCollection getPermissions() 1377 { 1378 return _permissions; 1379 } 1380 1381 1382 1389 public void addPermission(Permission permission) 1390 { 1391 if (_permissions==null) 1392 _permissions=new Permissions (); 1393 _permissions.add(permission); 1394 } 1395 1396 1397 1406 public void handle(HttpRequest request, 1407 HttpResponse response) 1408 throws HttpException, IOException 1409 { 1410 if (!isStarted() || _gracefulStop) 1411 return; 1412 1413 if (_hosts!=null && _hosts.size()>0) 1415 { 1416 Object o = request.getHttpConnection().getConnection(); 1417 if (o instanceof Socket ) 1418 { 1419 Socket s=(Socket )o; 1420 if (!_hosts.contains(s.getLocalAddress())) 1421 { 1422 if(log.isDebugEnabled())log.debug(s.getLocalAddress()+" not in "+_hosts); 1423 return; 1424 } 1425 } 1426 } 1427 1428 if (_statsOn) 1430 { 1431 synchronized(_statsLock) 1432 { 1433 _requests++; 1434 _requestsActive++; 1435 if (_requestsActive>_requestsActiveMax) 1436 _requestsActiveMax=_requestsActive; 1437 } 1438 } 1439 1440 String pathInContext = URI.canonicalPath(request.getPath()); 1441 if (pathInContext==null) 1442 { 1443 throw new HttpException(HttpResponse.__400_Bad_Request); 1445 } 1446 1447 if (_contextPath.length()>1) 1448 pathInContext=pathInContext.substring(_contextPath.length()); 1449 1450 if (_redirectNullPath && (pathInContext==null || 1451 pathInContext.length()==0)) 1452 { 1453 StringBuffer buf=request.getRequestURL(); 1454 buf.append("/"); 1455 String q=request.getQuery(); 1456 if (q!=null&&q.length()!=0) 1457 buf.append("?"+q); 1458 1459 response.sendRedirect(buf.toString()); 1460 if (log.isDebugEnabled()) 1461 log.debug(this+" consumed all of path "+ 1462 request.getPath()+ 1463 ", redirect to "+buf.toString()); 1464 return; 1465 } 1466 1467 String pathParams=null; 1468 int semi = pathInContext.lastIndexOf(';'); 1469 if (semi>=0) 1470 { 1471 int pl = pathInContext.length()-semi; 1472 String ep=request.getEncodedPath(); 1473 if(';'==ep.charAt(ep.length()-pl)) 1474 { 1475 pathParams=pathInContext.substring(semi+1); 1476 pathInContext=pathInContext.substring(0,semi); 1477 } 1478 } 1479 1480 try 1481 { 1482 handle(pathInContext,pathParams,request,response); 1483 } 1484 finally 1485 { 1486 if (_userRealm!=null && request.hasUserPrincipal()) 1487 _userRealm.disassociate(request.getUserPrincipal()); 1488 } 1489 } 1490 1491 1492 1502 public void handle(String pathInContext, 1503 String pathParams, 1504 HttpRequest request, 1505 HttpResponse response) 1506 throws HttpException, IOException 1507 { 1508 Object old_scope= null; 1509 try 1510 { 1511 old_scope= enterContextScope(request,response); 1512 HttpHandler[] handlers= getHandlers(); 1513 for (int k= 0; k < handlers.length; k++) 1514 { 1515 HttpHandler handler= handlers[k]; 1516 if (handler == null) 1517 { 1518 handlers= getHandlers(); 1519 k= -1; 1520 continue; 1521 } 1522 if (!handler.isStarted()) 1523 { 1524 if (log.isDebugEnabled()) 1525 log.debug(handler + " not started in " + this); 1526 continue; 1527 } 1528 if (log.isDebugEnabled()) 1529 log.debug("Handler " + handler); 1530 handler.handle(pathInContext, pathParams, request, response); 1531 if (request.isHandled()) 1532 { 1533 if (log.isDebugEnabled()) 1534 log.debug("Handled by " + handler); 1535 return; 1536 } 1537 } 1538 return; 1539 } 1540 finally 1541 { 1542 leaveContextScope(request, response, old_scope); 1543 } 1544 } 1545 1546 1547 1552 public Object enterContextScope(HttpRequest request, HttpResponse response) 1553 { 1554 Thread thread = Thread.currentThread(); 1556 ClassLoader cl=thread.getContextClassLoader(); 1557 HttpContext c=response.getHttpContext(); 1558 1559 Scope scope=null; 1560 if (cl!=HttpContext.class.getClassLoader() || c!=null) 1561 { 1562 scope=new Scope(); 1563 scope._classLoader=cl; 1564 scope._httpContext=c; 1565 } 1566 1567 if (_loader!=null) 1568 thread.setContextClassLoader(_loader); 1569 response.setHttpContext(this); 1570 1571 return scope; 1572 } 1573 1574 1575 1580 public void leaveContextScope(HttpRequest request, HttpResponse response,Object oldScope) 1581 { 1582 if (oldScope==null) 1583 { 1584 Thread.currentThread() 1585 .setContextClassLoader(HttpContext.class.getClassLoader()); 1586 response.setHttpContext(null); 1587 } 1588 else 1589 { 1590 Scope old = (Scope)oldScope; 1591 Thread.currentThread().setContextClassLoader(old._classLoader); 1592 response.setHttpContext(old._httpContext); 1593 } 1594 } 1595 1596 1597 1598 public String getHttpContextName() 1599 { 1600 if (_contextName==null) 1601 _contextName = (_vhosts.size()>1?(_vhosts.toString()+":"):"")+_contextPath; 1602 return _contextName; 1603 } 1604 1605 1606 public void setHttpContextName(String s) 1607 { 1608 _contextName=s; 1609 } 1610 1611 1612 public String toString() 1613 { 1614 return "HttpContext["+getContextPath()+","+getHttpContextName()+"]"; 1615 } 1616 1617 1618 public String toString(boolean detail) 1619 { 1620 return "HttpContext["+getContextPath()+","+getHttpContextName()+"]" + 1621 (detail?("="+_handlers):""); 1622 } 1623 1624 1625 1626 protected synchronized void doStart() 1627 throws Exception 1628 { 1629 if (isStarted()) 1630 return; 1631 1632 if (_httpServer.getServerClasses()!=null) 1633 _serverClasses=_httpServer.getServerClasses(); 1634 if (_httpServer.getSystemClasses()!=null) 1635 _systemClasses=_httpServer.getSystemClasses(); 1636 1637 _resources.start(); 1638 1639 statsReset(); 1640 1641 if (_httpServer==null) 1642 throw new IllegalStateException ("No server for "+this); 1643 1644 _resources.getMimeMap(); 1646 _resources.getEncodingMap(); 1647 1648 if (_userRealm==null && _authenticator!=null) 1650 { 1651 _userRealm=_httpServer.getRealm(_realmName); 1652 if (_userRealm==null) 1653 log.warn("No Realm: "+_realmName); 1654 } 1655 1656 initClassLoader(false); 1658 1659 String attr = getInitParameter(__fileClassPathAttr); 1661 if (attr!=null && attr.length()>0) 1662 setAttribute(attr,getFileClassPath()); 1663 1664 Thread thread = Thread.currentThread(); 1666 ClassLoader lastContextLoader=thread.getContextClassLoader(); 1667 try 1668 { 1669 if (_loader!=null) 1670 thread.setContextClassLoader(_loader); 1671 1672 if (_requestLog!=null) 1673 _requestLog.start(); 1674 1675 startHandlers(); 1676 } 1677 finally 1678 { 1679 thread.setContextClassLoader(lastContextLoader); 1680 getHandlers(); 1681 } 1682 1683 } 1684 1685 1686 1693 protected void startHandlers() 1694 throws Exception 1695 { 1696 MultiException mx = new MultiException(); 1698 1699 Iterator handlers = _handlers.iterator(); 1700 while(handlers.hasNext()) 1701 { 1702 HttpHandler handler=(HttpHandler)handlers.next(); 1703 if (!handler.isStarted()) 1704 try{handler.start();}catch(Exception e){mx.add(e);} 1705 } 1706 mx.ifExceptionThrow(); 1707 } 1708 1709 1710 1714 public void stop(boolean graceful) 1715 throws InterruptedException 1716 { 1717 boolean gs=_gracefulStop; 1718 try 1719 { 1720 _gracefulStop=true; 1721 1722 while (graceful && _statsOn && _requestsActive>0 && _httpServer!=null) 1724 try {Thread.sleep(100);} 1725 catch (InterruptedException e){throw e;} 1726 catch (Exception e){LogSupport.ignore(log,e);} 1727 1728 stop(); 1729 } 1730 finally 1731 { 1732 _gracefulStop=gs; 1733 } 1734 } 1735 1736 1737 1739 protected void doStop() 1740 throws Exception 1741 { 1742 if (_httpServer==null) 1743 throw new InterruptedException ("Destroy called"); 1744 1745 synchronized(this) 1746 { 1747 Thread thread = Thread.currentThread(); 1749 ClassLoader lastContextLoader=thread.getContextClassLoader(); 1750 try 1751 { 1752 if (_loader!=null) 1753 thread.setContextClassLoader(_loader); 1754 Iterator handlers = _handlers.iterator(); 1755 while(handlers.hasNext()) 1756 { 1757 HttpHandler handler=(HttpHandler)handlers.next(); 1758 if (handler.isStarted()) 1759 { 1760 try{handler.stop();} 1761 catch(Exception e){log.warn(LogSupport.EXCEPTION,e);} 1762 } 1763 } 1764 1765 if (_requestLog!=null) 1766 _requestLog.stop(); 1767 } 1768 finally 1769 { 1770 thread.setContextClassLoader(lastContextLoader); 1771 } 1772 1773 if (_loader instanceof ContextLoader) 1775 { 1776 ((ContextLoader)_loader).destroy(); 1777 LogFactory.release(_loader); 1778 } 1779 1780 _loader=null; 1781 } 1782 _resources.flushCache(); 1783 _resources.stop(); 1784 } 1785 1786 1787 1788 1792 public void destroy() 1793 { 1794 if (isStarted()) 1795 throw new IllegalStateException ("Started"); 1796 1797 if (_httpServer!=null) 1798 _httpServer.removeContext(this); 1799 1800 _httpServer=null; 1801 1802 if (_handlers!=null) 1803 _handlers.clear(); 1804 1805 _handlers=null; 1806 _parent=null; 1807 _loader=null; 1808 if (_attributes!=null) 1809 _attributes.clear(); 1810 _attributes=null; 1811 if (_initParams!=null) 1812 _initParams.clear(); 1813 _initParams=null; 1814 if (_vhosts!=null) 1815 _vhosts.clear(); 1816 _vhosts=null; 1817 _hosts=null; 1818 _tmpDir=null; 1819 1820 _permissions=null; 1821 1822 removeComponent(_resources); 1823 if (_resources!=null) 1824 { 1825 _resources.flushCache(); 1826 if (_resources.isStarted()) 1827 try{_resources.stop();}catch(Exception e){LogSupport.ignore(log,e);} 1828 _resources.destroy(); 1829 } 1830 _resources=null; 1831 1832 super.destroy(); 1833 1834 } 1835 1836 1837 1838 1841 public void setRequestLog(RequestLog log) 1842 { 1843 _requestLog=log; 1844 } 1845 1846 1847 public RequestLog getRequestLog() 1848 { 1849 return _requestLog; 1850 } 1851 1852 1853 1854 1862 public void sendError(HttpResponse response,int code,String msg) 1863 throws IOException 1864 { 1865 response.sendError(code,msg); 1866 } 1867 1868 1869 1877 public static void sendContextError(HttpResponse response,int code,String msg) 1878 throws IOException 1879 { 1880 HttpContext context = response.getHttpContext(); 1881 if (context!=null) 1882 context.sendError(response,code,msg); 1883 else 1884 response.sendError(code,msg); 1885 } 1886 1887 1888 1891 public void setStatsOn(boolean on) 1892 { 1893 log.info("setStatsOn "+on+" for "+this); 1894 _statsOn=on; 1895 statsReset(); 1896 } 1897 1898 1899 public boolean getStatsOn() {return _statsOn;} 1900 1901 1902 public long getStatsOnMs() 1903 {return _statsOn?(System.currentTimeMillis()-_statsStartedAt):0;} 1904 1905 1906 public void statsReset() 1907 { 1908 synchronized(_statsLock) 1909 { 1910 if (_statsOn) 1911 _statsStartedAt=System.currentTimeMillis(); 1912 _requests=0; 1913 _requestsActiveMax=_requestsActive; 1914 _responses1xx=0; 1915 _responses2xx=0; 1916 _responses3xx=0; 1917 _responses4xx=0; 1918 _responses5xx=0; 1919 } 1920 } 1921 1922 1923 1928 public int getRequests() {return _requests;} 1929 1930 1931 1935 public int getRequestsActive() {return _requestsActive;} 1936 1937 1938 1942 public int getRequestsActiveMax() {return _requestsActiveMax;} 1943 1944 1945 1950 public int getResponses1xx() {return _responses1xx;} 1951 1952 1953 1958 public int getResponses2xx() {return _responses2xx;} 1959 1960 1961 1966 public int getResponses3xx() {return _responses3xx;} 1967 1968 1969 1974 public int getResponses4xx() {return _responses4xx;} 1975 1976 1977 1982 public int getResponses5xx() {return _responses5xx;} 1983 1984 1985 1986 1991 public void log(HttpRequest request, 1992 HttpResponse response, 1993 int length) 1994 { 1995 if (_statsOn) 1996 { 1997 synchronized(_statsLock) 1998 { 1999 if (--_requestsActive<0) 2000 _requestsActive=0; 2001 2002 if (response!=null) 2003 { 2004 switch(response.getStatus()/100) 2005 { 2006 case 1: _responses1xx++;break; 2007 case 2: _responses2xx++;break; 2008 case 3: _responses3xx++;break; 2009 case 4: _responses4xx++;break; 2010 case 5: _responses5xx++;break; 2011 } 2012 } 2013 } 2014 } 2015 2016 if (_requestLog!=null && 2017 request!=null && 2018 response!=null) 2019 _requestLog.log(request,response,length); 2020 else if (_httpServer!=null) 2021 _httpServer.log(request,response,length); 2022 } 2023 2024 2025 2026 2027 2029 private static class Scope 2030 { 2031 ClassLoader _classLoader; 2032 HttpContext _httpContext; 2033 } 2034 2035 2038 public String getName() 2039 { 2040 return this.getContextPath(); 2041 } 2042 2043 2046 public HttpContext getHttpContext() 2047 { 2048 return this; 2049 } 2050 2051 2054 public void initialize(HttpContext context) 2055 { 2056 throw new UnsupportedOperationException (); 2057 } 2058 2059 2060 2063 public Resource getBaseResource() 2064 { 2065 return _resources.getBaseResource(); 2066 } 2067 2071 public String getEncodingByMimeType(String type) 2072 { 2073 return _resources.getEncodingByMimeType(type); 2074 } 2075 2078 public Map getEncodingMap() 2079 { 2080 return _resources.getEncodingMap(); 2081 } 2082 2085 public int getMaxCachedFileSize() 2086 { 2087 return _resources.getMaxCachedFileSize(); 2088 } 2089 2092 public int getMaxCacheSize() 2093 { 2094 return _resources.getMaxCacheSize(); 2095 } 2096 2100 public String getMimeByExtension(String filename) 2101 { 2102 return _resources.getMimeByExtension(filename); 2103 } 2104 2107 public Map getMimeMap() 2108 { 2109 return _resources.getMimeMap(); 2110 } 2111 2116 public Resource getResource(String pathInContext) throws IOException 2117 { 2118 return _resources.getResource(pathInContext); 2119 } 2120 2123 public String getResourceBase() 2124 { 2125 return _resources.getResourceBase(); 2126 } 2127 2131 public ResourceMetaData getResourceMetaData(Resource resource) 2132 { 2133 return _resources.getResourceMetaData(resource); 2134 } 2135 2138 public void setBaseResource(Resource base) 2139 { 2140 _resources.setBaseResource(base); 2141 } 2142 2145 public void setEncodingMap(Map encodingMap) 2146 { 2147 _resources.setEncodingMap(encodingMap); 2148 } 2149 2152 public void setMaxCachedFileSize(int maxCachedFileSize) 2153 { 2154 _resources.setMaxCachedFileSize(maxCachedFileSize); 2155 } 2156 2159 public void setMaxCacheSize(int maxCacheSize) 2160 { 2161 _resources.setMaxCacheSize(maxCacheSize); 2162 } 2163 2166 public void setMimeMap(Map mimeMap) 2167 { 2168 _resources.setMimeMap(mimeMap); 2169 } 2170 2174 public void setMimeMapping(String extension, String type) 2175 { 2176 _resources.setMimeMapping(extension, type); 2177 } 2178 2181 public void setResourceBase(String resourceBase) 2182 { 2183 _resources.setResourceBase(resourceBase); 2184 } 2185 2189 public void setTypeEncoding(String mimeType, String encoding) 2190 { 2191 _resources.setTypeEncoding(mimeType, encoding); 2192 } 2193} 2194 | Popular Tags |