Track the TLD URIs processed for each webapp and don't process duplicates.
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Mon, 13 Jul 2009 16:43:26 +0000 (16:43 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Mon, 13 Jul 2009 16:43:26 +0000 (16:43 +0000)
Because this tracks duplicate status in the RuleSet, each digester needs its own RuleSet rather than sharing the static one.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@793621 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/startup/TldConfig.java
java/org/apache/catalina/startup/TldRuleSet.java

index 2edf357..58e6f03 100644 (file)
@@ -80,8 +80,6 @@ public final class TldConfig  implements LifecycleListener {
      */
     private static Digester[] tldDigesters = new Digester[4];
 
-    private static final TldRuleSet tldRuleSet = new TldRuleSet();
-    
     /*
      * Initializes the set of JARs that are known not to contain any TLDs
      */
@@ -145,25 +143,25 @@ public final class TldConfig  implements LifecycleListener {
         if (!namespaceAware && !validation) {
             if (tldDigesters[0] == null) {
                 tldDigesters[0] = DigesterFactory.newDigester(validation,
-                        namespaceAware, tldRuleSet);
+                        namespaceAware, new TldRuleSet());
             }
             digester = tldDigesters[0];
         } else if (!namespaceAware && validation) {
             if (tldDigesters[1] == null) {
                 tldDigesters[1] = DigesterFactory.newDigester(validation,
-                        namespaceAware, tldRuleSet);
+                        namespaceAware, new TldRuleSet());
             }
             digester = tldDigesters[1];
         } else if (namespaceAware && !validation) {
             if (tldDigesters[2] == null) {
                 tldDigesters[2] = DigesterFactory.newDigester(validation,
-                        namespaceAware, tldRuleSet);
+                        namespaceAware, new TldRuleSet());
             }
             digester = tldDigesters[2];
         } else {
             if (tldDigesters[3] == null) {
                 tldDigesters[3] = DigesterFactory.newDigester(validation,
-                        namespaceAware, tldRuleSet);
+                        namespaceAware, new TldRuleSet());
             }
             digester = tldDigesters[3];
         }
@@ -199,11 +197,32 @@ public final class TldConfig  implements LifecycleListener {
 
     private boolean rescan=true;
 
+    /**
+     * Set of URIs discovered for the associated context. Used to enforce the
+     * correct processing priority. Only the TLD associated with the first
+     * instance of any URI will be processed.
+     */
+    private Set<String> taglibUris = new HashSet<String>();
+    
     private ArrayList<String> listeners = new ArrayList<String>();
 
     // --------------------------------------------------------- Public Methods
 
     /**
+     * Adds a taglib URI to the list of known URIs.
+     */
+    public void addTaglibUri(String uri) {
+        taglibUris.add(uri);
+    }
+
+    /**
+     * Determines if the provided URI is a known taglib URI.
+     */
+    public boolean isKnownTaglibUri(String uri) {
+        return taglibUris.contains(uri);
+    }
+
+    /**
      * Sets the list of JARs that are known not to contain any TLDs.
      *
      * @param jarNames List of comma-separated names of JAR files that are 
index e11ea99..b24218e 100644 (file)
@@ -20,6 +20,7 @@ package org.apache.catalina.startup;
 
 
 import org.apache.tomcat.util.digester.Digester;
+import org.apache.tomcat.util.digester.Rule;
 import org.apache.tomcat.util.digester.RuleSetBase;
 
 
@@ -87,10 +88,65 @@ public class TldRuleSet extends RuleSetBase {
      */
     public void addRuleInstances(Digester digester) {
 
-        digester.addCallMethod(prefix + "taglib/listener/listener-class",
-                               "addApplicationListener", 0);
+        TaglibUriRule taglibUriRule = new TaglibUriRule(); 
+        
+        digester.addRule(prefix + "taglib/uri", taglibUriRule);
+
+        digester.addRule(prefix + "taglib/listener/listener-class",
+                new TaglibListenerRule(taglibUriRule));
 
     }
 
 
 }
+
+final class TaglibUriRule extends Rule {
+    
+    private boolean duplicateUri;
+    
+    public TaglibUriRule() {
+    }
+
+    @Override
+    public void body(String namespace, String name, String text)
+            throws Exception {
+        TldConfig tldConfig =
+            (TldConfig) digester.peek(digester.getCount() - 1);
+        if (tldConfig.isKnownTaglibUri(text)) {
+            // Already seen this URI
+            duplicateUri = true;
+            digester.getLogger().info(
+                    "TLD skipped. URI: " + text + " is already defined");
+        } else {
+            // New URI. Add it to known list and carry on
+            duplicateUri = false;
+            tldConfig.addTaglibUri(text);
+        }
+    }
+    
+    public boolean isDuplicateUri() {
+        return duplicateUri;
+    }
+}
+
+final class TaglibListenerRule extends Rule {
+    
+    private final TaglibUriRule taglibUriRule;
+    
+    public TaglibListenerRule(TaglibUriRule taglibUriRule) {
+        this.taglibUriRule = taglibUriRule;
+    }
+
+    @Override
+    public void body(String namespace, String name, String text)
+            throws Exception {
+        TldConfig tldConfig =
+            (TldConfig) digester.peek(digester.getCount() - 1);
+        
+        // Only process the listener if the URI is not a duplicate
+        if (!taglibUriRule.isDuplicateUri()) {
+            tldConfig.addApplicationListener(text);
+        }
+    }
+    
+}
\ No newline at end of file