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