package net.sf.cotta;
import net.sf.cotta.io.OutputMode;
import net.sf.cotta.system.FileSystem;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.nio.channels.FileChannel;
/**
* A file system that delegates all file operations to a controller
*
* @see net.sf.cotta.ControlledFileSystem.Controller
*/
public class ControlledFileSystem implements FileSystem {
private FileSystem fileSystem;
protected Controller controller;
public ControlledFileSystem(FileSystem fileSystem, Controller controller) {
this.controller = controller;
this.fileSystem = fileSystem;
}
public boolean fileExists(TPath path) {
readControl(path);
return fileSystem.fileExists(path);
}
public void createFile(TPath path) throws TIoException {
controller.writeOperationControl(path);
fileSystem.createFile(path);
}
public void deleteFile(TPath path) throws TIoException {
controller.writeOperationControl(path);
fileSystem.deleteFile(path);
}
public boolean dirExists(TPath path) {
readControl(path);
return fileSystem.dirExists(path);
}
public void createDir(TPath path) throws TIoException {
controller.writeOperationControl(path);
fileSystem.createDir(path);
}
public PathContent list(TPath path) throws TIoException {
readControl(path);
return fileSystem.list(path);
}
public InputStream createInputStream(TPath path) throws TIoException {
controller.readOperationControl(path);
return fileSystem.createInputStream(path);
}
public FileChannel createInputChannel(TPath path) throws TIoException {
controller.readOperationControl(path);
return fileSystem.createInputChannel(path);
}
public OutputStream createOutputStream(TPath path, OutputMode mode) throws TIoException {
controller.writeOperationControl(path);
return fileSystem.createOutputStream(path, mode);
}
public FileChannel createOutputChannel(TPath path, OutputStream outputStream) throws TIoException {
controller.writeOperationControl(path);
return fileSystem.createOutputChannel(path, outputStream);
}
public void deleteDirectory(TPath path) throws TIoException {
controller.writeOperationControl(path);
fileSystem.deleteDirectory(path);
}
public void moveFile(TPath source, TPath destination) throws TIoException {
controller.writeOperationControl(source);
controller.writeOperationControl(destination);
fileSystem.moveFile(source, destination);
}
public void moveDirectory(TPath source, TPath destination) throws TIoException {
controller.writeOperationControl(source);
controller.writeOperationControl(destination);
fileSystem.moveFile(source, destination);
}
public String pathString(TPath path) {
return fileSystem.pathString(path);
}
public long fileLength(TPath path) {
readControl(path);
return fileSystem.fileLength(path);
}
public long fileLastModified(TPath path) {
readControl(path);
return fileSystem.fileLastModified(path);
}
public int compare(TPath path1, TPath path2) {
readControl(path1);
readControl(path2);
return fileSystem.compare(path1, path2);
}
public boolean equals(TPath path1, TPath path2) {
readControl(path1);
readControl(path2);
return fileSystem.equals(path1, path2);
}
public int hashCode(TPath path) {
readControl(path);
return fileSystem.hashCode(path);
}
public URI toUri(TPath path) {
return fileSystem.toUri(path);
}
private void readControl(TPath path) {
try {
controller.readOperationControl(path);
} catch (TIoException e) {
throw new TIoRuntimeException(e);
}
}
public File toJavaFile(TPath path) {
return fileSystem.toJavaFile(path);
}
public String toCanonicalPath(TPath path) {
return fileSystem.toCanonicalPath(path);
}
public static FileSystem pathControlledFileSystem(FileSystem fileSystem, final TPath pathAllowed) {
return new ControlledFileSystem(fileSystem, new PermissionController() {
public boolean writeAllowed(TPath path) {
return path.isChildOf(pathAllowed) || path.equals(pathAllowed);
}
public StringBuffer describe(StringBuffer buffer) {
return buffer.append("only files under <").append(pathAllowed.toPathString()).append(">is allowed");
}
});
}
public static FileSystem readOnlyFileSystem(FileSystem fileSystem) {
return new ControlledFileSystem(fileSystem, new PermissionController() {
public boolean writeAllowed(TPath path) {
return false;
}
public StringBuffer describe(StringBuffer buffer) {
return buffer.append("read only file system");
}
});
}
public static abstract class PermissionController implements Controller {
public abstract boolean writeAllowed(TPath path);
public void writeOperationControl(TPath path) throws PermissionDeniedException {
if (!writeAllowed(path)) {
StringBuffer buffer = new StringBuffer("permission denied:<").append(path.toPathString()).append(">");
throw new PermissionDeniedException(path, describe(buffer).toString());
}
}
public void readOperationControl(TPath path) {
}
public abstract StringBuffer describe(StringBuffer buffer);
}
public static interface Controller {
public void writeOperationControl(TPath path) throws TIoException;
public void readOperationControl(TPath path) throws TIoException;
}
}