Author: mgrigorov
Date: Mon Jul 11 10:03:46 2011
New Revision: 1145102

URL: http://svn.apache.org/viewvc?rev=1145102&view=rev
Log:
WICKET-3875 Clear Files.remove() behavior


Added:
    
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FileCleaner.java
      - copied, changed from r1144178, 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FileUploadCleaner.java
    
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FolderDeleteStrategy.java
    
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/IFileCleaner.java
      - copied, changed from r1144178, 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/IFileUploadCleaner.java
Removed:
    
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FileUploadCleaner.java
    
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/IFileUploadCleaner.java
Modified:
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/IResourceSettings.java
    
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/ResourceSettings.java
    
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/html/form/upload/FileUploadTest.java
    
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/Files.java
    
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItem.java
    
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItemFactory.java
    
wicket/trunk/wicket-util/src/test/java/org/apache/wicket/util/file/FilesTest.java

Modified: 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java?rev=1145102&r1=1145101&r2=1145102&view=diff
==============================================================================
--- 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
 (original)
+++ 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/WebApplication.java
 Mon Jul 11 10:03:46 2011
@@ -62,8 +62,8 @@ import org.apache.wicket.session.HttpSes
 import org.apache.wicket.session.ISessionStore;
 import org.apache.wicket.util.IContextProvider;
 import org.apache.wicket.util.IProvider;
-import org.apache.wicket.util.file.FileUploadCleaner;
-import org.apache.wicket.util.file.IFileUploadCleaner;
+import org.apache.wicket.util.file.FileCleaner;
+import org.apache.wicket.util.file.IFileCleaner;
 import org.apache.wicket.util.file.IResourceFinder;
 import org.apache.wicket.util.file.WebApplicationPath;
 import org.apache.wicket.util.lang.Args;
@@ -502,10 +502,10 @@ public abstract class WebApplication ext
                        resourceWatcher.destroy();
                }
 
-               IFileUploadCleaner fileUploadCleaner = 
getResourceSettings().getFileUploadCleaner();
-               if (fileUploadCleaner != null)
+               IFileCleaner fileCleaner = 
getResourceSettings().getFileCleaner();
+               if (fileCleaner != null)
                {
-                       fileUploadCleaner.destroy();
+                       fileCleaner.destroy();
                }
 
                super.internalDestroy();
@@ -541,7 +541,7 @@ public abstract class WebApplication ext
                // Set resource finder to web app path
                getResourceSettings().setResourceFinder(getResourceFinder());
 
-               getResourceSettings().setFileUploadCleaner(new 
FileUploadCleaner());
+               getResourceSettings().setFileCleaner(new FileCleaner());
 
                // Add optional sourceFolder for resources.
                String resourceFolder = getInitParameter("sourceFolder");

Modified: 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java?rev=1145102&r1=1145101&r2=1145102&view=diff
==============================================================================
--- 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
 (original)
+++ 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
 Mon Jul 11 10:03:46 2011
@@ -87,7 +87,7 @@ public class MultipartServletWebRequestI
        {
                this(request, filterPrefix, maxSize, new 
DiskFileItemFactory(Application.get()
                        .getResourceSettings()
-                       .getFileUploadCleaner()));
+                       .getFileCleaner()));
        }
 
        /**

Modified: 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/IResourceSettings.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/IResourceSettings.java?rev=1145102&r1=1145101&r2=1145102&view=diff
==============================================================================
--- 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/IResourceSettings.java
 (original)
+++ 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/IResourceSettings.java
 Mon Jul 11 10:03:46 2011
@@ -29,7 +29,7 @@ import org.apache.wicket.request.resourc
 import org.apache.wicket.resource.IPropertiesFactory;
 import org.apache.wicket.resource.IPropertiesFactoryContext;
 import org.apache.wicket.resource.loader.IStringResourceLoader;
-import org.apache.wicket.util.file.IFileUploadCleaner;
+import org.apache.wicket.util.file.IFileCleaner;
 import org.apache.wicket.util.file.IResourceFinder;
 import org.apache.wicket.util.resource.locator.IResourceStreamLocator;
 import org.apache.wicket.util.time.Duration;
@@ -210,9 +210,9 @@ public interface IResourceSettings exten
         * The default is one second in 'development' mode and 'never' in 
deployment mode.
         * 
         * @param resourcePollFrequency
-        *            Frequency at which to poll resources or 
-        *            <code>null</code> if polling should be disabled
-        *            
+        *            Frequency at which to poll resources or <code>null</code> 
if polling should be
+        *            disabled
+        * 
         * @see IResourceSettings#setResourceFinder(IResourceFinder)
         */
        void setResourcePollFrequency(final Duration resourcePollFrequency);
