package org.smoothbuild.io.fs.mem; import static org.smoothbuild.io.fs.base.AssertPath.assertPathExists; import static org.smoothbuild.io.fs.base.AssertPath.assertPathIsUnused; 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.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Iterator; import java.util.List; 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 org.smoothbuild.util.Streams; /** * In memory implementation of FileSystem. */ public class MemoryFileSystem implements FileSystem { private final MemoryDir root = new MemoryDir(null, Path.root()); public PathState pathState(Path path) { MemoryElement element = findElement(path); if (element == null) { return NOTHING; } if (element.isDir()) { return DIR; } return FILE; } public List<Path> files(Path dir) { return getDir(dir).childNames(); } 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."); } try { Streams.copy(openInputStream(source), openOutputStream(target)); } catch (IOException e) { throw new RuntimeException(e); } delete(source); } public void delete(Path path) { if (path.isRoot()) { root.removeAllChildren(); return; } MemoryElement element = findElement(path); if (element == null) { return; } element.parent().removeChild(element); } public InputStream openInputStream(Path path) { return getFile(path).openInputStream(); } public OutputStream openOutputStream(Path path) { if (pathState(path) == DIR) { throw new FileSystemException("Cannot use " + path + " path. It is already taken by dir."); } MemoryDir dir = createDirImpl(path.parent()); Path name = path.lastPart(); if (dir.hasChild(name)) { return dir.child(name).openOutputStream(); } else { MemoryFile child = new MemoryFile(dir, name); dir.addChild(child); return child.openOutputStream(); } } public void createLink(Path link, Path target) { assertPathExists(this, target); assertPathIsUnused(this, link); Path name = link.lastPart(); MemoryDir dir = createDirImpl(link.parent()); MemoryElement targetElement = findElement(target); dir.addChild(new MemoryLink(dir, name, targetElement)); } public void createDir(Path path) { createDirImpl(path); } private MemoryDir createDirImpl(Path dir) { Iterator<Path> it = dir.parts().iterator(); MemoryDir currentDir = root; while (it.hasNext()) { Path name = it.next(); if (currentDir.hasChild(name)) { MemoryElement child = currentDir.child(name); if (child.isDir()) { currentDir = (MemoryDir) child; } else { throw new FileSystemException("Cannot use " + dir + " path. It is already taken by file."); } } else { MemoryDir newDir = new MemoryDir(currentDir, name); currentDir.addChild(newDir); currentDir = newDir; } } return currentDir; } private MemoryElement getFile(Path path) { MemoryElement found = findElement(path); if (found != null && found.isFile()) { return found; } else { throw new FileSystemException("File " + path + " doesn't exist."); } } private MemoryElement getDir(Path path) { MemoryElement found = findElement(path); if (found != null && found.isDir()) { return found; } else { throw new FileSystemException("Dir " + path + " doesn't exists."); } } private MemoryElement findElement(Path path) { Iterator<Path> it = path.parts().iterator(); MemoryElement current = root; while (it.hasNext()) { Path name = it.next(); if (current.hasChild(name)) { current = current.child(name); } else { return null; } } return current; } }