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