@@ -233,18 +233,19 @@ public interface IResourceSettings exten
        void setResourceWatcher(IModificationWatcher watcher);
 
        /**
-        * Sets a cleaner for the temporary files created by FileUpload 
functionality
+        * Sets a cleaner that can be used to remove files asynchronously.
+        * <p>
+        * Used internally to delete the temporary files created by FileUpload 
functionality
         * 
-        * @param fileUploadCleaner
+        * @param fileCleaner
         *            the actual cleaner implementation. Can be 
<code>null</code>
         */
-       void setFileUploadCleaner(IFileUploadCleaner fileUploadCleaner);
+       void setFileCleaner(IFileCleaner fileCleaner);
 
        /**
-        * @return the cleaner for the temporary files created by FileUpload 
functionality. Can be
-        *         <code>null</code>
+        * @return the a cleaner which can be used to remove files 
asynchronously.
         */
-       IFileUploadCleaner getFileUploadCleaner();
+       IFileCleaner getFileCleaner();
 
        /**
         * @param throwExceptionOnMissingResource
@@ -258,10 +259,10 @@ public interface IResourceSettings exten
        void setUseDefaultOnMissingResource(final boolean 
useDefaultOnMissingResource);
 
        /**
-        * Set the javascript compressor implemententation use e.g. by 
-        * {@link org.apache.wicket.request.resource.JavaScriptPackageResource 
JavaScriptPackageResource}. 
-        * A typical implementation will remove comments and whitespace. But a 
no-op implementation is
-        * available as well.
+        * Set the javascript compressor implemententation use e.g. by
+        * {@link org.apache.wicket.request.resource.JavaScriptPackageResource
+        * JavaScriptPackageResource}. A typical implementation will remove 
comments and whitespace. But
+        * a no-op implementation is available as well.
         * 
         * @param compressor
         *            The implementation to be used
@@ -272,10 +273,9 @@ public interface IResourceSettings exten
        /**
         * Get the javascript compressor to remove comments and whitespace 
characters from javascripts
         * 
-        * @return whether the comments and whitespace characters will be 
stripped from 
-        *         resources served through 
-        *         {@link 
org.apache.wicket.request.resource.JavaScriptPackageResource 
JavaScriptPackageResource}. 
-        *         Null is a valid value.
+        * @return whether the comments and whitespace characters will be 
stripped from resources served
+        *         through {@link 
org.apache.wicket.request.resource.JavaScriptPackageResource
+        *         JavaScriptPackageResource}. Null is a valid value.
         */
        IJavaScriptCompressor getJavaScriptCompressor();
 
