import java.io.*;
public class Compiler {
- private final Map<Path, Module> modules = new HashMap<>();
+ private final Map<Path, File> files = new HashMap<>();
public static class ClassOutput {
public final String name;
infiles.add(p);
}
- private static final Pattern classpat = Pattern.compile("^((public|abstract)\\s+)*(class|interface)\\s+(\\S+)");
- public void split(Path infile) throws IOException {
- StringBuilder head = new StringBuilder();
- BufferedWriter cur = null;
- try(BufferedReader fp = Files.newBufferedReader(infile)) {
- for(String ln = fp.readLine(); ln != null; ln = fp.readLine()) {
- Matcher m = classpat.matcher(ln);
- if(m.find()) {
- String clnm = m.group(4);
- Path sp = srcdir.resolve(clnm + ".java");
- add(sp);
- if(cur != null)
- cur.close();
- cur = Files.newBufferedWriter(sp);
- cur.append(head);
- }
- if(cur != null) {
- cur.append(ln); cur.append('\n');
- } else {
- head.append(ln); head.append('\n');
- }
- }
- } finally {
- if(cur != null)
- cur.close();
- }
- }
-
public boolean compile() throws IOException {
List<String> args = new ArrayList<>();
args.add("javac");
}
}
- public static Collection<ClassOutput> compile(Path file) throws IOException {
- try(Compilation c = new Compilation()) {
- c.split(file);
- if(!c.compile())
- throw(new CompilationException(file, c.output()));
- return(c.classes());
- }
- }
-
public static class BufferedClassLoader extends ClassLoader {
public final Map<String, byte[]> contents;
public static class Module {
public final Path file;
- private FileTime mtime = null;
- private ClassLoader code = null;
+ public final ClassLoader code;
- private Module(Path file) {
+ public Module(Path file) throws IOException {
this.file = file;
+ try(Compilation c = new Compilation()) {
+ split(c);
+ if(!c.compile())
+ throw(new CompilationException(file, c.output()));
+ code = new BufferedClassLoader(c.classes());
+ }
+ }
+
+ private static final Pattern classpat = Pattern.compile("^((public|abstract)\\s+)*(class|interface)\\s+(\\S+)");
+ public void split(Compilation c) throws IOException {
+ StringBuilder head = new StringBuilder();
+ BufferedWriter cur = null;
+ try(BufferedReader fp = Files.newBufferedReader(file)) {
+ for(String ln = fp.readLine(); ln != null; ln = fp.readLine()) {
+ Matcher m = classpat.matcher(ln);
+ if(m.find()) {
+ String clnm = m.group(4);
+ Path sp = c.srcdir.resolve(clnm + ".java");
+ c.add(sp);
+ if(cur != null)
+ cur.close();
+ cur = Files.newBufferedWriter(sp);
+ cur.append(head);
+ }
+ if(cur != null) {
+ cur.append(ln); cur.append('\n');
+ } else {
+ head.append(ln); head.append('\n');
+ }
+ }
+ } finally {
+ if(cur != null)
+ cur.close();
+ }
+ }
+ }
+
+ public static class File {
+ public final Path name;
+ private FileTime mtime = null;
+ private Module mod = null;
+
+ private File(Path name) {
+ this.name = name;
}
public void update() throws IOException {
synchronized(this) {
- FileTime mtime = Files.getLastModifiedTime(file);
+ FileTime mtime = Files.getLastModifiedTime(name);
if((this.mtime == null) || (this.mtime.compareTo(mtime) < 0)) {
- code = new BufferedClassLoader(compile(file));
+ mod = new Module(name);
this.mtime = mtime;
}
}
}
- public ClassLoader code() {
- if(code == null)
- throw(new RuntimeException("module has not yet been updated"));
- return(code);
+ public Module mod() {
+ if(mod == null)
+ throw(new RuntimeException("file has not yet been updated"));
+ return(mod);
}
}
- public Module module(Path file) {
- synchronized(modules) {
- Module ret = modules.get(file);
+ public File file(Path name) {
+ synchronized(files) {
+ File ret = files.get(name);
if(ret == null)
- modules.put(file, ret = new Module(file));
+ files.put(name, ret = new File(name));
return(ret);
}
}
public class JavaHandler implements Function<Map<Object, Object>, Map<Object, Object>> {
private static final Logger log = Logger.getLogger("jagi-fs");
- private final Map<ClassLoader, Function<Map<Object, Object>, Map<Object, Object>>> handlers = new WeakHashMap<>();
+ private final Map<Compiler.Module, Function<Map<Object, Object>, Map<Object, Object>>> handlers = new WeakHashMap<>();
public static class HandlerException extends RuntimeException {
public final Path file;
private static Function<Map<Object, Object>, Map<Object, Object>> makehandler(Compiler.Module mod) {
Class<?> main;
try {
- main = mod.code().loadClass("Main");
+ main = mod.code.loadClass("Main");
} catch(ClassNotFoundException e) {
throw(new HandlerException(mod.file, "no Main class"));
}
throw(new HandlerException(mod.file, "no wmain and not directly applicable"));
}
- private Function<Map<Object, Object>, Map<Object, Object>> gethandler(Compiler.Module mod) {
- ClassLoader code = mod.code();
+ private Function<Map<Object, Object>, Map<Object, Object>> gethandler(Compiler.File file) {
+ Compiler.Module mod = file.mod();
synchronized(handlers) {
- Function<Map<Object, Object>, Map<Object, Object>> ret = handlers.get(code);
+ Function<Map<Object, Object>, Map<Object, Object>> ret = handlers.get(mod);
if(ret == null)
- handlers.put(code, ret = makehandler(mod));
+ handlers.put(mod, ret = makehandler(mod));
return(ret);
}
}
public Map<Object, Object> apply(Map<Object, Object> req) {
- Compiler.Module mod = Compiler.get().module(Paths.get((String)req.get("SCRIPT_FILENAME")));
+ Compiler.File file = Compiler.get().file(Paths.get((String)req.get("SCRIPT_FILENAME")));
try {
- mod.update();
+ file.update();
} catch(Compiler.CompilationException e) {
- log.warning(String.format("Could not compile %s:\n%s", mod.file, e.messages()));
+ log.warning(String.format("Could not compile %s:\n%s", file.name, e.messages()));
return(Utils.simpleerror(500, "Internal Error", "Could not load JAGI handler"));
} catch(Exception e) {
- log.log(Level.WARNING, String.format("Error occurred when loading %s", mod.file), e);
+ log.log(Level.WARNING, String.format("Error occurred when loading %s", file.name), e);
return(Utils.simpleerror(500, "Internal Error", "Could not load JAGI handler"));
}
Function<Map<Object, Object>, Map<Object, Object>> handler;
try {
- handler = gethandler(mod);
+ handler = gethandler(file);
} catch(HandlerException e) {
Throwable cause = e.getCause();
if(cause != null)