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