@@ -328,10 +328,10 @@ public interface IResourceSettings exten
        void setCachingStrategy(IResourceCachingStrategy strategy);
 
        /**
-        * Set the CSS compressor implemententation use e.g. by 
-        * {@link org.apache.wicket.request.resource.CssPackageResource 
CssPackageResource}. 
-        * A typical implementation will remove comments and whitespace. But a 
no-op implementation 
-        * is available as well.
+        * Set the CSS compressor implemententation use e.g. by
+        * {@link org.apache.wicket.request.resource.CssPackageResource 
CssPackageResource}. A typical
+        * implementation will remove comments and whitespace. But a no-op 
implementation is available
+        * as well.
         * 
         * @param compressor
         *            The implementation to be used
@@ -343,8 +343,8 @@ public interface IResourceSettings exten
         * Get the CSS compressor to remove comments and whitespace characters 
from css resources
         * 
         * @return whether the comments and whitespace characters will be 
stripped from resources served
-        *         through {@link 
org.apache.wicket.request.resource.CssPackageResource CssPackageResource}. 
-        *         Null is a valid value.
+        *         through {@link 
org.apache.wicket.request.resource.CssPackageResource
+        *         CssPackageResource}. Null is a valid value.
         */
        ICssCompressor getCssCompressor();
 }

Modified: 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/ResourceSettings.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/ResourceSettings.java?rev=1145102&r1=1145101&r2=1145102&view=diff
==============================================================================
--- 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/ResourceSettings.java
 (original)
+++ 
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/settings/def/ResourceSettings.java
 Mon Jul 11 10:03:46 2011
@@ -42,7 +42,7 @@ import org.apache.wicket.resource.loader
 import org.apache.wicket.resource.loader.PackageStringResourceLoader;
 import org.apache.wicket.resource.loader.ValidatorStringResourceLoader;
 import org.apache.wicket.settings.IResourceSettings;
-import org.apache.wicket.util.file.IFileUploadCleaner;
+import org.apache.wicket.util.file.IFileCleaner;
 import org.apache.wicket.util.file.IResourceFinder;
 import org.apache.wicket.util.file.IResourcePath;
 import org.apache.wicket.util.file.Path;
@@ -92,8 +92,12 @@ public class ResourceSettings implements
        /** ModificationWatcher to watch for changes in markup files */
        private IModificationWatcher resourceWatcher;
 
-       /** a cleaner for the temporary files created by FileUpload 
functionality */
-       private IFileUploadCleaner fileUploadCleaner;
+       /**
+        * A cleaner that removes files asynchronously.
+        * <p>
+        * Used internally to remove the temporary files created by FileUpload 
functionality.
+        */
+       private IFileCleaner fileCleaner;
 
        /** Chain of string resource loaders to use */
        private final List<IStringResourceLoader> stringResourceLoaders = 
Generics.newArrayList(4);
@@ -118,7 +122,7 @@ public class ResourceSettings implements
 
        // resource caching strategy
        private IResourceCachingStrategy resourceCachingStrategy;
-       
+
        // application these settings are bound to
        private final Application application;
 
@@ -260,14 +264,14 @@ public class ResourceSettings implements
                resourceWatcher = watcher;
        }
 
-       public IFileUploadCleaner getFileUploadCleaner()
+       public IFileCleaner getFileCleaner()
        {
-               return fileUploadCleaner;
+               return fileCleaner;
        }
 
