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