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