-       public void setFileUploadCleaner(IFileUploadCleaner fileUploadCleaner)
+       public void setFileCleaner(IFileCleaner fileUploadCleaner)
        {
-               this.fileUploadCleaner = fileUploadCleaner;
+               fileCleaner = fileUploadCleaner;
        }
 
        /**
@@ -443,7 +447,8 @@ public class ResourceSettings implements
                                // development mode:
                                // use last-modified timestamp of packaged 
resource for resource caching
                                // cache the version information for the 
lifetime of the current http request
-                               resourceVersion = new 
RequestCycleCachedResourceVersion(new LastModifiedResourceVersion());
+                               resourceVersion = new 
RequestCycleCachedResourceVersion(
+                                       new LastModifiedResourceVersion());
                        }
                        else
                        {
@@ -453,8 +458,8 @@ public class ResourceSettings implements
                                resourceVersion = new 
CachingResourceVersion(new MessageDigestResourceVersion());
                        }
                        // cache resource with a version string in the filename
-                       resourceCachingStrategy =
-                               new 
FilenameWithVersionResourceCachingStrategy(resourceVersion);
+                       resourceCachingStrategy = new 
FilenameWithVersionResourceCachingStrategy(
+                               resourceVersion);
                }
                return resourceCachingStrategy;
        }

Modified: 
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/html/form/upload/FileUploadTest.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/html/form/upload/FileUploadTest.java?rev=1145102&r1=1145101&r2=1145102&view=diff
==============================================================================
--- 
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/html/form/upload/FileUploadTest.java
 (original)
+++ 
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/html/form/upload/FileUploadTest.java
 Mon Jul 11 10:03:46 2011
@@ -23,8 +23,8 @@ import java.util.List;
 
 import org.apache.wicket.WicketTestCase;
 import org.apache.wicket.util.file.File;
-import org.apache.wicket.util.file.FileUploadCleaner;
-import org.apache.wicket.util.file.IFileUploadCleaner;
+import org.apache.wicket.util.file.FileCleaner;
+import org.apache.wicket.util.file.IFileCleaner;
 import org.apache.wicket.util.tester.FormTester;
 import org.apache.wicket.util.upload.DiskFileItemFactory;
 import org.apache.wicket.util.upload.FileItem;
@@ -55,7 +55,7 @@ public class FileUploadTest extends Wick
         */
        public void testGetInputStream() throws Exception
        {
-               IFileUploadCleaner fileUploadCleaner = new FileUploadCleaner();
+               IFileCleaner fileUploadCleaner = new FileCleaner();
 
                FileItem fileItem = new 
DiskFileItemFactory(fileUploadCleaner).createItem("dummyFieldName",
                        "text/java", false, "FileUploadTest.java");

Copied: 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FileCleaner.java
 (from r1144178, 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FileUploadCleaner.java)
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FileCleaner.java?p2=wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FileCleaner.java&p1=wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FileUploadCleaner.java&r1=1144178&r2=1145102&rev=1145102&view=diff
==============================================================================
--- 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FileUploadCleaner.java
 (original)
+++ 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FileCleaner.java
 Mon Jul 11 10:03:46 2011
@@ -19,35 +19,34 @@ package org.apache.wicket.util.file;
 import java.io.File;
 
 /**
- * Default implementation of {@link IFileUploadCleaner} that uses Apache 
commons-io
+ * Default implementation of {@link IFileCleaner} that uses Apache commons-io
  * {@link FileCleaningTracker} to track and clean the temporary created files.
  * <p>
  * Note: this implementation starts a daemon thread to do the actual work, so 
it may not be used in
  * some environments like Google AppEngine.
  */
-public class FileUploadCleaner implements IFileUploadCleaner
+public class FileCleaner implements IFileCleaner
 {
        private final FileCleaningTracker cleaner;
 
        /**
         * Construct.
         */
-       public FileUploadCleaner()
+       public FileCleaner()
        {
                cleaner = new FileCleaningTracker();
        }
 
-       /**
-        * {@inheritDoc}
-        */
        public void track(final File file, final Object marker)
        {
                cleaner.track(file, marker);
        }
 
-       /**
-        * {@inheritDoc}
-        */
+       public void track(final File file, final Object marker, 
FileDeleteStrategy deleteStrategy)
+       {
+               cleaner.track(file, marker, deleteStrategy);
+       }
+
        public void destroy()
        {
                cleaner.exitWhenFinished();

Modified: 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/Files.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/Files.java?rev=1145102&r1=1145101&r2=1145102&view=diff
==============================================================================
--- 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/Files.java 
(original)
+++ 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/Files.java 
Mon Jul 11 10:03:46 2011
@@ -103,49 +103,42 @@ public class Files
        }
 
        /**
-        * Deletes a file.
+        * Deletes a normal file.
         * <p>
-        * If the file cannot be deleted for any reason then at most 10 retries 
are attempted with delay
-        * of 100ms. If the file still cannot be deleted then it is scheduled 
to be deleted at JVM exit
-        * time.
+        * If the file cannot be deleted for any reason then at most 50 retries 
are attempted with delay
+        * of 100ms at each 10th attempt.
         * 
         * @param file
-        *            File to delete
-        * @return {@code true} if file was deleted, {@code false} if the file 
didn't exist or it cannot
-        *         be removed for some reason
+        *            the file to delete
+        * @return {@code true} if file was deleted, {@code false} if the file 
don't exist, is a folder
+        *         or cannot be removed for some reason
         */
        public static boolean remove(final java.io.File file)
        {
-               if (file == null || file.exists() == false || 
file.isDirectory())
+               if (file != null && file.isFile())
                {
-                       return false;
-               }
-
-               int retries = 10;
-
-               boolean deleted = false;
-
-               while ((deleted = file.delete()) == false && retries > 0)
-               {
-                       retries--;
-                       try
+                       for (int j = 0; j < 5; ++j)
                        {
-                               Thread.sleep(100);
-                       }
-                       catch (InterruptedException ignored)
-                       {
-                       }
-               }
+                               for (int i = 0; i < 10; ++i)
+                               {
+                                       if (file.delete())
+                                       {
+                                               return true;
+                                       }
 
-               if (deleted == false && logger.isWarnEnabled())
-               {
-                       logger.warn(
-                               "Cannot delete file '{}' for unknown reason. 
The file will be scheduled for deletion at JVM exit time.",
-                               file);
-                       file.deleteOnExit();
+                                       try
+                                       {
+                                               Thread.sleep(100);
+                                       }
+                                       catch (InterruptedException ix)
+                                       {
+                                               
Thread.currentThread().interrupt();
+                                       }
+                               }
+                       }
                }
 
-               return deleted;
+               return false;
        }
 
        /**
@@ -187,6 +180,55 @@ public class Files
        }
 
        /**
+        * Schedules a file for removal asynchronously.
+        * 
+        * @param file
+        *            the file to be removed
+        * @param fileCleaner
+        *            the file cleaner that will be used to remove the file
+        * @return {@code false} if the {@code file} is <em>null</em> or a 
folder, {@code true} -
+        *         otherwise (i.e. if it is scheduled)
+        */
+       public static final boolean removeAsync(final File file, final 
IFileCleaner fileCleaner)
+       {
+               if (file == null || file.isDirectory())
+               {
+                       return false;
+               }
+
+               Args.notNull(fileCleaner, "fileCleaner");
+
+               fileCleaner.track(file, new Object());
+
+               return true;
+       }
+
+
+       /**
+        * Schedules a folder and all files inside it for asynchronous removal.
+        * 
+        * @param folder
+        *            the folder to be removed
+        * @param fileCleaner
+        *            the file cleaner that will be used to remove the file
+        * @return {@code false} if the {@code folder} is <em>null</em> or a 
normal file, {@code true} -
+        *         otherwise (i.e. if it is scheduled)
+        */
+       public static final boolean removeFolderAsync(final File folder, final 
IFileCleaner fileCleaner)
+       {
+               if (folder == null || folder.isFile())
+               {
+                       return false;
+               }
+
+               Args.notNull(fileCleaner, "fileCleaner");
+
+               fileCleaner.track(folder, new Object(), new 
FolderDeleteStrategy());
+
+               return true;
+       }
+
+       /**
         * Writes the given input stream to the given file
         * 
         * @param file
@@ -386,30 +428,35 @@ public class Files
        }
 
        /**
-        * Utility method for creating a directory
+        * Utility method for creating a directory. If the creation didn't 
succeed for some reason then
+        * at most 50 attempts are made with delay of 100ms at every 10th 
attempt.
         * 
-        * @param file
+        * @param folder
+        *            the folder to create
+        * @return {@code true} if the creation is successful, {@code false} - 
otherwise
         */
-       public static void mkdirs(File file)
+       public static boolean mkdirs(File folder)
        {
                // for some reason, simple file.mkdirs sometimes fails under 
heavy load
                for (int j = 0; j < 5; ++j)
                {
                        for (int i = 0; i < 10; ++i)
                        {
-                               if (file.mkdirs())
+                               if (folder.mkdirs())
                                {
-                                       return;
+                                       return true;
                                }
                        }
                        try
                        {
                                Thread.sleep(100);
                        }
-                       catch (InterruptedException ignore)
+                       catch (InterruptedException ix)
                        {
+                               Thread.currentThread().interrupt();
                        }
                }
-               logger.error("Failed to make directory " + file);
+               logger.error("Failed to create directory: " + folder);
+               return false;
        }
 }

