Finished up WebServer
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
package org.openautonomousconnection.webserver.runtime;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Caches compiled Java WebPages by file lastModified timestamp.
|
||||
*/
|
||||
public final class JavaPageCache {
|
||||
|
||||
private static final class Entry {
|
||||
final long lastModified;
|
||||
final Class<?> clazz;
|
||||
|
||||
Entry(long lastModified, Class<?> clazz) {
|
||||
this.lastModified = lastModified;
|
||||
this.clazz = clazz;
|
||||
}
|
||||
}
|
||||
|
||||
private final ConcurrentHashMap<String, Entry> cache = new ConcurrentHashMap<>();
|
||||
|
||||
public Class<?> getOrCompile(File javaFile) throws Exception {
|
||||
String key = javaFile.getAbsolutePath();
|
||||
long lm = javaFile.lastModified();
|
||||
|
||||
Entry e = cache.get(key);
|
||||
if (e != null && e.lastModified == lm) {
|
||||
return e.clazz;
|
||||
}
|
||||
|
||||
Class<?> compiled = JavaPageCompiler.compile(javaFile);
|
||||
cache.put(key, new Entry(lm, compiled));
|
||||
return compiled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.openautonomousconnection.webserver.runtime;
|
||||
|
||||
import javax.tools.*;
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Compiles and loads Java web pages at runtime.
|
||||
*
|
||||
* NOTE: Requires running with a JDK (ToolProvider.getSystemJavaCompiler != null).
|
||||
*/
|
||||
public final class JavaPageCompiler {
|
||||
|
||||
private JavaPageCompiler() {}
|
||||
|
||||
public static Class<?> compile(File javaFile) throws Exception {
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
if (compiler == null) throw new IllegalStateException("JDK required (JavaCompiler not available)");
|
||||
|
||||
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
|
||||
|
||||
Iterable<? extends JavaFileObject> units = fileManager.getJavaFileObjects(javaFile);
|
||||
|
||||
// Compile in-place (class next to the .java file)
|
||||
List<String> options = List.of("-classpath", System.getProperty("java.class.path"));
|
||||
|
||||
boolean success = compiler.getTask(null, fileManager, null, options, null, units).call();
|
||||
fileManager.close();
|
||||
|
||||
if (!success) throw new RuntimeException("Compilation failed: " + javaFile.getName());
|
||||
|
||||
URLClassLoader cl = new URLClassLoader(new URL[]{ javaFile.getParentFile().toURI().toURL() });
|
||||
|
||||
String className = javaFile.getName().replace(".java", "");
|
||||
return cl.loadClass(className);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.openautonomousconnection.webserver.runtime;
|
||||
|
||||
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebRequestPacket;
|
||||
import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebResponsePacket;
|
||||
import org.openautonomousconnection.protocol.side.web.ConnectedWebClient;
|
||||
import org.openautonomousconnection.protocol.side.web.ProtocolWebServer;
|
||||
import org.openautonomousconnection.webserver.api.WebPage;
|
||||
import org.openautonomousconnection.webserver.api.WebPageContext;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public final class JavaPageDispatcher {
|
||||
|
||||
private static final JavaPageCache CACHE = new JavaPageCache();
|
||||
|
||||
private JavaPageDispatcher() {}
|
||||
|
||||
public static WebResponsePacket dispatch(
|
||||
ConnectedWebClient client,
|
||||
ProtocolWebServer server,
|
||||
WebRequestPacket request
|
||||
) throws Exception {
|
||||
|
||||
if (request.getPath() == null) return null;
|
||||
|
||||
String p = request.getPath().startsWith("/") ? request.getPath().substring(1) : request.getPath();
|
||||
File javaFile = new File(server.getContentFolder(), p + ".java");
|
||||
|
||||
if (!javaFile.exists() || !javaFile.isFile()) return null;
|
||||
|
||||
Class<?> clazz = CACHE.getOrCompile(javaFile);
|
||||
Object instance = clazz.getDeclaredConstructor().newInstance();
|
||||
|
||||
if (!(instance instanceof WebPage page))
|
||||
throw new IllegalStateException("Java page must implement WebPage");
|
||||
|
||||
WebPageContext ctx = new WebPageContext(client, server, request);
|
||||
return page.handle(ctx);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user