package org.marketcetera.util.file; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.Collection; import org.apache.commons.io.DirectoryWalker; import org.apache.commons.io.filefilter.IOFileFilter; import org.marketcetera.util.misc.ClassVersion; /** * A {@link DirectoryWalker} which provides convenience methods to * initiate traversal, and (optionally) does not follow symbolic * links. */ /* $License$ */ @ClassVersion("$Id: SmartLinksDirectoryWalker.java 16154 2012-07-14 16:34:05Z colin $") public abstract class SmartLinksDirectoryWalker extends DirectoryWalker { // INSTANCE DATA. private boolean mFollowLinks; // CONSTRUCTORS. /** * Constructor mirroring superclass constructor. * * @param followLinks True if links should be followed. * * @see DirectoryWalker#DirectoryWalker() */ protected SmartLinksDirectoryWalker (boolean followLinks) { mFollowLinks=followLinks; } /** * Constructor mirroring superclass constructor. * * @param followLinks True if links should be followed. * @param filter The filter to apply. It may be null, meaning * visit all files. * @param depthLimit Controls to what depth the hierarchy is * navigated. Less than 0 means unlimited. * * @see DirectoryWalker#DirectoryWalker(FileFilter,int) */ protected SmartLinksDirectoryWalker (boolean followLinks, FileFilter filter, int depthLimit) { super(filter,depthLimit); mFollowLinks=followLinks; } /** * Constructor mirroring superclass constructor. * * @param followLinks True if links should be followed. * @param directoryFilter The filter to apply to directories. It * may be null, meaning visit all directories. * @param fileFilter The filter to apply to files. It may be null, * meaning visit all directories. * @param depthLimit Controls to what depth the hierarchy is * navigated. Less than 0 means unlimited. * * @see DirectoryWalker#DirectoryWalker(IOFileFilter,IOFileFilter,int) */ protected SmartLinksDirectoryWalker (boolean followLinks, IOFileFilter directoryFilter, IOFileFilter fileFilter, int depthLimit) { super(directoryFilter,fileFilter,depthLimit); mFollowLinks=followLinks; } // INSTANCE METHODS. /** * Returns false if the given directory is a symbolic link to a * directory, and links are not to be followed, thereby blocking * following the link during traversal. In this case, it also * invokes {@link DirectoryWalker#handleFile(File,int,Collection)} * on the link. * * @see DirectoryWalker#handleDirectory(File,int,Collection) */ @SuppressWarnings("unchecked") @Override protected boolean handleDirectory (File directory, int depth, Collection results) throws IOException { if ((FileType.get(directory)!=FileType.LINK_DIR) || getFollowLinks()) { return true; } handleFile(directory,depth,results); return false; } /** * Returns true if symbolic links to directories should be * followed during traversal. * * @return True if so. */ public boolean getFollowLinks() { return mFollowLinks; } /** * Traverses the file tree rooted at the given root. The root may * be nonexistent (no-op) or a plain file (which becomes the only * file visited). * * @param root The root. * @param results An object passed intact into {@link * DirectoryWalker} callbacks. * * @throws IOException Thrown if an I/O error occurs. */ @SuppressWarnings("unchecked") public void apply (File root, Collection results) throws IOException { FileType type=FileType.get(root); if (type==FileType.NONEXISTENT) { return; } if (type.isFile() || (!getFollowLinks() && type.isSymbolicLink())) { handleFile(root,0,results); return; } walk(root,results); } /** * Traverses the file tree rooted at the given root. The root may * be nonexistent (no-op) or a plain file (which becomes the only * file visited). The <code>results</code> argument in all {@link * DirectoryWalker} callbacks will be null. * * @param root The root. * * @throws IOException Thrown if an I/O error occurs. */ public void apply (File root) throws IOException { apply(root,null); } /** * Traverses the file tree rooted at the file with the given * name. The root may be nonexistent (no-op) or a plain file * (which becomes the only file visited). * * @param name The file name. * @param results An object passed intact into {@link * DirectoryWalker} callbacks. * * @throws IOException Thrown if an I/O error occurs. */ @SuppressWarnings("unchecked") public void apply (String name, Collection results) throws IOException { apply(new File(name),results); } /** * Traverses the file tree rooted at the file with the given * name. The root may be nonexistent (no-op) or a plain file * (which becomes the only file visited). The <code>results</code> * argument in all {@link DirectoryWalker} callbacks will be null. * * @param name The file name. * * @throws IOException Thrown if an I/O error occurs. */ public void apply (String name) throws IOException { apply(name,null); } }