Added: 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FolderDeleteStrategy.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FolderDeleteStrategy.java?rev=1145102&view=auto
==============================================================================
--- 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FolderDeleteStrategy.java
 (added)
+++ 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/FolderDeleteStrategy.java
 Mon Jul 11 10:03:46 2011
@@ -0,0 +1,83 @@
+/*
+ * 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.wicket.util.file;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * A {@link FileDeleteStrategy} that can delete folders.
+ */
+public class FolderDeleteStrategy extends FileDeleteStrategy
+{
+       /**
+        * Construct.
+        * 
+        * @param name
+        */
+       protected FolderDeleteStrategy()
+       {
+               super("folder");
+       }
+
+       @Override
+       public boolean deleteQuietly(final File folder)
+       {
+               if (folder == null || folder.isFile())
+               {
+                       return false;
+               }
+
+               File[] files = folder.listFiles();
+               if (files != null)
+               {
+                       for (File file : files)
+                       {
+                               if (file.isDirectory())
+                               {
+                                       deleteQuietly(file);
+                               }
+                               else
+                               {
+                                       super.deleteQuietly(file);
+                               }
+                       }
+               }
+
+               return super.deleteQuietly(folder);
+       }
+
+       @Override
+       public void delete(final File folder) throws IOException
+       {
+               if (folder == null || folder.isFile())
+               {
+                       return;
+               }
+
+               File[] files = folder.listFiles();
+               if (files != null)
+               {
+                       for (File file : files)
+                       {
+                               super.delete(file);
+                       }
+               }
+       }
+
+
+}

