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.URL;
19 import java.net.URLClassLoader;
20 import java.util.ArrayList;
21 import java.util.EnumSet;
22 import java.util.EventListener;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26
27 import javax.servlet.ServletException;
28
29 import org.eclipse.jetty.http.security.Constraint;
30 import org.eclipse.jetty.security.ConstraintAware;
31 import org.eclipse.jetty.security.ConstraintMapping;
32 import org.eclipse.jetty.security.authentication.FormAuthenticator;
33 import org.eclipse.jetty.server.DispatcherType;
34 import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
35 import org.eclipse.jetty.servlet.FilterHolder;
36 import org.eclipse.jetty.servlet.FilterMapping;
37 import org.eclipse.jetty.servlet.ServletContextHandler;
38 import org.eclipse.jetty.servlet.ServletHolder;
39 import org.eclipse.jetty.servlet.ServletMapping;
40 import org.eclipse.jetty.util.LazyList;
41 import org.eclipse.jetty.util.Loader;
42 import org.eclipse.jetty.util.log.Log;
43 import org.eclipse.jetty.util.log.Logger;
44 import org.eclipse.jetty.util.resource.Resource;
45 import org.eclipse.jetty.xml.XmlParser;
46
47
48
49
50
51
52 public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
53 {
54 private static final Logger LOG = Log.getLogger(StandardDescriptorProcessor.class);
55
56 public static final String STANDARD_PROCESSOR = "org.eclipse.jetty.standardDescriptorProcessor";
57
58
59
60 public StandardDescriptorProcessor ()
61 {
62
63 try
64 {
65 registerVisitor("context-param", this.getClass().getDeclaredMethod("visitContextParam", __signature));
66 registerVisitor("display-name", this.getClass().getDeclaredMethod("visitDisplayName", __signature));
67 registerVisitor("servlet", this.getClass().getDeclaredMethod("visitServlet", __signature));
68 registerVisitor("servlet-mapping", this.getClass().getDeclaredMethod("visitServletMapping", __signature));
69 registerVisitor("session-config", this.getClass().getDeclaredMethod("visitSessionConfig", __signature));
70 registerVisitor("mime-mapping", this.getClass().getDeclaredMethod("visitMimeMapping", __signature));
71 registerVisitor("welcome-file-list", this.getClass().getDeclaredMethod("visitWelcomeFileList", __signature));
72 registerVisitor("locale-encoding-mapping-list", this.getClass().getDeclaredMethod("visitLocaleEncodingList", __signature));
73 registerVisitor("error-page", this.getClass().getDeclaredMethod("visitErrorPage", __signature));
74 registerVisitor("taglib", this.getClass().getDeclaredMethod("visitTagLib", __signature));
75 registerVisitor("jsp-config", this.getClass().getDeclaredMethod("visitJspConfig", __signature));
76 registerVisitor("security-constraint", this.getClass().getDeclaredMethod("visitSecurityConstraint", __signature));
77 registerVisitor("login-config", this.getClass().getDeclaredMethod("visitLoginConfig", __signature));
78 registerVisitor("security-role", this.getClass().getDeclaredMethod("visitSecurityRole", __signature));
79 registerVisitor("filter", this.getClass().getDeclaredMethod("visitFilter", __signature));
80 registerVisitor("filter-mapping", this.getClass().getDeclaredMethod("visitFilterMapping", __signature));
81 registerVisitor("listener", this.getClass().getDeclaredMethod("visitListener", __signature));
82 registerVisitor("distributable", this.getClass().getDeclaredMethod("visitDistributable", __signature));
83 }
84 catch (Exception e)
85 {
86 throw new IllegalStateException(e);
87 }
88 }
89
90
91
92
93
94
95 public void start(WebAppContext context, Descriptor descriptor)
96 {
97 }
98
99
100
101
102
103
104 public void end(WebAppContext context, Descriptor descriptor)
105 {
106 }
107
108
109
110
111
112
113 public void visitContextParam (WebAppContext context, Descriptor descriptor, XmlParser.Node node)
114 {
115 String name = node.getString("param-name", false, true);
116 String value = node.getString("param-value", false, true);
117 Origin o = context.getMetaData().getOrigin("context-param."+name);
118 switch (o)
119 {
120 case NotSet:
121 {
122
123 context.getInitParams().put(name, value);
124 context.getMetaData().setOrigin("context-param."+name, descriptor);
125 break;
126 }
127 case WebXml:
128 case WebDefaults:
129 case WebOverride:
130 {
131
132 if (!(descriptor instanceof FragmentDescriptor))
133 {
134 context.getInitParams().put(name, value);
135 context.getMetaData().setOrigin("context-param."+name, descriptor);
136 }
137 break;
138 }
139 case WebFragment:
140 {
141
142 if (descriptor instanceof FragmentDescriptor)
143 {
144 if (!((String)context.getInitParams().get(name)).equals(value))
145 throw new IllegalStateException("Conflicting context-param "+name+"="+value+" in "+descriptor.getResource());
146 }
147 break;
148 }
149 }
150 if (LOG.isDebugEnabled()) LOG.debug("ContextParam: " + name + "=" + value);
151
152 }
153
154
155
156
157
158
159
160
161 protected void visitDisplayName(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
162 {
163
164 if (!(descriptor instanceof FragmentDescriptor))
165 {
166 context.setDisplayName(node.toString(false, true));
167 context.getMetaData().setOrigin("display-name", descriptor);
168 }
169 }
170
171
172
173
174
175
176
177 protected void visitServlet(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
178 {
179 String id = node.getAttribute("id");
180
181
182 String servlet_name = node.getString("servlet-name", false, true);
183 ServletHolder holder = context.getServletHandler().getServlet(servlet_name);
184
185
186
187
188 if (holder == null)
189 {
190 holder = context.getServletHandler().newServletHolder();
191 holder.setName(servlet_name);
192 context.getServletHandler().addServlet(holder);
193 }
194
195
196 Iterator<?> iParamsIter = node.iterator("init-param");
197 while (iParamsIter.hasNext())
198 {
199 XmlParser.Node paramNode = (XmlParser.Node) iParamsIter.next();
200 String pname = paramNode.getString("param-name", false, true);
201 String pvalue = paramNode.getString("param-value", false, true);
202
203 Origin origin = context.getMetaData().getOrigin(servlet_name+".servlet.init-param."+pname);
204
205 switch (origin)
206 {
207 case NotSet:
208 {
209
210
211 holder.setInitParameter(pname, pvalue);
212 context.getMetaData().setOrigin(servlet_name+".servlet.init-param."+pname, descriptor);
213 break;
214 }
215 case WebXml:
216 case WebDefaults:
217 case WebOverride:
218 {
219
220
221 if (!(descriptor instanceof FragmentDescriptor))
222 {
223 holder.setInitParameter(pname, pvalue);
224 context.getMetaData().setOrigin(servlet_name+".servlet.init-param."+pname, descriptor);
225 }
226 break;
227 }
228 case WebFragment:
229 {
230
231 if (!holder.getInitParameter(pname).equals(pvalue))
232 throw new IllegalStateException("Mismatching init-param "+pname+"="+pvalue+" in "+descriptor.getResource());
233 break;
234 }
235 }
236 }
237
238 String servlet_class = node.getString("servlet-class", false, true);
239
240
241 String jspServletName=null;
242 String jspServletClass=null;;
243 boolean hasJSP=false;
244 if (id != null && id.equals("jsp"))
245 {
246 jspServletName = servlet_name;
247 jspServletClass = servlet_class;
248 try
249 {
250 Loader.loadClass(this.getClass(), servlet_class);
251 hasJSP = true;
252 }
253 catch (ClassNotFoundException e)
254 {
255 LOG.info("NO JSP Support for {}, did not find {}", context.getContextPath(), servlet_class);
256 jspServletClass = servlet_class = "org.eclipse.jetty.servlet.NoJspServlet";
257 }
258 if (holder.getInitParameter("scratchdir") == null)
259 {
260 File tmp = context.getTempDirectory();
261 File scratch = new File(tmp, "jsp");
262 if (!scratch.exists()) scratch.mkdir();
263 holder.setInitParameter("scratchdir", scratch.getAbsolutePath());
264
265 if ("?".equals(holder.getInitParameter("classpath")))
266 {
267 String classpath = context.getClassPath();
268 LOG.debug("classpath=" + classpath);
269 if (classpath != null)
270 holder.setInitParameter("classpath", classpath);
271 }
272 }
273
274
275 context.setAttribute("org.apache.catalina.jsp_classpath", context.getClassPath());
276
277
278 holder.setInitParameter("com.sun.appserv.jsp.classpath", getSystemClassPath(context));
279 }
280
281
282 if (servlet_class != null)
283 {
284 ((WebDescriptor)descriptor).addClassName(servlet_class);
285
286 Origin o = context.getMetaData().getOrigin(servlet_name+".servlet.servlet-class");
287 switch (o)
288 {
289 case NotSet:
290 {
291
292 holder.setClassName(servlet_class);
293 context.getMetaData().setOrigin(servlet_name+".servlet.servlet-class", descriptor);
294 break;
295 }
296 case WebXml:
297 case WebDefaults:
298 case WebOverride:
299 {
300
301 if (!(descriptor instanceof FragmentDescriptor))
302 {
303 holder.setClassName(servlet_class);
304 context.getMetaData().setOrigin(servlet_name+".servlet.servlet-class", descriptor);
305 }
306 break;
307 }
308 case WebFragment:
309 {
310
311 if (!servlet_class.equals(holder.getClassName()))
312 throw new IllegalStateException("Conflicting servlet-class "+servlet_class+" in "+descriptor.getResource());
313 break;
314 }
315 }
316 }
317
318
319 String jsp_file = node.getString("jsp-file", false, true);
320 if (jsp_file != null)
321 {
322 holder.setForcedPath(jsp_file);
323 holder.setClassName(jspServletClass);
324
325 holder.setInitParameter("com.sun.appserv.jsp.classpath", getSystemClassPath(context));
326 }
327
328
329 XmlParser.Node startup = node.get("load-on-startup");
330 if (startup != null)
331 {
332 String s = startup.toString(false, true).toLowerCase();
333 int order = 0;
334 if (s.startsWith("t"))
335 {
336 LOG.warn("Deprecated boolean load-on-startup. Please use integer");
337 order = 1;
338 }
339 else
340 {
341 try
342 {
343 if (s != null && s.trim().length() > 0) order = Integer.parseInt(s);
344 }
345 catch (Exception e)
346 {
347 LOG.warn("Cannot parse load-on-startup " + s + ". Please use integer");
348 LOG.ignore(e);
349 }
350 }
351
352 Origin o = context.getMetaData().getOrigin(servlet_name+".servlet.load-on-startup");
353 switch (o)
354 {
355 case NotSet:
356 {
357
358 holder.setInitOrder(order);
359 context.getMetaData().setOrigin(servlet_name+".servlet.load-on-startup", descriptor);
360 break;
361 }
362 case WebXml:
363 case WebDefaults:
364 case WebOverride:
365 {
366
367 if (!(descriptor instanceof FragmentDescriptor))
368 {
369 holder.setInitOrder(order);
370 context.getMetaData().setOrigin(servlet_name+".servlet.load-on-startup", descriptor);
371 }
372 break;
373 }
374 case WebFragment:
375 {
376
377 if (order != holder.getInitOrder())
378 throw new IllegalStateException("Conflicting load-on-startup value in "+descriptor.getResource());
379 break;
380 }
381 }
382 }
383
384 Iterator sRefsIter = node.iterator("security-role-ref");
385 while (sRefsIter.hasNext())
386 {
387 XmlParser.Node securityRef = (XmlParser.Node) sRefsIter.next();
388 String roleName = securityRef.getString("role-name", false, true);
389 String roleLink = securityRef.getString("role-link", false, true);
390 if (roleName != null && roleName.length() > 0 && roleLink != null && roleLink.length() > 0)
391 {
392 if (LOG.isDebugEnabled()) LOG.debug("link role " + roleName + " to " + roleLink + " for " + this);
393 Origin o = context.getMetaData().getOrigin(servlet_name+".servlet.role-name."+roleName);
394 switch (o)
395 {
396 case NotSet:
397 {
398
399 holder.setUserRoleLink(roleName, roleLink);
400 context.getMetaData().setOrigin(servlet_name+".servlet.role-name."+roleName, descriptor);
401 break;
402 }
403 case WebXml:
404 case WebDefaults:
405 case WebOverride:
406 {
407
408 if (!(descriptor instanceof FragmentDescriptor))
409 {
410 holder.setUserRoleLink(roleName, roleLink);
411 context.getMetaData().setOrigin(servlet_name+".servlet.role-name."+roleName, descriptor);
412 }
413 break;
414 }
415 case WebFragment:
416 {
417 if (!holder.getUserRoleLink(roleName).equals(roleLink))
418 throw new IllegalStateException("Conflicting role-link for role-name "+roleName+" for servlet "+servlet_name+" in "+descriptor.getResource());
419 break;
420 }
421 }
422 }
423 else
424 {
425 LOG.warn("Ignored invalid security-role-ref element: " + "servlet-name=" + holder.getName() + ", " + securityRef);
426 }
427 }
428
429
430 XmlParser.Node run_as = node.get("run-as");
431 if (run_as != null)
432 {
433 String roleName = run_as.getString("role-name", false, true);
434
435 if (roleName != null)
436 {
437 Origin o = context.getMetaData().getOrigin(servlet_name+".servlet.run-as");
438 switch (o)
439 {
440 case NotSet:
441 {
442
443 holder.setRunAsRole(roleName);
444 context.getMetaData().setOrigin(servlet_name+".servlet.run-as", descriptor);
445 break;
446 }
447 case WebXml:
448 case WebDefaults:
449 case WebOverride:
450 {
451
452 if (!(descriptor instanceof FragmentDescriptor))
453 {
454 holder.setRunAsRole(roleName);
455 context.getMetaData().setOrigin(servlet_name+".servlet.run-as", descriptor);
456 }
457 break;
458 }
459 case WebFragment:
460 {
461
462 if (!holder.getRunAsRole().equals(roleName))
463 throw new IllegalStateException("Conflicting run-as role "+roleName+" for servlet "+servlet_name+" in "+descriptor.getResource());
464 break;
465 }
466 }
467 }
468 }
469 }
470
471
472
473
474
475
476
477
478 protected void visitServletMapping(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
479 {
480
481
482
483
484
485
486 String servlet_name = node.getString("servlet-name", false, true);
487 Origin origin = context.getMetaData().getOrigin(servlet_name+".servlet.mappings");
488
489 switch (origin)
490 {
491 case NotSet:
492 {
493
494 context.getMetaData().setOrigin(servlet_name+".servlet.mappings", descriptor);
495 addServletMapping(servlet_name, node, context);
496 break;
497 }
498 case WebXml:
499 case WebDefaults:
500 case WebOverride:
501 {
502
503
504 if (!(descriptor instanceof FragmentDescriptor))
505 {
506 addServletMapping(servlet_name, node, context);
507 }
508 break;
509 }
510 case WebFragment:
511 {
512
513 addServletMapping(servlet_name, node, context);
514 break;
515 }
516 }
517 }
518
519
520
521
522
523
524
525 protected void visitSessionConfig(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
526 {
527 XmlParser.Node tNode = node.get("session-timeout");
528 if (tNode != null)
529 {
530 int timeout = Integer.parseInt(tNode.toString(false, true));
531 context.getSessionHandler().getSessionManager().setMaxInactiveInterval(timeout * 60);
532 }
533 }
534
535
536
537
538
539
540
541
542 protected void visitMimeMapping(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
543 {
544 String extension = node.getString("extension", false, true);
545 if (extension != null && extension.startsWith("."))
546 extension = extension.substring(1);
547 String mimeType = node.getString("mime-type", false, true);
548 if (extension != null)
549 {
550 Origin o = context.getMetaData().getOrigin("extension."+extension);
551 switch (o)
552 {
553 case NotSet:
554 {
555
556 context.getMimeTypes().addMimeMapping(extension, mimeType);
557 context.getMetaData().setOrigin("extension."+extension, descriptor);
558 break;
559 }
560 case WebXml:
561 case WebDefaults:
562 case WebOverride:
563 {
564
565 if (!(descriptor instanceof FragmentDescriptor))
566 {
567 context.getMimeTypes().addMimeMapping(extension, mimeType);
568 context.getMetaData().setOrigin("extension."+extension, descriptor);
569 }
570 break;
571 }
572 case WebFragment:
573 {
574
575 if (!context.getMimeTypes().getMimeByExtension("."+extension).equals(context.getMimeTypes().CACHE.lookup(mimeType)))
576 throw new IllegalStateException("Conflicting mime-type "+mimeType+" for extension "+extension+" in "+descriptor.getResource());
577 break;
578 }
579 }
580 }
581 }
582
583
584
585
586
587
588 protected void visitWelcomeFileList(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
589 {
590 Origin o = context.getMetaData().getOrigin("welcome-file-list");
591 switch (o)
592 {
593 case NotSet:
594 {
595 context.getMetaData().setOrigin("welcome-file-list", descriptor);
596 addWelcomeFiles(context,node);
597 break;
598 }
599 case WebXml:
600 {
601
602 addWelcomeFiles(context,node);
603 break;
604 }
605 case WebDefaults:
606 {
607
608
609 if (!(descriptor instanceof DefaultsDescriptor) && !(descriptor instanceof OverrideDescriptor) && !(descriptor instanceof FragmentDescriptor))
610 {
611 context.setWelcomeFiles(new String[0]);
612 }
613 addWelcomeFiles(context,node);
614 break;
615 }
616 case WebOverride:
617 {
618
619 addWelcomeFiles(context,node);
620 break;
621 }
622 case WebFragment:
623 {
624
625 addWelcomeFiles(context,node);
626 break;
627 }
628 }
629 }
630
631
632
633
634
635
636 protected void visitLocaleEncodingList(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
637 {
638 Iterator<XmlParser.Node> iter = node.iterator("locale-encoding-mapping");
639 while (iter.hasNext())
640 {
641 XmlParser.Node mapping = iter.next();
642 String locale = mapping.getString("locale", false, true);
643 String encoding = mapping.getString("encoding", false, true);
644
645 if (encoding != null)
646 {
647 Origin o = context.getMetaData().getOrigin("locale-encoding."+locale);
648 switch (o)
649 {
650 case NotSet:
651 {
652
653 context.addLocaleEncoding(locale, encoding);
654 context.getMetaData().setOrigin("locale-encoding."+locale, descriptor);
655 break;
656 }
657 case WebXml:
658 case WebDefaults:
659 case WebOverride:
660 {
661
662 if (!(descriptor instanceof FragmentDescriptor))
663 {
664 context.addLocaleEncoding(locale, encoding);
665 context.getMetaData().setOrigin("locale-encoding."+locale, descriptor);
666 }
667 break;
668 }
669 case WebFragment:
670 {
671
672 if (!encoding.equals(context.getLocaleEncoding(locale)))
673 throw new IllegalStateException("Conflicting locale-encoding mapping for locale "+locale+" in "+descriptor.getResource());
674 break;
675 }
676 }
677 }
678 }
679 }
680
681
682
683
684
685
686 protected void visitErrorPage(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
687 {
688 String error = node.getString("error-code", false, true);
689 int code=0;
690 if (error == null || error.length() == 0)
691 error = node.getString("exception-type", false, true);
692 else
693 code=Integer.valueOf(error);
694 String location = node.getString("location", false, true);
695
696
697 ErrorPageErrorHandler handler = (ErrorPageErrorHandler)context.getErrorHandler();
698
699
700 Origin o = context.getMetaData().getOrigin("error."+error);
701 switch (o)
702 {
703 case NotSet:
704 {
705
706 if (code>0)
707 handler.addErrorPage(code,location);
708 else
709 handler.addErrorPage(error,location);
710 context.getMetaData().setOrigin("error."+error, descriptor);
711 break;
712 }
713 case WebXml:
714 case WebDefaults:
715 case WebOverride:
716 {
717
718 if (!(descriptor instanceof FragmentDescriptor))
719 {
720 if (code>0)
721 handler.addErrorPage(code,location);
722 else
723 handler.addErrorPage(error,location);
724 context.getMetaData().setOrigin("error."+error, descriptor);
725 }
726 break;
727 }
728 case WebFragment:
729 {
730
731 if (!handler.getErrorPages().get(error).equals(location))
732 throw new IllegalStateException("Conflicting error-code or exception-type "+error+" in "+descriptor.getResource());
733 break;
734 }
735 }
736
737 }
738
739
740
741
742
743 protected void addWelcomeFiles(WebAppContext context, XmlParser.Node node)
744 {
745 Iterator<XmlParser.Node> iter = node.iterator("welcome-file");
746 while (iter.hasNext())
747 {
748 XmlParser.Node indexNode = (XmlParser.Node) iter.next();
749 String welcome = indexNode.toString(false, true);
750
751
752 context.setWelcomeFiles((String[])LazyList.addToArray(context.getWelcomeFiles(),welcome,String.class));
753 }
754 }
755
756
757
758
759
760
761
762 protected void addServletMapping (String servletName, XmlParser.Node node, WebAppContext context)
763 {
764 ServletMapping mapping = new ServletMapping();
765 mapping.setServletName(servletName);
766
767 List<String> paths = new ArrayList<String>();
768 Iterator<XmlParser.Node> iter = node.iterator("url-pattern");
769 while (iter.hasNext())
770 {
771 String p = iter.next().toString(false, true);
772 p = normalizePattern(p);
773 paths.add(p);
774 }
775 mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));
776 context.getServletHandler().addServletMapping(mapping);
777 }
778
779
780
781
782
783
784 protected void addFilterMapping (String filterName, XmlParser.Node node, WebAppContext context)
785 {
786 FilterMapping mapping = new FilterMapping();
787 mapping.setFilterName(filterName);
788
789 List<String> paths = new ArrayList<String>();
790 Iterator<XmlParser.Node> iter = node.iterator("url-pattern");
791 while (iter.hasNext())
792 {
793 String p = iter.next().toString(false, true);
794 p = normalizePattern(p);
795 paths.add(p);
796 }
797 mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));
798
799 List<String> names = new ArrayList<String>();
800 iter = node.iterator("servlet-name");
801 while (iter.hasNext())
802 {
803 String n = ((XmlParser.Node) iter.next()).toString(false, true);
804 names.add(n);
805 }
806 mapping.setServletNames((String[]) names.toArray(new String[names.size()]));
807
808
809 List<DispatcherType> dispatches = new ArrayList<DispatcherType>();
810 iter=node.iterator("dispatcher");
811 while(iter.hasNext())
812 {
813 String d=((XmlParser.Node)iter.next()).toString(false,true);
814 dispatches.add(FilterMapping.dispatch(d));
815 }
816
817 if (dispatches.size()>0)
818 mapping.setDispatcherTypes(EnumSet.copyOf(dispatches));
819
820 context.getServletHandler().addFilterMapping(mapping);
821 }
822
823
824
825
826
827
828
829 protected void visitTagLib(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
830 {
831
832 String uri = node.getString("taglib-uri", false, true);
833 String location = node.getString("taglib-location", false, true);
834
835 context.setResourceAlias(uri, location);
836 }
837
838
839
840
841
842
843 protected void visitJspConfig(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
844 {
845 for (int i = 0; i < node.size(); i++)
846 {
847 Object o = node.get(i);
848 if (o instanceof XmlParser.Node && "taglib".equals(((XmlParser.Node) o).getTag()))
849 visitTagLib(context,descriptor, (XmlParser.Node) o);
850 }
851
852
853
854 Iterator<XmlParser.Node> iter = node.iterator("jsp-property-group");
855 List<String> paths = new ArrayList<String>();
856 while (iter.hasNext())
857 {
858 XmlParser.Node group = iter.next();
859 Iterator<XmlParser.Node> iter2 = group.iterator("url-pattern");
860 while (iter2.hasNext())
861 {
862 String url = iter2.next().toString(false, true);
863 url = normalizePattern(url);
864 paths.add( url);
865 }
866 }
867
868 if (paths.size() > 0)
869 {
870 String jspName = "jsp";
871 Map.Entry entry = context.getServletHandler().getHolderEntry("test.jsp");
872 if (entry != null)
873 {
874 ServletHolder holder = (ServletHolder) entry.getValue();
875 jspName = holder.getName();
876 }
877
878 if (jspName != null)
879 {
880 ServletMapping mapping = new ServletMapping();
881 mapping.setServletName(jspName);
882 mapping.setPathSpecs(paths.toArray(new String[paths.size()]));
883 context.getServletHandler().addServletMapping(mapping);
884 }
885 }
886 }
887
888
889
890
891
892
893 protected void visitSecurityConstraint(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
894 {
895 Constraint scBase = new Constraint();
896
897
898
899 try
900 {
901 XmlParser.Node auths = node.get("auth-constraint");
902
903 if (auths != null)
904 {
905 scBase.setAuthenticate(true);
906
907 Iterator<XmlParser.Node> iter = auths.iterator("role-name");
908 List<String> roles = new ArrayList<String>();
909 while (iter.hasNext())
910 {
911 String role = iter.next().toString(false, true);
912 roles.add(role);
913 }
914 scBase.setRoles(roles.toArray(new String[roles.size()]));
915 }
916
917 XmlParser.Node data = node.get("user-data-constraint");
918 if (data != null)
919 {
920 data = data.get("transport-guarantee");
921 String guarantee = data.toString(false, true).toUpperCase();
922 if (guarantee == null || guarantee.length() == 0 || "NONE".equals(guarantee))
923 scBase.setDataConstraint(Constraint.DC_NONE);
924 else if ("INTEGRAL".equals(guarantee))
925 scBase.setDataConstraint(Constraint.DC_INTEGRAL);
926 else if ("CONFIDENTIAL".equals(guarantee))
927 scBase.setDataConstraint(Constraint.DC_CONFIDENTIAL);
928 else
929 {
930 LOG.warn("Unknown user-data-constraint:" + guarantee);
931 scBase.setDataConstraint(Constraint.DC_CONFIDENTIAL);
932 }
933 }
934 Iterator<XmlParser.Node> iter = node.iterator("web-resource-collection");
935 while (iter.hasNext())
936 {
937 XmlParser.Node collection = iter.next();
938 String name = collection.getString("web-resource-name", false, true);
939 Constraint sc = (Constraint) scBase.clone();
940 sc.setName(name);
941
942 Iterator<XmlParser.Node> iter2 = collection.iterator("url-pattern");
943 while (iter2.hasNext())
944 {
945 String url = iter2.next().toString(false, true);
946 url = normalizePattern(url);
947
948 Iterator<XmlParser.Node> iter3 = collection.iterator("http-method");
949 if (iter3.hasNext())
950 {
951 while (iter3.hasNext())
952 {
953 String method = ((XmlParser.Node) iter3.next()).toString(false, true);
954 ConstraintMapping mapping = new ConstraintMapping();
955 mapping.setMethod(method);
956 mapping.setPathSpec(url);
957 mapping.setConstraint(sc);
958
959 ((ConstraintAware)context.getSecurityHandler()).addConstraintMapping(mapping);
960 }
961 }
962 else
963 {
964 ConstraintMapping mapping = new ConstraintMapping();
965 mapping.setPathSpec(url);
966 mapping.setConstraint(sc);
967 ((ConstraintAware)context.getSecurityHandler()).addConstraintMapping(mapping);
968 }
969 }
970 }
971 }
972 catch (CloneNotSupportedException e)
973 {
974 LOG.warn(e);
975 }
976 }
977
978
979
980
981
982
983
984 protected void visitLoginConfig(WebAppContext context, Descriptor descriptor, XmlParser.Node node) throws Exception
985 {
986
987
988
989 XmlParser.Node method = node.get("auth-method");
990 if (method != null)
991 {
992
993 Origin o = context.getMetaData().getOrigin("auth-method");
994 switch (o)
995 {
996 case NotSet:
997 {
998
999 context.getSecurityHandler().setAuthMethod(method.toString(false, true));
1000 context.getMetaData().setOrigin("auth-method", descriptor);
1001 break;
1002 }
1003 case WebXml:
1004 case WebDefaults:
1005 case WebOverride:
1006 {
1007
1008 if (!(descriptor instanceof FragmentDescriptor))
1009 {
1010 context.getSecurityHandler().setAuthMethod(method.toString(false, true));
1011 context.getMetaData().setOrigin("auth-method", descriptor);
1012 }
1013 break;
1014 }
1015 case WebFragment:
1016 {
1017
1018 if (!context.getSecurityHandler().getAuthMethod().equals(method.toString(false, true)))
1019 throw new IllegalStateException("Conflicting auth-method value in "+descriptor.getResource());
1020 break;
1021 }
1022 }
1023
1024
1025 XmlParser.Node name = node.get("realm-name");
1026 String nameStr = (name == null ? "default" : name.toString(false, true));
1027 o = context.getMetaData().getOrigin("realm-name");
1028 switch (o)
1029 {
1030 case NotSet:
1031 {
1032
1033 context.getSecurityHandler().setRealmName(nameStr);
1034 context.getMetaData().setOrigin("realm-name", descriptor);
1035 break;
1036 }
1037 case WebXml:
1038 case WebDefaults:
1039 case WebOverride:
1040 {
1041
1042 if (!(descriptor instanceof FragmentDescriptor))
1043 {
1044 context.getSecurityHandler().setRealmName(nameStr);
1045 context.getMetaData().setOrigin("realm-name", descriptor);
1046 }
1047 break;
1048 }
1049 case WebFragment:
1050 {
1051
1052 if (!context.getSecurityHandler().getRealmName().equals(nameStr))
1053 throw new IllegalStateException("Conflicting realm-name value in "+descriptor.getResource());
1054 break;
1055 }
1056 }
1057
1058 if (Constraint.__FORM_AUTH.equals(context.getSecurityHandler().getAuthMethod()))
1059 {
1060 XmlParser.Node formConfig = node.get("form-login-config");
1061 if (formConfig != null)
1062 {
1063 String loginPageName = null;
1064 XmlParser.Node loginPage = formConfig.get("form-login-page");
1065 if (loginPage != null)
1066 loginPageName = loginPage.toString(false, true);
1067 String errorPageName = null;
1068 XmlParser.Node errorPage = formConfig.get("form-error-page");
1069 if (errorPage != null)
1070 errorPageName = errorPage.toString(false, true);
1071
1072
1073 o = context.getMetaData().getOrigin("form-login-page");
1074 switch (o)
1075 {
1076 case NotSet:
1077 {
1078
1079 context.getSecurityHandler().setInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE,loginPageName);
1080 context.getMetaData().setOrigin("form-login-page",descriptor);
1081 break;
1082 }
1083 case WebXml:
1084 case WebDefaults:
1085 case WebOverride:
1086 {
1087
1088 if (!(descriptor instanceof FragmentDescriptor))
1089 {
1090 context.getSecurityHandler().setInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE,loginPageName);
1091 context.getMetaData().setOrigin("form-login-page",descriptor);
1092 }
1093 break;
1094 }
1095 case WebFragment:
1096 {
1097
1098 if (!context.getSecurityHandler().getInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE).equals(loginPageName))
1099 throw new IllegalStateException("Conflicting form-login-page value in "+descriptor.getResource());
1100 break;
1101 }
1102 }
1103
1104
1105 o = context.getMetaData().getOrigin("form-error-page");
1106 switch (o)
1107 {
1108 case NotSet:
1109 {
1110
1111 context.getSecurityHandler().setInitParameter(FormAuthenticator.__FORM_ERROR_PAGE,errorPageName);
1112 context.getMetaData().setOrigin("form-error-page",descriptor);
1113 break;
1114 }
1115 case WebXml:
1116 case WebDefaults:
1117 case WebOverride:
1118 {
1119
1120 if (!(descriptor instanceof FragmentDescriptor))
1121 {
1122 context.getSecurityHandler().setInitParameter(FormAuthenticator.__FORM_ERROR_PAGE,errorPageName);
1123 context.getMetaData().setOrigin("form-error-page",descriptor);
1124 }
1125 break;
1126 }
1127 case WebFragment:
1128 {
1129
1130 if (!context.getSecurityHandler().getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE).equals(errorPageName))
1131 throw new IllegalStateException("Conflicting form-error-page value in "+descriptor.getResource());
1132 break;
1133 }
1134 }
1135 }
1136 else
1137 {
1138 throw new IllegalStateException("!form-login-config");
1139 }
1140 }
1141 }
1142 }
1143
1144
1145
1146
1147
1148
1149 protected void visitSecurityRole(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1150 {
1151
1152 XmlParser.Node roleNode = node.get("role-name");
1153 String role = roleNode.toString(false, true);
1154 ((ConstraintAware)context.getSecurityHandler()).addRole(role);
1155 }
1156
1157
1158
1159
1160
1161
1162
1163 protected void visitFilter(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1164 {
1165 String name = node.getString("filter-name", false, true);
1166 FilterHolder holder = context.getServletHandler().getFilter(name);
1167 if (holder == null)
1168 {
1169 holder = context.getServletHandler().newFilterHolder();
1170 holder.setName(name);
1171 context.getServletHandler().addFilter(holder);
1172 }
1173
1174 String filter_class = node.getString("filter-class", false, true);
1175 if (filter_class != null)
1176 {
1177 ((WebDescriptor)descriptor).addClassName(filter_class);
1178
1179 Origin o = context.getMetaData().getOrigin(name+".filter.filter-class");
1180 switch (o)
1181 {
1182 case NotSet:
1183 {
1184
1185 holder.setClassName(filter_class);
1186 context.getMetaData().setOrigin(name+".filter.filter-class", descriptor);
1187 break;
1188 }
1189 case WebXml:
1190 case WebDefaults:
1191 case WebOverride:
1192 {
1193
1194 if (!(descriptor instanceof FragmentDescriptor))
1195 {
1196 holder.setClassName(filter_class);
1197 context.getMetaData().setOrigin(name+".filter.filter-class", descriptor);
1198 }
1199 break;
1200 }
1201 case WebFragment:
1202 {
1203
1204 if (!holder.getClassName().equals(filter_class))
1205 throw new IllegalStateException("Conflicting filter-class for filter "+name+" in "+descriptor.getResource());
1206 break;
1207 }
1208 }
1209
1210 }
1211
1212 Iterator<XmlParser.Node> iter = node.iterator("init-param");
1213 while (iter.hasNext())
1214 {
1215 XmlParser.Node paramNode = iter.next();
1216 String pname = paramNode.getString("param-name", false, true);
1217 String pvalue = paramNode.getString("param-value", false, true);
1218
1219 Origin origin = context.getMetaData().getOrigin(name+".filter.init-param."+pname);
1220 switch (origin)
1221 {
1222 case NotSet:
1223 {
1224
1225 holder.setInitParameter(pname, pvalue);
1226 context.getMetaData().setOrigin(name+".filter.init-param."+pname, descriptor);
1227 break;
1228 }
1229 case WebXml:
1230 case WebDefaults:
1231 case WebOverride:
1232 {
1233
1234
1235 if (!(descriptor instanceof FragmentDescriptor))
1236 {
1237 holder.setInitParameter(pname, pvalue);
1238 context.getMetaData().setOrigin(name+".filter.init-param."+pname, descriptor);
1239 }
1240 break;
1241 }
1242 case WebFragment:
1243 {
1244
1245 if (!holder.getInitParameter(pname).equals(pvalue))
1246 throw new IllegalStateException("Mismatching init-param "+pname+"="+pvalue+" in "+descriptor.getResource());
1247 break;
1248 }
1249 }
1250 }
1251
1252 String async=node.getString("async-supported",false,true);
1253 if (async!=null)
1254 holder.setAsyncSupported(async.length()==0||Boolean.valueOf(async));
1255 if (async!=null)
1256 {
1257 boolean val = async.length()==0||Boolean.valueOf(async);
1258 Origin o = context.getMetaData().getOrigin(name+".filter.async-supported");
1259 switch (o)
1260 {
1261 case NotSet:
1262 {
1263
1264 holder.setAsyncSupported(val);
1265 context.getMetaData().setOrigin(name+".filter.async-supported", descriptor);
1266 break;
1267 }
1268 case WebXml:
1269 case WebDefaults:
1270 case WebOverride:
1271 {
1272
1273 if (!(descriptor instanceof FragmentDescriptor))
1274 {
1275 holder.setAsyncSupported(val);
1276 context.getMetaData().setOrigin(name+".filter.async-supported", descriptor);
1277 }
1278 break;
1279 }
1280 case WebFragment:
1281 {
1282
1283 if (holder.isAsyncSupported() != val)
1284 throw new IllegalStateException("Conflicting async-supported="+async+" for filter "+name+" in "+descriptor.getResource());
1285 break;
1286 }
1287 }
1288 }
1289
1290 }
1291
1292
1293
1294
1295
1296
1297 protected void visitFilterMapping(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1298 {
1299
1300
1301
1302
1303
1304
1305 String filter_name = node.getString("filter-name", false, true);
1306
1307 Origin origin = context.getMetaData().getOrigin(filter_name+".filter.mappings");
1308
1309 switch (origin)
1310 {
1311 case NotSet:
1312 {
1313
1314 context.getMetaData().setOrigin(filter_name+".filter.mappings", descriptor);
1315 addFilterMapping(filter_name, node, context);
1316 break;
1317 }
1318 case WebDefaults:
1319 case WebOverride:
1320 case WebXml:
1321 {
1322
1323 if (!(descriptor instanceof FragmentDescriptor))
1324 {
1325 addFilterMapping(filter_name, node, context);
1326 }
1327 break;
1328 }
1329 case WebFragment:
1330 {
1331
1332 addFilterMapping(filter_name, node, context);
1333 break;
1334 }
1335 }
1336 }
1337
1338
1339
1340
1341
1342
1343
1344 protected void visitListener(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1345 {
1346 String className = node.getString("listener-class", false, true);
1347 EventListener listener = null;
1348 try
1349 {
1350 if (className != null && className.length()> 0)
1351 {
1352
1353
1354 EventListener[] listeners=context.getEventListeners();
1355 if (listeners!=null)
1356 {
1357 for (EventListener l : listeners)
1358 {
1359 if (l.getClass().getName().equals(className))
1360 return;
1361 }
1362 }
1363
1364 ((WebDescriptor)descriptor).addClassName(className);
1365
1366 Class<? extends EventListener> listenerClass = (Class<? extends EventListener>)context.loadClass(className);
1367 listener = newListenerInstance(context,listenerClass);
1368 if (!(listener instanceof EventListener))
1369 {
1370 LOG.warn("Not an EventListener: " + listener);
1371 return;
1372 }
1373 context.addEventListener(listener);
1374 context.getMetaData().setOrigin(className+".listener", descriptor);
1375
1376 }
1377 }
1378 catch (Exception e)
1379 {
1380 LOG.warn("Could not instantiate listener " + className, e);
1381 return;
1382 }
1383 }
1384
1385
1386
1387
1388
1389
1390 protected void visitDistributable(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1391 {
1392
1393
1394
1395 ((WebDescriptor)descriptor).setDistributable(true);
1396 }
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406 protected EventListener newListenerInstance(WebAppContext context,Class<? extends EventListener> clazz) throws ServletException, InstantiationException, IllegalAccessException
1407 {
1408 try
1409 {
1410 return ((ServletContextHandler.Context)context.getServletContext()).createListener(clazz);
1411 }
1412 catch (ServletException se)
1413 {
1414 Throwable cause = se.getRootCause();
1415 if (cause instanceof InstantiationException)
1416 throw (InstantiationException)cause;
1417 if (cause instanceof IllegalAccessException)
1418 throw (IllegalAccessException)cause;
1419 throw se;
1420 }
1421 }
1422
1423
1424
1425
1426
1427 protected String normalizePattern(String p)
1428 {
1429 if (p != null && p.length() > 0 && !p.startsWith("/") && !p.startsWith("*")) return "/" + p;
1430 return p;
1431 }
1432
1433
1434
1435
1436
1437
1438
1439
1440 protected String getSystemClassPath(WebAppContext context)
1441 {
1442 ClassLoader loader = context.getClassLoader();
1443 if (loader.getParent() != null)
1444 loader = loader.getParent();
1445
1446 StringBuilder classpath=new StringBuilder();
1447 while (loader != null && (loader instanceof URLClassLoader))
1448 {
1449 URL[] urls = ((URLClassLoader)loader).getURLs();
1450 if (urls != null)
1451 {
1452 for (int i=0;i<urls.length;i++)
1453 {
1454 try
1455 {
1456 Resource resource = context.newResource(urls[i]);
1457 File file=resource.getFile();
1458 if (file!=null && file.exists())
1459 {
1460 if (classpath.length()>0)
1461 classpath.append(File.pathSeparatorChar);
1462 classpath.append(file.getAbsolutePath());
1463 }
1464 }
1465 catch (IOException e)
1466 {
1467 LOG.debug(e);
1468 }
1469 }
1470 }
1471 loader = loader.getParent();
1472 }
1473 return classpath.toString();
1474 }
1475 }