4 import java.util.function.*;
5 import java.util.logging.*;
6 import java.lang.reflect.*;
8 import java.nio.file.*;
11 public class Handler implements Function<Map<Object, Object>, Map<Object, Object>> {
12 private static final Logger log = Logger.getLogger("jagi-fs");
13 private Map<String, Function<Map<Object, Object>, Map<Object, Object>>> handlers = new HashMap<>();
14 private Map<String, Function<Map<Object, Object>, Map<Object, Object>>> exts = new HashMap<>();
16 @SuppressWarnings("unchecked")
17 private static Function<Map<Object, Object>, Map<Object, Object>> resolve(ClassLoader loader, String nm) {
20 cl = loader.loadClass(nm);
21 } catch(ClassNotFoundException e) {
23 cl = loader.loadClass(nm + ".Bootstrap");
24 } catch(ClassNotFoundException e2) {
25 throw(new RuntimeException("could not find handler class or package: " + nm, e2));
30 wmain = cl.getDeclaredMethod("wmain", String[].class);
31 int mod = wmain.getModifiers();
32 if(((mod & Modifier.STATIC) == 0) || ((mod & Modifier.PUBLIC) == 0))
33 throw(new NoSuchMethodException());
34 } catch(NoSuchMethodException e) {
35 throw(new RuntimeException("could not find wmain method in " + cl.getName(), e));
39 handler = wmain.invoke(null, new Object[] {new String[] {}});
40 } catch(IllegalAccessException e) {
41 throw(new RuntimeException("could not call wmain in " + cl.getName(), e));
42 } catch(InvocationTargetException e) {
43 throw(new RuntimeException("wmain in " + cl.getName() + " failed", e.getCause()));
45 if(!(handler instanceof Function))
46 throw(new RuntimeException("wmain in " + cl.getName() + " returned " + ((handler == null) ? "null" : ("a " + handler.getClass()))));
47 return((Function<Map<Object, Object>, Map<Object, Object>>)handler);
50 public Function<Map<Object, Object>, Map<Object, Object>> resolve(String nm) {
51 synchronized(handlers) {
52 Function<Map<Object, Object>, Map<Object, Object>> handler = handlers.get(nm);
54 handlers.put(nm, handler = resolve(Thread.currentThread().getContextClassLoader(), nm));
59 public void addext(String ext, String name) {
60 addext(ext, resolve(name));
63 public void addext(String ext, Function<Map<Object, Object>, Map<Object, Object>> handler) {
64 Map<String, Function<Map<Object, Object>, Map<Object, Object>>> exts = new HashMap<>(this.exts);
66 exts.put(ext, handler);
72 addext("jagi", new JavaHandler());
75 public Map<Object, Object> apply(Map<Object, Object> req) {
76 String filename = (String)req.get("SCRIPT_FILENAME");
77 if(filename == null) {
78 log.warning("jagi-fs called without SCRIPT_FILENAME set");
79 return(Utils.simpleerror(500, "Internal Error", "The server is erroneously configured"));
81 Path path = Paths.get(filename);
82 if(!Files.isReadable(path)) {
83 log.warning(path + ": not readable");
84 return(Utils.simpleerror(500, "Internal Error", "The server is erroneously configured"));
86 String hname = (String)req.get("HTTP_X_ASH_JAVA_HANDLER");
88 Function<Map<Object, Object>, Map<Object, Object>> handler;
90 handler = resolve(hname);
91 } catch(Exception e) {
92 log.log(Level.WARNING, "could not load handler " + hname, e);
93 return(Utils.simpleerror(500, "Internal Error", "The server is erroneously configured"));
95 return(handler.apply(req));
97 String base = path.getFileName().toString();
98 int p = base.lastIndexOf('.');
100 log.warning(path + ": no file extension");
101 return(Utils.simpleerror(500, "Internal Error", "The server is erroneously configured"));
103 String ext = base.substring(p + 1);
104 Function<Map<Object, Object>, Map<Object, Object>> handler = exts.get(ext);
105 if(handler == null) {
106 log.warning("non-registered file extension: " + ext);
107 return(Utils.simpleerror(500, "Internal Error", "The server is erroneously configured"));
109 return(handler.apply(req));