Copied: 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/IFileCleaner.java
 (from r1144178, 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/IFileUploadCleaner.java)
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/IFileCleaner.java?p2=wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/IFileCleaner.java&p1=wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/IFileUploadCleaner.java&r1=1144178&r2=1145102&rev=1145102&view=diff
==============================================================================
--- 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/IFileUploadCleaner.java
 (original)
+++ 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/file/IFileCleaner.java
 Mon Jul 11 10:03:46 2011
@@ -25,7 +25,7 @@ import java.io.File;
  * <p>
  * Needed to remove files created temporarily for the needs of FileUpload 
functionality.
  */
-public interface IFileUploadCleaner
+public interface IFileCleaner
 {
 
        /**
@@ -42,6 +42,22 @@ public interface IFileUploadCleaner
        void track(File file, Object marker);
 
        /**
+        * Track the specified file, using the provided marker, deleting the 
file when the marker
+        * instance is garbage collected.
+        * 
+        * @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 that actually deletes the file. E.g. to 
delete a non-empty folder the
+        *            strategy should delete all children first
+        * @throws NullPointerException
+        *             if the file is null
+        */
+       void track(File file, Object marker, FileDeleteStrategy deleteStrategy);
+
+       /**
         * Call this method to stop the cleaner and to free all allocated 
resources by it
         */
        void destroy();

Modified: 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItem.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItem.java?rev=1145102&r1=1145101&r2=1145102&view=diff
==============================================================================
--- 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItem.java
 (original)
+++ 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItem.java
 Mon Jul 11 10:03:46 2011
@@ -33,7 +33,7 @@ import java.util.Random;
 import java.util.UUID;
 
 import org.apache.wicket.util.file.Files;
-import org.apache.wicket.util.file.IFileUploadCleaner;
+import org.apache.wicket.util.file.IFileCleaner;
 import org.apache.wicket.util.io.DeferredFileOutputStream;
 import org.apache.wicket.util.io.IOUtils;
 import org.apache.wicket.util.io.Streams;
@@ -167,7 +167,7 @@ public class DiskFileItem implements Fil
         * This is transient because it is needed only for the upload request 
lifetime to add this file
         * item in the tracker. After that the cleaner is not needed anymore.
         */
-       private transient final IFileUploadCleaner fileUploadCleaner;
+       private transient final IFileCleaner fileUploadCleaner;
 
        /**
         * Constructs a new <code>DiskFileItem</code> instance.
@@ -191,7 +191,7 @@ public class DiskFileItem implements Fil
         */
        public DiskFileItem(final String fieldName, final String contentType,
                final boolean isFormField, final String fileName, final int 
sizeThreshold,
-               final File repository, final IFileUploadCleaner 
fileUploadCleaner)
+               final File repository, final IFileCleaner fileUploadCleaner)
        {
                this.fieldName = fieldName;
                this.contentType = contentType;

Modified: 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItemFactory.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItemFactory.java?rev=1145102&r1=1145101&r2=1145102&view=diff
==============================================================================
--- 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItemFactory.java
 (original)
+++ 
wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/upload/DiskFileItemFactory.java
 Mon Jul 11 10:03:46 2011
@@ -19,7 +19,7 @@ package org.apache.wicket.util.upload;
 import java.io.File;
 
 import org.apache.wicket.util.file.FileCleaningTracker;
-import org.apache.wicket.util.file.IFileUploadCleaner;
+import org.apache.wicket.util.file.IFileCleaner;
 
 
 /**
@@ -78,7 +78,7 @@ public class DiskFileItemFactory impleme
         */
        private int sizeThreshold = DEFAULT_SIZE_THRESHOLD;
 
-       private final IFileUploadCleaner fileUploadCleaner;
+       private final IFileCleaner fileUploadCleaner;
 
        // ----------------------------------------------------------- 
Constructors
 
@@ -89,7 +89,7 @@ public class DiskFileItemFactory impleme
         * 
         * @param fileUploadCleaner
         */
-       public DiskFileItemFactory(final IFileUploadCleaner fileUploadCleaner)
+       public DiskFileItemFactory(final IFileCleaner fileUploadCleaner)
        {
                this(DEFAULT_SIZE_THRESHOLD, null, fileUploadCleaner);
        }
@@ -107,7 +107,7 @@ public class DiskFileItemFactory impleme
         * @param fileUploadCleaner
         */
        public DiskFileItemFactory(final int sizeThreshold, final File 
repository,
-               final IFileUploadCleaner fileUploadCleaner)
+               final IFileCleaner fileUploadCleaner)
        {
                this.sizeThreshold = sizeThreshold;
                this.repository = repository;

Modified: 
wicket/trunk/wicket-util/src/test/java/org/apache/wicket/util/file/FilesTest.java
URL: 
http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/test/java/org/apache/wicket/util/file/FilesTest.java?rev=1145102&r1=1145101&r2=1145102&view=diff
==============================================================================
--- 
wicket/trunk/wicket-util/src/test/java/org/apache/wicket/util/file/FilesTest.java
 (original)
+++ 
wicket/trunk/wicket-util/src/test/java/org/apache/wicket/util/file/FilesTest.java
 Mon Jul 11 10:03:46 2011
@@ -41,7 +41,7 @@ public class FilesTest extends Assert
                        
"/somethingThatDoesntExistsOnMostMachines-111111111111111111111111111111")));
 
                java.io.File file = 
