package org.openautonomousconnection.webserver.runtime; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.WebRequestPacket; import org.openautonomousconnection.protocol.packets.v1_0_0.beta.web.WebResponsePacket; import org.openautonomousconnection.protocol.side.web.ConnectedWebClient; import org.openautonomousconnection.protocol.side.web.ProtocolWebServer; import org.openautonomousconnection.webserver.WebServer; import org.openautonomousconnection.webserver.api.WebPage; import org.openautonomousconnection.webserver.api.WebPageContext; import org.openautonomousconnection.webserver.utils.WebHasher; import org.openautonomousconnection.webserver.utils.RequestParams; import java.io.File; import java.nio.charset.StandardCharsets; import java.util.Map; /** * Dispatches Java WebPages using @Route annotation. */ public final class JavaPageDispatcher { private static final JavaRouteRegistry ROUTES = new JavaRouteRegistry(); private JavaPageDispatcher() {} public static WebResponsePacket dispatch( ConnectedWebClient client, ProtocolWebServer server, WebRequestPacket request ) throws Exception { if (request.getPath() == null) return null; String route = request.getPath(); if (!route.startsWith("/")) route = "/" + route; File contentRoot = server.getContentFolder(); ROUTES.refreshIfNeeded(contentRoot); JavaRouteRegistry.RouteLookupResult found = ROUTES.find(route); // If no @Route match, still detect "requested a .java-backed path by filename" // (legacy behavior): if a matching *.java exists, compile/load but return error. if (found == null) { String p = route.startsWith("/") ? route.substring(1) : route; File javaFile = new File(contentRoot, p + ".java"); if (javaFile.exists() && javaFile.isFile()) { // Compile/load but do not serve. new JavaPageCache().getOrCompile(javaFile); return error(501, "Java class exists but has no @Route: " + route); } return null; // not a Java route -> let file server handle it } // If it has @Route but is not a WebPage, compile/load but return error. if (!found.routable()) { return error(500, "Class has @Route but is not a WebPage: " + found.fqcn()); } // Load and execute Class clazz = Class.forName(found.fqcn()); Object instance = clazz.getDeclaredConstructor().newInstance(); if (!(instance instanceof WebPage page)) { return error(500, "Routed class is not a WebPage: " + found.fqcn()); } WebHasher hasher = (server instanceof WebServer ws) ? ws.getHasher() : null; if (hasher == null) return error(500, "WebHasher missing on server instance."); WebPageContext ctx = new WebPageContext(client, server, request, new RequestParams(request), hasher); return page.handle(ctx); } private static WebResponsePacket error(int code, String msg) { return new WebResponsePacket( code, "text/plain; charset=utf-8", Map.of(), msg.getBytes(StandardCharsets.UTF_8) ); } }