global.namespace.archive.io.bios.DirectoryStore Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) 2013-2018 Schlichtherle IT Services.
* All rights reserved. Use is subject to license terms.
*/
package global.namespace.archive.io.bios;
import global.namespace.archive.io.api.*;
import global.namespace.fun.io.api.Socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.Optional;
import static global.namespace.fun.io.bios.BIOS.copy;
import static java.nio.file.Files.*;
import static java.nio.file.Paths.get;
import static java.util.Optional.empty;
import static java.util.Optional.of;
/**
* Provides access to directories as if they were archive files.
* This is handy for testing purposes or if you want to diff/patch two directories.
*
* @author Christian Schlichtherle
*/
final class DirectoryStore implements ArchiveFileStore {
private final Path directory;
DirectoryStore(final Path directory) { this.directory = directory; }
@Override
public Socket> input() {
return () -> new ArchiveFileInput() {
@Override
public Iterator> iterator() {
try {
return Files
.walk(directory)
.filter(p -> !p.equals(directory))
.map(path -> pathSource(directory.relativize(path).toString()))
.iterator();
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
public Optional> source(final String name) {
final Path path = resolve(name);
return exists(path) ? of(pathSource(name)) : empty();
}
public void close() { }
};
}
@Override
public Socket> output() {
return () -> new ArchiveFileOutput() {
public boolean isJar() { return false; }
public ArchiveEntrySink sink(String name) { return pathSink(name); }
public void close() { }
};
}
private ArchiveEntrySource pathSource(String relativePath) {
return new ArchiveEntrySource() {
public String name() { return relativePath; }
public boolean isDirectory() { return Files.isDirectory(resolvedPath()); }
public Path entry() { return get(relativePath); }
public Socket input() { return () -> newInputStream(resolvedPath()); }
public void copyTo(ArchiveEntrySink> sink) throws Exception { copy(this, sink); }
Path resolvedPath() { return resolve(relativePath); }
};
}
private ArchiveEntrySink pathSink(String relativePath) {
return new ArchiveEntrySink() {
public String name() { return relativePath; }
public boolean isDirectory() { return Files.isDirectory(resolvedPath()); }
public Path entry() { return get(name()); }
public Socket output() {
return () -> {
final Path path = resolvedPath();
final Path parent = path.getParent();
if (null != parent) {
createDirectories(parent);
}
return newOutputStream(path);
};
}
Path resolvedPath() { return resolve(relativePath); }
};
}
private Path resolve(String relativePath) { return directory.resolve(relativePath); }
}