KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > core > StandardContext


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18
19 package org.apache.catalina.core;
20
21 import java.io.BufferedReader JavaDoc;
22 import java.io.File JavaDoc;
23 import java.io.FileInputStream JavaDoc;
24 import java.io.FileOutputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.InputStream JavaDoc;
27 import java.io.InputStreamReader JavaDoc;
28 import java.io.ObjectOutputStream JavaDoc;
29 import java.io.Serializable JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Hashtable JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.Stack JavaDoc;
35 import java.util.TreeMap JavaDoc;
36
37 import javax.management.AttributeNotFoundException JavaDoc;
38 import javax.management.ListenerNotFoundException JavaDoc;
39 import javax.management.MBeanNotificationInfo JavaDoc;
40 import javax.management.MBeanRegistrationException JavaDoc;
41 import javax.management.MBeanServer JavaDoc;
42 import javax.management.MalformedObjectNameException JavaDoc;
43 import javax.management.Notification JavaDoc;
44 import javax.management.NotificationBroadcasterSupport JavaDoc;
45 import javax.management.NotificationEmitter JavaDoc;
46 import javax.management.NotificationFilter JavaDoc;
47 import javax.management.NotificationListener JavaDoc;
48 import javax.management.ObjectName JavaDoc;
49 import javax.naming.NamingException JavaDoc;
50 import javax.naming.directory.DirContext JavaDoc;
51 import javax.servlet.FilterConfig JavaDoc;
52 import javax.servlet.ServletContext JavaDoc;
53 import javax.servlet.ServletContextAttributeListener JavaDoc;
54 import javax.servlet.ServletContextEvent JavaDoc;
55 import javax.servlet.ServletContextListener JavaDoc;
56 import javax.servlet.ServletException JavaDoc;
57 import javax.servlet.ServletRequestAttributeListener JavaDoc;
58 import javax.servlet.ServletRequestListener JavaDoc;
59 import javax.servlet.http.HttpSessionAttributeListener JavaDoc;
60 import javax.servlet.http.HttpSessionListener JavaDoc;
61
62 import org.apache.AnnotationProcessor;
63 import org.apache.catalina.Container;
64 import org.apache.catalina.ContainerListener;
65 import org.apache.catalina.Context;
66 import org.apache.catalina.Engine;
67 import org.apache.catalina.Globals;
68 import org.apache.catalina.Host;
69 import org.apache.catalina.InstanceListener;
70 import org.apache.catalina.Lifecycle;
71 import org.apache.catalina.LifecycleException;
72 import org.apache.catalina.LifecycleListener;
73 import org.apache.catalina.Loader;
74 import org.apache.catalina.Manager;
75 import org.apache.catalina.Wrapper;
76 import org.apache.catalina.deploy.ApplicationParameter;
77 import org.apache.catalina.deploy.ErrorPage;
78 import org.apache.catalina.deploy.FilterDef;
79 import org.apache.catalina.deploy.FilterMap;
80 import org.apache.catalina.deploy.LoginConfig;
81 import org.apache.catalina.deploy.MessageDestination;
82 import org.apache.catalina.deploy.MessageDestinationRef;
83 import org.apache.catalina.deploy.NamingResources;
84 import org.apache.catalina.deploy.SecurityCollection;
85 import org.apache.catalina.deploy.SecurityConstraint;
86 import org.apache.catalina.loader.WebappLoader;
87 import org.apache.catalina.session.StandardManager;
88 import org.apache.catalina.startup.ContextConfig;
89 import org.apache.catalina.startup.TldConfig;
90 import org.apache.catalina.util.CharsetMapper;
91 import org.apache.catalina.util.DefaultAnnotationProcessor;
92 import org.apache.catalina.util.ExtensionValidator;
93 import org.apache.catalina.util.RequestUtil;
94 import org.apache.catalina.util.URLEncoder;
95 import org.apache.commons.logging.Log;
96 import org.apache.commons.logging.LogFactory;
97 import org.apache.naming.ContextBindings;
98 import org.apache.naming.resources.BaseDirContext;
99 import org.apache.naming.resources.DirContextURLStreamHandler;
100 import org.apache.naming.resources.FileDirContext;
101 import org.apache.naming.resources.ProxyDirContext;
102 import org.apache.naming.resources.WARDirContext;
103 import org.apache.tomcat.util.modeler.Registry;
104
105 /**
106  * Standard implementation of the <b>Context</b> interface. Each
107  * child container must be a Wrapper implementation to process the
108  * requests directed to a particular servlet.
109  *
110  * @author Craig R. McClanahan
111  * @author Remy Maucherat
112  * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
113  */

