package net.sf.cotta; import net.sf.cotta.io.OutputManager; import net.sf.cotta.io.OutputProcessor; import net.sf.cotta.system.FileSystem; import java.io.File; import java.io.IOException; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * The class that represent the directory. To create TDirectory, use TFile, TDirectory, and TFileFactory * * @see TFileFactory#physicalDir(java.io.File) * @see TFileFactory#dir(String) * @see TFileFactory#dir(TPath) * @see TFile#parent() * @see TDirectory#parent() * @see TDirectory#dir(String) * @see TDirectory#dir(TPath) */ public class TDirectory extends TEntry { /** * Constructor that creates the directory to be mainly used internally. * * @param fileSystem The file system that backs the file * @param path The path to the file * @see #TDirectory(TFileFactory, TPath) * @deprecated Use the other constructor for default encoding support in TFileFactory */ public TDirectory(FileSystem fileSystem, TPath path) { super(new TFileFactory(fileSystem), path); } public TDirectory(TFileFactory factory, TPath path) { super(factory, path); } public boolean exists() { return filesystem().dirExists(path); } public TDirectory ensureExists() throws TIoException { if (!filesystem().dirExists(path)) { filesystem().createDir(path); } return this; } /** * Constucts a file given the path. If the path is relative path, * it will be constructed based on the current directory * * @param path the path of the file * @return The file that is under the directory with the name * @see #file(TPath) */ public TFile file(String path) { return file(TPath.parse(path)); } /** * Constructs a file given the relative path. If the path is relative, * it will be constructed based on the current direcotry * * @param path path to the file * @return The file that is of the relative to the current directory */ public TFile file(TPath path) { return new TFile(factory(), join(path)); } private TPath join(TPath path) { return path.isRelative() ? this.path.join(path) : path; } /** * Constructs a subdirectory given the directory name * * @param relativePath the relative path of the sub-directory * @return The directory that is under the current directory with the given name */ public TDirectory dir(String relativePath) { return dir(TPath.parse(relativePath)); } /** * Constructs a directory given the relative path to the current directory * * @param path the relative path of the target directory to current directory * @return The target directory that is of the given the relative path */ public TDirectory dir(TPath path) { return new TDirectory(factory(), join(path)); } /** * List the sub-directories of the current directory * * @return mutable list of TDirectory that can be sorted * @throws TIoException for error in reading the directory * @deprecated use list().dirs() */ @Deprecated public TDirectory[] listDirs() throws TIoException { List<TDirectory> dirs = list().dirs(); return dirs.toArray(new TDirectory[dirs.size()]); } /** * List the sub-directories of the current directory that can be accepted by the filter * * @param directoryFilter filter for the directory * @return list of sub-directories * @throws TIoException for error in reading the directory * @deprecated use list(directoryFilter).dirs() */ @Deprecated public TDirectory[] listDirs(TDirectoryFilter directoryFilter) throws TIoException { List<TDirectory> dirs = list(directoryFilter).dirs(); return dirs.toArray(new TDirectory[dirs.size()]); } /** * List the current directory * * @return list of TEntry that are either TFile or TDirectory * @throws TIoException for error in reading current directory */ public TDirectoryListing list() throws TIoException { return list(TEntryFilter.ALL); } /** * List the current directory with entry filter * * @param filter entry filter * @return directory listing that has file filter and directory filter set to the filterd passed in * @throws TIoException for error in reading current directory */ public TDirectoryListing list(TEntryFilter filter) throws TIoException { return listing().filteredBy(filter, filter); } /** * List the current directory with file filter * * @param filter file filter * @return filted directory listing with the directory filter set to ALL and file filter set to the filter passed in * @throws TIoException for error in reading current directory */ public TDirectoryListing list(TFileFilter filter) throws TIoException { return listing().filteredBy(TDirectoryFilter.ALL, filter); } /** * List the current directory with directory filter * * @param filter directory filter * @return filted direcotry listing with the directory filter set to the filter passed on, and file filter set to ALL * @throws TIoException for error in reading current directory */ public TDirectoryListing list(TDirectoryFilter filter) throws TIoException { return listing().filteredBy(filter, TFileFilter.ALL); } /** * List the current directory with file filter and directory filter * * @param directoryFilter directory filter * @param fileFilter file filter * @return filted direcotry listing with the directory filter set to the filter passed on, and file filter set to ALL * @throws TIoException for error in reading current directory */ public TDirectoryListing list(TDirectoryFilter directoryFilter, TFileFilter fileFilter) throws TIoException { return listing().filteredBy(directoryFilter, fileFilter); } private TDirectoryListing listing() throws TIoException { checkDirectoryExists(); return new TDirectoryListing(factory(), listContent()); } private PathContent listContent() throws TIoException { checkDirectoryExists(); return filesystem().list(this.path); } private void checkDirectoryExists() throws TIoException { if (!filesystem().dirExists(path)) { throw new TDirectoryNotFoundException(path); } } /** * List files under current directory * * @return a mutable list of files under current directory * @throws TIoException error in reading from current directory * @deprecated */ @Deprecated public TFile[] listFiles() throws TIoException { List<TFile> files = list(TFileFilter.ALL).files(); return files.toArray(new TFile[files.size()]); } /** * List files under current directory that accepted by the file filter * * @param fileFilter file filter for the list * @return a mutable list of files * @throws TIoException error in reading from current directory * @deprecated use list(fileFilter).files() */ @Deprecated public TFile[] listFiles(TFileFilter fileFilter) throws TIoException { List<TFile> files = list(fileFilter).files(); return files.toArray(new TFile[files.size()]); } /** * Delete the current directory. Most file system will fail * if the current directory is not empty * * @throws TIoException error in deleting the directory (most file system will fail when directory is not empty) */ public void delete() throws TIoException { filesystem().deleteDirectory(path); } /** * Delete the whole directory tree * * @throws TIoException error in the operation */ public void deleteAll() throws TIoException { TDirectoryListing listing = list(); for (TDirectory aSubDirectory : listing.dirs()) { aSubDirectory.deleteAll(); } List<TFile> files = listing.files(); for (TFile file : files) { file.delete(); } delete(); } public void mergeTo(TDirectory target) throws TIoException { target.ensureExists(); copySubDirectories(target); copyFiles(target); } private void copySubDirectories(TDirectory target) throws TIoException { for (TDirectory subdir : list().dirs()) { subdir.mergeTo(target.dir(subdir.name())); } } private void copyFiles(TDirectory target) throws TIoException { List<TFile> files = list().files(); for (TFile file : files) { file.copyTo(target.file(file.name())); } } public void moveTo(TDirectory target) throws TIoException { if (!exists()) { throw new TFileNotFoundException(path); } if (target.exists()) { throw new TIoException(target.path, "Destination exists"); } if (filesystem() == target.filesystem() || filesystem().equals(target.filesystem())) { filesystem().moveDirectory(path, target.path); } else { this.mergeTo(target); delete(); } } /** * @return java.io.File presentation of the directory * @deprecated use #toJavaFile() */ @Deprecated public File getJavaFile() { return toJavaFile(); } /** * Zip the current directory to a file, with the files and directories of current directory at the root level * * @param file the target file * @throws TIoException error in reading from the directory or writing to the file */ public void zipTo(TFile file) throws TIoException { file.write(new OutputProcessor() { public void process(OutputManager manager) throws IOException { ZipOutputStream zipStream = new ZipOutputStream(manager.outputStream()); manager.registerResource(zipStream); addDirEntry(zipStream, "", TDirectory.this); } private void addDirEntry(ZipOutputStream zipStream, String path, TDirectory directory) throws IOException { TDirectoryListing listing = directory.list(); List<TFile> files = listing.files(); for (TFile file : files) { addFileEntry(zipStream, path, file); } for (TDirectory subDirectory : listing.dirs()) { addDirEntry(zipStream, path + subDirectory.name() + "/", subDirectory); } zipStream.putNextEntry(new ZipEntry(path + "/")); zipStream.closeEntry(); } private void addFileEntry(ZipOutputStream zipStream, String path, TFile file) throws IOException { ZipEntry entry = new ZipEntry(path + file.name()); zipStream.putNextEntry(entry); file.copyTo(zipStream); zipStream.closeEntry(); } }); } public void visit(FileVisitor fileVisitor) throws TIoException { fileVisitor.visit(this); } public TDirectory toCanonicalDir() { return factory().dir(toCanonicalPath()); } }