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