/*
* Copyright (C) 2013 Google Inc.
*
* Licensed 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 interactivespaces.util.io;
import interactivespaces.InteractiveSpacesException;
import interactivespaces.SimpleInteractiveSpacesException;
import java.io.Closeable;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.List;
import java.util.zip.ZipOutputStream;
/**
* Various useful file routines.
*
* TODO(peringknife): All the explicit IOExceptions in this class/interface should be converted to be unchecked IS
* exception of some sort.
*
* @author Trevor Pering
*/
public interface FileSupport {
/**
* Internal helper function to recursively copy contents into a zip file.
*
* @param zipOutputStream
* output stream in which to copy the contents
* @param basePath
* base path for the content copy
* @param relPath
* relative path (to {@code basePath}), that will be included in the zip file
* @param pathPrefix
* path prefix for added sections
*/
void addFileToZipStream(ZipOutputStream zipOutputStream, File basePath, File relPath, String pathPrefix);
/**
* Create a new zip output stream.
*
* @param outputFile
* the target output file
*
* @return the zip output stream
*/
ZipOutputStream createZipOutputStream(File outputFile);
/**
* Place the contents of a zip file into a base directory.
*
* @param source
* the source zip file
* @param baseLocation
* where the contents will be written
*/
void unzip(File source, File baseLocation);
/**
* Place the contents of a zip file into a base directory and keep a record of unzipped files.
*
* @param source
* the source zip file
* @param baseLocation
* where the contents will be written
* @param fileCollector
* if not {@code null}, add extracted files to map, with dest (key) and source (value)
*/
void unzip(File source, File baseLocation, FileCollector fileCollector);
/**
* Place the contents of a directory into a zip file.
*
* @param target
* the output zip file
* @param sourceDirectory
* the source content directory
*/
void zip(File target, File sourceDirectory);
/**
* Place the contents of a directory into a zip file.
*
* @param target
* the output zip file
* @param sourceDirectory
* the source content directory
* @param overwrite
* {@code true} if should overwrite an existing target
*/
void zip(File target, File sourceDirectory, boolean overwrite);
/**
* Copy the source directory to the destination directory.
*
* <p>
* The copy includes all subdirectories, their subdirectories, etc.
*
* <p>
* The destination directory is cleaned out before the source directory is copied.
*
* @param srcDir
* the source directory
* @param destDir
* the destination directory
*/
void cleanDuplicateDirectory(File srcDir, File destDir);
/**
* Copy the contents of the source directory to the destination directory.
*
* <p>
* This includes all subdirectories, their subdirectories, etc.
*
* @param sourceDir
* the source directory
* @param destDir
* the destination directory (which will be created if necessary)
* @param overwrite
* {@code true} if should overwrite files if already in the destination folder
*/
void copyDirectory(File sourceDir, File destDir, boolean overwrite);
/**
* Copy the contents of the source directory to the destination directory.
*
* <p>
* This includes all subdirectories, their subdirectories, etc.
*
* @param sourceDir
* the source directory
* @param destDir
* the destination directory (which will be created if necessary)
* @param overwrite
* {@code true} if should overwrite files if already in the destination folder
* @param fileCollector
* if not {@code null}, used to collect copied files
*/
void copyDirectory(File sourceDir, File destDir, boolean overwrite, FileCollector fileCollector);
/**
* Copy the contents of the source directory to the destination directory.
*
* <p>
* This includes all subdirectories, their subdirectories, etc.
*
* <p>
* Files must pass the file filter to be copied.
*
* @param sourceDir
* the source directory
* @param filter
* the file filter that determines which files get copied, can be {@code null} which passes everything
* @param destDir
* the destination directory (which will be created if necessary)
* @param overwrite
* {@code true} if should overwrite files if already in the destination folder
* @param fileCollector
* if not {@code null}, used to collect copied files
*/
void copyDirectory(File sourceDir, FileFilter filter, File destDir, boolean overwrite, FileCollector fileCollector);
/**
* Copy an input stream to an output file.
*
* <p>
* Input stream will be closed upon completion.
*
* @param source
* the source file to copy
* @param destination
* the destination file to copy to
*/
void copyFile(File source, File destination);
/**
* Copy an input stream to an output file.
*
* <p>
* Input stream will be closed upon completion.
*
* @param in
* the input strem being copied
* @param file
* the file where the input stream's contents will be copied
*
* @throws IOException
* io problem with operation
*/
void copyInputStream(InputStream in, File file) throws IOException;
/**
* Copy an input stream to an output stream.
*
* <p>
* Both streams will be closed upon completion.
*
* @param in
* the input stream
* @param out
* the output stream
*
* @throws IOException
* io problem with operation
*/
void copyInputStream(InputStream in, OutputStream out) throws IOException;
/**
* Copy an input stream to an output stream.
*
* @param in
* the input stream
* @param out
* the output stream
* @param closeOnCompletion
* {@code true} if the streams should be closed when the copy finishes.
*
* @throws IOException
* io problem with operation
*/
void copyStream(InputStream in, OutputStream out, boolean closeOnCompletion) throws IOException;
/**
* Copy the contents of a file to an output stream.
*
* <p>
* The output stream will not be closed.
*
* @param in
* the input stream
* @param out
* the output stream
* @param closeOnCompletion
* {@code true} if the streams should be closed on completion of the copy
*
* @throws IOException
* io problem with operation
*/
void copyFileToStream(File in, OutputStream out, boolean closeOnCompletion) throws IOException;
/**
* Read the contents of an input stream and return a string containing the contents.
*
* @param in
* the input stream to read
*
* @return a string containing the contents
*
* @throws IOException
* io problem with operation
*/
String inputStreamAsString(InputStream in) throws IOException;
/**
* Read all the available data from an input stream and return it as a string.
*
* @param in
* the input stream to read
*
* @return a string containing the contents, or {@code null} if input is {@code null}
*
* @throws IOException
* io problem with operation
*/
String readAvailableToString(InputStream in) throws IOException;
/**
* Atomically creates a new, empty file named by this abstract pathname if and only if a file with this name does not
* yet exist. The check for the existence of the file and the creation of the file if it does not exist are a single
* operation that is atomic with respect to all other filesystem activities that might affect the file.
*
* @param file
* the file to be created
*
* @return {@code true} if the named file does not exist and was successfully created; {@code false} if the named file
* already exists
*
* @throws IOException
* If an I/O error occurred
*/
boolean createNewFile(File file) throws IOException;
/**
* Delete a file.
*
* <p>
* If a directory, will recursively delete the directory and its contents.
*
* <p>
* If the file doesn't exist, nothing happens.
*
* @param file
* the file to be deleted
*/
void delete(File file);
/**
* Delete the contents of a directory.
*
* <p>
* Will recursively delete subdirectories.
*
* @param file
* the directory to be deleted
*/
void deleteDirectoryContents(File file);
/**
* Make sure a directory exists. If not, it will be created.
*
* @param dir
* the directory that should exist
*
* @throws SimpleInteractiveSpacesException
* if the result is not the existence of a valid directory
*/
void directoryExists(File dir) throws SimpleInteractiveSpacesException;
/**
* Make sure a directory exists. If not, it will be created.
*
* @param dir
* the directory that should exist
* @param message
* the message to use if the directory cannot be made
*
* @throws SimpleInteractiveSpacesException
* if the result is not the existence of a valid directory
*/
void directoryExists(File dir, String message) throws SimpleInteractiveSpacesException;
/**
* Returns an array of abstract pathnames denoting the files in the directory denoted by this abstract pathname.
*
* @param dir
* the directory whose contents are to be listed
*
* @return the the set of files found in the directory
*/
File[] listFiles(File dir);
/**
* Get an array of abstract pathnames denoting the files in the directory denoted by this abstract pathname which pass
* the file filter.
*
* @param dir
* the directory whose contents are to be listed
* @param fileFilter
* the file filter
*
* @return the the set of files found in the directory that pass the filter
*/
File[] listFiles(File dir, FileFilter fileFilter);
/**
* Get an array of abstract pathnames denoting the files in the directory denoted by this abstract pathname which pass
* the file name filter.
*
* @param dir
* the directory whose contents are to be listed
* @param fileFilter
* the file name filter
*
* @return the the set of files found in the directory that pass the filter
*/
File[] listFiles(File dir, FilenameFilter fileFilter);
/**
* Tests whether the file denoted by this abstract pathname is a directory.
*
* @param dir
* the directory that is to be tested
*
* @return {@code true} if and only if the file denoted by this abstract pathname exists and is a directory;
* {@code false} otherwise
*/
boolean isDirectory(File dir);
/**
* Tests whether the file denoted by this abstract pathname is a normal file. A file is normal if it is not a
* directory and, in addition, satisfies other system-dependent criteria. Any non-directory file created by a Java
* application is guaranteed to be a normal file.
*
* @param file
* the file that is to be tested
*
* @return {@code true} if and only if the file denoted by this abstract pathname exists and is a normal file;
* {@code false} otherwise
*/
boolean isFile(File file);
/**
* Tests whether the file or directory denoted by this abstract pathname exists.
*
* @param file
* the file/directory that is to be tested
*
* @return {@code true} if and only if the file or directory denoted by this abstract pathname exists; {@code false}
* otherwise
*/
boolean exists(File file);
/**
* Create a new file for a specified path.
*
* <p>
* This method takes canonical pathnames and corrects them for the underlying operation system.
*
* @param path
* the path
*
* @return a file for the path
*/
File newFile(String path);
/**
* Create a new file for a specified path.
*
* @param uri
* the {@code file:} based URI for the file
*
* @return a file for the uRI
*/
File newFile(URI uri);
/**
* Create a new file for a specified path relative to the parent file.
*
* <p>
* This method takes canonical pathnames and corrects them for the underlying operation system.
*
* @param parent
* the parent file
* @param subpath
* the path
*
* @return a file for the subpath
*/
File newFile(File parent, String subpath);
/**
* Create a new file for a specified path relative to the parent file. if the subpath is absolute, the returned file
* will be just the subpath.
*
* <p>
* This method takes canonical pathnames and corrects them for the underlying operation system.
*
* @param baseDir
* the parent file if the subpath is relative
* @param subpath
* the path
*
* @return a file for the subpath
*/
File resolveFile(File baseDir, String subpath);
/**
* Returns the absolute form of this abstract pathname.
*
* @param file
* the file/directory whose path is to be examined
*
* @return The absolute abstract pathname denoting the same file or directory as this abstract pathname
*/
File getAbsoluteFile(File file);
/**
* Returns the absolute pathname string of this abstract pathname.
*
* @param file
* the file/directory whose path is to be examined
*
* @return The absolute pathname string denoting the same file or directory as this abstract pathname
*/
String getAbsolutePath(File file);
/**
* Returns the name of the file or directory denoted by this abstract pathname. This is just the last name in the
* pathname's name sequence. If the pathname's name sequence is empty, then the empty string is returned.
*
* @param file
* the file/directory whose path is to be determined
*
* @return The name of the file or directory denoted by this abstract pathname, or the empty string if this pathname's
* name sequence is empty
*/
String getName(File file);
/**
* Converts this abstract pathname into a pathname string. The resulting string uses the default name-separator
* character to separate the names in the name sequence.
*
* @param file
* the file/directory whose path is to be determined
*
* @return The abstract pathname of the parent directory named by this abstract pathname, or {@code null} if this
* pathname does not name a parent
*/
String getPath(File file);
/**
* Returns the pathname string of this abstract pathname's parent, or {@code null} if this pathname does not name a
* parent directory.
*
* @param file
* the file/directory whose path is to be examined
*
* @return The pathname string of the parent directory named by this abstract pathname, or {@code null} if this
* pathname does not name a parent
*/
String getParent(File file);
/**
* Returns the abstract pathname of this abstract pathname's parent, or null if this pathname does not name a parent
* directory.
*
* @param file
* the file/directory whose path is to be examined
*
* @return The abstract pathname of the parent directory named by this abstract pathname, or {@code null} if this
* pathname does not name a parent
*/
File getParentFile(File file);
/**
* Creates the directory named by this abstract pathname.
*
* @param dir
* the directory that is going to be created
*
* @return {@code true} if and only if the directory was created; {@code false} otherwise
*/
boolean mkdir(File dir);
/**
* Creates the directory named by this abstract pathname, including any necessary but nonexistent parent directories.
*
* @param dir
* the directory that is going to be created
*
* @return {@code true} if and only if the directory was created, along with all necessary parent directories;
* {@code false} otherwise
*/
boolean mkdirs(File dir);
/**
* Rename a file/directory.
*
* @param from
* source file to rename
* @param to
* new target name
*
* @return {@code true} if rename was successful
*/
boolean rename(File from, File to);
/**
* Create a unique temporary file in the given directory, using default prefix and suffix.
*
* @param baseDir
* directory in which to create file
*
* @return unique file
*/
File createTempFile(File baseDir);
/**
* Create a unique temporary file in the given directory.
*
* @param baseDir
* directory in which to create file
* @param prefix
* temp file prefix to use
* @param suffix
* temp file suffix to use
*
* @return unique file
*/
File createTempFile(File baseDir, String prefix, String suffix);
/**
* Create a unique temporary file somewhere in the filesystem.
*
* @param prefix
* temp file prefix to use
* @param suffix
* temp file suffix to use
*
* @return unique file
*/
File createTempFile(String prefix, String suffix);
/**
* Create a unique temporary directory in the given directory, using default prefix and suffix.
*
* @param baseDir
* directory in which to create directory
*
* @return unique directory
*/
File createTempDirectory(File baseDir);
/**
* Create a unique temporary directory in the given directory.
*
* @param baseDir
* directory in which to create directory
* @param prefix
* temp file prefix to use
*
* @return unique directory
*/
File createTempDirectory(File baseDir, String prefix);
/**
* Get a file as a string.
*
* @param file
* the file to be read
*
* @return the contents of the file
*/
String readFile(File file);
/**
* Write a string into a file.
*
* <p>
* The supplied string will be the only contents of the file.
*
* @param file
* the file to be written
* @param contents
* the contents to be written into the file
*/
void writeFile(File file, String contents);
/**
* Close the closeable. If asked to throw any exceptions from the close, the method will wrap it in an
* {@link InteractiveSpacesException}.
*
* @param closeable
* the item to close, can be {@code null}
* @param throwException
* {@code true} if any exceptions thrown during closing should be rethrown
*
* @throws InteractiveSpacesException
* an exception happened during close
*/
void close(Closeable closeable, boolean throwException) throws InteractiveSpacesException;
/**
* Is the candidate parent the parent of the file?
*
* <p>
* The parent relationship is a strict parent. {@code /foo/bar} is not considered a parent for {@code /foo/bart/spam}
* and {@code /foo/bar} is not a parent for {@code /foo/bar}.
*
* @param candidateParent
* the possible parent
* @param file
* the file that may have the candidate parent as a parent
*
* @return {@code true} if the candidate is a parent of the file
*/
boolean isParent(File candidateParent, File file);
/**
* Set the file as executable by the owner.
*
* @param file
* the file
* @param executable
* {@code true} if the file should be executable
*
* @return {@code true} if successful
*/
boolean setExecutable(File file, boolean executable);
/**
* Collect all files that pass the file filer.
*
* @param baseDir
* the base directory to start in
* @param filter
* the filter that decides which files
* @param recurse
* {@code true} if should recurse through directories
*
* @return the collection of files that pass the filter
*/
List<File> collectFiles(File baseDir, FileFilter filter, boolean recurse);
/**
* Create a new file input stream for the requested file.
*
* @param file
* the file
*
* @return the new stream
*/
FileInputStream newFileInputStream(File file);
/**
* Create a new file output stream for the requested file.
*
* @param file
* the file
*
* @return the new stream
*/
FileOutputStream newFileOutputStream(File file);
}