diff --git a/core/src/main/java/com/opensymphony/xwork2/util/fs/DefaultFileManager.java b/core/src/main/java/com/opensymphony/xwork2/util/fs/DefaultFileManager.java index f5fe7e1dfa..21d6cc0ada 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/fs/DefaultFileManager.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/fs/DefaultFileManager.java @@ -70,7 +70,9 @@ public InputStream loadFile(URL fileUrl) { return null; } InputStream is = openFile(fileUrl); - monitorFile(fileUrl); + if (reloadingConfigs) { + monitorFile(fileUrl); + } return is; } diff --git a/core/src/main/java/com/opensymphony/xwork2/util/fs/JarEntryRevision.java b/core/src/main/java/com/opensymphony/xwork2/util/fs/JarEntryRevision.java index a0fea58c40..9fb05348e2 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/fs/JarEntryRevision.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/fs/JarEntryRevision.java @@ -37,9 +37,7 @@ public class JarEntryRevision extends Revision { private long lastModified; public static Revision build(URL fileUrl, FileManager fileManager) { - StrutsJarURLConnection conn = null; - try { - conn = StrutsJarURLConnection.openConnection(fileUrl); + try (StrutsJarURLConnection conn = StrutsJarURLConnection.openConnection(fileUrl)) { conn.setUseCaches(false); URL url = fileManager.normalizeToFileProtocol(fileUrl); if (url != null) { @@ -51,14 +49,6 @@ public static Revision build(URL fileUrl, FileManager fileManager) { LOG.warn("Could not create JarEntryRevision for [{}]!", fileUrl, e); return null; } - finally { - if(null != conn) { - try { - conn.getInputStream().close(); - } catch (IOException ignored) { - } - } - } } private JarEntryRevision(URL jarFileURL, long lastModified) { @@ -70,21 +60,12 @@ private JarEntryRevision(URL jarFileURL, long lastModified) { } public boolean needsReloading() { - StrutsJarURLConnection conn = null; long lastLastModified = lastModified; - try { - conn = StrutsJarURLConnection.openConnection(jarFileURL); + try (StrutsJarURLConnection conn = StrutsJarURLConnection.openConnection(jarFileURL)) { conn.setUseCaches(false); lastLastModified = conn.getJarEntry().getTime(); - } catch (IOException ignored) { - } - finally { - if(null != conn) { - try { - conn.getInputStream().close(); - } catch (IOException ignored) { - } - } + } catch (Throwable e) { + LOG.warn("Could not check if needsReloading for [{}]!", jarFileURL, e); } return lastModified < lastLastModified; diff --git a/core/src/main/java/com/opensymphony/xwork2/util/fs/StrutsJarURLConnection.java b/core/src/main/java/com/opensymphony/xwork2/util/fs/StrutsJarURLConnection.java index 44a376aafa..e733ac7cea 100644 --- a/core/src/main/java/com/opensymphony/xwork2/util/fs/StrutsJarURLConnection.java +++ b/core/src/main/java/com/opensymphony/xwork2/util/fs/StrutsJarURLConnection.java @@ -44,7 +44,7 @@ * While {@link JarURLConnection#parseSpecs(URL)} is private, then we had to extend {@link URLConnection} instead * @since 2.5.15 */ -class StrutsJarURLConnection extends URLConnection { +class StrutsJarURLConnection extends URLConnection implements AutoCloseable { private static final String FILE_URL_PREFIX = "file:"; private JarURLConnection jarURLConnection; @@ -123,8 +123,8 @@ public JarFile run() throws IOException { Path tmpFile = Files.createTempFile("jar_cache", null); try { Files.copy(in, tmpFile, StandardCopyOption.REPLACE_EXISTING); - JarFile jarFile = new JarFile(tmpFile.toFile(), true, JarFile.OPEN_READ); - tmpFile.toFile().deleteOnExit(); + JarFile jarFile = new JarFile(tmpFile.toFile(), true, JarFile.OPEN_READ + | JarFile.OPEN_DELETE); return jarFile; } catch (Throwable thr) { try { @@ -171,6 +171,20 @@ public InputStream getInputStream() throws IOException { } } + @Override + public void close() throws Exception { + try { + getInputStream().close(); + } catch (IOException ignored) { + } + if (jarURLConnection == null) { + try { + jarFile.close(); + } catch (IOException ignored) { + } + } + } + static StrutsJarURLConnection openConnection(URL url) throws IOException { return new StrutsJarURLConnection(url); } diff --git a/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderTest.java b/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderTest.java index 252e1ba6a3..b66c2ff57f 100644 --- a/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderTest.java @@ -78,12 +78,14 @@ private static void changeFileTime(File f) throws Exception { } public void testNeedsReload() throws Exception { - container.getInstance(FileManagerFactory.class).setReloadingConfigs("true"); final String filename = "com/opensymphony/xwork2/config/providers/xwork-test-actions.xml"; - ConfigurationProvider provider = buildConfigurationProvider(filename); - container.getInstance(FileManagerFactory.class).setReloadingConfigs("true"); + ConfigurationProvider provider = new XmlConfigurationProvider(filename, true); + container.getInstance(FileManagerFactory.class).getFileManager().setReloadingConfigs(true); + container.inject(provider); + provider.init(configuration); + provider.loadPackages(); - assertTrue(!provider.needsReload()); // Revision exists and timestamp didn't change + assertFalse(provider.needsReload()); // Revision exists and timestamp didn't change File file = new File(getClass().getResource("/" + filename).toURI()); assertTrue("not exists: " + file.toString(), file.exists()); @@ -92,6 +94,24 @@ public void testNeedsReload() throws Exception { assertTrue(provider.needsReload()); } + public void testNeedsReloadNotReloadingConfigs() throws Exception { + final String filename = "com/opensymphony/xwork2/config/providers/xwork-test-actions.xml"; + buildConfigurationProvider(filename); + ConfigurationProvider provider = new XmlConfigurationProvider(filename, true); + container.getInstance(FileManagerFactory.class).getFileManager().setReloadingConfigs(false); + container.inject(provider); + provider.init(configuration); + provider.loadPackages(); + + assertFalse(provider.needsReload()); // Revision exists and timestamp didn't change + + File file = new File(getClass().getResource("/" + filename).toURI()); + assertTrue("not exists: " + file.toString(), file.exists()); + changeFileTime(file); + + assertFalse(provider.needsReload()); + } + public void testInheritence() throws Exception { final String filename = "com/opensymphony/xwork2/config/providers/xwork-include-parent.xml"; ConfigurationProvider provider = buildConfigurationProvider(filename); @@ -155,10 +175,13 @@ public void testGuessResultType() { public void testEmptySpaces() throws Exception { final String filename = "com/opensymphony/xwork2/config/providers/xwork- test.xml"; + ConfigurationProvider provider = new XmlConfigurationProvider(filename, true); container.getInstance(FileManagerFactory.class).getFileManager().setReloadingConfigs(true); + container.inject(provider); + provider.init(configuration); + provider.loadPackages(); - ConfigurationProvider provider = buildConfigurationProvider(filename); - assertTrue(!provider.needsReload()); + assertFalse(provider.needsReload()); URI uri = ClassLoaderUtil.getResource(filename, ConfigurationProvider.class).toURI(); @@ -170,6 +193,27 @@ public void testEmptySpaces() throws Exception { assertTrue(provider.needsReload()); } + public void testEmptySpacesNotReloadingConfigs() throws Exception { + final String filename = "com/opensymphony/xwork2/config/providers/xwork- test.xml"; + buildConfigurationProvider(filename); + ConfigurationProvider provider = new XmlConfigurationProvider(filename, true); + container.getInstance(FileManagerFactory.class).getFileManager().setReloadingConfigs(false); + container.inject(provider); + provider.init(configuration); + provider.loadPackages(); + + assertFalse(provider.needsReload()); + + URI uri = ClassLoaderUtil.getResource(filename, ConfigurationProvider.class).toURI(); + + File file = new File(uri); + + assertTrue(file.exists()); + changeFileTime(file); + + assertFalse(provider.needsReload()); + } + public void testConfigsInJarFiles() throws Exception { container.getInstance(FileManagerFactory.class).getFileManager().setReloadingConfigs(true); testProvider("xwork-jar.xml"); diff --git a/core/src/test/java/com/opensymphony/xwork2/util/DefaultFileManagerTest.java b/core/src/test/java/com/opensymphony/xwork2/util/DefaultFileManagerTest.java index 32d24853eb..c13e87383d 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/DefaultFileManagerTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/util/DefaultFileManagerTest.java @@ -21,16 +21,9 @@ import com.opensymphony.xwork2.FileManager; import com.opensymphony.xwork2.FileManagerFactory; import com.opensymphony.xwork2.XWorkTestCase; -import com.opensymphony.xwork2.util.fs.DefaultFileManager; -import org.apache.struts2.util.fs.JBossFileManager; -import java.io.IOException; import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; -import java.net.URLStreamHandlerFactory; +import java.net.*; /** * FileManager Tester. @@ -49,23 +42,40 @@ public void setUp() throws Exception { fileManager = container.getInstance(FileManagerFactory.class).getFileManager(); } - public void disabled_testGetFileInJar() throws Exception { - testLoadFile("xwork-jar.xml"); - testLoadFile("xwork - jar.xml"); - testLoadFile("xwork-zip.xml"); - testLoadFile("xwork - zip.xml"); - testLoadFile("xwork-jar2.xml"); - testLoadFile("xwork - jar2.xml"); - testLoadFile("xwork-zip2.xml"); - testLoadFile("xwork - zip2.xml"); + public void testGetFileInJar() throws Exception { + testLoadFile("xwork-jar.xml", false); + testLoadFile("xwork - jar.xml", false); + testLoadFile("xwork-zip.xml", false); + testLoadFile("xwork - zip.xml", false); + testLoadFile("xwork-jar2.xml", false); + testLoadFile("xwork - jar2.xml", false); + testLoadFile("xwork-zip2.xml", false); + testLoadFile("xwork - zip2.xml", false); + + testLoadFile("xwork-jar.xml", true); + testLoadFile("xwork - jar.xml", true); + testLoadFile("xwork-zip.xml", true); + testLoadFile("xwork - zip.xml", true); + testLoadFile("xwork-jar2.xml", true); + testLoadFile("xwork - jar2.xml", true); + testLoadFile("xwork-zip2.xml", true); + testLoadFile("xwork - zip2.xml", true); } - private void testLoadFile(String fileName) { - fileManager.setReloadingConfigs(true); + private void testLoadFile(String fileName, boolean reloadConfigs) throws Exception { + fileManager.setReloadingConfigs(reloadConfigs); URL url = ClassLoaderUtil.getResource(fileName, DefaultFileManagerTest.class); InputStream file = fileManager.loadFile(url); assertNotNull(file); - assertTrue(fileManager.fileNeedsReloading(fileName)); + file.close(); + assertFalse(fileManager.fileNeedsReloading(url.toString())); + + long now = System.currentTimeMillis(); + JarURLConnection conn = (JarURLConnection) url.openConnection(); + conn.getJarEntry().setTime(now + 60000); + conn.getInputStream().close(); + + assertEquals(reloadConfigs, fileManager.fileNeedsReloading(url.toString())); } public void testReloadingConfigs() throws Exception { diff --git a/core/src/test/java/com/opensymphony/xwork2/util/fs/JarEntryRevisionTest.java b/core/src/test/java/com/opensymphony/xwork2/util/fs/JarEntryRevisionTest.java index 54a10b90a9..6969ccd3fa 100644 --- a/core/src/test/java/com/opensymphony/xwork2/util/fs/JarEntryRevisionTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/util/fs/JarEntryRevisionTest.java @@ -21,7 +21,9 @@ import com.opensymphony.xwork2.FileManager; import com.opensymphony.xwork2.FileManagerFactory; import com.opensymphony.xwork2.XWorkTestCase; +import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; +import org.apache.commons.io.filefilter.WildcardFileFilter; import java.io.File; import java.io.FileOutputStream; @@ -30,6 +32,8 @@ import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandler; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.jar.Attributes; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; @@ -113,6 +117,20 @@ public void testNeedsReloadingWithContainerProvidedURLConnectionEmptyProtocol() assertTrue(entry.needsReloading()); } + @Override + protected void tearDown() throws Exception { + Path tmpFile = Files.createTempFile("jar_cache", null); + Path tmpFolder = tmpFile.getParent(); + int count = FileUtils.listFiles(tmpFolder.toFile(), new WildcardFileFilter("jar_cache*"), + null).size(); + if (tmpFile.toFile().delete()) { + count--; + } + assertEquals(0, count); + + super.tearDown(); + } + /** * WW-4901 Simulating container implementation of {@link URL#openConnection()}