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