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