114
115 public class StandardContext
116     extends ContainerBase
117     implements Context JavaDoc, Serializable JavaDoc, NotificationEmitter JavaDoc
118 {
119     private static transient Log log = LogFactory.getLog(StandardContext.class);
120
121
122     // ----------------------------------------------------------- Constructors
123

124
125     /**
126      * Create a new StandardContext component with the default basic Valve.
127      */

128     public StandardContext() {
129
130         super();
131         pipeline.setBasic(new StandardContextValve());
132         broadcaster = new NotificationBroadcasterSupport JavaDoc();
133
134     }
135
136
137     // ----------------------------------------------------- Class Variables
138

139
140     /**
141      * The descriptive information string for this implementation.
142      */

143     private static final String JavaDoc info =
144         "org.apache.catalina.core.StandardContext/1.0";
145
146
147     /**
148      * Array containing the safe characters set.
149      */

150     protected static URLEncoder urlEncoder;
151
152
153     /**
154      * GMT timezone - all HTTP dates are on GMT
155      */

156     static {
157         urlEncoder = new URLEncoder();
158         urlEncoder.addSafeCharacter('~');
159         urlEncoder.addSafeCharacter('-');
160         urlEncoder.addSafeCharacter('_');
161         urlEncoder.addSafeCharacter('.');
162         urlEncoder.addSafeCharacter('*');
163         urlEncoder.addSafeCharacter('/');
164     }
165
166
167     // ----------------------------------------------------- Instance Variables
168

169
170     /**
171      * The alternate deployment descriptor name.
172      */

173     private String JavaDoc altDDName = null;
174
175
176     /**
177      * Annotation processor.
178      */

179     private AnnotationProcessor annotationProcessor = null;
180
181
182    /**
183      * Associated host name.
184      */

185     private String JavaDoc hostName;
186
187
188     /**
189      * The antiJARLocking flag for this Context.
190      */

191     private boolean antiJARLocking = false;
192
193     
194     /**
195      * The antiResourceLocking flag for this Context.
196      */

197     private boolean antiResourceLocking = false;
198
199     
200     /**
201      * The set of application listener class names configured for this
202      * application, in the order they were encountered in the web.xml file.
203      */

204     private String JavaDoc applicationListeners[] = new String JavaDoc[0];
205
206
207     /**
208      * The set of instantiated application event listener objects</code>.
209      */

210     private transient Object JavaDoc applicationEventListenersObjects[] =
211         new Object JavaDoc[0];
212
213
214     /**
215      * The set of instantiated application lifecycle listener objects</code>.
216      */

217     private transient Object JavaDoc applicationLifecycleListenersObjects[] =
218         new Object JavaDoc[0];
219
220
221     /**
222      * The set of application parameters defined for this application.
223      */

224     private ApplicationParameter applicationParameters[] =
225         new ApplicationParameter[0];
226
227
228     /**
229      * The application available flag for this Context.
230      */

231     private boolean available = false;
232     
233     /**
234      * The broadcaster that sends j2ee notifications.
235      */

236     private NotificationBroadcasterSupport JavaDoc broadcaster = null;
237     
238     /**
239      * The Locale to character set mapper for this application.
240      */

241     private transient CharsetMapper charsetMapper = null;
242
243
244     /**
245      * The Java class name of the CharsetMapper class to be created.
246      */

247     private String JavaDoc charsetMapperClass =
248       "org.apache.catalina.util.CharsetMapper";
249
250
251     /**
252      * The path to a file to save this Context information.
253      */

254     private String JavaDoc configFile = null;
255
256
257     /**
258      * The "correctly configured" flag for this Context.
259      */

260     private boolean configured = false;
261
262
263     /**
264      * The security constraints for this web application.
265      */

266     private SecurityConstraint constraints[] = new SecurityConstraint[0];
267
268
269     /**
270      * The ServletContext implementation associated with this Context.
271      */

272     protected transient ApplicationContext context = null;
273
274
275     /**
276      * Compiler classpath to use.
277      */

278     private String JavaDoc compilerClasspath = null;
279
280
281     /**
282      * Should we attempt to use cookies for session id communication?
283      */

284     private boolean cookies = true;
285
286
287     /**
288      * Should we allow the <code>ServletContext.getContext()</code> method
289      * to access the context of other web applications in this server?
290      */

291     private boolean crossContext = false;
292
293     
294     /**
295      * Encoded path.
296      */

297     private String JavaDoc encodedPath = null;
298     
299
300     /**
301      * The "follow standard delegation model" flag that will be used to
302      * configure our ClassLoader.
303      */

304     private boolean delegate = false;
305
306
307     /**
308      * The display name of this web application.
309      */

310     private String JavaDoc displayName = null;
311
312
313     /**
314      * Override the default context xml location.
315      */

316     private String JavaDoc defaultContextXml;
317
318
319     /**
320      * Override the default web xml location.
321      */

322     private String JavaDoc defaultWebXml;
323
324
325     /**
326      * The distributable flag for this web application.
327      */

328     private boolean distributable = false;
329
330
331     /**
332      * The document root for this web application.
333      */

334     private String JavaDoc docBase = null;
335
336
337     /**
338      * The exception pages for this web application, keyed by fully qualified
339      * class name of the Java exception.
340      */

341     private HashMap JavaDoc exceptionPages = new HashMap JavaDoc();
342
343
344     /**
345      * The set of filter configurations (and associated filter instances) we
346      * have initialized, keyed by filter name.
347      */

348     private HashMap JavaDoc filterConfigs = new HashMap JavaDoc();
349
350
351     /**
352      * The set of filter definitions for this application, keyed by
353      * filter name.
354      */

355     private HashMap JavaDoc filterDefs = new HashMap JavaDoc();
356
357
358     /**
359      * The set of filter mappings for this application, in the order
360      * they were defined in the deployment descriptor.
361      */

362     private FilterMap filterMaps[] = new FilterMap[0];
363
364
365     /**
366      * Ignore annotations.
367      */

368     private boolean ignoreAnnotations = false;
369
370
371     /**
372      * The set of classnames of InstanceListeners that will be added
373      * to each newly created Wrapper by <code>createWrapper()</code>.
374      */

375     private String JavaDoc instanceListeners[] = new String JavaDoc[0];
376
377
378     /**
379      * The login configuration descriptor for this web application.
380      */

381     private LoginConfig loginConfig = null;
382
383
384     /**
385      * The mapper associated with this context.
386      */

387     private org.apache.tomcat.util.http.mapper.Mapper mapper =
388         new org.apache.tomcat.util.http.mapper.Mapper();
389
390
391     /**
392      * The naming context listener for this web application.
393      */

394     private transient NamingContextListener namingContextListener = null;
395
396
397     /**
398      * The naming resources for this web application.
399      */

400     private NamingResources namingResources = null;
401
402
403     /**
404      * The message destinations for this web application.
405      */

406     private HashMap JavaDoc messageDestinations = new HashMap JavaDoc();
407
408
409     /**
410      * The MIME mappings for this web application, keyed by extension.
411      */

412     private HashMap JavaDoc mimeMappings = new HashMap JavaDoc();
413
414
415      /**
416       * Special case: error page for status 200.
417       */

418      private ErrorPage okErrorPage = null;
419
420
421     /**
422      * The context initialization parameters for this web application,
423      * keyed by name.
424      */

425     private HashMap JavaDoc parameters = new HashMap JavaDoc();
426
427
428     /**
429      * The request processing pause flag (while reloading occurs)
430      */

431     private boolean paused = false;
432
433
434     /**
435      * The public identifier of the DTD for the web application deployment
436      * descriptor version we are currently parsing. This is used to support
437      * relaxed validation rules when processing version 2.2 web.xml files.
438      */

439     private String JavaDoc publicId = null;
440
441
442     /**
443      * The reloadable flag for this web application.
444      */

445     private boolean reloadable = false;
446
447
448     /**
449      * Unpack WAR property.
450      */

451     private boolean unpackWAR = true;
452
453
454     /**
455      * The DefaultContext override flag for this web application.
456      */

457     private boolean override = false;
458
459
460     /**
461      * The original document root for this web application.
462      */

463     private String JavaDoc originalDocBase = null;
464     
465     
466     /**
467      * The privileged flag for this web application.
468      */

469     private boolean privileged = false;
470
471
472     /**
473      * Should the next call to <code>addWelcomeFile()</code> cause replacement
474      * of any existing welcome files? This will be set before processing the
475      * web application's deployment descriptor, so that application specified
476      * choices <strong>replace</strong>, rather than append to, those defined
477      * in the global descriptor.
478      */

479     private boolean replaceWelcomeFiles = false;
480
481
482     /**
483      * The security role mappings for this application, keyed by role
484      * name (as used within the application).
485      */

486     private HashMap JavaDoc roleMappings = new HashMap JavaDoc();
487
488
489     /**
490      * The security roles for this application, keyed by role name.
491      */

492     private String JavaDoc securityRoles[] = new String JavaDoc[0];
493
494
495     /**
496      * The servlet mappings for this web application, keyed by
497      * matching pattern.
498      */

499     private HashMap JavaDoc servletMappings = new HashMap JavaDoc();
500
501
502     /**
503      * The session timeout (in minutes) for this web application.
504      */

505     private int sessionTimeout = 30;
506
507     /**
508      * The notification sequence number.
509      */

510     private long sequenceNumber = 0;
511     
512     /**
513      * The status code error pages for this web application, keyed by
514      * HTTP status code (as an Integer).
515      */

516     private HashMap JavaDoc statusPages = new HashMap JavaDoc();
517
518
519     /**
520      * Set flag to true to cause the system.out and system.err to be redirected
521      * to the logger when executing a servlet.
522      */

523     private boolean swallowOutput = false;
524
525
526     /**
527      * The JSP tag libraries for this web application, keyed by URI
528      */

529     private HashMap JavaDoc taglibs = new HashMap JavaDoc();
530
531
532     /**
533      * Amount of ms that the container will wait for servlets to unload.
534      */

535     private long unloadDelay = 2000;
536
537
538     /**
539      * The watched resources for this application.
540      */

541     private String JavaDoc watchedResources[] = new String JavaDoc[0];
542
543
544     /**
545      * The welcome files for this application.
546      */

547     private String JavaDoc welcomeFiles[] = new String JavaDoc[0];
548
549
550     /**
551      * The set of classnames of LifecycleListeners that will be added
552      * to each newly created Wrapper by <code>createWrapper()</code>.
553      */

554     private String JavaDoc wrapperLifecycles[] = new String JavaDoc[0];
555
556
557     /**
558      * The set of classnames of ContainerListeners that will be added
559      * to each newly created Wrapper by <code>createWrapper()</code>.
560      */

561     private String JavaDoc wrapperListeners[] = new String JavaDoc[0];
562
563
564     /**
565      * The pathname to the work directory for this context (relative to
566      * the server's home if not absolute).
567      */

568     private String JavaDoc workDir = null;
569
570
571     /**
572      * Java class name of the Wrapper class implementation we use.
573      */

574     private String JavaDoc wrapperClassName = StandardWrapper.class.getName();
575     private Class JavaDoc wrapperClass = null;
576
577
578     /**
579      * JNDI use flag.
580      */

581     private boolean useNaming = true;
582
583
584     /**
585      * Filesystem based flag.
586      */

587     private boolean filesystemBased = false;
588
589
590     /**
591      * Name of the associated naming context.
592      */

593     private String JavaDoc namingContextName = null;
594
595
596     /**
597      * Caching allowed flag.
598      */

599     private boolean cachingAllowed = true;
600
601
602     /**
603      * Case sensitivity.
604      */

605     protected boolean caseSensitive = true;
606
607
608     /**
609      * Allow linking.
610      */

611     protected boolean allowLinking = false;
612
613
614     /**
615      * Cache max size in KB.
616      */

617     protected int cacheMaxSize = 10240; // 10 MB
618

619
620     /**
621      * Cache TTL in ms.
622      */

623     protected int cacheTTL = 5000;
624
625
626     private boolean lazy=true;
627
628     /**
629      * Non proxied resources.
630      */

631     private transient DirContext JavaDoc webappResources = null;
632
633     private long startupTime;
634     private long startTime;
635     private long tldScanTime;
636
637     /**
638      * Name of the engine. If null, the domain is used.
639      */

640     private String JavaDoc engineName = null;
641     private String JavaDoc j2EEApplication="none";
642     private String JavaDoc j2EEServer="none";
643
644
645     /**
646      * Attribute value used to turn on/off XML validation
647      */

648      private boolean webXmlValidation = false;
649
650
651     /**
652      * Attribute value used to turn on/off XML namespace validation
653      */

654      private boolean webXmlNamespaceAware = false;
655
656     /**
657      * Attribute value used to turn on/off TLD processing
658      */

659     private boolean processTlds = true;
660
661     /**
662      * Attribute value used to turn on/off XML validation
663      */

664      private boolean tldValidation = false;
665
666
667     /**
668      * Attribute value used to turn on/off TLD XML namespace validation
669      */

670      private boolean tldNamespaceAware = false;
671
672
673     /**
674      * Should we save the configuration.
675      */

676     private boolean saveConfig = true;
677
678
679     // ----------------------------------------------------- Context Properties
680

681
682     public AnnotationProcessor getAnnotationProcessor() {
683        return annotationProcessor;
684     }
685
686
687     public void setAnnotationProcessor(AnnotationProcessor annotationProcessor) {
688        this.annotationProcessor = annotationProcessor;
689     }
690
691     
692     public String JavaDoc getEncodedPath() {
693         return encodedPath;
694     }
695
696
697     public void setName( String JavaDoc name ) {
698         super.setName( name );
699         encodedPath = urlEncoder.encode(name);
700     }
701
702
703     /**
704      * Is caching allowed ?
705      */

706     public boolean isCachingAllowed() {
707         return cachingAllowed;
708     }
709
710
711     /**
712      * Set caching allowed flag.
713      */

714     public void setCachingAllowed(boolean cachingAllowed) {
715         this.cachingAllowed = cachingAllowed;
716     }
717
718
719     /**
720      * Set case sensitivity.
721      */

722     public void setCaseSensitive(boolean caseSensitive) {
723         this.caseSensitive = caseSensitive;
724     }
725
726
727     /**
728      * Is case sensitive ?
729      */

730     public boolean isCaseSensitive() {
731         return caseSensitive;
732     }
733
734
735     /**
736      * Set allow linking.
737      */

738     public void setAllowLinking(boolean allowLinking) {
739         this.allowLinking = allowLinking;
740     }
741
742
743     /**
744      * Is linking allowed.
745      */

746     public boolean isAllowLinking() {
747         return allowLinking;
748     }
749
750
751     /**
752      * Set cache TTL.
753      */

754     public void setCacheTTL(int cacheTTL) {
755         this.cacheTTL = cacheTTL;
756     }
757
758
759     /**
760      * Get cache TTL.
761      */

762     public int getCacheTTL() {
763         return cacheTTL;
764     }
765
766
767     /**
768      * Return the maximum size of the cache in KB.
769      */

770     public int getCacheMaxSize() {
771         return cacheMaxSize;
772     }
773
774
775     /**
776      * Set the maximum size of the cache in KB.
777      */

778     public void setCacheMaxSize(int cacheMaxSize) {
779         this.cacheMaxSize = cacheMaxSize;
780     }
781
782
783     /**
784      * Return the "follow standard delegation model" flag used to configure
785      * our ClassLoader.
786      */

787     public boolean getDelegate() {
788
789         return (this.delegate);
790
791     }
792
793
794     /**
795      * Set the "follow standard delegation model" flag used to configure
796      * our ClassLoader.
797      *
798      * @param delegate The new flag
799      */

800     public void setDelegate(boolean delegate) {
801
802         boolean oldDelegate = this.delegate;
803         this.delegate = delegate;
804         support.firePropertyChange("delegate", new Boolean JavaDoc(oldDelegate),
805                                    new Boolean JavaDoc(this.delegate));
806
807     }
808
809
810     /**
811      * Returns true if the internal naming support is used.
812      */

813     public boolean isUseNaming() {
814
815         return (useNaming);
816
817     }
818
819
820     /**
821      * Enables or disables naming.
822      */

823     public void setUseNaming(boolean useNaming) {
824         this.useNaming = useNaming;
825     }
826
827
828     /**
829      * Returns true if the resources associated with this context are
830      * filesystem based.
831      */

832     public boolean isFilesystemBased() {
833
834         return (filesystemBased);
835
836     }
837
838
839     /**
840      * Return the set of initialized application event listener objects,
841      * in the order they were specified in the web application deployment
842      * descriptor, for this application.
843      *
844      * @exception IllegalStateException if this method is called before
845      * this application has started, or after it has been stopped
846      */

847     public Object JavaDoc[] getApplicationEventListeners() {
848         return (applicationEventListenersObjects);
849     }
850
851
852     /**
853      * Store the set of initialized application event listener objects,
854      * in the order they were specified in the web application deployment
855      * descriptor, for this application.
856      *
857      * @param listeners The set of instantiated listener objects.
858      */

859     public void setApplicationEventListeners(Object JavaDoc listeners[]) {
860         applicationEventListenersObjects = listeners;
861     }
862
863
864     /**
865      * Return the set of initialized application lifecycle listener objects,
866      * in the order they were specified in the web application deployment
867      * descriptor, for this application.
868      *
869      * @exception IllegalStateException if this method is called before
870      * this application has started, or after it has been stopped
871      */

872     public Object JavaDoc[] getApplicationLifecycleListeners() {
873         return (applicationLifecycleListenersObjects);
874     }
875
876
877     /**
878      * Store the set of initialized application lifecycle listener objects,
879      * in the order they were specified in the web application deployment
880      * descriptor, for this application.
881      *
882      * @param listeners The set of instantiated listener objects.
883      */

884     public void setApplicationLifecycleListeners(Object JavaDoc listeners[]) {
885         applicationLifecycleListenersObjects = listeners;
886     }
887
888
889     /**
890      * Return the antiJARLocking flag for this Context.
891      */

892     public boolean getAntiJARLocking() {
893
894         return (this.antiJARLocking);
895
896     }
897
898
899     /**
900      * Return the antiResourceLocking flag for this Context.
901      */

902     public boolean getAntiResourceLocking() {
903
904         return (this.antiResourceLocking);
905
906     }
907
908
909     /**
910      * Set the antiJARLocking feature for this Context.
911      *
912      * @param antiJARLocking The new flag value
913      */

914     public void setAntiJARLocking(boolean antiJARLocking) {
915
916         boolean oldAntiJARLocking = this.antiJARLocking;
917         this.antiJARLocking = antiJARLocking;
918         support.firePropertyChange("antiJARLocking",
919                                    new Boolean JavaDoc(oldAntiJARLocking),
920                                    new Boolean JavaDoc(this.antiJARLocking));
921
922     }
923
924
925     /**
926      * Set the antiResourceLocking feature for this Context.
927      *
928      * @param antiResourceLocking The new flag value
929      */

930     public void setAntiResourceLocking(boolean antiResourceLocking) {
931
932         boolean oldAntiResourceLocking = this.antiResourceLocking;
933         this.antiResourceLocking = antiResourceLocking;
934         support.firePropertyChange("antiResourceLocking",
935                                    new Boolean JavaDoc(oldAntiResourceLocking),
936                                    new Boolean JavaDoc(this.antiResourceLocking));
937
938     }
939
940
941     /**
942      * Return the application available flag for this Context.
943      */

944     public boolean getAvailable() {
945
946         return (this.available);
947
948     }
949
950
951     /**
952      * Set the application available flag for this Context.
953      *
954      * @param available The new application available flag
955      */

956     public void setAvailable(boolean available) {
957
958         boolean oldAvailable = this.available;
959         this.available = available;
960         support.firePropertyChange("available",
961                                    new Boolean JavaDoc(oldAvailable),
962                                    new Boolean JavaDoc(this.available));
963
964     }
965
966
967     /**
968      * Return the Locale to character set mapper for this Context.
969      */

970     public CharsetMapper getCharsetMapper() {
971
972         // Create a mapper the first time it is requested
973
if (this.charsetMapper == null) {
974             try {
975                 Class JavaDoc clazz = Class.forName(charsetMapperClass);
976                 this.charsetMapper =
977                   (CharsetMapper) clazz.newInstance();
978             } catch (Throwable JavaDoc t) {
979                 this.charsetMapper = new CharsetMapper();
980             }
981         }
982
983         return (this.charsetMapper);
984
985     }
986
987
988     /**
989      * Set the Locale to character set mapper for this Context.
990      *
991      * @param mapper The new mapper
992      */

993     public void setCharsetMapper(CharsetMapper mapper) {
994
995         CharsetMapper oldCharsetMapper = this.charsetMapper;
996         this.charsetMapper = mapper;
997         if( mapper != null )
998             this.charsetMapperClass= mapper.getClass().getName();
999         support.firePropertyChange("charsetMapper", oldCharsetMapper,
1000                                   this.charsetMapper);
1001
1002    }
1003
1004    /**
1005     * Return the path to a file to save this Context information.
1006     */

1007    public String JavaDoc getConfigFile() {
1008
1009        return (this.configFile);
1010
1011    }
1012
1013
1014    /**
1015     * Set the path to a file to save this Context information.
1016     *
1017     * @param configFile The path to a file to save this Context information.
1018     */

1019    public void setConfigFile(String JavaDoc configFile) {
1020
1021        this.configFile = configFile;
1022    }
1023
1024
1025    /**
1026     * Return the "correctly configured" flag for this Context.
1027     */

1028    public boolean getConfigured() {
1029
1030        return (this.configured);
1031
1032    }
1033
1034
1035    /**
1036     * Set the "correctly configured" flag for this Context. This can be
1037     * set to false by startup listeners that detect a fatal configuration
1038     * error to avoid the application from being made available.
1039     *
1040     * @param configured The new correctly configured flag
1041     */

1042    public void setConfigured(boolean configured) {
1043
1044        boolean oldConfigured = this.configured;
1045        this.configured = configured;
1046        support.firePropertyChange("configured",
1047                                   new Boolean JavaDoc(oldConfigured),
1048                                   new Boolean JavaDoc(this.configured));
1049
1050    }
1051
1052
1053    /**
1054     * Return the "use cookies for session ids" flag.
1055     */

1056    public boolean getCookies() {
1057
1058        return (this.cookies);
1059
1060    }
1061
1062
1063    /**
1064     * Set the "use cookies for session ids" flag.
1065     *
1066     * @param cookies The new flag
1067     */

1068    public void setCookies(boolean cookies) {
1069
1070        boolean oldCookies = this.cookies;
1071        this.cookies = cookies;
1072        support.firePropertyChange("cookies",
1073                                   new Boolean JavaDoc(oldCookies),
1074                                   new Boolean JavaDoc(this.cookies));
1075
1076    }
1077
1078
1079    /**
1080     * Return the "allow crossing servlet contexts" flag.
1081     */

1082    public boolean getCrossContext() {
1083
1084        return (this.crossContext);
1085
1086    }
1087
1088
1089    /**
1090     * Set the "allow crossing servlet contexts" flag.
1091     *
1092     * @param crossContext The new cross contexts flag
1093     */

1094    public void setCrossContext(boolean crossContext) {
1095
1096        boolean oldCrossContext = this.crossContext;
1097        this.crossContext = crossContext;
1098        support.firePropertyChange("crossContext",
1099                                   new Boolean JavaDoc(oldCrossContext),
1100                                   new Boolean JavaDoc(this.crossContext));
1101
1102    }
1103
1104    public String JavaDoc getDefaultContextXml() {
1105        return defaultContextXml;
1106    }
1107
1108    /**
1109     * Set the location of the default context xml that will be used.
1110     * If not absolute, it'll be made relative to the engine's base dir
1111     * ( which defaults to catalina.base system property ).
1112     *
1113     * @param defaultContextXml The default web xml
1114     */

1115    public void setDefaultContextXml(String JavaDoc defaultContextXml) {
1116        this.defaultContextXml = defaultContextXml;
1117    }
1118
1119    public String JavaDoc getDefaultWebXml() {
1120        return defaultWebXml;
1121    }
1122
1123    /**
1124     * Set the location of the default web xml that will be used.
1125     * If not absolute, it'll be made relative to the engine's base dir
1126     * ( which defaults to catalina.base system property ).
1127     *
1128     * @param defaultWebXml The default web xml
1129     */

1130    public void setDefaultWebXml(String JavaDoc defaultWebXml) {
1131        this.defaultWebXml = defaultWebXml;
1132    }
1133
1134    /**
1135     * Gets the time (in milliseconds) it took to start this context.
1136     *
1137     * @return Time (in milliseconds) it took to start this context.
1138     */

1139    public long getStartupTime() {
1140        return startupTime;
1141    }
1142
1143    public void setStartupTime(long startupTime) {
1144        this.startupTime = startupTime;
1145    }
1146
1147    public long getTldScanTime() {
1148        return tldScanTime;
1149    }
1150
1151    public void setTldScanTime(long tldScanTime) {
1152        this.tldScanTime = tldScanTime;
1153    }
1154
1155    /**
1156     * Return the display name of this web application.
1157     */

1158    public String JavaDoc getDisplayName() {
1159
1160        return (this.displayName);
1161
1162    }
1163
1164
1165    /**
1166     * Return the alternate Deployment Descriptor name.
1167     */

1168    public String JavaDoc getAltDDName(){
1169        return altDDName;
1170    }
1171
1172
1173    /**
1174     * Set an alternate Deployment Descriptor name.
1175     */

1176    public void setAltDDName(String JavaDoc altDDName) {
1177        this.altDDName = altDDName;
1178        if (context != null) {
1179            context.setAttribute(Globals.ALT_DD_ATTR,altDDName);
1180        }
1181    }
1182
1183
1184    /**
1185     * Return the compiler classpath.
1186     */

1187    public String JavaDoc getCompilerClasspath(){
1188        return compilerClasspath;
1189    }
1190
1191
1192    /**
1193     * Set the compiler classpath.
1194     */

1195    public void setCompilerClasspath(String JavaDoc compilerClasspath) {
1196        this.compilerClasspath = compilerClasspath;
1197    }
1198
1199
1200    /**
1201     * Set the display name of this web application.
1202     *
1203     * @param displayName The new display name
1204     */

1205    public void setDisplayName(String JavaDoc displayName) {
1206
1207        String JavaDoc oldDisplayName = this.displayName;
1208        this.displayName = displayName;
1209        support.firePropertyChange("displayName", oldDisplayName,
1210                                   this.displayName);
1211    }
1212
1213
1214    /**
1215     * Return the distributable flag for this web application.
1216     */

1217    public boolean getDistributable() {
1218
1219        return (this.distributable);
1220
1221    }
1222
1223    /**
1224     * Set the distributable flag for this web application.
1225     *
1226     * @param distributable The new distributable flag
1227     */

1228    public void setDistributable(boolean distributable) {
1229        boolean oldDistributable = this.distributable;
1230        this.distributable = distributable;
1231        support.firePropertyChange("distributable",
1232                                   new Boolean JavaDoc(oldDistributable),
1233                                   new Boolean JavaDoc(this.distributable));
1234
1235        // Bugzilla 32866
1236
if(getManager() != null) {
1237            if(log.isDebugEnabled()) {
1238                log.debug("Propagating distributable=" + distributable
1239                          + " to manager");
1240            }
1241            getManager().setDistributable(distributable);
1242        }
1243    }
1244
1245
1246    /**
1247     * Return the document root for this Context. This can be an absolute
1248     * pathname, a relative pathname, or a URL.
1249     */

1250    public String JavaDoc getDocBase() {
1251
1252        return (this.docBase);
1253
1254    }
1255
1256
1257    /**
1258     * Set the document root for this Context. This can be an absolute
1259     * pathname, a relative pathname, or a URL.
1260     *
1261     * @param docBase The new document root
1262     */

1263    public void setDocBase(String JavaDoc docBase) {
1264
1265        this.docBase = docBase;
1266
1267    }
1268
1269    // experimental
1270
public boolean isLazy() {
1271        return lazy;
1272    }
1273
1274    public void setLazy(boolean lazy) {
1275        this.lazy = lazy;
1276    }
1277
1278
1279    /**
1280     * Return descriptive information about this Container implementation and
1281     * the corresponding version number, in the format
1282     * <code>&lt;description&gt;/&lt;version&gt;</code>.
1283     */

1284    public String JavaDoc getInfo() {
1285
1286        return (info);
1287
1288    }
1289
1290    public String JavaDoc getEngineName() {
1291        if( engineName != null ) return engineName;
1292        return domain;
1293    }
1294
1295    public void setEngineName(String JavaDoc engineName) {
1296        this.engineName = engineName;
1297    }
1298
1299    public String JavaDoc getJ2EEApplication() {
1300        return j2EEApplication;
1301    }
1302
1303    public void setJ2EEApplication(String JavaDoc j2EEApplication) {
1304        this.j2EEApplication = j2EEApplication;
1305    }
1306
1307    public String JavaDoc getJ2EEServer() {
1308        return j2EEServer;
1309    }
1310
1311    public void setJ2EEServer(String JavaDoc j2EEServer) {
1312        this.j2EEServer = j2EEServer;
1313    }
1314
1315
1316    /**
1317     * Set the Loader with which this Context is associated.
1318     *
1319     * @param loader The newly associated loader
1320     */

1321    public synchronized void setLoader(Loader loader) {
1322
1323        super.setLoader(loader);
1324
1325    }
1326
1327
1328    /**
1329     * Return the boolean on the annotations parsing.
1330     */

1331    public boolean getIgnoreAnnotations() {
1332        return this.ignoreAnnotations;
1333    }
1334    
1335    
1336    /**
1337     * Set the boolean on the annotations parsing for this web
1338     * application.
1339     *
1340     * @param ignoreAnnotations The boolean on the annotations parsing
1341     */

1342    public void setIgnoreAnnotations(boolean ignoreAnnotations) {
1343        boolean oldIgnoreAnnotations = this.ignoreAnnotations;
1344        this.ignoreAnnotations = ignoreAnnotations;
1345        support.firePropertyChange("ignoreAnnotations", Boolean.valueOf(oldIgnoreAnnotations),
1346                Boolean.valueOf(this.ignoreAnnotations));
1347    }
1348    
1349    
1350    /**
1351     * Return the login configuration descriptor for this web application.
1352     */

1353    public LoginConfig getLoginConfig() {
1354
1355        return (this.loginConfig);
1356
1357    }
1358
1359
1360    /**
1361     * Set the login configuration descriptor for this web application.
1362     *
1363     * @param config The new login configuration
1364     */

1365    public void setLoginConfig(LoginConfig config) {
1366
1367        // Validate the incoming property value
1368
if (config == null)
1369            throw new IllegalArgumentException JavaDoc
1370                (sm.getString("standardContext.loginConfig.required"));
1371        String JavaDoc loginPage = config.getLoginPage();
1372        if ((loginPage != null) && !loginPage.startsWith("/")) {
1373            if (isServlet22()) {
1374                if(log.isDebugEnabled())
1375                    log.debug(sm.getString("standardContext.loginConfig.loginWarning",
1376                                 loginPage));
1377                config.setLoginPage("/" + loginPage);
1378            } else {
1379                throw new IllegalArgumentException JavaDoc
1380                    (sm.getString("standardContext.loginConfig.loginPage",
1381                                  loginPage));
1382            }
1383        }
1384        String JavaDoc errorPage = config.getErrorPage();
1385        if ((errorPage != null) && !errorPage.startsWith("/")) {
1386            if (isServlet22()) {
1387                if(log.isDebugEnabled())
1388                    log.debug(sm.getString("standardContext.loginConfig.errorWarning",
1389                                 errorPage));
1390                config.setErrorPage("/" + errorPage);
1391            } else {
1392                throw new IllegalArgumentException JavaDoc
1393                    (sm.getString("standardContext.loginConfig.errorPage",
1394                                  errorPage));
1395            }
1396        }
1397
1398        // Process the property setting change
1399
LoginConfig oldLoginConfig = this.loginConfig;
1400        this.loginConfig = config;
1401        support.firePropertyChange("loginConfig",
1402                                   oldLoginConfig, this.loginConfig);
1403
1404    }
1405
1406
1407    /**
1408     * Get the mapper associated with the context.
1409     */

1410    public org.apache.tomcat.util.http.mapper.Mapper getMapper() {
1411        return (mapper);
1412    }
1413
1414
1415    /**
1416     * Return the naming resources associated with this web application.
1417     */

1418    public NamingResources getNamingResources() {
1419
1420        if (namingResources == null) {
1421            setNamingResources(new NamingResources());
1422        }
1423        return (namingResources);
1424
1425    }
1426
1427
1428    /**
1429     * Set the naming resources for this web application.
1430     *
1431     * @param namingResources The new naming resources
1432     */

1433    public void setNamingResources(NamingResources namingResources) {
1434
1435        // Process the property setting change
1436
NamingResources oldNamingResources = this.namingResources;
1437        this.namingResources = namingResources;
1438        namingResources.setContainer(this);
1439        support.firePropertyChange("namingResources",
1440                                   oldNamingResources, this.namingResources);
1441
1442    }
1443
1444
1445    /**
1446     * Return the context path for this Context.
1447     */

1448    public String JavaDoc getPath() {
1449
1450        return (getName());
1451
1452    }
1453
1454    
1455    /**
1456     * Set the context path for this Context.
1457     * <p>
1458     * <b>IMPLEMENTATION NOTE</b>: The context path is used as the "name" of
1459     * a Context, because it must be unique.
1460     *
1461     * @param path The new context path
1462     */

1463    public void setPath(String JavaDoc path) {
1464        // XXX Use host in name
1465
setName(RequestUtil.URLDecode(path));
1466
1467    }
1468
1469
1470    /**
1471     * Return the public identifier of the deployment descriptor DTD that is
1472     * currently being parsed.
1473     */

1474    public String JavaDoc getPublicId() {
1475
1476        return (this.publicId);
1477
1478    }
1479
1480
1481    /**
1482     * Set the public identifier of the deployment descriptor DTD that is
1483     * currently being parsed.
1484     *
1485     * @param publicId The public identifier
1486     */

1487    public void setPublicId(String JavaDoc publicId) {
1488
1489        if (log.isDebugEnabled())
1490            log.debug("Setting deployment descriptor public ID to '" +
1491                publicId + "'");
1492
1493        String JavaDoc oldPublicId = this.publicId;
1494        this.publicId = publicId;
1495        support.firePropertyChange("publicId", oldPublicId, publicId);
1496
1497    }
1498
1499
1500    /**
1501     * Return the reloadable flag for this web application.
1502     */

1503    public boolean getReloadable() {
1504
1505        return (this.reloadable);
1506
1507    }
1508
1509
1510    /**
1511     * Return the DefaultContext override flag for this web application.
1512     */

1513    public boolean getOverride() {
1514
1515        return (this.override);
1516
1517    }
1518
1519
1520    /**
1521     * Return the original document root for this Context. This can be an absolute
1522     * pathname, a relative pathname, or a URL.
1523     * Is only set as deployment has change docRoot!
1524     */

1525    public String JavaDoc getOriginalDocBase() {
1526
1527        return (this.originalDocBase);
1528
1529    }
1530
1531    /**
1532     * Set the original document root for this Context. This can be an absolute
1533     * pathname, a relative pathname, or a URL.
1534     *
1535     * @param docBase The orginal document root
1536     */

1537    public void setOriginalDocBase(String JavaDoc docBase) {
1538
1539        this.originalDocBase = docBase;
1540    }
1541    
1542
1543    /**
1544     * Return the parent class loader (if any) for this web application.
1545     * This call is meaningful only <strong>after</strong> a Loader has
1546     * been configured.
1547     */

1548    public ClassLoader JavaDoc getParentClassLoader() {
1549        if (parentClassLoader != null)
1550            return (parentClassLoader);
1551        if (getPrivileged()) {
1552            return this.getClass().getClassLoader();
1553        } else if (parent != null) {
1554            return (parent.getParentClassLoader());
1555        }
1556        return (ClassLoader.getSystemClassLoader());
1557    }
1558
1559    
1560    /**
1561     * Return the privileged flag for this web application.
1562     */

1563    public boolean getPrivileged() {
1564
1565        return (this.privileged);
1566
1567    }
1568
1569
1570    /**
1571     * Set the privileged flag for this web application.
1572     *
1573     * @param privileged The new privileged flag
1574     */

1575    public void setPrivileged(boolean privileged) {
1576
1577        boolean oldPrivileged = this.privileged;
1578        this.privileged = privileged;
1579        support.firePropertyChange("privileged",
1580                                   new Boolean JavaDoc(oldPrivileged),
1581                                   new Boolean JavaDoc(this.privileged));
1582
1583    }
1584
1585
1586    /**
1587     * Set the reloadable flag for this web application.
1588     *
1589     * @param reloadable The new reloadable flag
1590     */

1591    public void setReloadable(boolean reloadable) {
1592
1593        boolean oldReloadable = this.reloadable;
1594        this.reloadable = reloadable;
1595        support.firePropertyChange("reloadable",
1596                                   new Boolean JavaDoc(oldReloadable),
1597                                   new Boolean JavaDoc(this.reloadable));
1598
1599    }
1600
1601
1602    /**
1603     * Set the DefaultContext override flag for this web application.
1604     *
1605     * @param override The new override flag
1606     */

1607    public void setOverride(boolean override) {
1608
1609        boolean oldOverride = this.override;
1610        this.override = override;
1611        support.firePropertyChange("override",
1612                                   new Boolean JavaDoc(oldOverride),
1613                                   new Boolean JavaDoc(this.override));
1614
1615    }
1616
1617
1618    /**
1619     * Return the "replace welcome files" property.
1620     */

1621    public boolean isReplaceWelcomeFiles() {
1622
1623        return (this.replaceWelcomeFiles);
1624
1625    }
1626
1627
1628    /**
1629     * Set the "replace welcome files" property.
1630     *
1631     * @param replaceWelcomeFiles The new property value
1632     */

1633    public void setReplaceWelcomeFiles(boolean replaceWelcomeFiles) {
1634
1635        boolean oldReplaceWelcomeFiles = this.replaceWelcomeFiles;
1636        this.replaceWelcomeFiles = replaceWelcomeFiles;
1637        support.firePropertyChange("replaceWelcomeFiles",
1638                                   new Boolean JavaDoc(oldReplaceWelcomeFiles),
1639                                   new Boolean JavaDoc(this.replaceWelcomeFiles));
1640
1641    }
1642
1643
1644    /**
1645     * Return the servlet context for which this Context is a facade.
1646     */

1647    public ServletContext JavaDoc getServletContext() {
1648
1649        if (context == null) {
1650            context = new ApplicationContext(getBasePath(), this);
1651            if (altDDName != null)
1652                context.setAttribute(Globals.ALT_DD_ATTR,altDDName);
1653        }
1654        return (context.getFacade());
1655
1656    }
1657
1658
1659    /**
1660     * Return the default session timeout (in minutes) for this
1661     * web application.
1662     */

1663    public int getSessionTimeout() {
1664
1665        return (this.sessionTimeout);
1666
1667    }
1668
1669
1670    /**
1671     * Set the default session timeout (in minutes) for this
1672     * web application.
1673     *
1674     * @param timeout The new default session timeout
1675     */

1676    public void setSessionTimeout(int timeout) {
1677
1678        int oldSessionTimeout = this.sessionTimeout;
1679        /*
1680         * SRV.13.4 ("Deployment Descriptor"):
1681         * If the timeout is 0 or less, the container ensures the default
1682         * behaviour of sessions is never to time out.
1683         */

1684        this.sessionTimeout = (timeout == 0) ? -1 : timeout;
1685        support.firePropertyChange("sessionTimeout",
1686                                   new Integer JavaDoc(oldSessionTimeout),
1687                                   new Integer JavaDoc(this.sessionTimeout));
1688
1689    }
1690
1691
1692    /**
1693     * Return the value of the swallowOutput flag.
1694     */

1695    public boolean getSwallowOutput() {
1696
1697        return (this.swallowOutput);
1698
1699    }
1700
1701
1702    /**
1703     * Set the value of the swallowOutput flag. If set to true, the system.out
1704     * and system.err will be redirected to the logger during a servlet
1705     * execution.
1706     *
1707     * @param swallowOutput The new value
1708     */

1709    public void setSwallowOutput(boolean swallowOutput) {
1710
1711        boolean oldSwallowOutput = this.swallowOutput;
1712        this.swallowOutput = swallowOutput;
1713        support.firePropertyChange("swallowOutput",
1714                                   new Boolean JavaDoc(oldSwallowOutput),
1715                                   new Boolean JavaDoc(this.swallowOutput));
1716
1717    }
1718
1719
1720    /**
1721     * Return the value of the unloadDelay flag.
1722     */

1723    public long getUnloadDelay() {
1724
1725        return (this.unloadDelay);
1726
1727    }
1728
1729
1730    /**
1731     * Set the value of the unloadDelay flag, which represents the amount
1732     * of ms that the container will wait when unloading servlets.
1733     * Setting this to a small value may cause more requests to fail
1734     * to complete when stopping a web application.
1735     *
1736     * @param unloadDelay The new value
1737     */

1738    public void setUnloadDelay(long unloadDelay) {
1739
1740        long oldUnloadDelay = this.unloadDelay;
1741        this.unloadDelay = unloadDelay;
1742        support.firePropertyChange("unloadDelay",
1743                                   new Long JavaDoc(oldUnloadDelay),
1744                                   new Long JavaDoc(this.unloadDelay));
1745
1746    }
1747
1748
1749    /**
1750     * Unpack WAR flag accessor.
1751     */

1752    public boolean getUnpackWAR() {
1753
1754        return (unpackWAR);
1755
1756    }
1757
1758
1759    /**
1760     * Unpack WAR flag mutator.
1761     */

1762    public void setUnpackWAR(boolean unpackWAR) {
1763
1764        this.unpackWAR = unpackWAR;
1765
1766    }
1767
1768    /**
1769     * Return the Java class name of the Wrapper implementation used
1770     * for servlets registered in this Context.
1771     */

1772    public String JavaDoc getWrapperClass() {
1773
1774        return (this.wrapperClassName);
1775
1776    }
1777
1778
1779    /**
1780     * Set the Java class name of the Wrapper implementation used
1781     * for servlets registered in this Context.
1782     *
1783     * @param wrapperClassName The new wrapper class name
1784     *
1785     * @throws IllegalArgumentException if the specified wrapper class
1786     * cannot be found or is not a subclass of StandardWrapper
1787     */

1788    public void setWrapperClass(String JavaDoc wrapperClassName) {
1789
1790        this.wrapperClassName = wrapperClassName;
1791
1792        try {
1793            wrapperClass = Class.forName(wrapperClassName);
1794            if (!StandardWrapper.class.isAssignableFrom(wrapperClass)) {
1795                throw new IllegalArgumentException JavaDoc(
1796                    sm.getString("standardContext.invalidWrapperClass",
1797                                 wrapperClassName));
1798            }
1799        } catch (ClassNotFoundException JavaDoc cnfe) {
1800            throw new IllegalArgumentException JavaDoc(cnfe.getMessage());
1801        }
1802    }
1803
1804
1805    /**
1806     * Set the resources DirContext object with which this Container is
1807     * associated.
1808     *
1809     * @param resources The newly associated DirContext
1810     */

1811    public synchronized void setResources(DirContext JavaDoc resources) {
1812
1813        if (started) {
1814            throw new IllegalStateException JavaDoc
1815                (sm.getString("standardContext.resources.started"));
1816        }
1817
1818        DirContext JavaDoc oldResources = this.webappResources;
1819        if (oldResources == resources)
1820            return;
1821
1822        if (resources instanceof BaseDirContext) {
1823            ((BaseDirContext) resources).setCached(isCachingAllowed());
1824            ((BaseDirContext) resources).setCacheTTL(getCacheTTL());
1825            ((BaseDirContext) resources).setCacheMaxSize(getCacheMaxSize());
1826        }
1827        if (resources instanceof FileDirContext) {
1828            filesystemBased = true;
1829            ((FileDirContext) resources).setCaseSensitive(isCaseSensitive());
1830            ((FileDirContext) resources).setAllowLinking(isAllowLinking());
1831        }
1832        this.webappResources = resources;
1833
1834        // The proxied resources will be refreshed on start
1835
this.resources = null;
1836
1837        support.firePropertyChange("resources", oldResources,
1838                                   this.webappResources);
1839
1840    }
1841
1842
1843    // ------------------------------------------------------ Public Properties
1844

1845
1846    /**
1847     * Return the Locale to character set mapper class for this Context.
1848     */

1849    public String JavaDoc getCharsetMapperClass() {
1850
1851        return (this.charsetMapperClass);
1852
1853    }
1854
1855
1856    /**
1857     * Set the Locale to character set mapper class for this Context.
1858     *
1859     * @param mapper The new mapper class
1860     */

1861    public void setCharsetMapperClass(String JavaDoc mapper) {
1862
1863        String JavaDoc oldCharsetMapperClass = this.charsetMapperClass;
1864        this.charsetMapperClass = mapper;
1865        support.firePropertyChange("charsetMapperClass",
1866                                   oldCharsetMapperClass,
1867                                   this.charsetMapperClass);
1868
1869    }
1870
1871
1872    /** Get the absolute path to the work dir.
1873     * To avoid duplication.
1874     *
1875     * @return The work path
1876     */

1877    public String JavaDoc getWorkPath() {
1878        File JavaDoc workDir = new File JavaDoc(getWorkDir());
1879        if (!workDir.isAbsolute()) {
1880            File JavaDoc catalinaHome = engineBase();
1881            String JavaDoc catalinaHomePath = null;
1882            try {
1883                catalinaHomePath = catalinaHome.getCanonicalPath();
1884                workDir = new File JavaDoc(catalinaHomePath,
1885                        getWorkDir());
1886            } catch (IOException JavaDoc e) {
1887                log.warn("Exception obtaining work path for " + getPath());
1888            }
1889        }
1890        return workDir.getAbsolutePath();
1891    }
1892    
1893    /**
1894     * Return the work directory for this Context.
1895     */

1896    public String JavaDoc getWorkDir() {
1897
1898        return (this.workDir);
1899
1900    }
1901
1902
1903    /**
1904     * Set the work directory for this Context.
1905     *
1906     * @param workDir The new work directory
1907     */

1908    public void setWorkDir(String JavaDoc workDir) {
1909
1910        this.workDir = workDir;
1911
1912        if (started) {
1913            postWorkDirectory();
1914        }
1915    }
1916
1917
1918    /**
1919     * Save config ?
1920     */

1921    public boolean isSaveConfig() {
1922        return saveConfig;
1923    }
1924
1925
1926    /**
1927     * Set save config flag.
1928     */

1929    public void setSaveConfig(boolean saveConfig) {
1930        this.saveConfig = saveConfig;
1931    }
1932
1933
1934    // -------------------------------------------------------- Context Methods
1935

1936
1937    /**
1938     * Add a new Listener class name to the set of Listeners
1939     * configured for this application.
1940     *
1941     * @param listener Java class name of a listener class
1942     */

1943    public void addApplicationListener(String JavaDoc listener) {
1944
1945        synchronized (applicationListeners) {
1946            String JavaDoc results[] =new String JavaDoc[applicationListeners.length + 1];
1947            for (int i = 0; i < applicationListeners.length; i++) {
1948                if (listener.equals(applicationListeners[i]))
1949                    return;
1950                results[i] = applicationListeners[i];
1951            }
1952            results[applicationListeners.length] = listener;
1953            applicationListeners = results;
1954        }
1955        fireContainerEvent("addApplicationListener", listener);
1956
1957        // FIXME - add instance if already started?
1958

1959    }
1960
1961
1962    /**
1963     * Add a new application parameter for this application.
1964     *
1965     * @param parameter The new application parameter
1966     */

1967    public void addApplicationParameter(ApplicationParameter parameter) {
1968
1969        synchronized (applicationParameters) {
1970            String JavaDoc newName = parameter.getName();
1971            for (int i = 0; i < applicationParameters.length; i++) {
1972                if (newName.equals(applicationParameters[i].getName()) &&
1973                    !applicationParameters[i].getOverride())
1974                    return;
1975            }
1976            ApplicationParameter results[] =
1977                new ApplicationParameter[applicationParameters.length + 1];
1978            System.arraycopy(applicationParameters, 0, results, 0,
1979                             applicationParameters.length);
1980            results[applicationParameters.length] = parameter;
1981            applicationParameters = results;
1982        }
1983        fireContainerEvent("addApplicationParameter", parameter);
1984
1985    }
1986
1987
1988    /**
1989     * Add a child Container, only if the proposed child is an implementation
1990     * of Wrapper.
1991     *
1992     * @param child Child container to be added
1993     *
1994     * @exception IllegalArgumentException if the proposed container is
1995     * not an implementation of Wrapper
1996     */

1997    public void addChild(Container child) {
1998
1999        // Global JspServlet
2000
Wrapper oldJspServlet = null;
2001
2002        if (!(child instanceof Wrapper)) {
2003            throw new IllegalArgumentException JavaDoc
2004                (sm.getString("standardContext.notWrapper"));
2005        }
2006
2007        Wrapper wrapper = (Wrapper) child;
2008        boolean isJspServlet = "jsp".equals(child.getName());
2009
2010        // Allow webapp to override JspServlet inherited from global web.xml.
2011
if (isJspServlet) {
2012            oldJspServlet = (Wrapper) findChild("jsp");
2013            if (oldJspServlet != null) {
2014                removeChild(oldJspServlet);
2015            }
2016        }
2017
2018        String JavaDoc jspFile = wrapper.getJspFile();
2019        if ((jspFile != null) && !jspFile.startsWith("/")) {
2020            if (isServlet22()) {
2021                if(log.isDebugEnabled())
2022                    log.debug(sm.getString("standardContext.wrapper.warning",
2023                                       jspFile));
2024                wrapper.setJspFile("/" + jspFile);
2025            } else {
2026                throw new IllegalArgumentException JavaDoc
2027                    (sm.getString("standardContext.wrapper.error", jspFile));
2028            }
2029        }
2030
2031        super.addChild(child);
2032
2033        if (isJspServlet && oldJspServlet != null) {
2034            /*
2035             * The webapp-specific JspServlet inherits all the mappings
2036             * specified in the global web.xml, and may add additional ones.
2037             */

2038            String JavaDoc[] jspMappings = oldJspServlet.findMappings();
2039            for (int i=0; jspMappings!=null && i<jspMappings.length; i++) {
2040                addServletMapping(jspMappings[i], child.getName());
2041            }
2042        }
2043    }
2044
2045
2046    /**
2047     * Add a security constraint to the set for this web application.
2048     */

2049    public void addConstraint(SecurityConstraint constraint) {
2050
2051        // Validate the proposed constraint
2052
SecurityCollection collections[] = constraint.findCollections();
2053        for (int i = 0; i < collections.length; i++) {
2054            String JavaDoc patterns[] = collections[i].findPatterns();
2055            for (int j = 0; j < patterns.length; j++) {
2056                patterns[j] = adjustURLPattern(patterns[j]);
2057                if (!validateURLPattern(patterns[j]))
2058                    throw new IllegalArgumentException JavaDoc
2059                        (sm.getString
2060                         ("standardContext.securityConstraint.pattern",
2061                          patterns[j]));
2062            }
2063        }
2064
2065        // Add this constraint to the set for our web application
2066
synchronized (constraints) {
2067            SecurityConstraint results[] =
2068                new SecurityConstraint[constraints.length + 1];
2069            for (int i = 0; i < constraints.length; i++)
2070                results[i] = constraints[i];
2071            results[constraints.length] = constraint;
2072            constraints = results;
2073        }
2074
2075    }
2076
2077
2078
2079    /**
2080     * Add an error page for the specified error or Java exception.
2081     *
2082     * @param errorPage The error page definition to be added
2083     */

2084    public void addErrorPage(ErrorPage errorPage) {
2085        // Validate the input parameters
2086
if (errorPage == null)
2087            throw new IllegalArgumentException JavaDoc
2088                (sm.getString("standardContext.errorPage.required"));
2089        String JavaDoc location = errorPage.getLocation();
2090        if ((location != null) && !location.startsWith("/")) {
2091            if (isServlet22()) {
2092                if(log.isDebugEnabled())
2093                    log.debug(sm.getString("standardContext.errorPage.warning",
2094                                 location));
2095                errorPage.setLocation("/" + location);
2096            } else {
2097                throw new IllegalArgumentException JavaDoc
2098                    (sm.getString("standardContext.errorPage.error",
2099                                  location));
2100            }
2101        }
2102
2103        // Add the specified error page to our internal collections
2104
String JavaDoc exceptionType = errorPage.getExceptionType();
2105        if (exceptionType != null) {
2106            synchronized (exceptionPages) {
2107                exceptionPages.put(exceptionType, errorPage);
2108            }
2109        } else {
2110            synchronized (statusPages) {
2111                if (errorPage.getErrorCode() == 200) {
2112                    this.okErrorPage = errorPage;
2113                }
2114                statusPages.put(new Integer JavaDoc(errorPage.getErrorCode()),
2115                                errorPage);
2116            }
2117        }
2118        fireContainerEvent("addErrorPage", errorPage);
2119
2120    }
2121
2122
2123    /**
2124     * Add a filter definition to this Context.
2125     *
2126     * @param filterDef The filter definition to be added
2127     */

2128    public void addFilterDef(FilterDef filterDef) {
2129
2130        synchronized (filterDefs) {
2131            filterDefs.put(filterDef.getFilterName(), filterDef);
2132        }
2133        fireContainerEvent("addFilterDef", filterDef);
2134
2135    }
2136
2137
2138    /**
2139     * Add a filter mapping to this Context.
2140     *
2141     * @param filterMap The filter mapping to be added
2142     *
2143     * @exception IllegalArgumentException if the specified filter name
2144     * does not match an existing filter definition, or the filter mapping
2145     * is malformed
2146     */

2147    public void addFilterMap(FilterMap filterMap) {
2148
2149        // Validate the proposed filter mapping
2150
String JavaDoc filterName = filterMap.getFilterName();
2151        String JavaDoc[] servletNames = filterMap.getServletNames();
2152        String JavaDoc[] urlPatterns = filterMap.getURLPatterns();
2153        if (findFilterDef(filterName) == null)
2154            throw new IllegalArgumentException JavaDoc
2155                (sm.getString("standardContext.filterMap.name", filterName));
2156        if ((servletNames.length == 0) && (urlPatterns.length == 0))
2157            throw new IllegalArgumentException JavaDoc
2158                (sm.getString("standardContext.filterMap.either"));
2159        // FIXME: Older spec revisions may still check this
2160
/*
2161        if ((servletNames.length != 0) && (urlPatterns.length != 0))
2162            throw new IllegalArgumentException
2163                (sm.getString("standardContext.filterMap.either"));
2164        */

2165        // Because filter-pattern is new in 2.3, no need to adjust
2166
// for 2.2 backwards compatibility
2167
for (int i = 0; i < urlPatterns.length; i++) {
2168            if (!validateURLPattern(urlPatterns[i])) {
2169                throw new IllegalArgumentException JavaDoc
2170                    (sm.getString("standardContext.filterMap.pattern",
2171                            urlPatterns[i]));
2172            }
2173        }
2174
2175        // Add this filter mapping to our registered set
2176
synchronized (filterMaps) {
2177            FilterMap results[] =new FilterMap[filterMaps.length + 1];
2178            System.arraycopy(filterMaps, 0, results, 0, filterMaps.length);
2179            results[filterMaps.length] = filterMap;
2180            filterMaps = results;
2181        }
2182        fireContainerEvent("addFilterMap", filterMap);
2183
2184    }
2185
2186
2187    /**
2188     * Add the classname of an InstanceListener to be added to each
2189     * Wrapper appended to this Context.
2190     *
2191     * @param listener Java class name of an InstanceListener class
2192     */

2193    public void addInstanceListener(String JavaDoc listener) {
2194
2195        synchronized (instanceListeners) {
2196            String JavaDoc results[] =new String JavaDoc[instanceListeners.length + 1];
2197            for (int i = 0; i < instanceListeners.length; i++)
2198                results[i] = instanceListeners[i];
2199            results[instanceListeners.length] = listener;
2200            instanceListeners = results;
2201        }
2202        fireContainerEvent("addInstanceListener", listener);
2203
2204    }
2205
2206    /**
2207     * Add the given URL pattern as a jsp-property-group. This maps
2208     * resources that match the given pattern so they will be passed
2209     * to the JSP container. Though there are other elements in the
2210     * property group, we only care about the URL pattern here. The
2211     * JSP container will parse the rest.
2212     *
2213     * @param pattern URL pattern to be mapped
2214     */

2215    public void addJspMapping(String JavaDoc pattern) {
2216        String JavaDoc servletName = findServletMapping("*.jsp");
2217        if (servletName == null) {
2218            servletName = "jsp";
2219        }
2220
2221        if( findChild(servletName) != null) {
2222            addServletMapping(pattern, servletName, true);
2223        } else {
2224            if(log.isDebugEnabled())
2225                log.debug("Skiping " + pattern + " , no servlet " + servletName);
2226        }
2227    }
2228
2229
2230    /**
2231     * Add a Locale Encoding Mapping (see Sec 5.4 of Servlet spec 2.4)
2232     *
2233     * @param locale locale to map an encoding for
2234     * @param encoding encoding to be used for a give locale
2235     */

2236    public void addLocaleEncodingMappingParameter(String JavaDoc locale, String JavaDoc encoding){
2237        getCharsetMapper().addCharsetMappingFromDeploymentDescriptor(locale, encoding);
2238    }
2239
2240
2241    /**
2242     * Add a message destination for this web application.
2243     *
2244     * @param md New message destination
2245     */

2246    public void addMessageDestination(MessageDestination md) {
2247
2248        synchronized (messageDestinations) {
2249            messageDestinations.put(md.getName(), md);
2250        }
2251        fireContainerEvent("addMessageDestination", md.getName());
2252
2253    }
2254
2255
2256    /**
2257     * Add a message destination reference for this web application.
2258     *
2259     * @param mdr New message destination reference
2260     */

2261    public void addMessageDestinationRef
2262        (MessageDestinationRef mdr) {
2263
2264        namingResources.addMessageDestinationRef(mdr);
2265        fireContainerEvent("addMessageDestinationRef", mdr.getName());
2266
2267    }
2268
2269
2270    /**
2271     * Add a new MIME mapping, replacing any existing mapping for
2272     * the specified extension.
2273     *
2274     * @param extension Filename extension being mapped
2275     * @param mimeType Corresponding MIME type
2276     */

2277    public void addMimeMapping(String JavaDoc extension, String JavaDoc mimeType) {
2278
2279        synchronized (mimeMappings) {
2280            mimeMappings.put(extension, mimeType);
2281        }
2282        fireContainerEvent("addMimeMapping", extension);
2283
2284    }
2285
2286
2287    /**
2288     * Add a new context initialization parameter.
2289     *
2290     * @param name Name of the new parameter
2291     * @param value Value of the new parameter
2292     *
2293     * @exception IllegalArgumentException if the name or value is missing,
2294     * or if this context initialization parameter has already been
2295     * registered
2296     */

2297    public void addParameter(String JavaDoc name, String JavaDoc value) {
2298        // Validate the proposed context initialization parameter
2299
if ((name == null) || (value == null))
2300            throw new IllegalArgumentException JavaDoc
2301                (sm.getString("standardContext.parameter.required"));
2302        if (parameters.get(name) != null)
2303            throw new IllegalArgumentException JavaDoc
2304                (sm.getString("standardContext.parameter.duplicate", name));
2305
2306        // Add this parameter to our defined set
2307
synchronized (parameters) {
2308            parameters.put(name, value);
2309        }
2310        fireContainerEvent("addParameter", name);
2311
2312    }
2313
2314
2315    /**
2316     * Add a security role reference for this web application.
2317     *
2318     * @param role Security role used in the application
2319     * @param link Actual security role to check for
2320     */

2321    public void addRoleMapping(String JavaDoc role, String JavaDoc link) {
2322
2323        synchronized (roleMappings) {
2324            roleMappings.put(role, link);
2325        }
2326        fireContainerEvent("addRoleMapping", role);
2327
2328    }
2329
2330
2331    /**
2332     * Add a new security role for this web application.
2333     *
2334     * @param role New security role
2335     */

2336    public void addSecurityRole(String JavaDoc role) {
2337
2338        synchronized (securityRoles) {
2339            String JavaDoc results[] =new String JavaDoc[securityRoles.length + 1];
2340            for (int i = 0; i < securityRoles.length; i++)
2341                results[i] = securityRoles[i];
2342            results[securityRoles.length] = role;
2343            securityRoles = results;
2344        }
2345        fireContainerEvent("addSecurityRole", role);
2346
2347    }
2348
2349
2350    /**
2351     * Add a new servlet mapping, replacing any existing mapping for
2352     * the specified pattern.
2353     *
2354     * @param pattern URL pattern to be mapped
2355     * @param name Name of the corresponding servlet to execute
2356     *
2357     * @exception IllegalArgumentException if the specified servlet name
2358     * is not known to this Context
2359     */

2360    public void addServletMapping(String JavaDoc pattern, String JavaDoc name) {
2361        addServletMapping(pattern, name, false);
2362    }
2363
2364
2365    /**
2366     * Add a new servlet mapping, replacing any existing mapping for
2367     * the specified pattern.
2368     *
2369     * @param pattern URL pattern to be mapped
2370     * @param name Name of the corresponding servlet to execute
2371     * @param jspWildCard true if name identifies the JspServlet
2372     * and pattern contains a wildcard; false otherwise
2373     *
2374     * @exception IllegalArgumentException if the specified servlet name
2375     * is not known to this Context
2376     */

2377    public void addServletMapping(String JavaDoc pattern, String JavaDoc name,
2378                                  boolean jspWildCard) {
2379        // Validate the proposed mapping
2380
if (findChild(name) == null)
2381            throw new IllegalArgumentException JavaDoc
2382                (sm.getString("standardContext.servletMap.name", name));
2383        pattern = adjustURLPattern(RequestUtil.URLDecode(pattern));
2384        if (!validateURLPattern(pattern))
2385            throw new IllegalArgumentException JavaDoc
2386                (sm.getString("standardContext.servletMap.pattern", pattern));
2387
2388        // Add this mapping to our registered set
2389
synchronized (servletMappings) {
2390            String JavaDoc name2 = (String JavaDoc) servletMappings.get(pattern);
2391            if (name2 != null) {
2392                // Don't allow more than one servlet on the same pattern
2393
Wrapper wrapper = (Wrapper) findChild(name2);
2394                wrapper.removeMapping(pattern);
2395                mapper.removeWrapper(pattern);
2396            }
2397            servletMappings.put(pattern, name);
2398        }
2399        Wrapper wrapper = (Wrapper) findChild(name);
2400        wrapper.addMapping(pattern);
2401
2402        // Update context mapper
2403
mapper.addWrapper(pattern, wrapper, jspWildCard);
2404
2405        fireContainerEvent("addServletMapping", pattern);
2406
2407    }
2408
2409
2410    /**
2411     * Add a JSP tag library for the specified URI.
2412     *
2413     * @param uri URI, relative to the web.xml file, of this tag library
2414     * @param location Location of the tag library descriptor
2415     */

2416    public void addTaglib(String JavaDoc uri, String JavaDoc location) {
2417
2418        synchronized (taglibs) {
2419            taglibs.put(uri, location);
2420        }
2421        fireContainerEvent("addTaglib", uri);
2422
2423    }
2424
2425
2426    /**
2427     * Add a new watched resource to the set recognized by this Context.
2428     *
2429     * @param name New watched resource file name
2430     */

2431    public void addWatchedResource(String JavaDoc name) {
2432
2433        synchronized (watchedResources) {
2434            String JavaDoc results[] = new String JavaDoc[watchedResources.length + 1];
2435            for (int i = 0; i < watchedResources.length; i++)
2436                results[i] = watchedResources[i];
2437            results[watchedResources.length] = name;
2438            watchedResources = results;
2439        }
2440        fireContainerEvent("addWatchedResource", name);
2441
2442    }
2443
2444
2445    /**
2446     * Add a new welcome file to the set recognized by this Context.
2447     *
2448     * @param name New welcome file name
2449     */

2450    public void addWelcomeFile(String JavaDoc name) {
2451
2452        synchronized (welcomeFiles) {
2453            // Welcome files from the application deployment descriptor
2454
// completely replace those from the default conf/web.xml file
2455
if (replaceWelcomeFiles) {
2456                welcomeFiles = new String JavaDoc[0];
2457                setReplaceWelcomeFiles(false);
2458            }
2459            String JavaDoc results[] =new String JavaDoc[welcomeFiles.length + 1];
2460            for (int i = 0; i < welcomeFiles.length; i++)
2461                results[i] = welcomeFiles[i];
2462            results[welcomeFiles.length] = name;
2463            welcomeFiles = results;
2464        }
2465        postWelcomeFiles();
2466        fireContainerEvent("addWelcomeFile", name);
2467
2468    }
2469
2470
2471    /**
2472     * Add the classname of a LifecycleListener to be added to each
2473     * Wrapper appended to this Context.
2474     *
2475     * @param listener Java class name of a LifecycleListener class
2476     */

2477    public void addWrapperLifecycle(String JavaDoc listener) {
2478
2479        synchronized (wrapperLifecycles) {
2480            String JavaDoc results[] =new String JavaDoc[wrapperLifecycles.length + 1];
2481            for (int i = 0; i < wrapperLifecycles.length; i++)
2482                results[i] = wrapperLifecycles[i];
2483            results[wrapperLifecycles.length] = listener;
2484            wrapperLifecycles = results;
2485        }
2486        fireContainerEvent("addWrapperLifecycle", listener);
2487
2488    }
2489
2490
2491    /**
2492     * Add the classname of a ContainerListener to be added to each
2493     * Wrapper appended to this Context.
2494     *
2495     * @param listener Java class name of a ContainerListener class
2496     */

2497    public void addWrapperListener(String JavaDoc listener) {
2498
2499        synchronized (wrapperListeners) {
2500            String JavaDoc results[] =new String JavaDoc[wrapperListeners.length + 1];
2501            for (int i = 0; i < wrapperListeners.length; i++)
2502                results[i] = wrapperListeners[i];
2503            results[wrapperListeners.length] = listener;
2504            wrapperListeners = results;
2505        }
2506        fireContainerEvent("addWrapperListener", listener);
2507
2508    }
2509
2510
2511    /**
2512     * Factory method to create and return a new Wrapper instance, of
2513     * the Java implementation class appropriate for this Context
2514     * implementation. The constructor of the instantiated Wrapper
2515     * will have been called, but no properties will have been set.
2516     */

2517    public Wrapper createWrapper() {
2518
2519        Wrapper wrapper = null;
2520        if (wrapperClass != null) {
2521            try {
2522                wrapper = (Wrapper) wrapperClass.newInstance();
2523            } catch (Throwable JavaDoc t) {
2524                log.error("createWrapper", t);
2525                return (null);
2526            }
2527        } else {
2528            wrapper = new StandardWrapper();
2529        }
2530
2531        synchronized (instanceListeners) {
2532            for (int i = 0; i < instanceListeners.length; i++) {
2533                try {
2534                    Class JavaDoc clazz = Class.forName(instanceListeners[i]);
2535                    InstanceListener listener =
2536                      (InstanceListener) clazz.newInstance();
2537                    wrapper.addInstanceListener(listener);
2538                } catch (Throwable JavaDoc t) {
2539                    log.error("createWrapper", t);
2540                    return (null);
2541                }
2542            }
2543        }
2544
2545        synchronized (wrapperLifecycles) {
2546            for (int i = 0; i < wrapperLifecycles.length; i++) {
2547                try {
2548                    Class JavaDoc clazz = Class.forName(wrapperLifecycles[i]);
2549                    LifecycleListener listener =
2550                      (LifecycleListener) clazz.newInstance();
2551                    if (wrapper instanceof Lifecycle)
2552                        ((Lifecycle) wrapper).addLifecycleListener(listener);
2553                } catch (Throwable JavaDoc t) {
2554                    log.error("createWrapper", t);
2555                    return (null);
2556                }
2557            }
2558        }
2559
2560        synchronized (wrapperListeners) {
2561            for (int i = 0; i < wrapperListeners.length; i++) {
2562                try {
2563                    Class JavaDoc clazz = Class.forName(wrapperListeners[i]);
2564                    ContainerListener listener =
2565                      (ContainerListener) clazz.newInstance();
2566                    wrapper.addContainerListener(listener);
2567                } catch (Throwable JavaDoc t) {
2568                    log.error("createWrapper", t);
2569                    return (null);
2570                }
2571            }
2572        }
2573
2574        return (wrapper);
2575
2576    }
2577
2578
2579    /**
2580     * Return the set of application listener class names configured
2581     * for this application.
2582     */

2583    public String JavaDoc[] findApplicationListeners() {
2584
2585        return (applicationListeners);
2586
2587    }
2588
2589
2590    /**
2591     * Return the set of application parameters for this application.
2592     */

2593    public ApplicationParameter[] findApplicationParameters() {
2594
2595        return (applicationParameters);
2596
2597    }
2598
2599
2600    /**
2601     * Return the security constraints for this web application.
2602     * If there are none, a zero-length array is returned.
2603     */

2604    public SecurityConstraint[] findConstraints() {
2605
2606        return (constraints);
2607
2608    }
2609
2610
2611    /**
2612     * Return the error page entry for the specified HTTP error code,
2613     * if any; otherwise return <code>null</code>.
2614     *
2615     * @param errorCode Error code to look up
2616     */

2617    public ErrorPage findErrorPage(int errorCode) {
2618        if (errorCode == 200) {
2619            return (okErrorPage);
2620        } else {
2621            return ((ErrorPage) statusPages.get(new Integer JavaDoc(errorCode)));
2622        }
2623
2624    }
2625
2626
2627    /**
2628     * Return the error page entry for the specified Java exception type,
2629     * if any; otherwise return <code>null</code>.
2630     *
2631     * @param exceptionType Exception type to look up
2632     */

2633    public ErrorPage findErrorPage(String JavaDoc exceptionType) {
2634
2635        synchronized (exceptionPages) {
2636            return ((ErrorPage) exceptionPages.get(exceptionType));
2637        }
2638
2639    }
2640
2641
2642    /**
2643     * Return the set of defined error pages for all specified error codes
2644     * and exception types.
2645     */

2646    public ErrorPage[] findErrorPages() {
2647
2648        synchronized(exceptionPages) {
2649            synchronized(statusPages) {
2650                ErrorPage results1[] = new ErrorPage[exceptionPages.size()];
2651                results1 =
2652                    (ErrorPage[]) exceptionPages.values().toArray(results1);
2653                ErrorPage results2[] = new ErrorPage[statusPages.size()];
2654                results2 =
2655                    (ErrorPage[]) statusPages.values().toArray(results2);
2656                ErrorPage results[] =
2657                    new ErrorPage[results1.length + results2.length];
2658                for (int i = 0; i < results1.length; i++)
2659                    results[i] = results1[i];
2660                for (int i = results1.length; i < results.length; i++)
2661                    results[i] = results2[i - results1.length];
2662                return (results);
2663            }
2664        }
2665
2666    }
2667
2668
2669    /**
2670     * Return the filter definition for the specified filter name, if any;
2671     * otherwise return <code>null</code>.
2672     *
2673     * @param filterName Filter name to look up
2674     */

2675    public FilterDef findFilterDef(String JavaDoc filterName) {
2676
2677        synchronized (filterDefs) {
2678            return ((FilterDef) filterDefs.get(filterName));
2679        }
2680
2681    }
2682
2683
2684    /**
2685     * Return the set of defined filters for this Context.
2686     */

2687    public FilterDef[] findFilterDefs() {
2688
2689        synchronized (filterDefs) {
2690            FilterDef results[] = new FilterDef[filterDefs.size()];
2691            return ((FilterDef[]) filterDefs.values().toArray(results));
2692        }
2693
2694    }
2695
2696
2697    /**
2698     * Return the set of filter mappings for this Context.
2699     */

2700    public FilterMap[] findFilterMaps() {
2701
2702        return (filterMaps);
2703
2704    }
2705
2706
2707    /**
2708     * Return the set of InstanceListener classes that will be added to
2709     * newly created Wrappers automatically.
2710     */

2711    public String JavaDoc[] findInstanceListeners() {
2712
2713        return (instanceListeners);
2714
2715    }
2716
2717
2718    /**
2719     * FIXME: Fooling introspection ...
2720     */

2721    public Context JavaDoc findMappingObject() {
2722        return (Context JavaDoc) getMappingObject();
2723    }
2724    
2725    
2726    /**
2727     * Return the message destination with the specified name, if any;
2728     * otherwise, return <code>null</code>.
2729     *
2730     * @param name Name of the desired message destination
2731     */

2732    public MessageDestination findMessageDestination(String JavaDoc name) {
2733
2734        synchronized (messageDestinations) {
2735            return ((MessageDestination) messageDestinations.get(name));
2736        }
2737
2738    }
2739
2740
2741    /**
2742     * Return the set of defined message destinations for this web
2743     * application. If none have been defined, a zero-length array
2744     * is returned.
2745     */

2746    public MessageDestination[] findMessageDestinations() {
2747
2748        synchronized (messageDestinations) {
2749            MessageDestination results[] =
2750                new MessageDestination[messageDestinations.size()];
2751            return ((MessageDestination[])
2752                    messageDestinations.values().toArray(results));
2753        }
2754
2755    }
2756
2757
2758    /**
2759     * Return the message destination ref with the specified name, if any;
2760     * otherwise, return <code>null</code>.
2761     *
2762     * @param name Name of the desired message destination ref
2763     */

2764    public MessageDestinationRef
2765        findMessageDestinationRef(String JavaDoc name) {
2766
2767        return namingResources.findMessageDestinationRef(name);
2768
2769    }
2770
2771
2772    /**
2773     * Return the set of defined message destination refs for this web
2774     * application. If none have been defined, a zero-length array
2775     * is returned.
2776     */

2777    public MessageDestinationRef[]
2778        findMessageDestinationRefs() {
2779
2780        return namingResources.findMessageDestinationRefs();
2781
2782    }
2783
2784
2785    /**
2786     * Return the MIME type to which the specified extension is mapped,
2787     * if any; otherwise return <code>null</code>.
2788     *
2789     * @param extension Extension to map to a MIME type
2790     */

2791    public String JavaDoc findMimeMapping(String JavaDoc extension) {
2792
2793        return ((String JavaDoc) mimeMappings.get(extension));
2794
2795    }
2796
2797
2798    /**
2799     * Return the extensions for which MIME mappings are defined. If there
2800     * are none, a zero-length array is returned.
2801     */

2802    public String JavaDoc[] findMimeMappings() {
2803
2804        synchronized (mimeMappings) {
2805            String JavaDoc results[] = new String JavaDoc[mimeMappings.size()];
2806            return
2807                ((String JavaDoc[]) mimeMappings.keySet().toArray(results));
2808        }
2809
2810    }
2811
2812
2813    /**
2814     * Return the value for the specified context initialization
2815     * parameter name, if any; otherwise return <code>null</code>.
2816     *
2817     * @param name Name of the parameter to return
2818     */

2819    public String JavaDoc findParameter(String JavaDoc name) {
2820
2821        synchronized (parameters) {
2822            return ((String JavaDoc) parameters.get(name));
2823        }
2824
2825    }
2826
2827
2828    /**
2829     * Return the names of all defined context initialization parameters
2830     * for this Context. If no parameters are defined, a zero-length
2831     * array is returned.
2832     */

2833    public String JavaDoc[] findParameters() {
2834
2835        synchronized (parameters) {
2836            String JavaDoc results[] = new String JavaDoc[parameters.size()];
2837            return ((String JavaDoc[]) parameters.keySet().toArray(results));
2838        }
2839
2840    }
2841
2842
2843    /**
2844     * For the given security role (as used by an application), return the
2845     * corresponding role name (as defined by the underlying Realm) if there
2846     * is one. Otherwise, return the specified role unchanged.
2847     *
2848     * @param role Security role to map
2849     */

2850    public String JavaDoc findRoleMapping(String JavaDoc role) {
2851
2852        String JavaDoc realRole = null;
2853        synchronized (roleMappings) {
2854            realRole = (String JavaDoc) roleMappings.get(role);
2855        }
2856        if (realRole != null)
2857            return (realRole);
2858        else
2859            return (role);
2860
2861    }
2862
2863
2864    /**
2865     * Return <code>true</code> if the specified security role is defined
2866     * for this application; otherwise return <code>false</code>.
2867     *
2868     * @param role Security role to verify
2869     */

2870    public boolean findSecurityRole(String JavaDoc role) {
2871
2872        synchronized (securityRoles) {
2873            for (int i = 0; i < securityRoles.length; i++) {
2874                if (role.equals(securityRoles[i]))
2875                    return (true);
2876            }
2877        }
2878        return (false);
2879
2880    }
2881
2882
2883    /**
2884     * Return the security roles defined for this application. If none
2885     * have been defined, a zero-length array is returned.
2886     */

2887    public String JavaDoc[] findSecurityRoles() {
2888
2889        return (securityRoles);
2890
2891    }
2892
2893
2894    /**
2895     * Return the servlet name mapped by the specified pattern (if any);
2896     * otherwise return <code>null</code>.
2897     *
2898     * @param pattern Pattern for which a mapping is requested
2899     */

2900    public String JavaDoc findServletMapping(String JavaDoc pattern) {
2901
2902        synchronized (servletMappings) {
2903            return ((String JavaDoc) servletMappings.get(pattern));
2904        }
2905
2906    }
2907
2908
2909    /**
2910     * Return the patterns of all defined servlet mappings for this
2911     * Context. If no mappings are defined, a zero-length array is returned.
2912     */

2913    public String JavaDoc[] findServletMappings() {
2914
2915        synchronized (servletMappings) {
2916            String JavaDoc results[] = new String JavaDoc[servletMappings.size()];
2917            return
2918               ((String JavaDoc[]) servletMappings.keySet().toArray(results));
2919        }
2920
2921    }
2922
2923
2924    /**
2925     * Return the context-relative URI of the error page for the specified
2926     * HTTP status code, if any; otherwise return <code>null</code>.
2927     *
2928     * @param status HTTP status code to look up
2929     */

2930    public String JavaDoc findStatusPage(int status) {
2931
2932        return ((String JavaDoc) statusPages.get(new Integer JavaDoc(status)));
2933
2934    }
2935
2936
2937    /**
2938     * Return the set of HTTP status codes for which error pages have
2939     * been specified. If none are specified, a zero-length array
2940     * is returned.
2941     */

2942    public int[] findStatusPages() {
2943
2944        synchronized (statusPages) {
2945            int results[] = new int[statusPages.size()];
2946            Iterator JavaDoc elements = statusPages.keySet().iterator();
2947            int i = 0;
2948            while (elements.hasNext())
2949                results[i++] = ((Integer JavaDoc) elements.next()).intValue();
2950            return (results);
2951        }
2952
2953    }
2954
2955
2956    /**
2957     * Return the tag library descriptor location for the specified taglib
2958     * URI, if any; otherwise, return <code>null</code>.
2959     *
2960     * @param uri URI, relative to the web.xml file
2961     */

2962    public String JavaDoc findTaglib(String JavaDoc uri) {
2963
2964        synchronized (taglibs) {
2965            return ((String JavaDoc) taglibs.get(uri));
2966        }
2967
2968    }
2969
2970
2971    /**
2972     * Return the URIs of all tag libraries for which a tag library
2973     * descriptor location has been specified. If none are specified,
2974     * a zero-length array is returned.
2975     */

2976    public String JavaDoc[] findTaglibs() {
2977
2978        synchronized (taglibs) {
2979            String JavaDoc results[] = new String JavaDoc[taglibs.size()];
2980            return ((String JavaDoc[]) taglibs.keySet().toArray(results));
2981        }
2982
2983    }
2984
2985
2986    /**
2987     * Return <code>true</code> if the specified welcome file is defined
2988     * for this Context; otherwise return <code>false</code>.
2989     *
2990     * @param name Welcome file to verify
2991     */

2992    public boolean findWelcomeFile(String JavaDoc name) {
2993
2994        synchronized (welcomeFiles) {
2995            for (int i = 0; i < welcomeFiles.length; i++) {
2996                if (name.equals(welcomeFiles[i]))
2997                    return (true);
2998            }
2999        }
3000        return (false);
3001
3002    }
3003
3004
3005    /**
3006     * Return the set of watched resources for this Context. If none are
3007     * defined, a zero length array will be returned.
3008     */

3009    public String JavaDoc[] findWatchedResources() {
3010        return watchedResources;
3011    }
3012    
3013    
3014    /**
3015     * Return the set of welcome files defined for this Context. If none are
3016     * defined, a zero-length array is returned.
3017     */

3018    public String JavaDoc[] findWelcomeFiles() {
3019
3020        return (welcomeFiles);
3021
3022    }
3023
3024
3025    /**
3026     * Return the set of LifecycleListener classes that will be added to
3027     * newly created Wrappers automatically.
3028     */

3029    public String JavaDoc[] findWrapperLifecycles() {
3030
3031        return (wrapperLifecycles);
3032
3033    }
3034
3035
3036    /**
3037     * Return the set of ContainerListener classes that will be added to
3038     * newly created Wrappers automatically.
3039     */

3040    public String JavaDoc[] findWrapperListeners() {
3041
3042        return (wrapperListeners);
3043
3044    }
3045
3046
3047    /**
3048     * Reload this web application, if reloading is supported.
3049     * <p>
3050     * <b>IMPLEMENTATION NOTE</b>: This method is designed to deal with
3051     * reloads required by changes to classes in the underlying repositories
3052     * of our class loader. It does not handle changes to the web application
3053     * deployment descriptor. If that has occurred, you should stop this
3054     * Context and create (and start) a new Context instance instead.
3055     *
3056     * @exception IllegalStateException if the <code>reloadable</code>
3057     * property is set to <code>false</code>.
3058     */

3059    public synchronized void reload() {
3060
3061        // Validate our current component state
3062
if (!started)
3063            throw new IllegalStateException JavaDoc
3064                (sm.getString("containerBase.notStarted", logName()));
3065
3066        // Make sure reloading is enabled
3067
// if (!reloadable)
3068
// throw new IllegalStateException
3069
// (sm.getString("standardContext.notReloadable"));
3070
if(log.isInfoEnabled())
3071            log.info(sm.getString("standardContext.reloadingStarted"));
3072
3073        // Stop accepting requests temporarily
3074
setPaused(true);
3075
3076        try {
3077            stop();
3078        } catch (LifecycleException e) {
3079            log.error(sm.getString("standardContext.stoppingContext"), e);
3080        }
3081
3082        try {
3083            start();
3084        } catch (LifecycleException e) {
3085            log.error(sm.getString("standardContext.startingContext"), e);
3086        }
3087
3088        setPaused(false);
3089
3090    }
3091
3092
3093    /**
3094     * Remove the specified application listener class from the set of
3095     * listeners for this application.
3096     *
3097     * @param listener Java class name of the listener to be removed
3098     */

3099    public void removeApplicationListener(String JavaDoc listener) {
3100
3101        synchronized (applicationListeners) {
3102
3103            // Make sure this welcome file is currently present
3104
int n = -1;
3105            for (int i = 0; i < applicationListeners.length; i++) {
3106                if (applicationListeners[i].equals(listener)) {
3107                    n = i;
3108                    break;
3109                }
3110            }
3111            if (n < 0)
3112                return;
3113
3114            // Remove the specified constraint
3115
int j = 0;
3116            String JavaDoc results[] = new String JavaDoc[applicationListeners.length - 1];
3117            for (int i = 0; i < applicationListeners.length; i++) {
3118                if (i != n)
3119                    results[j++] = applicationListeners[i];
3120            }
3121            applicationListeners = results;
3122
3123        }
3124
3125        // Inform interested listeners
3126
fireContainerEvent("removeApplicationListener", listener);
3127
3128        // FIXME - behavior if already started?
3129

3130    }
3131
3132
3133    /**
3134     * Remove the application parameter with the specified name from
3135     * the set for this application.
3136     *
3137     * @param name Name of the application parameter to remove
3138     */

3139    public void removeApplicationParameter(String JavaDoc name) {
3140
3141        synchronized (applicationParameters) {
3142
3143            // Make sure this parameter is currently present
3144
int n = -1;
3145            for (int i = 0; i < applicationParameters.length; i++) {
3146                if (name.equals(applicationParameters[i].getName())) {
3147                    n = i;
3148                    break;
3149                }
3150            }
3151            if (n < 0)
3152                return;
3153
3154            // Remove the specified parameter
3155
int j = 0;
3156            ApplicationParameter results[] =
3157                new ApplicationParameter[applicationParameters.length - 1];
3158            for (int i = 0; i < applicationParameters.length; i++) {
3159                if (i != n)
3160                    results[j++] = applicationParameters[i];
3161            }
3162            applicationParameters = results;
3163
3164        }
3165
3166        // Inform interested listeners
3167
fireContainerEvent("removeApplicationParameter", name);
3168
3169    }
3170
3171
3172    /**
3173     * Add a child Container, only if the proposed child is an implementation
3174     * of Wrapper.
3175     *
3176     * @param child Child container to be added
3177     *
3178     * @exception IllegalArgumentException if the proposed container is
3179     * not an implementation of Wrapper
3180     */

3181    public void removeChild(Container child) {
3182
3183        if (!(child instanceof Wrapper)) {
3184            throw new IllegalArgumentException JavaDoc
3185                (sm.getString("standardContext.notWrapper"));
3186        }
3187
3188        super.removeChild(child);
3189
3190    }
3191
3192
3193    /**
3194     * Remove the specified security constraint from this web application.
3195     *
3196     * @param constraint Constraint to be removed
3197     */

3198    public void removeConstraint(SecurityConstraint constraint) {
3199
3200        synchronized (constraints) {
3201
3202            // Make sure this constraint is currently present
3203
int n = -1;
3204            for (int i = 0; i < constraints.length; i++) {
3205                if (constraints[i].equals(constraint)) {
3206                    n = i;
3207                    break;
3208                }
3209            }
3210            if (n < 0)
3211                return;
3212
3213            // Remove the specified constraint
3214
int j = 0;
3215            SecurityConstraint results[] =
3216                new SecurityConstraint[constraints.length - 1];
3217            for (int i = 0; i < constraints.length; i++) {
3218                if (i != n)
3219                    results[j++] = constraints[i];
3220            }
3221            constraints = results;
3222
3223        }
3224
3225        // Inform interested listeners
3226
fireContainerEvent("removeConstraint", constraint);
3227
3228    }
3229
3230
3231    /**
3232     * Remove the error page for the specified error code or
3233     * Java language exception, if it exists; otherwise, no action is taken.
3234     *
3235     * @param errorPage The error page definition to be removed
3236     */

3237    public void removeErrorPage(ErrorPage errorPage) {
3238
3239        String JavaDoc exceptionType = errorPage.getExceptionType();
3240        if (exceptionType != null) {
3241            synchronized (exceptionPages) {
3242                exceptionPages.remove(exceptionType);
3243            }
3244        } else {
3245            synchronized (statusPages) {
3246                if (errorPage.getErrorCode() == 200) {
3247                    this.okErrorPage = null;
3248                }
3249                statusPages.remove(new Integer JavaDoc(errorPage.getErrorCode()));
3250            }
3251        }
3252        fireContainerEvent("removeErrorPage", errorPage);
3253
3254    }
3255
3256
3257    /**
3258     * Remove the specified filter definition from this Context, if it exists;
3259     * otherwise, no action is taken.
3260     *
3261     * @param filterDef Filter definition to be removed
3262     */

3263    public void removeFilterDef(FilterDef filterDef) {
3264
3265        synchronized (filterDefs) {
3266            filterDefs.remove(filterDef.getFilterName());
3267        }
3268        fireContainerEvent("removeFilterDef", filterDef);
3269
3270    }
3271
3272
3273    /**
3274     * Remove a filter mapping from this Context.
3275     *
3276     * @param filterMap The filter mapping to be removed
3277     */

3278    public void removeFilterMap(FilterMap filterMap) {
3279
3280        synchronized (filterMaps) {
3281
3282            // Make sure this filter mapping is currently present
3283
int n = -1;
3284            for (int i = 0; i < filterMaps.length; i++) {
3285                if (filterMaps[i] == filterMap) {
3286                    n = i;
3287                    break;
3288                }
3289            }
3290            if (n < 0)
3291                return;
3292
3293            // Remove the specified filter mapping
3294
FilterMap results[] = new FilterMap[filterMaps.length - 1];
3295            System.arraycopy(filterMaps, 0, results, 0, n);
3296            System.arraycopy(filterMaps, n + 1, results, n,
3297                             (filterMaps.length - 1) - n);
3298            filterMaps = results;
3299
3300        }
3301
3302        // Inform interested listeners
3303
fireContainerEvent("removeFilterMap", filterMap);
3304
3305    }
3306
3307
3308    /**
3309     * Remove a class name from the set of InstanceListener classes that
3310     * will be added to newly created Wrappers.
3311     *
3312     * @param listener Class name of an InstanceListener class to be removed
3313     */

3314    public void removeInstanceListener(String JavaDoc listener) {
3315
3316        synchronized (instanceListeners) {
3317
3318            // Make sure this welcome file is currently present
3319
int n = -1;
3320            for (int i = 0; i < instanceListeners.length; i++) {
3321                if (instanceListeners[i].equals(listener)) {
3322                    n = i;
3323                    break;
3324                }
3325            }
3326            if (n < 0)
3327                return;
3328
3329            // Remove the specified constraint
3330
int j = 0;
3331            String JavaDoc results[] = new String JavaDoc[instanceListeners.length - 1];
3332            for (int i = 0; i < instanceListeners.length; i++) {
3333                if (i != n)
3334                    results[j++] = instanceListeners[i];
3335            }
3336            instanceListeners = results;
3337
3338        }
3339
3340        // Inform interested listeners
3341
fireContainerEvent("removeInstanceListener", listener);
3342
3343    }
3344
3345
3346    /**
3347     * Remove any message destination with the specified name.
3348     *
3349     * @param name Name of the message destination to remove
3350     */

3351    public void removeMessageDestination(String JavaDoc name) {
3352
3353        synchronized (messageDestinations) {
3354            messageDestinations.remove(name);
3355        }
3356        fireContainerEvent("removeMessageDestination", name);
3357
3358    }
3359
3360
3361    /**
3362     * Remove any message destination ref with the specified name.
3363     *
3364     * @param name Name of the message destination ref to remove
3365     */

3366    public void removeMessageDestinationRef(String JavaDoc name) {
3367
3368        namingResources.removeMessageDestinationRef(name);
3369        fireContainerEvent("removeMessageDestinationRef", name);
3370
3371    }
3372
3373
3374    /**
3375     * Remove the MIME mapping for the specified extension, if it exists;
3376     * otherwise, no action is taken.
3377     *
3378     * @param extension Extension to remove the mapping for
3379     */

3380    public void removeMimeMapping(String JavaDoc extension) {
3381
3382        synchronized (mimeMappings) {
3383            mimeMappings.remove(extension);
3384        }
3385        fireContainerEvent("removeMimeMapping", extension);
3386
3387    }
3388
3389
3390    /**
3391     * Remove the context initialization parameter with the specified
3392     * name, if it exists; otherwise, no action is taken.
3393     *
3394     * @param name Name of the parameter to remove
3395     */

3396    public void removeParameter(String JavaDoc name) {
3397
3398        synchronized (parameters) {
3399            parameters.remove(name);
3400        }
3401        fireContainerEvent("removeParameter", name);
3402
3403    }
3404
3405
3406    /**
3407     * Remove any security role reference for the specified name
3408     *
3409     * @param role Security role (as used in the application) to remove
3410     */

3411    public void removeRoleMapping(String JavaDoc role) {
3412
3413        synchronized (roleMappings) {
3414            roleMappings.remove(role);
3415        }
3416        fireContainerEvent("removeRoleMapping", role);
3417
3418    }
3419
3420
3421    /**
3422     * Remove any security role with the specified name.
3423     *
3424     * @param role Security role to remove
3425     */

3426    public void removeSecurityRole(String JavaDoc role) {
3427
3428        synchronized (securityRoles) {
3429
3430            // Make sure this security role is currently present
3431
int n = -1;
3432            for (int i = 0; i < securityRoles.length; i++) {
3433                if (role.equals(securityRoles[i])) {
3434                    n = i;
3435                    break;
3436                }
3437            }
3438            if (n < 0)
3439                return;
3440
3441            // Remove the specified security role
3442
int j = 0;
3443            String JavaDoc results[] = new String JavaDoc[securityRoles.length - 1];
3444            for (int i = 0; i < securityRoles.length; i++) {
3445                if (i != n)
3446                    results[j++] = securityRoles[i];
3447            }
3448            securityRoles = results;
3449
3450        }
3451
3452        // Inform interested listeners
3453
fireContainerEvent("removeSecurityRole", role);
3454
3455    }
3456
3457
3458    /**
3459     * Remove any servlet mapping for the specified pattern, if it exists;
3460     * otherwise, no action is taken.
3461     *
3462     * @param pattern URL pattern of the mapping to remove
3463     */

3464    public void removeServletMapping(String JavaDoc pattern) {
3465
3466        String JavaDoc name = null;
3467        synchronized (servletMappings) {
3468            name = (String JavaDoc) servletMappings.remove(pattern);
3469        }
3470        Wrapper wrapper = (Wrapper) findChild(name);
3471        if( wrapper != null ) {
3472            wrapper.removeMapping(pattern);
3473        }
3474        mapper.removeWrapper(pattern);
3475        fireContainerEvent("removeServletMapping", pattern);
3476
3477    }
3478
3479
3480    /**
3481     * Remove the tag library location forthe specified tag library URI.
3482     *
3483     * @param uri URI, relative to the web.xml file
3484     */

3485    public void removeTaglib(String JavaDoc uri) {
3486
3487        synchronized (taglibs) {
3488            taglibs.remove(uri);
3489        }
3490        fireContainerEvent("removeTaglib", uri);
3491    }
3492
3493
3494    /**
3495     * Remove the specified watched resource name from the list associated
3496     * with this Context.
3497     *
3498     * @param name Name of the watched resource to be removed
3499     */

3500    public void removeWatchedResource(String JavaDoc name) {
3501        
3502        synchronized (watchedResources) {
3503
3504            // Make sure this watched resource is currently present
3505
int n = -1;
3506            for (int i = 0; i < watchedResources.length; i++) {
3507                if (watchedResources[i].equals(name)) {
3508                    n = i;
3509                    break;
3510                }
3511            }
3512            if (n < 0)
3513                return;
3514
3515            // Remove the specified watched resource
3516
int j = 0;
3517            String JavaDoc results[] = new String JavaDoc[watchedResources.length - 1];
3518            for (int i = 0; i < watchedResources.length; i++) {
3519                if (i != n)
3520                    results[j++] = watchedResources[i];
3521            }
3522            watchedResources = results;
3523
3524        }
3525
3526        fireContainerEvent("removeWatchedResource", name);
3527
3528    }
3529    
3530    
3531    /**
3532     * Remove the specified welcome file name from the list recognized
3533     * by this Context.
3534     *
3535     * @param name Name of the welcome file to be removed
3536     */

3537    public void removeWelcomeFile(String JavaDoc name) {
3538
3539        synchronized (welcomeFiles) {
3540
3541            // Make sure this welcome file is currently present
3542
int n = -1;
3543            for (int i = 0; i < welcomeFiles.length; i++) {
3544                if (welcomeFiles[i].equals(name)) {
3545                    n = i;
3546                    break;
3547                }
3548            }
3549            if (n < 0)
3550                return;
3551
3552            // Remove the specified constraint
3553
int j = 0;
3554            String JavaDoc results[] = new String JavaDoc[welcomeFiles.length - 1];
3555            for (int i = 0; i < welcomeFiles.length; i++) {
3556                if (i != n)
3557                    results[j++] = welcomeFiles[i];
3558            }
3559            welcomeFiles = results;
3560
3561        }
3562
3563        // Inform interested listeners
3564
postWelcomeFiles();
3565        fireContainerEvent("removeWelcomeFile", name);
3566
3567    }
3568
3569
3570    /**
3571     * Remove a class name from the set of LifecycleListener classes that
3572     * will be added to newly created Wrappers.
3573     *
3574     * @param listener Class name of a LifecycleListener class to be removed
3575     */

3576    public void removeWrapperLifecycle(String JavaDoc listener) {
3577
3578
3579        synchronized (wrapperLifecycles) {
3580
3581            // Make sure this welcome file is currently present
3582
int n = -1;
3583            for (int i = 0; i < wrapperLifecycles.length; i++) {
3584                if (wrapperLifecycles[i].equals(listener)) {
3585                    n = i;
3586                    break;
3587                }
3588            }
3589            if (n < 0)
3590                return;
3591
3592            // Remove the specified constraint
3593
int j = 0;
3594            String JavaDoc results[] = new String JavaDoc[wrapperLifecycles.length - 1];
3595            for (int i = 0; i < wrapperLifecycles.length; i++) {
3596                if (i != n)
3597                    results[j++] = wrapperLifecycles[i];
3598            }
3599            wrapperLifecycles = results;
3600
3601        }
3602
3603        // Inform interested listeners
3604
fireContainerEvent("removeWrapperLifecycle", listener);
3605
3606    }
3607
3608
3609    /**
3610     * Remove a class name from the set of ContainerListener classes that
3611     * will be added to newly created Wrappers.
3612     *
3613     * @param listener Class name of a ContainerListener class to be removed
3614     */

3615    public void removeWrapperListener(String JavaDoc listener) {
3616
3617
3618        synchronized (wrapperListeners) {
3619
3620            // Make sure this welcome file is currently present
3621
int n = -1;
3622            for (int i = 0; i < wrapperListeners.length; i++) {
3623                if (wrapperListeners[i].equals(listener)) {
3624                    n = i;
3625                    break;
3626                }
3627            }
3628            if (n < 0)
3629                return;
3630
3631            // Remove the specified constraint
3632
int j = 0;
3633            String JavaDoc results[] = new String JavaDoc[wrapperListeners.length - 1];
3634            for (int i = 0; i < wrapperListeners.length; i++) {
3635                if (i != n)
3636                    results[j++] = wrapperListeners[i];
3637            }
3638            wrapperListeners = results;
3639
3640        }
3641
3642        // Inform interested listeners
3643
fireContainerEvent("removeWrapperListener", listener);
3644
3645    }
3646
3647
3648    /**
3649     * Gets the cumulative processing times of all servlets in this
3650     * StandardContext.
3651     *
3652     * @return Cumulative processing times of all servlets in this
3653     * StandardContext
3654     */

3655    public long getProcessingTime() {
3656        
3657        long result = 0;
3658
3659        Container[] children = findChildren();
3660        if (children != null) {
3661            for( int i=0; i< children.length; i++ ) {
3662                result += ((StandardWrapper)children[i]).getProcessingTime();
3663            }
3664        }
3665
3666        return result;
3667    }
3668
3669
3670    // --------------------------------------------------------- Public Methods
3671

3672
3673    /**
3674     * Configure and initialize the set of filters for this Context.
3675     * Return <code>true</code> if all filter initialization completed
3676     * successfully, or <code>false</code> otherwise.
3677     */

3678    public boolean filterStart() {
3679
3680        if (getLogger().isDebugEnabled())
3681            getLogger().debug("Starting filters");
3682        // Instantiate and record a FilterConfig for each defined filter
3683
boolean ok = true;
3684        synchronized (filterConfigs) {
3685            filterConfigs.clear();
3686            Iterator JavaDoc names = filterDefs.keySet().iterator();
3687            while (names.hasNext()) {
3688                String JavaDoc name = (String JavaDoc) names.next();
3689                if (getLogger().isDebugEnabled())
3690                    getLogger().debug(" Starting filter '" + name + "'");
3691                ApplicationFilterConfig filterConfig = null;
3692                try {
3693                    filterConfig = new ApplicationFilterConfig
3694                      (this, (FilterDef) filterDefs.get(name));
3695                    filterConfigs.put(name, filterConfig);
3696                } catch (Throwable JavaDoc t) {
3697                    getLogger().error
3698                        (sm.getString("standardContext.filterStart", name), t);
3699                    ok = false;
3700                }
3701            }
3702        }
3703
3704        return (ok);
3705
3706    }
3707
3708
3709    /**
3710     * Finalize and release the set of filters for this Context.
3711     * Return <code>true</code> if all filter finalization completed
3712     * successfully, or <code>false</code> otherwise.
3713     */

3714    public boolean filterStop() {
3715
3716        if (getLogger().isDebugEnabled())
3717            getLogger().debug("Stopping filters");
3718
3719        // Release all Filter and FilterConfig instances
3720
synchronized (filterConfigs) {
3721            Iterator JavaDoc names = filterConfigs.keySet().iterator();
3722            while (names.hasNext()) {
3723                String JavaDoc name = (String JavaDoc) names.next();
3724                if (getLogger().isDebugEnabled())
3725                    getLogger().debug(" Stopping filter '" + name + "'");
3726                ApplicationFilterConfig filterConfig =
3727                  (ApplicationFilterConfig) filterConfigs.get(name);
3728                filterConfig.release();
3729            }
3730            filterConfigs.clear();
3731        }
3732        return (true);
3733
3734    }
3735
3736
3737    /**
3738     * Find and return the initialized <code>FilterConfig</code> for the
3739     * specified filter name, if any; otherwise return <code>null</code>.
3740     *
3741     * @param name Name of the desired filter
3742     */

3743    public FilterConfig JavaDoc findFilterConfig(String JavaDoc name) {
3744
3745        return ((FilterConfig JavaDoc) filterConfigs.get(name));
3746
3747    }
3748
3749
3750    /**
3751     * Configure the set of instantiated application event listeners
3752     * for this Context. Return <code>true</code> if all listeners wre
3753     * initialized successfully, or <code>false</code> otherwise.
3754     */

3755    public boolean listenerStart() {
3756
3757        if (log.isDebugEnabled())
3758            log.debug("Configuring application event listeners");
3759
3760        // Instantiate the required listeners
3761
ClassLoader JavaDoc loader = getLoader().getClassLoader();
3762        String JavaDoc listeners[] = findApplicationListeners();
3763        Object JavaDoc results[] = new Object JavaDoc[listeners.length];
3764        boolean ok = true;
3765        for (int i = 0; i < results.length; i++) {
3766            if (getLogger().isDebugEnabled())
3767                getLogger().debug(" Configuring event listener class '" +
3768                    listeners[i] + "'");
3769            try {
3770                Class JavaDoc clazz = loader.loadClass(listeners[i]);
3771                results[i] = clazz.newInstance();
3772                // Annotation processing
3773
if (!getIgnoreAnnotations()) {
3774                    getAnnotationProcessor().processAnnotations(results[i]);
3775                    getAnnotationProcessor().postConstruct(results[i]);
3776                }
3777            } catch (Throwable JavaDoc t) {
3778                getLogger().error
3779                    (sm.getString("standardContext.applicationListener",
3780                                  listeners[i]), t);
3781                ok = false;
3782            }
3783        }
3784        if (!ok) {
3785            getLogger().error(sm.getString("standardContext.applicationSkipped"));
3786            return (false);
3787        }
3788
3789        // Sort listeners in two arrays
3790
ArrayList JavaDoc eventListeners = new ArrayList JavaDoc();
3791        ArrayList JavaDoc lifecycleListeners = new ArrayList JavaDoc();
3792        for (int i = 0; i < results.length; i++) {
3793            if ((results[i] instanceof ServletContextAttributeListener JavaDoc)
3794                || (results[i] instanceof ServletRequestAttributeListener JavaDoc)
3795                || (results[i] instanceof ServletRequestListener JavaDoc)
3796                || (results[i] instanceof HttpSessionAttributeListener JavaDoc)) {
3797                eventListeners.add(results[i]);
3798            }
3799            if ((results[i] instanceof ServletContextListener JavaDoc)
3800                || (results[i] instanceof HttpSessionListener JavaDoc)) {
3801                lifecycleListeners.add(results[i]);
3802            }
3803        }
3804
3805        setApplicationEventListeners(eventListeners.toArray());
3806        setApplicationLifecycleListeners(lifecycleListeners.toArray());
3807
3808        // Send application start events
3809

3810        if (getLogger().isDebugEnabled())
3811            getLogger().debug("Sending application start events");
3812
3813        Object JavaDoc instances[] = getApplicationLifecycleListeners();
3814        if (instances == null)
3815            return (ok);
3816        ServletContextEvent JavaDoc event =
3817          new ServletContextEvent JavaDoc(getServletContext());
3818        for (int i = 0; i < instances.length; i++) {
3819            if (instances[i] == null)
3820                continue;
3821            if (!(instances[i] instanceof ServletContextListener JavaDoc))
3822                continue;
3823            ServletContextListener JavaDoc listener =
3824                (ServletContextListener JavaDoc) instances[i];
3825            try {
3826                fireContainerEvent("beforeContextInitialized", listener);
3827                listener.contextInitialized(event);
3828                fireContainerEvent("afterContextInitialized", listener);
3829            } catch (Throwable JavaDoc t) {
3830                fireContainerEvent("afterContextInitialized", listener);
3831                getLogger().error
3832                    (sm.getString("standardContext.listenerStart",
3833                                  instances[i].getClass().getName()), t);
3834                ok = false;
3835            }
3836        }
3837        return (ok);
3838
3839    }
3840
3841
3842    /**
3843     * Send an application stop event to all interested listeners.
3844     * Return <code>true</code> if all events were sent successfully,
3845     * or <code>false</code> otherwise.
3846     */

3847    public boolean listenerStop() {
3848
3849        if (log.isDebugEnabled())
3850            log.debug("Sending application stop events");
3851
3852        boolean ok = true;
3853        Object JavaDoc listeners[] = getApplicationLifecycleListeners();
3854        if (listeners != null) {
3855            ServletContextEvent JavaDoc event =
3856                new ServletContextEvent JavaDoc(getServletContext());
3857            for (int i = 0; i < listeners.length; i++) {
3858                int j = (listeners.length - 1) - i;
3859                if (listeners[j] == null)
3860                    continue;
3861                if (listeners[j] instanceof ServletContextListener JavaDoc) {
3862                    ServletContextListener JavaDoc listener =
3863                        (ServletContextListener JavaDoc) listeners[j];
3864                    try {
3865                        fireContainerEvent("beforeContextDestroyed", listener);
3866                        listener.contextDestroyed(event);
3867                        fireContainerEvent("afterContextDestroyed", listener);
3868                    } catch (Throwable JavaDoc t) {
3869                        fireContainerEvent("afterContextDestroyed", listener);
3870                        getLogger().error
3871                            (sm.getString("standardContext.listenerStop",
3872                                listeners[j].getClass().getName()), t);
3873                        ok = false;
3874                    }
3875                }
3876                // Annotation processing
3877
if (!getIgnoreAnnotations()) {
3878                    try {
3879                        getAnnotationProcessor().preDestroy(listeners[j]);
3880                    } catch (Throwable JavaDoc t) {
3881                        getLogger().error
3882                            (sm.getString("standardContext.listenerStop",
3883                                listeners[j].getClass().getName()), t);
3884                        ok = false;
3885                    }
3886                }
3887            }
3888        }
3889
3890        // Annotation processing
3891
listeners = getApplicationEventListeners();
3892        if (!getIgnoreAnnotations() && listeners != null) {
3893            for (int i = 0; i < listeners.length; i++) {
3894                int j = (listeners.length - 1) - i;
3895                if (listeners[j] == null)
3896                    continue;
3897                try {
3898                    getAnnotationProcessor().preDestroy(listeners[j]);
3899                } catch (Throwable JavaDoc t) {
3900                    getLogger().error
3901                        (sm.getString("standardContext.listenerStop",
3902                            listeners[j].getClass().getName()), t);
3903                    ok = false;
3904                }
3905            }
3906        }
3907        
3908        setApplicationEventListeners(null);
3909        setApplicationLifecycleListeners(null);
3910
3911        return (ok);
3912
3913    }
3914
3915
3916    /**
3917     * Allocate resources, including proxy.
3918     * Return <code>true</code> if initialization was successfull,
3919     * or <code>false</code> otherwise.
3920     */

3921    public boolean resourcesStart() {
3922
3923        boolean ok = true;
3924
3925        Hashtable JavaDoc env = new Hashtable JavaDoc();
3926        if (getParent() != null)
3927            env.put(ProxyDirContext.HOST, getParent().getName());
3928        env.put(ProxyDirContext.CONTEXT, getName());
3929
3930        try {
3931            ProxyDirContext proxyDirContext =
3932                new ProxyDirContext(env, webappResources);
3933            if (webappResources instanceof FileDirContext) {
3934                filesystemBased = true;
3935                ((FileDirContext) webappResources).setCaseSensitive
3936                    (isCaseSensitive());
3937                ((FileDirContext) webappResources).setAllowLinking
3938                    (isAllowLinking());
3939            }
3940            if (webappResources instanceof BaseDirContext) {
3941                ((BaseDirContext) webappResources).setDocBase(getBasePath());
3942                ((BaseDirContext) webappResources).setCached
3943                    (isCachingAllowed());
3944                ((BaseDirContext) webappResources).setCacheTTL(getCacheTTL());
3945                ((BaseDirContext) webappResources).setCacheMaxSize
3946                    (getCacheMaxSize());
3947                ((BaseDirContext) webappResources).allocate();
3948            }
3949            // Register the cache in JMX
3950
if (isCachingAllowed()) {
3951                ObjectName JavaDoc resourcesName =
3952                    new ObjectName JavaDoc(this.getDomain() + ":type=Cache,host="
3953                                   + getHostname() + ",path="
3954                                   + (("".equals(getPath()))?"/":getPath()));
3955                Registry.getRegistry(null, null).registerComponent
3956                    (proxyDirContext.getCache(), resourcesName, null);
3957            }
3958            this.resources = proxyDirContext;
3959        } catch (Throwable JavaDoc t) {
3960            log.error(sm.getString("standardContext.resourcesStart"), t);
3961            ok = false;
3962        }
3963
3964        return (ok);
3965
3966    }
3967
3968
3969    /**
3970     * Deallocate resources and destroy proxy.
3971     */

3972    public boolean resourcesStop() {
3973
3974        boolean ok = true;
3975
3976        try {
3977            if (resources != null) {
3978                if (resources instanceof Lifecycle) {
3979                    ((Lifecycle) resources).stop();
3980                }
3981                if (webappResources instanceof BaseDirContext) {
3982                    ((BaseDirContext) webappResources).release();
3983                }
3984                // Unregister the cache in JMX
3985
if (isCachingAllowed()) {
3986                    ObjectName JavaDoc resourcesName =
3987                        new ObjectName JavaDoc(this.getDomain()
3988                                       + ":type=Cache,host="
3989                                       + getHostname() + ",path="
3990                                       + (("".equals(getPath()))?"/"
3991                                          :getPath()));
3992                    Registry.getRegistry(null, null)
3993                        .unregisterComponent(resourcesName);
3994                }
3995            }
3996        } catch (Throwable JavaDoc t) {
3997            log.error(sm.getString("standardContext.resourcesStop"), t);
3998            ok = false;
3999        }
4000
4001        this.resources = null;
4002
4003        return (ok);
4004
4005    }
4006
4007
4008    /**
4009     * Load and initialize all servlets marked "load on startup" in the
4010     * web application deployment descriptor.
4011     *
4012     * @param children Array of wrappers for all currently defined
4013     * servlets (including those not declared load on startup)
4014     */

4015    public void loadOnStartup(Container children[]) {
4016
4017        // Collect "load on startup" servlets that need to be initialized
4018
TreeMap JavaDoc map = new TreeMap JavaDoc();
4019        for (int i = 0; i < children.length; i++) {
4020            Wrapper wrapper = (Wrapper) children[i];
4021            int loadOnStartup = wrapper.getLoadOnStartup();
4022            if (loadOnStartup < 0)
4023                continue;
4024            if (loadOnStartup == 0) // Arbitrarily put them last
4025
loadOnStartup = Integer.MAX_VALUE;
4026            Integer JavaDoc key = new Integer JavaDoc(loadOnStartup);
4027            ArrayList JavaDoc list = (ArrayList JavaDoc) map.get(key);
4028            if (list == null) {
4029                list = new ArrayList JavaDoc();
4030                map.put(key, list);
4031            }
4032            list.add(wrapper);
4033        }
4034
4035        // Load the collected "load on startup" servlets
4036
Iterator JavaDoc keys = map.keySet().iterator();
4037        while (keys.hasNext()) {
4038            Integer JavaDoc key = (Integer JavaDoc) keys.next();
4039            ArrayList JavaDoc list = (ArrayList JavaDoc) map.get(key);
4040            Iterator JavaDoc wrappers = list.iterator();
4041            while (wrappers.hasNext()) {
4042                Wrapper wrapper = (Wrapper) wrappers.next();
4043                try {
4044                    wrapper.load();
4045                } catch (ServletException JavaDoc e) {
4046                    getLogger().error(sm.getString("standardWrapper.loadException",
4047                                      getName()), StandardWrapper.getRootCause(e));
4048                    // NOTE: load errors (including a servlet that throws
4049
// UnavailableException from tht init() method) are NOT
4050
// fatal to application startup
4051
}
4052            }
4053        }
4054
4055    }
4056
4057
4058    /**
4059     * Start this Context component.
4060     *
4061     * @exception LifecycleException if a startup error occurs
4062     */

4063    public synchronized void start() throws LifecycleException {
4064        //if (lazy ) return;
4065
if (started) {
4066            if(log.isInfoEnabled())
4067                log.info(sm.getString("containerBase.alreadyStarted", logName()));
4068            return;
4069        }
4070        if( !initialized ) {
4071            try {
4072                init();
4073            } catch( Exception JavaDoc ex ) {
4074                throw new LifecycleException("Error initializaing ", ex);
4075            }
4076        }
4077        if(log.isDebugEnabled())
4078            log.debug("Starting " + ("".equals(getName()) ? "ROOT" : getName()));
4079
4080        // Set JMX object name for proper pipeline registration
4081
preRegisterJMX();
4082
4083        if ((oname != null) &&
4084            (Registry.getRegistry(null, null).getMBeanServer().isRegistered(oname))) {
4085            // As things depend on the JMX registration, the context
4086
// must be reregistered again once properly initialized
4087
Registry.getRegistry(null, null).unregisterComponent(oname);
4088        }
4089
4090        // Notify our interested LifecycleListeners
4091
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
4092
4093        setAvailable(false);
4094        setConfigured(false);
4095        boolean ok = true;
4096
4097        // Add missing components as necessary
4098
if (webappResources == null) { // (1) Required by Loader
4099
if (log.isDebugEnabled())
4100                log.debug("Configuring default Resources");
4101            try {
4102                if ((docBase != null) && (docBase.endsWith(".war")) && (!(new File JavaDoc(getBasePath())).isDirectory()))
4103                    setResources(new WARDirContext());
4104                else
4105                    setResources(new FileDirContext());
4106            } catch (IllegalArgumentException JavaDoc e) {
4107                log.error("Error initializing resources: " + e.getMessage());
4108                ok = false;
4109            }
4110        }
4111        if (ok) {
4112            if (!resourcesStart()) {
4113                log.error( "Error in resourceStart()");
4114                ok = false;
4115            }
4116        }
4117
4118        // Look for a realm - that may have been configured earlier.
4119
// If the realm is added after context - it'll set itself.
4120
// TODO: what is the use case for this ?
4121
if( realm == null && mserver != null ) {
4122            ObjectName JavaDoc realmName=null;
4123            try {
4124                realmName=new ObjectName JavaDoc( getEngineName() + ":type=Realm,host=" +
4125                        getHostname() + ",path=" + getPath());
4126                if( mserver.isRegistered(realmName ) ) {
4127                    mserver.invoke(realmName, "init",
4128                            new Object JavaDoc[] {},
4129                            new String JavaDoc[] {}
4130                    );
4131                }
4132            } catch( Throwable JavaDoc t ) {
4133                if(log.isDebugEnabled())
4134                    log.debug("No realm for this host " + realmName);
4135            }
4136        }
4137        
4138        if (getLoader() == null) {
4139            WebappLoader webappLoader = new WebappLoader(getParentClassLoader());
4140            webappLoader.setDelegate(getDelegate());
4141            setLoader(webappLoader);
4142        }
4143
4144        // Initialize character set mapper
4145
getCharsetMapper();
4146
4147        // Post work directory
4148
postWorkDirectory();
4149
4150        // Validate required extensions
4151
boolean dependencyCheck = true;
4152        try {
4153            dependencyCheck = ExtensionValidator.validateApplication
4154                (getResources(), this);
4155        } catch (IOException JavaDoc ioe) {
4156            log.error("Error in dependencyCheck", ioe);
4157            dependencyCheck = false;
4158        }
4159
4160        if (!dependencyCheck) {
4161            // do not make application available if depency check fails
4162
ok = false;
4163        }
4164
4165        // Reading the "catalina.useNaming" environment variable
4166
String JavaDoc useNamingProperty = System.getProperty("catalina.useNaming");
4167        if ((useNamingProperty != null)
4168            && (useNamingProperty.equals("false"))) {
4169            useNaming = false;
4170        }
4171
4172        if (ok && isUseNaming()) {
4173            if (namingContextListener == null) {
4174                namingContextListener = new NamingContextListener();
4175                namingContextListener.setName(getNamingContextName());
4176                addLifecycleListener(namingContextListener);
4177            }
4178        }
4179        
4180        // Standard container startup
4181
if (log.isDebugEnabled())
4182            log.debug("Processing standard container startup");
4183
4184        
4185        // Binding thread
4186
ClassLoader JavaDoc oldCCL = bindThread();
4187
4188        boolean mainOk = false;
4189
4190        try {
4191
4192            if (ok) {
4193                
4194                started = true;
4195
4196                // Start our subordinate components, if any
4197
if ((loader != null) && (loader instanceof Lifecycle))
4198                    ((Lifecycle) loader).start();
4199
4200                // Unbinding thread
4201
unbindThread(oldCCL);
4202
4203                // Binding thread
4204
oldCCL = bindThread();
4205
4206                // Initialize logger again. Other components might have used it too early,
4207
// so it should be reset.
4208
logger = null;
4209                getLogger();
4210                if ((logger != null) && (logger instanceof Lifecycle))
4211                    ((Lifecycle) logger).start();
4212                
4213                if ((cluster != null) && (cluster instanceof Lifecycle))
4214                    ((Lifecycle) cluster).start();
4215                if ((realm != null) && (realm instanceof Lifecycle))
4216                    ((Lifecycle) realm).start();
4217                if ((resources != null) && (resources instanceof Lifecycle))
4218                    ((Lifecycle) resources).start();
4219
4220                // Start our child containers, if any
4221
Container children[] = findChildren();
4222                for (int i = 0; i < children.length; i++) {
4223                    if (children[i] instanceof Lifecycle)
4224                        ((Lifecycle) children[i]).start();
4225                }
4226
4227                // Start the Valves in our pipeline (including the basic),
4228
// if any
4229
if (pipeline instanceof Lifecycle) {
4230                    ((Lifecycle) pipeline).start();
4231                }
4232                
4233                if(getProcessTlds()) {
4234                    processTlds();
4235                }
4236                
4237                // Notify our interested LifecycleListeners
4238
lifecycle.fireLifecycleEvent(START_EVENT, null);
4239                
4240                // Acquire clustered manager
4241
Manager contextManager = null;
4242                if (manager == null) {
4243                    if ( (getCluster() != null) && distributable) {
4244                        try {
4245                            contextManager = getCluster().createManager(getName());
4246                        } catch (Exception JavaDoc ex) {
4247                            log.error("standardContext.clusterFail", ex);
4248                            ok = false;
4249                        }
4250                    } else {
4251                        contextManager = new StandardManager();
4252                    }
4253                }
4254                
4255                // Configure default manager if none was specified
4256
if (contextManager != null) {
4257                    setManager(contextManager);
4258                }
4259
4260                if (manager!=null && (getCluster() != null) && distributable) {
4261                    //let the cluster know that there is a context that is distributable
4262
//and that it has its own manager
4263
getCluster().registerManager(manager);
4264                }
4265
4266                
4267                // Start manager
4268
if ((manager != null) && (manager instanceof Lifecycle)) {
4269                    ((Lifecycle) getManager()).start();
4270                }
4271
4272                // Start ContainerBackgroundProcessor thread
4273
super.threadStart();
4274
4275                mainOk = true;
4276
4277            }
4278
4279        } finally {
4280            // Unbinding thread
4281
unbindThread(oldCCL);
4282            if (!mainOk) {
4283                // An exception occurred
4284
// Register with JMX anyway, to allow management
4285
registerJMX();
4286            }
4287        }
4288
4289        if (!getConfigured()) {
4290            log.error( "Error getConfigured");
4291            ok = false;
4292        }
4293
4294        // We put the resources into the servlet context
4295
if (ok)
4296            getServletContext().setAttribute
4297                (Globals.RESOURCES_ATTR, getResources());
4298
4299        // Initialize associated mapper
4300
mapper.setContext(getPath(), welcomeFiles, resources);
4301
4302        // Binding thread
4303
oldCCL = bindThread();
4304
4305        // Set annotation processing parameter for Jasper (unfortunately, since
4306
// this can be configured in many places and not just in /WEB-INF/web.xml,
4307
// there are not many solutions)
4308
// Initialize annotation processor
4309
if (ok && !getIgnoreAnnotations()) {
4310            if (annotationProcessor == null) {
4311                if (isUseNaming() && namingContextListener != null) {
4312                    annotationProcessor =
4313                        new DefaultAnnotationProcessor(namingContextListener.getEnvContext());
4314                } else {
4315                    annotationProcessor = new DefaultAnnotationProcessor(null);
4316                }
4317            }
4318            getServletContext().setAttribute
4319                (AnnotationProcessor.class.getName(), annotationProcessor);
4320        }
4321
4322        try {
4323            
4324            // Create context attributes that will be required
4325
if (ok) {
4326                postWelcomeFiles();
4327            }
4328            
4329            if (ok) {
4330                // Notify our interested LifecycleListeners
4331
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
4332            }
4333            
4334            // Configure and call application event listeners and filters
4335
if (ok) {
4336                if (!listenerStart()) {
4337                    log.error( "Error listenerStart");
4338                    ok = false;
4339                }
4340            }
4341            if (ok) {
4342                if (!filterStart()) {
4343                    log.error( "Error filterStart");
4344                    ok = false;
4345                }
4346            }
4347            
4348            // Load and initialize all "load on startup" servlets
4349
if (ok) {
4350                loadOnStartup(findChildren());
4351            }
4352            
4353        } finally {
4354            // Unbinding thread
4355
unbindThread(oldCCL);
4356        }
4357
4358        // Set available status depending upon startup success
4359
if (ok) {
4360            if (log.isDebugEnabled())
4361                log.debug("Starting completed");
4362            setAvailable(true);
4363        } else {
4364            log.error(sm.getString("standardContext.startFailed", getName()));
4365            try {
4366                stop();
4367            } catch (Throwable JavaDoc t) {
4368                log.error(sm.getString("standardContext.startCleanup"), t);
4369            }
4370            setAvailable(false);
4371        }
4372
4373        // JMX registration
4374
registerJMX();
4375
4376        startTime=System.currentTimeMillis();
4377        
4378        // Send j2ee.state.running notification
4379
if (ok && (this.getObjectName() != null)) {
4380            Notification JavaDoc notification =
4381                new Notification JavaDoc("j2ee.state.running", this.getObjectName(),
4382                                sequenceNumber++);
4383            broadcaster.sendNotification(notification);
4384        }
4385
4386        // Close all JARs right away to avoid always opening a peak number
4387
// of files on startup
4388
if (getLoader() instanceof WebappLoader) {
4389            ((WebappLoader) getLoader()).closeJARs(true);
4390        }
4391
4392        // Reinitializing if something went wrong
4393
if (!ok && started) {
4394            stop();
4395        }
4396
4397        //cacheContext();
4398
}
4399
4400    /**
4401     * Processes TLDs.
4402     *
4403     * @throws LifecycleException If an error occurs
4404     */

4405     protected void processTlds() throws LifecycleException {
4406       TldConfig tldConfig = new TldConfig();
4407       tldConfig.setContext(this);
4408
4409       // (1) check if the attribute has been defined
4410
// on the context element.
4411
tldConfig.setTldValidation(tldValidation);
4412       tldConfig.setTldNamespaceAware(tldNamespaceAware);
4413
4414       // (2) if the attribute wasn't defined on the context
4415
// try the host.
4416
if (!tldValidation) {
4417         tldConfig.setTldValidation
4418           (((StandardHost) getParent()).getXmlValidation());
4419       }
4420
4421       if (!tldNamespaceAware) {
4422         tldConfig.setTldNamespaceAware
4423           (((StandardHost) getParent()).getXmlNamespaceAware());
4424       }
4425                    
4426       try {
4427         tldConfig.execute();
4428       } catch (Exception JavaDoc ex) {
4429         log.error("Error reading tld listeners "
4430                    + ex.toString(), ex);
4431       }
4432     }
4433    
4434    private void cacheContext() {
4435        try {
4436            File JavaDoc workDir=new File JavaDoc( getWorkPath() );
4437            
4438            File JavaDoc ctxSer=new File JavaDoc( workDir, "_tomcat_context.ser");
4439            FileOutputStream JavaDoc fos=new FileOutputStream JavaDoc( ctxSer );
4440            ObjectOutputStream JavaDoc oos=new ObjectOutputStream JavaDoc( fos );
4441            oos.writeObject(this);
4442            oos.close();
4443            fos.close();
4444        } catch( Throwable JavaDoc t ) {
4445            if(log.isInfoEnabled())
4446                log.info("Error saving context.ser ", t);
4447        }
4448    }
4449
4450    
4451    /**
4452     * Stop this Context component.
4453     *
4454     * @exception LifecycleException if a shutdown error occurs
4455     */

4456    public synchronized void stop() throws LifecycleException {
4457
4458        // Validate and update our current component state
4459
if (!started) {
4460            if(log.isInfoEnabled())
4461                log.info(sm.getString("containerBase.notStarted", logName()));
4462            return;
4463        }
4464
4465        // Notify our interested LifecycleListeners
4466
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
4467        
4468        // Send j2ee.state.stopping notification
4469
if (this.getObjectName() != null) {
4470            Notification JavaDoc notification =
4471                new Notification JavaDoc("j2ee.state.stopping", this.getObjectName(),
4472                                sequenceNumber++);
4473            broadcaster.sendNotification(notification);
4474        }
4475        
4476        // Mark this application as unavailable while we shut down
4477
setAvailable(false);
4478
4479        // Binding thread
4480
ClassLoader JavaDoc oldCCL = bindThread();
4481
4482        try {
4483
4484            // Stop our child containers, if any
4485
Container[] children = findChildren();
4486            for (int i = 0; i < children.length; i++) {
4487                if (children[i] instanceof Lifecycle)
4488                    ((Lifecycle) children[i]).stop();
4489            }
4490
4491            // Stop our filters
4492
filterStop();
4493
4494            // Stop ContainerBackgroundProcessor thread
4495
super.threadStop();
4496
4497            if ((manager != null) && (manager instanceof Lifecycle)) {
4498                ((Lifecycle) manager).stop();
4499            }
4500
4501            // Stop our application listeners
4502
listenerStop();
4503
4504            // Finalize our character set mapper
4505
setCharsetMapper(null);
4506
4507            // Normal container shutdown processing
4508
if (log.isDebugEnabled())
4509                log.debug("Processing standard container shutdown");
4510            // Notify our interested LifecycleListeners
4511
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
4512            started = false;
4513
4514            // Stop the Valves in our pipeline (including the basic), if any
4515
if (pipeline instanceof Lifecycle) {
4516                ((Lifecycle) pipeline).stop();
4517            }
4518
4519            // Clear all application-originated servlet context attributes
4520
if (context != null)
4521                context.clearAttributes();
4522
4523            // Stop resources
4524
resourcesStop();
4525
4526            if ((realm != null) && (realm instanceof Lifecycle)) {
4527                ((Lifecycle) realm).stop();
4528            }
4529            if ((cluster != null) && (cluster instanceof Lifecycle)) {
4530                ((Lifecycle) cluster).stop();
4531            }
4532            if ((logger != null) && (logger instanceof Lifecycle)) {
4533                ((Lifecycle) logger).stop();
4534            }
4535            if ((loader != null) && (loader instanceof Lifecycle)) {
4536                ((Lifecycle) loader).stop();
4537            }
4538
4539        } finally {
4540
4541            // Unbinding thread
4542
unbindThread(oldCCL);
4543
4544        }
4545
4546        // Send j2ee.state.stopped notification
4547
if (this.getObjectName() != null) {
4548            Notification JavaDoc notification =
4549                new Notification JavaDoc("j2ee.state.stopped", this.getObjectName(),
4550                                sequenceNumber++);
4551            broadcaster.sendNotification(notification);
4552        }
4553        
4554        // Reset application context
4555
context = null;
4556
4557        // This object will no longer be visible or used.
4558
try {
4559            resetContext();
4560        } catch( Exception JavaDoc ex ) {
4561            log.error( "Error reseting context " + this + " " + ex, ex );
4562        }
4563        
4564        // Notify our interested LifecycleListeners
4565
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
4566
4567        if (log.isDebugEnabled())
4568            log.debug("Stopping complete");
4569
4570    }
4571
4572    /** Destroy needs to clean up the context completely.
4573     *
4574     * The problem is that undoing all the config in start() and restoring
4575     * a 'fresh' state is impossible. After stop()/destroy()/init()/start()
4576     * we should have the same state as if a fresh start was done - i.e
4577     * read modified web.xml, etc. This can only be done by completely
4578     * removing the context object and remapping a new one, or by cleaning
4579     * up everything.
4580     *
4581     * XXX Should this be done in stop() ?
4582     *
4583     */

4584    public void destroy() throws Exception JavaDoc {
4585        if( oname != null ) {
4586            // Send j2ee.object.deleted notification
4587
Notification JavaDoc notification =
4588                new Notification JavaDoc("j2ee.object.deleted", this.getObjectName(),
4589                                sequenceNumber++);
4590            broadcaster.sendNotification(notification);
4591        }
4592        super.destroy();
4593
4594        // Notify our interested LifecycleListeners
4595
lifecycle.fireLifecycleEvent(DESTROY_EVENT, null);
4596
4597        instanceListeners = new String JavaDoc[0];
4598
4599    }
4600    
4601    private void resetContext() throws Exception JavaDoc, MBeanRegistrationException JavaDoc {
4602        // Restore the original state ( pre reading web.xml in start )
4603
// If you extend this - override this method and make sure to clean up
4604
children=new HashMap JavaDoc();
4605        startupTime = 0;
4606        startTime = 0;
4607        tldScanTime = 0;
4608
4609        // Bugzilla 32867
4610
distributable = false;
4611
4612        applicationListeners = new String JavaDoc[0];
4613        applicationEventListenersObjects = new Object JavaDoc[0];
4614        applicationLifecycleListenersObjects = new Object JavaDoc[0];
4615        
4616        if(log.isDebugEnabled())
4617            log.debug("resetContext " + oname);
4618    }
4619
4620    /**
4621     * Return a String representation of this component.
4622     */

4623    public String JavaDoc toString() {
4624
4625        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
4626        if (getParent() != null) {
4627            sb.append(getParent().toString());
4628            sb.append(".");
4629        }
4630        sb.append("StandardContext[");
4631        sb.append(getName());
4632        sb.append("]");
4633        return (sb.toString());
4634
4635    }
4636
4637
4638    // ------------------------------------------------------ Protected Methods
4639

4640
4641    /**
4642     * Adjust the URL pattern to begin with a leading slash, if appropriate
4643     * (i.e. we are running a servlet 2.2 application). Otherwise, return
4644     * the specified URL pattern unchanged.
4645     *
4646     * @param urlPattern The URL pattern to be adjusted (if needed)
4647     * and returned
4648     */

4649    protected String JavaDoc adjustURLPattern(String JavaDoc urlPattern) {
4650
4651        if (urlPattern == null)
4652            return (urlPattern);
4653        if (urlPattern.startsWith("/") || urlPattern.startsWith("*."))
4654            return (urlPattern);
4655        if (!isServlet22())
4656            return (urlPattern);
4657        if(log.isDebugEnabled())
4658            log.debug(sm.getString("standardContext.urlPattern.patternWarning",
4659                         urlPattern));
4660        return ("/" + urlPattern);
4661
4662    }
4663
4664
4665    /**
4666     * Are we processing a version 2.2 deployment descriptor?
4667     */

4668    protected boolean isServlet22() {
4669
4670        if (this.publicId == null)
4671            return (false);
4672        if (this.publicId.equals
4673            (org.apache.catalina.startup.Constants.WebDtdPublicId_22))
4674            return (true);
4675        else
4676            return (false);
4677
4678    }
4679
4680
4681    /**
4682     * Return a File object representing the base directory for the
4683     * entire servlet container (i.e. the Engine container if present).
4684     */

4685    protected File JavaDoc engineBase() {
4686        String JavaDoc base=System.getProperty("catalina.base");
4687        if( base == null ) {
4688            StandardEngine eng=(StandardEngine)this.getParent().getParent();
4689            base=eng.getBaseDir();
4690        }
4691        return (new File JavaDoc(base));
4692    }
4693
4694
4695    // -------------------------------------------------------- Private Methods
4696

4697
4698    /**
4699     * Bind current thread, both for CL purposes and for JNDI ENC support
4700     * during : startup, shutdown and realoading of the context.
4701     *
4702     * @return the previous context class loader
4703     */

4704    private ClassLoader JavaDoc bindThread() {
4705
4706        ClassLoader JavaDoc oldContextClassLoader =
4707            Thread.currentThread().getContextClassLoader();
4708
4709        if (getResources() == null)
4710            return oldContextClassLoader;
4711
4712        if (getLoader().getClassLoader() != null) {
4713            Thread.currentThread().setContextClassLoader
4714                (getLoader().getClassLoader());
4715        }
4716
4717        DirContextURLStreamHandler.bind(getResources());
4718
4719        if (isUseNaming()) {
4720            try {
4721                ContextBindings.bindThread(this, this);
4722            } catch (NamingException JavaDoc e) {
4723                // Silent catch, as this is a normal case during the early
4724
// startup stages
4725
}
4726        }
4727
4728        return oldContextClassLoader;
4729
4730    }
4731
4732
4733    /**
4734     * Unbind thread.
4735     */

4736    private void unbindThread(ClassLoader JavaDoc oldContextClassLoader) {
4737
4738        Thread.currentThread().setContextClassLoader(oldContextClassLoader);
4739
4740        oldContextClassLoader = null;
4741
4742        if (isUseNaming()) {
4743            ContextBindings.unbindThread(this, this);
4744        }
4745
4746        DirContextURLStreamHandler.unbind();
4747
4748    }
4749
4750
4751
4752    /**
4753     * Get base path.
4754     */

4755    protected String JavaDoc getBasePath() {
4756        String JavaDoc docBase = null;
4757        Container container = this;
4758        while (container != null) {
4759            if (container instanceof Host)
4760                break;
4761            container = container.getParent();
4762        }
4763        File JavaDoc file = new File JavaDoc(getDocBase());
4764        if (!file.isAbsolute()) {
4765            if (container == null) {
4766                docBase = (new File JavaDoc(engineBase(), getDocBase())).getPath();
4767            } else {
4768                // Use the "appBase" property of this container
4769
String JavaDoc appBase = ((Host) container).getAppBase();
4770                file = new File JavaDoc(appBase);
4771                if (!file.isAbsolute())
4772                    file = new File JavaDoc(engineBase(), appBase);
4773                docBase = (new File JavaDoc(file, getDocBase())).getPath();
4774            }
4775        } else {
4776            docBase = file.getPath();
4777        }
4778        return docBase;
4779    }
4780
4781
4782    /**
4783     * Get app base.
4784     */

4785    protected String JavaDoc getAppBase() {
4786        String JavaDoc appBase = null;
4787        Container container = this;
4788        while (container != null) {
4789            if (container instanceof Host)
4790                break;
4791            container = container.getParent();
4792        }
4793        if (container != null) {
4794            appBase = ((Host) container).getAppBase();
4795        }
4796        return appBase;
4797    }
4798
4799
4800    /**
4801     * Get config base.
4802     */

4803    public File JavaDoc getConfigBase() {
4804        File JavaDoc configBase =
4805            new File JavaDoc(System.getProperty("catalina.base"), "conf");
4806        if (!configBase.exists()) {
4807            return null;
4808        }
4809        Container container = this;
4810        Container host = null;
4811        Container engine = null;
4812        while (container != null) {
4813            if (container instanceof Host)
4814                host = container;
4815            if (container instanceof Engine)
4816                engine = container;
4817            container = container.getParent();
4818        }
4819        if (engine != null) {
4820            configBase = new File JavaDoc(configBase, engine.getName());
4821        }
4822        if (host != null) {
4823            configBase = new File JavaDoc(configBase, host.getName());
4824        }
4825        if (saveConfig) {
4826            configBase.mkdirs();
4827        }
4828        return configBase;
4829    }
4830
4831
4832    /**
4833     * Given a context path, get the config file name.
4834     */

4835    protected String JavaDoc getDefaultConfigFile() {
4836        String JavaDoc basename = null;
4837        String JavaDoc path = getPath();
4838        if (path.equals("")) {
4839            basename = "ROOT";
4840        } else {
4841            basename = path.substring(1).replace('/', '#');
4842        }
4843        return (basename + ".xml");
4844    }
4845
4846
4847    /**
4848     * Copy a file.
4849     */

4850    private boolean copy(File JavaDoc src, File JavaDoc dest) {
4851        FileInputStream JavaDoc is = null;
4852        FileOutputStream JavaDoc os = null;
4853        try {
4854            is = new FileInputStream JavaDoc(src);
4855            os = new FileOutputStream JavaDoc(dest);
4856            byte[] buf = new byte[4096];
4857            while (true) {
4858                int len = is.read(buf);
4859                if (len < 0)
4860                    break;
4861                os.write(buf, 0, len);
4862            }
4863            is.close();
4864            os.close();
4865        } catch (IOException JavaDoc e) {
4866            return false;
4867        } finally {
4868            try {
4869                if (is != null) {
4870                    is.close();
4871                }
4872            } catch (Exception JavaDoc e) {
4873                // Ignore
4874
}
4875            try {
4876                if (os != null) {
4877                    os.close();
4878                }
4879            } catch (Exception JavaDoc e) {
4880                // Ignore
4881
}
4882        }
4883        return true;
4884    }
4885
4886
4887    /**
4888     * Get naming context full name.
4889     */

4890    private String JavaDoc getNamingContextName() {
4891    if (namingContextName == null) {
4892        Container parent = getParent();
4893        if (parent == null) {
4894        namingContextName = getName();
4895        } else {
4896        Stack JavaDoc stk = new Stack JavaDoc();
4897        StringBuffer JavaDoc buff = new StringBuffer JavaDoc();
4898        while (parent != null) {
4899            stk.push(parent.getName());
4900            parent = parent.getParent();
4901        }
4902        while (!stk.empty()) {
4903            buff.append("/" + stk.pop());
4904        }
4905        buff.append(getName());
4906        namingContextName = buff.toString();
4907        }
4908    }
4909    return namingContextName;
4910    }
4911
4912    
4913    /**
4914     * Naming context listener accessor.
4915     */

4916    public NamingContextListener getNamingContextListener() {
4917        return namingContextListener;
4918    }
4919    
4920
4921    /**
4922     * Naming context listener setter.
4923     */

4924    public void setNamingContextListener(NamingContextListener namingContextListener) {
4925        this.namingContextListener = namingContextListener;
4926    }
4927    
4928
4929    /**
4930     * Return the request processing paused flag for this Context.
4931     */

4932    public boolean getPaused() {
4933
4934        return (this.paused);
4935
4936    }
4937
4938
4939    /**
4940     * Post a copy of our web application resources as a servlet context
4941     * attribute.
4942     */

4943    private void postResources() {
4944
4945        getServletContext().setAttribute
4946            (Globals.RESOURCES_ATTR, getResources());
4947
4948    }
4949
4950
4951    /**
4952     * Post a copy of our current list of welcome files as a servlet context
4953     * attribute, so that the default servlet can find them.
4954     */

4955    private void postWelcomeFiles() {
4956
4957        getServletContext().setAttribute("org.apache.catalina.WELCOME_FILES",
4958                                         welcomeFiles);
4959
4960    }
4961
4962    public String JavaDoc getHostname() {
4963        Container parentHost = getParent();
4964        if (parentHost != null) {
4965            hostName = parentHost.getName();
4966        }
4967        if ((hostName == null) || (hostName.length() < 1))
4968            hostName = "_";
4969        return hostName;
4970    }
4971
4972    /**
4973     * Set the appropriate context attribute for our work directory.
4974     */

4975    private void postWorkDirectory() {
4976
4977        // Acquire (or calculate) the work directory path
4978
String JavaDoc workDir = getWorkDir();
4979        if (workDir == null) {
4980
4981            // Retrieve our parent (normally a host) name
4982
String JavaDoc hostName = null;
4983            String JavaDoc engineName = null;
4984            String JavaDoc hostWorkDir = null;
4985            Container parentHost = getParent();
4986            if (parentHost != null) {
4987                hostName = parentHost.getName();
4988                if (parentHost instanceof StandardHost) {
4989                    hostWorkDir = ((StandardHost)parentHost).getWorkDir();
4990                }
4991                Container parentEngine = parentHost.getParent();
4992                if (parentEngine != null) {
4993                   engineName = parentEngine.getName();
4994                }
4995            }
4996            if ((hostName == null) || (hostName.length() < 1))
4997                hostName = "_";
4998            if ((engineName == null) || (engineName.length() < 1))
4999                engineName = "_";
5000
5001            String JavaDoc temp = getPath();
5002            if (temp.startsWith("/"))
5003                temp = temp.substring(1);
5004            temp = temp.replace('/', '_');
5005            temp = temp.replace('\\', '_');
5006            if (temp.length() < 1)
5007                temp = "_";
5008            if (hostWorkDir != null ) {
5009                workDir = hostWorkDir + File.separator + temp;
5010            } else {
5011                workDir = "work" + File.separator + engineName +
5012                    File.separator + hostName + File.separator + temp;
5013            }
5014            setWorkDir(workDir);
5015        }
5016
5017        // Create this directory if necessary
5018
File JavaDoc dir = new File JavaDoc(workDir);
5019        if (!dir.isAbsolute()) {
5020            File JavaDoc catalinaHome = engineBase();
5021            String JavaDoc catalinaHomePath = null;
5022            try {
5023                catalinaHomePath = catalinaHome.getCanonicalPath();
5024                dir = new File JavaDoc(catalinaHomePath, workDir);
5025            } catch (IOException JavaDoc e) {
5026            }
5027        }
5028        dir.mkdirs();
5029
5030        // Set the appropriate servlet context attribute
5031
getServletContext().setAttribute(Globals.WORK_DIR_ATTR, dir);
5032        if (getServletContext() instanceof ApplicationContext)
5033            ((ApplicationContext) getServletContext()).setAttributeReadOnly
5034                (Globals.WORK_DIR_ATTR);
5035
5036    }
5037
5038
5039    /**
5040     * Set the request processing paused flag for this Context.
5041     *
5042     * @param paused The new request processing paused flag
5043     */

5044    private void setPaused(boolean paused) {
5045
5046        this.paused = paused;
5047
5048    }
5049
5050
5051    /**
5052     * Validate the syntax of a proposed <code>&lt;url-pattern&gt;</code>
5053     * for conformance with specification requirements.
5054     *
5055     * @param urlPattern URL pattern to be validated
5056     */

5057    private boolean validateURLPattern(String JavaDoc urlPattern) {
5058
5059        if (urlPattern == null)
5060            return (false);
5061        if (urlPattern.indexOf('\n') >= 0 || urlPattern.indexOf('\r') >= 0) {
5062            getLogger().warn(sm.getString("standardContext.crlfinurl",urlPattern));
5063        }
5064        if (urlPattern.startsWith("*.")) {
5065            if (urlPattern.indexOf('/') < 0)
5066                return (true);
5067            else
5068                return (false);
5069        }
5070        if ( (urlPattern.startsWith("/")) &&
5071                (urlPattern.indexOf("*.") < 0))
5072            return (true);
5073        else
5074            return (false);
5075
5076    }
5077
5078
5079    // ------------------------------------------------------------- Operations
5080

5081
5082    /**
5083     * JSR77 deploymentDescriptor attribute
5084     *
5085     * @return string deployment descriptor
5086     */

5087    public String JavaDoc getDeploymentDescriptor() {
5088    
5089        InputStream JavaDoc stream = null;
5090        ServletContext JavaDoc servletContext = getServletContext();
5091        if (servletContext != null) {
5092            stream = servletContext.getResourceAsStream(
5093                org.apache.catalina.startup.Constants.ApplicationWebXml);
5094        }
5095        if (stream == null) {
5096            return "";
5097        }
5098        BufferedReader JavaDoc br = new BufferedReader JavaDoc(
5099                                new InputStreamReader JavaDoc(stream));
5100        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
5101        String JavaDoc strRead = "";
5102        try {
5103            while (strRead != null) {
5104                sb.append(strRead);
5105                strRead = br.readLine();
5106            }
5107        } catch (IOException JavaDoc e) {
5108            return "";
5109        }
5110
5111        return sb.toString();
5112    
5113    }
5114    
5115    
5116    /**
5117     * JSR77 servlets attribute
5118     *
5119     * @return list of all servlets ( we know about )
5120     */

5121    public String JavaDoc[] getServlets() {
5122        
5123        String JavaDoc[] result = null;
5124
5125        Container[] children = findChildren();
5126        if (children != null) {
5127            result = new String JavaDoc[children.length];
5128            for( int i=0; i< children.length; i++ ) {
5129                result[i] = ((StandardWrapper)children[i]).getObjectName();
5130            }
5131        }
5132
5133        return result;
5134    }
5135    
5136
5137    public ObjectName JavaDoc createObjectName(String JavaDoc hostDomain, ObjectName JavaDoc parentName)
5138            throws MalformedObjectNameException JavaDoc
5139    {
5140        String JavaDoc onameStr;
5141        StandardHost hst=(StandardHost)getParent();
5142        
5143        String JavaDoc pathName=getName();
5144        String JavaDoc hostName=getParent().getName();
5145        String JavaDoc name= "//" + ((hostName==null)? "DEFAULT" : hostName) +
5146                (("".equals(pathName))?"/":pathName );
5147
5148        String JavaDoc suffix=",J2EEApplication=" +
5149                getJ2EEApplication() + ",J2EEServer=" +
5150                getJ2EEServer();
5151
5152        onameStr="j2eeType=WebModule,name=" + name + suffix;
5153        if( log.isDebugEnabled())
5154            log.debug("Registering " + onameStr + " for " + oname);
5155        
5156        // default case - no domain explictely set.
5157
if( getDomain() == null ) domain=hst.getDomain();
5158
5159        ObjectName JavaDoc oname=new ObjectName JavaDoc(getDomain() + ":" + onameStr);
5160        return oname;
5161    }
5162    
5163    private void preRegisterJMX() {
5164        try {
5165            StandardHost host = (StandardHost) getParent();
5166            if ((oname == null)
5167                || (oname.getKeyProperty("j2eeType") == null)) {
5168                oname = createObjectName(host.getDomain(), host.getJmxName());
5169                controller = oname;
5170            }
5171        } catch(Exception JavaDoc ex) {
5172            if(log.isInfoEnabled())
5173                log.info("Error registering ctx with jmx " + this + " " +
5174                     oname + " " + ex.toString(), ex );
5175        }
5176    }
5177
5178    private void registerJMX() {
5179        try {
5180            if (log.isDebugEnabled()) {
5181                log.debug("Checking for " + oname );
5182            }
5183            if(! Registry.getRegistry(null, null)
5184                .getMBeanServer().isRegistered(oname)) {
5185                controller = oname;
5186                Registry.getRegistry(null, null)
5187                    .registerComponent(this, oname, null);
5188                
5189                // Send j2ee.object.created notification
5190
if (this.getObjectName() != null) {
5191                    Notification JavaDoc notification = new Notification JavaDoc(
5192                                                        "j2ee.object.created",
5193                                                        this.getObjectName(),
5194                                                        sequenceNumber++);
5195                    broadcaster.sendNotification(notification);
5196                }
5197            }
5198            Container children[] = findChildren();
5199            for (int i=0; children!=null && i<children.length; i++) {
5200                ((StandardWrapper)children[i]).registerJMX( this );
5201            }
5202        } catch (Exception JavaDoc ex) {
5203            if(log.isInfoEnabled())
5204                log.info("Error registering wrapper with jmx " + this + " " +
5205                    oname + " " + ex.toString(), ex );
5206        }
5207    }
5208
5209    /** There are 2 cases:
5210     * 1.The context is created and registered by internal APIS
5211     * 2. The context is created by JMX, and it'll self-register.
5212     *
5213     * @param server The server
5214     * @param name The object name
5215     * @return ObjectName The name of the object
5216     * @throws Exception If an error occurs
5217     */

5218    public ObjectName JavaDoc preRegister(MBeanServer JavaDoc server,
5219                                  ObjectName JavaDoc name)
5220            throws Exception JavaDoc
5221    {
5222        if( oname != null ) {
5223            //log.info( "Already registered " + oname + " " + name);
5224
// Temporary - /admin uses the old names
5225
return name;
5226        }
5227        ObjectName JavaDoc result=super.preRegister(server,name);
5228        return name;
5229    }
5230
5231    public void preDeregister() throws Exception JavaDoc {
5232        if( started ) {
5233            try {
5234                stop();
5235            } catch( Exception JavaDoc ex ) {
5236                log.error( "error stopping ", ex);
5237            }
5238        }
5239    }
5240
5241    public void init() throws Exception JavaDoc {
5242
5243        if( this.getParent() == null ) {
5244            ObjectName JavaDoc parentName=getParentName();
5245            
5246            if( ! mserver.isRegistered(parentName)) {
5247                if(log.isDebugEnabled())
5248                    log.debug("No host, creating one " + parentName);
5249                StandardHost host=new StandardHost();
5250                host.setName(hostName);
5251                host.setAutoDeploy(false);
5252                Registry.getRegistry(null, null)
5253                    .registerComponent(host, parentName, null);
5254                // We could do it the hard way...
5255
//mserver.invoke(parentName, "init", new Object[] {}, new String[] {} );
5256
// or same thing easier:
5257
host.init();
5258            }
5259            
5260            // Add the main configuration listener
5261
LifecycleListener config = null;
5262            try {
5263                String JavaDoc configClassName = null;
5264                try {
5265                    configClassName = String.valueOf(mserver.getAttribute(parentName, "configClass"));
5266                } catch (AttributeNotFoundException JavaDoc e) {
5267                    // Ignore, it's normal a host may not have this optional attribute
5268
}
5269                if (configClassName != null) {
5270                    Class JavaDoc clazz = Class.forName(configClassName);
5271                    config = (LifecycleListener) clazz.newInstance();
5272                } else {
5273                    config = new ContextConfig();
5274                }
5275            } catch (Exception JavaDoc e) {
5276                log.warn("Error creating ContextConfig for " + parentName, e);
5277                throw e;
5278            }
5279            this.addLifecycleListener(config);
5280
5281            if (log.isDebugEnabled()) {
5282                log.debug("AddChild " + parentName + " " + this);
5283            }
5284            try {
5285                mserver.invoke(parentName, "addChild", new Object JavaDoc[] { this },
5286                        new String JavaDoc[] {"org.apache.catalina.Container"});
5287            } catch (Exception JavaDoc e) {
5288                destroy();
5289                throw e;
5290            }
5291            // It's possible that addChild may have started us
5292
if( initialized ) {
5293                return;
5294            }
5295        }
5296        super.init();
5297        
5298        // Notify our interested LifecycleListeners
5299
lifecycle.fireLifecycleEvent(INIT_EVENT, null);
5300
5301        // Send j2ee.state.starting notification
5302
if (this.getObjectName() != null) {
5303            Notification JavaDoc notification = new Notification JavaDoc("j2ee.state.starting",
5304                                                        this.getObjectName(),
5305                                                        sequenceNumber++);
5306            broadcaster.sendNotification(notification);
5307        }
5308        
5309    }
5310
5311    public ObjectName JavaDoc getParentName() throws MalformedObjectNameException JavaDoc {
5312        // "Life" update
5313
String JavaDoc path=oname.getKeyProperty("name");
5314        if( path == null ) {
5315            log.error( "No name attribute " +name );
5316            return null;
5317        }
5318        if( ! path.startsWith( "//")) {
5319            log.error("Invalid name " + name);
5320        }
5321        path=path.substring(2);
5322        int delim=path.indexOf( "/" );
5323        hostName="localhost"; // Should be default...
5324
if( delim > 0 ) {
5325            hostName=path.substring(0, delim);
5326            path = path.substring(delim);
5327            if (path.equals("/")) {
5328                this.setName("");
5329            } else {
5330                this.setName(path);
5331            }
5332        } else {
5333            if(log.isDebugEnabled())
5334                log.debug("Setting path " + path );
5335            this.setName( path );
5336        }
5337        // XXX The service and domain should be the same.
5338
String JavaDoc parentDomain=getEngineName();
5339        if( parentDomain == null ) parentDomain=domain;
5340        ObjectName JavaDoc parentName=new ObjectName JavaDoc( parentDomain + ":" +
5341                "type=Host,host=" + hostName);
5342        return parentName;
5343    }
5344    
5345    public void create() throws Exception JavaDoc{
5346        init();
5347    }
5348
5349    /* Remove a JMX notficationListener
5350     * @see javax.management.NotificationEmitter#removeNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
5351     */

5352    public void removeNotificationListener(NotificationListener JavaDoc listener,
5353            NotificationFilter JavaDoc filter, Object JavaDoc object) throws ListenerNotFoundException JavaDoc {
5354        broadcaster.removeNotificationListener(listener,filter,object);
5355        
5356    }
5357    
5358    private MBeanNotificationInfo JavaDoc[] notificationInfo;
5359    
5360    /* Get JMX Broadcaster Info
5361     * @TODO use StringManager for international support!
5362     * @TODO This two events we not send j2ee.state.failed and j2ee.attribute.changed!
5363     * @see javax.management.NotificationBroadcaster#getNotificationInfo()
5364     */

5365    public MBeanNotificationInfo JavaDoc[] getNotificationInfo() {
5366        // FIXME: i18n
5367
if(notificationInfo == null) {
5368            notificationInfo = new MBeanNotificationInfo JavaDoc[]{
5369                    new MBeanNotificationInfo JavaDoc(new String JavaDoc[] {
5370                    "j2ee.object.created"},
5371                    Notification JavaDoc.class.getName(),
5372                    "web application is created"
5373                    ),
5374                    new MBeanNotificationInfo JavaDoc(new String JavaDoc[] {
5375                    "j2ee.state.starting"},
5376                    Notification JavaDoc.class.getName(),
5377                    "change web application is starting"
5378                    ),
5379                    new MBeanNotificationInfo JavaDoc(new String JavaDoc[] {
5380                    "j2ee.state.running"},
5381                    Notification JavaDoc.class.getName(),
5382                    "web application is running"
5383                    ),
5384                    new MBeanNotificationInfo JavaDoc(new String JavaDoc[] {
5385                    "j2ee.state.stopped"},
5386                    Notification JavaDoc.class.getName(),
5387                    "web application start to stopped"
5388                    ),
5389                    new MBeanNotificationInfo JavaDoc(new String JavaDoc[] {
5390                    "j2ee.object.stopped"},
5391                    Notification JavaDoc.class.getName(),
5392                    "web application is stopped"
5393                    ),
5394                    new MBeanNotificationInfo JavaDoc(new String JavaDoc[] {
5395                    "j2ee.object.deleted"},
5396                    Notification JavaDoc.class.getName(),
5397                    "web application is deleted"
5398                    )
5399            };
5400            
5401        }
5402        
5403        return notificationInfo;
5404    }
5405    
5406    
5407    /* Add a JMX-NotificationListener
5408     * @see javax.management.NotificationBroadcaster#addNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
5409     */

5410    public void addNotificationListener(NotificationListener JavaDoc listener,
5411            NotificationFilter JavaDoc filter, Object JavaDoc object) throws IllegalArgumentException JavaDoc {
5412        broadcaster.addNotificationListener(listener,filter,object);
5413        
5414    }
5415    
5416    
5417    /**
5418     * Remove a JMX-NotificationListener
5419     * @see javax.management.NotificationBroadcaster#removeNotificationListener(javax.management.NotificationListener)
5420     */

5421    public void removeNotificationListener(NotificationListener JavaDoc listener)
5422    throws ListenerNotFoundException JavaDoc {
5423        broadcaster.removeNotificationListener(listener);
5424        
5425    }
5426    
5427    
5428    // ------------------------------------------------------------- Attributes
5429

5430
5431    /**
5432     * Return the naming resources associated with this web application.
5433     */

5434    public javax.naming.directory.DirContext JavaDoc getStaticResources() {
5435
5436        return getResources();
5437
5438    }
5439
5440
5441    /**
5442     * Return the naming resources associated with this web application.
5443     * FIXME: Fooling introspection ...
5444     */

5445    public javax.naming.directory.DirContext JavaDoc findStaticResources() {
5446
5447        return getResources();
5448
5449    }
5450
5451
5452    /**
5453     * Return the naming resources associated with this web application.
5454     */

5455    public String JavaDoc[] getWelcomeFiles() {
5456
5457        return findWelcomeFiles();
5458
5459    }
5460
5461     /**
5462     * Set the validation feature of the XML parser used when
5463     * parsing xml instances.
5464     * @param webXmlValidation true to enable xml instance validation
5465     */

5466    public void setXmlValidation(boolean webXmlValidation){
5467        
5468        this.webXmlValidation = webXmlValidation;
5469
5470    }
5471
5472    /**
5473     * Get the server.xml <context> attribute's xmlValidation.
5474     * @return true if validation is enabled.
5475     *
5476     */

5477    public boolean getXmlValidation(){
5478        return webXmlValidation;
5479    }
5480
5481
5482    /**
5483     * Get the server.xml <context> attribute's xmlNamespaceAware.
5484     * @return true if namespace awarenes is enabled.
5485     */

5486    public boolean getXmlNamespaceAware(){
5487        return webXmlNamespaceAware;
5488    }
5489
5490
5491    /**
5492     * Set the namespace aware feature of the XML parser used when
5493     * parsing xml instances.
5494     * @param webXmlNamespaceAware true to enable namespace awareness
5495     */

5496    public void setXmlNamespaceAware(boolean webXmlNamespaceAware){
5497        this.webXmlNamespaceAware= webXmlNamespaceAware;
5498    }
5499
5500
5501    /**
5502     * Set the validation feature of the XML parser used when
5503     * parsing tlds files.
5504     * @param tldValidation true to enable xml instance validation
5505     */

5506    public void setTldValidation(boolean tldValidation){
5507        
5508        this.tldValidation = tldValidation;
5509
5510    }
5511
5512    /**
5513     * Get the server.xml <context> attribute's webXmlValidation.
5514     * @return true if validation is enabled.
5515     *
5516     */

5517    public boolean getTldValidation(){
5518        return tldValidation;
5519    }
5520
5521    /**
5522     * Sets the process TLDs attribute.
5523     *
5524     * @param newProcessTlds The new value
5525     */

5526    public void setProcessTlds(boolean newProcessTlds) {
5527    processTlds = newProcessTlds;
5528    }
5529
5530    /**
5531     * Returns the processTlds attribute value.
5532     */

5533    public boolean getProcessTlds() {
5534    return processTlds;
5535    }
5536
5537    /**
5538     * Get the server.xml <host> attribute's xmlNamespaceAware.
5539     * @return true if namespace awarenes is enabled.
5540     */

5541    public boolean getTldNamespaceAware(){
5542        return tldNamespaceAware;
5543    }
5544
5545
5546    /**
5547     * Set the namespace aware feature of the XML parser used when
5548     * parsing xml instances.
5549     * @param tldNamespaceAware true to enable namespace awareness
5550     */

5551    public void setTldNamespaceAware(boolean tldNamespaceAware){
5552        this.tldNamespaceAware= tldNamespaceAware;
5553    }
5554
5555
5556    /**
5557     * Support for "stateManageable" JSR77
5558     */

5559    public boolean isStateManageable() {
5560        return true;
5561    }
5562    
5563    public void startRecursive() throws LifecycleException {
5564        // nothing to start recursive, the servlets will be started by load-on-startup
5565
start();
5566    }
5567    
5568    public int getState() {
5569        if( started ) {
5570            return 1; // RUNNING
5571
}
5572        if( initialized ) {
5573            return 0; // starting ?
5574
}
5575        if( ! available ) {
5576            return 4; //FAILED
5577
}
5578        // 2 - STOPPING
5579
return 3; // STOPPED
5580
}
5581    
5582    /**
5583     * The J2EE Server ObjectName this module is deployed on.
5584     */

5585    private String JavaDoc server = null;
5586    
5587    /**
5588     * The Java virtual machines on which this module is running.
5589     */

5590    private String JavaDoc[] javaVMs = null;
5591    
5592    public String JavaDoc getServer() {
5593        return server;
5594    }
5595        
5596    public String JavaDoc setServer(String JavaDoc server) {
5597        return this.server=server;
5598    }
5599        
5600    public String JavaDoc[] getJavaVMs() {
5601        return javaVMs;
5602    }
5603        
5604    public String JavaDoc[] setJavaVMs(String JavaDoc[] javaVMs) {
5605        return this.javaVMs = javaVMs;
5606    }
5607    
5608    /**
5609     * Gets the time this context was started.
5610     *
5611     * @return Time (in milliseconds since January 1, 1970, 00:00:00) when this
5612     * context was started
5613     */

5614    public long getStartTime() {
5615        return startTime;
5616    }
5617    
5618    public boolean isEventProvider() {
5619        return false;
5620    }
5621    
5622    public boolean isStatisticsProvider() {
5623        return false;
5624    }
5625    
5626}
5627
Popular Tags