package org.smoothbuild.io.fs.disk; import static java.nio.file.StandardCopyOption.ATOMIC_MOVE; import static java.util.Collections.nCopies; import static java.util.stream.Collectors.joining; import static org.smoothbuild.io.fs.base.AssertPath.assertPathExists; import static org.smoothbuild.io.fs.base.AssertPath.assertPathIsDir; import static org.smoothbuild.io.fs.base.AssertPath.assertPathIsFile; import static org.smoothbuild.io.fs.base.AssertPath.assertPathIsUnused; import static org.smoothbuild.io.fs.base.Path.path; import static org.smoothbuild.io.fs.base.PathState.DIR; import static org.smoothbuild.io.fs.base.PathState.FILE; import static org.smoothbuild.io.fs.base.PathState.NOTHING; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.DirectoryStream; import java.nio.file.FileAlreadyExistsException; import java.nio.file.Files; import java.nio.file.Paths; import org.smoothbuild.io.fs.base.FileSystem; import org.smoothbuild.io.fs.base.FileSystemException; import org.smoothbuild.io.fs.base.Path; import org.smoothbuild.io.fs.base.PathState; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList.Builder; public class DiskFileSystem implements FileSystem { private final java.nio.file.Path rootDir; public DiskFileSystem(Path path) { this.rootDir = path.toJPath(); } DiskFileSystem(java.nio.file.Path path) { this.rootDir = path; } public PathState pathState(Path path) { java.nio.file.Path jdkPath = jdkPath(path); if (!Files.exists(jdkPath)) { return NOTHING; } if (Files.isDirectory(jdkPath)) { return DIR; } return FILE; } public Iterable<Path> files(Path dir) { assertPathIsDir(this, dir); try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(jdkPath( dir))) { Builder<Path> builder = ImmutableList.builder(); for (java.nio.file.Path path : stream) { builder.add(path(path.getFileName().toString())); } return builder.build(); } catch (IOException e) { throw new FileSystemException(e); } } public void move(Path source, Path target) { if (pathState(source) == NOTHING) { throw new FileSystemException("Cannot move " + source + ". It doesn't exist."); } if (pathState(source) == DIR) { throw new FileSystemException("Cannot move " + source + ". It is directory."); } if (pathState(target) == DIR) { throw new FileSystemException("Cannot move to " + target + ". It is directory."); } Path targetParent = target.parent(); if (pathState(targetParent) == NOTHING) { createDir(targetParent); } try { Files.move(jdkPath(source), jdkPath(target), ATOMIC_MOVE); } catch (IOException e) { throw new FileSystemException(e); } } public InputStream openInputStream(Path path) { assertPathIsFile(this, path); try { return new BufferedInputStream(Files.newInputStream(jdkPath(path))); } catch (IOException e) { throw new FileSystemException(e); } } public OutputStream openOutputStream(Path path) { if (pathState(path) == DIR) { throw new FileSystemException("Cannot use " + path + " path. It is already taken by dir."); } createDir(path.parent()); try { return new BufferedOutputStream(java.nio.file.Files.newOutputStream(jdkPath(path))); } catch (IOException e) { throw new FileSystemException(e); } } public void createDir(Path path) { try { Files.createDirectories(jdkPath(path)); } catch (FileAlreadyExistsException e) { throw new FileSystemException("Cannot use " + path + " path. It is already taken by file."); } catch (IOException e) { throw new FileSystemException(e); } } public void delete(Path path) { if (pathState(path) == NOTHING) { return; } try { RecursiveDeleter.deleteRecursively(jdkPath(path)); } catch (IOException e) { throw new FileSystemException(e); } } public void createLink(Path link, Path target) { assertPathExists(this, target); assertPathIsUnused(this, link); createDir(link.parent()); try { String escape = escapeString(link.parts().size() - 1); java.nio.file.Path targetJdkPath = Paths.get(escape, target.value()); Files.createSymbolicLink(jdkPath(link), targetJdkPath); } catch (IOException e) { throw new FileSystemException(e); } } private static String escapeString(int length) { return nCopies(length, "..").stream().collect(joining("/")); } private java.nio.file.Path jdkPath(Path path) { if (path.isRoot()) { return rootDir; } else { return rootDir.resolve(path.value()); } } }