Author: markt Date: Sat Oct 24 20:07:42 2009 New Revision: 829440 URL: http://svn.apache.org/viewvc?rev=829440&view=rev Log: Implement merge rules for a few more web.xml elements Required some refactoring as some of the rules depend on all fragments and the main web.xml
Modified: tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties tomcat/trunk/java/org/apache/catalina/startup/WebXml.java Modified: tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java?rev=829440&r1=829439&r2=829440&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java Sat Oct 24 20:07:42 2009 @@ -1215,6 +1215,7 @@ */ protected void webConfig() { WebXml webXml = new WebXml(); + // Parse global web.xml if present InputSource globalWebXml = getGlobalWebXmlSource(); if (globalWebXml == null) { @@ -1242,14 +1243,14 @@ // Merge the fragments into the main web.xml mergeWebFragments(webXml, fragments); - // Apply merged web.xml to Context - webXml.configureContext(context); - // Process JARs for annotations processAnnotationsInJars(fragments); // Process /WEB-INF/classes for annotations // TODO SERVLET3 + + // Apply merged web.xml to Context + webXml.configureContext(context); } else { // Apply merged web.xml to Context webXml.configureContext(context); @@ -1601,18 +1602,9 @@ // TODO SERVLET3 Relative ordering } - // Merge fragments in order - conflict == error - WebXml mergedFragments = new WebXml(); - for (WebXml fragment : orderedFragments) { - ok = mergedFragments.merge(fragment, false); - if (ok == false) { - break; - } - } - - // Merge fragment into application - conflict == application wins + // Merge fragment into application if (ok) { - ok = application.merge(mergedFragments, true); + ok = application.merge(orderedFragments); } } Modified: tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties?rev=829440&r1=829439&r2=829440&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties Sat Oct 24 20:07:42 2009 @@ -114,5 +114,8 @@ webXml.duplicateResourceEnvRef=Duplicate resource-env-ref name webXml.duplicateResourceRef=Duplicate resource-ref name webXml.reservedName=A web.xml file was detected using a reserved name [{0}]. The name element will be ignored for this fragment. +webXml.mergeConflictContextParam=Context parameter [{0}] was defined in multiple fragments with different values including fragment with name [{1}] located at [{2}] +webXml.mergeConflictDisplayName=The display name was defined in multiple fragments with different values including fragment with name [{0}] located at [{1}] +webXml.mergeConflictEjbLocalRef=The EjbLocalRef [{0}] was defined in multiple fragments including fragment with name [{1}] located at [{2}] webXml.mergeConflictListener=Listener [{0}] was defined in multiple fragments including fragment with name [{1}] located at [{2}] webXml.multipleOther=Multiple others entries in ordering Modified: tomcat/trunk/java/org/apache/catalina/startup/WebXml.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/WebXml.java?rev=829440&r1=829439&r2=829440&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/WebXml.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/WebXml.java Sat Oct 24 20:07:42 2009 @@ -323,11 +323,14 @@ // ejb-local-ref // TODO: Should support multiple description elements with language - private Set<ContextLocalEjb> ejbLocalRefs = new HashSet<ContextLocalEjb>(); + private Map<String,ContextLocalEjb> ejbLocalRefs = + new HashMap<String,ContextLocalEjb>(); public void addEjbLocalRef(ContextLocalEjb ejbLocalRef) { - ejbLocalRefs.add(ejbLocalRef); + ejbLocalRefs.put(ejbLocalRef.getName(),ejbLocalRef); + } + public Map<String,ContextLocalEjb> getEjbLocalRefs() { + return ejbLocalRefs; } - public Set<ContextLocalEjb> getEjbLocalRefs() { return ejbLocalRefs; } // service-ref // TODO: Should support multiple description elements with language @@ -448,7 +451,7 @@ } context.setDisplayName(displayName); context.setDistributable(distributable); - for (ContextLocalEjb ejbLocalRef : ejbLocalRefs) { + for (ContextLocalEjb ejbLocalRef : ejbLocalRefs.values()) { context.getNamingResources().addLocalEjb(ejbLocalRef); } for (ContextEjb ejbRef : ejbRefs) { @@ -558,30 +561,131 @@ } /** - * Merge the supplied web fragment into this this one. + * Merge the supplied web fragments into this main web.xml. * - * @param source The fragment to merge in - * @boolean ignoreConflicts Flag that indicates that conflicts should be - * ignored and the existing value used + * @param fragments The fragments to merge in * @return <code>true</code> if merge is successful, else * <code>false</code> */ - public boolean merge(WebXml source, boolean ignoreConflicts) { - // TODO SERVLET3 + public boolean merge(Set<WebXml> fragments) { + // As far as possible, process in alphabetical order so it is easy to + // check everything is present + + // Merge rules vary from element to element. See SRV.8.2.3 + + WebXml temp = new WebXml(); + + for (WebXml fragment : fragments) { + for (String contextParam : fragment.getContextParams().keySet()) { + if (!contextParams.containsKey(contextParam)) { + // Not defined in main web.xml + String value = + fragment.getContextParams().get(contextParam); + if (temp.getContextParams().containsKey(contextParam)) { + if (value != null && !value.equals( + temp.getContextParams().get(contextParam))) { + log.error(sm.getString( + "webXml.mergeConflictContextParam", + contextParam, + fragment.getName(), + fragment.getURL())); + return false; + } + } else { + temp.addContextParam(contextParam, value); + } + } + } + } + contextParams.putAll(temp.getContextParams()); + + if (displayName == null) { + for (WebXml fragment : fragments) { + String value = fragment.getDisplayName(); + if (value != null) { + if (temp.getDisplayName() == null) { + temp.setDisplayName(value); + } else { + log.error(sm.getString( + "webXml.mergeConflictDisplayName", + fragment.getName(), + fragment.getURL())); + return false; + } + } + } + } + displayName = temp.getDisplayName(); + + if (distributable) { + for (WebXml fragment : fragments) { + if (!fragment.isDistributable()) { + distributable = false; + break; + } + } + } - // Just do listeners for now since that is what my simple test case is - // using - for (String listener : source.getListeners()) { - if (listeners.contains(listener)) { - if (!ignoreConflicts) { - log.error(sm.getString("webXml.mergeConflictListener", - listener, source.getName(), source.getURL())); - return false; + Map<String,Boolean> mergeInjectionFlags = + new HashMap<String, Boolean>(); + for (WebXml fragment : fragments) { + for (ContextLocalEjb ejbLocalRef : + fragment.getEjbLocalRefs().values()) { + String name = ejbLocalRef.getName(); + boolean mergeInjectionFlag = false; + if (ejbLocalRefs.containsKey(name)) { + if (mergeInjectionFlags.containsKey(name)) { + mergeInjectionFlag = + mergeInjectionFlags.get(name).booleanValue(); + } else { + if (ejbLocalRefs.get( + name).getInjectionTargets().size() == 0) { + mergeInjectionFlag = true; + } + mergeInjectionFlags.put(name, + Boolean.valueOf(mergeInjectionFlag)); + } + if (mergeInjectionFlag) { + ejbLocalRefs.get(name).getInjectionTargets().addAll( + ejbLocalRef.getInjectionTargets()); + } + } else { + // Not defined in main web.xml + if (temp.getEjbLocalRefs().containsKey(name)) { + log.error(sm.getString( + "webXml.mergeConflictEjbLocalRef", + name, + fragment.getName(), + fragment.getURL())); + return false; + } else { + temp.getEjbLocalRefs().put(name, ejbLocalRef); + } + } + } + } + ejbLocalRefs.putAll(temp.getEjbLocalRefs()); + + // TODO SERVLET3 - Merge remaining elements + + for (WebXml fragment : fragments) { + for (String listener : fragment.getListeners()) { + if (!listeners.contains(listener)) { + // Not defined in main web.xml + if (temp.getListeners().contains(listener)) { + log.error(sm.getString( + "webXml.mergeConflictListener", + listener, + fragment.getName(), + fragment.getURL())); + return false; + } else { + temp.addListener(listener); + } } - } else { - listeners.add(listener); } } + listeners.addAll(temp.getListeners()); return true; } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org