1
17 package org.apache.tomcat.util.descriptor.web;
18
19 import java.io.UnsupportedEncodingException;
20 import java.net.URL;
21 import java.net.URLEncoder;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.EnumSet;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.LinkedHashMap;
29 import java.util.LinkedHashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Map.Entry;
33 import java.util.Set;
34
35 import javax.servlet.DispatcherType;
36 import javax.servlet.ServletContext;
37 import javax.servlet.SessionTrackingMode;
38 import javax.servlet.descriptor.JspConfigDescriptor;
39 import javax.servlet.descriptor.JspPropertyGroupDescriptor;
40 import javax.servlet.descriptor.TaglibDescriptor;
41
42 import org.apache.juli.logging.Log;
43 import org.apache.juli.logging.LogFactory;
44 import org.apache.tomcat.util.buf.B2CConverter;
45 import org.apache.tomcat.util.buf.UDecoder;
46 import org.apache.tomcat.util.descriptor.XmlIdentifiers;
47 import org.apache.tomcat.util.digester.DocumentProperties;
48 import org.apache.tomcat.util.res.StringManager;
49 import org.apache.tomcat.util.security.Escape;
50
51
59 public class WebXml extends XmlEncodingBase implements DocumentProperties.Charset {
60
61 protected static final String ORDER_OTHERS =
62 "org.apache.catalina.order.others";
63
64 private static final StringManager sm =
65 StringManager.getManager(Constants.PACKAGE_NAME);
66
67 private final Log log = LogFactory.getLog(WebXml.class);
68
69
74 private boolean overridable = false;
75 public boolean isOverridable() {
76 return overridable;
77 }
78 public void setOverridable(boolean overridable) {
79 this.overridable = overridable;
80 }
81
82
87 private boolean duplicated = false;
88 public boolean isDuplicated() {
89 return duplicated;
90 }
91 public void setDuplicated(boolean duplicated) {
92 this.duplicated = duplicated;
93 }
94
95
99 private Set<String> absoluteOrdering = null;
100 public void createAbsoluteOrdering() {
101 if (absoluteOrdering == null) {
102 absoluteOrdering = new LinkedHashSet<>();
103 }
104 }
105 public void addAbsoluteOrdering(String fragmentName) {
106 createAbsoluteOrdering();
107 absoluteOrdering.add(fragmentName);
108 }
109 public void addAbsoluteOrderingOthers() {
110 createAbsoluteOrdering();
111 absoluteOrdering.add(ORDER_OTHERS);
112 }
113 public Set<String> getAbsoluteOrdering() {
114 return absoluteOrdering;
115 }
116
117
121 private final Set<String> after = new LinkedHashSet<>();
122 public void addAfterOrdering(String fragmentName) {
123 after.add(fragmentName);
124 }
125 public void addAfterOrderingOthers() {
126 if (before.contains(ORDER_OTHERS)) {
127 throw new IllegalArgumentException(sm.getString(
128 "webXml.multipleOther"));
129 }
130 after.add(ORDER_OTHERS);
131 }
132 public Set<String> getAfterOrdering() { return after; }
133
134 private final Set<String> before = new LinkedHashSet<>();
135 public void addBeforeOrdering(String fragmentName) {
136 before.add(fragmentName);
137 }
138 public void addBeforeOrderingOthers() {
139 if (after.contains(ORDER_OTHERS)) {
140 throw new IllegalArgumentException(sm.getString(
141 "webXml.multipleOther"));
142 }
143 before.add(ORDER_OTHERS);
144 }
145 public Set<String> getBeforeOrdering() { return before; }
146
147
148
149 public String getVersion() {
150 StringBuilder sb = new StringBuilder(3);
151 sb.append(majorVersion);
152 sb.append('.');
153 sb.append(minorVersion);
154 return sb.toString();
155 }
156
160 public void setVersion(String version) {
161 if (version == null) {
162 return;
163 }
164 switch (version) {
165 case "2.4":
166 majorVersion = 2;
167 minorVersion = 4;
168 break;
169 case "2.5":
170 majorVersion = 2;
171 minorVersion = 5;
172 break;
173 case "3.0":
174 majorVersion = 3;
175 minorVersion = 0;
176 break;
177 case "3.1":
178 majorVersion = 3;
179 minorVersion = 1;
180 break;
181 case "4.0":
182 majorVersion = 4;
183 minorVersion = 0;
184 break;
185 default:
186 log.warn(sm.getString("webXml.version.unknown", version));
187 }
188 }
189
190
191
192
193 private String publicId = null;
194 public String getPublicId() { return publicId; }
195 public void setPublicId(String publicId) {
196
197 if (publicId == null) {
198 return;
199 }
200 switch (publicId) {
201 case XmlIdentifiers.WEB_22_PUBLIC:
202 majorVersion = 2;
203 minorVersion = 2;
204 this.publicId = publicId;
205 break;
206 case XmlIdentifiers.WEB_23_PUBLIC:
207 majorVersion = 2;
208 minorVersion = 3;
209 this.publicId = publicId;
210 break;
211 default:
212 log.warn(sm.getString("webXml.unrecognisedPublicId", publicId));
213 break;
214 }
215 }
216
217
218 private boolean metadataComplete = false;
219 public boolean isMetadataComplete() { return metadataComplete; }
220 public void setMetadataComplete(boolean metadataComplete) {
221 this.metadataComplete = metadataComplete; }
222
223
224 private String name = null;
225 public String getName() { return name; }
226 public void setName(String name) {
227 if (ORDER_OTHERS.equalsIgnoreCase(name)) {
228
229 log.warn(sm.getString("webXml.reservedName", name));
230 } else {
231 this.name = name;
232 }
233 }
234
235
236
237 private int majorVersion = 4;
238 private int minorVersion = 0;
239 public int getMajorVersion() { return majorVersion; }
240 public int getMinorVersion() { return minorVersion; }
241
242
243
244
245
246
247
248 private String displayName = null;
249 public String getDisplayName() { return displayName; }
250 public void setDisplayName(String displayName) {
251 this.displayName = displayName;
252 }
253
254
255 private boolean distributable = false;
256 public boolean isDistributable() { return distributable; }
257 public void setDistributable(boolean distributable) {
258 this.distributable = distributable;
259 }
260
261
262 private boolean denyUncoveredHttpMethods = false;
263 public boolean getDenyUncoveredHttpMethods() {
264 return denyUncoveredHttpMethods;
265 }
266 public void setDenyUncoveredHttpMethods(boolean denyUncoveredHttpMethods) {
267 this.denyUncoveredHttpMethods = denyUncoveredHttpMethods;
268 }
269
270
271
272 private final Map<String,String> contextParams = new HashMap<>();
273 public void addContextParam(String param, String value) {
274 contextParams.put(param, value);
275 }
276 public Map<String,String> getContextParams() { return contextParams; }
277
278
279
280
281
282
283 private final Map<String,FilterDef> filters = new LinkedHashMap<>();
284 public void addFilter(FilterDef filter) {
285 if (filters.containsKey(filter.getFilterName())) {
286
287 throw new IllegalArgumentException(
288 sm.getString("webXml.duplicateFilter",
289 filter.getFilterName()));
290 }
291 filters.put(filter.getFilterName(), filter);
292 }
293 public Map<String,FilterDef> getFilters() { return filters; }
294
295
296 private final Set<FilterMap> filterMaps = new LinkedHashSet<>();
297 private final Set<String> filterMappingNames = new HashSet<>();
298 public void addFilterMapping(FilterMap filterMap) {
299 filterMaps.add(filterMap);
300 filterMappingNames.add(filterMap.getFilterName());
301 }
302 public Set<FilterMap> getFilterMappings() { return filterMaps; }
303
304
305
306
307
308 private final Set<String> listeners = new LinkedHashSet<>();
309 public void addListener(String className) {
310 listeners.add(className);
311 }
312 public Set<String> getListeners() { return listeners; }
313
314
315
316
317
318
319
320 private final Map<String,ServletDef> servlets = new HashMap<>();
321 public void addServlet(ServletDef servletDef) {
322 servlets.put(servletDef.getServletName(), servletDef);
323 if (overridable) {
324 servletDef.setOverridable(overridable);
325 }
326 }
327 public Map<String,ServletDef> getServlets() { return servlets; }
328
329
330
331
332 private final Map<String,String> servletMappings = new HashMap<>();
333 private final Set<String> servletMappingNames = new HashSet<>();
334 public void addServletMapping(String urlPattern, String servletName) {
335 addServletMappingDecoded(UDecoder.URLDecode(urlPattern, getCharset()), servletName);
336 }
337 public void addServletMappingDecoded(String urlPattern, String servletName) {
338 String oldServletName = servletMappings.put(urlPattern, servletName);
339 if (oldServletName != null) {
340
341
342 throw new IllegalArgumentException(sm.getString(
343 "webXml.duplicateServletMapping", oldServletName,
344 servletName, urlPattern));
345 }
346 servletMappingNames.add(servletName);
347 }
348 public Map<String,String> getServletMappings() { return servletMappings; }
349
350
351
352 private SessionConfig sessionConfig = new SessionConfig();
353 public void setSessionConfig(SessionConfig sessionConfig) {
354 this.sessionConfig = sessionConfig;
355 }
356 public SessionConfig getSessionConfig() { return sessionConfig; }
357
358
359 private final Map<String,String> mimeMappings = new HashMap<>();
360 public void addMimeMapping(String extension, String mimeType) {
361 mimeMappings.put(extension, mimeType);
362 }
363 public Map<String,String> getMimeMappings() { return mimeMappings; }
364
365
366 private boolean replaceWelcomeFiles = false;
367 private boolean alwaysAddWelcomeFiles = true;
368
374 public void setReplaceWelcomeFiles(boolean replaceWelcomeFiles) {
375 this.replaceWelcomeFiles = replaceWelcomeFiles;
376 }
377
382 public void setAlwaysAddWelcomeFiles(boolean alwaysAddWelcomeFiles) {
383 this.alwaysAddWelcomeFiles = alwaysAddWelcomeFiles;
384 }
385
386
387 private final Set<String> welcomeFiles = new LinkedHashSet<>();
388 public void addWelcomeFile(String welcomeFile) {
389 if (replaceWelcomeFiles) {
390 welcomeFiles.clear();
391 replaceWelcomeFiles = false;
392 }
393 welcomeFiles.add(welcomeFile);
394 }
395 public Set<String> getWelcomeFiles() { return welcomeFiles; }
396
397
398 private final Map<String,ErrorPage> errorPages = new HashMap<>();
399 public void addErrorPage(ErrorPage errorPage) {
400 errorPages.put(errorPage.getName(), errorPage);
401 }
402 public Map<String,ErrorPage> getErrorPages() { return errorPages; }
403
404
405
406 private final Map<String,String> taglibs = new HashMap<>();
407 public void addTaglib(String uri, String location) {
408 if (taglibs.containsKey(uri)) {
409
410 throw new IllegalArgumentException(
411 sm.getString("webXml.duplicateTaglibUri", uri));
412 }
413 taglibs.put(uri, location);
414 }
415 public Map<String,String> getTaglibs() { return taglibs; }
416
417
418 private final Set<JspPropertyGroup> jspPropertyGroups = new LinkedHashSet<>();
419 public void addJspPropertyGroup(JspPropertyGroup propertyGroup) {
420 propertyGroup.setCharset(getCharset());
421 jspPropertyGroups.add(propertyGroup);
422 }
423 public Set<JspPropertyGroup> getJspPropertyGroups() {
424 return jspPropertyGroups;
425 }
426
427
428
429
430 private final Set<SecurityConstraint> securityConstraints = new HashSet<>();
431 public void addSecurityConstraint(SecurityConstraint securityConstraint) {
432 securityConstraint.setCharset(getCharset());
433 securityConstraints.add(securityConstraint);
434 }
435 public Set<SecurityConstraint> getSecurityConstraints() {
436 return securityConstraints;
437 }
438
439
440
441 private LoginConfig loginConfig = null;
442 public void setLoginConfig(LoginConfig loginConfig) {
443 this.loginConfig = loginConfig;
444 }
445 public LoginConfig getLoginConfig() { return loginConfig; }
446
447
448
449 private final Set<String> securityRoles = new HashSet<>();
450 public void addSecurityRole(String securityRole) {
451 securityRoles.add(securityRole);
452 }
453 public Set<String> getSecurityRoles() { return securityRoles; }
454
455
456
457 private final Map<String,ContextEnvironment> envEntries = new HashMap<>();
458 public void addEnvEntry(ContextEnvironment envEntry) {
459 if (envEntries.containsKey(envEntry.getName())) {
460
461 throw new IllegalArgumentException(
462 sm.getString("webXml.duplicateEnvEntry",
463 envEntry.getName()));
464 }
465 envEntries.put(envEntry.getName(),envEntry);
466 }
467 public Map<String,ContextEnvironment> getEnvEntries() { return envEntries; }
468
469
470
471 private final Map<String,ContextEjb> ejbRefs = new HashMap<>();
472 public void addEjbRef(ContextEjb ejbRef) {
473 ejbRefs.put(ejbRef.getName(),ejbRef);
474 }
475 public Map<String,ContextEjb> getEjbRefs() { return ejbRefs; }
476
477
478
479 private final Map<String,ContextLocalEjb> ejbLocalRefs = new HashMap<>();
480 public void addEjbLocalRef(ContextLocalEjb ejbLocalRef) {
481 ejbLocalRefs.put(ejbLocalRef.getName(),ejbLocalRef);
482 }
483 public Map<String,ContextLocalEjb> getEjbLocalRefs() {
484 return ejbLocalRefs;
485 }
486
487
488
489
490
491 private final Map<String,ContextService> serviceRefs = new HashMap<>();
492 public void addServiceRef(ContextService serviceRef) {
493 serviceRefs.put(serviceRef.getName(), serviceRef);
494 }
495 public Map<String,ContextService> getServiceRefs() { return serviceRefs; }
496
497
498
499 private final Map<String,ContextResource> resourceRefs = new HashMap<>();
500 public void addResourceRef(ContextResource resourceRef) {
501 if (resourceRefs.containsKey(resourceRef.getName())) {
502
503 throw new IllegalArgumentException(
504 sm.getString("webXml.duplicateResourceRef",
505 resourceRef.getName()));
506 }
507 resourceRefs.put(resourceRef.getName(), resourceRef);
508 }
509 public Map<String,ContextResource> getResourceRefs() {
510 return resourceRefs;
511 }
512
513
514
515 private final Map<String,ContextResourceEnvRef> resourceEnvRefs = new HashMap<>();
516 public void addResourceEnvRef(ContextResourceEnvRef resourceEnvRef) {
517 if (resourceEnvRefs.containsKey(resourceEnvRef.getName())) {
518
519 throw new IllegalArgumentException(
520 sm.getString("webXml.duplicateResourceEnvRef",
521 resourceEnvRef.getName()));
522 }
523 resourceEnvRefs.put(resourceEnvRef.getName(), resourceEnvRef);
524 }
525 public Map<String,ContextResourceEnvRef> getResourceEnvRefs() {
526 return resourceEnvRefs;
527 }
528
529
530
531 private final Map<String,MessageDestinationRef> messageDestinationRefs =
532 new HashMap<>();
533 public void addMessageDestinationRef(
534 MessageDestinationRef messageDestinationRef) {
535 if (messageDestinationRefs.containsKey(
536 messageDestinationRef.getName())) {
537
538
539 throw new IllegalArgumentException(sm.getString(
540 "webXml.duplicateMessageDestinationRef",
541 messageDestinationRef.getName()));
542 }
543 messageDestinationRefs.put(messageDestinationRef.getName(),
544 messageDestinationRef);
545 }
546 public Map<String,MessageDestinationRef> getMessageDestinationRefs() {
547 return messageDestinationRefs;
548 }
549
550
551
552
553
554 private final Map<String,MessageDestination> messageDestinations =
555 new HashMap<>();
556 public void addMessageDestination(
557 MessageDestination messageDestination) {
558 if (messageDestinations.containsKey(
559 messageDestination.getName())) {
560
561
562 throw new IllegalArgumentException(
563 sm.getString("webXml.duplicateMessageDestination",
564 messageDestination.getName()));
565 }
566 messageDestinations.put(messageDestination.getName(),
567 messageDestination);
568 }
569 public Map<String,MessageDestination> getMessageDestinations() {
570 return messageDestinations;
571 }
572
573
574 private final Map<String,String> localeEncodingMappings = new HashMap<>();
575 public void addLocaleEncodingMapping(String locale, String encoding) {
576 localeEncodingMappings.put(locale, encoding);
577 }
578 public Map<String,String> getLocaleEncodingMappings() {
579 return localeEncodingMappings;
580 }
581
582
583 private Map<String, String> postConstructMethods = new HashMap<>();
584 public void addPostConstructMethods(String clazz, String method) {
585 if (!postConstructMethods.containsKey(clazz)) {
586 postConstructMethods.put(clazz, method);
587 }
588 }
589 public Map<String, String> getPostConstructMethods() {
590 return postConstructMethods;
591 }
592
593
594 private Map<String, String> preDestroyMethods = new HashMap<>();
595 public void addPreDestroyMethods(String clazz, String method) {
596 if (!preDestroyMethods.containsKey(clazz)) {
597 preDestroyMethods.put(clazz, method);
598 }
599 }
600 public Map<String, String> getPreDestroyMethods() {
601 return preDestroyMethods;
602 }
603
604 public JspConfigDescriptor getJspConfigDescriptor() {
605 if (jspPropertyGroups.isEmpty() && taglibs.isEmpty()) {
606 return null;
607 }
608
609 Collection<JspPropertyGroupDescriptor> descriptors =
610 new ArrayList<>(jspPropertyGroups.size());
611 for (JspPropertyGroup jspPropertyGroup : jspPropertyGroups) {
612 JspPropertyGroupDescriptor descriptor =
613 new JspPropertyGroupDescriptorImpl(jspPropertyGroup);
614 descriptors.add(descriptor);
615
616 }
617
618 Collection<TaglibDescriptor> tlds = new HashSet<>(taglibs.size());
619 for (Entry<String, String> entry : taglibs.entrySet()) {
620 TaglibDescriptor descriptor = new TaglibDescriptorImpl(
621 entry.getValue(), entry.getKey());
622 tlds.add(descriptor);
623 }
624 return new JspConfigDescriptorImpl(descriptors, tlds);
625 }
626
627 private String requestCharacterEncoding;
628 public String getRequestCharacterEncoding() {
629 return requestCharacterEncoding;
630 }
631 public void setRequestCharacterEncoding(String requestCharacterEncoding) {
632 if (requestCharacterEncoding != null) {
633 try {
634 B2CConverter.getCharset(requestCharacterEncoding);
635 } catch (UnsupportedEncodingException e) {
636 throw new IllegalArgumentException(e);
637 }
638 }
639 this.requestCharacterEncoding = requestCharacterEncoding;
640 }
641
642 private String responseCharacterEncoding;
643 public String getResponseCharacterEncoding() {
644 return responseCharacterEncoding;
645 }
646 public void setResponseCharacterEncoding(String responseCharacterEncoding) {
647 if (responseCharacterEncoding != null) {
648 try {
649 B2CConverter.getCharset(responseCharacterEncoding);
650 } catch (UnsupportedEncodingException e) {
651 throw new IllegalArgumentException(e);
652 }
653 }
654 this.responseCharacterEncoding = responseCharacterEncoding;
655 }
656
657
658
659
660 private URL uRL = null;
661 public void setURL(URL url) { this.uRL = url; }
662 public URL getURL() { return uRL; }
663
664
665 private String jarName = null;
666 public void setJarName(String jarName) { this.jarName = jarName; }
667 public String getJarName() { return jarName; }
668
669
670
671 private boolean webappJar = true;
672 public void setWebappJar(boolean webappJar) { this.webappJar = webappJar; }
673 public boolean getWebappJar() { return webappJar; }
674
675
676 private boolean delegate = false;
677 public boolean getDelegate() { return delegate; }
678 public void setDelegate(boolean delegate) { this.delegate = delegate; }
679
680 @Override
681 public String toString() {
682 StringBuilder buf = new StringBuilder(32);
683 buf.append("Name: ");
684 buf.append(getName());
685 buf.append(", URL: ");
686 buf.append(getURL());
687 return buf.toString();
688 }
689
690 private static final String INDENT2 = " ";
691 private static final String INDENT4 = " ";
692 private static final String INDENT6 = " ";
693
694
700 public String toXml() {
701 StringBuilder sb = new StringBuilder(2048);
702
703
704
705
706
707
708
709
710
711
712
713
714 sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
715
716
717 if (publicId != null) {
718 sb.append("<!DOCTYPE web-app PUBLIC\n");
719 sb.append(" \"");
720 sb.append(publicId);
721 sb.append("\"\n");
722 sb.append(" \"");
723 if (XmlIdentifiers.WEB_22_PUBLIC.equals(publicId)) {
724 sb.append(XmlIdentifiers.WEB_22_SYSTEM);
725 } else {
726 sb.append(XmlIdentifiers.WEB_23_SYSTEM);
727 }
728 sb.append("\">\n");
729 sb.append("<web-app>");
730 } else {
731 String javaeeNamespace = null;
732 String webXmlSchemaLocation = null;
733 String version = getVersion();
734 if ("2.4".equals(version)) {
735 javaeeNamespace = XmlIdentifiers.JAVAEE_1_4_NS;
736 webXmlSchemaLocation = XmlIdentifiers.WEB_24_XSD;
737 } else if ("2.5".equals(version)) {
738 javaeeNamespace = XmlIdentifiers.JAVAEE_5_NS;
739 webXmlSchemaLocation = XmlIdentifiers.WEB_25_XSD;
740 } else if ("3.0".equals(version)) {
741 javaeeNamespace = XmlIdentifiers.JAVAEE_6_NS;
742 webXmlSchemaLocation = XmlIdentifiers.WEB_30_XSD;
743 } else if ("3.1".equals(version)) {
744 javaeeNamespace = XmlIdentifiers.JAVAEE_7_NS;
745 webXmlSchemaLocation = XmlIdentifiers.WEB_31_XSD;
746 } else if ("4.0".equals(version)) {
747 javaeeNamespace = XmlIdentifiers.JAVAEE_8_NS;
748 webXmlSchemaLocation = XmlIdentifiers.WEB_40_XSD;
749 }
750 sb.append("<web-app xmlns=\"");
751 sb.append(javaeeNamespace);
752 sb.append("\"\n");
753 sb.append(" xmlns:xsi=");
754 sb.append("\"http:
755 sb.append(" xsi:schemaLocation=\"");
756 sb.append(javaeeNamespace);
757 sb.append(" ");
758 sb.append(webXmlSchemaLocation);
759 sb.append("\"\n");
760 sb.append(" version=\"");
761 sb.append(getVersion());
762 sb.append("\"");
763 if ("2.4".equals(version)) {
764 sb.append(">\n\n");
765 } else {
766 sb.append("\n metadata-complete=\"true\">\n\n");
767 }
768 }
769
770 appendElement(sb, INDENT2, "display-name", displayName);
771
772 if (isDistributable()) {
773 sb.append(" <distributable/>\n\n");
774 }
775
776 for (Map.Entry<String, String> entry : contextParams.entrySet()) {
777 sb.append(" <context-param>\n");
778 appendElement(sb, INDENT4, "param-name", entry.getKey());
779 appendElement(sb, INDENT4, "param-value", entry.getValue());
780 sb.append(" </context-param>\n");
781 }
782 sb.append('\n');
783
784
785 if (getMajorVersion() > 2 || getMinorVersion() > 2) {
786 for (Map.Entry<String, FilterDef> entry : filters.entrySet()) {
787 FilterDef filterDef = entry.getValue();
788 sb.append(" <filter>\n");
789 appendElement(sb, INDENT4, "description",
790 filterDef.getDescription());
791 appendElement(sb, INDENT4, "display-name",
792 filterDef.getDisplayName());
793 appendElement(sb, INDENT4, "filter-name",
794 filterDef.getFilterName());
795 appendElement(sb, INDENT4, "filter-class",
796 filterDef.getFilterClass());
797
798 if (getMajorVersion() != 2) {
799 appendElement(sb, INDENT4, "async-supported",
800 filterDef.getAsyncSupported());
801 }
802 for (Map.Entry<String, String> param :
803 filterDef.getParameterMap().entrySet()) {
804 sb.append(" <init-param>\n");
805 appendElement(sb, INDENT6, "param-name", param.getKey());
806 appendElement(sb, INDENT6, "param-value", param.getValue());
807 sb.append(" </init-param>\n");
808 }
809 sb.append(" </filter>\n");
810 }
811 sb.append('\n');
812
813 for (FilterMap filterMap : filterMaps) {
814 sb.append(" <filter-mapping>\n");
815 appendElement(sb, INDENT4, "filter-name",
816 filterMap.getFilterName());
817 if (filterMap.getMatchAllServletNames()) {
818 sb.append(" <servlet-name>*</servlet-name>\n");
819 } else {
820 for (String servletName : filterMap.getServletNames()) {
821 appendElement(sb, INDENT4, "servlet-name", servletName);
822 }
823 }
824 if (filterMap.getMatchAllUrlPatterns()) {
825 sb.append(" <url-pattern>*</url-pattern>\n");
826 } else {
827 for (String urlPattern : filterMap.getURLPatterns()) {
828 appendElement(sb, INDENT4, "url-pattern", encodeUrl(urlPattern));
829 }
830 }
831
832 if (getMajorVersion() > 2 || getMinorVersion() > 3) {
833 for (String dispatcher : filterMap.getDispatcherNames()) {
834 if (getMajorVersion() == 2 &&
835 DispatcherType.ASYNC.name().equals(dispatcher)) {
836 continue;
837 }
838 appendElement(sb, INDENT4, "dispatcher", dispatcher);
839 }
840 }
841 sb.append(" </filter-mapping>\n");
842 }
843 sb.append('\n');
844 }
845
846
847 if (getMajorVersion() > 2 || getMinorVersion() > 2) {
848 for (String listener : listeners) {
849 sb.append(" <listener>\n");
850 appendElement(sb, INDENT4, "listener-class", listener);
851 sb.append(" </listener>\n");
852 }
853 sb.append('\n');
854 }
855
856 for (Map.Entry<String, ServletDef> entry : servlets.entrySet()) {
857 ServletDef servletDef = entry.getValue();
858 sb.append(" <servlet>\n");
859 appendElement(sb, INDENT4, "description",
860 servletDef.getDescription());
861 appendElement(sb, INDENT4, "display-name",
862 servletDef.getDisplayName());
863 appendElement(sb, INDENT4, "servlet-name", entry.getKey());
864 appendElement(sb, INDENT4, "servlet-class",
865 servletDef.getServletClass());
866 appendElement(sb, INDENT4, "jsp-file", servletDef.getJspFile());
867 for (Map.Entry<String, String> param :
868 servletDef.getParameterMap().entrySet()) {
869 sb.append(" <init-param>\n");
870 appendElement(sb, INDENT6, "param-name", param.getKey());
871 appendElement(sb, INDENT6, "param-value", param.getValue());
872 sb.append(" </init-param>\n");
873 }
874 appendElement(sb, INDENT4, "load-on-startup",
875 servletDef.getLoadOnStartup());
876 appendElement(sb, INDENT4, "enabled", servletDef.getEnabled());
877
878 if (getMajorVersion() != 2) {
879 appendElement(sb, INDENT4, "async-supported",
880 servletDef.getAsyncSupported());
881 }
882
883 if (getMajorVersion() > 2 || getMinorVersion() > 2) {
884 if (servletDef.getRunAs() != null) {
885 sb.append(" <run-as>\n");
886 appendElement(sb, INDENT6, "role-name", servletDef.getRunAs());
887 sb.append(" </run-as>\n");
888 }
889 }
890 for (SecurityRoleRef roleRef : servletDef.getSecurityRoleRefs()) {
891 sb.append(" <security-role-ref>\n");
892 appendElement(sb, INDENT6, "role-name", roleRef.getName());
893 appendElement(sb, INDENT6, "role-link", roleRef.getLink());
894 sb.append(" </security-role-ref>\n");
895 }
896
897 if (getMajorVersion() != 2) {
898 MultipartDef multipartDef = servletDef.getMultipartDef();
899 if (multipartDef != null) {
900 sb.append(" <multipart-config>\n");
901 appendElement(sb, INDENT6, "location",
902 multipartDef.getLocation());
903 appendElement(sb, INDENT6, "max-file-size",
904 multipartDef.getMaxFileSize());
905 appendElement(sb, INDENT6, "max-request-size",
906 multipartDef.getMaxRequestSize());
907 appendElement(sb, INDENT6, "file-size-threshold",
908 multipartDef.getFileSizeThreshold());
909 sb.append(" </multipart-config>\n");
910 }
911 }
912 sb.append(" </servlet>\n");
913 }
914 sb.append('\n');
915
916 for (Map.Entry<String, String> entry : servletMappings.entrySet()) {
917 sb.append(" <servlet-mapping>\n");
918 appendElement(sb, INDENT4, "servlet-name", entry.getValue());
919 appendElement(sb, INDENT4, "url-pattern", encodeUrl(entry.getKey()));
920 sb.append(" </servlet-mapping>\n");
921 }
922 sb.append('\n');
923
924 if (sessionConfig != null) {
925 sb.append(" <session-config>\n");
926 appendElement(sb, INDENT4, "session-timeout",
927 sessionConfig.getSessionTimeout());
928 if (majorVersion >= 3) {
929 sb.append(" <cookie-config>\n");
930 appendElement(sb, INDENT6, "name", sessionConfig.getCookieName());
931 appendElement(sb, INDENT6, "domain",
932 sessionConfig.getCookieDomain());
933 appendElement(sb, INDENT6, "path", sessionConfig.getCookiePath());
934 appendElement(sb, INDENT6, "comment",
935 sessionConfig.getCookieComment());
936 appendElement(sb, INDENT6, "http-only",
937 sessionConfig.getCookieHttpOnly());
938 appendElement(sb, INDENT6, "secure",
939 sessionConfig.getCookieSecure());
940 appendElement(sb, INDENT6, "max-age",
941 sessionConfig.getCookieMaxAge());
942 sb.append(" </cookie-config>\n");
943 for (SessionTrackingMode stm :
944 sessionConfig.getSessionTrackingModes()) {
945 appendElement(sb, INDENT4, "tracking-mode", stm.name());
946 }
947 }
948 sb.append(" </session-config>\n\n");
949 }
950
951 for (Map.Entry<String, String> entry : mimeMappings.entrySet()) {
952 sb.append(" <mime-mapping>\n");
953 appendElement(sb, INDENT4, "extension", entry.getKey());
954 appendElement(sb, INDENT4, "mime-type", entry.getValue());
955 sb.append(" </mime-mapping>\n");
956 }
957 sb.append('\n');
958
959 if (welcomeFiles.size() > 0) {
960 sb.append(" <welcome-file-list>\n");
961 for (String welcomeFile : welcomeFiles) {
962 appendElement(sb, INDENT4, "welcome-file", welcomeFile);
963 }
964 sb.append(" </welcome-file-list>\n\n");
965 }
966
967 for (ErrorPage errorPage : errorPages.values()) {
968 String exceptionType = errorPage.getExceptionType();
969 int errorCode = errorPage.getErrorCode();
970
971 if (exceptionType == null && errorCode == 0 && getMajorVersion() == 2) {
972
973 continue;
974 }
975 sb.append(" <error-page>\n");
976 if (errorPage.getExceptionType() != null) {
977 appendElement(sb, INDENT4, "exception-type", exceptionType);
978 } else if (errorPage.getErrorCode() > 0) {
979 appendElement(sb, INDENT4, "error-code",
980 Integer.toString(errorCode));
981 }
982 appendElement(sb, INDENT4, "location", errorPage.getLocation());
983 sb.append(" </error-page>\n");
984 }
985 sb.append('\n');
986
987
988
989 if (taglibs.size() > 0 || jspPropertyGroups.size() > 0) {
990 if (getMajorVersion() > 2 || getMinorVersion() > 3) {
991 sb.append(" <jsp-config>\n");
992 }
993 for (Map.Entry<String, String> entry : taglibs.entrySet()) {
994 sb.append(" <taglib>\n");
995 appendElement(sb, INDENT6, "taglib-uri", entry.getKey());
996 appendElement(sb, INDENT6, "taglib-location", entry.getValue());
997 sb.append(" </taglib>\n");
998 }
999 if (getMajorVersion() > 2 || getMinorVersion() > 3) {
1000 for (JspPropertyGroup jpg : jspPropertyGroups) {
1001 sb.append(" <jsp-property-group>\n");
1002 for (String urlPattern : jpg.getUrlPatterns()) {
1003 appendElement(sb, INDENT6, "url-pattern", encodeUrl(urlPattern));
1004 }
1005 appendElement(sb, INDENT6, "el-ignored", jpg.getElIgnored());
1006 appendElement(sb, INDENT6, "page-encoding",
1007 jpg.getPageEncoding());
1008 appendElement(sb, INDENT6, "scripting-invalid",
1009 jpg.getScriptingInvalid());
1010 appendElement(sb, INDENT6, "is-xml", jpg.getIsXml());
1011 for (String prelude : jpg.getIncludePreludes()) {
1012 appendElement(sb, INDENT6, "include-prelude", prelude);
1013 }
1014 for (String coda : jpg.getIncludeCodas()) {
1015 appendElement(sb, INDENT6, "include-coda", coda);
1016 }
1017 appendElement(sb, INDENT6, "deferred-syntax-allowed-as-literal",
1018 jpg.getDeferredSyntax());
1019 appendElement(sb, INDENT6, "trim-directive-whitespaces",
1020 jpg.getTrimWhitespace());
1021 appendElement(sb, INDENT6, "default-content-type",
1022 jpg.getDefaultContentType());
1023 appendElement(sb, INDENT6, "buffer", jpg.getBuffer());
1024 appendElement(sb, INDENT6, "error-on-undeclared-namespace",
1025 jpg.getErrorOnUndeclaredNamespace());
1026 sb.append(" </jsp-property-group>\n");
1027 }
1028 sb.append(" </jsp-config>\n\n");
1029 }
1030 }
1031
1032
1033 if (getMajorVersion() > 2 || getMinorVersion() > 2) {
1034 for (ContextResourceEnvRef resourceEnvRef : resourceEnvRefs.values()) {
1035 sb.append(" <resource-env-ref>\n");
1036 appendElement(sb, INDENT4, "description",
1037 resourceEnvRef.getDescription());
1038 appendElement(sb, INDENT4, "resource-env-ref-name",
1039 resourceEnvRef.getName());
1040 appendElement(sb, INDENT4, "resource-env-ref-type",
1041 resourceEnvRef.getType());
1042 appendElement(sb, INDENT4, "mapped-name",
1043 resourceEnvRef.getProperty("mappedName"));
1044 for (InjectionTarget target :
1045 resourceEnvRef.getInjectionTargets()) {
1046 sb.append(" <injection-target>\n");
1047 appendElement(sb, INDENT6, "injection-target-class",
1048 target.getTargetClass());
1049 appendElement(sb, INDENT6, "injection-target-name",
1050 target.getTargetName());
1051 sb.append(" </injection-target>\n");
1052 }
1053 appendElement(sb, INDENT4, "lookup-name", resourceEnvRef.getLookupName());
1054 sb.append(" </resource-env-ref>\n");
1055 }
1056 sb.append('\n');
1057 }
1058
1059 for (ContextResource resourceRef : resourceRefs.values()) {
1060 sb.append(" <resource-ref>\n");
1061 appendElement(sb, INDENT4, "description",
1062 resourceRef.getDescription());
1063 appendElement(sb, INDENT4, "res-ref-name", resourceRef.getName());
1064 appendElement(sb, INDENT4, "res-type", resourceRef.getType());
1065 appendElement(sb, INDENT4, "res-auth", resourceRef.getAuth());
1066
1067 if (getMajorVersion() > 2 || getMinorVersion() > 2) {
1068 appendElement(sb, INDENT4, "res-sharing-scope", resourceRef.getScope());
1069 }
1070 appendElement(sb, INDENT4, "mapped-name", resourceRef.getProperty("mappedName"));
1071 for (InjectionTarget target : resourceRef.getInjectionTargets()) {
1072 sb.append(" <injection-target>\n");
1073 appendElement(sb, INDENT6, "injection-target-class",
1074 target.getTargetClass());
1075 appendElement(sb, INDENT6, "injection-target-name",
1076 target.getTargetName());
1077 sb.append(" </injection-target>\n");
1078 }
1079 appendElement(sb, INDENT4, "lookup-name", resourceRef.getLookupName());
1080 sb.append(" </resource-ref>\n");
1081 }
1082 sb.append('\n');
1083
1084 for (SecurityConstraint constraint : securityConstraints) {
1085 sb.append(" <security-constraint>\n");
1086
1087 if (getMajorVersion() > 2 || getMinorVersion() > 2) {
1088 appendElement(sb, INDENT4, "display-name",
1089 constraint.getDisplayName());
1090 }
1091 for (SecurityCollection collection : constraint.findCollections()) {
1092 sb.append(" <web-resource-collection>\n");
1093 appendElement(sb, INDENT6, "web-resource-name",
1094 collection.getName());
1095 appendElement(sb, INDENT6, "description",
1096 collection.getDescription());
1097 for (String urlPattern : collection.findPatterns()) {
1098 appendElement(sb, INDENT6, "url-pattern", encodeUrl(urlPattern));
1099 }
1100 for (String method : collection.findMethods()) {
1101 appendElement(sb, INDENT6, "http-method", method);
1102 }
1103 for (String method : collection.findOmittedMethods()) {
1104 appendElement(sb, INDENT6, "http-method-omission", method);
1105 }
1106 sb.append(" </web-resource-collection>\n");
1107 }
1108 if (constraint.findAuthRoles().length > 0) {
1109 sb.append(" <auth-constraint>\n");
1110 for (String role : constraint.findAuthRoles()) {
1111 appendElement(sb, INDENT6, "role-name", role);
1112 }
1113 sb.append(" </auth-constraint>\n");
1114 }
1115 if (constraint.getUserConstraint() != null) {
1116 sb.append(" <user-data-constraint>\n");
1117 appendElement(sb, INDENT6, "transport-guarantee",
1118 constraint.getUserConstraint());
1119 sb.append(" </user-data-constraint>\n");
1120 }
1121 sb.append(" </security-constraint>\n");
1122 }
1123 sb.append('\n');
1124
1125 if (loginConfig != null) {
1126 sb.append(" <login-config>\n");
1127 appendElement(sb, INDENT4, "auth-method",
1128 loginConfig.getAuthMethod());
1129 appendElement(sb,INDENT4, "realm-name",
1130 loginConfig.getRealmName());
1131 if (loginConfig.getErrorPage() != null ||
1132 loginConfig.getLoginPage() != null) {
1133 sb.append(" <form-login-config>\n");
1134 appendElement(sb, INDENT6, "form-login-page",
1135 loginConfig.getLoginPage());
1136 appendElement(sb, INDENT6, "form-error-page",
1137 loginConfig.getErrorPage());
1138 sb.append(" </form-login-config>\n");
1139 }
1140 sb.append(" </login-config>\n\n");
1141 }
1142
1143 for (String roleName : securityRoles) {
1144 sb.append(" <security-role>\n");
1145 appendElement(sb, INDENT4, "role-name", roleName);
1146 sb.append(" </security-role>\n");
1147 }
1148
1149 for (ContextEnvironment envEntry : envEntries.values()) {
1150 sb.append(" <env-entry>\n");
1151 appendElement(sb, INDENT4, "description",
1152 envEntry.getDescription());
1153 appendElement(sb, INDENT4, "env-entry-name", envEntry.getName());
1154 appendElement(sb, INDENT4, "env-entry-type", envEntry.getType());
1155 appendElement(sb, INDENT4, "env-entry-value", envEntry.getValue());
1156 appendElement(sb, INDENT4, "mapped-name", envEntry.getProperty("mappedName"));
1157 for (InjectionTarget target : envEntry.getInjectionTargets()) {
1158 sb.append(" <injection-target>\n");
1159 appendElement(sb, INDENT6, "injection-target-class",
1160 target.getTargetClass());
1161 appendElement(sb, INDENT6, "injection-target-name",
1162 target.getTargetName());
1163 sb.append(" </injection-target>\n");
1164 }
1165 appendElement(sb, INDENT4, "lookup-name", envEntry.getLookupName());
1166 sb.append(" </env-entry>\n");
1167 }
1168 sb.append('\n');
1169
1170 for (ContextEjb ejbRef : ejbRefs.values()) {
1171 sb.append(" <ejb-ref>\n");
1172 appendElement(sb, INDENT4, "description", ejbRef.getDescription());
1173 appendElement(sb, INDENT4, "ejb-ref-name", ejbRef.getName());
1174 appendElement(sb, INDENT4, "ejb-ref-type", ejbRef.getType());
1175 appendElement(sb, INDENT4, "home", ejbRef.getHome());
1176 appendElement(sb, INDENT4, "remote", ejbRef.getRemote());
1177 appendElement(sb, INDENT4, "ejb-link", ejbRef.getLink());
1178 appendElement(sb, INDENT4, "mapped-name", ejbRef.getProperty("mappedName"));
1179 for (InjectionTarget target : ejbRef.getInjectionTargets()) {
1180 sb.append(" <injection-target>\n");
1181 appendElement(sb, INDENT6, "injection-target-class",
1182 target.getTargetClass());
1183 appendElement(sb, INDENT6, "injection-target-name",
1184 target.getTargetName());
1185 sb.append(" </injection-target>\n");
1186 }
1187 appendElement(sb, INDENT4, "lookup-name", ejbRef.getLookupName());
1188 sb.append(" </ejb-ref>\n");
1189 }
1190 sb.append('\n');
1191
1192
1193 if (getMajorVersion() > 2 || getMinorVersion() > 2) {
1194 for (ContextLocalEjb ejbLocalRef : ejbLocalRefs.values()) {
1195 sb.append(" <ejb-local-ref>\n");
1196 appendElement(sb, INDENT4, "description",
1197 ejbLocalRef.getDescription());
1198 appendElement(sb, INDENT4, "ejb-ref-name", ejbLocalRef.getName());
1199 appendElement(sb, INDENT4, "ejb-ref-type", ejbLocalRef.getType());
1200 appendElement(sb, INDENT4, "local-home", ejbLocalRef.getHome());
1201 appendElement(sb, INDENT4, "local", ejbLocalRef.getLocal());
1202 appendElement(sb, INDENT4, "ejb-link", ejbLocalRef.getLink());
1203 appendElement(sb, INDENT4, "mapped-name", ejbLocalRef.getProperty("mappedName"));
1204 for (InjectionTarget target : ejbLocalRef.getInjectionTargets()) {
1205 sb.append(" <injection-target>\n");
1206 appendElement(sb, INDENT6, "injection-target-class",
1207 target.getTargetClass());
1208 appendElement(sb, INDENT6, "injection-target-name",
1209 target.getTargetName());
1210 sb.append(" </injection-target>\n");
1211 }
1212 appendElement(sb, INDENT4, "lookup-name", ejbLocalRef.getLookupName());
1213 sb.append(" </ejb-local-ref>\n");
1214 }
1215 sb.append('\n');
1216 }
1217
1218
1219 if (getMajorVersion() > 2 || getMinorVersion() > 3) {
1220 for (ContextService serviceRef : serviceRefs.values()) {
1221 sb.append(" <service-ref>\n");
1222 appendElement(sb, INDENT4, "description",
1223 serviceRef.getDescription());
1224 appendElement(sb, INDENT4, "display-name",
1225 serviceRef.getDisplayname());
1226 appendElement(sb, INDENT4, "service-ref-name",
1227 serviceRef.getName());
1228 appendElement(sb, INDENT4, "service-interface",
1229 serviceRef.getInterface());
1230 appendElement(sb, INDENT4, "service-ref-type",
1231 serviceRef.getType());
1232 appendElement(sb, INDENT4, "wsdl-file", serviceRef.getWsdlfile());
1233 appendElement(sb, INDENT4, "jaxrpc-mapping-file",
1234 serviceRef.getJaxrpcmappingfile());
1235 String qname = serviceRef.getServiceqnameNamespaceURI();
1236 if (qname != null) {
1237 qname = qname + ":";
1238 }
1239 qname = qname + serviceRef.getServiceqnameLocalpart();
1240 appendElement(sb, INDENT4, "service-qname", qname);
1241 Iterator<String> endpointIter = serviceRef.getServiceendpoints();
1242 while (endpointIter.hasNext()) {
1243 String endpoint = endpointIter.next();
1244 sb.append(" <port-component-ref>\n");
1245 appendElement(sb, INDENT6, "service-endpoint-interface",
1246 endpoint);
1247 appendElement(sb, INDENT6, "port-component-link",
1248 serviceRef.getProperty(endpoint));
1249 sb.append(" </port-component-ref>\n");
1250 }
1251 Iterator<String> handlerIter = serviceRef.getHandlers();
1252 while (handlerIter.hasNext()) {
1253 String handler = handlerIter.next();
1254 sb.append(" <handler>\n");
1255 ContextHandler ch = serviceRef.getHandler(handler);
1256 appendElement(sb, INDENT6, "handler-name", ch.getName());
1257 appendElement(sb, INDENT6, "handler-class",
1258 ch.getHandlerclass());
1259 sb.append(" </handler>\n");
1260 }
1261
1262 appendElement(sb, INDENT4, "mapped-name", serviceRef.getProperty("mappedName"));
1263 for (InjectionTarget target : serviceRef.getInjectionTargets()) {
1264 sb.append(" <injection-target>\n");
1265 appendElement(sb, INDENT6, "injection-target-class",
1266 target.getTargetClass());
1267 appendElement(sb, INDENT6, "injection-target-name",
1268 target.getTargetName());
1269 sb.append(" </injection-target>\n");
1270 }
1271 appendElement(sb, INDENT4, "lookup-name", serviceRef.getLookupName());
1272 sb.append(" </service-ref>\n");
1273 }
1274 sb.append('\n');
1275 }
1276
1277 if (!postConstructMethods.isEmpty()) {
1278 for (Entry<String, String> entry : postConstructMethods
1279 .entrySet()) {
1280 sb.append(" <post-construct>\n");
1281 appendElement(sb, INDENT4, "lifecycle-callback-class",
1282 entry.getKey());
1283 appendElement(sb, INDENT4, "lifecycle-callback-method",
1284 entry.getValue());
1285 sb.append(" </post-construct>\n");
1286 }
1287 sb.append('\n');
1288 }
1289
1290 if (!preDestroyMethods.isEmpty()) {
1291 for (Entry<String, String> entry : preDestroyMethods
1292 .entrySet()) {
1293 sb.append(" <pre-destroy>\n");
1294 appendElement(sb, INDENT4, "lifecycle-callback-class",
1295 entry.getKey());
1296 appendElement(sb, INDENT4, "lifecycle-callback-method",
1297 entry.getValue());
1298 sb.append(" </pre-destroy>\n");
1299 }
1300 sb.append('\n');
1301 }
1302
1303
1304
1305 if (getMajorVersion() > 2 || getMinorVersion() > 3) {
1306 for (MessageDestinationRef mdr : messageDestinationRefs.values()) {
1307 sb.append(" <message-destination-ref>\n");
1308 appendElement(sb, INDENT4, "description", mdr.getDescription());
1309 appendElement(sb, INDENT4, "message-destination-ref-name",
1310 mdr.getName());
1311 appendElement(sb, INDENT4, "message-destination-type",
1312 mdr.getType());
1313 appendElement(sb, INDENT4, "message-destination-usage",
1314 mdr.getUsage());
1315 appendElement(sb, INDENT4, "message-destination-link",
1316 mdr.getLink());
1317 appendElement(sb, INDENT4, "mapped-name", mdr.getProperty("mappedName"));
1318 for (InjectionTarget target : mdr.getInjectionTargets()) {
1319 sb.append(" <injection-target>\n");
1320 appendElement(sb, INDENT6, "injection-target-class",
1321 target.getTargetClass());
1322 appendElement(sb, INDENT6, "injection-target-name",
1323 target.getTargetName());
1324 sb.append(" </injection-target>\n");
1325 }
1326 appendElement(sb, INDENT4, "lookup-name", mdr.getLookupName());
1327 sb.append(" </message-destination-ref>\n");
1328 }
1329 sb.append('\n');
1330
1331 for (MessageDestination md : messageDestinations.values()) {
1332 sb.append(" <message-destination>\n");
1333 appendElement(sb, INDENT4, "description", md.getDescription());
1334 appendElement(sb, INDENT4, "display-name", md.getDisplayName());
1335 appendElement(sb, INDENT4, "message-destination-name",
1336 md.getName());
1337 appendElement(sb, INDENT4, "mapped-name", md.getProperty("mappedName"));
1338 appendElement(sb, INDENT4, "lookup-name", md.getLookupName());
1339 sb.append(" </message-destination>\n");
1340 }
1341 sb.append('\n');
1342 }
1343
1344
1345 if (getMajorVersion() > 2 || getMinorVersion() > 3) {
1346 if (localeEncodingMappings.size() > 0) {
1347 sb.append(" <locale-encoding-mapping-list>\n");
1348 for (Map.Entry<String, String> entry :
1349 localeEncodingMappings.entrySet()) {
1350 sb.append(" <locale-encoding-mapping>\n");
1351 appendElement(sb, INDENT6, "locale", entry.getKey());
1352 appendElement(sb, INDENT6, "encoding", entry.getValue());
1353 sb.append(" </locale-encoding-mapping>\n");
1354 }
1355 sb.append(" </locale-encoding-mapping-list>\n");
1356 sb.append("\n");
1357 }
1358 }
1359
1360
1361 if (getMajorVersion() > 3 ||
1362 (getMajorVersion() == 3 && getMinorVersion() > 0)) {
1363 if (denyUncoveredHttpMethods) {
1364 sb.append(" <deny-uncovered-http-methods/>");
1365 sb.append("\n");
1366 }
1367 }
1368
1369
1370 if (getMajorVersion() >= 4) {
1371 appendElement(sb, INDENT2, "request-character-encoding", requestCharacterEncoding);
1372 appendElement(sb, INDENT2, "response-character-encoding", responseCharacterEncoding);
1373 }
1374 sb.append("</web-app>");
1375 return sb.toString();
1376 }
1377
1378
1379 private String encodeUrl(String input) {
1380 try {
1381 return URLEncoder.encode(input, "UTF-8");
1382 } catch (UnsupportedEncodingException e) {
1383
1384 return null;
1385 }
1386 }
1387
1388
1389 private static void appendElement(StringBuilder sb, String indent,
1390 String elementName, String value) {
1391 if (value == null) {
1392 return;
1393 }
1394 if (value.length() == 0) {
1395 sb.append(indent);
1396 sb.append('<');
1397 sb.append(elementName);
1398 sb.append("/>\n");
1399 } else {
1400 sb.append(indent);
1401 sb.append('<');
1402 sb.append(elementName);
1403 sb.append('>');
1404 sb.append(Escape.xml(value));
1405 sb.append("</");
1406 sb.append(elementName);
1407 sb.append(">\n");
1408 }
1409 }
1410
1411 private static void appendElement(StringBuilder sb, String indent,
1412 String elementName, Object value) {
1413 if (value == null) return;
1414 appendElement(sb, indent, elementName, value.toString());
1415 }
1416
1417
1418
1425 public boolean merge(Set<WebXml> fragments) {
1426
1427
1428
1429
1430
1431 WebXml temp = new WebXml();
1432
1433 for (WebXml fragment : fragments) {
1434 if (!mergeMap(fragment.getContextParams(), contextParams,
1435 temp.getContextParams(), fragment, "Context Parameter")) {
1436 return false;
1437 }
1438 }
1439 contextParams.putAll(temp.getContextParams());
1440
1441 if (displayName == null) {
1442 for (WebXml fragment : fragments) {
1443 String value = fragment.getDisplayName();
1444 if (value != null) {
1445 if (temp.getDisplayName() == null) {
1446 temp.setDisplayName(value);
1447 } else {
1448 log.error(sm.getString(
1449 "webXml.mergeConflictDisplayName",
1450 fragment.getName(),
1451 fragment.getURL()));
1452 return false;
1453 }
1454 }
1455 }
1456 displayName = temp.getDisplayName();
1457 }
1458
1459
1460
1461 if (!denyUncoveredHttpMethods) {
1462 for (WebXml fragment : fragments) {
1463 if (fragment.getDenyUncoveredHttpMethods()) {
1464 denyUncoveredHttpMethods = true;
1465 break;
1466 }
1467 }
1468 }
1469 if (requestCharacterEncoding == null) {
1470 for (WebXml fragment : fragments) {
1471 if (fragment.getRequestCharacterEncoding() != null) {
1472 requestCharacterEncoding = fragment.getRequestCharacterEncoding();
1473 }
1474 }
1475 }
1476 if (responseCharacterEncoding == null) {
1477 for (WebXml fragment : fragments) {
1478 if (fragment.getResponseCharacterEncoding() != null) {
1479 responseCharacterEncoding = fragment.getResponseCharacterEncoding();
1480 }
1481 }
1482 }
1483
1484 if (distributable) {
1485 for (WebXml fragment : fragments) {
1486 if (!fragment.isDistributable()) {
1487 distributable = false;
1488 break;
1489 }
1490 }
1491 }
1492
1493 for (WebXml fragment : fragments) {
1494 if (!mergeResourceMap(fragment.getEjbLocalRefs(), ejbLocalRefs,
1495 temp.getEjbLocalRefs(), fragment)) {
1496 return false;
1497 }
1498 }
1499 ejbLocalRefs.putAll(temp.getEjbLocalRefs());
1500
1501 for (WebXml fragment : fragments) {
1502 if (!mergeResourceMap(fragment.getEjbRefs(), ejbRefs,
1503 temp.getEjbRefs(), fragment)) {
1504 return false;
1505 }
1506 }
1507 ejbRefs.putAll(temp.getEjbRefs());
1508
1509 for (WebXml fragment : fragments) {
1510 if (!mergeResourceMap(fragment.getEnvEntries(), envEntries,
1511 temp.getEnvEntries(), fragment)) {
1512 return false;
1513 }
1514 }
1515 envEntries.putAll(temp.getEnvEntries());
1516
1517 for (WebXml fragment : fragments) {
1518 if (!mergeMap(fragment.getErrorPages(), errorPages,
1519 temp.getErrorPages(), fragment, "Error Page")) {
1520 return false;
1521 }
1522 }
1523 errorPages.putAll(temp.getErrorPages());
1524
1525
1526
1527
1528 List<FilterMap> filterMapsToAdd = new ArrayList<>();
1529 for (WebXml fragment : fragments) {
1530 for (FilterMap filterMap : fragment.getFilterMappings()) {
1531 if (!filterMappingNames.contains(filterMap.getFilterName())) {
1532 filterMapsToAdd.add(filterMap);
1533 }
1534 }
1535 }
1536 for (FilterMap filterMap : filterMapsToAdd) {
1537
1538 addFilterMapping(filterMap);
1539 }
1540
1541 for (WebXml fragment : fragments) {
1542 for (Map.Entry<String,FilterDef> entry :
1543 fragment.getFilters().entrySet()) {
1544 if (filters.containsKey(entry.getKey())) {
1545 mergeFilter(entry.getValue(),
1546 filters.get(entry.getKey()), false);
1547 } else {
1548 if (temp.getFilters().containsKey(entry.getKey())) {
1549 if (!(mergeFilter(entry.getValue(),
1550 temp.getFilters().get(entry.getKey()), true))) {
1551 log.error(sm.getString(
1552 "webXml.mergeConflictFilter",
1553 entry.getKey(),
1554 fragment.getName(),
1555 fragment.getURL()));
1556
1557 return false;
1558 }
1559 } else {
1560 temp.getFilters().put(entry.getKey(), entry.getValue());
1561 }
1562 }
1563 }
1564 }
1565 filters.putAll(temp.getFilters());
1566
1567 for (WebXml fragment : fragments) {
1568 for (JspPropertyGroup jspPropertyGroup :
1569 fragment.getJspPropertyGroups()) {
1570
1571 addJspPropertyGroup(jspPropertyGroup);
1572 }
1573 }
1574
1575 for (WebXml fragment : fragments) {
1576 for (String listener : fragment.getListeners()) {
1577
1578 addListener(listener);
1579 }
1580 }
1581
1582 for (WebXml fragment : fragments) {
1583 if (!mergeMap(fragment.getLocaleEncodingMappings(),
1584 localeEncodingMappings, temp.getLocaleEncodingMappings(),
1585 fragment, "Locale Encoding Mapping")) {
1586 return false;
1587 }
1588 }
1589 localeEncodingMappings.putAll(temp.getLocaleEncodingMappings());
1590
1591 if (getLoginConfig() == null) {
1592 LoginConfig tempLoginConfig = null;
1593 for (WebXml fragment : fragments) {
1594 LoginConfig fragmentLoginConfig = fragment.loginConfig;
1595 if (fragmentLoginConfig != null) {
1596 if (tempLoginConfig == null ||
1597 fragmentLoginConfig.equals(tempLoginConfig)) {
1598 tempLoginConfig = fragmentLoginConfig;
1599 } else {
1600 log.error(sm.getString(
1601 "webXml.mergeConflictLoginConfig",
1602 fragment.getName(),
1603 fragment.getURL()));
1604 }
1605 }
1606 }
1607 loginConfig = tempLoginConfig;
1608 }
1609
1610 for (WebXml fragment : fragments) {
1611 if (!mergeResourceMap(fragment.getMessageDestinationRefs(), messageDestinationRefs,
1612 temp.getMessageDestinationRefs(), fragment)) {
1613 return false;
1614 }
1615 }
1616 messageDestinationRefs.putAll(temp.getMessageDestinationRefs());
1617
1618 for (WebXml fragment : fragments) {
1619 if (!mergeResourceMap(fragment.getMessageDestinations(), messageDestinations,
1620 temp.getMessageDestinations(), fragment)) {
1621 return false;
1622 }
1623 }
1624 messageDestinations.putAll(temp.getMessageDestinations());
1625
1626 for (WebXml fragment : fragments) {
1627 if (!mergeMap(fragment.getMimeMappings(), mimeMappings,
1628 temp.getMimeMappings(), fragment, "Mime Mapping")) {
1629 return false;
1630 }
1631 }
1632 mimeMappings.putAll(temp.getMimeMappings());
1633
1634 for (WebXml fragment : fragments) {
1635 if (!mergeResourceMap(fragment.getResourceEnvRefs(), resourceEnvRefs,
1636 temp.getResourceEnvRefs(), fragment)) {
1637 return false;
1638 }
1639 }
1640 resourceEnvRefs.putAll(temp.getResourceEnvRefs());
1641
1642 for (WebXml fragment : fragments) {
1643 if (!mergeResourceMap(fragment.getResourceRefs(), resourceRefs,
1644 temp.getResourceRefs(), fragment)) {
1645 return false;
1646 }
1647 }
1648 resourceRefs.putAll(temp.getResourceRefs());
1649
1650 for (WebXml fragment : fragments) {
1651 for (SecurityConstraint constraint : fragment.getSecurityConstraints()) {
1652
1653 addSecurityConstraint(constraint);
1654 }
1655 }
1656
1657 for (WebXml fragment : fragments) {
1658 for (String role : fragment.getSecurityRoles()) {
1659
1660 addSecurityRole(role);
1661 }
1662 }
1663
1664 for (WebXml fragment : fragments) {
1665 if (!mergeResourceMap(fragment.getServiceRefs(), serviceRefs,
1666 temp.getServiceRefs(), fragment)) {
1667 return false;
1668 }
1669 }
1670 serviceRefs.putAll(temp.getServiceRefs());
1671
1672
1673
1674
1675
1676
1677 List<Map.Entry<String,String>> servletMappingsToAdd = new ArrayList<>();
1678 for (WebXml fragment : fragments) {
1679 for (Map.Entry<String,String> servletMap :
1680 fragment.getServletMappings().entrySet()) {
1681 if (!servletMappingNames.contains(servletMap.getValue()) &&
1682 !servletMappings.containsKey(servletMap.getKey())) {
1683 servletMappingsToAdd.add(servletMap);
1684 }
1685 }
1686 }
1687
1688
1689 for (Map.Entry<String,String> mapping : servletMappingsToAdd) {
1690 addServletMappingDecoded(mapping.getKey(), mapping.getValue());
1691 }
1692
1693 for (WebXml fragment : fragments) {
1694 for (Map.Entry<String,ServletDef> entry :
1695 fragment.getServlets().entrySet()) {
1696 if (servlets.containsKey(entry.getKey())) {
1697 mergeServlet(entry.getValue(),
1698 servlets.get(entry.getKey()), false);
1699 } else {
1700 if (temp.getServlets().containsKey(entry.getKey())) {
1701 if (!(mergeServlet(entry.getValue(),
1702 temp.getServlets().get(entry.getKey()), true))) {
1703 log.error(sm.getString(
1704 "webXml.mergeConflictServlet",
1705 entry.getKey(),
1706 fragment.getName(),
1707 fragment.getURL()));
1708
1709 return false;
1710 }
1711 } else {
1712 temp.getServlets().put(entry.getKey(), entry.getValue());
1713 }
1714 }
1715 }
1716 }
1717 servlets.putAll(temp.getServlets());
1718
1719 if (sessionConfig.getSessionTimeout() == null) {
1720 for (WebXml fragment : fragments) {
1721 Integer value = fragment.getSessionConfig().getSessionTimeout();
1722 if (value != null) {
1723 if (temp.getSessionConfig().getSessionTimeout() == null) {
1724 temp.getSessionConfig().setSessionTimeout(value.toString());
1725 } else if (value.equals(
1726 temp.getSessionConfig().getSessionTimeout())) {
1727
1728 } else {
1729 log.error(sm.getString(
1730 "webXml.mergeConflictSessionTimeout",
1731 fragment.getName(),
1732 fragment.getURL()));
1733 return false;
1734 }
1735 }
1736 }
1737 if (temp.getSessionConfig().getSessionTimeout() != null) {
1738 sessionConfig.setSessionTimeout(
1739 temp.getSessionConfig().getSessionTimeout().toString());
1740 }
1741 }
1742
1743 if (sessionConfig.getCookieName() == null) {
1744 for (WebXml fragment : fragments) {
1745 String value = fragment.getSessionConfig().getCookieName();
1746 if (value != null) {
1747 if (temp.getSessionConfig().getCookieName() == null) {
1748 temp.getSessionConfig().setCookieName(value);
1749 } else if (value.equals(
1750 temp.getSessionConfig().getCookieName())) {
1751
1752 } else {
1753 log.error(sm.getString(
1754 "webXml.mergeConflictSessionCookieName",
1755 fragment.getName(),
1756 fragment.getURL()));
1757 return false;
1758 }
1759 }
1760 }
1761 sessionConfig.setCookieName(
1762 temp.getSessionConfig().getCookieName());
1763 }
1764 if (sessionConfig.getCookieDomain() == null) {
1765 for (WebXml fragment : fragments) {
1766 String value = fragment.getSessionConfig().getCookieDomain();
1767 if (value != null) {
1768 if (temp.getSessionConfig().getCookieDomain() == null) {
1769 temp.getSessionConfig().setCookieDomain(value);
1770 } else if (value.equals(
1771 temp.getSessionConfig().getCookieDomain())) {
1772
1773 } else {
1774 log.error(sm.getString(
1775 "webXml.mergeConflictSessionCookieDomain",
1776 fragment.getName(),
1777 fragment.getURL()));
1778 return false;
1779 }
1780 }
1781 }
1782 sessionConfig.setCookieDomain(
1783 temp.getSessionConfig().getCookieDomain());
1784 }
1785 if (sessionConfig.getCookiePath() == null) {
1786 for (WebXml fragment : fragments) {
1787 String value = fragment.getSessionConfig().getCookiePath();
1788 if (value != null) {
1789 if (temp.getSessionConfig().getCookiePath() == null) {
1790 temp.getSessionConfig().setCookiePath(value);
1791 } else if (value.equals(
1792 temp.getSessionConfig().getCookiePath())) {
1793
1794 } else {
1795 log.error(sm.getString(
1796 "webXml.mergeConflictSessionCookiePath",
1797 fragment.getName(),
1798 fragment.getURL()));
1799 return false;
1800 }
1801 }
1802 }
1803 sessionConfig.setCookiePath(
1804 temp.getSessionConfig().getCookiePath());
1805 }
1806 if (sessionConfig.getCookieComment() == null) {
1807 for (WebXml fragment : fragments) {
1808 String value = fragment.getSessionConfig().getCookieComment();
1809 if (value != null) {
1810 if (temp.getSessionConfig().getCookieComment() == null) {
1811 temp.getSessionConfig().setCookieComment(value);
1812 } else if (value.equals(
1813 temp.getSessionConfig().getCookieComment())) {
1814
1815 } else {
1816 log.error(sm.getString(
1817 "webXml.mergeConflictSessionCookieComment",
1818 fragment.getName(),
1819 fragment.getURL()));
1820 return false;
1821 }
1822 }
1823 }
1824 sessionConfig.setCookieComment(
1825 temp.getSessionConfig().getCookieComment());
1826 }
1827 if (sessionConfig.getCookieHttpOnly() == null) {
1828 for (WebXml fragment : fragments) {
1829 Boolean value = fragment.getSessionConfig().getCookieHttpOnly();
1830 if (value != null) {
1831 if (temp.getSessionConfig().getCookieHttpOnly() == null) {
1832 temp.getSessionConfig().setCookieHttpOnly(value.toString());
1833 } else if (value.equals(
1834 temp.getSessionConfig().getCookieHttpOnly())) {
1835
1836 } else {
1837 log.error(sm.getString(
1838 "webXml.mergeConflictSessionCookieHttpOnly",
1839 fragment.getName(),
1840 fragment.getURL()));
1841 return false;
1842 }
1843 }
1844 }
1845 if (temp.getSessionConfig().getCookieHttpOnly() != null) {
1846 sessionConfig.setCookieHttpOnly(
1847 temp.getSessionConfig().getCookieHttpOnly().toString());
1848 }
1849 }
1850 if (sessionConfig.getCookieSecure() == null) {
1851 for (WebXml fragment : fragments) {
1852 Boolean value = fragment.getSessionConfig().getCookieSecure();
1853 if (value != null) {
1854 if (temp.getSessionConfig().getCookieSecure() == null) {
1855 temp.getSessionConfig().setCookieSecure(value.toString());
1856 } else if (value.equals(
1857 temp.getSessionConfig().getCookieSecure())) {
1858
1859 } else {
1860 log.error(sm.getString(
1861 "webXml.mergeConflictSessionCookieSecure",
1862 fragment.getName(),
1863 fragment.getURL()));
1864 return false;
1865 }
1866 }
1867 }
1868 if (temp.getSessionConfig().getCookieSecure() != null) {
1869 sessionConfig.setCookieSecure(
1870 temp.getSessionConfig().getCookieSecure().toString());
1871 }
1872 }
1873 if (sessionConfig.getCookieMaxAge() == null) {
1874 for (WebXml fragment : fragments) {
1875 Integer value = fragment.getSessionConfig().getCookieMaxAge();
1876 if (value != null) {
1877 if (temp.getSessionConfig().getCookieMaxAge() == null) {
1878 temp.getSessionConfig().setCookieMaxAge(value.toString());
1879 } else if (value.equals(
1880 temp.getSessionConfig().getCookieMaxAge())) {
1881
1882 } else {
1883 log.error(sm.getString(
1884 "webXml.mergeConflictSessionCookieMaxAge",
1885 fragment.getName(),
1886 fragment.getURL()));
1887 return false;
1888 }
1889 }
1890 }
1891 if (temp.getSessionConfig().getCookieMaxAge() != null) {
1892 sessionConfig.setCookieMaxAge(
1893 temp.getSessionConfig().getCookieMaxAge().toString());
1894 }
1895 }
1896
1897 if (sessionConfig.getSessionTrackingModes().size() == 0) {
1898 for (WebXml fragment : fragments) {
1899 EnumSet<SessionTrackingMode> value =
1900 fragment.getSessionConfig().getSessionTrackingModes();
1901 if (value.size() > 0) {
1902 if (temp.getSessionConfig().getSessionTrackingModes().size() == 0) {
1903 temp.getSessionConfig().getSessionTrackingModes().addAll(value);
1904 } else if (value.equals(
1905 temp.getSessionConfig().getSessionTrackingModes())) {
1906
1907 } else {
1908 log.error(sm.getString(
1909 "webXml.mergeConflictSessionTrackingMode",
1910 fragment.getName(),
1911 fragment.getURL()));
1912 return false;
1913 }
1914 }
1915 }
1916 sessionConfig.getSessionTrackingModes().addAll(
1917 temp.getSessionConfig().getSessionTrackingModes());
1918 }
1919
1920 for (WebXml fragment : fragments) {
1921 if (!mergeMap(fragment.getTaglibs(), taglibs,
1922 temp.getTaglibs(), fragment, "Taglibs")) {
1923 return false;
1924 }
1925 }
1926 taglibs.putAll(temp.getTaglibs());
1927
1928 for (WebXml fragment : fragments) {
1929 if (fragment.alwaysAddWelcomeFiles || welcomeFiles.size() == 0) {
1930 for (String welcomeFile : fragment.getWelcomeFiles()) {
1931 addWelcomeFile(welcomeFile);
1932 }
1933 }
1934 }
1935
1936 if (postConstructMethods.isEmpty()) {
1937 for (WebXml fragment : fragments) {
1938 if (!mergeLifecycleCallback(fragment.getPostConstructMethods(),
1939 temp.getPostConstructMethods(), fragment,
1940 "Post Construct Methods")) {
1941 return false;
1942 }
1943 }
1944 postConstructMethods.putAll(temp.getPostConstructMethods());
1945 }
1946
1947 if (preDestroyMethods.isEmpty()) {
1948 for (WebXml fragment : fragments) {
1949 if (!mergeLifecycleCallback(fragment.getPreDestroyMethods(),
1950 temp.getPreDestroyMethods(), fragment,
1951 "Pre Destroy Methods")) {
1952 return false;
1953 }
1954 }
1955 preDestroyMethods.putAll(temp.getPreDestroyMethods());
1956 }
1957
1958 return true;
1959 }
1960
1961 private <T extends ResourceBase> boolean mergeResourceMap(
1962 Map<String, T> fragmentResources, Map<String, T> mainResources,
1963 Map<String, T> tempResources, WebXml fragment) {
1964 for (T resource : fragmentResources.values()) {
1965 String resourceName = resource.getName();
1966 if (mainResources.containsKey(resourceName)) {
1967 mainResources.get(resourceName).getInjectionTargets().addAll(
1968 resource.getInjectionTargets());
1969 } else {
1970
1971 T existingResource = tempResources.get(resourceName);
1972 if (existingResource != null) {
1973 if (!existingResource.equals(resource)) {
1974 log.error(sm.getString(
1975 "webXml.mergeConflictResource",
1976 resourceName,
1977 fragment.getName(),
1978 fragment.getURL()));
1979 return false;
1980 }
1981 } else {
1982 tempResources.put(resourceName, resource);
1983 }
1984 }
1985 }
1986 return true;
1987 }
1988
1989 private <T> boolean mergeMap(Map<String,T> fragmentMap,
1990 Map<String,T> mainMap, Map<String,T> tempMap, WebXml fragment,
1991 String mapName) {
1992 for (Entry<String, T> entry : fragmentMap.entrySet()) {
1993 final String key = entry.getKey();
1994 if (!mainMap.containsKey(key)) {
1995
1996 T value = entry.getValue();
1997 if (tempMap.containsKey(key)) {
1998 if (value != null && !value.equals(
1999 tempMap.get(key))) {
2000 log.error(sm.getString(
2001 "webXml.mergeConflictString",
2002 mapName,
2003 key,
2004 fragment.getName(),
2005 fragment.getURL()));
2006 return false;
2007 }
2008 } else {
2009 tempMap.put(key, value);
2010 }
2011 }
2012 }
2013 return true;
2014 }
2015
2016 private static boolean mergeFilter(FilterDef src, FilterDef dest,
2017 boolean failOnConflict) {
2018 if (dest.getAsyncSupported() == null) {
2019 dest.setAsyncSupported(src.getAsyncSupported());
2020 } else if (src.getAsyncSupported() != null) {
2021 if (failOnConflict &&
2022 !src.getAsyncSupported().equals(dest.getAsyncSupported())) {
2023 return false;
2024 }
2025 }
2026
2027 if (dest.getFilterClass() == null) {
2028 dest.setFilterClass(src.getFilterClass());
2029 } else if (src.getFilterClass() != null) {
2030 if (failOnConflict &&
2031 !src.getFilterClass().equals(dest.getFilterClass())) {
2032 return false;
2033 }
2034 }
2035
2036 for (Map.Entry<String,String> srcEntry :
2037 src.getParameterMap().entrySet()) {
2038 if (dest.getParameterMap().containsKey(srcEntry.getKey())) {
2039 if (failOnConflict && !dest.getParameterMap().get(
2040 srcEntry.getKey()).equals(srcEntry.getValue())) {
2041 return false;
2042 }
2043 } else {
2044 dest.addInitParameter(srcEntry.getKey(), srcEntry.getValue());
2045 }
2046 }
2047 return true;
2048 }
2049
2050 private static boolean mergeServlet(ServletDef src, ServletDef dest,
2051 boolean failOnConflict) {
2052
2053 if (dest.getServletClass() != null && dest.getJspFile() != null) {
2054 return false;
2055 }
2056 if (src.getServletClass() != null && src.getJspFile() != null) {
2057 return false;
2058 }
2059
2060
2061 if (dest.getServletClass() == null && dest.getJspFile() == null) {
2062 dest.setServletClass(src.getServletClass());
2063 dest.setJspFile(src.getJspFile());
2064 } else if (failOnConflict) {
2065 if (src.getServletClass() != null &&
2066 (dest.getJspFile() != null ||
2067 !src.getServletClass().equals(dest.getServletClass()))) {
2068 return false;
2069 }
2070 if (src.getJspFile() != null &&
2071 (dest.getServletClass() != null ||
2072 !src.getJspFile().equals(dest.getJspFile()))) {
2073 return false;
2074 }
2075 }
2076
2077
2078 for (SecurityRoleRef securityRoleRef : src.getSecurityRoleRefs()) {
2079 dest.addSecurityRoleRef(securityRoleRef);
2080 }
2081
2082 if (dest.getLoadOnStartup() == null) {
2083 if (src.getLoadOnStartup() != null) {
2084 dest.setLoadOnStartup(src.getLoadOnStartup().toString());
2085 }
2086 } else if (src.getLoadOnStartup() != null) {
2087 if (failOnConflict &&
2088 !src.getLoadOnStartup().equals(dest.getLoadOnStartup())) {
2089 return false;
2090 }
2091 }
2092
2093 if (dest.getEnabled() == null) {
2094 if (src.getEnabled() != null) {
2095 dest.setEnabled(src.getEnabled().toString());
2096 }
2097 } else if (src.getEnabled() != null) {
2098 if (failOnConflict &&
2099 !src.getEnabled().equals(dest.getEnabled())) {
2100 return false;
2101 }
2102 }
2103
2104 for (Map.Entry<String,String> srcEntry :
2105 src.getParameterMap().entrySet()) {
2106 if (dest.getParameterMap().containsKey(srcEntry.getKey())) {
2107 if (failOnConflict && !dest.getParameterMap().get(
2108 srcEntry.getKey()).equals(srcEntry.getValue())) {
2109 return false;
2110 }
2111 } else {
2112 dest.addInitParameter(srcEntry.getKey(), srcEntry.getValue());
2113 }
2114 }
2115
2116 if (dest.getMultipartDef() == null) {
2117 dest.setMultipartDef(src.getMultipartDef());
2118 } else if (src.getMultipartDef() != null) {
2119 return mergeMultipartDef(src.getMultipartDef(),
2120 dest.getMultipartDef(), failOnConflict);
2121 }
2122
2123 if (dest.getAsyncSupported() == null) {
2124 if (src.getAsyncSupported() != null) {
2125 dest.setAsyncSupported(src.getAsyncSupported().toString());
2126 }
2127 } else if (src.getAsyncSupported() != null) {
2128 if (failOnConflict &&
2129 !src.getAsyncSupported().equals(dest.getAsyncSupported())) {
2130 return false;
2131 }
2132 }
2133
2134 return true;
2135 }
2136
2137 private static boolean mergeMultipartDef(MultipartDef src, MultipartDef dest,
2138 boolean failOnConflict) {
2139
2140 if (dest.getLocation() == null) {
2141 dest.setLocation(src.getLocation());
2142 } else if (src.getLocation() != null) {
2143 if (failOnConflict &&
2144 !src.getLocation().equals(dest.getLocation())) {
2145 return false;
2146 }
2147 }
2148
2149 if (dest.getFileSizeThreshold() == null) {
2150 dest.setFileSizeThreshold(src.getFileSizeThreshold());
2151 } else if (src.getFileSizeThreshold() != null) {
2152 if (failOnConflict &&
2153 !src.getFileSizeThreshold().equals(
2154 dest.getFileSizeThreshold())) {
2155 return false;
2156 }
2157 }
2158
2159 if (dest.getMaxFileSize() == null) {
2160 dest.setMaxFileSize(src.getMaxFileSize());
2161 } else if (src.getMaxFileSize() != null) {
2162 if (failOnConflict &&
2163 !src.getMaxFileSize().equals(dest.getMaxFileSize())) {
2164 return false;
2165 }
2166 }
2167
2168 if (dest.getMaxRequestSize() == null) {
2169 dest.setMaxRequestSize(src.getMaxRequestSize());
2170 } else if (src.getMaxRequestSize() != null) {
2171 if (failOnConflict &&
2172 !src.getMaxRequestSize().equals(
2173 dest.getMaxRequestSize())) {
2174 return false;
2175 }
2176 }
2177
2178 return true;
2179 }
2180
2181
2182 private boolean mergeLifecycleCallback(
2183 Map<String, String> fragmentMap, Map<String, String> tempMap,
2184 WebXml fragment, String mapName) {
2185 for (Entry<String, String> entry : fragmentMap.entrySet()) {
2186 final String key = entry.getKey();
2187 final String value = entry.getValue();
2188 if (tempMap.containsKey(key)) {
2189 if (value != null && !value.equals(tempMap.get(key))) {
2190 log.error(sm.getString("webXml.mergeConflictString",
2191 mapName, key, fragment.getName(), fragment.getURL()));
2192 return false;
2193 }
2194 } else {
2195 tempMap.put(key, value);
2196 }
2197 }
2198 return true;
2199 }
2200
2201
2202
2213 public static Set<WebXml> orderWebFragments(WebXml application,
2214 Map<String,WebXml> fragments, ServletContext servletContext) {
2215 return application.orderWebFragments(fragments, servletContext);
2216 }
2217
2218
2219 private Set<WebXml> orderWebFragments(Map<String,WebXml> fragments,
2220 ServletContext servletContext) {
2221
2222 Set<WebXml> orderedFragments = new LinkedHashSet<>();
2223
2224 boolean absoluteOrdering = getAbsoluteOrdering() != null;
2225 boolean orderingPresent = false;
2226
2227 if (absoluteOrdering) {
2228 orderingPresent = true;
2229
2230 Set<String> requestedOrder = getAbsoluteOrdering();
2231
2232 for (String requestedName : requestedOrder) {
2233 if (WebXml.ORDER_OTHERS.equals(requestedName)) {
2234
2235 for (Entry<String, WebXml> entry : fragments.entrySet()) {
2236 if (!requestedOrder.contains(entry.getKey())) {
2237 WebXml fragment = entry.getValue();
2238 if (fragment != null) {
2239 orderedFragments.add(fragment);
2240 }
2241 }
2242 }
2243 } else {
2244 WebXml fragment = fragments.get(requestedName);
2245 if (fragment != null) {
2246 orderedFragments.add(fragment);
2247 } else {
2248 log.warn(sm.getString("webXml.wrongFragmentName",requestedName));
2249 }
2250 }
2251 }
2252 } else {
2253
2254 for (WebXml fragment : fragments.values()) {
2255 if (fragment.isDuplicated()) {
2256 throw new IllegalArgumentException(
2257 sm.getString("webXml.duplicateFragment", fragment.getName()));
2258 }
2259 }
2260
2261
2262 for (WebXml fragment : fragments.values()) {
2263 Iterator<String> before =
2264 fragment.getBeforeOrdering().iterator();
2265 while (before.hasNext()) {
2266 orderingPresent = true;
2267 String beforeEntry = before.next();
2268 if (!beforeEntry.equals(ORDER_OTHERS)) {
2269 WebXml beforeFragment = fragments.get(beforeEntry);
2270 if (beforeFragment == null) {
2271 before.remove();
2272 } else {
2273 beforeFragment.addAfterOrdering(fragment.getName());
2274 }
2275 }
2276 }
2277 Iterator<String> after = fragment.getAfterOrdering().iterator();
2278 while (after.hasNext()) {
2279 orderingPresent = true;
2280 String afterEntry = after.next();
2281 if (!afterEntry.equals(ORDER_OTHERS)) {
2282 WebXml afterFragment = fragments.get(afterEntry);
2283 if (afterFragment == null) {
2284 after.remove();
2285 } else {
2286 afterFragment.addBeforeOrdering(fragment.getName());
2287 }
2288 }
2289 }
2290 }
2291
2292
2293
2294
2295 for (WebXml fragment : fragments.values()) {
2296 if (fragment.getBeforeOrdering().contains(ORDER_OTHERS)) {
2297 makeBeforeOthersExplicit(fragment.getAfterOrdering(), fragments);
2298 }
2299 if (fragment.getAfterOrdering().contains(ORDER_OTHERS)) {
2300 makeAfterOthersExplicit(fragment.getBeforeOrdering(), fragments);
2301 }
2302 }
2303
2304
2305 Set<WebXml> beforeSet = new HashSet<>();
2306 Set<WebXml> othersSet = new HashSet<>();
2307 Set<WebXml> afterSet = new HashSet<>();
2308
2309 for (WebXml fragment : fragments.values()) {
2310 if (fragment.getBeforeOrdering().contains(ORDER_OTHERS)) {
2311 beforeSet.add(fragment);
2312 fragment.getBeforeOrdering().remove(ORDER_OTHERS);
2313 } else if (fragment.getAfterOrdering().contains(ORDER_OTHERS)) {
2314 afterSet.add(fragment);
2315 fragment.getAfterOrdering().remove(ORDER_OTHERS);
2316 } else {
2317 othersSet.add(fragment);
2318 }
2319 }
2320
2321
2322
2323
2324
2325
2326
2327 decoupleOtherGroups(beforeSet);
2328 decoupleOtherGroups(othersSet);
2329 decoupleOtherGroups(afterSet);
2330
2331
2332
2333
2334 orderFragments(orderedFragments, beforeSet);
2335 orderFragments(orderedFragments, othersSet);
2336 orderFragments(orderedFragments, afterSet);
2337 }
2338
2339
2340 Set<WebXml> containerFragments = new LinkedHashSet<>();
2341
2342
2343 for (WebXml fragment : fragments.values()) {
2344 if (!fragment.getWebappJar()) {
2345 containerFragments.add(fragment);
2346 orderedFragments.remove(fragment);
2347 }
2348 }
2349
2350
2351 if (servletContext != null) {
2352
2353
2354 List<String> orderedJarFileNames = null;
2355 if (orderingPresent) {
2356 orderedJarFileNames = new ArrayList<>();
2357 for (WebXml fragment: orderedFragments) {
2358 orderedJarFileNames.add(fragment.getJarName());
2359 }
2360 }
2361 servletContext.setAttribute(ServletContext.ORDERED_LIBS,
2362 orderedJarFileNames);
2363 }
2364
2365
2366
2367 if (containerFragments.size() > 0) {
2368 Set<WebXml> result = new LinkedHashSet<>();
2369 if (containerFragments.iterator().next().getDelegate()) {
2370 result.addAll(containerFragments);
2371 result.addAll(orderedFragments);
2372 } else {
2373 result.addAll(orderedFragments);
2374 result.addAll(containerFragments);
2375 }
2376 return result;
2377 } else {
2378 return orderedFragments;
2379 }
2380 }
2381
2382 private static void decoupleOtherGroups(Set<WebXml> group) {
2383 Set<String> names = new HashSet<>();
2384 for (WebXml fragment : group) {
2385 names.add(fragment.getName());
2386 }
2387 for (WebXml fragment : group) {
2388 Iterator<String> after = fragment.getAfterOrdering().iterator();
2389 while (after.hasNext()) {
2390 String entry = after.next();
2391 if (!names.contains(entry)) {
2392 after.remove();
2393 }
2394 }
2395 }
2396 }
2397 private static void orderFragments(Set<WebXml> orderedFragments,
2398 Set<WebXml> unordered) {
2399 Set<WebXml> addedThisRound = new HashSet<>();
2400 Set<WebXml> addedLastRound = new HashSet<>();
2401 while (unordered.size() > 0) {
2402 Iterator<WebXml> source = unordered.iterator();
2403 while (source.hasNext()) {
2404 WebXml fragment = source.next();
2405 for (WebXml toRemove : addedLastRound) {
2406 fragment.getAfterOrdering().remove(toRemove.getName());
2407 }
2408 if (fragment.getAfterOrdering().isEmpty()) {
2409 addedThisRound.add(fragment);
2410 orderedFragments.add(fragment);
2411 source.remove();
2412 }
2413 }
2414 if (addedThisRound.size() == 0) {
2415
2416 throw new IllegalArgumentException(
2417 sm.getString("webXml.mergeConflictOrder"));
2418 }
2419 addedLastRound.clear();
2420 addedLastRound.addAll(addedThisRound);
2421 addedThisRound.clear();
2422 }
2423 }
2424
2425 private static void makeBeforeOthersExplicit(Set<String> beforeOrdering,
2426 Map<String, WebXml> fragments) {
2427 for (String before : beforeOrdering) {
2428 if (!before.equals(ORDER_OTHERS)) {
2429 WebXml webXml = fragments.get(before);
2430 if (!webXml.getBeforeOrdering().contains(ORDER_OTHERS)) {
2431 webXml.addBeforeOrderingOthers();
2432 makeBeforeOthersExplicit(webXml.getAfterOrdering(), fragments);
2433 }
2434 }
2435 }
2436 }
2437
2438 private static void makeAfterOthersExplicit(Set<String> afterOrdering,
2439 Map<String, WebXml> fragments) {
2440 for (String after : afterOrdering) {
2441 if (!after.equals(ORDER_OTHERS)) {
2442 WebXml webXml = fragments.get(after);
2443 if (!webXml.getAfterOrdering().contains(ORDER_OTHERS)) {
2444 webXml.addAfterOrderingOthers();
2445 makeAfterOthersExplicit(webXml.getBeforeOrdering(), fragments);
2446 }
2447 }
2448 }
2449 }
2450 }
2451