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

Reply via email to