diff --git a/src/main/java/org/lumijiez/Main.java b/src/main/java/org/lumijiez/Main.java index bb5e848..b38ef6b 100644 --- a/src/main/java/org/lumijiez/Main.java +++ b/src/main/java/org/lumijiez/Main.java @@ -1,28 +1,38 @@ package org.lumijiez; -import org.lumijiez.core.TcpServer; +import org.lumijiez.core.HttpServer; + +import java.net.Socket; public class Main { public static void main(String[] args) { - TcpServer server = new TcpServer(8080, (message, clientSocket) -> { - System.out.println("Processing message from " + clientSocket.getInetAddress() + ": " + message); - - if (message.equalsIgnoreCase("hello")) { - return "Hello, client!"; - } else if (message.equalsIgnoreCase("bye")) { - return "Goodbye!"; - } else { - return "Unknown command."; + TcpServerCallback callback = new TcpServerCallback() { + @Override + public String onClientMessage(String message, Socket clientSocket) { + return ""; } + + @Override + public String onClientConnected(Socket clientSocket) { + System.out.println("Client connected: " + clientSocket.getInetAddress()); + return ""; + } + }; + + HttpServer httpServer = new HttpServer(8080, callback); + + httpServer.GET("/hello", (req, res) -> { + res.sendResponse(200, "Hello, World!"); }); - new Thread(server::start).start(); + httpServer.GET("/goodbye", (req, res) -> { + res.sendResponse(200, "Goodbye, World!"); + }); - try { - Thread.sleep(60000); - server.stop(); - } catch (InterruptedException e) { - e.printStackTrace(); - } + httpServer.POST("/data", (req, res) -> { + res.sendResponse(200, "Data received"); + }); + + httpServer.start(); } } \ No newline at end of file diff --git a/src/main/java/org/lumijiez/core/HttpHandler.java b/src/main/java/org/lumijiez/core/HttpHandler.java new file mode 100644 index 0000000..35514fd --- /dev/null +++ b/src/main/java/org/lumijiez/core/HttpHandler.java @@ -0,0 +1,6 @@ +package org.lumijiez.core; + +@FunctionalInterface +public interface HttpHandler { + void handle(HttpRequest request, HttpResponse response); +} \ No newline at end of file diff --git a/src/main/java/org/lumijiez/core/HttpRequest.java b/src/main/java/org/lumijiez/core/HttpRequest.java new file mode 100644 index 0000000..bff82eb --- /dev/null +++ b/src/main/java/org/lumijiez/core/HttpRequest.java @@ -0,0 +1,38 @@ +package org.lumijiez.core; + +import java.io.BufferedReader; +import java.io.IOException; + +public class HttpRequest { + private String method; + private String path; + private String httpVersion; + + public HttpRequest(BufferedReader in) throws IOException { + parseRequest(in); + } + + private void parseRequest(BufferedReader in) throws IOException { + String requestLine = in.readLine(); + if (requestLine != null) { + String[] tokens = requestLine.split(" "); + if (tokens.length >= 3) { + this.method = tokens[0]; + this.path = tokens[1]; + this.httpVersion = tokens[2]; + } + } + } + + public String getMethod() { + return method; + } + + public String getPath() { + return path; + } + + public String getHttpVersion() { + return httpVersion; + } +} diff --git a/src/main/java/org/lumijiez/core/HttpResponse.java b/src/main/java/org/lumijiez/core/HttpResponse.java new file mode 100644 index 0000000..9eb9ed0 --- /dev/null +++ b/src/main/java/org/lumijiez/core/HttpResponse.java @@ -0,0 +1,20 @@ +package org.lumijiez.core; + +import java.io.PrintWriter; + +public class HttpResponse { + private final PrintWriter out; + + public HttpResponse(PrintWriter out) { + this.out = out; + } + + public void sendResponse(int statusCode, String message) { + out.println("HTTP/1.1 " + statusCode + " " + message); + out.println("Content-Type: text/plain"); + out.println("Connection: close"); + out.println(); + out.println(message); + out.flush(); + } +} diff --git a/src/main/java/org/lumijiez/core/HttpServer.java b/src/main/java/org/lumijiez/core/HttpServer.java new file mode 100644 index 0000000..99b5ce9 --- /dev/null +++ b/src/main/java/org/lumijiez/core/HttpServer.java @@ -0,0 +1,39 @@ +package org.lumijiez.core; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.Socket; +import java.util.function.BiConsumer; + +public class HttpServer extends TcpServer { + private final Router router; + + public HttpServer(int port, TcpServerCallback callback) { + super(port); + this.router = new Router(); + } + + public void GET(String path, BiConsumer handler) { + router.addRoute("GET", path, handler); + } + + public void POST(String path, BiConsumer handler) { + router.addRoute("POST", path, handler); + } + + @Override + protected void handleClient(Socket clientSocket) { + try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) { + + HttpRequest request = new HttpRequest(in); + HttpResponse response = new HttpResponse(out); + + router.handleRequest(request, response); + } catch (IOException e) { + System.out.println("Error handling client: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/org/lumijiez/core/Route.java b/src/main/java/org/lumijiez/core/Route.java new file mode 100644 index 0000000..7e4abd5 --- /dev/null +++ b/src/main/java/org/lumijiez/core/Route.java @@ -0,0 +1,27 @@ +package org.lumijiez.core; + +import java.util.function.BiConsumer; + +public class Route { + private final String path; + private final String method; + private final BiConsumer handler; + + public Route(String method, String path, BiConsumer handler) { + this.method = method; + this.path = path; + this.handler = handler; + } + + public String getPath() { + return path; + } + + public String getMethod() { + return method; + } + + public void handle(HttpRequest request, HttpResponse response) { + handler.accept(request, response); + } +} diff --git a/src/main/java/org/lumijiez/core/Router.java b/src/main/java/org/lumijiez/core/Router.java new file mode 100644 index 0000000..8d164c1 --- /dev/null +++ b/src/main/java/org/lumijiez/core/Router.java @@ -0,0 +1,24 @@ +package org.lumijiez.core; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiConsumer; + +public class Router { + private final List routes = new ArrayList<>(); + + public void addRoute(String method, String path, BiConsumer handler) { + routes.add(new Route(method, path, handler)); + } + + public void handleRequest(HttpRequest request, HttpResponse response) { + for (Route route : routes) { + if (route.getMethod().equalsIgnoreCase(request.getMethod()) && + route.getPath().equals(request.getPath())) { + route.handle(request, response); + return; + } + } + response.sendResponse(404, "Not Found"); + } +} diff --git a/src/main/java/org/lumijiez/core/TcpClientHandler.java b/src/main/java/org/lumijiez/core/TcpClientHandler.java deleted file mode 100644 index 4e28450..0000000 --- a/src/main/java/org/lumijiez/core/TcpClientHandler.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.lumijiez.core; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.Socket; - -public class TcpClientHandler implements Runnable { - private final Socket clientSocket; - private final TcpServerCallback callback; - - public TcpClientHandler(Socket clientSocket, TcpServerCallback callback) { - this.clientSocket = clientSocket; - this.callback = callback; - } - - @Override - public void run() { - try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); - OutputStream out = clientSocket.getOutputStream()) { - - String receivedMessage; - while ((receivedMessage = in.readLine()) != null) { - System.out.println("Received from client: " + receivedMessage); - - String response = callback.onClientMessage(receivedMessage, clientSocket); - - if (response != null) { - out.write((response + "\n").getBytes()); - out.flush(); - } - } - - } catch (IOException e) { - System.out.println("Error handling client: " + e.getMessage()); - } finally { - try { - clientSocket.close(); - System.out.println("Client disconnected: " + clientSocket.getInetAddress()); - } catch (IOException e) { - System.out.println("Error closing client socket: " + e.getMessage()); - } - } - } -} diff --git a/src/main/java/org/lumijiez/core/TcpServer.java b/src/main/java/org/lumijiez/core/TcpServer.java index a9e47b3..500ac29 100644 --- a/src/main/java/org/lumijiez/core/TcpServer.java +++ b/src/main/java/org/lumijiez/core/TcpServer.java @@ -5,16 +5,14 @@ import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -public class TcpServer { +public abstract class TcpServer { private final int port; private boolean running; private ServerSocket serverSocket; private final ExecutorService threadPool; - private final TcpServerCallback callback; - public TcpServer(int port, TcpServerCallback callback) { + public TcpServer(int port) { this.port = port; - this.callback = callback; this.running = false; this.threadPool = Executors.newCachedThreadPool(); } @@ -30,8 +28,7 @@ public class TcpServer { Socket clientSocket = serverSocket.accept(); System.out.println("New client connected: " + clientSocket.getInetAddress()); - TcpClientHandler clientHandler = new TcpClientHandler(clientSocket, callback); - threadPool.submit(clientHandler); + threadPool.submit(() -> handleClient(clientSocket)); } catch (IOException e) { if (running) { System.out.println("Error accepting client connection: " + e.getMessage()); @@ -45,6 +42,8 @@ public class TcpServer { } } + protected abstract void handleClient(Socket clientSocket); + public void stop() { running = false; if (serverSocket != null) { @@ -61,5 +60,4 @@ public class TcpServer { public boolean isRunning() { return running; } -} - +} \ No newline at end of file diff --git a/src/main/java/org/lumijiez/core/TcpServerCallback.java b/src/main/java/org/lumijiez/core/TcpServerCallback.java deleted file mode 100644 index adc385a..0000000 --- a/src/main/java/org/lumijiez/core/TcpServerCallback.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.lumijiez.core; - -import java.net.Socket; - -public interface TcpServerCallback { - String onClientMessage(String message, Socket clientSocket); -} diff --git a/src/main/java/org/lumijiez/logging/Logger.java b/src/main/java/org/lumijiez/logging/Logger.java new file mode 100644 index 0000000..f615bfb --- /dev/null +++ b/src/main/java/org/lumijiez/logging/Logger.java @@ -0,0 +1,54 @@ +package org.lumijiez.logging; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class Logger { + private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + public enum LogLevel { + DEBUG, INFO, WARN, ERROR + } + + private LogLevel currentLogLevel; + + public Logger(LogLevel level) { + this.currentLogLevel = level; + } + + public void log(LogLevel level, String source, String message) { + if (level.ordinal() >= currentLogLevel.ordinal()) { + String timestamp = LocalDateTime.now().format(formatter); + System.out.println("[" + timestamp + "] [" + level + "] [" + source + "] " + message); + } + } + + public void debug(String source, String message) { + log(LogLevel.DEBUG, source, message); + } + + public void info(String source, String message) { + log(LogLevel.INFO, source, message); + } + + public void warn(String source, String message) { + log(LogLevel.WARN, source, message); + } + + public void error(String source, String message) { + log(LogLevel.ERROR, source, message); + } + + public void error(String source, String message, Throwable throwable) { + log(LogLevel.ERROR, source, message + ": " + throwable.getMessage()); + // throwable.printStackTrace(); + } + + public void setLogLevel(LogLevel level) { + this.currentLogLevel = level; + } + + public LogLevel getLogLevel() { + return currentLogLevel; + } +}