Files
schafkopf-bot/Backend/schafkopf-client/src/main/java/org/schafkopf/BackendServer.java
Valentin Heiserer 2e5a42b6d3 edited stuff (#50)
2024-04-23 21:27:01 +00:00

142 lines
4.4 KiB
Java

package org.schafkopf;
import jakarta.servlet.DispatcherType;
import java.awt.Desktop;
import java.net.URI;
import java.net.URL;
import java.time.Duration;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlets.CrossOriginFilter;
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
import org.schafkopf.SchafkopfMessage.SchafkopfBaseMessage;
/**
* Main Class that represents the Backend Server.
*/
public class BackendServer implements MessageSender {
private final Server server;
private final List<FrontendEndpoint> frontendEndpoints = new ArrayList<>();
/**
* Creates an Instance of the Backend Server.
*/
public BackendServer(String hostName, int port, boolean openFrontend,
MessageListener messageListener) throws Exception {
server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setHost(hostName);
connector.setPort(port);
server.addConnector(connector);
// Setup the basic application "context" for this application at "/"
// This is also known as the handler tree (in jetty speak)
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
// Configure CORS settings
configureCors(context);
if (openFrontend) {
URL webContentUrl = getClass().getClassLoader().getResource("web-content");
if (webContentUrl == null) {
throw new RuntimeException("Unable to find 'web-content' directory");
}
String webContentPath = webContentUrl.toExternalForm();
context.setResourceBase(webContentPath);
context.addServlet(new ServletHolder("frontend", DefaultServlet.class), "/");
}
// Configure specific websocket behavior
JettyWebSocketServletContainerInitializer.configure(
context,
(servletContext, wsContainer) -> {
// Configure default max size
wsContainer.setMaxTextMessageSize(65535);
wsContainer.setIdleTimeout(Duration.ofDays(300000));
// Add websockets
wsContainer.addMapping("/schafkopf-events/*",
new FrontendEndpointCreator(this, messageListener));
});
if (openFrontend) {
URI uri = new URI("http://" + hostName + ":" + port); // Replace with your target URL
Desktop.getDesktop().browse(uri);
}
// Start the server in a separate thread
Thread serverThread = new Thread(() -> {
try {
server.start();
server.join(); // Wait for server to finish execution
} catch (Exception e) {
e.printStackTrace();
}
});
serverThread.start();
}
private void configureCors(ServletContextHandler context) {
// Enable CORS for all paths
FilterHolder cors = context.addFilter(CrossOriginFilter.class, "/*", null);
// Configure allowed origins, headers, and methods
cors.setInitParameter("allowedOrigins", "*");
cors.setInitParameter("allowedHeaders", "X-Requested-With,Content-Type,Accept,Origin");
cors.setInitParameter("allowedMethods", "GET,POST,PUT,DELETE,OPTIONS");
// Add filter mappings
EnumSet<DispatcherType> types = EnumSet.of(DispatcherType.REQUEST);
context.addFilter(cors, "*", types);
}
private void start() throws Exception {
server.start();
}
private void join() throws InterruptedException {
server.join();
}
public void addFrontendEndpoint(FrontendEndpoint endpoint) {
frontendEndpoints.add(endpoint);
}
public void removeFrontendEndpoint(FrontendEndpoint endpoint) {
frontendEndpoints.remove(endpoint);
}
/**
* Sends Message to all Frontend Instances.
*
* @param message Message to send (String).
*/
private void sendMessageToAllFrontendEndpoints(String message) {
for (FrontendEndpoint endpoint : frontendEndpoints) {
endpoint.sendMessage(message);
}
}
@Override
public void sendMessage(SchafkopfBaseMessage message) {
sendMessageToAllFrontendEndpoints(
message.getBaseMessage().toString());
}
public void sendMessageTest(String message) {
sendMessageToAllFrontendEndpoints(message);
}
}