package com.googlecode.totallylazy; import com.googlecode.totallylazy.functions.Block; import com.googlecode.totallylazy.functions.Function1; import com.googlecode.totallylazy.predicates.LogicalPredicate; import com.googlecode.totallylazy.predicates.Predicate; import com.googlecode.totallylazy.predicates.Predicates; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.Set; import static com.googlecode.totallylazy.functions.Callables.doThen; import static com.googlecode.totallylazy.functions.Callables.returns; import static com.googlecode.totallylazy.Closeables.using; import static com.googlecode.totallylazy.Option.none; import static com.googlecode.totallylazy.Option.some; import static com.googlecode.totallylazy.predicates.Predicates.is; import static com.googlecode.totallylazy.predicates.Predicates.where; import static com.googlecode.totallylazy.Sequences.sequence; import static com.googlecode.totallylazy.time.Dates.date; import static java.lang.String.format; import static java.lang.System.getProperty; import static java.util.UUID.randomUUID; public class Files { public static final File TEMP_DIR = new File(getProperty("java.io.tmpdir")); public static String relativePath(File folder, File file) { return folder.toURI().relativize(file.toURI()).getPath(); } public static LogicalPredicate<File> isFile() { return new LogicalPredicate<File>() { public boolean matches(File file) { return file.isFile(); } }; } public static LogicalPredicate<File> hasSuffix(final String suffix) { return new LogicalPredicate<File>() { public boolean matches(File file) { return file.getName().endsWith("." + suffix); } }; } public static LogicalPredicate<File> isDirectory() { return new LogicalPredicate<File>() { public boolean matches(File file) { return file.isDirectory(); } }; } public static LogicalPredicate<File> hasName(final String name) { return where(name(), is(name)); } public static Function1<File, String> name() { return file -> file.getName(); } public static Function1<File, Sequence<File>> files() { return file -> files(file); } public static Function1<File, String> path() { return file -> file.getPath(); } public static Function1<File, File> parent() { return file -> file.getParentFile(); } public static File temporaryDirectory() { return TEMP_DIR; } public static File temporaryDirectory(String name) { return directory(TEMP_DIR, name); } public static File emptyVMDirectory(String name) { return emptyTemporaryDirectory(format("%s-%s", name, getProperty("java.version"))); } public static File emptyTemporaryDirectory(String name) { File directory = directory(TEMP_DIR, name); deleteFiles(directory); return directory; } public static boolean delete(File file) { return deleteFiles(file) && file.delete(); } public static boolean deleteFiles(File file) { return recursiveFiles(file).map(deleteFile()).forAll(is(true)); } public static Function1<File, Boolean> deleteFile() { return file -> file.delete(); } public static Function1<File, Boolean> delete() { return Files::delete; } public static File temporaryFile() { return temporaryFile(TEMP_DIR); } public static File temporaryFile(File directory) { return temporaryFile(directory, randomFilename()); } public static File temporaryFile(File directory, String name) { File file = new File(directory, name); file.deleteOnExit(); create(file); return file; } private static void create(File file) { try { file.getParentFile().mkdirs(); file.createNewFile(); } catch (IOException e) { throw LazyException.lazyException(e); } } public static File workingDirectory() { return new File(getProperty("user.dir")); } public static String randomFilename() { return randomUUID().toString(); } public static Sequence<File> files(File directory) { return sequence(directory.listFiles()); } public static Predicate<File> containsFile(final String fileName) { return containsFile(hasName(fileName)); } public static LogicalPredicate<File> containsFile(final Predicate<? super File> predicate) { return where(Files.files(), Predicates.<File>exists(predicate)); } public static Sequence<File> ancestorsAndSelf(File file) { if (file.getParentFile() == null) return sequence(file); return sequence(file).join(ancestorsAndSelf(file.getParentFile())); } public static Sequence<File> ancestors(File file) { if (file.getParentFile() == null) return Sequences.empty(); return sequence(file.getParentFile()).join(ancestors(file.getParentFile())); } public static Sequence<File> recursiveFiles(final File directory) { return files(directory).flatMap(recursiveFiles()); } public static Function1<File, Iterable<File>> recursiveFiles() { return file -> file.isDirectory() ? recursiveFiles(file).append(file) : sequence(file); } public static Sequence<File> recursiveFilesDirectoriesFirst(final File directory) { return files(directory).flatMap(recursiveFilesDirectoriesFirst()); } public static Function1<File, Iterable<File>> recursiveFilesDirectoriesFirst() { return file -> file.isDirectory() ? recursiveFilesDirectoriesFirst(file).cons(file) : sequence(file); } public static File write(byte[] bytes, File file) { return write(bytes, file, false); } public static File append(byte[] bytes, File file) { return write(bytes, file, true); } public static File write(byte[] bytes, File file, boolean append) { try { return using(new FileOutputStream(file, append), doThen(Runnables.write(bytes), returns(file))); } catch (FileNotFoundException e) { throw LazyException.lazyException(e); } } public static File deleteOnExit(File directory) { delete.add(directory); return directory; } private static Set<File> delete = Sets.concurrentSet(); static { Runtime.getRuntime().addShutdownHook(new Thread(() -> { for (File directory : delete) { Files.delete(directory); } })); } public static Block<InputStream> write(final File output) { return inputStream -> Streams.copyAndClose(inputStream, new FileOutputStream(output)); } public static Function1<String, File> asFile() { return name -> new File(name); } public static File directory(File parent, String name) { File child = new File(parent, name); child.mkdirs(); return child; } public static File file(File parent, String name) { File file = new File(parent, name); if (file.isDirectory()) { throw new IllegalArgumentException(format("%s is a isDirectory", file)); } create(file); return file; } public static Option<File> fileOption(File parent, String name) { final File file = new File(parent, name); return file.exists() ? some(file) : none(File.class); } public static Function1<File, Date> lastModified() { return file -> date(file.lastModified()); } public static File randomFile() { return file(temporaryDirectory(), randomFilename()); } }