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