You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by jb...@apache.org on 2013/08/11 23:24:50 UTC

svn commit: r1513007 - in /tomcat/trunk: java/org/apache/jasper/servlet/ java/org/apache/tomcat/util/descriptor/tld/ test/org/apache/tomcat/util/descriptor/tld/

Author: jboynes
Date: Sun Aug 11 21:24:50 2013
New Revision: 1513007

URL: http://svn.apache.org/r1513007
Log:
Refactor TLD scanning and parsing around the notion of a TLD resource path as defined by the JSP specification.

Added:
    tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java   (with props)
Modified:
    tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java
    tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java
    tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java

Modified: tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java?rev=1513007&r1=1513006&r2=1513007&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java (original)
+++ tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java Sun Aug 11 21:24:50 2013
@@ -18,7 +18,6 @@ package org.apache.jasper.servlet;
 
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.JarURLConnection;
 import java.net.URL;
 import java.nio.file.FileVisitResult;
@@ -46,9 +45,9 @@ import org.apache.tomcat.JarScanner;
 import org.apache.tomcat.JarScannerCallback;
 import org.apache.tomcat.util.descriptor.tld.TaglibXml;
 import org.apache.tomcat.util.descriptor.tld.TldParser;
+import org.apache.tomcat.util.descriptor.tld.TldResourcePath;
 import org.apache.tomcat.util.scan.Jar;
 import org.apache.tomcat.util.scan.JarFactory;
-import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 
 /**
@@ -61,7 +60,8 @@ public class TldScanner {
     private static final String WEB_INF = "/WEB-INF/";
     private final ServletContext context;
     private final TldParser tldParser;
-    private final Map<String, TaglibXml> taglibMap = new HashMap<>();
+    private final Map<String, TldResourcePath> taglibMap = new HashMap<>();
+    private final Map<TldResourcePath, TaglibXml> tldCache = new HashMap<>();
     private final List<String> listeners = new ArrayList<>();
 
     /**
@@ -86,16 +86,14 @@ public class TldScanner {
      * <li>Additional entries from the container</li>
      * </ol>
      *
-     * @return the taglib map build by this scan
      * @throws IOException  if there was a problem scanning for or loading a TLD
      * @throws SAXException if there was a problem parsing a TLD
      */
-    public Map<String, TaglibXml> scan() throws IOException, SAXException {
+    public void scan() throws IOException, SAXException {
         scanPlatform();
         scanJspConfig();
         scanResourcePaths(WEB_INF);
         scanJars();
-        return taglibMap;
     }
 
     /**
@@ -103,7 +101,7 @@ public class TldScanner {
      *
      * @return the taglib map
      */
-    public Map<String, TaglibXml> getTaglibMap() {
+    public Map<String, TldResourcePath> getTaglibMap() {
         return taglibMap;
     }
 
@@ -156,16 +154,21 @@ public class TldScanner {
             }
 
             URL url = context.getResource(resourcePath);
+            TldResourcePath tldResourcePath;
             if (resourcePath.endsWith(".jar")) {
                 // if the path points to a jar file, the TLD is presumed to be
                 // inside at META-INF/taglib.tld
-                url = new URL ("jar:" +
-                        url.toExternalForm() +
-                        "!/META-INF/taglib.tld");
+                tldResourcePath = new TldResourcePath(url, "META-INF/taglib.tld");
+            } else {
+                tldResourcePath = new TldResourcePath(url);
+            }
+            // parse TLD but store using the URI supplied in the descriptor
+            TaglibXml tld = tldParser.parse(tldResourcePath);
+            taglibMap.put(taglibURI, tldResourcePath);
+            tldCache.put(tldResourcePath, tld);
+            if (tld.getListeners() != null) {
+                listeners.addAll(tld.getListeners());
             }
-
-            TaglibXml tld = tldParser.parse(url);
-            taglibMap.put(taglibURI, tld);
         }
     }
 
@@ -209,21 +212,20 @@ public class TldScanner {
     }
 
     private void parseTld(String resourcePath) throws IOException, SAXException {
-        parseTld(context.getResource(resourcePath));
-    }
-
-    private void parseTld(URL url) throws IOException, SAXException {
-        TaglibXml tld = tldParser.parse(url);
-        registerTld(tld);
+        TldResourcePath tldResourcePath =
+                new TldResourcePath(context.getResource(resourcePath));
+        parseTld(tldResourcePath);
     }
 
