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, jboy...@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-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: dev-h...@tomcat.apache.org
> 

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to