| 1 17 18 19 package org.apache.catalina.startup; 20 21 22 import java.io.File ; 23 import java.io.FileInputStream ; 24 import java.io.FileNotFoundException ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.net.URL ; 28 import java.util.Map ; 29 import java.util.Properties ; 30 31 import javax.servlet.ServletContext ; 32 33 import org.apache.catalina.Authenticator; 34 import org.apache.catalina.Container; 35 import org.apache.catalina.Context; 36 import org.apache.catalina.Engine; 37 import org.apache.catalina.Globals; 38 import org.apache.catalina.Host; 39 import org.apache.catalina.Lifecycle; 40 import org.apache.catalina.LifecycleEvent; 41 import org.apache.catalina.LifecycleListener; 42 import org.apache.catalina.Pipeline; 43 import org.apache.catalina.Valve; 44 import org.apache.catalina.Wrapper; 45 import org.apache.catalina.core.ContainerBase; 46 import org.apache.catalina.core.StandardContext; 47 import org.apache.catalina.core.StandardEngine; 48 import org.apache.catalina.core.StandardHost; 49 import org.apache.catalina.deploy.ErrorPage; 50 import org.apache.catalina.deploy.FilterDef; 51 import org.apache.catalina.deploy.FilterMap; 52 import org.apache.catalina.deploy.LoginConfig; 53 import org.apache.catalina.deploy.SecurityConstraint; 54 import org.apache.catalina.util.StringManager; 55 import org.apache.tomcat.util.digester.Digester; 56 import org.apache.tomcat.util.digester.RuleSet; 57 import org.xml.sax.ErrorHandler ; 58 import org.xml.sax.InputSource ; 59 import org.xml.sax.SAXParseException ; 60 61 69 70 public class ContextConfig 71 implements LifecycleListener { 72 73 protected static org.apache.commons.logging.Log log= 74 org.apache.commons.logging.LogFactory.getLog( ContextConfig.class ); 75 76 78 79 82 protected Map customAuthenticators; 83 84 85 90 protected static Properties authenticators = null; 91 92 93 96 protected Context context = null; 97 98 99 102 protected String defaultContextXml = null; 103 104 105 108 protected String defaultWebXml = null; 109 110 111 114 protected boolean ok = false; 115 116 117 120 protected SAXParseException parseException = null; 121 122 123 126 protected String originalDocBase = null; 127 128 129 132 protected static final StringManager sm = 133 StringManager.getManager(Constants.Package); 134 135 136 140 protected static Digester contextDigester = null; 141 142 143 147 protected static Digester webDigester = null; 148 149 150 153 protected static WebRuleSet webRuleSet = new WebRuleSet(); 154 155 158 protected static boolean xmlValidation = false; 159 160 161 164 protected static boolean xmlNamespaceAware = false; 165 166 167 170 protected static long deploymentCount = 0L; 171 172 173 protected static final LoginConfig DUMMY_LOGIN_CONFIG = 174 new LoginConfig("NONE", null, null, null); 175 176 177 179 180 183 public String getDefaultWebXml() { 184 if( defaultWebXml == null ) { 185 defaultWebXml=Constants.DefaultWebXml; 186 } 187 188 return (this.defaultWebXml); 189 190 } 191 192 193 198 public void setDefaultWebXml(String path) { 199 200 this.defaultWebXml = path; 201 202 } 203 204 205 208 public String getDefaultContextXml() { 209 if( defaultContextXml == null ) { 210 defaultContextXml=Constants.DefaultContextXml; 211 } 212 213 return (this.defaultContextXml); 214 215 } 216 217 218 223 public void setDefaultContextXml(String path) { 224 225 this.defaultContextXml = path; 226 227 } 228 229 230 236 public void setCustomAuthenticators(Map customAuthenticators) { 237 this.customAuthenticators = customAuthenticators; 238 } 239 240 241 243 244 249 public void lifecycleEvent(LifecycleEvent event) { 250 251 try { 253 context = (Context ) event.getLifecycle(); 254 } catch (ClassCastException e) { 255 log.error(sm.getString("contextConfig.cce", event.getLifecycle()), e); 256 return; 257 } 258 259 if (event.getType().equals(Lifecycle.START_EVENT)) { 261 start(); 262 } else if (event.getType().equals(StandardContext.BEFORE_START_EVENT)) { 263 beforeStart(); 264 } else if (event.getType().equals(StandardContext.AFTER_START_EVENT)) { 265 if (originalDocBase != null) { 267 String docBase = context.getDocBase(); 268 context.setDocBase(originalDocBase); 269 originalDocBase = docBase; 270 } 271 } else if (event.getType().equals(Lifecycle.STOP_EVENT)) { 272 if (originalDocBase != null) { 273 String docBase = context.getDocBase(); 274 context.setDocBase(originalDocBase); 275 originalDocBase = docBase; 276 } 277 stop(); 278 } else if (event.getType().equals(Lifecycle.INIT_EVENT)) { 279 init(); 280 } else if (event.getType().equals(Lifecycle.DESTROY_EVENT)) { 281 destroy(); 282 } 283 284 } 285 286 287 289 290 293 protected void applicationAnnotationsConfig() { 294 295 long t1=System.currentTimeMillis(); 296 297 WebAnnotationSet.loadApplicationAnnotations(context); 298 299 long t2=System.currentTimeMillis(); 300 if (context instanceof StandardContext) { 301 ((StandardContext) context).setStartupTime(t2-t1+ 302 ((StandardContext) context).getStartupTime()); 303 } 304 } 305 306 307 310 protected void applicationWebConfig() { 311 312 String altDDName = null; 313 314 InputStream stream = null; 316 ServletContext servletContext = context.getServletContext(); 317 if (servletContext != null) { 318 altDDName = (String )servletContext.getAttribute( 319 Globals.ALT_DD_ATTR); 320 if (altDDName != null) { 321 try { 322 stream = new FileInputStream (altDDName); 323 } catch (FileNotFoundException e) { 324 log.error(sm.getString("contextConfig.altDDNotFound", 325 altDDName)); 326 } 327 } 328 else { 329 stream = servletContext.getResourceAsStream 330 (Constants.ApplicationWebXml); 331 } 332 } 333 if (stream == null) { 334 if (log.isDebugEnabled()) { 335 log.debug(sm.getString("contextConfig.applicationMissing") + " " + context); 336 } 337 return; 338 } 339 340 long t1=System.currentTimeMillis(); 341 342 if (webDigester == null){ 343 webDigester = createWebDigester(); 344 } 345 346 URL url=null; 347 synchronized (webDigester) { 349 try { 350 if (altDDName != null) { 351 url = new File (altDDName).toURL(); 352 } else { 353 url = servletContext.getResource( 354 Constants.ApplicationWebXml); 355 } 356 if( url!=null ) { 357 InputSource is = new InputSource (url.toExternalForm()); 358 is.setByteStream(stream); 359 if (context instanceof StandardContext) { 360 ((StandardContext) context).setReplaceWelcomeFiles(true); 361 } 362 webDigester.push(context); 363 webDigester.setErrorHandler(new ContextErrorHandler()); 364 365 if(log.isDebugEnabled()) { 366 log.debug("Parsing application web.xml file at " + url.toExternalForm()); 367 } 368 369 webDigester.parse(is); 370 371 if (parseException != null) { 372 ok = false; 373 } 374 } else { 375 log.info("No web.xml, using defaults " + context ); 376 } 377 } catch (SAXParseException e) { 378 log.error(sm.getString("contextConfig.applicationParse", url.toExternalForm()), e); 379 log.error(sm.getString("contextConfig.applicationPosition", 380 "" + e.getLineNumber(), 381 "" + e.getColumnNumber())); 382 ok = false; 383 } catch (Exception e) { 384 log.error(sm.getString("contextConfig.applicationParse", url.toExternalForm()), e); 385 ok = false; 386 } finally { 387 webDigester.reset(); 388 parseException = null; 389 try { 390 if (stream != null) { 391 stream.close(); 392 } 393 } catch (IOException e) { 394 log.error(sm.getString("contextConfig.applicationClose"), e); 395 } 396 } 397 } 398 webRuleSet.recycle(); 399 400 long t2=System.currentTimeMillis(); 401 if (context instanceof StandardContext) { 402 ((StandardContext) context).setStartupTime(t2-t1); 403 } 404 } 405 406 407 411 protected synchronized void authenticatorConfig() { 412 413 SecurityConstraint constraints[] = context.findConstraints(); 415 if ((constraints == null) || (constraints.length == 0)) 416 return; 417 LoginConfig loginConfig = context.getLoginConfig(); 418 if (loginConfig == null) { 419 loginConfig = DUMMY_LOGIN_CONFIG; 420 context.setLoginConfig(loginConfig); 421 } 422 423 if (context instanceof Authenticator) 425 return; 426 if (context instanceof ContainerBase) { 427 Pipeline pipeline = ((ContainerBase) context).getPipeline(); 428 if (pipeline != null) { 429 Valve basic = pipeline.getBasic(); 430 if ((basic != null) && (basic instanceof Authenticator)) 431 return; 432 Valve valves[] = pipeline.getValves(); 433 for (int i = 0; i < valves.length; i++) { 434 if (valves[i] instanceof Authenticator) 435 return; 436 } 437 } 438 } else { 439 return; } 441 442 if (context.getRealm() == null) { 444 log.error(sm.getString("contextConfig.missingRealm")); 445 ok = false; 446 return; 447 } 448 449 454 Valve authenticator = null; 455 if (customAuthenticators != null) { 456 authenticator = (Valve) 457 customAuthenticators.get(loginConfig.getAuthMethod()); 458 } 459 if (authenticator == null) { 460 if (authenticators == null) { 462 try { 463 InputStream is=this.getClass().getClassLoader().getResourceAsStream("org/apache/catalina/startup/Authenticators.properties"); 464 if( is!=null ) { 465 authenticators = new Properties (); 466 authenticators.load(is); 467 } else { 468 log.error(sm.getString( 469 "contextConfig.authenticatorResources")); 470 ok=false; 471 return; 472 } 473 } catch (IOException e) { 474 log.error(sm.getString( 475 "contextConfig.authenticatorResources"), e); 476 ok = false; 477 return; 478 } 479 } 480 481 String authenticatorName = null; 483 authenticatorName = 484 authenticators.getProperty(loginConfig.getAuthMethod()); 485 if (authenticatorName == null) { 486 log.error(sm.getString("contextConfig.authenticatorMissing", 487 loginConfig.getAuthMethod())); 488 ok = false; 489 return; 490 } 491 492 try { 494 Class authenticatorClass = Class.forName(authenticatorName); 495 authenticator = (Valve) authenticatorClass.newInstance(); 496 } catch (Throwable t) { 497 log.error(sm.getString( 498 "contextConfig.authenticatorInstantiate", 499 authenticatorName), 500 t); 501 ok = false; 502 } 503 } 504 505 if (authenticator != null && context instanceof ContainerBase) { 506 Pipeline pipeline = ((ContainerBase) context).getPipeline(); 507 if (pipeline != null) { 508 ((ContainerBase) context).addValve(authenticator); 509 if (log.isDebugEnabled()) { 510 log.debug(sm.getString( 511 "contextConfig.authenticatorConfigured", 512 loginConfig.getAuthMethod())); 513 } 514 } 515 } 516 517 } 518 519 520 524 protected static Digester createWebDigester() { 525 Digester webDigester = 526 createWebXmlDigester(xmlNamespaceAware, xmlValidation); 527 return webDigester; 528 } 529 530 531 535 public static Digester createWebXmlDigester(boolean namespaceAware, 536 boolean validation) { 537 538 Digester webDigester = DigesterFactory.newDigester(xmlValidation, 539 xmlNamespaceAware, 540 webRuleSet); 541 return webDigester; 542 } 543 544 545 549 protected Digester createContextDigester() { 550 Digester digester = new Digester(); 551 digester.setValidating(false); 552 RuleSet contextRuleSet = new ContextRuleSet("", false); 553 digester.addRuleSet(contextRuleSet); 554 RuleSet namingRuleSet = new NamingRuleSet("Context/"); 555 digester.addRuleSet(namingRuleSet); 556 return digester; 557 } 558 559 560 protected String getBaseDir() { 561 Container engineC=context.getParent().getParent(); 562 if( engineC instanceof StandardEngine ) { 563 return ((StandardEngine)engineC).getBaseDir(); 564 } 565 return System.getProperty("catalina.base"); 566 } 567 568 573 protected void defaultWebConfig() { 574 long t1=System.currentTimeMillis(); 575 576 if( defaultWebXml==null && context instanceof StandardContext ) { 578 defaultWebXml=((StandardContext)context).getDefaultWebXml(); 579 } 580 if( defaultWebXml==null ) getDefaultWebXml(); 582 583 File file = new File (this.defaultWebXml); 584 if (!file.isAbsolute()) { 585 file = new File (getBaseDir(), 586 this.defaultWebXml); 587 } 588 589 InputStream stream = null; 590 InputSource source = null; 591 592 try { 593 if ( ! file.exists() ) { 594 stream = getClass().getClassLoader() 596 .getResourceAsStream(defaultWebXml); 597 if( stream != null ) { 598 source = new InputSource  599 (getClass().getClassLoader() 600 .getResource(defaultWebXml).toString()); 601 } 602 if( stream== null ) { 603 stream = getClass().getClassLoader() 605 .getResourceAsStream("web-embed.xml"); 606 if( stream != null ) { 607 source = new InputSource  608 (getClass().getClassLoader() 609 .getResource("web-embed.xml").toString()); 610 } 611 } 612 613 if( stream== null ) { 614 log.info("No default web.xml"); 615 } 616 } else { 617 source = 618 new InputSource ("file://" + file.getAbsolutePath()); 619 stream = new FileInputStream (file); 620 context.addWatchedResource(file.getAbsolutePath()); 621 } 622 } catch (Exception e) { 623 log.error(sm.getString("contextConfig.defaultMissing") 624 + " " + defaultWebXml + " " + file , e); 625 } 626 627 if (webDigester == null){ 628 webDigester = createWebDigester(); 629 } 630 631 if (stream != null) { 632 processDefaultWebConfig(webDigester, stream, source); 633 webRuleSet.recycle(); 634 } 635 636 long t2=System.currentTimeMillis(); 637 if( (t2-t1) > 200 ) 638 log.debug("Processed default web.xml " + file + " " + ( t2-t1)); 639 640 stream = null; 641 source = null; 642 643 String resourceName = getHostConfigPath(Constants.HostWebXml); 644 file = new File (getConfigBase(), resourceName); 645 646 try { 647 if ( ! file.exists() ) { 648 stream = getClass().getClassLoader() 650 .getResourceAsStream(resourceName); 651 if( stream != null ) { 652 source = new InputSource  653 (getClass().getClassLoader() 654 .getResource(resourceName).toString()); 655 } 656 } else { 657 source = 658 new InputSource ("file://" + file.getAbsolutePath()); 659 stream = new FileInputStream (file); 660 } 661 } catch (Exception e) { 662 log.error(sm.getString("contextConfig.defaultMissing") 663 + " " + resourceName + " " + file , e); 664 } 665 666 if (stream != null) { 667 processDefaultWebConfig(webDigester, stream, source); 668 webRuleSet.recycle(); 669 } 670 671 } 672 673 674 677 protected void processDefaultWebConfig(Digester digester, InputStream stream, 678 InputSource source) { 679 680 if (log.isDebugEnabled()) 681 log.debug("Processing context [" + context.getName() 682 + "] web configuration resource " + source.getSystemId()); 683 684 synchronized (digester) { 686 try { 687 source.setByteStream(stream); 688 689 if (context instanceof StandardContext) 690 ((StandardContext) context).setReplaceWelcomeFiles(true); 691 digester.setClassLoader(this.getClass().getClassLoader()); 692 digester.setUseContextClassLoader(false); 693 digester.push(context); 694 digester.setErrorHandler(new ContextErrorHandler()); 695 digester.parse(source); 696 if (parseException != null) { 697 ok = false; 698 } 699 } catch (SAXParseException e) { 700 log.error(sm.getString("contextConfig.defaultParse"), e); 701 log.error(sm.getString("contextConfig.defaultPosition", 702 "" + e.getLineNumber(), 703 "" + e.getColumnNumber())); 704 ok = false; 705 } catch (Exception e) { 706 log.error(sm.getString("contextConfig.defaultParse"), e); 707 ok = false; 708 } finally { 709 digester.reset(); 710 parseException = null; 711 try { 712 if (stream != null) { 713 stream.close(); 714 } 715 } catch (IOException e) { 716 log.error(sm.getString("contextConfig.defaultClose"), e); 717 } 718 } 719 } 720 } 721 722 723 726 protected void contextConfig() { 727 728 if( defaultContextXml==null && context instanceof StandardContext ) { 730 defaultContextXml = ((StandardContext)context).getDefaultContextXml(); 731 } 732 if( defaultContextXml==null ) getDefaultContextXml(); 734 735 if (!context.getOverride()) { 736 processContextConfig(new File (getBaseDir()), defaultContextXml); 737 processContextConfig(getConfigBase(), getHostConfigPath(Constants.HostContextXml)); 738 } 739 if (context.getConfigFile() != null) 740 processContextConfig(new File (context.getConfigFile()), null); 741 742 } 743 744 745 748 protected void processContextConfig(File baseDir, String resourceName) { 749 750 if (log.isDebugEnabled()) 751 log.debug("Processing context [" + context.getName() 752 + "] configuration file " + baseDir + " " + resourceName); 753 754 InputSource source = null; 755 InputStream stream = null; 756 757 File file = baseDir; 758 if (resourceName != null) { 759 file = new File (baseDir, resourceName); 760 } 761 762 try { 763 if ( !file.exists() ) { 764 if (resourceName != null) { 765 stream = getClass().getClassLoader() 767 .getResourceAsStream(resourceName); 768 if( stream != null ) { 769 source = new InputSource  770 (getClass().getClassLoader() 771 .getResource(resourceName).toString()); 772 } 773 } 774 } else { 775 source = 776 new InputSource ("file://" + file.getAbsolutePath()); 777 stream = new |