/** * Track the specified file, using the provided marker, deleting the file * when the marker instance is garbage collected. * The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used. * * @param file the file to be tracked, not null * @param marker the marker object used to track the file, not null * @throws NullPointerException if the file is null */ public void track(final File file, final Object marker) { track(file, marker, null); }
/** * Call this method to cause the file cleaner thread to terminate when * there are no more objects being tracked for deletion. * <p> * In a simple environment, you don't need this method as the file cleaner * thread will simply exit when the JVM exits. In a more complex environment, * with multiple class loaders (such as an application server), you should be * aware that the file cleaner thread will continue running even if the class * loader it was started from terminates. This can constitute a memory leak. * <p> * For example, suppose that you have developed a web application, which * contains the commons-io jar file in your WEB-INF/lib directory. In other * words, the FileCleaner class is loaded through the class loader of your * web application. If the web application is terminated, but the servlet * container is still running, then the file cleaner thread will still exist, * posing a memory leak. * <p> * This method allows the thread to be terminated. Simply call this method * in the resource cleanup code, such as * {@code javax.servlet.ServletContextListener.contextDestroyed(javax.servlet.ServletContextEvent)}. * One called, no new objects can be tracked by the file cleaner. * @deprecated Use {@link FileCleaningTracker#exitWhenFinished()}. */ @Deprecated public static synchronized void exitWhenFinished() { theInstance.exitWhenFinished(); }
/** * Retrieve the number of files currently being tracked, and therefore * awaiting deletion. * * @return the number of files being tracked * @deprecated Use {@link FileCleaningTracker#getTrackCount()}. */ @Deprecated public static int getTrackCount() { return theInstance.getTrackCount(); }
@Test public void testFileCleanerExitWhenFinished1() throws Exception { final String path = testFile.getPath(); assertEquals("1-testFile exists: " + testFile, false, testFile.exists()); RandomAccessFile r = new RandomAccessFile(testFile, "rw"); assertEquals("2-testFile exists", true, testFile.exists()); assertEquals("3-Track Count", 0, theInstance.getTrackCount()); theInstance.track(path, r); assertEquals("4-Track Count", 1, theInstance.getTrackCount()); assertEquals("5-exitWhenFinished", false, theInstance.exitWhenFinished); assertEquals("6-reaper.isAlive", true, theInstance.reaper.isAlive()); assertEquals("7-exitWhenFinished", false, theInstance.exitWhenFinished); theInstance.exitWhenFinished(); assertEquals("8-exitWhenFinished", true, theInstance.exitWhenFinished); assertEquals("9-reaper.isAlive", true, theInstance.reaper.isAlive()); r.close(); testFile = null; r = null; waitUntilTrackCount(); pauseForDeleteToComplete(new File(path)); assertEquals("10-Track Count", 0, theInstance.getTrackCount()); assertEquals("11-testFile exists " + showFailures(), false, new File(path).exists()); assertEquals("12-exitWhenFinished", true, theInstance.exitWhenFinished); assertEquals("13-reaper.isAlive", false, theInstance.reaper.isAlive()); }
@Test public void testFileCleanerFile() throws Exception { final String path = testFile.getPath(); assertFalse(testFile.exists()); RandomAccessFile r = new RandomAccessFile(testFile, "rw"); assertTrue(testFile.exists()); assertEquals(0, theInstance.getTrackCount()); theInstance.track(path, r); assertEquals(1, theInstance.getTrackCount()); r.close(); testFile = null; r = null; waitUntilTrackCount(); pauseForDeleteToComplete(new File(path)); assertEquals(0, theInstance.getTrackCount()); assertEquals(showFailures(), false, new File(path).exists()); }
@Test public void testFileCleanerExitWhenFinished_NoTrackAfter() throws Exception { assertFalse(theInstance.exitWhenFinished); theInstance.exitWhenFinished(); assertTrue(theInstance.exitWhenFinished); assertEquals(null, theInstance.reaper); final String path = testFile.getPath(); final Object marker = new Object(); try { theInstance.track(path, marker); fail(); } catch (final IllegalStateException ex) { // expected } assertTrue(theInstance.exitWhenFinished); assertEquals(null, theInstance.reaper); }
/** * Track the specified file, using the provided marker, deleting the file * when the marker instance is garbage collected. * The specified deletion strategy is used. * * @param path the full path to the file to be tracked, not null * @param marker the marker object used to track the file, not null * @param deleteStrategy the strategy to delete the file, null means normal * @throws NullPointerException if the path is null */ public void track(final String path, final Object marker, final FileDeleteStrategy deleteStrategy) { if (path == null) { throw new NullPointerException("The path must not be null"); } addTracker(path, marker, deleteStrategy); }
@Test public void testFileCleanerExitWhenFinishedFirst() throws Exception { assertFalse(theInstance.exitWhenFinished); theInstance.exitWhenFinished(); assertTrue(theInstance.exitWhenFinished); assertEquals(null, theInstance.reaper); waitUntilTrackCount(); assertEquals(0, theInstance.getTrackCount()); assertTrue(theInstance.exitWhenFinished); assertEquals(null, theInstance.reaper); }
public void track() { if (file != null) { FileCleaningTracker fileCleaningTracker = new FileCleaningTracker(); fileCleaningTracker.track(file, this); } }
protected FileCleaningTracker newInstance() { return new FileCleaningTracker(); }
@Test public void testFileCleanerExitWhenFinished2() throws Exception { final String path = testFile.getPath(); assertFalse(testFile.exists()); RandomAccessFile r = new RandomAccessFile(testFile, "rw"); assertTrue(testFile.exists()); assertEquals(0, theInstance.getTrackCount()); theInstance.track(path, r); assertEquals(1, theInstance.getTrackCount()); assertFalse(theInstance.exitWhenFinished); assertTrue(theInstance.reaper.isAlive()); r.close(); testFile = null; r = null; waitUntilTrackCount(); pauseForDeleteToComplete(new File(path)); assertEquals(0, theInstance.getTrackCount()); assertEquals(showFailures(), false, new File(path).exists()); assertFalse(theInstance.exitWhenFinished); assertTrue(theInstance.reaper.isAlive()); assertFalse(theInstance.exitWhenFinished); theInstance.exitWhenFinished(); for (int i = 0; i < 20 && theInstance.reaper.isAlive(); i++) { TestUtils.sleep(500L); // allow reaper thread to die } assertTrue(theInstance.exitWhenFinished); assertFalse(theInstance.reaper.isAlive()); }
@Test public void testFileCleanerDirectory() throws Exception { TestUtils.createFile(testFile, 100); assertTrue(testFile.exists()); assertTrue(getTestDirectory().exists()); Object obj = new Object(); assertEquals(0, theInstance.getTrackCount()); theInstance.track(getTestDirectory(), obj); assertEquals(1, theInstance.getTrackCount()); obj = null; waitUntilTrackCount(); assertEquals(0, theInstance.getTrackCount()); assertTrue(testFile.exists()); // not deleted, as dir not empty assertTrue(testFile.getParentFile().exists()); // not deleted, as dir not empty }
/** * Track the specified file, using the provided marker, deleting the file * when the marker instance is garbage collected. * The specified deletion strategy is used. * * @param file the file to be tracked, not null * @param marker the marker object used to track the file, not null * @param deleteStrategy the strategy to delete the file, null means normal * @throws NullPointerException if the file is null */ public void track(final File file, final Object marker, final FileDeleteStrategy deleteStrategy) { if (file == null) { throw new NullPointerException("The file must not be null"); } addTracker(file.getPath(), marker, deleteStrategy); }
/** * Called when the web application is initialized. Does * nothing. * * @param sce The servlet context, used for calling * {@link #setFileCleaningTracker(ServletContext, FileCleaningTracker)}. */ @Override public void contextInitialized(ServletContextEvent sce) { setFileCleaningTracker(sce.getServletContext(), new FileCleaningTracker()); }
/** * Track the specified file, using the provided marker, deleting the file * when the marker instance is garbage collected. * The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used. * * @param path the full path to the file to be tracked, not null * @param marker the marker object used to track the file, not null * @throws NullPointerException if the path is null */ public void track(final String path, final Object marker) { track(path, marker, null); }
/** * Call this method to cause the file cleaner thread to terminate when * there are no more objects being tracked for deletion. * <p> * In a simple environment, you don't need this method as the file cleaner * thread will simply exit when the JVM exits. In a more complex environment, * with multiple class loaders (such as an application server), you should be * aware that the file cleaner thread will continue running even if the class * loader it was started from terminates. This can consitute a memory leak. * <p> * For example, suppose that you have developed a web application, which * contains the commons-io jar file in your WEB-INF/lib directory. In other * words, the FileCleaner class is loaded through the class loader of your * web application. If the web application is terminated, but the servlet * container is still running, then the file cleaner thread will still exist, * posing a memory leak. * <p> * This method allows the thread to be terminated. Simply call this method * in the resource cleanup code, such as {@link javax.servlet.ServletContextListener#contextDestroyed}. * One called, no new objects can be tracked by the file cleaner. */ public static synchronized void exitWhenFinished() { theInstance.exitWhenFinished(); }
@Test public void testFileCleanerDirectory_NullStrategy() throws Exception { TestUtils.createFile(testFile, 100); assertTrue(testFile.exists()); assertTrue(getTestDirectory().exists()); Object obj = new Object(); assertEquals(0, theInstance.getTrackCount()); theInstance.track(getTestDirectory(), obj, null); assertEquals(1, theInstance.getTrackCount()); obj = null; waitUntilTrackCount(); assertEquals(0, theInstance.getTrackCount()); assertTrue(testFile.exists()); // not deleted, as dir not empty assertTrue(testFile.getParentFile().exists()); // not deleted, as dir not empty }
/** * Track the specified file, using the provided marker, deleting the file * when the marker instance is garbage collected. * The speified deletion strategy is used. * * @param path the full path to the file to be tracked, not null * @param marker the marker object used to track the file, not null * @param deleteStrategy the strategy to delete the file, null means normal * @throws NullPointerException if the path is null */ public void track(String path, Object marker, FileDeleteStrategy deleteStrategy) { if (path == null) { throw new NullPointerException("The path must not be null"); } addTracker(path, marker, deleteStrategy); }
/** * Retrieve the number of files currently being tracked, and therefore * awaiting deletion. * * @return the number of files being tracked */ public static int getTrackCount() { return theInstance.getTrackCount(); }
/** * Construct. */ public FileCleaner() { cleaner = new FileCleaningTracker(); }