From 861b4d6fab4aaafda7f4e53932b98d1545bce2d5 Mon Sep 17 00:00:00 2001 From: George Aristy Date: Wed, 14 Nov 2018 16:59:02 -0500 Subject: [PATCH 1/2] (#176) HttpClientEnvelope + PlainHttpClient --- .../amihaiemil/docker/HttpClientEnvelope.java | 128 ++++++++++++++++++ .../amihaiemil/docker/PlainHttpClient.java | 47 +++++++ .../com/amihaiemil/docker/RemoteDocker.java | 11 ++ .../com/amihaiemil/docker/SslHttpClient.java | 94 +------------ .../com/amihaiemil/docker/UnixHttpClient.java | 109 +-------------- .../docker/SslHttpClientTestCase.java | 2 +- .../docker/UnixHttpClientTestCase.java | 20 +-- 7 files changed, 202 insertions(+), 209 deletions(-) create mode 100644 src/main/java/com/amihaiemil/docker/HttpClientEnvelope.java create mode 100644 src/main/java/com/amihaiemil/docker/PlainHttpClient.java diff --git a/src/main/java/com/amihaiemil/docker/HttpClientEnvelope.java b/src/main/java/com/amihaiemil/docker/HttpClientEnvelope.java new file mode 100644 index 00000000..4b150a8c --- /dev/null +++ b/src/main/java/com/amihaiemil/docker/HttpClientEnvelope.java @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2018, Mihai Emil Andronache + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1)Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2)Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3)Neither the name of docker-java-api nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package com.amihaiemil.docker; + +import java.io.IOException; +import java.util.function.Supplier; +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.params.HttpParams; +import org.apache.http.protocol.HttpContext; + +/** + * HTTP client envelope. + * + * @author George Aristy (george.aristy@gmail.com) + * @since 0.0.4 + */ +abstract class HttpClientEnvelope implements HttpClient { + /** + * Actual HttpClient. + */ + private final HttpClient enveloped; + + /** + * Ctor. + * @param enveloped The concrete http client + */ + HttpClientEnvelope(final Supplier enveloped) { + this.enveloped = enveloped.get(); + } + + @Override + public HttpParams getParams() { + return this.enveloped.getParams(); + } + + @Override + public ClientConnectionManager getConnectionManager() { + return this.enveloped.getConnectionManager(); + } + + @Override + public HttpResponse execute(final HttpUriRequest request) + throws IOException, ClientProtocolException { + return this.enveloped.execute(request); + } + + @Override + public HttpResponse execute(final HttpUriRequest request, + final HttpContext context) + throws IOException, ClientProtocolException { + return this.enveloped.execute(request, context); + } + + @Override + public HttpResponse execute(final HttpHost target, + final HttpRequest request) + throws IOException, ClientProtocolException { + return this.enveloped.execute(target, request); + } + + @Override + public HttpResponse execute(final HttpHost target, + final HttpRequest request, final HttpContext context) + throws IOException, ClientProtocolException { + return this.enveloped.execute(target, request, context); + } + + @Override + public T execute(final HttpUriRequest request, + final ResponseHandler responseHandler) + throws IOException, ClientProtocolException { + return this.enveloped.execute(request, responseHandler); + } + + @Override + public T execute(final HttpUriRequest request, + final ResponseHandler responseHandler, + final HttpContext context) throws IOException, ClientProtocolException { + return this.enveloped.execute(request, responseHandler, context); + } + + @Override + public T execute(final HttpHost target, final HttpRequest request, + final ResponseHandler responseHandler) + throws IOException, ClientProtocolException { + return this.enveloped.execute(target, request, responseHandler); + } + + // @checkstyle ParameterNumber (2 lines) + @Override + public T execute(final HttpHost target, final HttpRequest request, + final ResponseHandler responseHandler, + final HttpContext context) throws IOException, ClientProtocolException { + return this.enveloped.execute( + target, request, responseHandler, context + ); + } +} diff --git a/src/main/java/com/amihaiemil/docker/PlainHttpClient.java b/src/main/java/com/amihaiemil/docker/PlainHttpClient.java new file mode 100644 index 00000000..b8362001 --- /dev/null +++ b/src/main/java/com/amihaiemil/docker/PlainHttpClient.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2018, Mihai Emil Andronache + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1)Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2)Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3)Neither the name of docker-java-api nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package com.amihaiemil.docker; + +import org.apache.http.impl.client.HttpClients; + +/** + * Plain HTTP (no TLS) client. + * + * @author George Aristy (george.aristy@gmail.com) + * @since 0.0.4 + */ +final class PlainHttpClient extends HttpClientEnvelope { + /** + * Ctor. + */ + PlainHttpClient() { + super(() -> HttpClients.custom() + .setMaxConnPerRoute(10) + .setMaxConnTotal(10) + .build() + ); + } +} diff --git a/src/main/java/com/amihaiemil/docker/RemoteDocker.java b/src/main/java/com/amihaiemil/docker/RemoteDocker.java index 6db739a2..0ca6d31b 100644 --- a/src/main/java/com/amihaiemil/docker/RemoteDocker.java +++ b/src/main/java/com/amihaiemil/docker/RemoteDocker.java @@ -76,6 +76,17 @@ public final class RemoteDocker extends RtDocker { ); } + /** + * Remote Docker engine. + * + * An insecure docker API v1.35 endpoint is assumed. + * + * @param uri Remote Docker URI. + */ + public RemoteDocker(final URI uri) { + this(new PlainHttpClient(), uri); + } + /** * Remote Docker engine. You have to configure your own HttpClient, * most likely with some authentication mechanism, depending on where diff --git a/src/main/java/com/amihaiemil/docker/SslHttpClient.java b/src/main/java/com/amihaiemil/docker/SslHttpClient.java index 683419cd..59682d2f 100644 --- a/src/main/java/com/amihaiemil/docker/SslHttpClient.java +++ b/src/main/java/com/amihaiemil/docker/SslHttpClient.java @@ -30,17 +30,8 @@ import java.security.GeneralSecurityException; import java.util.function.Supplier; -import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.conn.ClientConnectionManager; import org.apache.http.impl.client.HttpClients; -import org.apache.http.params.HttpParams; -import org.apache.http.protocol.HttpContext; import org.apache.http.ssl.SSLContexts; /** @@ -50,16 +41,8 @@ * @version $Id$ * @since 0.0.1 * @checkstyle ParameterNumber (150 lines) - * @todo #100:30min Add a plain HTTP client for use. It is possible - * for users to disable TLS on docker's API. See - * https://docs.docker.com/registry/insecure/. */ -final class SslHttpClient implements HttpClient { - /** - * Decorated HttpClient. - */ - private final HttpClient origin; - +final class SslHttpClient extends HttpClientEnvelope { /** * Ctor. * @param keys Path to the keystore. @@ -92,79 +75,6 @@ final class SslHttpClient implements HttpClient { * @param client Decorated HttpClient. */ SslHttpClient(final Supplier client) { - this(client.get()); - } - - /** - * Ctor. - * @param client Decorated HttpClient. - */ - SslHttpClient(final HttpClient client) { - this.origin = client; - } - - @Override - public HttpParams getParams() { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public ClientConnectionManager getConnectionManager() { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public HttpResponse execute(final HttpUriRequest request) - throws IOException, ClientProtocolException { - return this.origin.execute(request); - } - - @Override - public HttpResponse execute(final HttpUriRequest request, - final HttpContext context) - throws IOException, ClientProtocolException { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public HttpResponse execute(final HttpHost target, - final HttpRequest request) - throws IOException, ClientProtocolException { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public HttpResponse execute(final HttpHost target, - final HttpRequest request, final HttpContext context) - throws IOException, ClientProtocolException { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public T execute(final HttpUriRequest request, - final ResponseHandler responseHandler) - throws IOException, ClientProtocolException { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public T execute(final HttpUriRequest request, - final ResponseHandler responseHandler, - final HttpContext context) throws IOException, ClientProtocolException { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public T execute(final HttpHost target, final HttpRequest request, - final ResponseHandler responseHandler) - throws IOException, ClientProtocolException { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public T execute(final HttpHost target, final HttpRequest request, - final ResponseHandler responseHandler, - final HttpContext context) throws IOException, ClientProtocolException { - throw new UnsupportedOperationException("Not supported yet."); + super(client); } } diff --git a/src/main/java/com/amihaiemil/docker/UnixHttpClient.java b/src/main/java/com/amihaiemil/docker/UnixHttpClient.java index a8c92b13..e3043015 100644 --- a/src/main/java/com/amihaiemil/docker/UnixHttpClient.java +++ b/src/main/java/com/amihaiemil/docker/UnixHttpClient.java @@ -25,20 +25,11 @@ */ package com.amihaiemil.docker; -import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; -import org.apache.http.client.ResponseHandler; -import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.params.HttpParams; -import org.apache.http.protocol.HttpContext; import java.io.File; -import java.io.IOException; import java.util.function.Supplier; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; @@ -51,13 +42,7 @@ * @checkstyle ParameterNumber (150 lines) * @checkstyle AnonInnerLength (150 lines) */ -final class UnixHttpClient implements HttpClient { - - /** - * Decorated HttpClient. - */ - private HttpClient client; - +final class UnixHttpClient extends HttpClientEnvelope { /** * Ctor. * @param socketFile Unix socket on disk. @@ -81,97 +66,9 @@ final class UnixHttpClient implements HttpClient { /** * Ctor. - * @param client The HttpClient. + * @param client The http client */ UnixHttpClient(final Supplier client) { - this(client.get()); - } - - /** - * Ctor. - * @param client Decorated HttpClient. - */ - UnixHttpClient(final HttpClient client) { - this.client = client; - } - - @Override - public HttpParams getParams() { - return this.client.getParams(); - } - - @Override - public ClientConnectionManager getConnectionManager() { - return this.client.getConnectionManager(); - } - - @Override - public HttpResponse execute( - final HttpUriRequest httpUriRequest - ) throws IOException { - return this.client.execute(httpUriRequest); - } - - @Override - public HttpResponse execute( - final HttpUriRequest httpUriRequest, final HttpContext httpContext - ) throws IOException { - return this.client.execute(httpUriRequest, httpContext); - } - - @Override - public HttpResponse execute( - final HttpHost httpHost, final HttpRequest httpRequest - ) throws IOException { - return this.client.execute(httpHost, httpRequest); - } - - @Override - public HttpResponse execute( - final HttpHost httpHost, - final HttpRequest httpRequest, - final HttpContext httpContext - ) throws IOException { - return this.client.execute(httpHost, httpRequest, httpContext); - } - - @Override - public T execute( - final HttpUriRequest httpUriRequest, - final ResponseHandler responseHandler - ) throws IOException { - return this.client.execute(httpUriRequest, responseHandler); - } - - @Override - public T execute( - final HttpUriRequest httpUriRequest, - final ResponseHandler responseHandler, - final HttpContext httpContext - ) throws IOException { - return this.client.execute( - httpUriRequest, responseHandler, httpContext - ); - } - - @Override - public T execute( - final HttpHost httpHost, - final HttpRequest httpRequest, - final ResponseHandler responseHandler - ) throws IOException { - return this.client.execute(httpHost, httpRequest, responseHandler); - } - - @Override - public T execute( - final HttpHost httpHost, - final HttpRequest httpRequest, - final ResponseHandler responseHandler, - final HttpContext httpContext - ) throws IOException { - return this.client.execute( - httpHost, httpRequest, responseHandler, httpContext - ); + super(client); } } diff --git a/src/test/java/com/amihaiemil/docker/SslHttpClientTestCase.java b/src/test/java/com/amihaiemil/docker/SslHttpClientTestCase.java index 2e4bd1d1..af09c233 100644 --- a/src/test/java/com/amihaiemil/docker/SslHttpClientTestCase.java +++ b/src/test/java/com/amihaiemil/docker/SslHttpClientTestCase.java @@ -52,7 +52,7 @@ public void executesRequestAndReturnsResponse() throws Exception { final Response response = new Response(HttpStatus.SC_OK, ""); MatcherAssert.assertThat( new SslHttpClient( - new AssertRequest(response) + () -> new AssertRequest(response) ).execute(new HttpGet()), Matchers.is(response) ); diff --git a/src/test/java/com/amihaiemil/docker/UnixHttpClientTestCase.java b/src/test/java/com/amihaiemil/docker/UnixHttpClientTestCase.java index f7728d54..fc6dd31a 100644 --- a/src/test/java/com/amihaiemil/docker/UnixHttpClientTestCase.java +++ b/src/test/java/com/amihaiemil/docker/UnixHttpClientTestCase.java @@ -70,7 +70,7 @@ public void getsHttpParams() { final HttpClient decorated = Mockito.mock(HttpClient.class); Mockito.when(decorated.getParams()).thenReturn(params); - final HttpClient unix = new UnixHttpClient(decorated); + final HttpClient unix = new UnixHttpClient(() -> decorated); MatcherAssert.assertThat(unix.getParams(), Matchers.is(params)); Mockito.verify( decorated, Mockito.times(1) @@ -88,7 +88,7 @@ public void getsClientConnectionManager() { final HttpClient decorated = Mockito.mock(HttpClient.class); Mockito.when(decorated.getConnectionManager()).thenReturn(cmngr); - final HttpClient unix = new UnixHttpClient(decorated); + final HttpClient unix = new UnixHttpClient(() -> decorated); MatcherAssert.assertThat( unix.getConnectionManager(), Matchers.is(cmngr) ); @@ -108,7 +108,7 @@ public void executesUriRequest() throws IOException { final HttpClient decorated = Mockito.mock(HttpClient.class); Mockito.when(decorated.execute(req)).thenReturn(resp); - final HttpClient unix = new UnixHttpClient(decorated); + final HttpClient unix = new UnixHttpClient(() -> decorated); MatcherAssert.assertThat( unix.execute(req), Matchers.is(resp) ); @@ -132,7 +132,7 @@ public void executesUriRequestWithContext() throws IOException { decorated.execute(req, context) ).thenReturn(resp); - final HttpClient unix = new UnixHttpClient(decorated); + final HttpClient unix = new UnixHttpClient(() -> decorated); MatcherAssert.assertThat( unix.execute(req, context), Matchers.is(resp) ); @@ -155,7 +155,7 @@ public void executesRequestWithHost() throws IOException { decorated.execute(host, req) ).thenReturn(resp); - final HttpClient unix = new UnixHttpClient(decorated); + final HttpClient unix = new UnixHttpClient(() -> decorated); MatcherAssert.assertThat( unix.execute(host, req), Matchers.is(resp) ); @@ -180,7 +180,7 @@ public void executesRequestWithHostAndContext() throws IOException { decorated.execute(host, req, context) ).thenReturn(resp); - final HttpClient unix = new UnixHttpClient(decorated); + final HttpClient unix = new UnixHttpClient(() -> decorated); MatcherAssert.assertThat( unix.execute(host, req, context), Matchers.is(resp) ); @@ -205,7 +205,7 @@ public void executesUriRequestWithHandler() throws IOException { decorated.execute(req, handler) ).thenReturn("executed"); - final HttpClient unix = new UnixHttpClient(decorated); + final HttpClient unix = new UnixHttpClient(() -> decorated); MatcherAssert.assertThat( unix.execute(req, handler), Matchers.equalTo("executed") ); @@ -231,7 +231,7 @@ public void executesUriRequestWithHandlerAndContext() throws IOException { decorated.execute(req, handler, context) ).thenReturn("executed"); - final HttpClient unix = new UnixHttpClient(decorated); + final HttpClient unix = new UnixHttpClient(() -> decorated); MatcherAssert.assertThat( unix.execute(req, handler, context), Matchers.equalTo("executed") ); @@ -258,7 +258,7 @@ public void executesRequestWithHostAndHandler() throws IOException { decorated.execute(host, req, handler) ).thenReturn("executed"); - final HttpClient unix = new UnixHttpClient(decorated); + final HttpClient unix = new UnixHttpClient(() -> decorated); MatcherAssert.assertThat( unix.execute(host, req, handler), Matchers.equalTo("executed") ); @@ -285,7 +285,7 @@ public void executesRequestWithHostHandlerAndContext() throws IOException { decorated.execute(host, req, handler, context) ).thenReturn("executed"); - final HttpClient unix = new UnixHttpClient(decorated); + final HttpClient unix = new UnixHttpClient(() -> decorated); MatcherAssert.assertThat( unix.execute(host, req, handler, context), Matchers.equalTo("executed") From f97da022b55b3ece85c304b2ca8f09b539b30dff Mon Sep 17 00:00:00 2001 From: George Aristy Date: Sun, 18 Nov 2018 13:41:21 -0500 Subject: [PATCH 2/2] (#176) HttpClientEnvelope + PlainHttpClient Fixed style issues. --- src/main/java/com/amihaiemil/docker/HttpClientEnvelope.java | 1 + src/main/java/com/amihaiemil/docker/PlainHttpClient.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/com/amihaiemil/docker/HttpClientEnvelope.java b/src/main/java/com/amihaiemil/docker/HttpClientEnvelope.java index 4b150a8c..dc78ea45 100644 --- a/src/main/java/com/amihaiemil/docker/HttpClientEnvelope.java +++ b/src/main/java/com/amihaiemil/docker/HttpClientEnvelope.java @@ -42,6 +42,7 @@ * HTTP client envelope. * * @author George Aristy (george.aristy@gmail.com) + * @version $Id$ * @since 0.0.4 */ abstract class HttpClientEnvelope implements HttpClient { diff --git a/src/main/java/com/amihaiemil/docker/PlainHttpClient.java b/src/main/java/com/amihaiemil/docker/PlainHttpClient.java index b8362001..0c29271c 100644 --- a/src/main/java/com/amihaiemil/docker/PlainHttpClient.java +++ b/src/main/java/com/amihaiemil/docker/PlainHttpClient.java @@ -31,6 +31,7 @@ * Plain HTTP (no TLS) client. * * @author George Aristy (george.aristy@gmail.com) + * @version $Id$ * @since 0.0.4 */ final class PlainHttpClient extends HttpClientEnvelope {