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;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.io.ObjectOutputStream;
29 import java.io.Serializable;
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 import java.util.Hashtable;
33 import java.util.Iterator;
34 import java.util.Stack;
35 import java.util.TreeMap;
36
37 import javax.management.AttributeNotFoundException;
38 import javax.management.ListenerNotFoundException;
39 import javax.management.MBeanNotificationInfo;
40 import javax.management.MBeanRegistrationException;
41 import javax.management.MBeanServer;
42 import javax.management.MalformedObjectNameException;
43 import javax.management.Notification;
44 import javax.management.NotificationBroadcasterSupport;
45 import javax.management.NotificationEmitter;
46 import javax.management.NotificationFilter;
47 import javax.management.NotificationListener;
48 import javax.management.ObjectName;
49 import javax.naming.NamingException;
50 import javax.naming.directory.DirContext;
51 import javax.servlet.FilterConfig;
52 import javax.servlet.ServletContext;
53 import javax.servlet.ServletContextAttributeListener;
54 import javax.servlet.ServletContextEvent;
55 import javax.servlet.ServletContextListener;
56 import javax.servlet.ServletException;
57 import javax.servlet.ServletRequestAttributeListener;
58 import javax.servlet.ServletRequestListener;
59 import javax.servlet.http.HttpSessionAttributeListener;
60 import javax.servlet.http.HttpSessionListener;
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.juli.logging.Log;
96 import org.apache.juli.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: 615899 $ $Date: 2008-01-28 15:47:11 +0100 (lun., 28 janv. 2008) $
113 */
114
115 public class StandardContext
116 extends ContainerBase
117 implements Context, Serializable, NotificationEmitter
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();
133
134 }
135
136
137 // ----------------------------------------------------- Class Variables
138
139
140 /**
141 * The descriptive information string for this implementation.
142 */
143 private static final String 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 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 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 applicationListeners[] = new String[0];
205
206
207 /**
208 * The set of instantiated application event listener objects</code>.
209 */
210 private transient Object applicationEventListenersObjects[] =
211 new Object[0];
212
213
214 /**
215 * The set of instantiated application lifecycle listener objects</code>.
216 */
217 private transient Object applicationLifecycleListenersObjects[] =
218 new Object[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 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 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 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 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 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 displayName = null;
311
312
313 /**
314 * Override the default context xml location.
315 */
316 private String defaultContextXml;
317
318
319 /**
320 * Override the default web xml location.
321 */
322 private String 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 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 exceptionPages = new HashMap();
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 filterConfigs = new HashMap();
349
350
351 /**
352 * The set of filter definitions for this application, keyed by
353 * filter name.
354 */
355 private HashMap filterDefs = new HashMap();
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 instanceListeners[] = new String[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 messageDestinations = new HashMap();
407
408
409 /**
410 * The MIME mappings for this web application, keyed by extension.
411 */
412 private HashMap mimeMappings = new HashMap();
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 parameters = new HashMap();
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 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 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 roleMappings = new HashMap();
487
488
489 /**
490 * The security roles for this application, keyed by role name.
491 */
492 private String securityRoles[] = new String[0];
493
494
495 /**
496 * The servlet mappings for this web application, keyed by
497 * matching pattern.
498 */
499 private HashMap servletMappings = new HashMap();
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 statusPages = new HashMap();
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 taglibs = new HashMap();
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 watchedResources[] = new String[0];
542
543
544 /**
545 * The welcome files for this application.
546 */
547 private String welcomeFiles[] = new String[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 wrapperLifecycles[] = new String[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 wrapperListeners[] = new String[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 workDir = null;
569
570
571 /**
572 * Java class name of the Wrapper class implementation we use.
573 */
574 private String wrapperClassName = StandardWrapper.class.getName();
575 private Class 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 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 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 engineName = null;
641 private String j2EEApplication="none";
642 private String 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 getEncodedPath() {
693 return encodedPath;
694 }
695
696
697 public void setName( String 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(oldDelegate),
805 new Boolean(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[] 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 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[] 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 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(oldAntiJARLocking),
920 new Boolean(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(oldAntiResourceLocking),
936 new Boolean(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(oldAvailable),
962 new Boolean(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 clazz = Class.forName(charsetMapperClass);
976 this.charsetMapper =
977 (CharsetMapper) clazz.newInstance();
978 } catch (Throwable 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 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 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(oldConfigured),
1048 new Boolean(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(oldCookies),
1074 new Boolean(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(oldCrossContext),
1100 new Boolean(this.crossContext));
1101
1102 }
1103
1104 public String 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 defaultContextXml) {
1116 this.defaultContextXml = defaultContextXml;
1117 }
1118
1119 public String 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 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 getDisplayName() {
1159
1160 return (this.displayName);
1161
1162 }
1163
1164
1165 /**
1166 * Return the alternate Deployment Descriptor name.
1167 */
1168 public String getAltDDName(){
1169 return altDDName;
1170 }
1171
1172
1173 /**
1174 * Set an alternate Deployment Descriptor name.
1175 */
1176 public void setAltDDName(String 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 getCompilerClasspath(){
1188 return compilerClasspath;
1189 }
1190
1191
1192 /**
1193 * Set the compiler classpath.
1194 */
1195 public void setCompilerClasspath(String 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 displayName) {
1206
1207 String 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(oldDistributable),
1233 new Boolean(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 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 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><description>/<version></code>.
1283 */
1284 public String getInfo() {
1285
1286 return (info);
1287
1288 }
1289
1290 public String getEngineName() {
1291 if( engineName != null ) return engineName;
1292 return domain;
1293 }
1294
1295 public void setEngineName(String engineName) {
1296 this.engineName = engineName;
1297 }
1298
1299 public String getJ2EEApplication() {
1300 return j2EEApplication;
1301 }
1302
1303 public void setJ2EEApplication(String j2EEApplication) {
1304 this.j2EEApplication = j2EEApplication;
1305 }
1306
1307 public String getJ2EEServer() {
1308 return j2EEServer;
1309 }
1310
1311 public void setJ2EEServer(String 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
1370 (sm.getString("standardContext.loginConfig.required"));
1371 String 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
1380 (sm.getString("standardContext.loginConfig.loginPage",
1381 loginPage));
1382 }
1383 }
1384 String 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
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 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 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 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 publicId) {
1488
1489 if (log.isDebugEnabled())
1490 log.debug("Setting deployment descriptor public ID to '" +
1491 publicId + "'");
1492
1493 String 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 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 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 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(oldPrivileged),
1581 new Boolean(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(oldReloadable),
1597 new Boolean(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(oldOverride),
1613 new Boolean(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(oldReplaceWelcomeFiles),
1639 new Boolean(this.replaceWelcomeFiles));
1640
1641 }
1642
1643
1644 /**
1645 * Return the servlet context for which this Context is a facade.
1646 */
1647 public ServletContext 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(oldSessionTimeout),
1687 new Integer(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(oldSwallowOutput),
1715 new Boolean(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(oldUnloadDelay),
1744 new Long(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 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 wrapperClassName) {
1789
1790 this.wrapperClassName = wrapperClassName;
1791
1792 try {
1793 wrapperClass = Class.forName(wrapperClassName);
1794 if (!StandardWrapper.class.isAssignableFrom(wrapperClass)) {
1795 throw new IllegalArgumentException(
1796 sm.getString("standardContext.invalidWrapperClass",
1797 wrapperClassName));
1798 }
1799 } catch (ClassNotFoundException cnfe) {
1800 throw new IllegalArgumentException(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 resources) {
1812
1813 if (started) {
1814 throw new IllegalStateException
1815 (sm.getString("standardContext.resources.started"));
1816 }
1817
1818 DirContext 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 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 mapper) {
1862
1863 String 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 getWorkPath() {
1878 if (getWorkDir() == null) {
1879 return null;
1880 }
1881 File workDir = new File(getWorkDir());
1882 if (!workDir.isAbsolute()) {
1883 File catalinaHome = engineBase();
1884 String catalinaHomePath = null;
1885 try {
1886 catalinaHomePath = catalinaHome.getCanonicalPath();
1887 workDir = new File(catalinaHomePath,
1888 getWorkDir());
1889 } catch (IOException e) {
1890 log.warn("Exception obtaining work path for " + getPath());
1891 }
1892 }
1893 return workDir.getAbsolutePath();
1894 }
1895
1896 /**
1897 * Return the work directory for this Context.
1898 */
1899 public String getWorkDir() {
1900
1901 return (this.workDir);
1902
1903 }
1904
1905
1906 /**
1907 * Set the work directory for this Context.
1908 *
1909 * @param workDir The new work directory
1910 */
1911 public void setWorkDir(String workDir) {
1912
1913 this.workDir = workDir;
1914
1915 if (started) {
1916 postWorkDirectory();
1917 }
1918 }
1919
1920
1921 /**
1922 * Save config ?
1923 */
1924 public boolean isSaveConfig() {
1925 return saveConfig;
1926 }
1927
1928
1929 /**
1930 * Set save config flag.
1931 */
1932 public void setSaveConfig(boolean saveConfig) {
1933 this.saveConfig = saveConfig;
1934 }
1935
1936
1937 // -------------------------------------------------------- Context Methods
1938
1939
1940 /**
1941 * Add a new Listener class name to the set of Listeners
1942 * configured for this application.
1943 *
1944 * @param listener Java class name of a listener class
1945 */
1946 public void addApplicationListener(String listener) {
1947
1948 synchronized (applicationListeners) {
1949 String results[] =new String[applicationListeners.length + 1];
1950 for (int i = 0; i < applicationListeners.length; i++) {
1951 if (listener.equals(applicationListeners[i])) {
1952 log.info(sm.getString(
1953 "standardContext.duplicateListener",listener));
1954 return;
1955 }
1956 results[i] = applicationListeners[i];
1957 }
1958 results[applicationListeners.length] = listener;
1959 applicationListeners = results;
1960 }
1961 fireContainerEvent("addApplicationListener", listener);
1962
1963 // FIXME - add instance if already started?
1964
1965 }
1966
1967
1968 /**
1969 * Add a new application parameter for this application.
1970 *
1971 * @param parameter The new application parameter
1972 */
1973 public void addApplicationParameter(ApplicationParameter parameter) {
1974
1975 synchronized (applicationParameters) {
1976 String newName = parameter.getName();
1977 for (int i = 0; i < applicationParameters.length; i++) {
1978 if (newName.equals(applicationParameters[i].getName()) &&
1979 !applicationParameters[i].getOverride())
1980 return;
1981 }
1982 ApplicationParameter results[] =
1983 new ApplicationParameter[applicationParameters.length + 1];
1984 System.arraycopy(applicationParameters, 0, results, 0,
1985 applicationParameters.length);
1986 results[applicationParameters.length] = parameter;
1987 applicationParameters = results;
1988 }
1989 fireContainerEvent("addApplicationParameter", parameter);
1990
1991 }
1992
1993
1994 /**
1995 * Add a child Container, only if the proposed child is an implementation
1996 * of Wrapper.
1997 *
1998 * @param child Child container to be added
1999 *
2000 * @exception IllegalArgumentException if the proposed container is
2001 * not an implementation of Wrapper
2002 */
2003 public void addChild(Container child) {
2004
2005 // Global JspServlet
2006 Wrapper oldJspServlet = null;
2007
2008 if (!(child instanceof Wrapper)) {
2009 throw new IllegalArgumentException
2010 (sm.getString("standardContext.notWrapper"));
2011 }
2012
2013 Wrapper wrapper = (Wrapper) child;
2014 boolean isJspServlet = "jsp".equals(child.getName());
2015
2016 // Allow webapp to override JspServlet inherited from global web.xml.
2017 if (isJspServlet) {
2018 oldJspServlet = (Wrapper) findChild("jsp");
2019 if (oldJspServlet != null) {
2020 removeChild(oldJspServlet);
2021 }
2022 }
2023
2024 String jspFile = wrapper.getJspFile();
2025 if ((jspFile != null) && !jspFile.startsWith("/")) {
2026 if (isServlet22()) {
2027 if(log.isDebugEnabled())
2028 log.debug(sm.getString("standardContext.wrapper.warning",
2029 jspFile));
2030 wrapper.setJspFile("/" + jspFile);
2031 } else {
2032 throw new IllegalArgumentException
2033 (sm.getString("standardContext.wrapper.error", jspFile));
2034 }
2035 }
2036
2037 super.addChild(child);
2038
2039 if (isJspServlet && oldJspServlet != null) {
2040 /*
2041 * The webapp-specific JspServlet inherits all the mappings
2042 * specified in the global web.xml, and may add additional ones.
2043 */
2044 String[] jspMappings = oldJspServlet.findMappings();
2045 for (int i=0; jspMappings!=null && i<jspMappings.length; i++) {
2046 addServletMapping(jspMappings[i], child.getName());
2047 }
2048 }
2049 }
2050
2051
2052 /**
2053 * Add a security constraint to the set for this web application.
2054 */
2055 public void addConstraint(SecurityConstraint constraint) {
2056
2057 // Validate the proposed constraint
2058 SecurityCollection collections[] = constraint.findCollections();
2059 for (int i = 0; i < collections.length; i++) {
2060 String patterns[] = collections[i].findPatterns();
2061 for (int j = 0; j < patterns.length; j++) {
2062 patterns[j] = adjustURLPattern(patterns[j]);
2063 if (!validateURLPattern(patterns[j]))
2064 throw new IllegalArgumentException
2065 (sm.getString
2066 ("standardContext.securityConstraint.pattern",
2067 patterns[j]));
2068 }
2069 }
2070
2071 // Add this constraint to the set for our web application
2072 synchronized (constraints) {
2073 SecurityConstraint results[] =
2074 new SecurityConstraint[constraints.length + 1];
2075 for (int i = 0; i < constraints.length; i++)
2076 results[i] = constraints[i];
2077 results[constraints.length] = constraint;
2078 constraints = results;
2079 }
2080
2081 }
2082
2083
2084
2085 /**
2086 * Add an error page for the specified error or Java exception.
2087 *
2088 * @param errorPage The error page definition to be added
2089 */
2090 public void addErrorPage(ErrorPage errorPage) {
2091 // Validate the input parameters
2092 if (errorPage == null)
2093 throw new IllegalArgumentException
2094 (sm.getString("standardContext.errorPage.required"));
2095 String location = errorPage.getLocation();
2096 if ((location != null) && !location.startsWith("/")) {
2097 if (isServlet22()) {
2098 if(log.isDebugEnabled())
2099 log.debug(sm.getString("standardContext.errorPage.warning",
2100 location));
2101 errorPage.setLocation("/" + location);
2102 } else {
2103 throw new IllegalArgumentException
2104 (sm.getString("standardContext.errorPage.error",
2105 location));
2106 }
2107 }
2108
2109 // Add the specified error page to our internal collections
2110 String exceptionType = errorPage.getExceptionType();
2111 if (exceptionType != null) {
2112 synchronized (exceptionPages) {
2113 exceptionPages.put(exceptionType, errorPage);
2114 }
2115 } else {
2116 synchronized (statusPages) {
2117 if (errorPage.getErrorCode() == 200) {
2118 this.okErrorPage = errorPage;
2119 }
2120 statusPages.put(new Integer(errorPage.getErrorCode()),
2121 errorPage);
2122 }
2123 }
2124 fireContainerEvent("addErrorPage", errorPage);
2125
2126 }
2127
2128
2129 /**
2130 * Add a filter definition to this Context.
2131 *
2132 * @param filterDef The filter definition to be added
2133 */
2134 public void addFilterDef(FilterDef filterDef) {
2135
2136 synchronized (filterDefs) {
2137 filterDefs.put(filterDef.getFilterName(), filterDef);
2138 }
2139 fireContainerEvent("addFilterDef", filterDef);
2140
2141 }
2142
2143
2144 /**
2145 * Add a filter mapping to this Context.
2146 *
2147 * @param filterMap The filter mapping to be added
2148 *
2149 * @exception IllegalArgumentException if the specified filter name
2150 * does not match an existing filter definition, or the filter mapping
2151 * is malformed
2152 */
2153 public void addFilterMap(FilterMap filterMap) {
2154
2155 // Validate the proposed filter mapping
2156 String filterName = filterMap.getFilterName();
2157 String[] servletNames = filterMap.getServletNames();
2158 String[] urlPatterns = filterMap.getURLPatterns();
2159 if (findFilterDef(filterName) == null)
2160 throw new IllegalArgumentException
2161 (sm.getString("standardContext.filterMap.name", filterName));
2162 // <= Servlet API 2.4
2163 // if ((servletNames.length == 0) && (urlPatterns.length == 0))
2164 // Servlet API 2.5 (FIX 43338)
2165 // SRV 6.2.5 says supporting for '*' as the servlet-name in filter-mapping.
2166 if (!filterMap.getMatchAllServletNames() &&
2167 !filterMap.getMatchAllUrlPatterns() &&
2168 (servletNames.length == 0) && (urlPatterns.length == 0))
2169 throw new IllegalArgumentException
2170 (sm.getString("standardContext.filterMap.either"));
2171 // FIXME: Older spec revisions may still check this
2172 /*
2173 if ((servletNames.length != 0) && (urlPatterns.length != 0))
2174 throw new IllegalArgumentException
2175 (sm.getString("standardContext.filterMap.either"));
2176 */
2177 // Because filter-pattern is new in 2.3, no need to adjust
2178 // for 2.2 backwards compatibility
2179 for (int i = 0; i < urlPatterns.length; i++) {
2180 if (!validateURLPattern(urlPatterns[i])) {
2181 throw new IllegalArgumentException
2182 (sm.getString("standardContext.filterMap.pattern",
2183 urlPatterns[i]));
2184 }
2185 }
2186
2187 // Add this filter mapping to our registered set
2188 synchronized (filterMaps) {
2189 FilterMap results[] =new FilterMap[filterMaps.length + 1];
2190 System.arraycopy(filterMaps, 0, results, 0, filterMaps.length);
2191 results[filterMaps.length] = filterMap;
2192 filterMaps = results;
2193 }
2194 fireContainerEvent("addFilterMap", filterMap);
2195
2196 }
2197
2198
2199 /**
2200 * Add the classname of an InstanceListener to be added to each
2201 * Wrapper appended to this Context.
2202 *
2203 * @param listener Java class name of an InstanceListener class
2204 */
2205 public void addInstanceListener(String listener) {
2206
2207 synchronized (instanceListeners) {
2208 String results[] =new String[instanceListeners.length + 1];
2209 for (int i = 0; i < instanceListeners.length; i++)
2210 results[i] = instanceListeners[i];
2211 results[instanceListeners.length] = listener;
2212 instanceListeners = results;
2213 }
2214 fireContainerEvent("addInstanceListener", listener);
2215
2216 }
2217
2218 /**
2219 * Add the given URL pattern as a jsp-property-group. This maps
2220 * resources that match the given pattern so they will be passed
2221 * to the JSP container. Though there are other elements in the
2222 * property group, we only care about the URL pattern here. The
2223 * JSP container will parse the rest.
2224 *
2225 * @param pattern URL pattern to be mapped
2226 */
2227 public void addJspMapping(String pattern) {
2228 String servletName = findServletMapping("*.jsp");
2229 if (servletName == null) {
2230 servletName = "jsp";
2231 }
2232
2233 if( findChild(servletName) != null) {
2234 addServletMapping(pattern, servletName, true);
2235 } else {
2236 if(log.isDebugEnabled())
2237 log.debug("Skiping " + pattern + " , no servlet " + servletName);
2238 }
2239 }
2240
2241
2242 /**
2243 * Add a Locale Encoding Mapping (see Sec 5.4 of Servlet spec 2.4)
2244 *
2245 * @param locale locale to map an encoding for
2246 * @param encoding encoding to be used for a give locale
2247 */
2248 public void addLocaleEncodingMappingParameter(String locale, String encoding){
2249 getCharsetMapper().addCharsetMappingFromDeploymentDescriptor(locale, encoding);
2250 }
2251
2252
2253 /**
2254 * Add a message destination for this web application.
2255 *
2256 * @param md New message destination
2257 */
2258 public void addMessageDestination(MessageDestination md) {
2259
2260 synchronized (messageDestinations) {
2261 messageDestinations.put(md.getName(), md);
2262 }
2263 fireContainerEvent("addMessageDestination", md.getName());
2264
2265 }
2266
2267
2268 /**
2269 * Add a message destination reference for this web application.
2270 *
2271 * @param mdr New message destination reference
2272 */
2273 public void addMessageDestinationRef
2274 (MessageDestinationRef mdr) {
2275
2276 namingResources.addMessageDestinationRef(mdr);
2277 fireContainerEvent("addMessageDestinationRef", mdr.getName());
2278
2279 }
2280
2281
2282 /**
2283 * Add a new MIME mapping, replacing any existing mapping for
2284 * the specified extension.
2285 *
2286 * @param extension Filename extension being mapped
2287 * @param mimeType Corresponding MIME type
2288 */
2289 public void addMimeMapping(String extension, String mimeType) {
2290
2291 synchronized (mimeMappings) {
2292 mimeMappings.put(extension, mimeType);
2293 }
2294 fireContainerEvent("addMimeMapping", extension);
2295
2296 }
2297
2298
2299 /**
2300 * Add a new context initialization parameter.
2301 *
2302 * @param name Name of the new parameter
2303 * @param value Value of the new parameter
2304 *
2305 * @exception IllegalArgumentException if the name or value is missing,
2306 * or if this context initialization parameter has already been
2307 * registered
2308 */
2309 public void addParameter(String name, String value) {
2310 // Validate the proposed context initialization parameter
2311 if ((name == null) || (value == null))
2312 throw new IllegalArgumentException
2313 (sm.getString("standardContext.parameter.required"));
2314 if (parameters.get(name) != null)
2315 throw new IllegalArgumentException
2316 (sm.getString("standardContext.parameter.duplicate", name));
2317
2318 // Add this parameter to our defined set
2319 synchronized (parameters) {
2320 parameters.put(name, value);
2321 }
2322 fireContainerEvent("addParameter", name);
2323
2324 }
2325
2326
2327 /**
2328 * Add a security role reference for this web application.
2329 *
2330 * @param role Security role used in the application
2331 * @param link Actual security role to check for
2332 */
2333 public void addRoleMapping(String role, String link) {
2334
2335 synchronized (roleMappings) {
2336 roleMappings.put(role, link);
2337 }
2338 fireContainerEvent("addRoleMapping", role);
2339
2340 }
2341
2342
2343 /**
2344 * Add a new security role for this web application.
2345 *
2346 * @param role New security role
2347 */
2348 public void addSecurityRole(String role) {
2349
2350 synchronized (securityRoles) {
2351 String results[] =new String[securityRoles.length + 1];
2352 for (int i = 0; i < securityRoles.length; i++)
2353 results[i] = securityRoles[i];
2354 results[securityRoles.length] = role;
2355 securityRoles = results;
2356 }
2357 fireContainerEvent("addSecurityRole", role);
2358
2359 }
2360
2361
2362 /**
2363 * Add a new servlet mapping, replacing any existing mapping for
2364 * the specified pattern.
2365 *
2366 * @param pattern URL pattern to be mapped
2367 * @param name Name of the corresponding servlet to execute
2368 *
2369 * @exception IllegalArgumentException if the specified servlet name
2370 * is not known to this Context
2371 */
2372 public void addServletMapping(String pattern, String name) {
2373 addServletMapping(pattern, name, false);
2374 }
2375
2376
2377 /**
2378 * Add a new servlet mapping, replacing any existing mapping for
2379 * the specified pattern.
2380 *
2381 * @param pattern URL pattern to be mapped
2382 * @param name Name of the corresponding servlet to execute
2383 * @param jspWildCard true if name identifies the JspServlet
2384 * and pattern contains a wildcard; false otherwise
2385 *
2386 * @exception IllegalArgumentException if the specified servlet name
2387 * is not known to this Context
2388 */
2389 public void addServletMapping(String pattern, String name,
2390 boolean jspWildCard) {
2391 // Validate the proposed mapping
2392 if (findChild(name) == null)
2393 throw new IllegalArgumentException
2394 (sm.getString("standardContext.servletMap.name", name));
2395 pattern = adjustURLPattern(RequestUtil.URLDecode(pattern));
2396 if (!validateURLPattern(pattern))
2397 throw new IllegalArgumentException
2398 (sm.getString("standardContext.servletMap.pattern", pattern));
2399
2400 // Add this mapping to our registered set
2401 synchronized (servletMappings) {
2402 String name2 = (String) servletMappings.get(pattern);
2403 if (name2 != null) {
2404 // Don't allow more than one servlet on the same pattern
2405 Wrapper wrapper = (Wrapper) findChild(name2);
2406 wrapper.removeMapping(pattern);
2407 mapper.removeWrapper(pattern);
2408 }
2409 servletMappings.put(pattern, name);
2410 }
2411 Wrapper wrapper = (Wrapper) findChild(name);
2412 wrapper.addMapping(pattern);
2413
2414 // Update context mapper
2415 mapper.addWrapper(pattern, wrapper, jspWildCard);
2416
2417 fireContainerEvent("addServletMapping", pattern);
2418
2419 }
2420
2421
2422 /**
2423 * Add a JSP tag library for the specified URI.
2424 *
2425 * @param uri URI, relative to the web.xml file, of this tag library
2426 * @param location Location of the tag library descriptor
2427 */
2428 public void addTaglib(String uri, String location) {
2429
2430 synchronized (taglibs) {
2431 taglibs.put(uri, location);
2432 }
2433 fireContainerEvent("addTaglib", uri);
2434
2435 }
2436
2437
2438 /**
2439 * Add a new watched resource to the set recognized by this Context.
2440 *
2441 * @param name New watched resource file name
2442 */
2443 public void addWatchedResource(String name) {
2444
2445 synchronized (watchedResources) {
2446 String results[] = new String[watchedResources.length + 1];
2447 for (int i = 0; i < watchedResources.length; i++)
2448 results[i] = watchedResources[i];
2449 results[watchedResources.length] = name;
2450 watchedResources = results;
2451 }
2452 fireContainerEvent("addWatchedResource", name);
2453
2454 }
2455
2456
2457 /**
2458 * Add a new welcome file to the set recognized by this Context.
2459 *
2460 * @param name New welcome file name
2461 */
2462 public void addWelcomeFile(String name) {
2463
2464 synchronized (welcomeFiles) {
2465 // Welcome files from the application deployment descriptor
2466 // completely replace those from the default conf/web.xml file
2467 if (replaceWelcomeFiles) {
2468 welcomeFiles = new String[0];
2469 setReplaceWelcomeFiles(false);
2470 }
2471 String results[] =new String[welcomeFiles.length + 1];
2472 for (int i = 0; i < welcomeFiles.length; i++)
2473 results[i] = welcomeFiles[i];
2474 results[welcomeFiles.length] = name;
2475 welcomeFiles = results;
2476 }
2477 postWelcomeFiles();
2478 fireContainerEvent("addWelcomeFile", name);
2479
2480 }
2481
2482
2483 /**
2484 * Add the classname of a LifecycleListener to be added to each
2485 * Wrapper appended to this Context.
2486 *
2487 * @param listener Java class name of a LifecycleListener class
2488 */
2489 public void addWrapperLifecycle(String listener) {
2490
2491 synchronized (wrapperLifecycles) {
2492 String results[] =new String[wrapperLifecycles.length + 1];
2493 for (int i = 0; i < wrapperLifecycles.length; i++)
2494 results[i] = wrapperLifecycles[i];
2495 results[wrapperLifecycles.length] = listener;
2496 wrapperLifecycles = results;
2497 }
2498 fireContainerEvent("addWrapperLifecycle", listener);
2499
2500 }
2501
2502
2503 /**
2504 * Add the classname of a ContainerListener to be added to each
2505 * Wrapper appended to this Context.
2506 *
2507 * @param listener Java class name of a ContainerListener class
2508 */
2509 public void addWrapperListener(String listener) {
2510
2511 synchronized (wrapperListeners) {
2512 String results[] =new String[wrapperListeners.length + 1];
2513 for (int i = 0; i < wrapperListeners.length; i++)
2514 results[i] = wrapperListeners[i];
2515 results[wrapperListeners.length] = listener;
2516 wrapperListeners = results;
2517 }
2518 fireContainerEvent("addWrapperListener", listener);
2519
2520 }
2521
2522
2523 /**
2524 * Factory method to create and return a new Wrapper instance, of
2525 * the Java implementation class appropriate for this Context
2526 * implementation. The constructor of the instantiated Wrapper
2527 * will have been called, but no properties will have been set.
2528 */
2529 public Wrapper createWrapper() {
2530
2531 Wrapper wrapper = null;
2532 if (wrapperClass != null) {
2533 try {
2534 wrapper = (Wrapper) wrapperClass.newInstance();
2535 } catch (Throwable t) {
2536 log.error("createWrapper", t);
2537 return (null);
2538 }
2539 } else {
2540 wrapper = new StandardWrapper();
2541 }
2542
2543 synchronized (instanceListeners) {
2544 for (int i = 0; i < instanceListeners.length; i++) {
2545 try {
2546 Class clazz = Class.forName(instanceListeners[i]);
2547 InstanceListener listener =
2548 (InstanceListener) clazz.newInstance();
2549 wrapper.addInstanceListener(listener);
2550 } catch (Throwable t) {
2551 log.error("createWrapper", t);
2552 return (null);
2553 }
2554 }
2555 }
2556
2557 synchronized (wrapperLifecycles) {
2558 for (int i = 0; i < wrapperLifecycles.length; i++) {
2559 try {
2560 Class clazz = Class.forName(wrapperLifecycles[i]);
2561 LifecycleListener listener =
2562 (LifecycleListener) clazz.newInstance();
2563 if (wrapper instanceof Lifecycle)
2564 ((Lifecycle) wrapper).addLifecycleListener(listener);
2565 } catch (Throwable t) {
2566 log.error("createWrapper", t);
2567 return (null);
2568 }
2569 }
2570 }
2571
2572 synchronized (wrapperListeners) {
2573 for (int i = 0; i < wrapperListeners.length; i++) {
2574 try {
2575 Class clazz = Class.forName(wrapperListeners[i]);
2576 ContainerListener listener =
2577 (ContainerListener) clazz.newInstance();
2578 wrapper.addContainerListener(listener);
2579 } catch (Throwable t) {
2580 log.error("createWrapper", t);
2581 return (null);
2582 }
2583 }
2584 }
2585
2586 return (wrapper);
2587
2588 }
2589
2590
2591 /**
2592 * Return the set of application listener class names configured
2593 * for this application.
2594 */
2595 public String[] findApplicationListeners() {
2596
2597 return (applicationListeners);
2598
2599 }
2600
2601
2602 /**
2603 * Return the set of application parameters for this application.
2604 */
2605 public ApplicationParameter[] findApplicationParameters() {
2606
2607 return (applicationParameters);
2608
2609 }
2610
2611
2612 /**
2613 * Return the security constraints for this web application.
2614 * If there are none, a zero-length array is returned.
2615 */
2616 public SecurityConstraint[] findConstraints() {
2617
2618 return (constraints);
2619
2620 }
2621
2622
2623 /**
2624 * Return the error page entry for the specified HTTP error code,
2625 * if any; otherwise return <code>null</code>.
2626 *
2627 * @param errorCode Error code to look up
2628 */
2629 public ErrorPage findErrorPage(int errorCode) {
2630 if (errorCode == 200) {
2631 return (okErrorPage);
2632 } else {
2633 return ((ErrorPage) statusPages.get(new Integer(errorCode)));
2634 }
2635
2636 }
2637
2638
2639 /**
2640 * Return the error page entry for the specified Java exception type,
2641 * if any; otherwise return <code>null</code>.
2642 *
2643 * @param exceptionType Exception type to look up
2644 */
2645 public ErrorPage findErrorPage(String exceptionType) {
2646
2647 synchronized (exceptionPages) {
2648 return ((ErrorPage) exceptionPages.get(exceptionType));
2649 }
2650
2651 }
2652
2653
2654 /**
2655 * Return the set of defined error pages for all specified error codes
2656 * and exception types.
2657 */
2658 public ErrorPage[] findErrorPages() {
2659
2660 synchronized(exceptionPages) {
2661 synchronized(statusPages) {
2662 ErrorPage results1[] = new ErrorPage[exceptionPages.size()];
2663 results1 =
2664 (ErrorPage[]) exceptionPages.values().toArray(results1);
2665 ErrorPage results2[] = new ErrorPage[statusPages.size()];
2666 results2 =
2667 (ErrorPage[]) statusPages.values().toArray(results2);
2668 ErrorPage results[] =
2669 new ErrorPage[results1.length + results2.length];
2670 for (int i = 0; i < results1.length; i++)
2671 results[i] = results1[i];
2672 for (int i = results1.length; i < results.length; i++)
2673 results[i] = results2[i - results1.length];
2674 return (results);
2675 }
2676 }
2677
2678 }
2679
2680
2681 /**
2682 * Return the filter definition for the specified filter name, if any;
2683 * otherwise return <code>null</code>.
2684 *
2685 * @param filterName Filter name to look up
2686 */
2687 public FilterDef findFilterDef(String filterName) {
2688
2689 synchronized (filterDefs) {
2690 return ((FilterDef) filterDefs.get(filterName));
2691 }
2692
2693 }
2694
2695
2696 /**
2697 * Return the set of defined filters for this Context.
2698 */
2699 public FilterDef[] findFilterDefs() {
2700
2701 synchronized (filterDefs) {
2702 FilterDef results[] = new FilterDef[filterDefs.size()];
2703 return ((FilterDef[]) filterDefs.values().toArray(results));
2704 }
2705
2706 }
2707
2708
2709 /**
2710 * Return the set of filter mappings for this Context.
2711 */
2712 public FilterMap[] findFilterMaps() {
2713
2714 return (filterMaps);
2715
2716 }
2717
2718
2719 /**
2720 * Return the set of InstanceListener classes that will be added to
2721 * newly created Wrappers automatically.
2722 */
2723 public String[] findInstanceListeners() {
2724
2725 return (instanceListeners);
2726
2727 }
2728
2729
2730 /**
2731 * FIXME: Fooling introspection ...
2732 */
2733 public Context findMappingObject() {
2734 return (Context) getMappingObject();
2735 }
2736
2737
2738 /**
2739 * Return the message destination with the specified name, if any;
2740 * otherwise, return <code>null</code>.
2741 *
2742 * @param name Name of the desired message destination
2743 */
2744 public MessageDestination findMessageDestination(String name) {
2745
2746 synchronized (messageDestinations) {
2747 return ((MessageDestination) messageDestinations.get(name));
2748 }
2749
2750 }
2751
2752
2753 /**
2754 * Return the set of defined message destinations for this web
2755 * application. If none have been defined, a zero-length array
2756 * is returned.
2757 */
2758 public MessageDestination[] findMessageDestinations() {
2759
2760 synchronized (messageDestinations) {
2761 MessageDestination results[] =
2762 new MessageDestination[messageDestinations.size()];
2763 return ((MessageDestination[])
2764 messageDestinations.values().toArray(results));
2765 }
2766
2767 }
2768
2769
2770 /**
2771 * Return the message destination ref with the specified name, if any;
2772 * otherwise, return <code>null</code>.
2773 *
2774 * @param name Name of the desired message destination ref
2775 */
2776 public MessageDestinationRef
2777 findMessageDestinationRef(String name) {
2778
2779 return namingResources.findMessageDestinationRef(name);
2780
2781 }
2782
2783
2784 /**
2785 * Return the set of defined message destination refs for this web
2786 * application. If none have been defined, a zero-length array
2787 * is returned.
2788 */
2789 public MessageDestinationRef[]
2790 findMessageDestinationRefs() {
2791
2792 return namingResources.findMessageDestinationRefs();
2793
2794 }
2795
2796
2797 /**
2798 * Return the MIME type to which the specified extension is mapped,
2799 * if any; otherwise return <code>null</code>.
2800 *
2801 * @param extension Extension to map to a MIME type
2802 */
2803 public String findMimeMapping(String extension) {
2804
2805 return ((String) mimeMappings.get(extension));
2806
2807 }
2808
2809
2810 /**
2811 * Return the extensions for which MIME mappings are defined. If there
2812 * are none, a zero-length array is returned.
2813 */
2814 public String[] findMimeMappings() {
2815
2816 synchronized (mimeMappings) {
2817 String results[] = new String[mimeMappings.size()];
2818 return
2819 ((String[]) mimeMappings.keySet().toArray(results));
2820 }
2821
2822 }
2823
2824
2825 /**
2826 * Return the value for the specified context initialization
2827 * parameter name, if any; otherwise return <code>null</code>.
2828 *
2829 * @param name Name of the parameter to return
2830 */
2831 public String findParameter(String name) {
2832
2833 synchronized (parameters) {
2834 return ((String) parameters.get(name));
2835 }
2836
2837 }
2838
2839
2840 /**
2841 * Return the names of all defined context initialization par