1 // ========================================================================
2 // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
3 // ------------------------------------------------------------------------
4 // All rights reserved. This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v1.0
6 // and Apache License v2.0 which accompanies this distribution.
7 // The Eclipse Public License is available at
8 // http://www.eclipse.org/legal/epl-v10.html
9 // The Apache License v2.0 is available at
10 // http://www.opensource.org/licenses/apache2.0.php
11 // You may elect to redistribute this code under either of these licenses.
12 // ========================================================================
13
14 package org.eclipse.jetty.webapp;
15
16 import java.io.File;
17 import java.io.IOException;
18 import java.net.MalformedURLException;
19 import java.security.PermissionCollection;
20 import java.util.EventListener;
21 import java.util.HashMap;
22 import java.util.Map;
23
24 import javax.servlet.http.HttpSessionActivationListener;
25 import javax.servlet.http.HttpSessionAttributeListener;
26 import javax.servlet.http.HttpSessionBindingListener;
27 import javax.servlet.http.HttpSessionListener;
28
29 import org.eclipse.jetty.security.SecurityHandler;
30 import org.eclipse.jetty.server.Connector;
31 import org.eclipse.jetty.server.HandlerContainer;
32 import org.eclipse.jetty.server.handler.ContextHandler;
33 import org.eclipse.jetty.server.handler.ErrorHandler;
34 import org.eclipse.jetty.server.session.SessionHandler;
35 import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
36 import org.eclipse.jetty.servlet.ServletContextHandler;
37 import org.eclipse.jetty.servlet.ServletHandler;
38 import org.eclipse.jetty.util.LazyList;
39 import org.eclipse.jetty.util.Loader;
40 import org.eclipse.jetty.util.StringUtil;
41 import org.eclipse.jetty.util.URIUtil;
42 import org.eclipse.jetty.util.log.Log;
43 import org.eclipse.jetty.util.resource.Resource;
44
45 /* ------------------------------------------------------------ */
46 /** Web Application Context Handler.
47 * The WebAppContext handler is an extension of ContextHandler that
48 * coordinates the construction and configuration of nested handlers:
49 * {@link org.eclipse.jetty.security.ConstraintSecurityHandler}, {@link org.eclipse.jetty.server.session.SessionHandler}
50 * and {@link org.eclipse.jetty.servlet.ServletHandler}.
51 * The handlers are configured by pluggable configuration classes, with
52 * the default being {@link org.eclipse.jetty.server.server.webapp.WebXmlConfiguration} and
53 * {@link org.eclipse.jetty.server.server.webapp.JettyWebXmlConfiguration}.
54 *
55 * @org.apache.xbean.XBean description="Creates a servlet web application at a given context from a resource base"
56 *
57 *
58 *
59 */
60 public class WebAppContext extends ServletContextHandler
61 {
62 public static final String TEMPDIR = "javax.servlet.context.tempdir";
63 public final static String WEB_DEFAULTS_XML="org/eclipse/jetty/webapp/webdefault.xml";
64 public final static String ERROR_PAGE="org.eclipse.jetty.server.error_page";
65
66 private static String[] __dftConfigurationClasses =
67 {
68 "org.eclipse.jetty.webapp.WebInfConfiguration",
69 "org.eclipse.jetty.webapp.WebXmlConfiguration",
70 "org.eclipse.jetty.webapp.MetaInfConfiguration",
71 "org.eclipse.jetty.webapp.FragmentConfiguration",
72 "org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
73 "org.eclipse.jetty.webapp.TagLibConfiguration"
74 } ;
75 private String[] _configurationClasses=__dftConfigurationClasses;
76 private Configuration[] _configurations;
77 private String _defaultsDescriptor=WEB_DEFAULTS_XML;
78 private String _descriptor=null;
79 private String _overrideDescriptor=null;
80 private boolean _distributable=false;
81 private boolean _extractWAR=true;
82 private boolean _copyDir=false;
83 private boolean _logUrlOnStart =false;
84 private boolean _parentLoaderPriority= Boolean.getBoolean("org.eclipse.jetty.server.webapp.parentLoaderPriority");
85 private PermissionCollection _permissions;
86 private String[] _systemClasses = {
87 "java.", // Java SE classes (per servlet spec v2.5 / SRV.9.7.2)
88 "javax.", // Java SE classes (per servlet spec v2.5 / SRV.9.7.2)
89 "org.xml.", // needed by javax.xml
90 "org.w3c.", // needed by javax.xml
91 "org.apache.commons.logging.", // special case.
92 "org.eclipse.jetty.continuation.", // webapp cannot change continuation classes
93 "org.eclipse.jetty.jndi.", // webapp cannot change naming classes
94 "org.eclipse.jetty.plus.jaas.", // webapp cannot change jetty jaas classes
95 "org.eclipse.jetty.servlet.DefaultServlet", // webapp cannot change default servlets
96 };
97 private String[] _serverClasses = {
98 "-org.eclipse.jetty.continuation.", // don't hide continuation classes
99 "-org.eclipse.jetty.jndi.", // don't hide naming classes
100 "-org.eclipse.jetty.plus.jaas.", // don't hide jaas modules
101 "-org.eclipse.jetty.servlet.DefaultServlet", // webapp cannot change default servlets
102 "org.eclipse.jetty." // hide rest of jetty classes
103 };
104 private File _tmpDir;
105 private String _war;
106 private String _extraClasspath;
107 private Throwable _unavailableException;
108
109 private Map _resourceAliases;
110 private boolean _ownClassLoader=false;
111 private boolean _configurationDiscovered=true;
112
113 public static ContextHandler getCurrentWebAppContext()
114 {
115 ContextHandler.Context context=ContextHandler.getCurrentContext();
116 if (context!=null)
117 {
118 ContextHandler handler = context.getContextHandler();
119 if (handler instanceof WebAppContext)
120 return (ContextHandler)handler;
121 }
122 return null;
123 }
124
125 /* ------------------------------------------------------------ */
126 public WebAppContext()
127 {
128 super(SESSIONS|SECURITY);
129 }
130
131 /* ------------------------------------------------------------ */
132 /**
133 * @param contextPath The context path
134 * @param webApp The URL or filename of the webapp directory or war file.
135 */
136 public WebAppContext(String webApp,String contextPath)
137 {
138 super(null,contextPath,SESSIONS|SECURITY);
139 setContextPath(contextPath);
140 setWar(webApp);
141 setErrorHandler(new ErrorPageErrorHandler());
142 }
143
144 /* ------------------------------------------------------------ */
145 /**
146 * @param parent The parent HandlerContainer.
147 * @param contextPath The context path
148 * @param webApp The URL or filename of the webapp directory or war file.
149 */
150 public WebAppContext(HandlerContainer parent, String webApp, String contextPath)
151 {
152 super(parent,contextPath,SESSIONS|SECURITY);
153 setWar(webApp);
154 setErrorHandler(new ErrorPageErrorHandler());
155 }
156
157 /* ------------------------------------------------------------ */
158 /**
159 */
160 public WebAppContext(SessionHandler sessionHandler, SecurityHandler securityHandler, ServletHandler servletHandler, ErrorHandler errorHandler)
161 {
162 super(null,sessionHandler,securityHandler,servletHandler,errorHandler);
163
164 setErrorHandler(errorHandler!=null?errorHandler:new ErrorPageErrorHandler());
165 }
166
167 /* ------------------------------------------------------------ */
168 /**
169 * @param servletContextName The servletContextName to set.
170 */
171 public void setDisplayName(String servletContextName)
172 {
173 super.setDisplayName(servletContextName);
174 ClassLoader cl = getClassLoader();
175 if (cl!=null && cl instanceof WebAppClassLoader)
176 ((WebAppClassLoader)cl).setName(servletContextName);
177 }
178
179 /* ------------------------------------------------------------ */
180 /** Get an exception that caused the webapp to be unavailable
181 * @return A throwable if the webapp is unavailable or null
182 */
183 public Throwable getUnavailableException()
184 {
185 return _unavailableException;
186 }
187
188
189 /* ------------------------------------------------------------ */
190 /** Set Resource Alias.
191 * Resource aliases map resource uri's within a context.
192 * They may optionally be used by a handler when looking for
193 * a resource.
194 * @param alias
195 * @param uri
196 */
197 public void setResourceAlias(String alias, String uri)
198 {
199 if (_resourceAliases == null)
200 _resourceAliases= new HashMap(5);
201 _resourceAliases.put(alias, uri);
202 }
203
204 /* ------------------------------------------------------------ */
205 public Map getResourceAliases()
206 {
207 if (_resourceAliases == null)
208 return null;
209 return _resourceAliases;
210 }
211
212 /* ------------------------------------------------------------ */
213 public void setResourceAliases(Map map)
214 {
215 _resourceAliases = map;
216 }
217
218 /* ------------------------------------------------------------ */
219 public String getResourceAlias(String alias)
220 {
221 if (_resourceAliases == null)
222 return null;
223 return (String)_resourceAliases.get(alias);
224 }
225
226 /* ------------------------------------------------------------ */
227 public String removeResourceAlias(String alias)
228 {
229 if (_resourceAliases == null)
230 return null;
231 return (String)_resourceAliases.remove(alias);
232 }
233
234 /* ------------------------------------------------------------ */
235 /* (non-Javadoc)
236 * @see org.eclipse.jetty.server.server.handler.ContextHandler#setClassLoader(java.lang.ClassLoader)
237 */
238 public void setClassLoader(ClassLoader classLoader)
239 {
240 super.setClassLoader(classLoader);
241 if (classLoader!=null && classLoader instanceof WebAppClassLoader)
242 ((WebAppClassLoader)classLoader).setName(getDisplayName());
243 }
244
245 /* ------------------------------------------------------------ */
246 public Resource getResource(String uriInContext) throws MalformedURLException
247 {
248 IOException ioe= null;
249 Resource resource= null;
250 int loop=0;
251 while (uriInContext!=null && loop++<100)
252 {
253 try
254 {
255 resource= super.getResource(uriInContext);
256 if (resource != null && resource.exists())
257 return resource;
258
259 uriInContext = getResourceAlias(uriInContext);
260 }
261 catch (IOException e)
262 {
263 Log.ignore(e);
264 if (ioe==null)
265 ioe= e;
266 }
267 }
268
269 if (ioe != null && ioe instanceof MalformedURLException)
270 throw (MalformedURLException)ioe;
271
272 return resource;
273 }
274
275
276 /* ------------------------------------------------------------ */
277 /** Is the context Automatically configured.
278 *
279 * @return true if configuration discovery.
280 */
281 public boolean isConfigurationDiscovered()
282 {
283 return _configurationDiscovered;
284 }
285
286 /* ------------------------------------------------------------ */
287 /** Set the configuration discovery mode.
288 * If configuration discovery is set to true, then the JSR315
289 * servlet 3.0 discovered configuration features are enabled.
290 * These are:<ul>
291 * <li>Web Fragments</li>
292 * <li>META-INF/resource directories</li>
293 * </ul>
294 * @param servlet3autoConfig the servlet3autoConfig to set
295 */
296 public void setConfigurationDiscovered(boolean discovered)
297 {
298 _configurationDiscovered = discovered;
299 }
300
301 /* ------------------------------------------------------------ */
302 /*
303 * @see org.eclipse.thread.AbstractLifeCycle#doStart()
304 */
305 protected void doStart() throws Exception
306 {
307 try
308 {
309 // Setup configurations
310 loadConfigurations();
311
312
313 // Configure classloader
314 _ownClassLoader=false;
315 if (getClassLoader()==null)
316 {
317 WebAppClassLoader classLoader = new WebAppClassLoader(this);
318 setClassLoader(classLoader);
319 _ownClassLoader=true;
320 }
321
322 if (Log.isDebugEnabled())
323 {
324 ClassLoader loader = getClassLoader();
325 Log.debug("Thread Context class loader is: " + loader);
326 loader=loader.getParent();
327 while(loader!=null)
328 {
329 Log.debug("Parent class loader is: " + loader);
330 loader=loader.getParent();
331 }
332 }
333
334
335
336 // Prepare for configuration
337 for (int i=0;i<_configurations.length;i++)
338 _configurations[i].preConfigure(this);
339
340 super.doStart();
341
342 // Clean up after configuration
343 for (int i=0;i<_configurations.length;i++)
344 _configurations[i].postConfigure(this);
345
346
347 if (isLogUrlOnStart())
348 dumpUrl();
349 }
350 catch (Exception e)
351 {
352 //start up of the webapp context failed, make sure it is not started
353 Log.warn("Failed startup of context "+this, e);
354 _unavailableException=e;
355 setAvailable(false);
356 }
357 }
358
359 /* ------------------------------------------------------------ */
360 /*
361 * Dumps the current web app name and URL to the log
362 */
363 public void dumpUrl()
364 {
365 Connector[] connectors = getServer().getConnectors();
366 for (int i=0;i<connectors.length;i++)
367 {
368 String connectorName = connectors[i].getName();
369 String displayName = getDisplayName();
370 if (displayName == null)
371 displayName = "WebApp@"+connectors.hashCode();
372
373 Log.info(displayName + " at http://" + connectorName + getContextPath());
374 }
375 }
376
377 /* ------------------------------------------------------------ */
378 /*
379 * @see org.eclipse.thread.AbstractLifeCycle#doStop()
380 */
381 protected void doStop() throws Exception
382 {
383 super.doStop();
384
385 try
386 {
387 for (int i=_configurations.length;i-->0;)
388 _configurations[i].deconfigure(this);
389
390 _configurations=null;
391
392 }
393 finally
394 {
395 if (_ownClassLoader)
396 setClassLoader(null);
397
398 setAvailable(true);
399 _unavailableException=null;
400 }
401 }
402
403 /* ------------------------------------------------------------ */
404 /**
405 * @return Returns the configurations.
406 */
407 public String[] getConfigurationClasses()
408 {
409 return _configurationClasses;
410 }
411
412 /* ------------------------------------------------------------ */
413 /**
414 * @return Returns the configurations.
415 */
416 public Configuration[] getConfigurations()
417 {
418 return _configurations;
419 }
420
421 /* ------------------------------------------------------------ */
422 /**
423 * The default descriptor is a web.xml format file that is applied to the context before the standard WEB-INF/web.xml
424 * @return Returns the defaultsDescriptor.
425 */
426 public String getDefaultsDescriptor()
427 {
428 return _defaultsDescriptor;
429 }
430
431 /* ------------------------------------------------------------ */
432 /**
433 * The override descriptor is a web.xml format file that is applied to the context after the standard WEB-INF/web.xml
434 * @return Returns the Override Descriptor.
435 */
436 public String getOverrideDescriptor()
437 {
438 return _overrideDescriptor;
439 }
440
441 /* ------------------------------------------------------------ */
442 /**
443 * @return Returns the permissions.
444 */
445 public PermissionCollection getPermissions()
446 {
447 return _permissions;
448 }
449
450
451 /* ------------------------------------------------------------ */
452 /**
453 * @see #setServerClasses(String[])
454 * @return Returns the serverClasses.
455 */
456 public String[] getServerClasses()
457 {
458 return _serverClasses;
459 }
460
461
462 /* ------------------------------------------------------------ */
463 /**
464 * @see #setSystemClasses(String[])
465 * @return Returns the systemClasses.
466 */
467 public String[] getSystemClasses()
468 {
469 return _systemClasses;
470 }
471
472
473
474 /* ------------------------------------------------------------ */
475 public boolean isServerClass(String name)
476 {
477 name=name.replace('/','.');
478 while(name.startsWith("."))
479 name=name.substring(1);
480
481 String[] server_classes = getServerClasses();
482 if (server_classes!=null)
483 {
484 for (int i=0;i<server_classes.length;i++)
485 {
486 boolean result=true;
487 String c=server_classes[i];
488 if (c.startsWith("-"))
489 {
490 c=c.substring(1); // TODO cache
491 result=false;
492 }
493
494 if (c.endsWith("."))
495 {
496 if (name.startsWith(c))
497 return result;
498 }
499 else if (name.equals(c))
500 return result;
501 }
502 }
503 return false;
504 }
505
506 /* ------------------------------------------------------------ */
507 public boolean isSystemClass(String name)
508 {
509 name=name.replace('/','.');
510 while(name.startsWith("."))
511 name=name.substring(1);
512 String[] system_classes = getSystemClasses();
513 if (system_classes!=null)
514 {
515 for (int i=0;i<system_classes.length;i++)
516 {
517 boolean result=true;
518 String c=system_classes[i];
519
520 if (c.startsWith("-"))
521 {
522 c=c.substring(1); // TODO cache
523 result=false;
524 }
525
526 if (c.endsWith("."))
527 {
528 if (name.startsWith(c))
529 return result;
530 }
531 else if (name.equals(c))
532 return result;
533 }
534 }
535
536 return false;
537
538 }
539
540
541
542
543 /* ------------------------------------------------------------ */
544 /**
545 * @return Returns the war as a file or URL string (Resource)
546 */
547 public String getWar()
548 {
549 if (_war==null)
550 _war=getResourceBase();
551 return _war;
552 }
553
554 /* ------------------------------------------------------------ */
555 public Resource getWebInf() throws IOException
556 {
557 if (super.getBaseResource() == null)
558 return null;
559
560 // Iw there a WEB-INF directory?
561 Resource web_inf= super.getBaseResource().addPath("WEB-INF/");
562 if (!web_inf.exists() || !web_inf.isDirectory())
563 return null;
564
565 return web_inf;
566 }
567
568 /* ------------------------------------------------------------ */
569 /**
570 * @return Returns the distributable.
571 */
572 public boolean isDistributable()
573 {
574 return _distributable;
575 }
576
577 /* ------------------------------------------------------------ */
578 /**
579 * @return Returns the extractWAR.
580 */
581 public boolean isExtractWAR()
582 {
583 return _extractWAR;
584 }
585
586 /* ------------------------------------------------------------ */
587 /**
588 * @return True if the webdir is copied (to allow hot replacement of jars)
589 */
590 public boolean isCopyWebDir()
591 {
592 return _copyDir;
593 }
594
595 /* ------------------------------------------------------------ */
596 /**
597 * @return Returns the java2compliant.
598 */
599 public boolean isParentLoaderPriority()
600 {
601 return _parentLoaderPriority;
602 }
603
604 /* ------------------------------------------------------------ */
605 protected void loadConfigurations()
606 throws Exception
607 {
608 if (_configurations!=null)
609 return;
610 if (_configurationClasses==null)
611 _configurationClasses=__dftConfigurationClasses;
612
613 _configurations = new Configuration[_configurationClasses.length];
614 for (int i=0;i<_configurations.length;i++)
615 {
616 _configurations[i]=(Configuration)Loader.loadClass(this.getClass(), _configurationClasses[i]).newInstance();
617 }
618 }
619
620 /* ------------------------------------------------------------ */
621 protected boolean isProtectedTarget(String target)
622 {
623 while (target.startsWith("//"))
624 target=URIUtil.compactPath(target);
625
626 return StringUtil.startsWithIgnoreCase(target, "/web-inf") || StringUtil.startsWithIgnoreCase(target, "/meta-inf");
627 }
628
629
630 /* ------------------------------------------------------------ */
631 public String toString()
632 {
633 return super.toString()+(_war==null?"":(","+_war));
634 }
635
636
637
638
639 /* ------------------------------------------------------------ */
640 /**
641 * @param configurations The configuration class names. If setConfigurations is not called
642 * these classes are used to create a configurations array.
643 */
644 public void setConfigurationClasses(String[] configurations)
645 {
646 _configurationClasses = configurations==null?null:(String[])configurations.clone();
647 }
648
649 /* ------------------------------------------------------------ */
650 /**
651 * @param configurations The configurations to set.
652 */
653 public void setConfigurations(Configuration[] configurations)
654 {
655 _configurations = configurations==null?null:(Configuration[])configurations.clone();
656 }
657
658 /* ------------------------------------------------------------ */
659 /**
660 * The default descriptor is a web.xml format file that is applied to the context before the standard WEB-INF/web.xml
661 * @param defaultsDescriptor The defaultsDescriptor to set.
662 */
663 public void setDefaultsDescriptor(String defaultsDescriptor)
664 {
665 _defaultsDescriptor = defaultsDescriptor;
666 }
667
668 /* ------------------------------------------------------------ */
669 /**
670 * The override descriptor is a web.xml format file that is applied to the context after the standard WEB-INF/web.xml
671 * @param overrideDescriptor The overrideDescritpor to set.
672 */
673 public void setOverrideDescriptor(String overrideDescriptor)
674 {
675 _overrideDescriptor = overrideDescriptor;
676 }
677
678 /* ------------------------------------------------------------ */
679 /**
680 * @return the web.xml descriptor to use. If set to null, WEB-INF/web.xml is used if it exists.
681 */
682 public String getDescriptor()
683 {
684 return _descriptor;
685 }
686
687 /* ------------------------------------------------------------ */
688 /**
689 * @param descriptor the web.xml descriptor to use. If set to null, WEB-INF/web.xml is used if it exists.
690 */
691 public void setDescriptor(String descriptor)
692 {
693 _descriptor=descriptor;
694 }
695
696 /* ------------------------------------------------------------ */
697 /**
698 * @param distributable The distributable to set.
699 */
700 public void setDistributable(boolean distributable)
701 {
702 this._distributable = distributable;
703 }
704
705 /* ------------------------------------------------------------ */
706 public void setEventListeners(EventListener[] eventListeners)
707 {
708 if (_sessionHandler!=null)
709 _sessionHandler.clearEventListeners();
710
711 super.setEventListeners(eventListeners);
712
713 for (int i=0; eventListeners!=null && i<eventListeners.length;i ++)
714 {
715 EventListener listener = eventListeners[i];
716
717 if ((listener instanceof HttpSessionActivationListener)
718 || (listener instanceof HttpSessionAttributeListener)
719 || (listener instanceof HttpSessionBindingListener)
720 || (listener instanceof HttpSessionListener))
721 {
722 if (_sessionHandler!=null)
723 _sessionHandler.addEventListener(listener);
724 }
725
726 }
727 }
728
729 /* ------------------------------------------------------------ */
730 /** Add EventListener
731 * Conveniance method that calls {@link #setEventListeners(EventListener[])}
732 * @param listener
733 */
734 public void addEventListener(EventListener listener)
735 {
736 setEventListeners((EventListener[])LazyList.addToArray(getEventListeners(), listener, EventListener.class));
737 }
738
739
740 /* ------------------------------------------------------------ */
741 /**
742 * @param extractWAR True if war files are extracted
743 */
744 public void setExtractWAR(boolean extractWAR)
745 {
746 _extractWAR = extractWAR;
747 }
748
749 /* ------------------------------------------------------------ */
750 /**
751 *
752 * @param copy True if the webdir is copied (to allow hot replacement of jars)
753 */
754 public void setCopyWebDir(boolean copy)
755 {
756 _copyDir = copy;
757 }
758
759 /* ------------------------------------------------------------ */
760 /**
761 * @param java2compliant The java2compliant to set.
762 */
763 public void setParentLoaderPriority(boolean java2compliant)
764 {
765 _parentLoaderPriority = java2compliant;
766 }
767
768 /* ------------------------------------------------------------ */
769 /**
770 * @param permissions The permissions to set.
771 */
772 public void setPermissions(PermissionCollection permissions)
773 {
774 _permissions = permissions;
775 }
776
777 /* ------------------------------------------------------------ */
778 /**
779 * Set the server classes patterns.
780 * <p>
781 * Server classes/packages are classes used to implement the server and are hidden
782 * from the context. If the context needs to load these classes, it must have its
783 * own copy of them in WEB-INF/lib or WEB-INF/classes.
784 * A class pattern is a string of one of the forms:<dl>
785 * <dt>org.package.Classname</dt><dd>Match a specific class</dd>
786 * <dt>org.package.</dt><dd>Match a specific package hierarchy</dd>
787 * <dt>-org.package.Classname</dt><dd>Exclude a specific class</dd>
788 * <dt>-org.package.</dt><dd>Exclude a specific package hierarchy</dd>
789 * </dl>
790 * @param serverClasses The serverClasses to set.
791 */
792 public void setServerClasses(String[] serverClasses)
793 {
794 _serverClasses = serverClasses==null?null:(String[])serverClasses.clone();
795 }
796
797 /* ------------------------------------------------------------ */
798 /**
799 * Set the system classes patterns.
800 * <p>
801 * System classes/packages are classes provided by the JVM and that
802 * cannot be replaced by classes of the same name from WEB-INF,
803 * regardless of the value of {@link #setParentLoaderPriority(boolean)}.
804 * A class pattern is a string of one of the forms:<dl>
805 * <dt>org.package.Classname</dt><dd>Match a specific class</dd>
806 * <dt>org.package.</dt><dd>Match a specific package hierarchy</dd>
807 * <dt>-org.package.Classname</dt><dd>Exclude a specific class</dd>
808 * <dt>-org.package.</dt><dd>Exclude a specific package hierarchy</dd>
809 * </dl>
810 * @param systemClasses The systemClasses to set.
811 */
812 public void setSystemClasses(String[] systemClasses)
813 {
814 _systemClasses = systemClasses==null?null:(String[])systemClasses.clone();
815 }
816
817
818 /* ------------------------------------------------------------ */
819 /** Set temporary directory for context.
820 * The javax.servlet.context.tempdir attribute is also set.
821 * @param dir Writable temporary directory.
822 */
823 public void setTempDirectory(File dir)
824 {
825 if (isStarted())
826 throw new IllegalStateException("Started");
827
828 if (dir!=null)
829 {
830 try{dir=new File(dir.getCanonicalPath());}
831 catch (IOException e){Log.warn(Log.EXCEPTION,e);}
832 }
833
834 if (dir!=null && !dir.exists())
835 {
836 dir.mkdir();
837 dir.deleteOnExit();
838 }
839
840 if (dir!=null && ( !dir.exists() || !dir.isDirectory() || !dir.canWrite()))
841 throw new IllegalArgumentException("Bad temp directory: "+dir);
842
843 _tmpDir=dir;
844 setAttribute(TEMPDIR,_tmpDir);
845 }
846
847 public File getTempDirectory ()
848 {
849 return _tmpDir;
850 }
851
852 /* ------------------------------------------------------------ */
853 /**
854 * @param war The war to set as a file name or URL
855 */
856 public void setWar(String war)
857 {
858 _war = war;
859 }
860
861
862 /* ------------------------------------------------------------ */
863 /**
864 * @return Comma or semicolon separated path of filenames or URLs
865 * pointing to directories or jar files. Directories should end
866 * with '/'.
867 */
868 public String getExtraClasspath()
869 {
870 return _extraClasspath;
871 }
872
873 /* ------------------------------------------------------------ */
874 /**
875 * @param extraClasspath Comma or semicolon separated path of filenames or URLs
876 * pointing to directories or jar files. Directories should end
877 * with '/'.
878 */
879 public void setExtraClasspath(String extraClasspath)
880 {
881 _extraClasspath=extraClasspath;
882 }
883
884 /* ------------------------------------------------------------ */
885 public boolean isLogUrlOnStart()
886 {
887 return _logUrlOnStart;
888 }
889
890 /* ------------------------------------------------------------ */
891 /**
892 * Sets whether or not the web app name and URL is logged on startup
893 *
894 * @param logOnStart whether or not the log message is created
895 */
896 public void setLogUrlOnStart(boolean logOnStart)
897 {
898 this._logUrlOnStart = logOnStart;
899 }
900
901 /* ------------------------------------------------------------ */
902 protected void startContext()
903 throws Exception
904 {
905
906
907 // Configure webapp
908 for (int i=0;i<_configurations.length;i++)
909 _configurations[i].configure(this);
910
911
912 super.startContext();
913 }
914
915 }