Module support #11
@ -1,6 +1,8 @@
|
||||
package me.topchetoeu.jscript.filesystem;
|
||||
|
||||
public interface Filesystem {
|
||||
String cwd(String cwd, String path);
|
||||
String normalize(String path);
|
||||
File open(String path, Mode mode) throws FilesystemException;
|
||||
void create(String path, EntryType type) throws FilesystemException;
|
||||
FileStat stat(String path) throws FilesystemException;
|
||||
|
@ -5,6 +5,7 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import me.topchetoeu.jscript.Buffer;
|
||||
import me.topchetoeu.jscript.Filename;
|
||||
import me.topchetoeu.jscript.filesystem.FilesystemException.FSCode;
|
||||
|
||||
public class MemoryFilesystem implements Filesystem {
|
||||
@ -12,66 +13,76 @@ public class MemoryFilesystem implements Filesystem {
|
||||
private HashMap<Path, Buffer> files = new HashMap<>();
|
||||
private HashSet<Path> folders = new HashSet<>();
|
||||
|
||||
private Path getPath(String name) {
|
||||
return Path.of("/" + name.replace("\\", "/")).normalize();
|
||||
private Path realPath(String path) {
|
||||
return Filename.normalize(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(String path, EntryType type) {
|
||||
var _path = getPath(path);
|
||||
public String normalize(String path) {
|
||||
return Paths.normalize(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String cwd(String cwd, String path) {
|
||||
return Paths.cwd(cwd, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(String _path, EntryType type) {
|
||||
var path = realPath(_path);
|
||||
|
||||
switch (type) {
|
||||
case FILE:
|
||||
if (!folders.contains(_path.getParent())) throw new FilesystemException(path, FSCode.DOESNT_EXIST);
|
||||
if (folders.contains(_path) || files.containsKey(_path)) throw new FilesystemException(path, FSCode.ALREADY_EXISTS);
|
||||
if (folders.contains(_path)) throw new FilesystemException(path, FSCode.ALREADY_EXISTS);
|
||||
files.put(_path, new Buffer());
|
||||
if (!folders.contains(path.getParent())) throw new FilesystemException(path.toString(), FSCode.DOESNT_EXIST);
|
||||
if (folders.contains(path) || files.containsKey(path)) throw new FilesystemException(path.toString(), FSCode.ALREADY_EXISTS);
|
||||
if (folders.contains(path)) throw new FilesystemException(path.toString(), FSCode.ALREADY_EXISTS);
|
||||
files.put(path, new Buffer());
|
||||
break;
|
||||
case FOLDER:
|
||||
if (!folders.contains(_path.getParent())) throw new FilesystemException(path, FSCode.DOESNT_EXIST);
|
||||
if (folders.contains(_path) || files.containsKey(_path)) throw new FilesystemException(path, FSCode.ALREADY_EXISTS);
|
||||
folders.add(_path);
|
||||
if (!folders.contains(path.getParent())) throw new FilesystemException(_path, FSCode.DOESNT_EXIST);
|
||||
if (folders.contains(path) || files.containsKey(path)) throw new FilesystemException(path.toString(), FSCode.ALREADY_EXISTS);
|
||||
folders.add(path);
|
||||
break;
|
||||
default:
|
||||
case NONE:
|
||||
if (!folders.remove(_path) && files.remove(_path) == null) throw new FilesystemException(path, FSCode.DOESNT_EXIST);
|
||||
if (!folders.remove(path) && files.remove(path) == null) throw new FilesystemException(path.toString(), FSCode.DOESNT_EXIST);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public File open(String path, Mode perms) {
|
||||
var _path = getPath(path);
|
||||
var pcount = _path.getNameCount();
|
||||
public File open(String _path, Mode perms) {
|
||||
var path = realPath(_path);
|
||||
var pcount = path.getNameCount();
|
||||
|
||||
if (files.containsKey(_path)) return new MemoryFile(path, files.get(_path), perms);
|
||||
else if (folders.contains(_path)) {
|
||||
if (files.containsKey(path)) return new MemoryFile(path.toString(), files.get(path), perms);
|
||||
else if (folders.contains(path)) {
|
||||
var res = new StringBuilder();
|
||||
for (var folder : folders) {
|
||||
if (pcount + 1 != folder.getNameCount()) continue;
|
||||
if (!folder.startsWith(_path)) continue;
|
||||
if (!folder.startsWith(path)) continue;
|
||||
res.append(folder.toFile().getName()).append('\n');
|
||||
}
|
||||
for (var file : files.keySet()) {
|
||||
if (pcount + 1 != file.getNameCount()) continue;
|
||||
if (!file.startsWith(_path)) continue;
|
||||
if (!file.startsWith(path)) continue;
|
||||
res.append(file.toFile().getName()).append('\n');
|
||||
}
|
||||
return new MemoryFile(path, new Buffer(res.toString().getBytes()), perms.intersect(Mode.READ));
|
||||
return new MemoryFile(path.toString(), new Buffer(res.toString().getBytes()), perms.intersect(Mode.READ));
|
||||
}
|
||||
else throw new FilesystemException(path, FSCode.DOESNT_EXIST);
|
||||
else throw new FilesystemException(path.toString(), FSCode.DOESNT_EXIST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileStat stat(String path) {
|
||||
var _path = getPath(path);
|
||||
public FileStat stat(String _path) {
|
||||
var path = realPath(_path);
|
||||
|
||||
if (files.containsKey(_path)) return new FileStat(mode, EntryType.FILE);
|
||||
else if (folders.contains(_path)) return new FileStat(mode, EntryType.FOLDER);
|
||||
else throw new FilesystemException(path, FSCode.DOESNT_EXIST);
|
||||
if (files.containsKey(path)) return new FileStat(mode, EntryType.FILE);
|
||||
else if (folders.contains(path)) return new FileStat(mode, EntryType.FOLDER);
|
||||
else return new FileStat(Mode.NONE, EntryType.NONE);
|
||||
}
|
||||
|
||||
public MemoryFilesystem put(String path, byte[] data) {
|
||||
var _path = getPath(path);
|
||||
var _path = realPath(path);
|
||||
var _curr = "/";
|
||||
|
||||
for (var seg : _path) {
|
||||
|
51
src/me/topchetoeu/jscript/filesystem/Paths.java
Normal file
51
src/me/topchetoeu/jscript/filesystem/Paths.java
Normal file
@ -0,0 +1,51 @@
|
||||
package me.topchetoeu.jscript.filesystem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Paths {
|
||||
public static String normalize(String path) {
|
||||
var parts = path.split("[\\\\/]");
|
||||
var res = new ArrayList<String>();
|
||||
|
||||
for (var part : parts) {
|
||||
if (part.equals("...")) res.clear();
|
||||
else if (part.equals("..")) {
|
||||
if (res.size() > 0) res.remove(res.size() - 1);
|
||||
}
|
||||
else if (!part.equals(".")) res.add(part);
|
||||
}
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
for (var el : res) sb.append("/").append(el);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String chroot(String root, String path) {
|
||||
return normalize(root) + normalize(path);
|
||||
}
|
||||
|
||||
public static String cwd(String cwd, String path) {
|
||||
return normalize(cwd + "/" + path);
|
||||
}
|
||||
|
||||
public static String filename(String path) {
|
||||
var i = path.lastIndexOf('/');
|
||||
if (i < 0) i = path.lastIndexOf('\\');
|
||||
|
||||
if (i < 0) return path;
|
||||
else return path.substring(i + 1);
|
||||
}
|
||||
|
||||
public static String extension(String path) {
|
||||
var i = path.lastIndexOf('.');
|
||||
|
||||
if (i < 0) return "";
|
||||
else return path.substring(i + 1);
|
||||
}
|
||||
|
||||
public static String dir(String path) {
|
||||
return normalize(path + "/..");
|
||||
}
|
||||
}
|
@ -1,76 +1,92 @@
|
||||
package me.topchetoeu.jscript.filesystem;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import me.topchetoeu.jscript.filesystem.FilesystemException.FSCode;
|
||||
|
||||
public class PhysicalFilesystem implements Filesystem {
|
||||
public final Path root;
|
||||
|
||||
private Path getPath(String name) {
|
||||
var absolutized = Path.of("/" + name.replace("\\", "/")).normalize().toString();
|
||||
var res = Path.of(root.toString() + absolutized).normalize();
|
||||
return res;
|
||||
}
|
||||
public final String root;
|
||||
|
||||
private void checkMode(Path path, Mode mode) {
|
||||
if (!path.startsWith(root)) throw new FilesystemException(path.toString(), FSCode.NO_PERMISSIONS_R);
|
||||
if (mode.readable && !path.toFile().canRead()) throw new FilesystemException(path.toString(), FSCode.NO_PERMISSIONS_R);
|
||||
if (mode.writable && !path.toFile().canWrite()) throw new FilesystemException(path.toString(), FSCode.NO_PERMISSIONS_RW);
|
||||
var stat = stat(path.toString());
|
||||
if (mode.readable && !stat.mode.readable) throw new FilesystemException(path.toString(), FSCode.NO_PERMISSIONS_R);
|
||||
if (mode.writable && !stat.mode.writable) throw new FilesystemException(path.toString(), FSCode.NO_PERMISSIONS_RW);
|
||||
}
|
||||
|
||||
private Path realPath(String path) {
|
||||
return Path.of(Paths.chroot(root, path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public File open(String path, Mode perms) {
|
||||
var _path = getPath(path);
|
||||
var f = _path.toFile();
|
||||
|
||||
checkMode(_path, perms);
|
||||
|
||||
|
||||
if (f.isDirectory()) return MemoryFile.fromFileList(path, f.listFiles());
|
||||
else try { return new PhysicalFile(path, perms); }
|
||||
catch (FileNotFoundException e) { throw new FilesystemException(_path.toString(), FSCode.DOESNT_EXIST); }
|
||||
public String normalize(String path) {
|
||||
return Paths.normalize(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(String path, EntryType type) {
|
||||
var _path = getPath(path);
|
||||
var f = _path.toFile();
|
||||
public String cwd(String cwd, String path) {
|
||||
return Paths.cwd(cwd, path);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case FILE:
|
||||
try {
|
||||
if (!f.createNewFile()) throw new FilesystemException(_path.toString(), FSCode.ALREADY_EXISTS);
|
||||
else break;
|
||||
}
|
||||
catch (IOException e) { throw new FilesystemException(_path.toString(), FSCode.NO_PERMISSIONS_RW); }
|
||||
case FOLDER:
|
||||
if (!f.mkdir()) throw new FilesystemException(_path.toString(), FSCode.ALREADY_EXISTS);
|
||||
else break;
|
||||
case NONE:
|
||||
default:
|
||||
if (!f.delete()) throw new FilesystemException(_path.toString(), FSCode.DOESNT_EXIST);
|
||||
else break;
|
||||
@Override
|
||||
public File open(String _path, Mode perms) {
|
||||
var path = realPath(_path);
|
||||
|
||||
checkMode(path, perms);
|
||||
|
||||
try {
|
||||
if (Files.isDirectory(path)) return new ListFile(path);
|
||||
else return new PhysicalFile(path.toString(), perms);
|
||||
}
|
||||
catch (IOException e) { throw new FilesystemException(path.toString(), FSCode.DOESNT_EXIST); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileStat stat(String path) {
|
||||
var _path = getPath(path);
|
||||
var f = _path.toFile();
|
||||
public void create(String _path, EntryType type) {
|
||||
var path = realPath(_path);
|
||||
|
||||
if (!f.exists()) throw new FilesystemException(_path.toString(), FSCode.DOESNT_EXIST);
|
||||
checkMode(_path, Mode.READ);
|
||||
if (type == EntryType.NONE != Files.exists(path)) throw new FilesystemException(path.toString(), FSCode.ALREADY_EXISTS);
|
||||
|
||||
try {
|
||||
switch (type) {
|
||||
case FILE:
|
||||
Files.createFile(path);
|
||||
break;
|
||||
case FOLDER:
|
||||
Files.createDirectories(path);
|
||||
break;
|
||||
case NONE:
|
||||
default:
|
||||
Files.delete(path);
|
||||
}
|
||||
}
|
||||
catch (IOException e) { throw new FilesystemException(path.toString(), FSCode.NO_PERMISSIONS_RW); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileStat stat(String _path) {
|
||||
var path = realPath(_path);
|
||||
|
||||
if (!Files.exists(path)) return new FileStat(Mode.NONE, EntryType.NONE);
|
||||
|
||||
var perms = Mode.NONE;
|
||||
|
||||
if (Files.isReadable(path)) {
|
||||
if (Files.isWritable(path)) perms = Mode.READ_WRITE;
|
||||
else perms = Mode.READ;
|
||||
}
|
||||
|
||||
if (perms == Mode.NONE) return new FileStat(Mode.NONE, EntryType.NONE);
|
||||
|
||||
return new FileStat(
|
||||
f.canWrite() ? Mode.READ_WRITE : Mode.READ,
|
||||
f.isFile() ? EntryType.FILE : EntryType.FOLDER
|
||||
perms,
|
||||
Files.isDirectory(path) ? EntryType.FOLDER : EntryType.FILE
|
||||
);
|
||||
}
|
||||
|
||||
public PhysicalFilesystem(Path root) {
|
||||
this.root = root.toAbsolutePath().normalize();
|
||||
public PhysicalFilesystem(String root) {
|
||||
this.root = Paths.normalize(Path.of(root).toAbsolutePath().toString());
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,18 @@ public class RootFilesystem implements Filesystem {
|
||||
if (mode.writable && perms != null && !canWrite(_path)) throw new FilesystemException(_path, FSCode.NO_PERMISSIONS_RW);
|
||||
}
|
||||
|
||||
@Override public String normalize(String path) {
|
||||
var filename = Filename.parse(path);
|
||||
var protocol = protocols.get(filename.protocol);
|
||||
if (protocol == null) return filename.toString();
|
||||
else return new Filename(filename.protocol, protocol.normalize(filename.path)).toString();
|
||||
}
|
||||
@Override public String cwd(String cwd, String path) {
|
||||
var filename = Filename.parse(cwd);
|
||||
var protocol = protocols.get(filename.protocol);
|
||||
if (protocol == null) return filename.toString();
|
||||
else return new Filename(filename.protocol, protocol.cwd(filename.path, path)).toString();
|
||||
}
|
||||
@Override public File open(String path, Mode perms) throws FilesystemException {
|
||||
var filename = Filename.parse(path);
|
||||
var protocol = protocols.get(filename.protocol);
|
||||
|
Loading…
Reference in New Issue
Block a user