Author: markt Date: Tue Mar 3 14:47:12 2015 New Revision: 1663715 URL: http://svn.apache.org/r1663715 Log: In directly fix https://bz.apache.org/bugzilla/show_bug.cgi?id=57251 Enable Tomcat to detect when a WAR file has been changed while Tomcat is not running. Note Tomcat does this by setting the last modified time of the expanded directory to the last modified time of the WAR.
Modified: tomcat/trunk/java/org/apache/catalina/startup/ExpandWar.java tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties Modified: tomcat/trunk/java/org/apache/catalina/startup/ExpandWar.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/ExpandWar.java?rev=1663715&r1=1663714&r2=1663715&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/ExpandWar.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/ExpandWar.java Tue Mar 3 14:47:12 2015 @@ -55,8 +55,7 @@ public class ExpandWar { /** * Expand the WAR file found at the specified URL into an unpacked - * directory structure, and return the absolute pathname to the expanded - * directory. + * directory structure. * * @param host Host war is being installed for * @param war URL of the web application archive to be expanded @@ -67,31 +66,62 @@ public class ExpandWar { * WAR file is invalid * @exception IOException if an input/output error was encountered * during expansion + * + * @return The absolute path to the expanded directory foe the given WAR */ public static String expand(Host host, URL war, String pathname) throws IOException { - // Make sure that there is no such directory already existing - File docBase = new File(host.getAppBaseFile(), pathname); - if (docBase.exists()) { - // War file is already installed - return (docBase.getAbsolutePath()); - } - - // Create the new document base directory - if(!docBase.mkdir() && !docBase.isDirectory()) - throw new IOException(sm.getString("expandWar.createFailed", docBase)); - - // Expand the WAR into the new document base directory - String canonicalDocBasePrefix = docBase.getCanonicalPath(); - if (!canonicalDocBasePrefix.endsWith(File.separator)) { - canonicalDocBasePrefix += File.separator; - } + // Open the connection to the WAR. There is no explicit close method. + // You have to get the JarFile and close that. JarURLConnection juc = (JarURLConnection) war.openConnection(); juc.setUseCaches(false); + // Set up the variables used in the finally block of the following try boolean success = false; + File docBase = new File(host.getAppBaseFile(), pathname); + try (JarFile jarFile = juc.getJarFile()) { + + // Get the last modified time for the WAR + long warLastModified = juc.getContentLengthLong(); + + // Check to see of the WAR has been expanded previously + if (docBase.exists()) { + // A WAR was expanded. Tomcat will have set the last modified + // time of the expanded directory to the last modified time of + // the WAR so changes to the WAR while Tomcat is stopped can be + // detected + long dirLastModified = docBase.lastModified(); + + if (dirLastModified == warLastModified) { + // No changes to the WAR + return (docBase.getAbsolutePath()); + } + + log.info(sm.getString("expandWar.deleteOld", docBase)); + + // WAR must have been modified. Remove expanded directory. + if (!delete(docBase)) { + throw new IOException(sm.getString("expandWar.deleteFailed", docBase)); + } + } + + // Create the new document base directory + if(!docBase.mkdir() && !docBase.isDirectory()) { + throw new IOException(sm.getString("expandWar.createFailed", docBase)); + } + + // Align the last modified time of the directory with the WAR so + // changes to the WAR while Tomcat is stopped can be detected + docBase.setLastModified(warLastModified); + + // Expand the WAR into the new document base directory + String canonicalDocBasePrefix = docBase.getCanonicalPath(); + if (!canonicalDocBasePrefix.endsWith(File.separator)) { + canonicalDocBasePrefix += File.separator; + } + Enumeration<JarEntry> jarEntries = jarFile.entries(); while (jarEntries.hasMoreElements()) { JarEntry jarEntry = jarEntries.nextElement(); @@ -119,7 +149,6 @@ public class ExpandWar { continue; } - try (InputStream input = jarFile.getInputStream(jarEntry)) { if (null == input) throw new ZipException(sm.getString("expandWar.missingJarEntry", Modified: tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java?rev=1663715&r1=1663714&r2=1663715&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java Tue Mar 3 14:47:12 2015 @@ -789,9 +789,17 @@ public class HostConfig entry = null; } + // If there is an expanded directory then any xml in that directory + // should only be used if the directory is not out of date and + // unpackWARs is true. Note the code below may apply further limits + boolean useXml = false; + if (xml.exists() && unpackWARs && xml.lastModified() == war.lastModified()) { + useXml = true; + } + Context context = null; try { - if (deployXML && xml.exists() && unpackWARs && !copyXML) { + if (deployXML && useXml && !copyXML) { synchronized (digesterLock) { try { context = (Context) digester.parse(xml); Modified: tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties?rev=1663715&r1=1663714&r2=1663715&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties Tue Mar 3 14:47:12 2015 @@ -76,6 +76,7 @@ engineConfig.stop=EngineConfig: Processi expandWar.copy=Error copying {0} to {1} expandWar.createFailed=Unable to create the directory [{0}] expandWar.deleteFailed=[{0}] could not be completely deleted. The presence of the remaining files may cause problems +expandWar.deleteOld=An expanded directory [{0}] was found with a last modified time that did not match the associated WAR. It will be deleted. expandWar.illegalPath=The archive [{0}] is malformed and will be ignored: an entry contains an illegal path [{1}] which was not expanded to [{2}] since that is outside of the defined docBase [{3}] expandWar.missingJarEntry=Cannot get input stream for JarEntry "{0}" - broken WAR file? failedContext.start=Failed to process either the global, per-host or context-specific context.xml file therefore the [{0}] Context cannot be started. --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org