/*
* Copyright(c) 2005 Center for E-Commerce Infrastructure Development, The
* University of Hong Kong (HKU). All Rights Reserved.
*
* This software is licensed under the GNU GENERAL PUBLIC LICENSE Version 2.0 [1]
*
* [1] http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
*/
package hk.hku.cecid.piazza.commons.io;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
/**
* FileSystem encapsulates a root directory and provides accessors for querying
* and modifying this root.
*
* @author Hugo Y. K. Lam
*
*/
public class FileSystem {
/**
* Type File.
*/
public static int TYPE_FILE = 1;
/**
* Type Directory.
*/
public static int TYPE_DIR = 2;
/**
* Type All.
*/
public static int TYPE_ALL = (TYPE_FILE | TYPE_DIR);
/**
* The root of this file system.
*/
private File root;
/**
* Creates a new instance of FileSystem.
*
* @param root the root of this file system. If root is null, it will be set
* to the current user directory.
*/
public FileSystem(File root) {
if (root == null) {
this.root = new File(System.getProperty("user.dir"));
}
else {
root = root.getAbsoluteFile();
if (root.isDirectory() || !root.exists()) {
this.root = root;
}
else {
this.root = root.getParentFile();
}
}
}
/**
* Retrieves a collection of file-only File objects from the
* root of this file system.
*
* @param isRecursive true if the search should be recursive.
* @return a collection of File objects resulted from the search.
*/
public Collection getFiles(boolean isRecursive) {
return getFiles(isRecursive, TYPE_FILE, null);
}
/**
* Retrieves a collection of file-only File objects from the
* root of this file system.
*
* @param isRecursive true if the search should be recursive.
* @param pattern the filename's pattern for filtering the result. null if
* no filtering should be applied.
* @return a collection of File objects resulted from the search.
*/
public Collection getFiles(boolean isRecursive, String pattern) {
return getFiles(isRecursive, TYPE_FILE, pattern);
}
/**
* Retrieves a collection of directory-only File objects from the
* root of this file system.
*
* @param isRecursive true if the search should be recursive.
* @return a collection of File objects resulted from the search.
*/
public Collection getDirectories(boolean isRecursive) {
return getFiles(isRecursive, TYPE_DIR, null);
}
/**
* Retrieves a collection of directory-only File objects from the
* root of this file system.
*
* @param isRecursive true if the search should be recursive.
* @param pattern the filename's pattern for filtering the result. null if
* no filtering should be applied.
* @return a collection of File objects resulted from the search.
*/
public Collection getDirectories(boolean isRecursive, String pattern) {
return getFiles(isRecursive, TYPE_DIR, pattern);
}
/**
* Retrieves a collection of File objects from the root of this file system.
*
* @param isRecursive true if the search should be recursive.
* @param type the file type to be searched.
* @param pattern the filename's pattern for filtering the result. null if
* no filtering should be applied.
* @return a collection of File objects resulted from the search.
*/
public Collection getFiles(boolean isRecursive, int type, String pattern) {
return this.getFiles(null, isRecursive, type, pattern);
}
/**
* Retrieves a collection of File objects from the root of this file system.
*
* @param c the collection into which the result will be stored.
* @param isRecursive true if the search should be recursive.
* @param type the file type to be searched.
* @param pattern the filename's pattern for filtering the result. null if
* no filtering should be applied.
* @return a collection of File objects resulted from the search.
*/
public Collection getFiles(Collection c, boolean isRecursive, int type,
String pattern) {
return this.getFiles(c, root, isRecursive, type, pattern);
}
/**
* Retrieves a collection of File objects from a specified directory.
*
* @param c the collection into which the result will be stored.
* @param rootDir the directory to be searched.
* @param isRecursive true if the search should be recursive.
* @param type the file type to be searched.
* @param pattern the filename's pattern for filtering the result. null if
* no filtering should be applied.
* @return a collection of File objects resulted from the search.
*/
private Collection getFiles(Collection c, File rootDir,
boolean isRecursive, int type, String pattern) {
File[] subfiles = rootDir.listFiles();
if (subfiles == null || subfiles.length == 0) {
return Collections.EMPTY_LIST;
}
else {
if (c == null) {
c = new ArrayList();
}
for (int i = 0; i < subfiles.length; i++) {
if (subfiles[i].isDirectory()) {
if ((TYPE_DIR & type) == TYPE_DIR) {
if (accept(subfiles[i], pattern)) {
c.add(subfiles[i]);
}
}
if (isRecursive) {
getFiles(c, subfiles[i], isRecursive, type, pattern);
}
}
else {
if ((TYPE_FILE & type) == TYPE_FILE) {
if (accept(subfiles[i], pattern)) {
c.add(subfiles[i]);
}
}
}
}
return c;
}
}
/**
* Checks if the specified file should be accepted according to the given
* pattern.
*
* @param f the file to be checked.
* @param pattern the filename's pattern to be checked against.
* @return true if the specified file should be accepted.
*/
private boolean accept(File f, String pattern) {
if (pattern == null || f.getName().matches(pattern)) {
return true;
}
else {
return false;
}
}
/**
* Removes the files, including the directories, under the root directory of
* this file system recursively. The operation ceases when it encounters any
* error in removing any file. If the operation is successful, the root
* directory itself will be removed as well.
*
* @return true if and only if all the files are removed successfully.
*/
public boolean remove() {
return remove(true);
}
/**
* Removes the files, including the directories, under the root of this file
* system recursively. The operation ceases when it encounters any error
* in removing any file.
*
* @param isSelfRemoved true if the root directory itself should be removed.
* @return true if and only if all the files are removed successfully.
*/
public boolean remove(boolean isSelfRemoved) {
return remove(root, isSelfRemoved, false);
}
/**
* Removes the files, including the directories, under the specified
* directory recursively. The operation ceases when it encounters any error
* in removing any file.
*
* @param rootDir the directory under which the files will be removed.
* @param isSelfRemoved true if the root directory itself should be removed.
* @param isDeferAllowed true if the files can be removed on exit when necessary.
* @return true if and only if all the files are removed successfully.
*/
private boolean remove(File rootDir, boolean isSelfRemoved, boolean isDeferAllowed) {
File[] subfiles = rootDir.listFiles();
if (subfiles != null) {
for (int i=0; i<subfiles.length; i++) {
if (subfiles[i].isDirectory()) {
if (!remove(subfiles[i], true, isDeferAllowed)) {
if (!isDeferAllowed) {
return false;
}
}
}
else {
if (!subfiles[i].delete()) {
if (isDeferAllowed) {
subfiles[i].deleteOnExit();
}
else {
return false;
}
}
}
}
}
if (isSelfRemoved) {
if (!rootDir.delete()) {
if (isDeferAllowed) {
rootDir.deleteOnExit() ;
}
else {
return false;
}
}
}
return true;
}
/**
* Removes the files, including the directories, under the root directory of
* this file system recursively. If there are files that cannot be removed
* immediately, the files will be deleted on exit. This method will also
* remove the root directory itself.
*/
public void purge() {
purge(true);
}
/**
* Removes the files, including the directories, under the root directory of
* this file system recursively. If there are files that cannot be removed
* immediately, the files will be deleted on exit.
*
* @param isSelfRemoved true if the root directory itself should be removed.
*/
public void purge(boolean isSelfRemoved) {
remove(root, isSelfRemoved, true);
}
/**
* Gets the root of this file system.
*
* @return the root of this file system.
*/
public File getRoot() {
return root;
}
/**
* Checks if the root of this file system exists.
*
* @return true if the root of this file system exists.
*/
public boolean exists() {
return root.exists();
}
/**
* Returns the absolute path of the root of this file system.
*
* @return the absolute path of the root of this file system.
* @see java.lang.Object#toString()
*/
public String toString() {
return root.getAbsolutePath();
}
}