java.io.File.createTempFile("wicket-test--", ".tmp");
-               assertTrue("The just created file should exist!", 
file.exists());
+               assertTrue("The just created file should exist!", 
file.isFile());
 
                boolean removed = Files.remove(file);
                assertFalse("The just removed file should not exist!", 
file.exists());
@@ -68,9 +68,9 @@ public class FilesTest extends Assert
        @Test
        public void removeFolder() throws Exception
        {
-               assertFalse("'null' folders are not deleted.", 
Files.remove(null));
+               assertFalse("'null' folders are not deleted.", 
Files.removeFolder(null));
 
-               assertFalse("Non existing files are not deleted.", 
Files.removeFolder(new File(
+               assertFalse("Non existing folders are not deleted.", 
Files.removeFolder(new File(
                        
"/somethingThatDoesntExistsOnMostMachines-111111111111111111111111111111")));
 
                java.io.File folder = new 
File(System.getProperty("java.io.tmpdir"), "wicket-test-folder");
@@ -82,4 +82,68 @@ public class FilesTest extends Assert
 
                assertTrue("Should be able to delete a folder.", 
Files.removeFolder(folder));
        }
+
+       /**
+        * Tests for {@link Files#removeAsync(java.io.File, IFileCleaner)}
+        * 
+        * @throws Exception
+        */
+       @Test
+       public void removeAsync() throws Exception
+       {
+
+               IFileCleaner fileCleaner = new FileCleaner();
+
+               assertFalse("'null' files are not deleted.", 
Files.removeAsync(null, fileCleaner));
+
+               File nonExistingFile = new File(
+                       
"/somethingThatDoesntExistsOnMostMachines-111111111111111111111111111111");
+               assertTrue("Even non existing file are scheduled for deletion.",
+                       Files.removeFolderAsync(nonExistingFile, fileCleaner));
+               assertFalse(nonExistingFile.exists());
+
+               java.io.File file = 
java.io.File.createTempFile("wicket-test--", ".tmp");
+               assertTrue("The just created file should exist!", 
file.exists());
+               file.createNewFile();
+               assertTrue(file.isFile());
+
+               assertTrue("The file is scheduled for deletion.", 
Files.removeAsync(file, fileCleaner));
+               // give chance to the file cleaner to run and delete the folder
+               System.gc();
+               Thread.sleep(5);
+               assertFalse("", file.exists());
+       }
+
+       /**
+        * Tests for {@link Files#removeFolderAsync(java.io.File, IFileCleaner)}
+        * 
+        * @throws Exception
+        */
+       @Test
+       public void removeFolderAsync() throws Exception
+       {
+               assertFalse("'null' folders are not deleted.", 
Files.removeFolderAsync(null, null));
+
+               IFileCleaner fileCleaner = new FileCleaner();
+
+               File nonExistingFolder = new File(
+                       
"/somethingThatDoesntExistsOnMostMachines-111111111111111111111111111111");
+               assertTrue("Even non existing folders are scheduled for 
deletion.",
+                       Files.removeFolderAsync(nonExistingFolder, 
fileCleaner));
+               assertFalse(nonExistingFolder.exists());
+
+               java.io.File folder = new 
File(System.getProperty("java.io.tmpdir"), "wicket-test-folder");
+               Files.mkdirs(folder);
+               assertTrue(folder.isDirectory());
+               File file = new File(folder, "child");
+               file.createNewFile();
+               assertTrue(file.exists());
+
+               assertTrue("The folder is scheduled for deletion.",
+                       Files.removeFolderAsync(folder, fileCleaner));
+               // give chance to the file cleaner to run and delete the folder
+               System.gc();
+               Thread.sleep(5);
+               assertFalse("", folder.exists());
+       }
 }


Reply via email to