From 16f300c24a60f1e152e0770a29b915d4b9bd2da5 Mon Sep 17 00:00:00 2001 From: George Aristy Date: Thu, 12 Apr 2018 10:39:20 -0400 Subject: [PATCH] (#79) Draft for sending responses back to clients from the mock UnixServer --- .../com/amihaiemil/docker/mock/Response.java | 52 +++++++++++++++++++ .../amihaiemil/docker/mock/UnixServer.java | 19 ++++--- 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/amihaiemil/docker/mock/Response.java b/src/test/java/com/amihaiemil/docker/mock/Response.java index 78a6cde8..f1d100b9 100644 --- a/src/test/java/com/amihaiemil/docker/mock/Response.java +++ b/src/test/java/com/amihaiemil/docker/mock/Response.java @@ -25,6 +25,11 @@ */ package com.amihaiemil.docker.mock; +import com.sun.grizzly.util.Charsets; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.WritableByteChannel; +import java.time.Instant; import java.util.Locale; import org.apache.http.Header; import org.apache.http.HeaderIterator; @@ -37,6 +42,7 @@ import org.apache.http.entity.StringEntity; import org.apache.http.message.BasicStatusLine; import org.apache.http.params.HttpParams; +import org.apache.http.util.EntityUtils; /** * An {@link HttpResponse} suitable for tests. Can be configured with @@ -45,6 +51,9 @@ * @author George Aristy (george.aristy@gmail.com) * @version $Id$ * @since 0.0.1 + * @todo 79:30min The 'asString()' method needs a little more work (fix the + * formatting on the date header value, etc) and then test the 'printTo()' + * method in conjunction with the UnixServer. */ public final class Response implements HttpResponse { /** @@ -207,4 +216,47 @@ public HttpParams getParams() { public void setParams(final HttpParams params) { throw new UnsupportedOperationException("Not supported yet."); } + + /** + * Prints itself to the channel. + * @param channel The channel. + * @throws IOException If an error occurs. + */ + public void printTo(final WritableByteChannel channel) throws IOException { + channel.write( + ByteBuffer.wrap( + this.asString().getBytes(Charsets.UTF8_CHARSET) + ) + ); + } + + /** + * This response as a string. + * @return String representation of this {@link Response}. + * @throws IOException If an error occurs. + */ + private String asString() throws IOException { + final String CRLF = "" + (char) 0x0D + (char) 0x0A; + final StringBuilder builder = new StringBuilder("HTTP/") + .append(this.statusLine.getProtocolVersion()) + .append(" ") + .append(this.statusLine.getStatusCode()) + .append(" ") + .append(this.statusLine.getReasonPhrase()) + .append(CRLF) + .append("Date: ") + .append(Instant.now()) + .append(CRLF); + if (this.payload.getContentLength() > 0) { + builder.append("ContentType: ") + .append(this.payload.getContentType().getValue()) + .append(CRLF) + .append("Content-Length: ") + .append(this.payload.getContentLength()) + .append(CRLF) + .append(CRLF) + .append(EntityUtils.toString(this.payload)); + } + return builder.toString(); + } } diff --git a/src/test/java/com/amihaiemil/docker/mock/UnixServer.java b/src/test/java/com/amihaiemil/docker/mock/UnixServer.java index 1cd179a1..9b16aad3 100644 --- a/src/test/java/com/amihaiemil/docker/mock/UnixServer.java +++ b/src/test/java/com/amihaiemil/docker/mock/UnixServer.java @@ -27,7 +27,6 @@ import java.io.Closeable; import java.io.IOException; -import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.file.Files; @@ -69,9 +68,10 @@ public final class UnixServer implements Closeable { * Ctor. *

* Eagerly opens a unix file socket created in a temp directory. + * @param response The mock response to send back to the caller. * @throws IOException If an I/O error occurs. */ - public UnixServer() throws IOException { + public UnixServer(final Response response) throws IOException { this.socketFile = Files.createTempFile("", ""); this.channel = UnixServerSocketChannel.open(); this.channel.configureBlocking(false); @@ -81,7 +81,7 @@ public UnixServer() throws IOException { this.selector = NativeSelectorProvider.getInstance().openSelector(); this.channel.register(this.selector, SelectionKey.OP_READ); this.threadPool = Executors.newSingleThreadExecutor(); - this.threadPool.submit(new Service(this.selector)); + this.threadPool.submit(new Service(this.selector, response)); } /** @@ -108,13 +108,19 @@ private static final class Service implements Callable { * Selector. */ private final Selector selector; + /** + * Response to send back to caller. + */ + private final Response response; /** * Ctor. * @param selector The selector to listen on. + * @param response The response to send back to the client. */ - private Service(final Selector selector) { + private Service(final Selector selector, final Response response) { this.selector = selector; + this.response = response; } @Override @@ -129,10 +135,7 @@ public Void call() throws IOException { final UnixSocketChannel channel = (UnixSocketChannel) key.channel(); channel.configureBlocking(false); - // @todo #41:30min Make the response from this buffer - // configurable and then implement some tests. - final ByteBuffer buffer = ByteBuffer.wrap("".getBytes()); - channel.write(buffer); + this.response.printTo(channel); } } return null;