621 lines
25 KiB
Java
621 lines
25 KiB
Java
/*
|
|
* 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.commons.io;
|
|
|
|
import java.io.File;
|
|
import java.io.FileFilter;
|
|
import java.io.IOException;
|
|
import java.util.Collection;
|
|
|
|
import org.apache.commons.io.filefilter.FileFilterUtils;
|
|
import org.apache.commons.io.filefilter.IOFileFilter;
|
|
import org.apache.commons.io.filefilter.TrueFileFilter;
|
|
|
|
/**
|
|
* Abstract class that walks through a directory hierarchy and provides
|
|
* subclasses with convenient hooks to add specific behaviour.
|
|
* <p>
|
|
* This class operates with a {@link FileFilter} and maximum depth to
|
|
* limit the files and direcories visited.
|
|
* Commons IO supplies many common filter implementations in the
|
|
* <a href="filefilter/package-summary.html"> filefilter</a> package.
|
|
* <p>
|
|
* The following sections describe:
|
|
* <ul>
|
|
* <li><a href="#example">1. Example Implementation</a> - example
|
|
* <code>FileCleaner</code> implementation.</li>
|
|
* <li><a href="#filter">2. Filter Example</a> - using
|
|
* {@link FileFilter}(s) with <code>DirectoryWalker</code>.</li>
|
|
* <li><a href="#cancel">3. Cancellation</a> - how to implement cancellation
|
|
* behaviour.</li>
|
|
* </ul>
|
|
*
|
|
* <a name="example"></a>
|
|
* <h3>1. Example Implementation</h3>
|
|
*
|
|
* There are many possible extensions, for example, to delete all
|
|
* files and '.svn' directories, and return a list of deleted files:
|
|
* <pre>
|
|
* public class FileCleaner extends DirectoryWalker {
|
|
*
|
|
* public FileCleaner() {
|
|
* super();
|
|
* }
|
|
*
|
|
* public List clean(File startDirectory) {
|
|
* List results = new ArrayList();
|
|
* walk(startDirectory, results);
|
|
* return results;
|
|
* }
|
|
*
|
|
* protected boolean handleDirectory(File directory, int depth, Collection results) {
|
|
* // delete svn directories and then skip
|
|
* if (".svn".equals(directory.getName())) {
|
|
* directory.delete();
|
|
* return false;
|
|
* } else {
|
|
* return true;
|
|
* }
|
|
*
|
|
* }
|
|
*
|
|
* protected void handleFile(File file, int depth, Collection results) {
|
|
* // delete file and add to list of deleted
|
|
* file.delete();
|
|
* results.add(file);
|
|
* }
|
|
* }
|
|
* </pre>
|
|
*
|
|
* <a name="filter"></a>
|
|
* <h3>2. Filter Example</h3>
|
|
*
|
|
* Choosing which directories and files to process can be a key aspect
|
|
* of using this class. This information can be setup in three ways,
|
|
* via three different constructors.
|
|
* <p>
|
|
* The first option is to visit all directories and files.
|
|
* This is achieved via the no-args constructor.
|
|
* <p>
|
|
* The second constructor option is to supply a single {@link FileFilter}
|
|
* that describes the files and directories to visit. Care must be taken
|
|
* with this option as the same filter is used for both directories
|
|
* and files.
|
|
* <p>
|
|
* For example, if you wanted all directories which are not hidden
|
|
* and files which end in ".txt":
|
|
* <pre>
|
|
* public class FooDirectoryWalker extends DirectoryWalker {
|
|
* public FooDirectoryWalker(FileFilter filter) {
|
|
* super(filter, -1);
|
|
* }
|
|
* }
|
|
*
|
|
* // Build up the filters and create the walker
|
|
* // Create a filter for Non-hidden directories
|
|
* IOFileFilter fooDirFilter =
|
|
* FileFilterUtils.andFileFilter(FileFilterUtils.directoryFileFilter,
|
|
* HiddenFileFilter.VISIBLE);
|
|
*
|
|
* // Create a filter for Files ending in ".txt"
|
|
* IOFileFilter fooFileFilter =
|
|
* FileFilterUtils.andFileFilter(FileFilterUtils.fileFileFilter,
|
|
* FileFilterUtils.suffixFileFilter(".txt"));
|
|
*
|
|
* // Combine the directory and file filters using an OR condition
|
|
* java.io.FileFilter fooFilter =
|
|
* FileFilterUtils.orFileFilter(fooDirFilter, fooFileFilter);
|
|
*
|
|
* // Use the filter to construct a DirectoryWalker implementation
|
|
* FooDirectoryWalker walker = new FooDirectoryWalker(fooFilter);
|
|
* </pre>
|
|
* <p>
|
|
* The third constructor option is to specify separate filters, one for
|
|
* directories and one for files. These are combined internally to form
|
|
* the correct <code>FileFilter</code>, something which is very easy to
|
|
* get wrong when attempted manually, particularly when trying to
|
|
* express constructs like 'any file in directories named docs'.
|
|
* <p>
|
|
* For example, if you wanted all directories which are not hidden
|
|
* and files which end in ".txt":
|
|
* <pre>
|
|
* public class FooDirectoryWalker extends DirectoryWalker {
|
|
* public FooDirectoryWalker(IOFileFilter dirFilter, IOFileFilter fileFilter) {
|
|
* super(dirFilter, fileFilter, -1);
|
|
* }
|
|
* }
|
|
*
|
|
* // Use the filters to construct the walker
|
|
* FooDirectoryWalker walker = new FooDirectoryWalker(
|
|
* HiddenFileFilter.VISIBLE,
|
|
* FileFilterUtils.suffixFileFilter(".txt"),
|
|
* );
|
|
* </pre>
|
|
* This is much simpler than the previous example, and is why it is the preferred
|
|
* option for filtering.
|
|
*
|
|
* <a name="cancel"></a>
|
|
* <h3>3. Cancellation</h3>
|
|
*
|
|
* The DirectoryWalker contains some of the logic required for cancel processing.
|
|
* Subclasses must complete the implementation.
|
|
* <p>
|
|
* What <code>DirectoryWalker</code> does provide for cancellation is:
|
|
* <ul>
|
|
* <li>{@link CancelException} which can be thrown in any of the
|
|
* <i>lifecycle</i> methods to stop processing.</li>
|
|
* <li>The <code>walk()</code> method traps thrown {@link CancelException}
|
|
* and calls the <code>handleCancelled()</code> method, providing
|
|
* a place for custom cancel processing.</li>
|
|
* </ul>
|
|
* <p>
|
|
* Implementations need to provide:
|
|
* <ul>
|
|
* <li>The decision logic on whether to cancel processing or not.</li>
|
|
* <li>Constructing and throwing a {@link CancelException}.</li>
|
|
* <li>Custom cancel processing in the <code>handleCancelled()</code> method.
|
|
* </ul>
|
|
* <p>
|
|
* Two possible scenarios are envisaged for cancellation:
|
|
* <ul>
|
|
* <li><a href="#external">3.1 External / Mult-threaded</a> - cancellation being
|
|
* decided/initiated by an external process.</li>
|
|
* <li><a href="#internal">3.2 Internal</a> - cancellation being decided/initiated
|
|
* from within a DirectoryWalker implementation.</li>
|
|
* </ul>
|
|
* <p>
|
|
* The following sections provide example implementations for these two different
|
|
* scenarios.
|
|
*
|
|
* <a name="external"></a>
|
|
* <h4>3.1 External / Multi-threaded</h4>
|
|
*
|
|
* This example provides a public <code>cancel()</code> method that can be
|
|
* called by another thread to stop the processing. A typical example use-case
|
|
* would be a cancel button on a GUI. Calling this method sets a
|
|
* <a href="http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#36930">
|
|
* volatile</a> flag to ensure it will work properly in a multi-threaded environment.
|
|
* The flag is returned by the <code>handleIsCancelled()</code> method, which
|
|
* will cause the walk to stop immediately. The <code>handleCancelled()</code>
|
|
* method will be the next, and last, callback method received once cancellation
|
|
* has occurred.
|
|
*
|
|
* <pre>
|
|
* public class FooDirectoryWalker extends DirectoryWalker {
|
|
*
|
|
* private volatile boolean cancelled = false;
|
|
*
|
|
* public void cancel() {
|
|
* cancelled = true;
|
|
* }
|
|
*
|
|
* private void handleIsCancelled(File file, int depth, Collection results) {
|
|
* return cancelled;
|
|
* }
|
|
*
|
|
* protected void handleCancelled(File startDirectory, Collection results, CancelException cancel) {
|
|
* // implement processing required when a cancellation occurs
|
|
* }
|
|
* }
|
|
* </pre>
|
|
*
|
|
* <a name="internal"></a>
|
|
* <h4>3.2 Internal</h4>
|
|
*
|
|
* This shows an example of how internal cancellation processing could be implemented.
|
|
* <b>Note</b> the decision logic and throwing a {@link CancelException} could be implemented
|
|
* in any of the <i>lifecycle</i> methods.
|
|
*
|
|
* <pre>
|
|
* public class BarDirectoryWalker extends DirectoryWalker {
|
|
*
|
|
* protected boolean handleDirectory(File directory, int depth, Collection results) throws IOException {
|
|
* // cancel if hidden directory
|
|
* if (directory.isHidden()) {
|
|
* throw new CancelException(file, depth);
|
|
* }
|
|
* return true;
|
|
* }
|
|
*
|
|
* protected void handleFile(File file, int depth, Collection results) throws IOException {
|
|
* // cancel if read-only file
|
|
* if (!file.canWrite()) {
|
|
* throw new CancelException(file, depth);
|
|
* }
|
|
* results.add(file);
|
|
* }
|
|
*
|
|
* protected void handleCancelled(File startDirectory, Collection results, CancelException cancel) {
|
|
* // implement processing required when a cancellation occurs
|
|
* }
|
|
* }
|
|
* </pre>
|
|
*
|
|
* @since Commons IO 1.3
|
|
* @version $Revision: 424748 $
|
|
*/
|
|
public abstract class DirectoryWalker {
|
|
|
|
/**
|
|
* The file filter to use to filter files and directories.
|
|
*/
|
|
private final FileFilter filter;
|
|
/**
|
|
* The limit on the directory depth to walk.
|
|
*/
|
|
private final int depthLimit;
|
|
|
|
/**
|
|
* Construct an instance with no filtering and unlimited <i>depth</i>.
|
|
*/
|
|
protected DirectoryWalker() {
|
|
this(null, -1);
|
|
}
|
|
|
|
/**
|
|
* Construct an instance with a filter and limit the <i>depth</i> navigated to.
|
|
* <p>
|
|
* The filter controls which files and directories will be navigated to as
|
|
* part of the walk. The {@link FileFilterUtils} class is useful for combining
|
|
* various filters together. A <code>null</code> filter means that no
|
|
* filtering should occur and all files and directories will be visited.
|
|
*
|
|
* @param filter the filter to apply, null means visit all files
|
|
* @param depthLimit controls how <i>deep</i> the hierarchy is
|
|
* navigated to (less than 0 means unlimited)
|
|
*/
|
|
protected DirectoryWalker(FileFilter filter, int depthLimit) {
|
|
this.filter = filter;
|
|
this.depthLimit = depthLimit;
|
|
}
|
|
|
|
/**
|
|
* Construct an instance with a directory and a file filter and an optional
|
|
* limit on the <i>depth</i> navigated to.
|
|
* <p>
|
|
* The filters control which files and directories will be navigated to as part
|
|
* of the walk. This constructor uses {@link FileFilterUtils#makeDirectoryOnly(IOFileFilter)}
|
|
* and {@link FileFilterUtils#makeFileOnly(IOFileFilter)} internally to combine the filters.
|
|
* A <code>null</code> filter means that no filtering should occur.
|
|
*
|
|
* @param directoryFilter the filter to apply to directories, null means visit all directories
|
|
* @param fileFilter the filter to apply to files, null means visit all files
|
|
* @param depthLimit controls how <i>deep</i> the hierarchy is
|
|
* navigated to (less than 0 means unlimited)
|
|
*/
|
|
protected DirectoryWalker(IOFileFilter directoryFilter, IOFileFilter fileFilter, int depthLimit) {
|
|
if (directoryFilter == null && fileFilter == null) {
|
|
this.filter = null;
|
|
} else {
|
|
directoryFilter = (directoryFilter != null ? directoryFilter : TrueFileFilter.TRUE);
|
|
fileFilter = (fileFilter != null ? fileFilter : TrueFileFilter.TRUE);
|
|
directoryFilter = FileFilterUtils.makeDirectoryOnly(directoryFilter);
|
|
fileFilter = FileFilterUtils.makeFileOnly(fileFilter);
|
|
this.filter = FileFilterUtils.orFileFilter(directoryFilter, fileFilter);
|
|
}
|
|
this.depthLimit = depthLimit;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
/**
|
|
* Internal method that walks the directory hierarchy in a depth-first manner.
|
|
* <p>
|
|
* Users of this class do not need to call this method. This method will
|
|
* be called automatically by another (public) method on the specific subclass.
|
|
* <p>
|
|
* Writers of subclasses should call this method to start the directory walk.
|
|
* Once called, this method will emit events as it walks the hierarchy.
|
|
* The event methods have the prefix <code>handle</code>.
|
|
*
|
|
* @param startDirectory the directory to start from, not null
|
|
* @param results the collection of result objects, may be updated
|
|
* @throws NullPointerException if the start directory is null
|
|
* @throws IOException if an I/O Error occurs
|
|
*/
|
|
protected final void walk(File startDirectory, Collection results) throws IOException {
|
|
if (startDirectory == null) {
|
|
throw new NullPointerException("Start Directory is null");
|
|
}
|
|
try {
|
|
handleStart(startDirectory, results);
|
|
walk(startDirectory, 0, results);
|
|
handleEnd(results);
|
|
} catch(CancelException cancel) {
|
|
handleCancelled(startDirectory, results, cancel);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Main recursive method to examine the directory hierarchy.
|
|
*
|
|
* @param directory the directory to examine, not null
|
|
* @param depth the directory level (starting directory = 0)
|
|
* @param results the collection of result objects, may be updated
|
|
* @throws IOException if an I/O Error occurs
|
|
*/
|
|
private void walk(File directory, int depth, Collection results) throws IOException {
|
|
checkIfCancelled(directory, depth, results);
|
|
if (handleDirectory(directory, depth, results)) {
|
|
handleDirectoryStart(directory, depth, results);
|
|
int childDepth = depth + 1;
|
|
if (depthLimit < 0 || childDepth <= depthLimit) {
|
|
checkIfCancelled(directory, depth, results);
|
|
File[] childFiles = (filter == null ? directory.listFiles() : directory.listFiles(filter));
|
|
if (childFiles == null) {
|
|
handleRestricted(directory, childDepth, results);
|
|
} else {
|
|
for (int i = 0; i < childFiles.length; i++) {
|
|
File childFile = childFiles[i];
|
|
if (childFile.isDirectory()) {
|
|
walk(childFile, childDepth, results);
|
|
} else {
|
|
checkIfCancelled(childFile, childDepth, results);
|
|
handleFile(childFile, childDepth, results);
|
|
checkIfCancelled(childFile, childDepth, results);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
handleDirectoryEnd(directory, depth, results);
|
|
}
|
|
checkIfCancelled(directory, depth, results);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
/**
|
|
* Checks whether the walk has been cancelled by calling {@link #handleIsCancelled},
|
|
* throwing a <code>CancelException</code> if it has.
|
|
* <p>
|
|
* Writers of subclasses should not normally call this method as it is called
|
|
* automatically by the walk of the tree. However, sometimes a single method,
|
|
* typically {@link #handleFile}, may take a long time to run. In that case,
|
|
* you may wish to check for cancellation by calling this method.
|
|
*
|
|
* @param file the current file being processed
|
|
* @param depth the current file level (starting directory = 0)
|
|
* @param results the collection of result objects, may be updated
|
|
* @throws IOException if an I/O Error occurs
|
|
*/
|
|
protected final void checkIfCancelled(File file, int depth, Collection results) throws IOException {
|
|
if (handleIsCancelled(file, depth, results)) {
|
|
throw new CancelException(file, depth);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Overridable callback method invoked to determine if the entire walk
|
|
* operation should be immediately cancelled.
|
|
* <p>
|
|
* This method should be implemented by those subclasses that want to
|
|
* provide a public <code>cancel()</code> method available from another
|
|
* thread. The design pattern for the subclass should be as follows:
|
|
* <pre>
|
|
* public class FooDirectoryWalker extends DirectoryWalker {
|
|
* private volatile boolean cancelled = false;
|
|
*
|
|
* public void cancel() {
|
|
* cancelled = true;
|
|
* }
|
|
* private void handleIsCancelled(File file, int depth, Collection results) {
|
|
* return cancelled;
|
|
* }
|
|
* protected void handleCancelled(File startDirectory,
|
|
* Collection results, CancelException cancel) {
|
|
* // implement processing required when a cancellation occurs
|
|
* }
|
|
* }
|
|
* </pre>
|
|
* <p>
|
|
* If this method returns true, then the directory walk is immediately
|
|
* cancelled. The next callback method will be {@link #handleCancelled}.
|
|
* <p>
|
|
* This implementation returns false.
|
|
*
|
|
* @param file the file or directory being processed
|
|
* @param depth the current directory level (starting directory = 0)
|
|
* @param results the collection of result objects, may be updated
|
|
* @return true if the walk has been cancelled
|
|
* @throws IOException if an I/O Error occurs
|
|
*/
|
|
protected boolean handleIsCancelled(
|
|
File file, int depth, Collection results) throws IOException {
|
|
// do nothing - overridable by subclass
|
|
return false; // not cancelled
|
|
}
|
|
|
|
/**
|
|
* Overridable callback method invoked when the operation is cancelled.
|
|
* The file being processed when the cancellation occurred can be
|
|
* obtained from the exception.
|
|
* <p>
|
|
* This implementation just re-throws the {@link CancelException}.
|
|
*
|
|
* @param startDirectory the directory that the walk started from
|
|
* @param results the collection of result objects, may be updated
|
|
* @param cancel the exception throw to cancel further processing
|
|
* containing details at the point of cancellation.
|
|
* @throws IOException if an I/O Error occurs
|
|
*/
|
|
protected void handleCancelled(File startDirectory, Collection results,
|
|
CancelException cancel) throws IOException {
|
|
// re-throw exception - overridable by subclass
|
|
throw cancel;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
/**
|
|
* Overridable callback method invoked at the start of processing.
|
|
* <p>
|
|
* This implementation does nothing.
|
|
*
|
|
* @param startDirectory the directory to start from
|
|
* @param results the collection of result objects, may be updated
|
|
* @throws IOException if an I/O Error occurs
|
|
*/
|
|
protected void handleStart(File startDirectory, Collection results) throws IOException {
|
|
// do nothing - overridable by subclass
|
|
}
|
|
|
|
/**
|
|
* Overridable callback method invoked to determine if a directory should be processed.
|
|
* <p>
|
|
* This method returns a boolean to indicate if the directory should be examined or not.
|
|
* If you return false, the entire directory and any subdirectories will be skipped.
|
|
* Note that this functionality is in addition to the filtering by file filter.
|
|
* <p>
|
|
* This implementation does nothing and returns true.
|
|
*
|
|
* @param directory the current directory being processed
|
|
* @param depth the current directory level (starting directory = 0)
|
|
* @param results the collection of result objects, may be updated
|
|
* @return true to process this directory, false to skip this directory
|
|
* @throws IOException if an I/O Error occurs
|
|
*/
|
|
protected boolean handleDirectory(File directory, int depth, Collection results) throws IOException {
|
|
// do nothing - overridable by subclass
|
|
return true; // process directory
|
|
}
|
|
|
|
/**
|
|
* Overridable callback method invoked at the start of processing each directory.
|
|
* <p>
|
|
* This implementation does nothing.
|
|
*
|
|
* @param directory the current directory being processed
|
|
* @param depth the current directory level (starting directory = 0)
|
|
* @param results the collection of result objects, may be updated
|
|
* @throws IOException if an I/O Error occurs
|
|
*/
|
|
protected void handleDirectoryStart(File directory, int depth, Collection results) throws IOException {
|
|
// do nothing - overridable by subclass
|
|
}
|
|
|
|
/**
|
|
* Overridable callback method invoked for each (non-directory) file.
|
|
* <p>
|
|
* This implementation does nothing.
|
|
*
|
|
* @param file the current file being processed
|
|
* @param depth the current directory level (starting directory = 0)
|
|
* @param results the collection of result objects, may be updated
|
|
* @throws IOException if an I/O Error occurs
|
|
*/
|
|
protected void handleFile(File file, int depth, Collection results) throws IOException {
|
|
// do nothing - overridable by subclass
|
|
}
|
|
|
|
/**
|
|
* Overridable callback method invoked for each restricted directory.
|
|
* <p>
|
|
* This implementation does nothing.
|
|
*
|
|
* @param directory the restricted directory
|
|
* @param depth the current directory level (starting directory = 0)
|
|
* @param results the collection of result objects, may be updated
|
|
* @throws IOException if an I/O Error occurs
|
|
*/
|
|
protected void handleRestricted(File directory, int depth, Collection results) throws IOException {
|
|
// do nothing - overridable by subclass
|
|
}
|
|
|
|
/**
|
|
* Overridable callback method invoked at the end of processing each directory.
|
|
* <p>
|
|
* This implementation does nothing.
|
|
*
|
|
* @param directory the directory being processed
|
|
* @param depth the current directory level (starting directory = 0)
|
|
* @param results the collection of result objects, may be updated
|
|
* @throws IOException if an I/O Error occurs
|
|
*/
|
|
protected void handleDirectoryEnd(File directory, int depth, Collection results) throws IOException {
|
|
// do nothing - overridable by subclass
|
|
}
|
|
|
|
/**
|
|
* Overridable callback method invoked at the end of processing.
|
|
* <p>
|
|
* This implementation does nothing.
|
|
*
|
|
* @param results the collection of result objects, may be updated
|
|
* @throws IOException if an I/O Error occurs
|
|
*/
|
|
protected void handleEnd(Collection results) throws IOException {
|
|
// do nothing - overridable by subclass
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
/**
|
|
* CancelException is thrown in DirectoryWalker to cancel the current
|
|
* processing.
|
|
*/
|
|
public static class CancelException extends IOException {
|
|
|
|
/** Serialization id. */
|
|
private static final long serialVersionUID = 1347339620135041008L;
|
|
|
|
/** The file being processed when the exception was thrown. */
|
|
private File file;
|
|
/** The file depth when the exception was thrown. */
|
|
private int depth = -1;
|
|
|
|
/**
|
|
* Constructs a <code>CancelException</code> with
|
|
* the file and depth when cancellation occurred.
|
|
*
|
|
* @param file the file when the operation was cancelled, may be null
|
|
* @param depth the depth when the operation was cancelled, may be null
|
|
*/
|
|
public CancelException(File file, int depth) {
|
|
this("Operation Cancelled", file, depth);
|
|
}
|
|
|
|
/**
|
|
* Constructs a <code>CancelException</code> with
|
|
* an appropriate message and the file and depth when
|
|
* cancellation occurred.
|
|
*
|
|
* @param message the detail message
|
|
* @param file the file when the operation was cancelled
|
|
* @param depth the depth when the operation was cancelled
|
|
*/
|
|
public CancelException(String message, File file, int depth) {
|
|
super(message);
|
|
this.file = file;
|
|
this.depth = depth;
|
|
}
|
|
|
|
/**
|
|
* Return the file when the operation was cancelled.
|
|
*
|
|
* @return the file when the operation was cancelled
|
|
*/
|
|
public File getFile() {
|
|
return file;
|
|
}
|
|
|
|
/**
|
|
* Return the depth when the operation was cancelled.
|
|
*
|
|
* @return the depth when the operation was cancelled
|
|
*/
|
|
public int getDepth() {
|
|
return depth;
|
|
}
|
|
}
|
|
}
|