Author: markt Date: Fri Oct 23 16:39:32 2009 New Revision: 829121 URL: http://svn.apache.org/viewvc?rev=829121&view=rev Log: Add support for absolute ordering of web fragments and the start of the fragment merge code
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/WebRuleSet.java 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=829121&r1=829120&r2=829121&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java Fri Oct 23 16:39:32 2009 @@ -29,8 +29,10 @@ import java.net.URL; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Properties; +import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -1235,7 +1237,7 @@ if (!webXml.isMetadataComplete()) { // Have to process JARs for fragments - Map<URL,WebXml> fragments = processJarsForWebFragments(); + Map<String,WebXml> fragments = processJarsForWebFragments(); // Merge the fragments into the main web.xml mergeWebFragments(webXml, fragments); @@ -1452,7 +1454,7 @@ * * @return A map of JAR name to processed web fragment (if any) */ - protected Map<URL,WebXml> processJarsForWebFragments() { + protected Map<String,WebXml> processJarsForWebFragments() { JarScanner jarScanner = context.getJarScanner(); FragmentJarScannerCallback callback = new FragmentJarScannerCallback(); @@ -1467,7 +1469,7 @@ private static final String FRAGMENT_LOCATION = "META-INF/web-fragment.xml"; - private Map<URL,WebXml> fragments = new HashMap<URL,WebXml>(); + private Map<String,WebXml> fragments = new HashMap<String,WebXml>(); @Override public void scan(JarURLConnection urlConn) throws IOException { @@ -1505,7 +1507,15 @@ // ignore } } - fragments.put(urlConn.getURL(), fragment); + if (fragment == null) { + fragments.put(urlConn.getURL().toString(), fragment); + } else { + fragment.setURL(urlConn.getURL()); + if (fragment.getName() == null) { + fragment.setName(fragment.getURL().toString()); + } + fragments.put(fragment.getName(), fragment); + } } } @@ -1533,11 +1543,19 @@ // ignore } } - fragments.put(file.toURI().toURL(), fragment); + if (fragment == null) { + fragments.put(file.toURI().toURL().toString(), fragment); + } else { + fragment.setURL(file.toURI().toURL()); + if (fragment.getName() == null) { + fragment.setName(fragment.getURL().toString()); + } + fragments.put(fragment.getName(), fragment); + } } } - public Map<URL,WebXml> getFragments() { + public Map<String,WebXml> getFragments() { return fragments; } } @@ -1547,22 +1565,61 @@ * Servlet spec. * * @param application The application web.xml file - * @param fragments The map of JARs to web fragments + * @param fragments The map of fragment names to web fragments */ protected void mergeWebFragments(WebXml application, - Map<URL,WebXml> fragments) { - // TODO SERVLET3 - // Check order + Map<String,WebXml> fragments) { + + Set<WebXml> orderedFragments = new LinkedHashSet<WebXml>(); + + boolean absoluteOrdering = + (application.getAbsoluteOrdering() != null); + + if (absoluteOrdering) { + // Only those fragments listed should be processed + Set<String> requestedOrder = application.getAbsoluteOrdering(); + + for (String requestedName : requestedOrder) { + if (WebXml.ORDER_OTHERS.equals(requestedName)) { + // Add all fragments not named explicitly at this point + for (String name : fragments.keySet()) { + if (!requestedOrder.contains(name)) { + WebXml fragment = fragments.get(name); + if (fragment != null) { + orderedFragments.add(fragment); + } + } + } + } else { + WebXml fragment = fragments.get(requestedName); + if (fragment != null) { + orderedFragments.add(fragment); + } + } + } + } else { + // 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 - conflict == application wins + if (ok) { + ok = application.merge(mergedFragments, true); + } } - protected void processAnnotationsInJars(Map<URL,WebXml> fragments) { - for(URL url : fragments.keySet()) { - WebXml fragment = fragments.get(url); + protected void processAnnotationsInJars(Map<String,WebXml> fragments) { + for(String name : fragments.keySet()) { + WebXml fragment = fragments.get(name); if (fragment == null || !fragment.isMetadataComplete()) { // Scan jar for annotations // TODO SERVLET3 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=829121&r1=829120&r2=829121&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties Fri Oct 23 16:39:32 2009 @@ -105,11 +105,14 @@ userConfig.error=Error deploying web application for user {0} userConfig.start=UserConfig: Processing START userConfig.stop=UserConfig: Processing STOP -webXmlCommon.duplicateEnvEntry=Duplicate env-entry name -webXmlCommon.duplicateFilter=Duplicate filter name -webXmlCommon.duplicateMessageDestination=Duplicate message-destination name -webXmlCommon.duplicateMessageDestinationRef=Duplicate message-destination-ref name -webXmlCommon.duplicateResourceEnvRef=Duplicate resource-env-ref name -webXmlCommon.duplicateResourceRef=Duplicate resource-ref name -webXmlCommon.reservedName=A web.xml file was detected using a reserved name [{0}]. The name element will be ignored for this fragment. -webXmlFragment.multipleOther=Multiple others entries in ordering +webRuleSet.absoluteOrdering=<absolute-ordering> element not valid in web-fragment.xml and will be ignored +webRuleSet.relativeOrdering=<ordering> element not valid in web.xml and will be ignored +webXml.duplicateEnvEntry=Duplicate env-entry name +webXml.duplicateFilter=Duplicate filter name +webXml.duplicateMessageDestination=Duplicate message-destination name +webXml.duplicateMessageDestinationRef=Duplicate message-destination-ref name +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.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/WebRuleSet.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/WebRuleSet.java?rev=829121&r1=829120&r2=829121&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/WebRuleSet.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/WebRuleSet.java Fri Oct 23 16:39:32 2009 @@ -33,6 +33,7 @@ import org.apache.tomcat.util.digester.Rule; import org.apache.tomcat.util.digester.RuleSetBase; import org.apache.tomcat.util.digester.SetNextRule; +import org.apache.tomcat.util.res.StringManager; import org.xml.sax.Attributes; @@ -46,6 +47,11 @@ public class WebRuleSet extends RuleSetBase { + /** + * The string resources for this package. + */ + protected static final StringManager sm = + StringManager.getManager(Constants.Package); // ----------------------------------------------------- Instance Variables @@ -62,6 +68,12 @@ protected String fullPrefix = null; /** + * Flag that indicates if this ruleset is for a web-fragment.xml file or for + * a web.xml file. + */ + protected boolean fragment = false; + + /** * The <code>SetSessionConfig</code> rule used to parse the web.xml */ protected SetSessionConfig sessionConfig; @@ -116,13 +128,13 @@ super(); this.namespaceURI = null; this.prefix = prefix; + this.fragment = fragment; if(fragment) { fullPrefix = prefix + "web-fragment"; } else { fullPrefix = prefix + "web-app"; } - } @@ -148,6 +160,31 @@ digester.addRule(fullPrefix, new IgnoreAnnotationsRule()); + digester.addCallMethod(fullPrefix + "/name", + "setName", 0); + + if (fragment) { + // web-fragment.xml + digester.addRule(fullPrefix + "/absolute-ordering", + new AbsoluteOrderingRule()); + digester.addCallMethod(fullPrefix + "/ordering/after/name", + "addAfterOrdering", 0); + digester.addCallMethod(fullPrefix + "/ordering/after/others", + "addAfterOrderingOthers"); + digester.addCallMethod(fullPrefix + "/ordering/before/name", + "addBeforeOrdering", 0); + digester.addCallMethod(fullPrefix + "/ordering/before/others", + "addBeforeOrderingOthers"); + } else { + // web.xml + digester.addRule(fullPrefix + "/ordering", + new RelativeOrderingRule()); + digester.addCallMethod(fullPrefix + "/absolute-ordering/name", + "addAbsoluteOrdering", 0); + digester.addCallMethod(fullPrefix + "/absolute-ordering/name/others", + "addAbsoluteOrderingOthers"); + } + digester.addCallMethod(fullPrefix + "/context-param", "addContextParam", 2); digester.addCallParam(fullPrefix + "/context-param/param-name", 0); @@ -904,6 +941,36 @@ } /** + * A rule that logs a warning if absolute ordering is configured. + */ +final class AbsoluteOrderingRule extends Rule { + + public AbsoluteOrderingRule() { + } + + public void begin(String namespace, String name, Attributes attributes) + throws Exception { + digester.getLogger().warn( + WebRuleSet.sm.getString("webRuleSet.absoluteOrdering")); + } +} + +/** + * A rule that logs a warning if relative ordering is configured. + */ +final class RelativeOrderingRule extends Rule { + + public RelativeOrderingRule() { + } + + public void begin(String namespace, String name, Attributes attributes) + throws Exception { + digester.getLogger().warn( + WebRuleSet.sm.getString("webRuleSet.relativeOrdering")); + } +} + +/** * A Rule that sets soap headers on the ContextHandler. * */ 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=829121&r1=829120&r2=829121&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/WebXml.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/WebXml.java Fri Oct 23 16:39:32 2009 @@ -18,6 +18,7 @@ package org.apache.catalina.startup; +import java.net.URL; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; @@ -65,13 +66,22 @@ // web.xml only elements // Absolute Ordering - private Set<String> absoluteOrdering = new LinkedHashSet<String>(); + private Set<String> absoluteOrdering = null; public void addAbsoluteOrdering(String name) { + if (absoluteOrdering == null) { + absoluteOrdering = new LinkedHashSet<String>(); + } absoluteOrdering.add(name); } public void addAbsoluteOrderingOthers() { + if (absoluteOrdering == null) { + absoluteOrdering = new LinkedHashSet<String>(); + } absoluteOrdering.add(ORDER_OTHERS); } + public Set<String> getAbsoluteOrdering() { + return absoluteOrdering; + } // web-fragment.xml only elements // Relative ordering @@ -82,7 +92,7 @@ public void addAfterOrderingOthers() { if (before.contains(ORDER_OTHERS)) { throw new IllegalArgumentException(sm.getString( - "webXmlFragment.multipleOther")); + "webXml.multipleOther")); } after.add(ORDER_OTHERS); } @@ -93,7 +103,7 @@ public void addBeforeOrderingOthers() { if (after.contains(ORDER_OTHERS)) { throw new IllegalArgumentException(sm.getString( - "webXmlFragment.multipleOther")); + "webXml.multipleOther")); } before.add(ORDER_OTHERS); } @@ -122,7 +132,7 @@ public void setName(String name) { if (ORDER_OTHERS.equalsIgnoreCase(name)) { // This is unusual. This name will be ignored. Log the fact. - log.warn(sm.getString("webXmlCommon.reservedName", name)); + log.warn(sm.getString("webXml.reservedName", name)); } else { this.name = name; } @@ -165,7 +175,7 @@ if (filters.containsKey(filter.getFilterName())) { // Filter names must be unique within a web(-fragment).xml throw new IllegalArgumentException( - sm.getString("webXmlCommon.duplicateFilter")); + sm.getString("webXml.duplicateFilter")); } filters.put(filter.getFilterName(), filter); } @@ -299,7 +309,7 @@ if (envEntries.containsKey(envEntry.getName())) { // env-entry names must be unique within a web(-fragment).xml throw new IllegalArgumentException( - sm.getString("webXmlCommon.duplicateEnvEntry")); + sm.getString("webXml.duplicateEnvEntry")); } envEntries.put(envEntry.getName(),envEntry); } @@ -337,7 +347,7 @@ if (resourceRefs.containsKey(resourceRef.getName())) { // resource-ref names must be unique within a web(-fragment).xml throw new IllegalArgumentException( - sm.getString("webXmlCommon.duplicateResourceRef")); + sm.getString("webXml.duplicateResourceRef")); } resourceRefs.put(resourceRef.getName(), resourceRef); } @@ -353,7 +363,7 @@ if (resourceEnvRefs.containsKey(resourceEnvRef.getName())) { // resource-env-ref names must be unique within a web(-fragment).xml throw new IllegalArgumentException( - sm.getString("webXmlCommon.duplicateResourceEnvRef")); + sm.getString("webXml.duplicateResourceEnvRef")); } resourceEnvRefs.put(resourceEnvRef.getName(), resourceEnvRef); } @@ -372,7 +382,7 @@ // message-destination-ref names must be unique within a // web(-fragment).xml throw new IllegalArgumentException(sm.getString( - "webXmlCommon.duplicateMessageDestinationRef")); + "webXml.duplicateMessageDestinationRef")); } messageDestinationRefs.put(messageDestinationRef.getName(), messageDestinationRef); @@ -394,7 +404,7 @@ // message-destination names must be unique within a // web(-fragment).xml throw new IllegalArgumentException( - sm.getString("webXmlCommon.duplicateMessageDestination")); + sm.getString("webXml.duplicateMessageDestination")); } messageDestinations.put(messageDestination.getName(), messageDestination); @@ -413,6 +423,14 @@ return localeEncodingMappings; } + + // Attributes not defined in web.xml or web-fragment.xml + + // URL of web-fragment + private URL uRL = null; + public void setURL(URL url) { this.uRL = url; } + public URL getURL() { return uRL; } + /** * Configure a {...@link Context} using the stored web.xml representation. * @@ -538,4 +556,33 @@ context.addJspMapping(jspPropertyGroup.getUrlPattern()); } } + + /** + * Merge the supplied web fragment into this this one. + * + * @param source The fragment to merge in + * @boolean ignoreConflicts Flag that indicates that conflicts should be + * ignored and the existing value used + * @return <code>true</code> if merge is successful, else + * <code>false</code> + */ + public boolean merge(WebXml source, boolean ignoreConflicts) { + // TODO SERVLET3 + + // 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; + } + } else { + listeners.add(listener); + } + } + + return true; + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org