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