Author: markt Date: Wed Dec 5 20:02:23 2018 New Revision: 1848240 URL: http://svn.apache.org/viewvc?rev=1848240&view=rev Log: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=62976 Avoid an IllegalStateException when using background compilation when tag files are packaged in JAR files.
Added: tomcat/trunk/java/org/apache/tomcat/util/scan/ReferenceCountedJar.java (with props) Modified: tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java tomcat/trunk/webapps/docs/changelog.xml Modified: 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=1848240&r1=1848239&r2=1848240&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java Wed Dec 5 20:02:23 2018 @@ -23,6 +23,7 @@ import java.util.Objects; import org.apache.tomcat.Jar; import org.apache.tomcat.util.scan.JarFactory; +import org.apache.tomcat.util.scan.ReferenceCountedJar; /** * A TLD Resource Path as defined in JSP 7.3.2. @@ -131,7 +132,16 @@ public class TldResourcePath { if (entryName == null) { return null; } else { - return JarFactory.newInstance(url); + // Bug 62976 + // Jar files containing tags are typically opened during initial + // compilation and then closed when compilation is complete. The + // reference counting wrapper is used because, when background + // compilation is enabled, the Jar will need to be accessed (to + // check for modifications) after it has been closed at the end + // of the compilation stage. + // Using a reference counted Jar enables the Jar to be re-opened, + // used and then closed again rather than triggering an ISE. + return new ReferenceCountedJar(url); } } Added: tomcat/trunk/java/org/apache/tomcat/util/scan/ReferenceCountedJar.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/scan/ReferenceCountedJar.java?rev=1848240&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/scan/ReferenceCountedJar.java (added) +++ tomcat/trunk/java/org/apache/tomcat/util/scan/ReferenceCountedJar.java Wed Dec 5 20:02:23 2018 @@ -0,0 +1,146 @@ +/* + * 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.scan; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.jar.Manifest; + +import org.apache.tomcat.Jar; + +/** + * This class provides a wrapper around {@link Jar} that uses reference counting + * to close and re-create the wrapped {@link Jar} instance as required. + */ +public class ReferenceCountedJar implements Jar { + + private final URL url; + private Jar wrappedJar; + private int referenceCount = 0; + + public ReferenceCountedJar(URL url) throws IOException { + this.url = url; + open(); + } + + + /* + * Note: Returns this instance so it can be used with try-with-resources + */ + private synchronized ReferenceCountedJar open() throws IOException { + if (wrappedJar == null) { + wrappedJar = JarFactory.newInstance(url); + } + referenceCount++; + return this; + } + + + @Override + public synchronized void close() { + referenceCount--; + if (referenceCount == 0) { + wrappedJar.close(); + wrappedJar = null; + } + } + + + @Override + public URL getJarFileURL() { + return url; + } + + + @Override + public InputStream getInputStream(String name) throws IOException { + try (ReferenceCountedJar jar = open()) { + return jar.wrappedJar.getInputStream(name); + } + } + + + @Override + public long getLastModified(String name) throws IOException { + try (ReferenceCountedJar jar = open()) { + return jar.wrappedJar.getLastModified(name); + } + } + + + @Override + public boolean exists(String name) throws IOException { + try (ReferenceCountedJar jar = open()) { + return jar.wrappedJar.exists(name); + } + } + + + @Override + public void nextEntry() { + try (ReferenceCountedJar jar = open()) { + jar.wrappedJar.nextEntry(); + } catch (IOException ioe) { + throw new IllegalStateException(ioe); + } + } + + + @Override + public String getEntryName() { + try (ReferenceCountedJar jar = open()) { + return jar.wrappedJar.getEntryName(); + } catch (IOException ioe) { + throw new IllegalStateException(ioe); + } + } + + + @Override + public InputStream getEntryInputStream() throws IOException { + try (ReferenceCountedJar jar = open()) { + return jar.wrappedJar.getEntryInputStream(); + } + } + + + @Override + public String getURL(String entry) { + try (ReferenceCountedJar jar = open()) { + return jar.wrappedJar.getURL(entry); + } catch (IOException ioe) { + throw new IllegalStateException(ioe); + } + } + + + @Override + public Manifest getManifest() throws IOException { + try (ReferenceCountedJar jar = open()) { + return jar.wrappedJar.getManifest(); + } + } + + + @Override + public void reset() throws IOException { + try (ReferenceCountedJar jar = open()) { + jar.wrappedJar.reset(); + } + } +} Propchange: tomcat/trunk/java/org/apache/tomcat/util/scan/ReferenceCountedJar.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1848240&r1=1848239&r2=1848240&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Wed Dec 5 20:02:23 2018 @@ -155,6 +155,10 @@ <bug>53737</bug>: Extend JspC, the precompilation tool, to include support for resource JARs. (markt) </add> + <fix> + <bug>62976</bug>: Avoid an <code>IllegalStateException</code> when using + background compilation when tag files are packaged in JAR files. (markt) + </fix> </changelog> </subsection> <subsection name="Web applications"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org