Finished up WebServer

This commit is contained in:
Finn
2025-12-12 21:16:13 +01:00
parent 4e8e8e3e82
commit 195bd58bea
16 changed files with 383 additions and 30 deletions

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}