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.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.EnumSet;
24 import java.util.EventListener;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.ListIterator;
30 import java.util.Locale;
31 import java.util.Map;
32 import java.util.Set;
33
34 import javax.servlet.DispatcherType;
35 import javax.servlet.MultipartConfigElement;
36 import javax.servlet.ServletException;
37 import javax.servlet.SessionTrackingMode;
38
39 import org.eclipse.jetty.security.ConstraintAware;
40 import org.eclipse.jetty.security.ConstraintMapping;
41 import org.eclipse.jetty.security.authentication.FormAuthenticator;
42 import org.eclipse.jetty.servlet.BaseHolder.Source;
43 import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
44 import org.eclipse.jetty.servlet.FilterHolder;
45 import org.eclipse.jetty.servlet.FilterMapping;
46 import org.eclipse.jetty.servlet.ListenerHolder;
47 import org.eclipse.jetty.servlet.ServletContextHandler.JspConfig;
48 import org.eclipse.jetty.servlet.ServletContextHandler.JspPropertyGroup;
49 import org.eclipse.jetty.servlet.ServletContextHandler.TagLib;
50 import org.eclipse.jetty.servlet.ServletHolder;
51 import org.eclipse.jetty.servlet.ServletMapping;
52 import org.eclipse.jetty.util.ArrayUtil;
53 import org.eclipse.jetty.util.Loader;
54 import org.eclipse.jetty.util.StringUtil;
55 import org.eclipse.jetty.util.log.Log;
56 import org.eclipse.jetty.util.log.Logger;
57 import org.eclipse.jetty.util.security.Constraint;
58 import org.eclipse.jetty.xml.XmlParser;
59 import org.eclipse.jetty.xml.XmlParser.Node;
60
61
62
63
64
65
66 public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
67 {
68 private static final Logger LOG = Log.getLogger(StandardDescriptorProcessor.class);
69
70 public static final String STANDARD_PROCESSOR = "org.eclipse.jetty.standardDescriptorProcessor";
71
72 final Map<String,FilterHolder> _filterHolderMap = new HashMap<>();
73 final List<FilterHolder> _filterHolders = new ArrayList<>();
74 final List<FilterMapping> _filterMappings = new ArrayList<>();
75 final Map<String,ServletHolder> _servletHolderMap = new HashMap<>();
76 final List<ServletHolder> _servletHolders = new ArrayList<>();
77 final List<ServletMapping> _servletMappings = new ArrayList<>();
78
79 public StandardDescriptorProcessor ()
80 {
81 try
82 {
83 registerVisitor("context-param", this.getClass().getMethod("visitContextParam", __signature));
84 registerVisitor("display-name", this.getClass().getMethod("visitDisplayName", __signature));
85 registerVisitor("servlet", this.getClass().getMethod("visitServlet", __signature));
86 registerVisitor("servlet-mapping", this.getClass().getMethod("visitServletMapping", __signature));
87 registerVisitor("session-config", this.getClass().getMethod("visitSessionConfig", __signature));
88 registerVisitor("mime-mapping", this.getClass().getMethod("visitMimeMapping", __signature));
89 registerVisitor("welcome-file-list", this.getClass().getMethod("visitWelcomeFileList", __signature));
90 registerVisitor("locale-encoding-mapping-list", this.getClass().getMethod("visitLocaleEncodingList", __signature));
91 registerVisitor("error-page", this.getClass().getMethod("visitErrorPage", __signature));
92 registerVisitor("taglib", this.getClass().getMethod("visitTagLib", __signature));
93 registerVisitor("jsp-config", this.getClass().getMethod("visitJspConfig", __signature));
94 registerVisitor("security-constraint", this.getClass().getMethod("visitSecurityConstraint", __signature));
95 registerVisitor("login-config", this.getClass().getMethod("visitLoginConfig", __signature));
96 registerVisitor("security-role", this.getClass().getMethod("visitSecurityRole", __signature));
97 registerVisitor("filter", this.getClass().getMethod("visitFilter", __signature));
98 registerVisitor("filter-mapping", this.getClass().getMethod("visitFilterMapping", __signature));
99 registerVisitor("listener", this.getClass().getMethod("visitListener", __signature));
100 registerVisitor("distributable", this.getClass().getMethod("visitDistributable", __signature));
101 registerVisitor("deny-uncovered-http-methods", this.getClass().getMethod("visitDenyUncoveredHttpMethods", __signature));
102 }
103 catch (Exception e)
104 {
105 throw new IllegalStateException(e);
106 }
107 }
108
109
110
111
112
113
114 public void start(WebAppContext context, Descriptor descriptor)
115 {
116 for (FilterHolder h : context.getServletHandler().getFilters())
117 {
118 _filterHolderMap.put(h.getName(),h);
119 _filterHolders.add(h);
120 }
121 if (context.getServletHandler().getFilterMappings()!=null)
122 _filterMappings.addAll(Arrays.asList(context.getServletHandler().getFilterMappings()));
123 for (ServletHolder h : context.getServletHandler().getServlets())
124 {
125 _servletHolderMap.put(h.getName(),h);
126 _servletHolders.add(h);
127 }
128 if (context.getServletHandler().getServletMappings()!=null)
129 _servletMappings.addAll(Arrays.asList(context.getServletHandler().getServletMappings()));
130 }
131
132
133
134
135
136 public void end(WebAppContext context, Descriptor descriptor)
137 {
138 context.getServletHandler().setFilters(_filterHolders.toArray(new FilterHolder[_filterHolderMap.size()]));
139 context.getServletHandler().setServlets(_servletHolders.toArray(new ServletHolder[_servletHolderMap.size()]));
140
141 context.getServletHandler().setFilterMappings(_filterMappings.toArray(new FilterMapping[_filterMappings.size()]));
142 context.getServletHandler().setServletMappings(_servletMappings.toArray(new ServletMapping[_servletMappings.size()]));
143
144 _filterHolderMap.clear();
145 _filterHolders.clear();
146 _filterMappings.clear();
147 _servletHolderMap.clear();
148 _servletHolders.clear();
149 _servletMappings.clear();
150 }
151
152 public void visitContextParam (WebAppContext context, Descriptor descriptor, XmlParser.Node node)
153 {
154 String name = node.getString("param-name", false, true);
155 String value = node.getString("param-value", false, true);
156 switch (context.getMetaData().getOrigin("context-param."+name))
157 {
158 case NotSet:
159 {
160
161 context.getInitParams().put(name, value);
162 context.getMetaData().setOrigin("context-param."+name, descriptor);
163 break;
164 }
165 case WebXml:
166 case WebDefaults:
167 case WebOverride:
168 {
169
170 if (!(descriptor instanceof FragmentDescriptor))
171 {
172 context.getInitParams().put(name, value);
173 context.getMetaData().setOrigin("context-param."+name, descriptor);
174 }
175 break;
176 }
177 case WebFragment:
178 {
179
180 if (descriptor instanceof FragmentDescriptor)
181 {
182 if (!((String)context.getInitParams().get(name)).equals(value))
183 throw new IllegalStateException("Conflicting context-param "+name+"="+value+" in "+descriptor.getResource());
184 }
185 break;
186 }
187 default:
188 LOG.warn(new Throwable());
189 }
190 if (LOG.isDebugEnabled())
191 LOG.debug("ContextParam: " + name + "=" + value);
192
193 }
194
195 public void visitDisplayName(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
196 {
197
198 if (!(descriptor instanceof FragmentDescriptor))
199 {
200 context.setDisplayName(node.toString(false, true));
201 context.getMetaData().setOrigin("display-name", descriptor);
202 }
203 }
204
205 public void visitServlet(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
206 {
207 String id = node.getAttribute("id");
208
209
210 String name = node.getString("servlet-name", false, true);
211 ServletHolder holder = _servletHolderMap.get(name);
212
213
214 if (holder == null)
215 {
216 holder = context.getServletHandler().newServletHolder(Source.DESCRIPTOR);
217 holder.setName(name);
218 _servletHolderMap.put(name,holder);
219 _servletHolders.add(holder);
220 }
221
222
223 Iterator<?> iParamsIter = node.iterator("init-param");
224 while (iParamsIter.hasNext())
225 {
226 XmlParser.Node paramNode = (XmlParser.Node) iParamsIter.next();
227 String pname = paramNode.getString("param-name", false, true);
228 String pvalue = paramNode.getString("param-value", false, true);
229 String originName = name+".servlet.init-param."+pname;
230
231 Descriptor originDescriptor = context.getMetaData().getOriginDescriptor(originName);
232 switch (context.getMetaData().getOrigin(originName))
233 {
234 case NotSet:
235 {
236
237 holder.setInitParameter(pname, pvalue);
238 context.getMetaData().setOrigin(originName, descriptor);
239 break;
240 }
241 case WebXml:
242 case WebDefaults:
243 case WebOverride:
244 {
245
246
247
248 if (!(descriptor instanceof FragmentDescriptor) && (descriptor!=originDescriptor))
249 {
250 holder.setInitParameter(pname, pvalue);
251 context.getMetaData().setOrigin(originName, descriptor);
252 }
253 break;
254 }
255 case WebFragment:
256 {
257
258 if ((descriptor != originDescriptor) && !holder.getInitParameter(pname).equals(pvalue))
259 throw new IllegalStateException("Mismatching init-param "+pname+"="+pvalue+" in "+descriptor.getResource());
260 break;
261 }
262 default:
263 LOG.warn(new Throwable());
264 }
265 }
266
267 String servlet_class = node.getString("servlet-class", false, true);
268 if ("".equals(servlet_class))
269 servlet_class = null;
270
271
272 if (id != null && id.equals("jsp") && servlet_class != null)
273 {
274 try
275 {
276 Loader.loadClass(this.getClass(), servlet_class);
277 }
278 catch (ClassNotFoundException e)
279 {
280 LOG.info("NO JSP Support for {}, did not find {}", context.getContextPath(), servlet_class);
281 servlet_class = "org.eclipse.jetty.servlet.NoJspServlet";
282 }
283 }
284
285
286
287 if (servlet_class != null)
288 {
289 ((WebDescriptor)descriptor).addClassName(servlet_class);
290 switch (context.getMetaData().getOrigin(name+".servlet.servlet-class"))
291 {
292 case NotSet:
293 {
294
295 holder.setClassName(servlet_class);
296 context.getMetaData().setOrigin(name+".servlet.servlet-class", descriptor);
297 break;
298 }
299 case WebXml:
300 case WebDefaults:
301 case WebOverride:
302 {
303
304 if (!(descriptor instanceof FragmentDescriptor))
305 {
306 holder.setClassName(servlet_class);
307 context.getMetaData().setOrigin(name+".servlet.servlet-class", descriptor);
308 }
309 break;
310 }
311 case WebFragment:
312 {
313
314 if (!servlet_class.equals(holder.getClassName()))
315 throw new IllegalStateException("Conflicting servlet-class "+servlet_class+" in "+descriptor.getResource());
316 break;
317 }
318 default:
319 LOG.warn(new Throwable());
320 }
321 }
322
323
324 String jsp_file = node.getString("jsp-file", false, true);
325 if (jsp_file != null)
326 holder.setForcedPath(jsp_file);
327
328
329 XmlParser.Node startup = node.get("load-on-startup");
330 if (startup != null)
331 {
332 String s = startup.toString(false, true).toLowerCase(Locale.ENGLISH);
333 int order = 0;
334 if (s.startsWith("t"))
335 {
336 LOG.warn("Deprecated boolean load-on-startup. Please use integer");
337 order = 1;
338 }
339 else
340 {
341 try
342 {
343 if (s != null && s.trim().length() > 0) order = Integer.parseInt(s);
344 }
345 catch (Exception e)
346 {
347 LOG.warn("Cannot parse load-on-startup " + s + ". Please use integer");
348 LOG.ignore(e);
349 }
350 }
351
352 switch (context.getMetaData().getOrigin(name+".servlet.load-on-startup"))
353 {
354 case NotSet:
355 {
356
357 holder.setInitOrder(order);
358 context.getMetaData().setOrigin(name+".servlet.load-on-startup", descriptor);
359 break;
360 }
361 case WebXml:
362 case WebDefaults:
363 case WebOverride:
364 {
365
366 if (!(descriptor instanceof FragmentDescriptor))
367 {
368 holder.setInitOrder(order);
369 context.getMetaData().setOrigin(name+".servlet.load-on-startup", descriptor);
370 }
371 break;
372 }
373 case WebFragment:
374 {
375
376 if (order != holder.getInitOrder())
377 throw new IllegalStateException("Conflicting load-on-startup value in "+descriptor.getResource());
378 break;
379 }
380 default:
381 LOG.warn(new Throwable());
382 }
383 }
384
385 Iterator<Node> sRefsIter = node.iterator("security-role-ref");
386 while (sRefsIter.hasNext())
387 {
388 XmlParser.Node securityRef = (XmlParser.Node) sRefsIter.next();
389 String roleName = securityRef.getString("role-name", false, true);
390 String roleLink = securityRef.getString("role-link", false, true);
391 if (roleName != null && roleName.length() > 0 && roleLink != null && roleLink.length() > 0)
392 {
393 if (LOG.isDebugEnabled()) LOG.debug("link role " + roleName + " to " + roleLink + " for " + this);
394 switch (context.getMetaData().getOrigin(name+".servlet.role-name."+roleName))
395 {
396 case NotSet:
397 {
398
399 holder.setUserRoleLink(roleName, roleLink);
400 context.getMetaData().setOrigin(name+".servlet.role-name."+roleName, descriptor);
401 break;
402 }
403 case WebXml:
404 case WebDefaults:
405 case WebOverride:
406 {
407
408 if (!(descriptor instanceof FragmentDescriptor))
409 {
410 holder.setUserRoleLink(roleName, roleLink);
411 context.getMetaData().setOrigin(name+".servlet.role-name."+roleName, descriptor);
412 }
413 break;
414 }
415 case WebFragment:
416 {
417 if (!holder.getUserRoleLink(roleName).equals(roleLink))
418 throw new IllegalStateException("Conflicting role-link for role-name "+roleName+" for servlet "+name+" in "+descriptor.getResource());
419 break;
420 }
421 default:
422 LOG.warn(new Throwable());
423 }
424 }
425 else
426 {
427 LOG.warn("Ignored invalid security-role-ref element: " + "servlet-name=" + holder.getName() + ", " + securityRef);
428 }
429 }
430
431
432 XmlParser.Node run_as = node.get("run-as");
433 if (run_as != null)
434 {
435 String roleName = run_as.getString("role-name", false, true);
436
437 if (roleName != null)
438 {
439 switch (context.getMetaData().getOrigin(name+".servlet.run-as"))
440 {
441 case NotSet:
442 {
443
444 holder.setRunAsRole(roleName);
445 context.getMetaData().setOrigin(name+".servlet.run-as", descriptor);
446 break;
447 }
448 case WebXml:
449 case WebDefaults:
450 case WebOverride:
451 {
452
453 if (!(descriptor instanceof FragmentDescriptor))
454 {
455 holder.setRunAsRole(roleName);
456 context.getMetaData().setOrigin(name+".servlet.run-as", descriptor);
457 }
458 break;
459 }
460 case WebFragment:
461 {
462
463 if (!holder.getRunAsRole().equals(roleName))
464 throw new IllegalStateException("Conflicting run-as role "+roleName+" for servlet "+name+" in "+descriptor.getResource());
465 break;
466 }
467 default:
468 LOG.warn(new Throwable());
469 }
470 }
471 }
472
473 String async=node.getString("async-supported",false,true);
474 if (async!=null)
475 {
476 boolean val = async.length()==0||Boolean.valueOf(async);
477 switch (context.getMetaData().getOrigin(name+".servlet.async-supported"))
478 {
479 case NotSet:
480 {
481
482 holder.setAsyncSupported(val);
483 context.getMetaData().setOrigin(name+".servlet.async-supported", descriptor);
484 break;
485 }
486 case WebXml:
487 case WebDefaults:
488 case WebOverride:
489 {
490
491 if (!(descriptor instanceof FragmentDescriptor))
492 {
493 holder.setAsyncSupported(val);
494 context.getMetaData().setOrigin(name+".servlet.async-supported", descriptor);
495 }
496 break;
497 }
498 case WebFragment:
499 {
500
501 if (holder.isAsyncSupported() != val)
502 throw new IllegalStateException("Conflicting async-supported="+async+" for servlet "+name+" in "+descriptor.getResource());
503 break;
504 }
505 default:
506 LOG.warn(new Throwable());
507 }
508 }
509
510 String enabled = node.getString("enabled", false, true);
511 if (enabled!=null)
512 {
513 boolean is_enabled = enabled.length()==0||Boolean.valueOf(enabled);
514 switch (context.getMetaData().getOrigin(name+".servlet.enabled"))
515 {
516 case NotSet:
517 {
518
519 holder.setEnabled(is_enabled);
520 context.getMetaData().setOrigin(name+".servlet.enabled", descriptor);
521 break;
522 }
523 case WebXml:
524 case WebDefaults:
525 case WebOverride:
526 {
527
528 if (!(descriptor instanceof FragmentDescriptor))
529 {
530 holder.setEnabled(is_enabled);
531 context.getMetaData().setOrigin(name+".servlet.enabled", descriptor);
532 }
533 break;
534 }
535 case WebFragment:
536 {
537
538 if (holder.isEnabled() != is_enabled)
539 throw new IllegalStateException("Conflicting value of servlet enabled for servlet "+name+" in "+descriptor.getResource());
540 break;
541 }
542 default:
543 LOG.warn(new Throwable());
544 }
545 }
546
547
548
549
550
551
552 XmlParser.Node multipart = node.get("multipart-config");
553 if (multipart != null)
554 {
555 String location = multipart.getString("location", false, true);
556 String maxFile = multipart.getString("max-file-size", false, true);
557 String maxRequest = multipart.getString("max-request-size", false, true);
558 String threshold = multipart.getString("file-size-threshold",false,true);
559 MultipartConfigElement element = new MultipartConfigElement(location,
560 (maxFile==null||"".equals(maxFile)?-1L:Long.parseLong(maxFile)),
561 (maxRequest==null||"".equals(maxRequest)?-1L:Long.parseLong(maxRequest)),
562 (threshold==null||"".equals(threshold)?0:Integer.parseInt(threshold)));
563
564 switch (context.getMetaData().getOrigin(name+".servlet.multipart-config"))
565 {
566 case NotSet:
567 {
568
569 holder.getRegistration().setMultipartConfig(element);
570 context.getMetaData().setOrigin(name+".servlet.multipart-config", descriptor);
571 break;
572 }
573 case WebXml:
574 case WebDefaults:
575 case WebOverride:
576 {
577
578 if (!(descriptor instanceof FragmentDescriptor))
579 {
580 holder.getRegistration().setMultipartConfig(element);
581 context.getMetaData().setOrigin(name+".servlet.multipart-config", descriptor);
582 }
583 break;
584 }
585 case WebFragment:
586 {
587
588 MultipartConfigElement cfg = ((ServletHolder.Registration)holder.getRegistration()).getMultipartConfig();
589
590 if (cfg.getMaxFileSize() != element.getMaxFileSize())
591 throw new IllegalStateException("Conflicting multipart-config max-file-size for servlet "+name+" in "+descriptor.getResource());
592 if (cfg.getMaxRequestSize() != element.getMaxRequestSize())
593 throw new IllegalStateException("Conflicting multipart-config max-request-size for servlet "+name+" in "+descriptor.getResource());
594 if (cfg.getFileSizeThreshold() != element.getFileSizeThreshold())
595 throw new IllegalStateException("Conflicting multipart-config file-size-threshold for servlet "+name+" in "+descriptor.getResource());
596 if ((cfg.getLocation() != null && (element.getLocation() == null || element.getLocation().length()==0))
597 || (cfg.getLocation() == null && (element.getLocation()!=null || element.getLocation().length() > 0)))
598 throw new IllegalStateException("Conflicting multipart-config location for servlet "+name+" in "+descriptor.getResource());
599 break;
600 }
601 default:
602 LOG.warn(new Throwable());
603 }
604 }
605 }
606
607 public void visitServletMapping(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
608 {
609
610
611
612
613
614
615 String servlet_name = node.getString("servlet-name", false, true);
616 switch (context.getMetaData().getOrigin(servlet_name+".servlet.mappings"))
617 {
618 case NotSet:
619 {
620
621 context.getMetaData().setOrigin(servlet_name+".servlet.mappings", descriptor);
622 addServletMapping(servlet_name, node, context, descriptor);
623 break;
624 }
625 case WebDefaults:
626 case WebXml:
627 case WebOverride:
628 {
629
630
631 if (!(descriptor instanceof FragmentDescriptor))
632 {
633 addServletMapping(servlet_name, node, context, descriptor);
634 }
635 break;
636 }
637 case WebFragment:
638 {
639
640 addServletMapping(servlet_name, node, context, descriptor);
641 break;
642 }
643 default:
644 LOG.warn(new Throwable());
645 }
646 }
647
648 public void visitSessionConfig(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
649 {
650 XmlParser.Node tNode = node.get("session-timeout");
651 if (tNode != null)
652 {
653 int timeout = Integer.parseInt(tNode.toString(false, true));
654 context.getSessionHandler().getSessionManager().setMaxInactiveInterval(timeout * 60);
655 }
656
657
658
659
660 Iterator<Node> iter = node.iterator("tracking-mode");
661 if (iter.hasNext())
662 {
663 Set<SessionTrackingMode> modes = null;
664 Origin o = context.getMetaData().getOrigin("session.tracking-mode");
665 switch (o)
666 {
667 case NotSet:
668 case WebDefaults:
669 {
670
671 modes = new HashSet<SessionTrackingMode>();
672 context.getMetaData().setOrigin("session.tracking-mode", descriptor);
673 break;
674 }
675 case WebXml:
676 case WebFragment:
677 case WebOverride:
678 {
679
680 if (descriptor instanceof OverrideDescriptor)
681 modes = new HashSet<SessionTrackingMode>();
682 else
683 modes = new HashSet<SessionTrackingMode>(context.getSessionHandler().getSessionManager().getEffectiveSessionTrackingModes());
684 context.getMetaData().setOrigin("session.tracking-mode", descriptor);
685 break;
686 }
687 default:
688 LOG.warn(new Throwable());
689 }
690
691 while (iter.hasNext())
692 {
693 XmlParser.Node mNode = (XmlParser.Node) iter.next();
694 String trackMode = mNode.toString(false, true);
695 modes.add(SessionTrackingMode.valueOf(trackMode));
696 }
697 context.getSessionHandler().getSessionManager().setSessionTrackingModes(modes);
698 }
699
700
701
702
703 XmlParser.Node cookieConfig = node.get("cookie-config");
704 if (cookieConfig != null)
705 {
706
707 String name = cookieConfig.getString("name", false, true);
708 if (name != null)
709 {
710 switch (context.getMetaData().getOrigin("cookie-config.name"))
711 {
712 case NotSet:
713 {
714
715 context.getSessionHandler().getSessionManager().getSessionCookieConfig().setName(name);
716 context.getMetaData().setOrigin("cookie-config.name", descriptor);
717 break;
718 }
719 case WebXml:
720 case WebDefaults:
721 case WebOverride:
722 {
723
724 if (!(descriptor instanceof FragmentDescriptor))
725 {
726 context.getSessionHandler().getSessionManager().getSessionCookieConfig().setName(name);
727 context.getMetaData().setOrigin("cookie-config.name", descriptor);
728 }
729 break;
730 }
731 case WebFragment:
732 {
733
734 if (!context.getSessionHandler().getSessionManager().getSessionCookieConfig().getName().equals(name))
735 throw new IllegalStateException("Conflicting cookie-config name "+name+" in "+descriptor.getResource());
736 break;
737 }
738 default:
739 LOG.warn(new Throwable());
740 }
741 }
742
743
744 String domain = cookieConfig.getString("domain", false, true);
745 if (domain != null)
746 {
747 switch (context.getMetaData().getOrigin("cookie-config.domain"))
748 {
749 case NotSet:
750 {
751
752 context.getSessionHandler().getSessionManager().getSessionCookieConfig().setDomain(domain);
753 context.getMetaData().setOrigin("cookie-config.domain", descriptor);
754 break;
755 }
756 case WebXml:
757 case WebDefaults:
758 case WebOverride:
759 {
760
761 if (!(descriptor instanceof FragmentDescriptor))
762 {
763 context.getSessionHandler().getSessionManager().getSessionCookieConfig().setDomain(domain);
764 context.getMetaData().setOrigin("cookie-config.domain", descriptor);
765 }
766 break;
767 }
768 case WebFragment:
769 {
770
771 if (!context.getSessionHandler().getSessionManager().getSessionCookieConfig().getDomain().equals(domain))
772 throw new IllegalStateException("Conflicting cookie-config domain "+domain+" in "+descriptor.getResource());
773 break;
774 }
775 default:
776 LOG.warn(new Throwable());
777 }
778 }
779
780
781 String path = cookieConfig.getString("path", false, true);
782 if (path != null)
783 {
784 switch (context.getMetaData().getOrigin("cookie-config.path"))
785 {
786 case NotSet:
787 {
788
789 context.getSessionHandler().getSessionManager().getSessionCookieConfig().setPath(path);
790 context.getMetaData().setOrigin("cookie-config.path", descriptor);
791 break;
792 }
793 case WebXml:
794 case WebDefaults:
795 case WebOverride:
796 {
797
798 if (!(descriptor instanceof FragmentDescriptor))
799 {
800 context.getSessionHandler().getSessionManager().getSessionCookieConfig().setPath(path);
801 context.getMetaData().setOrigin("cookie-config.path", descriptor);
802 }
803 break;
804 }
805 case WebFragment:
806 {
807
808 if (!context.getSessionHandler().getSessionManager().getSessionCookieConfig().getPath().equals(path))
809 throw new IllegalStateException("Conflicting cookie-config path "+path+" in "+descriptor.getResource());
810 break;
811 }
812 default:
813 LOG.warn(new Throwable());
814 }
815 }
816
817
818 String comment = cookieConfig.getString("comment", false, true);
819 if (comment != null)
820 {
821 switch (context.getMetaData().getOrigin("cookie-config.comment"))
822 {
823 case NotSet:
824 {
825
826 context.getSessionHandler().getSessionManager().getSessionCookieConfig().setComment(comment);
827 context.getMetaData().setOrigin("cookie-config.comment", descriptor);
828 break;
829 }
830 case WebXml:
831 case WebDefaults:
832 case WebOverride:
833 {
834
835 if (!(descriptor instanceof FragmentDescriptor))
836 {
837 context.getSessionHandler().getSessionManager().getSessionCookieConfig().setComment(comment);
838 context.getMetaData().setOrigin("cookie-config.comment", descriptor);
839 }
840 break;
841 }
842 case WebFragment:
843 {
844
845 if (!context.getSessionHandler().getSessionManager().getSessionCookieConfig().getComment().equals(comment))
846 throw new IllegalStateException("Conflicting cookie-config comment "+comment+" in "+descriptor.getResource());
847 break;
848 }
849 default:
850 LOG.warn(new Throwable());
851 }
852 }
853
854
855 tNode = cookieConfig.get("http-only");
856 if (tNode != null)
857 {
858 boolean httpOnly = Boolean.parseBoolean(tNode.toString(false,true));
859 switch (context.getMetaData().getOrigin("cookie-config.http-only"))
860 {
861 case NotSet:
862 {
863
864 context.getSessionHandler().getSessionManager().getSessionCookieConfig().setHttpOnly(httpOnly);
865 context.getMetaData().setOrigin("cookie-config.http-only", descriptor);
866 break;
867 }
868 case WebXml:
869 case WebDefaults:
870 case WebOverride:
871 {
872
873 if (!(descriptor instanceof FragmentDescriptor))
874 {
875 context.getSessionHandler().getSessionManager().getSessionCookieConfig().setHttpOnly(httpOnly);
876 context.getMetaData().setOrigin("cookie-config.http-only", descriptor);
877 }
878 break;
879 }
880 case WebFragment:
881 {
882
883 if (context.getSessionHandler().getSessionManager().getSessionCookieConfig().isHttpOnly() != httpOnly)
884 throw new IllegalStateException("Conflicting cookie-config http-only "+httpOnly+" in "+descriptor.getResource());
885 break;
886 }
887 default:
888 LOG.warn(new Throwable());
889 }
890 }
891
892
893 tNode = cookieConfig.get("secure");
894 if (tNode != null)
895 {
896 boolean secure = Boolean.parseBoolean(tNode.toString(false,true));
897 switch (context.getMetaData().getOrigin("cookie-config.secure"))
898 {
899 case NotSet:
900 {
901
902 context.getSessionHandler().getSessionManager().getSessionCookieConfig().setSecure(secure);
903 context.getMetaData().setOrigin("cookie-config.secure", descriptor);
904 break;
905 }
906 case WebXml:
907 case WebDefaults:
908 case WebOverride:
909 {
910
911 if (!(descriptor instanceof FragmentDescriptor))
912 {
913 context.getSessionHandler().getSessionManager().getSessionCookieConfig().setSecure(secure);
914 context.getMetaData().setOrigin("cookie-config.secure", descriptor);
915 }
916 break;
917 }
918 case WebFragment:
919 {
920
921 if (context.getSessionHandler().getSessionManager().getSessionCookieConfig().isSecure() != secure)
922 throw new IllegalStateException("Conflicting cookie-config secure "+secure+" in "+descriptor.getResource());
923 break;
924 }
925 default:
926 LOG.warn(new Throwable());
927 }
928 }
929
930
931 tNode = cookieConfig.get("max-age");
932 if (tNode != null)
933 {
934 int maxAge = Integer.parseInt(tNode.toString(false,true));
935 switch (context.getMetaData().getOrigin("cookie-config.max-age"))
936 {
937 case NotSet:
938 {
939
940 context.getSessionHandler().getSessionManager().getSessionCookieConfig().setMaxAge(maxAge);
941 context.getMetaData().setOrigin("cookie-config.max-age", descriptor);
942 break;
943 }
944 case WebXml:
945 case WebDefaults:
946 case WebOverride:
947 {
948
949 if (!(descriptor instanceof FragmentDescriptor))
950 {
951 context.getSessionHandler().getSessionManager().getSessionCookieConfig().setMaxAge(maxAge);
952 context.getMetaData().setOrigin("cookie-config.max-age", descriptor);
953 }
954 break;
955 }
956 case WebFragment:
957 {
958
959 if (context.getSessionHandler().getSessionManager().getSessionCookieConfig().getMaxAge() != maxAge)
960 throw new IllegalStateException("Conflicting cookie-config max-age "+maxAge+" in "+descriptor.getResource());
961 break;
962 }
963 default:
964 LOG.warn(new Throwable());
965 }
966 }
967 }
968 }
969
970 public void visitMimeMapping(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
971 {
972 String extension = node.getString("extension", false, true);
973 if (extension != null && extension.startsWith("."))
974 extension = extension.substring(1);
975 String mimeType = node.getString("mime-type", false, true);
976 if (extension != null)
977 {
978 switch (context.getMetaData().getOrigin("extension."+extension))
979 {
980 case NotSet:
981 {
982
983 context.getMimeTypes().addMimeMapping(extension, mimeType);
984 context.getMetaData().setOrigin("extension."+extension, descriptor);
985 break;
986 }
987 case WebXml:
988 case WebDefaults:
989 case WebOverride:
990 {
991
992 if (!(descriptor instanceof FragmentDescriptor))
993 {
994 context.getMimeTypes().addMimeMapping(extension, mimeType);
995 context.getMetaData().setOrigin("extension."+extension, descriptor);
996 }
997 break;
998 }
999 case WebFragment:
1000 {
1001
1002 if (!context.getMimeTypes().getMimeByExtension("."+extension).equals(mimeType))
1003 throw new IllegalStateException("Conflicting mime-type "+mimeType+" for extension "+extension+" in "+descriptor.getResource());
1004 break;
1005 }
1006 default:
1007 LOG.warn(new Throwable());
1008 }
1009 }
1010 }
1011
1012 public void visitWelcomeFileList(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1013 {
1014 switch (context.getMetaData().getOrigin("welcome-file-list"))
1015 {
1016 case NotSet:
1017 {
1018 context.getMetaData().setOrigin("welcome-file-list", descriptor);
1019 addWelcomeFiles(context,node);
1020 break;
1021 }
1022 case WebXml:
1023 {
1024
1025 addWelcomeFiles(context,node);
1026 break;
1027 }
1028 case WebDefaults:
1029 {
1030
1031
1032 if (!(descriptor instanceof DefaultsDescriptor) && !(descriptor instanceof OverrideDescriptor) && !(descriptor instanceof FragmentDescriptor))
1033 {
1034 context.setWelcomeFiles(new String[0]);
1035 }
1036 addWelcomeFiles(context,node);
1037 break;
1038 }
1039 case WebOverride:
1040 {
1041
1042 addWelcomeFiles(context,node);
1043 break;
1044 }
1045 case WebFragment:
1046 {
1047
1048 addWelcomeFiles(context,node);
1049 break;
1050 }
1051 default:
1052 LOG.warn(new Throwable());
1053 }
1054 }
1055
1056 public void visitLocaleEncodingList(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1057 {
1058 Iterator<XmlParser.Node> iter = node.iterator("locale-encoding-mapping");
1059 while (iter.hasNext())
1060 {
1061 XmlParser.Node mapping = iter.next();
1062 String locale = mapping.getString("locale", false, true);
1063 String encoding = mapping.getString("encoding", false, true);
1064
1065 if (encoding != null)
1066 {
1067 switch (context.getMetaData().getOrigin("locale-encoding."+locale))
1068 {
1069 case NotSet:
1070 {
1071
1072 context.addLocaleEncoding(locale, encoding);
1073 context.getMetaData().setOrigin("locale-encoding."+locale, descriptor);
1074 break;
1075 }
1076 case WebXml:
1077 case WebDefaults:
1078 case WebOverride:
1079 {
1080
1081 if (!(descriptor instanceof FragmentDescriptor))
1082 {
1083 context.addLocaleEncoding(locale, encoding);
1084 context.getMetaData().setOrigin("locale-encoding."+locale, descriptor);
1085 }
1086 break;
1087 }
1088 case WebFragment:
1089 {
1090
1091 if (!encoding.equals(context.getLocaleEncoding(locale)))
1092 throw new IllegalStateException("Conflicting loacle-encoding mapping for locale "+locale+" in "+descriptor.getResource());
1093 break;
1094 }
1095 default:
1096 LOG.warn(new Throwable());
1097 }
1098 }
1099 }
1100 }
1101
1102 public void visitErrorPage(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1103 {
1104 String error = node.getString("error-code", false, true);
1105 int code=0;
1106 if (error == null || error.length() == 0)
1107 {
1108 error = node.getString("exception-type", false, true);
1109 if (error == null || error.length() == 0)
1110 error = ErrorPageErrorHandler.GLOBAL_ERROR_PAGE;
1111 }
1112 else
1113 code=Integer.valueOf(error);
1114
1115 String location = node.getString("location", false, true);
1116 ErrorPageErrorHandler handler = (ErrorPageErrorHandler)context.getErrorHandler();
1117 String originName = "error."+error;
1118 switch (context.getMetaData().getOrigin(originName))
1119 {
1120 case NotSet:
1121 {
1122
1123 if (code>0)
1124 handler.addErrorPage(code,location);
1125 else
1126 handler.addErrorPage(error,location);
1127 context.getMetaData().setOrigin("error."+error, descriptor);
1128 break;
1129 }
1130 case WebXml:
1131 case WebDefaults:
1132 case WebOverride:
1133 {
1134
1135 if (!(descriptor instanceof FragmentDescriptor))
1136 {
1137
1138 Descriptor originDescriptor = context.getMetaData().getOriginDescriptor(originName);
1139 if (descriptor == originDescriptor)
1140 throw new IllegalStateException("Duplicate error-page "+error+" at "+location);
1141
1142 if (code>0)
1143 handler.addErrorPage(code,location);
1144 else
1145 handler.addErrorPage(error,location);
1146 context.getMetaData().setOrigin("error."+error, descriptor);
1147 }
1148 break;
1149 }
1150 case WebFragment:
1151 {
1152
1153 if (!handler.getErrorPages().get(error).equals(location))
1154 throw new IllegalStateException("Conflicting error-code or exception-type "+error+" in "+descriptor.getResource());
1155 break;
1156 }
1157 default:
1158 LOG.warn(new Throwable());
1159 }
1160
1161 }
1162
1163 public void addWelcomeFiles(WebAppContext context, XmlParser.Node node)
1164 {
1165 Iterator<XmlParser.Node> iter = node.iterator("welcome-file");
1166 while (iter.hasNext())
1167 {
1168 XmlParser.Node indexNode = (XmlParser.Node) iter.next();
1169 String welcome = indexNode.toString(false, true);
1170
1171
1172 if (welcome != null && welcome.trim().length() > 0)
1173 context.setWelcomeFiles((String[])ArrayUtil.addToArray(context.getWelcomeFiles(),welcome,String.class));
1174 }
1175 }
1176
1177 public ServletMapping addServletMapping (String servletName, XmlParser.Node node, WebAppContext context, Descriptor descriptor)
1178 {
1179 ServletMapping mapping = new ServletMapping();
1180 mapping.setServletName(servletName);
1181 mapping.setDefault(descriptor instanceof DefaultsDescriptor);
1182
1183 List<String> paths = new ArrayList<String>();
1184 Iterator<XmlParser.Node> iter = node.iterator("url-pattern");
1185 while (iter.hasNext())
1186 {
1187 String p = iter.next().toString(false, true);
1188 p = normalizePattern(p);
1189
1190
1191 ListIterator<ServletMapping> listItor = _servletMappings.listIterator();
1192 boolean found = false;
1193 while (listItor.hasNext() && !found)
1194 {
1195 ServletMapping sm = listItor.next();
1196 if (sm.getPathSpecs() != null)
1197 {
1198 for (String ps:sm.getPathSpecs())
1199 {
1200
1201
1202 if (p.equals(ps) && (sm.isDefault() || servletName.equals(sm.getServletName())))
1203 {
1204 if (sm.isDefault())
1205 {
1206 if (LOG.isDebugEnabled()) LOG.debug("{} in mapping {} from defaults descriptor is overridden by ",ps,sm,servletName);
1207 }
1208 else
1209 LOG.warn("Duplicate mapping from {} to {}", p, servletName);
1210
1211
1212
1213 String[] updatedPaths = ArrayUtil.removeFromArray(sm.getPathSpecs(), ps);
1214
1215 if (updatedPaths == null || updatedPaths.length == 0)
1216 {
1217 if (LOG.isDebugEnabled()) LOG.debug("Removed empty mapping {}",sm);
1218 listItor.remove();
1219 }
1220 else
1221 {
1222 sm.setPathSpecs(updatedPaths);
1223 if (LOG.isDebugEnabled()) LOG.debug("Removed path {} from mapping {}", p,sm);
1224 }
1225 found = true;
1226 break;
1227 }
1228 }
1229 }
1230 }
1231
1232 paths.add(p);
1233 context.getMetaData().setOrigin(servletName+".servlet.mapping."+p, descriptor);
1234 }
1235
1236 mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));
1237 if (LOG.isDebugEnabled()) LOG.debug("Added mapping {} ",mapping);
1238 _servletMappings.add(mapping);
1239 return mapping;
1240 }
1241
1242 public void addFilterMapping (String filterName, XmlParser.Node node, WebAppContext context, Descriptor descriptor)
1243 {
1244 FilterMapping mapping = new FilterMapping();
1245 mapping.setFilterName(filterName);
1246
1247 List<String> paths = new ArrayList<String>();
1248 Iterator<XmlParser.Node> iter = node.iterator("url-pattern");
1249 while (iter.hasNext())
1250 {
1251 String p = iter.next().toString(false, true);
1252 p = normalizePattern(p);
1253 paths.add(p);
1254 context.getMetaData().setOrigin(filterName+".filter.mapping."+p, descriptor);
1255 }
1256 mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));
1257
1258 List<String> names = new ArrayList<String>();
1259 iter = node.iterator("servlet-name");
1260 while (iter.hasNext())
1261 {
1262 String n = ((XmlParser.Node) iter.next()).toString(false, true);
1263 names.add(n);
1264 }
1265 mapping.setServletNames((String[]) names.toArray(new String[names.size()]));
1266
1267
1268 List<DispatcherType> dispatches = new ArrayList<DispatcherType>();
1269 iter=node.iterator("dispatcher");
1270 while(iter.hasNext())
1271 {
1272 String d=((XmlParser.Node)iter.next()).toString(false,true);
1273 dispatches.add(FilterMapping.dispatch(d));
1274 }
1275
1276 if (dispatches.size()>0)
1277 mapping.setDispatcherTypes(EnumSet.copyOf(dispatches));
1278
1279 _filterMappings.add(mapping);
1280 }
1281
1282 public void visitTagLib(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1283 {
1284
1285 String uri = node.getString("taglib-uri", false, true);
1286 String location = node.getString("taglib-location", false, true);
1287
1288 context.setResourceAlias(uri, location);
1289
1290 JspConfig config = (JspConfig)context.getServletContext().getJspConfigDescriptor();
1291 if (config == null)
1292 {
1293 config = new JspConfig();
1294 context.getServletContext().setJspConfigDescriptor(config);
1295 }
1296
1297 TagLib tl = new TagLib();
1298 tl.setTaglibLocation(location);
1299 tl.setTaglibURI(uri);
1300 config.addTaglibDescriptor(tl);
1301 }
1302
1303 public void visitJspConfig(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1304 {
1305
1306 JspConfig config = (JspConfig)context.getServletContext().getJspConfigDescriptor();
1307 if (config == null)
1308 {
1309 config = new JspConfig();
1310 context.getServletContext().setJspConfigDescriptor(config);
1311 }
1312
1313
1314 for (int i = 0; i < node.size(); i++)
1315 {
1316 Object o = node.get(i);
1317 if (o instanceof XmlParser.Node && "taglib".equals(((XmlParser.Node) o).getTag()))
1318 visitTagLib(context,descriptor, (XmlParser.Node) o);
1319 }
1320
1321
1322
1323 Iterator<XmlParser.Node> iter = node.iterator("jsp-property-group");
1324 List<String> paths = new ArrayList<String>();
1325 while (iter.hasNext())
1326 {
1327
1328 JspPropertyGroup jpg = new JspPropertyGroup();
1329 config.addJspPropertyGroup(jpg);
1330 XmlParser.Node group = iter.next();
1331
1332 Iterator<XmlParser.Node> iter2 = group.iterator("url-pattern");
1333 while (iter2.hasNext())
1334 {
1335 String url = iter2.next().toString(false, true);
1336 url = normalizePattern(url);
1337 paths.add( url);
1338 jpg.addUrlPattern(url);
1339 }
1340
1341 jpg.setElIgnored(group.getString("el-ignored", false, true));
1342 jpg.setPageEncoding(group.getString("page-encoding", false, true));
1343 jpg.setScriptingInvalid(group.getString("scripting-invalid", false, true));
1344 jpg.setIsXml(group.getString("is-xml", false, true));
1345 jpg.setDeferredSyntaxAllowedAsLiteral(group.getString("deferred-syntax-allowed-as-literal", false, true));
1346 jpg.setTrimDirectiveWhitespaces(group.getString("trim-directive-whitespaces", false, true));
1347 jpg.setDefaultContentType(group.getString("default-content-type", false, true));
1348 jpg.setBuffer(group.getString("buffer", false, true));
1349 jpg.setErrorOnUndeclaredNamespace(group.getString("error-on-undeclared-namespace", false, true));
1350
1351
1352 Iterator<XmlParser.Node> preludes = group.iterator("include-prelude");
1353 while (preludes.hasNext())
1354 {
1355 String prelude = preludes.next().toString(false, true);
1356 jpg.addIncludePrelude(prelude);
1357 }
1358
1359 Iterator<XmlParser.Node> codas = group.iterator("include-coda");
1360 while (codas.hasNext())
1361 {
1362 String coda = codas.next().toString(false, true);
1363 jpg.addIncludeCoda(coda);
1364 }
1365
1366 if (LOG.isDebugEnabled()) LOG.debug(config.toString());
1367 }
1368
1369
1370 if (paths.size() > 0)
1371 {
1372 ServletMapping jspMapping = null;
1373 for (ServletMapping m: _servletMappings)
1374 {
1375 if (m.getServletName().equals("jsp"))
1376 {
1377 jspMapping = m;
1378 break;
1379 }
1380 }
1381 if (jspMapping != null)
1382 {
1383 if (jspMapping.getPathSpecs() == null)
1384 {
1385
1386 if (LOG.isDebugEnabled()) LOG.debug("Adding all paths from jsp-config to jsp servlet mapping");
1387 jspMapping.setPathSpecs(paths.toArray(new String[paths.size()]));
1388 }
1389 else
1390 {
1391
1392 ListIterator<String> piterator = paths.listIterator();
1393 while (piterator.hasNext())
1394 {
1395 String p = piterator.next();
1396 if (jspMapping.containsPathSpec(p))
1397 piterator.remove();
1398 }
1399
1400
1401 if (paths.size() > 0)
1402 {
1403 for (String p:jspMapping.getPathSpecs())
1404 paths.add(p);
1405 if (LOG.isDebugEnabled()) LOG.debug("Adding extra paths from jsp-config to jsp servlet mapping");
1406 jspMapping.setPathSpecs((String[])paths.toArray(new String[paths.size()]));
1407 }
1408 }
1409 }
1410 else
1411 {
1412
1413 ServletMapping mapping = new ServletMapping();
1414 mapping.setServletName("jsp");
1415 mapping.setPathSpecs(paths.toArray(new String[paths.size()]));
1416 _servletMappings.add(mapping);
1417 }
1418 }
1419 }
1420
1421 public void visitSecurityConstraint(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1422 {
1423 Constraint scBase = new Constraint();
1424
1425
1426
1427
1428
1429 try
1430 {
1431 XmlParser.Node auths = node.get("auth-constraint");
1432
1433 if (auths != null)
1434 {
1435 scBase.setAuthenticate(true);
1436
1437 Iterator<XmlParser.Node> iter = auths.iterator("role-name");
1438 List<String> roles = new ArrayList<String>();
1439 while (iter.hasNext())
1440 {
1441 String role = iter.next().toString(false, true);
1442 roles.add(role);
1443 }
1444 scBase.setRoles(roles.toArray(new String[roles.size()]));
1445 }
1446
1447 XmlParser.Node data = node.get("user-data-constraint");
1448 if (data != null)
1449 {
1450 data = data.get("transport-guarantee");
1451 String guarantee = data.toString(false, true).toUpperCase(Locale.ENGLISH);
1452 if (guarantee == null || guarantee.length() == 0 || "NONE".equals(guarantee))
1453 scBase.setDataConstraint(Constraint.DC_NONE);
1454 else if ("INTEGRAL".equals(guarantee))
1455 scBase.setDataConstraint(Constraint.DC_INTEGRAL);
1456 else if ("CONFIDENTIAL".equals(guarantee))
1457 scBase.setDataConstraint(Constraint.DC_CONFIDENTIAL);
1458 else
1459 {
1460 LOG.warn("Unknown user-data-constraint:" + guarantee);
1461 scBase.setDataConstraint(Constraint.DC_CONFIDENTIAL);
1462 }
1463 }
1464 Iterator<XmlParser.Node> iter = node.iterator("web-resource-collection");
1465 while (iter.hasNext())
1466 {
1467 XmlParser.Node collection = iter.next();
1468 String name = collection.getString("web-resource-name", false, true);
1469 Constraint sc = (Constraint) scBase.clone();
1470 sc.setName(name);
1471
1472 Iterator<XmlParser.Node> iter2 = collection.iterator("url-pattern");
1473 while (iter2.hasNext())
1474 {
1475 String url = iter2.next().toString(false, true);
1476 url = normalizePattern(url);
1477
1478 context.getMetaData().setOrigin("constraint.url."+url, descriptor);
1479
1480 Iterator<XmlParser.Node> methods = collection.iterator("http-method");
1481 Iterator<XmlParser.Node> ommissions = collection.iterator("http-method-omission");
1482
1483 if (methods.hasNext())
1484 {
1485 if (ommissions.hasNext())
1486 throw new IllegalStateException ("web-resource-collection cannot contain both http-method and http-method-omission");
1487
1488
1489 while (methods.hasNext())
1490 {
1491 String method = ((XmlParser.Node) methods.next()).toString(false, true);
1492 ConstraintMapping mapping = new ConstraintMapping();
1493 mapping.setMethod(method);
1494 mapping.setPathSpec(url);
1495 mapping.setConstraint(sc);
1496 ((ConstraintAware)context.getSecurityHandler()).addConstraintMapping(mapping);
1497 }
1498 }
1499 else if (ommissions.hasNext())
1500 {
1501
1502
1503 while (ommissions.hasNext())
1504 {
1505 String method = ((XmlParser.Node)ommissions.next()).toString(false, true);
1506 ConstraintMapping mapping = new ConstraintMapping();
1507 mapping.setMethodOmissions(new String[]{method});
1508 mapping.setPathSpec(url);
1509 mapping.setConstraint(sc);
1510 ((ConstraintAware)context.getSecurityHandler()).addConstraintMapping(mapping);
1511 }
1512 }
1513 else
1514 {
1515
1516 ConstraintMapping mapping = new ConstraintMapping();
1517 mapping.setPathSpec(url);
1518 mapping.setConstraint(sc);
1519 ((ConstraintAware)context.getSecurityHandler()).addConstraintMapping(mapping);
1520 }
1521 }
1522 }
1523 }
1524 catch (CloneNotSupportedException e)
1525 {
1526 LOG.warn(e);
1527 }
1528 }
1529
1530 public void visitLoginConfig(WebAppContext context, Descriptor descriptor, XmlParser.Node node) throws Exception
1531 {
1532
1533
1534
1535 XmlParser.Node method = node.get("auth-method");
1536 if (method != null)
1537 {
1538
1539 switch (context.getMetaData().getOrigin("auth-method"))
1540 {
1541 case NotSet:
1542 {
1543
1544 context.getSecurityHandler().setAuthMethod(method.toString(false, true));
1545 context.getMetaData().setOrigin("auth-method", descriptor);
1546 break;
1547 }
1548 case WebXml:
1549 case WebDefaults:
1550 case WebOverride:
1551 {
1552
1553 if (!(descriptor instanceof FragmentDescriptor))
1554 {
1555 context.getSecurityHandler().setAuthMethod(method.toString(false, true));
1556 context.getMetaData().setOrigin("auth-method", descriptor);
1557 }
1558 break;
1559 }
1560 case WebFragment:
1561 {
1562
1563 if (!context.getSecurityHandler().getAuthMethod().equals(method.toString(false, true)))
1564 throw new IllegalStateException("Conflicting auth-method value in "+descriptor.getResource());
1565 break;
1566 }
1567 default:
1568 LOG.warn(new Throwable());
1569 }
1570
1571
1572 XmlParser.Node name = node.get("realm-name");
1573 String nameStr = (name == null ? "default" : name.toString(false, true));
1574 switch (context.getMetaData().getOrigin("realm-name"))
1575 {
1576 case NotSet:
1577 {
1578
1579 context.getSecurityHandler().setRealmName(nameStr);
1580 context.getMetaData().setOrigin("realm-name", descriptor);
1581 break;
1582 }
1583 case WebXml:
1584 case WebDefaults:
1585 case WebOverride:
1586 {
1587
1588 if (!(descriptor instanceof FragmentDescriptor))
1589 {
1590 context.getSecurityHandler().setRealmName(nameStr);
1591 context.getMetaData().setOrigin("realm-name", descriptor);
1592 }
1593 break;
1594 }
1595 case WebFragment:
1596 {
1597
1598 if (!context.getSecurityHandler().getRealmName().equals(nameStr))
1599 throw new IllegalStateException("Conflicting realm-name value in "+descriptor.getResource());
1600 break;
1601 }
1602 default:
1603 LOG.warn(new Throwable());
1604 }
1605
1606 if (Constraint.__FORM_AUTH.equalsIgnoreCase(context.getSecurityHandler().getAuthMethod()))
1607 {
1608 XmlParser.Node formConfig = node.get("form-login-config");
1609 if (formConfig != null)
1610 {
1611 String loginPageName = null;
1612 XmlParser.Node loginPage = formConfig.get("form-login-page");
1613 if (loginPage != null)
1614 loginPageName = loginPage.toString(false, true);
1615 String errorPageName = null;
1616 XmlParser.Node errorPage = formConfig.get("form-error-page");
1617 if (errorPage != null)
1618 errorPageName = errorPage.toString(false, true);
1619
1620
1621 switch (context.getMetaData().getOrigin("form-login-page"))
1622 {
1623 case NotSet:
1624 {
1625
1626 context.getSecurityHandler().setInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE,loginPageName);
1627 context.getMetaData().setOrigin("form-login-page",descriptor);
1628 break;
1629 }
1630 case WebXml:
1631 case WebDefaults:
1632 case WebOverride:
1633 {
1634
1635 if (!(descriptor instanceof FragmentDescriptor))
1636 {
1637 context.getSecurityHandler().setInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE,loginPageName);
1638 context.getMetaData().setOrigin("form-login-page",descriptor);
1639 }
1640 break;
1641 }
1642 case WebFragment:
1643 {
1644
1645 if (!context.getSecurityHandler().getInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE).equals(loginPageName))
1646 throw new IllegalStateException("Conflicting form-login-page value in "+descriptor.getResource());
1647 break;
1648 }
1649 default:
1650 LOG.warn(new Throwable());
1651 }
1652
1653
1654 switch (context.getMetaData().getOrigin("form-error-page"))
1655 {
1656 case NotSet:
1657 {
1658
1659 context.getSecurityHandler().setInitParameter(FormAuthenticator.__FORM_ERROR_PAGE,errorPageName);
1660 context.getMetaData().setOrigin("form-error-page",descriptor);
1661 break;
1662 }
1663 case WebXml:
1664 case WebDefaults:
1665 case WebOverride:
1666 {
1667
1668 if (!(descriptor instanceof FragmentDescriptor))
1669 {
1670 context.getSecurityHandler().setInitParameter(FormAuthenticator.__FORM_ERROR_PAGE,errorPageName);
1671 context.getMetaData().setOrigin("form-error-page",descriptor);
1672 }
1673 break;
1674 }
1675 case WebFragment:
1676 {
1677
1678 if (!context.getSecurityHandler().getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE).equals(errorPageName))
1679 throw new IllegalStateException("Conflicting form-error-page value in "+descriptor.getResource());
1680 break;
1681 }
1682 default:
1683 LOG.warn(new Throwable());
1684 }
1685 }
1686 else
1687 {
1688 throw new IllegalStateException("!form-login-config");
1689 }
1690 }
1691 }
1692 }
1693
1694 public void visitSecurityRole(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1695 {
1696
1697 XmlParser.Node roleNode = node.get("role-name");
1698 String role = roleNode.toString(false, true);
1699 ((ConstraintAware)context.getSecurityHandler()).addRole(role);
1700 }
1701
1702 public void visitFilter(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1703 {
1704 String name = node.getString("filter-name", false, true);
1705 FilterHolder holder = _filterHolderMap.get(name);
1706 if (holder == null)
1707 {
1708 holder = context.getServletHandler().newFilterHolder(Source.DESCRIPTOR);
1709 holder.setName(name);
1710 _filterHolderMap.put(name,holder);
1711 _filterHolders.add(holder);
1712 }
1713
1714 String filter_class = node.getString("filter-class", false, true);
1715 if (filter_class != null)
1716 {
1717 ((WebDescriptor)descriptor).addClassName(filter_class);
1718
1719 switch (context.getMetaData().getOrigin(name+".filter.filter-class"))
1720 {
1721 case NotSet:
1722 {
1723
1724 holder.setClassName(filter_class);
1725 context.getMetaData().setOrigin(name+".filter.filter-class", descriptor);
1726 break;
1727 }
1728 case WebXml:
1729 case WebDefaults:
1730 case WebOverride:
1731 {
1732
1733 if (!(descriptor instanceof FragmentDescriptor))
1734 {
1735 holder.setClassName(filter_class);
1736 context.getMetaData().setOrigin(name+".filter.filter-class", descriptor);
1737 }
1738 break;
1739 }
1740 case WebFragment:
1741 {
1742
1743 if (!holder.getClassName().equals(filter_class))
1744 throw new IllegalStateException("Conflicting filter-class for filter "+name+" in "+descriptor.getResource());
1745 break;
1746 }
1747 default:
1748 LOG.warn(new Throwable());
1749 }
1750 }
1751
1752 Iterator<XmlParser.Node> iter = node.iterator("init-param");
1753 while (iter.hasNext())
1754 {
1755 XmlParser.Node paramNode = iter.next();
1756 String pname = paramNode.getString("param-name", false, true);
1757 String pvalue = paramNode.getString("param-value", false, true);
1758
1759 switch (context.getMetaData().getOrigin(name+".filter.init-param."+pname))
1760 {
1761 case NotSet:
1762 {
1763
1764 holder.setInitParameter(pname, pvalue);
1765 context.getMetaData().setOrigin(name+".filter.init-param."+pname, descriptor);
1766 break;
1767 }
1768 case WebXml:
1769 case WebDefaults:
1770 case WebOverride:
1771 {
1772
1773
1774 if (!(descriptor instanceof FragmentDescriptor))
1775 {
1776 holder.setInitParameter(pname, pvalue);
1777 context.getMetaData().setOrigin(name+".filter.init-param."+pname, descriptor);
1778 }
1779 break;
1780 }
1781 case WebFragment:
1782 {
1783
1784 if (!holder.getInitParameter(pname).equals(pvalue))
1785 throw new IllegalStateException("Mismatching init-param "+pname+"="+pvalue+" in "+descriptor.getResource());
1786 break;
1787 }
1788 default:
1789 LOG.warn(new Throwable());
1790 }
1791 }
1792
1793 String async=node.getString("async-supported",false,true);
1794 if (async!=null)
1795 holder.setAsyncSupported(async.length()==0||Boolean.valueOf(async));
1796 if (async!=null)
1797 {
1798 boolean val = async.length()==0||Boolean.valueOf(async);
1799 switch (context.getMetaData().getOrigin(name+".filter.async-supported"))
1800 {
1801 case NotSet:
1802 {
1803
1804 holder.setAsyncSupported(val);
1805 context.getMetaData().setOrigin(name+".filter.async-supported", descriptor);
1806 break;
1807 }
1808 case WebXml:
1809 case WebDefaults:
1810 case WebOverride:
1811 {
1812
1813 if (!(descriptor instanceof FragmentDescriptor))
1814 {
1815 holder.setAsyncSupported(val);
1816 context.getMetaData().setOrigin(name+".filter.async-supported", descriptor);
1817 }
1818 break;
1819 }
1820 case WebFragment:
1821 {
1822
1823 if (holder.isAsyncSupported() != val)
1824 throw new IllegalStateException("Conflicting async-supported="+async+" for filter "+name+" in "+descriptor.getResource());
1825 break;
1826 }
1827 default:
1828 LOG.warn(new Throwable());
1829 }
1830 }
1831 }
1832
1833 public void visitFilterMapping(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1834 {
1835
1836
1837
1838
1839 String filter_name = node.getString("filter-name", false, true);
1840 switch (context.getMetaData().getOrigin(filter_name+".filter.mappings"))
1841 {
1842 case NotSet:
1843 {
1844
1845 context.getMetaData().setOrigin(filter_name+".filter.mappings", descriptor);
1846 addFilterMapping(filter_name, node, context, descriptor);
1847 break;
1848 }
1849 case WebDefaults:
1850 case WebOverride:
1851 case WebXml:
1852 {
1853
1854 if (!(descriptor instanceof FragmentDescriptor))
1855 {
1856 addFilterMapping(filter_name, node, context, descriptor);
1857 }
1858 break;
1859 }
1860 case WebFragment:
1861 {
1862
1863 addFilterMapping(filter_name, node, context, descriptor);
1864 break;
1865 }
1866 default:
1867 LOG.warn(new Throwable());
1868 }
1869 }
1870
1871 public void visitListener(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1872 {
1873 String className = node.getString("listener-class", false, true);
1874 EventListener listener = null;
1875 try
1876 {
1877 if (className != null && className.length()> 0)
1878 {
1879
1880
1881 EventListener[] listeners=context.getEventListeners();
1882 if (listeners!=null)
1883 {
1884 for (EventListener l : listeners)
1885 {
1886 if (l.getClass().getName().equals(className))
1887 return;
1888 }
1889 }
1890
1891 ((WebDescriptor)descriptor).addClassName(className);
1892
1893 Class<? extends EventListener> listenerClass = (Class<? extends EventListener>)context.loadClass(className);
1894 listener = newListenerInstance(context,listenerClass);
1895 if (!(listener instanceof EventListener))
1896 {
1897 LOG.warn("Not an EventListener: " + listener);
1898 return;
1899 }
1900 context.addEventListener(listener);
1901 context.getMetaData().setOrigin(className+".listener", descriptor);
1902
1903 }
1904 }
1905 catch (Exception e)
1906 {
1907 LOG.warn("Could not instantiate listener " + className, e);
1908 return;
1909 }
1910 }
1911
1912 public void visitDistributable(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1913 {
1914
1915
1916
1917 ((WebDescriptor)descriptor).setDistributable(true);
1918 }
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931 public void visitDenyUncoveredHttpMethods(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
1932 {
1933 ((ConstraintAware)context.getSecurityHandler()).setDenyUncoveredHttpMethods(true);
1934 }
1935
1936 public EventListener newListenerInstance(WebAppContext context,Class<? extends EventListener> clazz) throws Exception
1937 {
1938 ListenerHolder h = context.getServletHandler().newListenerHolder(Source.DESCRIPTOR);
1939 EventListener l = context.getServletContext().createInstance(clazz);
1940 h.setListener(l);
1941 context.getServletHandler().addListener(h);
1942 return l;
1943
1944 }
1945
1946 public String normalizePattern(String p)
1947 {
1948 if (p != null && p.length() > 0 && !p.startsWith("/") && !p.startsWith("*")) return "/" + p;
1949 return p;
1950 }
1951 }