1 29 30 package com.caucho.server.webapp; 31 32 import com.caucho.config.ConfigException; 33 import com.caucho.lifecycle.Lifecycle; 34 import com.caucho.loader.ClassLoaderListener; 35 import com.caucho.loader.DynamicClassLoader; 36 import com.caucho.loader.Environment; 37 import com.caucho.loader.EnvironmentClassLoader; 38 import com.caucho.loader.EnvironmentListener; 39 import com.caucho.log.Log; 40 import com.caucho.make.AlwaysModified; 41 import com.caucho.server.cluster.Server; 42 import com.caucho.server.deploy.DeployContainer; 43 import com.caucho.server.deploy.DeployGenerator; 44 import com.caucho.server.dispatch.DispatchBuilder; 45 import com.caucho.server.dispatch.DispatchServer; 46 import com.caucho.server.dispatch.ErrorFilterChain; 47 import com.caucho.server.dispatch.ExceptionFilterChain; 48 import com.caucho.server.dispatch.Invocation; 49 import com.caucho.server.dispatch.InvocationDecoder; 50 import com.caucho.server.e_app.EarConfig; 51 import com.caucho.server.e_app.EarDeployController; 52 import com.caucho.server.e_app.EarDeployGenerator; 53 import com.caucho.server.e_app.EarSingleDeployGenerator; 54 import com.caucho.server.host.Host; 55 import com.caucho.server.log.AbstractAccessLog; 56 import com.caucho.server.log.AccessLog; 57 import com.caucho.server.session.SessionManager; 58 import com.caucho.server.util.CauchoSystem; 59 import com.caucho.util.L10N; 60 import com.caucho.util.LruCache; 61 import com.caucho.vfs.Path; 62 import com.caucho.vfs.Vfs; 63 64 import javax.annotation.PostConstruct; 65 import javax.servlet.FilterChain ; 66 import javax.servlet.RequestDispatcher ; 67 import javax.servlet.ServletException ; 68 import javax.servlet.UnavailableException ; 69 import javax.servlet.http.HttpServletResponse ; 70 import java.io.FileNotFoundException ; 71 import java.util.ArrayList ; 72 import java.util.logging.Level ; 73 import java.util.logging.Logger ; 74 75 78 public class WebAppContainer 79 implements DispatchBuilder, ClassLoaderListener, EnvironmentListener 80 { 81 static final L10N L = new L10N(WebApp.class); 82 static final Logger log = Log.open(WebAppContainer.class); 83 84 private DispatchServer _dispatchServer; 86 87 private EnvironmentClassLoader _classLoader; 89 90 private Path _rootDir; 92 93 private Path _docDir; 95 96 private RewriteInvocation _rewriteInvocation; 98 99 private ArrayList <EarConfig> _earDefaultList 101 = new ArrayList <EarConfig>(); 102 103 106 private DeployContainer<EarDeployController> _earDeploy; 107 private DeployContainer<WebAppController> _appDeploy; 108 private WebAppExpandDeployGenerator _warGenerator; 109 110 private boolean _hasWarGenerator; 111 112 private LruCache<String ,WebAppController> _uriToAppCache 114 = new LruCache<String ,WebAppController>(8192); 115 116 121 122 private ArrayList <WebAppConfig> _webAppDefaultList 124 = new ArrayList <WebAppConfig>(); 125 126 129 134 135 private AbstractAccessLog _accessLog; 136 private ErrorPageManager _errorPageManager; 137 138 private long _startWaitTime = 10000L; 139 140 private Throwable _configException; 141 142 private final Lifecycle _lifecycle = new Lifecycle(); 144 145 148 public WebAppContainer() 149 { 150 this((EnvironmentClassLoader) Thread.currentThread().getContextClassLoader()); 151 } 152 153 156 public WebAppContainer(EnvironmentClassLoader loader) 157 { 158 _rootDir = Vfs.lookup(); 159 _docDir = Vfs.lookup(); 160 161 _classLoader = loader; 162 _errorPageManager = new ErrorPageManager(); 163 _errorPageManager.setWebAppContainer(this); 164 165 169 170 Thread thread = Thread.currentThread(); 171 ClassLoader oldLoader = thread.getContextClassLoader(); 172 try { 173 thread.setContextClassLoader(loader); 174 175 _earDeploy = new DeployContainer<EarDeployController>(); 178 179 _appDeploy = new DeployContainer<WebAppController>(); 180 181 _warGenerator = new WebAppExpandDeployGenerator(_appDeploy, this); 182 } finally { 183 thread.setContextClassLoader(oldLoader); 184 } 185 } 186 187 190 public void setDispatchServer(DispatchServer server) 191 { 192 _dispatchServer = server; 193 } 194 195 198 public DispatchServer getDispatchServer() 199 { 200 return _dispatchServer; 201 } 202 203 206 public ClassLoader getClassLoader() 207 { 208 return _classLoader; 209 } 210 211 214 public void setEnvironmentClassLoader(EnvironmentClassLoader loader) 215 { 216 _classLoader = loader; 217 } 218 219 222 public Host getHost() 223 { 224 return null; 225 } 226 227 230 public Path getRootDirectory() 231 { 232 return _rootDir; 233 } 234 235 238 public void setRootDirectory(Path path) 239 { 240 _rootDir = path; 241 242 Vfs.setPwd(path, getClassLoader()); 243 } 244 245 248 public Path getDocumentDirectory() 249 { 250 return _docDir; 251 } 252 253 256 public void setDocumentDirectory(Path path) 257 { 258 _docDir = path; 259 } 260 261 264 public void setDocDir(Path path) 265 { 266 setDocumentDirectory(path); 267 } 268 269 272 public AbstractAccessLog createAccessLog() 273 { 274 return new AccessLog(); 275 } 276 277 280 public void setAccessLog(AbstractAccessLog log) 281 { 282 _accessLog = log; 283 284 Environment.setAttribute("caucho.server.access-log", log); 285 } 286 287 290 public void addErrorPage(ErrorPage errorPage) 291 { 292 _errorPageManager.addErrorPage(errorPage); 293 } 294 295 298 public ErrorPageManager getErrorPageManager() 299 { 300 return _errorPageManager; 301 } 302 303 306 public void setConfigException(Throwable e) 307 { 308 _configException = e; 309 } 310 311 314 public DeployContainer<WebAppController> getWebAppGenerator() 315 { 316 return _appDeploy; 317 } 318 319 322 public SessionManager getSessionManager() 323 { 324 return null; 325 } 326 327 330 public RewriteInvocation createRewriteDispatch() 331 { 332 if (_rewriteInvocation == null) { 333 _rewriteInvocation = new RewriteInvocation(); 334 } 335 336 return _rewriteInvocation; 337 } 338 339 342 public boolean isModified() 343 { 344 return _lifecycle.isDestroyed() || _classLoader.isModified(); 345 } 346 347 350 public void addWebApp(WebAppConfig config) 351 throws Exception 352 { 353 if (config.getURLRegexp() != null) { 354 DeployGenerator<WebAppController> deploy = new WebAppRegexpDeployGenerator(_appDeploy, 355 this, config); 356 _appDeploy.add(deploy); 357 return; 358 } 359 360 WebAppController oldEntry = _appDeploy.findController(config.getContextPath()); 361 362 if (oldEntry != null && oldEntry.getSourceType().equals("single")) { 363 throw new ConfigException(L.l("duplicate web-app '{0}' forbidden.", 364 config.getId())); 365 } 366 367 WebAppSingleDeployGenerator deploy = new WebAppSingleDeployGenerator(_appDeploy, 368 this, config); 369 deploy.deploy(); 370 371 _appDeploy.add(deploy); 372 } 373 374 377 void removeWebApp(WebAppController entry) 378 { 379 _appDeploy.remove(entry.getContextPath()); 380 381 clearCache(); 382 } 383 384 387 public void addWebAppDefault(WebAppConfig init) 388 { 389 _webAppDefaultList.add(init); 390 } 391 392 395 public ArrayList <WebAppConfig> getWebAppDefaultList() 396 { 397 return _webAppDefaultList; 398 } 399 400 403 public WebAppExpandDeployGenerator createWarDeploy() 404 { 405 return new WebAppExpandDeployGenerator(_appDeploy, this); 406 } 407 408 411 public WebAppExpandDeployGenerator createWebAppDeploy() 412 { 413 return createWarDeploy(); 414 } 415 416 419 public void addWebAppDeploy(WebAppExpandDeployGenerator deploy) 420 throws ConfigException 421 { 422 addWarDeploy(deploy); 423 } 424 425 428 public void addWarDeploy(WebAppExpandDeployGenerator webAppDeploy) 429 throws ConfigException 430 { 431 assert webAppDeploy.getContainer() == this; 432 433 if (! _hasWarGenerator) { 434 _hasWarGenerator = true; 435 _warGenerator = webAppDeploy; 436 } 437 438 _appDeploy.add(webAppDeploy); 439 } 440 441 444 public void addDeploy(DeployGenerator deploy) 445 throws ConfigException 446 { 447 if (deploy instanceof WebAppExpandDeployGenerator) 448 addWebAppDeploy((WebAppExpandDeployGenerator) deploy); 449 else 450 _appDeploy.add(deploy); 451 } 452 453 456 public void removeWebAppDeploy(DeployGenerator deploy) 457 { 458 _appDeploy.remove(deploy); 459 } 460 461 464 public void updateWebAppDeploy(String name) 465 throws Throwable 466 { 467 clearCache(); 468 469 _appDeploy.update(); 470 WebAppController controller = _appDeploy.update(name); 471 472 if (controller != null) { 473 Throwable configException = controller.getConfigException(); 474 475 if (configException != null) 476 throw configException; 477 } 478 } 479 480 483 public void addApplication(EarConfig config) 484 { 485 DeployGenerator<EarDeployController> deploy = new EarSingleDeployGenerator(_earDeploy, this, config); 486 487 _earDeploy.add(deploy); 488 } 489 490 493 public void updateEarDeploy(String name) 494 throws Throwable 495 { 496 clearCache(); 497 498 _earDeploy.update(); 499 EarDeployController entry = _earDeploy.update(name); 500 501 if (entry != null) { 502 entry.start(); 503 504 Throwable configException = entry.getConfigException(); 505 506 if (configException != null) 507 throw configException; 508 } 509 } 510 511 514 public void expandEarDeploy(String name) 515 { 516 clearCache(); 517 518 _earDeploy.update(); 519 EarDeployController entry = _earDeploy.update(name); 520 521 if (entry != null) 522 entry.start(); 523 } 524 525 528 public void startEarDeploy(String name) 529 { 530 clearCache(); 531 532 _earDeploy.update(); 533 EarDeployController entry = _earDeploy.update(name); 534 535 if (entry != null) 536 entry.start(); 537 } 538 539 542 public void addEarDefault(EarConfig config) 543 { 544 _earDefaultList.add(config); 545 } 546 547 550 public ArrayList <EarConfig> getEarDefaultList() 551 { 552 return _earDefaultList; 553 } 554 555 558 public EarDeployGenerator createEarDeploy() 559 throws Exception 560 { 561 return new EarDeployGenerator(_earDeploy, this); 562 } 563 564 567 public void addEarDeploy(EarDeployGenerator earDeploy) 568 throws Exception 569 { 570 _earDeploy.add(earDeploy); 571 572 _appDeploy.add(new WebAppEarDeployGenerator(_appDeploy, this, earDeploy)); 575 576 579 } 580 581 584 public String getURL() 585 { 586 return ""; 587 } 588 589 592 public String getHostName() 593 { 594 return ""; 595 } 596 597 599 602 public void setWarDir(Path warDir) 603 throws ConfigException 604 { 605 _warGenerator.setPath(warDir); 606 607 if (! _hasWarGenerator) { 608 _hasWarGenerator = true; 609 addWebAppDeploy(_warGenerator); 610 } 611 } 612 613 616 public Path getWarDir() 617 { 618 return _warGenerator.getPath(); 619 } 620 621 624 public void setWarExpandDir(Path warDir) 625 { 626 _warGenerator.setExpandDirectory(warDir); 627 } 628 629 632 public Path getWarExpandDir() 633 { 634 return _warGenerator.getExpandDirectory(); 635 } 636 637 640 @PostConstruct 641 public void init() 642 throws Exception 643 { 644 if (! _lifecycle.toInitializing()) 645 return; 646 647 log.fine(this + " initializing"); 648 649 _lifecycle.toInit(); 650 } 651 652 655 protected void start() 656 { 657 if (! _lifecycle.toActive()) 658 return; 659 660 667 668 try { 669 _appDeploy.start(); 670 } catch (Throwable e) { 671 log.log(Level.WARNING, e.toString(), e); 672 } 673 } 674 675 678 public void clearCache() 679 { 680 if (_dispatchServer != null) 681 _dispatchServer.clearCache(); 682 683 _uriToAppCache.clear(); 684 } 685 686 689 public void buildInvocation(Invocation invocation) 690 throws Exception 691 { 692 if (_configException != null) { 693 FilterChain chain = new ExceptionFilterChain(_configException); 694 invocation.setFilterChain(chain); 695 invocation.setDependency(AlwaysModified.create()); 696 return; 697 } 698 else if (! _lifecycle.waitForActive(_startWaitTime)) { 699 int code = HttpServletResponse.SC_SERVICE_UNAVAILABLE; 700 FilterChain chain = new ErrorFilterChain(code); 701 invocation.setFilterChain(chain); 702 703 if (_dispatchServer instanceof Server) { 704 Server server = (Server) _dispatchServer; 705 invocation.setWebApp(server.getErrorWebApp()); 706 } 707 708 invocation.setDependency(AlwaysModified.create()); 709 return; 710 } 711 712 if (_rewriteInvocation != null) { 713 FilterChain chain = _rewriteInvocation.map(invocation.getURI(), 714 invocation); 715 716 if (chain != null) { 717 Server server = (Server) _dispatchServer; 718 invocation.setWebApp(server.getErrorWebApp()); 719 invocation.setFilterChain(chain); 720 return; 721 } 722 } 723 724 WebApp app = getWebApp(invocation, true); 725 726 if (app != null) 727 app.buildInvocation(invocation); 728 else { 729 int code = HttpServletResponse.SC_NOT_FOUND; 730 FilterChain chain = new ErrorFilterChain(code); 731 ContextFilterChain contextChain = new ContextFilterChain(chain); 732 contextChain.setErrorPageManager(_errorPageManager); 733 invocation.setFilterChain(contextChain); 734 invocation.setDependency(AlwaysModified.create()); 735 } 736 } 737 738 741 public RequestDispatcher getRequestDispatcher(String url) 742 { 743 745 if (url == null) 746 throw new IllegalArgumentException (L.l("request dispatcher url can't be null.")); 747 else if (! url.startsWith("/")) 748 throw new IllegalArgumentException (L.l("request dispatcher url `{0}' must be absolute", url)); 749 750 Invocation includeInvocation = new Invocation(); 751 Invocation forwardInvocation = new Invocation(); 752 Invocation errorInvocation = new Invocation(); 753 InvocationDecoder decoder = new InvocationDecoder(); 754 755 String rawURI = url; 756 757 try { 758 decoder.splitQuery(includeInvocation, rawURI); 759 decoder.splitQuery(forwardInvocation, rawURI); 760 decoder.splitQuery(errorInvocation, rawURI); 761 762 buildIncludeInvocation(includeInvocation); 763 buildForwardInvocation(forwardInvocation); 764 buildErrorInvocation(errorInvocation); 765 766 RequestDispatcher disp = new RequestDispatcherImpl(includeInvocation, 767 forwardInvocation, 768 errorInvocation, 769 getWebApp(includeInvocation, false)); 770 771 return disp; 772 } catch (Exception e) { 773 log.log(Level.FINE, e.toString(), e); 774 775 return null; 776 } 777 } 778 779 782 public void buildIncludeInvocation(Invocation invocation) 783 throws ServletException 784 { 785 WebApp app = buildSubInvocation(invocation); 786 787 if (app != null) 788 app.buildIncludeInvocation(invocation); 789 } 790 791 794 public void buildForwardInvocation(Invocation invocation) 795 throws ServletException 796 { 797 WebApp app = buildSubInvocation(invocation); 798 799 if (app != null) 800 app.buildForwardInvocation(invocation); 801 } 802 803 806 public void buildErrorInvocation(Invocation invocation) 807 throws ServletException 808 { 809 WebApp app = buildSubInvocation(invocation); 810 811 if (app != null) 812 app.buildErrorInvocation(invocation); 813 } 814 815 818 public void buildLoginInvocation(Invocation invocation) 819 throws ServletException 820 { 821 WebApp app = buildSubInvocation(invocation); 822 823 if (app != null) 824 app.buildErrorInvocation(invocation); 825 } 826 827 830 private WebApp buildSubInvocation(Invocation invocation) 831 { 832 if (! _lifecycle.waitForActive(_startWaitTime)) { 833 UnavailableException e; 834 e = new UnavailableException (invocation.getURI()); 835 836 FilterChain chain = new ExceptionFilterChain(e); 837 invocation.setFilterChain(chain); 838 invocation.setDependency(AlwaysModified.create()); 839 return null; 840 } 841 842 WebAppController appController = getWebAppController(invocation); 843 844 if (appController == null) { 845 String url = invocation.getURI(); 846 847 FileNotFoundException e = new FileNotFoundException (url); 848 849 FilterChain chain = new ExceptionFilterChain(e); 850 invocation.setFilterChain(chain); 851 invocation.setDependency(AlwaysModified.create()); 852 return null; 853 } 854 855 WebApp app = appController.subrequest(); 856 857 if (app == null) { 858 UnavailableException e; 859 e = new UnavailableException (invocation.getURI()); 860 861 FilterChain chain = new ExceptionFilterChain(e); 862 invocation.setFilterChain(chain); 863 invocation.setDependency(AlwaysModified.create()); 864 return null; 865 } 866 867 return app; 868 } 869 870 873 private WebApp getWebApp(Invocation invocation, 874 boolean enableRedeploy) 875 throws ServletException 876 { 877 try { 878 WebAppController controller = getWebAppController(invocation); 879 880 if (controller != null) { 881 WebApp app; 882 883 if (enableRedeploy) 884 app = controller.request(); 885 else 886 app = controller.subrequest(); 887 888 if (app == null) { 889 return null; 890 } 891 892 invocation.setWebApp(app); 893 894 return app; 895 } 896 else { 897 return null; 898 } 899 } catch (Exception e) { 900 throw new ServletException (e); 901 } 902 } 903 904 912 private WebAppController getWebAppController(Invocation invocation) 913 { 914 WebAppController controller = findByURI(invocation.getURI()); 915 916 if (controller == null) 917 return null; 918 919 String invocationURI = invocation.getURI(); 920 921 String contextPath = controller.getContextPath(invocationURI); 922 923 invocation.setContextPath(invocationURI.substring(0, contextPath.length())); 924 925 String uri = invocationURI.substring(contextPath.length()); 926 invocation.setContextURI(uri); 927 928 return controller; 929 } 930 931 934 public WebApp findWebAppByURI(String uri) 935 throws Exception 936 { 937 WebAppController controller = findByURI(uri); 938 939 if (controller != null) 940 return controller.request(); 941 else 942 return null; 943 } 944 945 948 public WebApp findSubWebAppByURI(String uri) 949 throws Exception 950 { 951 WebAppController controller = findByURI(uri); 952 953 if (controller != null) 954 return controller.subrequest(); 955 else 956 return null; 957 } 958 959 962 public WebAppController findByURI(String uri) 963 { 964 if (CauchoSystem.isCaseInsensitive()) 965 uri = uri.toLowerCase(); 966 967 return findByURIImpl(uri); 968 } 969 970 973 private WebAppController findByURIImpl(String subURI) 974 { 975 WebAppController controller = _uriToAppCache.get(subURI); 976 977 if (controller != null) { 978 return controller; 979 } 980 981 int length = subURI.length(); 982 int p = subURI.lastIndexOf('/'); 983 984 if (p < 0 || p < length - 1) { controller = _appDeploy.findController(subURI); 986 987 if (controller != null) { 988 _uriToAppCache.put(subURI, controller); 989 990 return controller; 991 } 992 } 993 994 if (p >= 0) { 995 controller = findByURIImpl(subURI.substring(0, p)); 996 997 if (controller != null) 998 _uriToAppCache.put(subURI, controller); 999 } 1000 1001 return controller; 1002 } 1003 1004 1007 public ArrayList <WebAppController> getWebAppList() 1008 { 1009 return _appDeploy.getControllers(); 1010 } 1011 1012 1015 public ArrayList <EarDeployController> getEntAppList() 1016 { 1017 return _earDeploy.getControllers(); 1018 } 1019 1020 1023 public final boolean isDestroyed() 1024 { 1025 return _lifecycle.isDestroyed(); 1026 } 1027 1028 1031 public final boolean isActive() 1032 { 1033 return _lifecycle.isActive(); 1034 } 1035 1036 1039 public boolean stop() 1040 { 1041 if (! _lifecycle.toStop()) 1042 return false; 1043 1044 _earDeploy.stop(); 1045 _appDeploy.stop(); 1046 1047 return true; 1048 } 1049 1050 1053 public void destroy() 1054 { 1055 stop(); 1056 1057 if (! _lifecycle.toDestroy()) 1058 return; 1059 1060 _earDeploy.destroy(); 1061 _appDeploy.destroy(); 1062 } 1063 1064 1067 public void classLoaderInit(DynamicClassLoader loader) 1068 { 1069 } 1070 1071 1074 public void classLoaderDestroy(DynamicClassLoader loader) 1075 { 1076 destroy(); 1077 } 1078 1079 1082 public void environmentStart(EnvironmentClassLoader loader) 1083 { 1084 } 1085 1086 1089 public void environmentStop(EnvironmentClassLoader loader) 1090 { 1091 stop(); 1092 } 1093} 1094 | Popular Tags |