1
2
3
4
5
6
7
8
9
10
11
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
47
48
49
50
51
52
53
54
55
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.",
88 "javax.",
89 "org.xml.",
90 "org.w3c.",
91 "org.apache.commons.logging.",
92 "org.eclipse.jetty.continuation.",
93 "org.eclipse.jetty.jndi.",
94 "org.eclipse.jetty.plus.jaas.",
95 "org.eclipse.jetty.servlet.DefaultServlet",
96 };
97 private String[] _serverClasses = {
98 "-org.eclipse.jetty.continuation.",
99 "-org.eclipse.jetty.jndi.",
100 "-org.eclipse.jetty.plus.jaas.",
101 "-org.eclipse.jetty.servlet.DefaultServlet",
102 "org.eclipse.jetty."
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
134
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
147
148
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
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
181
182
183 public Throwable getUnavailableException()
184 {
185 return _unavailableException;
186 }
187
188
189
190
191
192
193
194
195
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
236
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
278
279
280
281 public boolean isConfigurationDiscovered()
282 {
283 return _configurationDiscovered;
284 }
285
286
287
288
289
290
291
292
293
294
295
296 public void setConfigurationDiscovered(boolean discovered)
297 {
298 _configurationDiscovered = discovered;
299 }
300
301
302
303
304
305 protected void doStart() throws Exception
306 {
307 try
308 {
309
310 loadConfigurations();
311
312
313
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
337 for (int i=0;i<_configurations.length;i++)
338 _configurations[i].preConfigure(this);
339
340 super.doStart();
341
342
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
353 Log.warn("Failed startup of context "+this, e);
354 _unavailableException=e;
355 setAvailable(false);
356 }
357 }
358
359
360
361
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
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
406
407 public String[] getConfigurationClasses()
408 {
409 return _configurationClasses;
410 }
411
412
413
414
415
416 public Configuration[] getConfigurations()
417 {
418 return _configurations;
419 }
420
421
422
423
424
425
426 public String getDefaultsDescriptor()
427 {
428 return _defaultsDescriptor;
429 }
430
431
432
433
434
435
436 public String getOverrideDescriptor()
437 {
438 return _overrideDescriptor;
439 }
440
441
442
443
444
445 public PermissionCollection getPermissions()
446 {
447 return _permissions;
448 }
449
450
451
452
453
454
455
456 public String[] getServerClasses()
457 {
458 return _serverClasses;
459 }
460
461
462
463
464
465
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);
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);
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
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
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
571
572 public boolean isDistributable()
573 {
574 return _distributable;
575 }
576
577
578
579
580
581 public boolean isExtractWAR()
582 {
583 return _extractWAR;
584 }
585
586
587
588
589
590 public boolean isCopyWebDir()
591 {
592 return _copyDir;
593 }
594
595
596
597
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
642
643
644 public void setConfigurationClasses(String[] configurations)
645 {
646 _configurationClasses = configurations==null?null:(String[])configurations.clone();
647 }
648
649
650
651
652
653 public void setConfigurations(Configuration[] configurations)
654 {
655 _configurations = configurations==null?null:(Configuration[])configurations.clone();
656 }
657
658
659
660
661
662
663 public void setDefaultsDescriptor(String defaultsDescriptor)
664 {
665 _defaultsDescriptor = defaultsDescriptor;
666 }
667
668
669
670
671
672
673 public void setOverrideDescriptor(String overrideDescriptor)
674 {
675 _overrideDescriptor = overrideDescriptor;
676 }
677
678
679
680
681
682 public String getDescriptor()
683 {
684 return _descriptor;
685 }
686
687
688
689
690
691 public void setDescriptor(String descriptor)
692 {
693 _descriptor=descriptor;
694 }
695
696
697
698
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
731
732
733
734 public void addEventListener(EventListener listener)
735 {
736 setEventListeners((EventListener[])LazyList.addToArray(getEventListeners(), listener, EventListener.class));
737 }
738
739
740
741
742
743
744 public void setExtractWAR(boolean extractWAR)
745 {
746 _extractWAR = extractWAR;
747 }
748
749
750
751
752
753
754 public void setCopyWebDir(boolean copy)
755 {
756 _copyDir = copy;
757 }
758
759
760
761
762
763 public void setParentLoaderPriority(boolean java2compliant)
764 {
765 _parentLoaderPriority = java2compliant;
766 }
767
768
769
770
771
772 public void setPermissions(PermissionCollection permissions)
773 {
774 _permissions = permissions;
775 }
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792 public void setServerClasses(String[] serverClasses)
793 {
794 _serverClasses = serverClasses==null?null:(String[])serverClasses.clone();
795 }
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812 public void setSystemClasses(String[] systemClasses)
813 {
814 _systemClasses = systemClasses==null?null:(String[])systemClasses.clone();
815 }
816
817
818
819
820
821
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
855
856 public void setWar(String war)
857 {
858 _war = war;
859 }
860
861
862
863
864
865
866
867
868 public String getExtraClasspath()
869 {
870 return _extraClasspath;
871 }
872
873
874
875
876
877
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
893
894
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
908 for (int i=0;i<_configurations.length;i++)
909 _configurations[i].configure(this);
910
911
912 super.startContext();
913 }
914
915 }