diff --git a/pom.xml b/pom.xml index 217a19c..d3f560f 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,9 @@ 21 21 + UTF-8 + eu.m724.Main @@ -20,6 +22,71 @@ json 20250107 + + + org.slf4j + slf4j-api + 2.0.16 + + + org.slf4j + slf4j-simple + 2.0.16 + + + + org.jetbrains + annotations + 26.0.1 + compile + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.4.2 + + + + true + ${exec.mainClass} + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + true + false + true + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/eu/m724/Main.java b/src/main/java/eu/m724/Main.java index fac62e9..42da78c 100644 --- a/src/main/java/eu/m724/Main.java +++ b/src/main/java/eu/m724/Main.java @@ -4,6 +4,8 @@ import eu.m724.docker.DockerEngine; import eu.m724.docker.exception.FailedRequestException; import eu.m724.docker.proxy.TcpSocketProxy; import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.StandardProtocolFamily; @@ -11,29 +13,30 @@ import java.net.UnixDomainSocketAddress; import java.util.concurrent.ExecutionException; public class Main { + private static final Logger LOGGER = LoggerFactory.getLogger(Main.class); + public static void main(String[] args) throws IOException, InterruptedException { var proxy = new TcpSocketProxy(StandardProtocolFamily.UNIX, UnixDomainSocketAddress.of("/var/run/docker.sock")); proxy.start(); - System.out.println("Started"); - System.out.printf("Tested in %d ms %n", proxy.test() / 1000000); + LOGGER.info("Latency to remote: {} ms", proxy.test() / 1000000); var engine = new DockerEngine(proxy.getURI()); engine.ping().join(); var info = engine.info().join(); - System.out.println("Docker runtime:"); - System.out.println("- " + info.getString("ID")); - System.out.println("- " + info.getString("OSType") + " " + info.getString("Architecture")); - System.out.println("- OS: " + info.getString("OperatingSystem") + " " + info.getString("OSVersion")); - System.out.println("- Hostname: " + info.getString("Name")); + LOGGER.info("Docker runtime:"); + LOGGER.info("- {}", info.getString("ID")); + LOGGER.info("- {}, {}", info.getString("OSType"), info.getString("Architecture")); + LOGGER.info("- OS: {} version {}", info.getString("OperatingSystem"), info.getString("OSVersion")); + LOGGER.info("- Hostname: {}", info.getString("Name")); JSONObject containerInfo = null; try { containerInfo = engine.inspectContainer("dcdn_nginx").get(); } catch (ExecutionException e) { if (e.getCause() instanceof FailedRequestException fre && fre.getResponse().statusCode() == 404) { - System.out.println("Container doesn't exist"); + LOGGER.info("Container doesn't exist"); } else { throw new RuntimeException("Exception getting container info", e); } @@ -41,14 +44,14 @@ public class Main { if (containerInfo != null) { var mounts = containerInfo.getJSONArray("Mounts"); - System.out.printf("Detected %d mounts:%n", mounts.length()); + LOGGER.debug("Detected {} mounts:", mounts.length()); for (int i=0; i %s %n", j.getString("Name"), j.getString("Source"), j.getString("Destination")); + LOGGER.debug("{} {} -> {}", j.getString("Name"), j.getString("Source"), j.getString("Destination")); } } else { - System.out.println("Creating it"); + LOGGER.info("Creating it"); var data = new JSONObject() .put("Image", "nginx:1.27"); diff --git a/src/main/java/eu/m724/docker/DockerEngine.java b/src/main/java/eu/m724/docker/DockerEngine.java index dc94dc3..f06a1bc 100644 --- a/src/main/java/eu/m724/docker/DockerEngine.java +++ b/src/main/java/eu/m724/docker/DockerEngine.java @@ -3,6 +3,8 @@ package eu.m724.docker; import org.json.JSONObject; import java.net.URI; +import java.net.http.HttpClient; +import java.time.Duration; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; @@ -12,7 +14,7 @@ public class DockerEngine { public DockerEngine(URI socketUri) { - this.dao = new DockerEngineDAO(socketUri); + this.dao = new DockerEngineDAO(socketUri, HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).connectTimeout(Duration.ofSeconds(30)).build()); } public CompletableFuture ping() { diff --git a/src/main/java/eu/m724/docker/DockerEngineDAO.java b/src/main/java/eu/m724/docker/DockerEngineDAO.java index d3151b3..5c8a6db 100644 --- a/src/main/java/eu/m724/docker/DockerEngineDAO.java +++ b/src/main/java/eu/m724/docker/DockerEngineDAO.java @@ -1,31 +1,34 @@ package eu.m724.docker; import eu.m724.docker.exception.FailedRequestException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.net.URI; +import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; -import java.time.Duration; +import java.nio.charset.StandardCharsets; import java.util.Map; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; public class DockerEngineDAO { + private static final Logger LOGGER = LoggerFactory.getLogger(DockerEngineDAO.class); + private final URI socketUri; private final HttpClient httpClient; - DockerEngineDAO(URI socketUri) { + DockerEngineDAO(URI socketUri, HttpClient httpClient) { this.socketUri = socketUri; - this.httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).connectTimeout(Duration.ofSeconds(30)).build(); + this.httpClient = httpClient; } - public void close() { - httpClient.close(); - } - - /** * Create a GET request that expects a JSON from the server.
* A {@link FailedRequestException} is thrown by the future if a non-200 status code is returned. @@ -172,19 +175,16 @@ public class DockerEngineDAO { } - private HttpRequest createRequest(String path) { - return HttpRequest.newBuilder(socketUri.resolve(path)).build(); - } + private CompletableFuture commonRequest(@NotNull String path, @Nullable Map queryParams, @Nullable JSONObject data, @NotNull HttpResponse.BodyHandler bodyHandler) { + Objects.requireNonNull(path, "Request path cannot be null"); + Objects.requireNonNull(bodyHandler, "Body handler cannot be null"); - private CompletableFuture commonRequest(String path, Map queryParams, JSONObject data, HttpResponse.BodyHandler bodyHandler) { if (queryParams != null && !queryParams.isEmpty()) { - path += '?'; - path += queryParams.entrySet().stream() - .map(e -> e.getKey() + '=' + e.getValue()) - .collect(Collectors.joining("&")); + path += encodeQueryParams(queryParams); } - System.out.println(path); + LOGGER.debug("Calling request: {}", path); + var builder = HttpRequest.newBuilder(socketUri.resolve(path)); if (data != null) { @@ -200,4 +200,12 @@ public class DockerEngineDAO { return response.body(); }); } + + private String encodeQueryParams(@NotNull Map params) { + return params.entrySet().stream() + .map(e -> URLEncoder.encode(e.getKey(), StandardCharsets.UTF_8) + + "=" + + URLEncoder.encode(String.valueOf(e.getValue()), StandardCharsets.UTF_8)) + .collect(Collectors.joining("&", "?", "")); + } } diff --git a/src/main/java/eu/m724/docker/exception/FailedRequestException.java b/src/main/java/eu/m724/docker/exception/FailedRequestException.java index 10a9635..1ba3522 100644 --- a/src/main/java/eu/m724/docker/exception/FailedRequestException.java +++ b/src/main/java/eu/m724/docker/exception/FailedRequestException.java @@ -12,7 +12,7 @@ public class FailedRequestException extends CompletionException { @Override public String getMessage() { - return "Code: " + response.statusCode() + " | Body: " + response.body(); + return "Request failed with status %d: %s".formatted(response.statusCode(), response.body()); } public HttpResponse getResponse() { diff --git a/src/main/java/eu/m724/docker/proxy/ConnectionThread.java b/src/main/java/eu/m724/docker/proxy/ConnectionThread.java index 958ef73..de94228 100644 --- a/src/main/java/eu/m724/docker/proxy/ConnectionThread.java +++ b/src/main/java/eu/m724/docker/proxy/ConnectionThread.java @@ -1,5 +1,8 @@ package eu.m724.docker.proxy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.net.Socket; import java.nio.ByteBuffer; @@ -13,6 +16,8 @@ public class ConnectionThread extends Thread { private final RemoteSocketFactory remoteSocketFactory; private final Socket clientSocket; + private final Logger LOGGER = LoggerFactory.getLogger(ConnectionThread.class); + ConnectionThread(ExecutorService executorService, RemoteSocketFactory remoteSocketFactory, Socket clientSocket) { this.executorService = executorService; this.remoteSocketFactory = remoteSocketFactory; @@ -25,11 +30,11 @@ public class ConnectionThread extends Thread { clientSocket; var remoteSocket = remoteSocketFactory.newChannel() ) { - System.out.println("connected"); + LOGGER.debug("starting inner"); inner(remoteSocket); - System.out.println("disconnected"); + LOGGER.debug("inner ended"); } catch (IOException e) { - System.err.println("Exception handling client: " + e.getMessage()); + LOGGER.error("Exception handling client", e); } } diff --git a/src/main/java/eu/m724/docker/proxy/ServerRunnable.java b/src/main/java/eu/m724/docker/proxy/ServerRunnable.java index 98a402f..bd2d7ca 100644 --- a/src/main/java/eu/m724/docker/proxy/ServerRunnable.java +++ b/src/main/java/eu/m724/docker/proxy/ServerRunnable.java @@ -1,10 +1,15 @@ package eu.m724.docker.proxy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.net.ServerSocket; import java.util.concurrent.ExecutorService; public class ServerRunnable implements Runnable { + private static final Logger LOGGER = LoggerFactory.getLogger(ServerRunnable.class); + private final ExecutorService executorService; private final ServerSocket serverSocket; private final RemoteSocketFactory remoteSocketFactory; @@ -26,7 +31,7 @@ public class ServerRunnable implements Runnable { } catch (IOException e) { if (serverSocket.isClosed()) break; - System.err.println("Exception handling client request: " + e.getMessage()); + LOGGER.error("Exception handling client request", e); } } } diff --git a/src/main/java/eu/m724/docker/proxy/TcpSocketProxy.java b/src/main/java/eu/m724/docker/proxy/TcpSocketProxy.java index 400d7b3..a6a980b 100644 --- a/src/main/java/eu/m724/docker/proxy/TcpSocketProxy.java +++ b/src/main/java/eu/m724/docker/proxy/TcpSocketProxy.java @@ -1,11 +1,16 @@ package eu.m724.docker.proxy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.net.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TcpSocketProxy implements AutoCloseable { + private static final Logger LOGGER = LoggerFactory.getLogger(TcpSocketProxy.class); + private final RemoteSocketFactory remoteSocketFactory; private ServerSocket serverSocket; @@ -28,7 +33,7 @@ public class TcpSocketProxy implements AutoCloseable { this.executorService = Executors.newVirtualThreadPerTaskExecutor(); executorService.execute(new ServerRunnable(executorService, serverSocket, remoteSocketFactory)); - System.out.println("Proxy bound on " + getURI()); + LOGGER.info("Proxy bound on {}", getURI()); } public long test() throws IOException {