-    private void registerTld(TaglibXml tld) {
+    private void parseTld(TldResourcePath path) throws IOException, SAXException {
+        TaglibXml tld = tldParser.parse(path);
         String uri = tld.getUri();
         if (uri != null) {
             if (!taglibMap.containsKey(uri)) {
-                taglibMap.put(uri, tld);
+                taglibMap.put(uri, path);
             }
         }
+        tldCache.put(path, tld);
         if (tld.getListeners() != null) {
             listeners.addAll(tld.getListeners());
         }
@@ -236,9 +238,7 @@ public class TldScanner {
         public void scan(JarURLConnection urlConn, boolean isWebapp) throws IOException {
             boolean found = false;
             Jar jar = JarFactory.newInstance(urlConn.getURL());
-            StringBuilder base = new StringBuilder(256);
-            base.append("jar:").append(urlConn.getURL()).append("!/");
-            int baseLength = base.length();
+            URL jarURL = urlConn.getJarFileURL();
             try {
                 jar.nextEntry();
                 for (String entryName = jar.getEntryName();
@@ -249,13 +249,10 @@ public class TldScanner {
                         continue;
                     }
                     found = true;
-                    String location = base.append(entryName).toString();
-                    base.setLength(baseLength);
-                    try (InputStream is = jar.getEntryInputStream()) {
-                        InputSource source = new InputSource(is);
-                        source.setSystemId(location);
-                        TaglibXml tld = tldParser.parse(source);
-                        registerTld(tld);
+                    TldResourcePath tldResourcePath =
+                            new TldResourcePath(jarURL, entryName);
+                    try {
+                        parseTld(tldResourcePath);
                     } catch (SAXException e) {
                         throw new IOException(e);
                     }
@@ -268,7 +265,7 @@ public class TldScanner {
             } else {
                 if (log.isDebugEnabled()) {
                     log.debug(Localizer.getMessage("jsp.tldCache.noTldInJar",
-                            urlConn.getJarFileURL().toString()));
+                            jarURL.toString()));
                 }
             }
         }
@@ -284,13 +281,17 @@ public class TldScanner {
                 public FileVisitResult visitFile(Path file,
                                                  BasicFileAttributes attrs)
                         throws IOException {
-                    if (file.endsWith(TLD_EXT)) {
-                        try {
-                            parseTld(file.toUri().toURL());
-                            tldFound = true;
-                        } catch (SAXException e) {
-                            throw new IOException(e);
-                        }
+                    if (!file.endsWith(TLD_EXT)) {
+                        return FileVisitResult.CONTINUE;
+                    }
+
+                    try {
+                        URL url = file.toUri().toURL();
+                        TldResourcePath path = new TldResourcePath(url);
+                        parseTld(path);
+                        tldFound = true;
+                    } catch (SAXException e) {
+                        throw new IOException(e);
                     }
                     return FileVisitResult.CONTINUE;
                 }

Modified: tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java?rev=1513007&r1=1513006&r2=1513007&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java Sun Aug 11 21:24:50 2013
@@ -17,7 +17,7 @@
 package org.apache.tomcat.util.descriptor.tld;
 
 import java.io.IOException;
-import java.net.URL;
+import java.io.InputStream;
 
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
@@ -32,7 +32,6 @@ import org.xml.sax.SAXException;
  */
 public class TldParser {
     private static final Log LOG = LogFactory.getLog(TldParser.class);
-
     private final Digester digester;
 
     public TldParser(boolean namespaceAware, boolean validation) {
@@ -40,19 +39,16 @@ public class TldParser {
         digester = DigesterFactory.newDigester(validation, namespaceAware, ruleSet);
     }
 
-    public TaglibXml parse(URL url) throws IOException, SAXException {
-        InputSource source = new InputSource(url.toExternalForm());
-        source.setByteStream(url.openStream());
-        return parse(source);
-    }
-
-    public TaglibXml parse(InputSource source) throws IOException, SAXException {
-        try {
+    public TaglibXml parse(TldResourcePath path) throws IOException, SAXException {
+        try (InputStream is = path.openStream()) {
             XmlErrorHandler handler = new XmlErrorHandler();
             digester.setErrorHandler(handler);
 
             TaglibXml taglibXml = new TaglibXml();
             digester.push(taglibXml);
+
+            InputSource source = new InputSource(path.toExternalForm());
+            source.setByteStream(is);
             digester.parse(source);
             if (!handler.getWarnings().isEmpty() || !handler.getErrors().isEmpty()) {
                 handler.logFindings(LOG, source.getSystemId());

Added: tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java?rev=1513007&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java Sun Aug 11 21:24:50 2013
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.descriptor.tld;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Objects;
+
+/**
+ * A TLD Resource Path as defined in JSP 7.3.2.
+ * <p/>
+ * This encapsulates references to Tag Library Descriptors that can be located
+ * in different places:
+ * <ul>
+ * <li>As resources within an application</li>
+ * <li>As entries in JAR files included in the application</li>
+ * <li>As resources provided by the container</li>
+ * </ul>
+ * When configuring a mapping from a well-known URI to a TLD, a user is allowed
+ * to specify just the name of a JAR file that implicitly contains a TLD in
+ * <code>META-INF/taglib.tld</code>. Such a mapping must be explcitly converted
+ * to a URL and entryName when using this implementation.
+ */
+public class TldResourcePath {
+    private final URL url;
+    private final String entryName;
+
+    /**
+     * Constructor identifying a TLD resource directly.
+     *
+     * @param url the location of the TLD
+     */
+    public TldResourcePath(URL url) {
+        this(url, null);
+    }
+
+    /**
+     * Constructor identifying a TLD packaged within a JAR file.
+     *
+     * @param url       the location of the JAR
+     * @param entryName the name of the entry in the JAR
+     */
+    public TldResourcePath(URL url, String entryName) {
+        this.url = url;
+        this.entryName = entryName;
+    }
+
+    /**
+     * Returns the URL of the TLD or of the JAR containing the TLD.
+     *
+     * @return the URL of the TLD
+     */
+    public URL getUrl() {
+        return url;
+    }
+
+    /**
+     * Returns the name of the JAR entry that contains the TLD.
+     * May be null to indicate the URL refers directly to the TLD itself.
+     *
+     * @return the name of the JAR entry that contains the TLD
+     */
+    public String getEntryName() {
+        return entryName;
+    }
+
+    /**
+     * Return the external form of the URL representing this TLD.
+     * This can be used as a canonical location for the TLD itself, for example,
+     * as the systemId to use when parsing its XML.
+     *
+     * @return the external form of the URL representing this TLD
+     */
+    public String toExternalForm() {
+        if (entryName == null) {
+            return url.toExternalForm();
+        } else {
+            return "jar:" + url.toExternalForm() + "!/" + entryName;
+        }
+    }
+
+    /**
+     * Opens a stream to access the TLD.
+     *
+     * @return a stream containing the TLD content
+     * @throws IOException if there was a problem opening the stream
+     */
+    public InputStream openStream() throws IOException {
+        if (entryName == null) {
+            return url.openStream();
+        } else {
+            // TODO: should this use the JarFactory abstraction?
+            URL entryUrl = new URL("jar:" + url.toExternalForm() + "!/" + entryName);
+            return entryUrl.openStream();
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        TldResourcePath other = (TldResourcePath) o;
+        return url.equals(other.url) && Objects.equals(entryName, other.entryName);
+    }
+
+    @Override
+    public int hashCode() {
+        return url.hashCode() * 31 + Objects.hashCode(entryName);
+    }
+}

Propchange: tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java?rev=1513007&r1=1513006&r2=1513007&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java (original)
+++ tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java Sun Aug 11 21:24:50 2013
@@ -16,14 +16,15 @@
  */
 package org.apache.tomcat.util.descriptor.tld;
 
-import java.io.FileInputStream;
+import java.io.File;
+import java.io.IOException;
 import java.util.List;
 
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
 
 public class TestTldParser {
     private static final String WEBAPP = "test/webapp-3.1/WEB-INF/";
@@ -36,54 +37,42 @@ public class TestTldParser {
 
     @Test
     public void testParseTld21() throws Exception {
-        try (FileInputStream is = new FileInputStream(WEBAPP + "tags21.tld")) {
-            InputSource source = new InputSource(is);
-            TaglibXml xml = parser.parse(source);
-            Assert.assertEquals("1.0", xml.getTlibVersion());
-            Assert.assertEquals("2.1", xml.getJspVersion());
-            Assert.assertEquals("Tags21", xml.getShortName());
-            Assert.assertEquals("http://tomcat.apache.org/tags21", xml.getUri());
-            verifyTags(xml.getTags());
-        }
+        TaglibXml xml = parse("test/webapp-3.1/WEB-INF/tags21.tld");
+        Assert.assertEquals("1.0", xml.getTlibVersion());
+        Assert.assertEquals("2.1", xml.getJspVersion());
+        Assert.assertEquals("Tags21", xml.getShortName());
+        Assert.assertEquals("http://tomcat.apache.org/tags21", xml.getUri());
+        verifyTags(xml.getTags());
     }
 
     @Test
     public void testParseTld20() throws Exception {
-        try (FileInputStream is = new FileInputStream(WEBAPP + "tags20.tld")) {
-            InputSource source = new InputSource(is);
-            TaglibXml xml = parser.parse(source);
-            Assert.assertEquals("1.0", xml.getTlibVersion());
-            Assert.assertEquals("2.0", xml.getJspVersion());
-            Assert.assertEquals("Tags20", xml.getShortName());
-            Assert.assertEquals("http://tomcat.apache.org/tags20", xml.getUri());
-            verifyTags(xml.getTags());
-        }
+        TaglibXml xml = parse("test/webapp-3.1/WEB-INF/tags20.tld");
+        Assert.assertEquals("1.0", xml.getTlibVersion());
+        Assert.assertEquals("2.0", xml.getJspVersion());
+        Assert.assertEquals("Tags20", xml.getShortName());
+        Assert.assertEquals("http://tomcat.apache.org/tags20", xml.getUri());
+        verifyTags(xml.getTags());
     }
 
     @Test
     public void testParseTld12() throws Exception {
-        try (FileInputStream is = new FileInputStream(WEBAPP + "tags12.tld")) {
-            InputSource source = new InputSource(is);
-            TaglibXml xml = parser.parse(source);
-            Assert.assertEquals("1.0", xml.getTlibVersion());
-            Assert.assertEquals("1.2", xml.getJspVersion());
-            Assert.assertEquals("Tags12", xml.getShortName());
-            Assert.assertEquals("http://tomcat.apache.org/tags12", xml.getUri());
-            verifyTags(xml.getTags());
-        }
+        TaglibXml xml = parse("test/webapp-3.1/WEB-INF/tags12.tld");
+        Assert.assertEquals("1.0", xml.getTlibVersion());
+        Assert.assertEquals("1.2", xml.getJspVersion());
+        Assert.assertEquals("Tags12", xml.getShortName());
+        Assert.assertEquals("http://tomcat.apache.org/tags12", xml.getUri());
+        verifyTags(xml.getTags());
     }
 
     @Test
     public void testParseTld11() throws Exception {
-        try (FileInputStream is = new FileInputStream(WEBAPP + "tags11.tld")) {
-            InputSource source = new InputSource(is);
-            TaglibXml xml = parser.parse(source);
-            Assert.assertEquals("1.0", xml.getTlibVersion());
-            Assert.assertEquals("1.1", xml.getJspVersion());
-            Assert.assertEquals("Tags11", xml.getShortName());
-            Assert.assertEquals("http://tomcat.apache.org/tags11", xml.getUri());
-            verifyTags(xml.getTags());
-        }
+        TaglibXml xml = parse("test/webapp-3.1/WEB-INF/tags11.tld");
+        Assert.assertEquals("1.0", xml.getTlibVersion());
+        Assert.assertEquals("1.1", xml.getJspVersion());
+        Assert.assertEquals("Tags11", xml.getShortName());
+        Assert.assertEquals("http://tomcat.apache.org/tags11", xml.getUri());
+        verifyTags(xml.getTags());
     }
 
     private void verifyTags(List<Tag> tags) {
@@ -97,14 +86,17 @@ public class TestTldParser {
 
     @Test
     public void testListener() throws Exception {
-        try (FileInputStream is = new FileInputStream("test/webapp-3.0/WEB-INF/listener.tld")) {
-            InputSource source = new InputSource(is);
-            TaglibXml xml = parser.parse(source);
-            Assert.assertEquals("1.0", xml.getTlibVersion());
-            List<String> listeners = xml.getListeners();
-            Assert.assertEquals(1, listeners.size());
-            Assert.assertEquals("org.apache.catalina.core.TesterTldListener", listeners.get(0));
-        }
+        TaglibXml xml = parse("test/webapp-3.0/WEB-INF/listener.tld");
+        Assert.assertEquals("1.0", xml.getTlibVersion());
+        List<String> listeners = xml.getListeners();
+        Assert.assertEquals(1, listeners.size());
+        Assert.assertEquals("org.apache.catalina.core.TesterTldListener", listeners.get(0));
+    }
+
+    private TaglibXml parse(String pathname) throws IOException, SAXException {
+        File file = new File(pathname);
+        TldResourcePath path = new TldResourcePath(file.toURI().toURL());
+        return parser.parse(path);
     }
 
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Back-port JSP/TLD changes to 7.0.x?, was: svn commit: r1513007 ...

Posted by Jeremy Boynes <jb...@apache.org>.
On Aug 12, 2013, at 12:33 PM, Christopher Schultz <ch...@christopherschultz.net> wrote:

> Jeremy,
> 
> Will you be back-porting any of this to Tomcat 7? Or is the idea that so
> many things will be changing that it's unfair to surprise Tomcat 7 users
> with these changes?

As is, I think this would be too big a change for a 7.0.x release. We can take a look once it's done and see if some portions can be used for more incremental improvements.

Cheers
Jeremy


Re: svn commit: r1513007 - in /tomcat/trunk: java/org/apache/jasper/servlet/ java/org/apache/tomcat/util/descriptor/tld/ test/org/apache/tomcat/util/descriptor/tld/

Posted by Christopher Schultz <ch...@christopherschultz.net>.
Jeremy,

Will you be back-porting any of this to Tomcat 7? Or is the idea that so
many things will be changing that it's unfair to surprise Tomcat 7 users
with these changes?

-chris

On 8/11/13 5:24 PM, jboynes@apache.org wrote:
> Author: jboynes
> Date: Sun Aug 11 21:24:50 2013
> New Revision: 1513007
> 
> URL: http://svn.apache.org/r1513007
> Log:
> Refactor TLD scanning and parsing around the notion of a TLD resource path as defined by the JSP specification.
> 
> Added:
>     tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java   (with props)
> Modified:
>     tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java
>     tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java
>     tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java
> 
> Modified: tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java
> URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java?rev=1513007&r1=1513006&r2=1513007&view=diff
> ==============================================================================
> --- tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java (original)
> +++ tomcat/trunk/java/org/apache/jasper/servlet/TldScanner.java Sun Aug 11 21:24:50 2013
> @@ -18,7 +18,6 @@ package org.apache.jasper.servlet;
>  
>  import java.io.File;
>  import java.io.IOException;
> -import java.io.InputStream;
>  import java.net.JarURLConnection;
>  import java.net.URL;
>  import java.nio.file.FileVisitResult;
> @@ -46,9 +45,9 @@ import org.apache.tomcat.JarScanner;
>  import org.apache.tomcat.JarScannerCallback;
>  import org.apache.tomcat.util.descriptor.tld.TaglibXml;
>  import org.apache.tomcat.util.descriptor.tld.TldParser;
> +import org.apache.tomcat.util.descriptor.tld.TldResourcePath;
>  import org.apache.tomcat.util.scan.Jar;
>  import org.apache.tomcat.util.scan.JarFactory;
> -import org.xml.sax.InputSource;
>  import org.xml.sax.SAXException;
>  
>  /**
> @@ -61,7 +60,8 @@ public class TldScanner {
>      private static final String WEB_INF = "/WEB-INF/";
>      private final ServletContext context;
>      private final TldParser tldParser;
> -    private final Map<String, TaglibXml> taglibMap = new HashMap<>();
> +    private final Map<String, TldResourcePath> taglibMap = new HashMap<>();
> +    private final Map<TldResourcePath, TaglibXml> tldCache = new HashMap<>();
>      private final List<String> listeners = new ArrayList<>();
>  
>      /**
> @@ -86,16 +86,14 @@ public class TldScanner {
>       * <li>Additional entries from the container</li>
>       * </ol>
>       *
> -     * @return the taglib map build by this scan
>       * @throws IOException  if there was a problem scanning for or loading a TLD
>       * @throws SAXException if there was a problem parsing a TLD
>       */
> -    public Map<String, TaglibXml> scan() throws IOException, SAXException {
> +    public void scan() throws IOException, SAXException {
>          scanPlatform();
>          scanJspConfig();
>          scanResourcePaths(WEB_INF);
>          scanJars();
> -        return taglibMap;
>      }
>  
>      /**
> @@ -103,7 +101,7 @@ public class TldScanner {
>       *
>       * @return the taglib map
>       */
> -    public Map<String, TaglibXml> getTaglibMap() {
> +    public Map<String, TldResourcePath> getTaglibMap() {
>          return taglibMap;
>      }
>  
> @@ -156,16 +154,21 @@ public class TldScanner {
>              }
>  
>              URL url = context.getResource(resourcePath);
> +            TldResourcePath tldResourcePath;
>              if (resourcePath.endsWith(".jar")) {
>                  // if the path points to a jar file, the TLD is presumed to be
>                  // inside at META-INF/taglib.tld
> -                url = new URL ("jar:" +
> -                        url.toExternalForm() +
> -                        "!/META-INF/taglib.tld");
> +                tldResourcePath = new TldResourcePath(url, "META-INF/taglib.tld");
> +            } else {
> +                tldResourcePath = new TldResourcePath(url);
> +            }
> +            // parse TLD but store using the URI supplied in the descriptor
> +            TaglibXml tld = tldParser.parse(tldResourcePath);
> +            taglibMap.put(taglibURI, tldResourcePath);
> +            tldCache.put(tldResourcePath, tld);
> +            if (tld.getListeners() != null) {
> +                listeners.addAll(tld.getListeners());
>              }
> -
> -            TaglibXml tld = tldParser.parse(url);
> -            taglibMap.put(taglibURI, tld);
>          }
>      }
>  
> @@ -209,21 +212,20 @@ public class TldScanner {
>      }
>  
>      private void parseTld(String resourcePath) throws IOException, SAXException {
> -        parseTld(context.getResource(resourcePath));
> -    }
> -
> -    private void parseTld(URL url) throws IOException, SAXException {
> -        TaglibXml tld = tldParser.parse(url);
> -        registerTld(tld);
> +        TldResourcePath tldResourcePath =
> +                new TldResourcePath(context.getResource(resourcePath));
> +        parseTld(tldResourcePath);
>      }
>  
> -    private void registerTld(TaglibXml tld) {
> +    private void parseTld(TldResourcePath path) throws IOException, SAXException {
> +        TaglibXml tld = tldParser.parse(path);
>          String uri = tld.getUri();
>          if (uri != null) {
>              if (!taglibMap.containsKey(uri)) {
> -                taglibMap.put(uri, tld);
> +                taglibMap.put(uri, path);
>              }
>          }
> +        tldCache.put(path, tld);
>          if (tld.getListeners() != null) {
>              listeners.addAll(tld.getListeners());
>          }
> @@ -236,9 +238,7 @@ public class TldScanner {
>          public void scan(JarURLConnection urlConn, boolean isWebapp) throws IOException {
>              boolean found = false;
>              Jar jar = JarFactory.newInstance(urlConn.getURL());
> -            StringBuilder base = new StringBuilder(256);
> -            base.append("jar:").append(urlConn.getURL()).append("!/");
> -            int baseLength = base.length();
> +            URL jarURL = urlConn.getJarFileURL();
>              try {
>                  jar.nextEntry();
>                  for (String entryName = jar.getEntryName();
> @@ -249,13 +249,10 @@ public class TldScanner {
>                          continue;
>                      }
>                      found = true;
> -                    String location = base.append(entryName).toString();
> -                    base.setLength(baseLength);
> -                    try (InputStream is = jar.getEntryInputStream()) {
> -                        InputSource source = new InputSource(is);
> -                        source.setSystemId(location);
> -                        TaglibXml tld = tldParser.parse(source);
> -                        registerTld(tld);
> +                    TldResourcePath tldResourcePath =
> +                            new TldResourcePath(jarURL, entryName);
> +                    try {
> +                        parseTld(tldResourcePath);
>                      } catch (SAXException e) {
>                          throw new IOException(e);
>                      }
> @@ -268,7 +265,7 @@ public class TldScanner {
>              } else {
>                  if (log.isDebugEnabled()) {
>                      log.debug(Localizer.getMessage("jsp.tldCache.noTldInJar",
> -                            urlConn.getJarFileURL().toString()));
> +                            jarURL.toString()));
>                  }
>              }
>          }
> @@ -284,13 +281,17 @@ public class TldScanner {
>                  public FileVisitResult visitFile(Path file,
>                                                   BasicFileAttributes attrs)
>                          throws IOException {
> -                    if (file.endsWith(TLD_EXT)) {
> -                        try {
> -                            parseTld(file.toUri().toURL());
> -                            tldFound = true;
> -                        } catch (SAXException e) {
> -                            throw new IOException(e);
> -                        }
> +                    if (!file.endsWith(TLD_EXT)) {
> +                        return FileVisitResult.CONTINUE;
> +                    }
> +
> +                    try {
> +                        URL url = file.toUri().toURL();
> +                        TldResourcePath path = new TldResourcePath(url);
> +                        parseTld(path);
> +                        tldFound = true;
> +                    } catch (SAXException e) {
> +                        throw new IOException(e);
>                      }
>                      return FileVisitResult.CONTINUE;
>                  }
> 
> Modified: tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java
> URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java?rev=1513007&r1=1513006&r2=1513007&view=diff
> ==============================================================================
> --- tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java (original)
> +++ tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldParser.java Sun Aug 11 21:24:50 2013
> @@ -17,7 +17,7 @@
>  package org.apache.tomcat.util.descriptor.tld;
>  
>  import java.io.IOException;
> -import java.net.URL;
> +import java.io.InputStream;
>  
>  import org.apache.juli.logging.Log;
>  import org.apache.juli.logging.LogFactory;
> @@ -32,7 +32,6 @@ import org.xml.sax.SAXException;
>   */
>  public class TldParser {
>      private static final Log LOG = LogFactory.getLog(TldParser.class);
> -
>      private final Digester digester;
>  
>      public TldParser(boolean namespaceAware, boolean validation) {
> @@ -40,19 +39,16 @@ public class TldParser {
>          digester = DigesterFactory.newDigester(validation, namespaceAware, ruleSet);
>      }
>  
> -    public TaglibXml parse(URL url) throws IOException, SAXException {
> -        InputSource source = new InputSource(url.toExternalForm());
> -        source.setByteStream(url.openStream());
> -        return parse(source);
> -    }
> -
> -    public TaglibXml parse(InputSource source) throws IOException, SAXException {
> -        try {
> +    public TaglibXml parse(TldResourcePath path) throws IOException, SAXException {
> +        try (InputStream is = path.openStream()) {
>              XmlErrorHandler handler = new XmlErrorHandler();
>              digester.setErrorHandler(handler);
>  
>              TaglibXml taglibXml = new TaglibXml();
>              digester.push(taglibXml);
> +
> +            InputSource source = new InputSource(path.toExternalForm());
> +            source.setByteStream(is);
>              digester.parse(source);
>              if (!handler.getWarnings().isEmpty() || !handler.getErrors().isEmpty()) {
>                  handler.logFindings(LOG, source.getSystemId());
> 
> Added: tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java
> URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java?rev=1513007&view=auto
> ==============================================================================
> --- tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java (added)
> +++ tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java Sun Aug 11 21:24:50 2013
> @@ -0,0 +1,130 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache License, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License.  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.tomcat.util.descriptor.tld;
> +
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.net.URL;
> +import java.util.Objects;
> +
> +/**
> + * A TLD Resource Path as defined in JSP 7.3.2.
> + * <p/>
> + * This encapsulates references to Tag Library Descriptors that can be located
> + * in different places:
> + * <ul>
> + * <li>As resources within an application</li>
> + * <li>As entries in JAR files included in the application</li>
> + * <li>As resources provided by the container</li>
> + * </ul>
> + * When configuring a mapping from a well-known URI to a TLD, a user is allowed
> + * to specify just the name of a JAR file that implicitly contains a TLD in
> + * <code>META-INF/taglib.tld</code>. Such a mapping must be explcitly converted
> + * to a URL and entryName when using this implementation.
> + */
> +public class TldResourcePath {
> +    private final URL url;
> +    private final String entryName;
> +
> +    /**
> +     * Constructor identifying a TLD resource directly.
> +     *
> +     * @param url the location of the TLD
> +     */
> +    public TldResourcePath(URL url) {
> +        this(url, null);
> +    }
> +
> +    /**
> +     * Constructor identifying a TLD packaged within a JAR file.
> +     *
> +     * @param url       the location of the JAR
> +     * @param entryName the name of the entry in the JAR
> +     */
> +    public TldResourcePath(URL url, String entryName) {
> +        this.url = url;
> +        this.entryName = entryName;
> +    }
> +
> +    /**
> +     * Returns the URL of the TLD or of the JAR containing the TLD.
> +     *
> +     * @return the URL of the TLD
> +     */
> +    public URL getUrl() {
> +        return url;
> +    }
> +
> +    /**
> +     * Returns the name of the JAR entry that contains the TLD.
> +     * May be null to indicate the URL refers directly to the TLD itself.
> +     *
> +     * @return the name of the JAR entry that contains the TLD
> +     */
> +    public String getEntryName() {
> +        return entryName;
> +    }
> +
> +    /**
> +     * Return the external form of the URL representing this TLD.
> +     * This can be used as a canonical location for the TLD itself, for example,
> +     * as the systemId to use when parsing its XML.
> +     *
> +     * @return the external form of the URL representing this TLD
> +     */
> +    public String toExternalForm() {
> +        if (entryName == null) {
> +            return url.toExternalForm();
> +        } else {
> +            return "jar:" + url.toExternalForm() + "!/" + entryName;
> +        }
> +    }
> +
> +    /**
> +     * Opens a stream to access the TLD.
> +     *
> +     * @return a stream containing the TLD content
> +     * @throws IOException if there was a problem opening the stream
> +     */
> +    public InputStream openStream() throws IOException {
> +        if (entryName == null) {
> +            return url.openStream();
> +        } else {
> +            // TODO: should this use the JarFactory abstraction?
> +            URL entryUrl = new URL("jar:" + url.toExternalForm() + "!/" + entryName);
> +            return entryUrl.openStream();
> +        }
> +    }
> +
> +    @Override
> +    public boolean equals(Object o) {
> +        if (this == o) {
> +            return true;
> +        }
> +        if (o == null || getClass() != o.getClass()) {
> +            return false;
> +        }
> +
> +        TldResourcePath other = (TldResourcePath) o;
> +        return url.equals(other.url) && Objects.equals(entryName, other.entryName);
> +    }
> +
> +    @Override
> +    public int hashCode() {
> +        return url.hashCode() * 31 + Objects.hashCode(entryName);
> +    }
> +}
> 
> Propchange: tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
> 
> Modified: tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java
> URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java?rev=1513007&r1=1513006&r2=1513007&view=diff
> ==============================================================================
> --- tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java (original)
> +++ tomcat/trunk/test/org/apache/tomcat/util/descriptor/tld/TestTldParser.java Sun Aug 11 21:24:50 2013
> @@ -16,14 +16,15 @@
>   */
>  package org.apache.tomcat.util.descriptor.tld;
>  
> -import java.io.FileInputStream;
> +import java.io.File;
> +import java.io.IOException;
>  import java.util.List;
>  
>  import org.junit.Assert;
>  import org.junit.Before;
>  import org.junit.Test;
>  
> -import org.xml.sax.InputSource;
> +import org.xml.sax.SAXException;
>  
>  public class TestTldParser {
>      private static final String WEBAPP = "test/webapp-3.1/WEB-INF/";
> @@ -36,54 +37,42 @@ public class TestTldParser {
>  
>      @Test
>      public void testParseTld21() throws Exception {
> -        try (FileInputStream is = new FileInputStream(WEBAPP + "tags21.tld")) {
> -            InputSource source = new InputSource(is);
> -            TaglibXml xml = parser.parse(source);
> -            Assert.assertEquals("1.0", xml.getTlibVersion());
> -            Assert.assertEquals("2.1", xml.getJspVersion());
> -            Assert.assertEquals("Tags21", xml.getShortName());
> -            Assert.assertEquals("http://tomcat.apache.org/tags21", xml.getUri());
> -            verifyTags(xml.getTags());
> -        }
> +        TaglibXml xml = parse("test/webapp-3.1/WEB-INF/tags21.tld");
> +        Assert.assertEquals("1.0", xml.getTlibVersion());
> +        Assert.assertEquals("2.1", xml.getJspVersion());
> +        Assert.assertEquals("Tags21", xml.getShortName());
> +        Assert.assertEquals("http://tomcat.apache.org/tags21", xml.getUri());
> +        verifyTags(xml.getTags());
>      }
>  
>      @Test
>      public void testParseTld20() throws Exception {
> -        try (FileInputStream is = new FileInputStream(WEBAPP + "tags20.tld")) {
> -            InputSource source = new InputSource(is);
> -            TaglibXml xml = parser.parse(source);
> -            Assert.assertEquals("1.0", xml.getTlibVersion());
> -            Assert.assertEquals("2.0", xml.getJspVersion());
> -            Assert.assertEquals("Tags20", xml.getShortName());
> -            Assert.assertEquals("http://tomcat.apache.org/tags20", xml.getUri());
> -            verifyTags(xml.getTags());
> -        }
> +        TaglibXml xml = parse("test/webapp-3.1/WEB-INF/tags20.tld");
> +        Assert.assertEquals("1.0", xml.getTlibVersion());
> +        Assert.assertEquals("2.0", xml.getJspVersion());
> +        Assert.assertEquals("Tags20", xml.getShortName());
> +        Assert.assertEquals("http://tomcat.apache.org/tags20", xml.getUri());
> +        verifyTags(xml.getTags());
>      }
>  
>      @Test
>      public void testParseTld12() throws Exception {
> -        try (FileInputStream is = new FileInputStream(WEBAPP + "tags12.tld")) {
> -            InputSource source = new InputSource(is);
> -            TaglibXml xml = parser.parse(source);
> -            Assert.assertEquals("1.0", xml.getTlibVersion());
> -            Assert.assertEquals("1.2", xml.getJspVersion());
> -            Assert.assertEquals("Tags12", xml.getShortName());
> -            Assert.assertEquals("http://tomcat.apache.org/tags12", xml.getUri());
> -            verifyTags(xml.getTags());
> -        }
> +        TaglibXml xml = parse("test/webapp-3.1/WEB-INF/tags12.tld");
> +        Assert.assertEquals("1.0", xml.getTlibVersion());
> +        Assert.assertEquals("1.2", xml.getJspVersion());
> +        Assert.assertEquals("Tags12", xml.getShortName());
> +        Assert.assertEquals("http://tomcat.apache.org/tags12", xml.getUri());
> +        verifyTags(xml.getTags());
>      }
>  
>      @Test
>      public void testParseTld11() throws Exception {
> -        try (FileInputStream is = new FileInputStream(WEBAPP + "tags11.tld")) {
> -            InputSource source = new InputSource(is);
> -            TaglibXml xml = parser.parse(source);
> -            Assert.assertEquals("1.0", xml.getTlibVersion());
> -            Assert.assertEquals("1.1", xml.getJspVersion());
> -            Assert.assertEquals("Tags11", xml.getShortName());
> -            Assert.assertEquals("http://tomcat.apache.org/tags11", xml.getUri());
> -            verifyTags(xml.getTags());
> -        }
> +        TaglibXml xml = parse("test/webapp-3.1/WEB-INF/tags11.tld");
> +        Assert.assertEquals("1.0", xml.getTlibVersion());
> +        Assert.assertEquals("1.1", xml.getJspVersion());
> +        Assert.assertEquals("Tags11", xml.getShortName());
> +        Assert.assertEquals("http://tomcat.apache.org/tags11", xml.getUri());
> +        verifyTags(xml.getTags());
>      }
>  
>      private void verifyTags(List<Tag> tags) {
> @@ -97,14 +86,17 @@ public class TestTldParser {
>  
>      @Test
>      public void testListener() throws Exception {
> -        try (FileInputStream is = new FileInputStream("test/webapp-3.0/WEB-INF/listener.tld")) {
> -            InputSource source = new InputSource(is);
> -            TaglibXml xml = parser.parse(source);
> -            Assert.assertEquals("1.0", xml.getTlibVersion());
> -            List<String> listeners = xml.getListeners();
> -            Assert.assertEquals(1, listeners.size());
> -            Assert.assertEquals("org.apache.catalina.core.TesterTldListener", listeners.get(0));
> -        }
> +        TaglibXml xml = parse("test/webapp-3.0/WEB-INF/listener.tld");
> +        Assert.assertEquals("1.0", xml.getTlibVersion());
> +        List<String> listeners = xml.getListeners();
> +        Assert.assertEquals(1, listeners.size());
> +        Assert.assertEquals("org.apache.catalina.core.TesterTldListener", listeners.get(0));
> +    }
> +
> +    private TaglibXml parse(String pathname) throws IOException, SAXException {
> +        File file = new File(pathname);
> +        TldResourcePath path = new TldResourcePath(file.toURI().toURL());
> +        return parser.parse(path);
>      }
>  
>  }
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
>