You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2014/11/27 21:20:52 UTC
[2/2] jclouds git commit: JCLOUDS-744: Upgrade to OkHttp 2.1.0 and
use its native API
JCLOUDS-744: Upgrade to OkHttp 2.1.0 and use its native API
Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/902f1b41
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/902f1b41
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/902f1b41
Branch: refs/heads/master
Commit: 902f1b4105c2cf72f500e9231fc1c5cdf817f874
Parents: 7775f1a
Author: Ignasi Barrera <na...@apache.org>
Authored: Thu Nov 27 18:06:01 2014 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Thu Nov 27 18:44:08 2014 +0100
----------------------------------------------------------------------
.../ec2/internal/BaseEC2ApiMockTest.java | 6 +-
.../keystone/v2_0/handlers/RetryOnRenew.java | 7 +-
.../v2_0/handlers/RetryOnRenewTest.java | 2 +-
.../v2_0/internal/BaseOpenStackMockTest.java | 2 +-
.../openstack/swift/v1/TempAuthMockTest.java | 10 +-
.../swift/v1/features/ObjectApiMockTest.java | 9 +-
...quentialMultipartUploadStrategyMockTest.java | 2 +-
.../BaseHttpCommandExecutorService.java | 2 +-
...tpCommandExecutorServiceIntegrationTest.java | 11 +-
.../org/jclouds/http/BaseMockWebServerTest.java | 19 +--
drivers/okhttp/README.md | 2 -
.../okhttp/OkHttpCommandExecutorService.java | 168 ++++++++++++++-----
.../OkHttpCommandExecutorServiceModule.java | 57 ++++++-
project/pom.xml | 2 +-
.../aws/ec2/internal/BaseAWSEC2ApiMockTest.java | 9 +-
.../BaseHPCloudObjectStorageMockTest.java | 2 +-
16 files changed, 226 insertions(+), 84 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ApiMockTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ApiMockTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ApiMockTest.java
index 2387ed9..900d217 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ApiMockTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ApiMockTest.java
@@ -63,9 +63,10 @@ public class BaseEC2ApiMockTest {
protected ContextBuilder builder(Properties overrides) {
overrides.setProperty(Constants.PROPERTY_MAX_RETRIES, "1");
+ MockWebServer defaultServer = regionToServers.get(DEFAULT_REGION);
return ContextBuilder.newBuilder(new EC2ApiMetadata())
.credentials(ACCESS_KEY, SECRET_KEY)
- .endpoint("http://localhost:" + regionToServers.get(DEFAULT_REGION).getPort())
+ .endpoint(defaultServer.getUrl("").toString())
.overrides(overrides)
.modules(modules);
}
@@ -101,7 +102,8 @@ public class BaseEC2ApiMockTest {
server.play();
regionToServers.put(region, server);
}
- String regionEndpoint = "http://localhost:" + regionToServers.get(region).getPort();
+ MockWebServer server = regionToServers.get(region);
+ String regionEndpoint = server.getUrl("").toString();
describeRegionsResponse.append("<regionEndpoint>").append(regionEndpoint).append("</regionEndpoint>");
describeRegionsResponse.append("</item>");
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/handlers/RetryOnRenew.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/handlers/RetryOnRenew.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/handlers/RetryOnRenew.java
index 01ce1a2..07983e9 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/handlers/RetryOnRenew.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/handlers/RetryOnRenew.java
@@ -17,7 +17,6 @@
package org.jclouds.openstack.keystone.v2_0.handlers;
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
-import static org.jclouds.http.HttpUtils.releasePayload;
import java.util.concurrent.TimeUnit;
@@ -122,7 +121,11 @@ public class RetryOnRenew implements HttpRetryHandler {
}
return retry;
} finally {
- releasePayload(response);
+ // If the request is failed and is not going to be retried, the
+ // ErrorHandler will be invoked and it might need to read the payload.
+ // For some kind of payload sources, such as the OkHttp Source, if the
+ // payload is released, the upcoming operations will fail.
+ closeClientButKeepContentStream(response);
}
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/handlers/RetryOnRenewTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/handlers/RetryOnRenewTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/handlers/RetryOnRenewTest.java
index 5bc7d81..badf120 100644
--- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/handlers/RetryOnRenewTest.java
+++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/handlers/RetryOnRenewTest.java
@@ -112,7 +112,7 @@ public class RetryOnRenewTest {
BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class);
expect(response.getPayload()).andReturn(Payloads.newStringPayload(
- "The server has waited too long for the request to be sent by the client.")).times(2);
+ "The server has waited too long for the request to be sent by the client.")).times(3);
expect(backoffHandler.shouldRetryRequest(command, response)).andReturn(true).once();
expect(response.getStatusCode()).andReturn(408).once();
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/apis/openstack-keystone/src/test/java/org/jclouds/openstack/v2_0/internal/BaseOpenStackMockTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/v2_0/internal/BaseOpenStackMockTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/v2_0/internal/BaseOpenStackMockTest.java
index d36f7e2..ddb1405 100644
--- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/v2_0/internal/BaseOpenStackMockTest.java
+++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/v2_0/internal/BaseOpenStackMockTest.java
@@ -108,7 +108,7 @@ public class BaseOpenStackMockTest<A extends Closeable> {
* access.json or accessRackspace.json) for the declared service
* endpoints.
*/
- String newBody = urlTokenPattern.matcher(new String(response.getBody())).replaceAll(": \"" + url.toString());
+ String newBody = urlTokenPattern.matcher(new String(response.getBody().readByteArray())).replaceAll(": \"" + url.toString());
response = response.setBody(newBody);
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/TempAuthMockTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/TempAuthMockTest.java b/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/TempAuthMockTest.java
index 140db7d..6a148af 100644
--- a/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/TempAuthMockTest.java
+++ b/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/TempAuthMockTest.java
@@ -43,19 +43,19 @@ public class TempAuthMockTest {
private MockWebServer tempAuthServer;
- public void testGenerateJWTRequest() throws Exception {
+ public void testGenerateJWTRequest() throws Exception {
tempAuthServer.enqueue(new MockResponse().setResponseCode(204)
.addHeader("X-Auth-Token", "token")
- .addHeader("X-Storage-Url", "http://127.0.0.1:" + swiftServer.getPort()));
+ .addHeader("X-Storage-Url", swiftServer.getUrl("").toString()));
swiftServer.enqueue(new MockResponse().setBody("[{\"name\":\"test_container_1\",\"count\":2,\"bytes\":78}]"));
- SwiftApi api = api("http://127.0.0.1:" + tempAuthServer.getPort());
+ SwiftApi api = api(tempAuthServer.getUrl("").toString());
// Region name is derived from the swift server host.
- assertEquals(api.getConfiguredRegions(), ImmutableSet.of("127.0.0.1"));
+ assertEquals(api.getConfiguredRegions(), ImmutableSet.of(tempAuthServer.getHostName()));
- assertTrue(api.getContainerApi("127.0.0.1").list().iterator().hasNext());
+ assertTrue(api.getContainerApi(tempAuthServer.getHostName()).list().iterator().hasNext());
RecordedRequest auth = tempAuthServer.takeRequest();
assertEquals(auth.getMethod(), "GET");
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiMockTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiMockTest.java b/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiMockTest.java
index 8c0e4d1..87166df 100644
--- a/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiMockTest.java
+++ b/apis/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/ObjectApiMockTest.java
@@ -339,7 +339,14 @@ public class ObjectApiMockTest extends BaseOpenStackMockTest<SwiftApi> {
fail("testReplaceTimeout test should have failed with an HttpResponseException.");
} finally {
- server.shutdown();
+ try {
+ server.shutdown();
+ } catch (IOException e) {
+ // MockWebServer 2.1.0 introduces an active wait for its executor termination.
+ // That active wait is a hardcoded value and throws an IOE if the executor has not
+ // terminated in that timeout. It is safe to ignore this exception as the functionality
+ // has been properly verified.
+ }
}
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/strategy/internal/SequentialMultipartUploadStrategyMockTest.java
----------------------------------------------------------------------
diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/strategy/internal/SequentialMultipartUploadStrategyMockTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/strategy/internal/SequentialMultipartUploadStrategyMockTest.java
index 1652b5f..2ad3186 100644
--- a/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/strategy/internal/SequentialMultipartUploadStrategyMockTest.java
+++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/strategy/internal/SequentialMultipartUploadStrategyMockTest.java
@@ -127,7 +127,7 @@ public class SequentialMultipartUploadStrategyMockTest {
public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
MockResponse response = responseQueue.take();
if (response.getBody() != null) {
- String newBody = new String(response.getBody()).replace("URL", url.get().toString());
+ String newBody = new String(response.getBody().readByteArray()).replace("URL", url.get().toString());
response = response.setBody(newBody);
}
return response;
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/core/src/main/java/org/jclouds/http/internal/BaseHttpCommandExecutorService.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/http/internal/BaseHttpCommandExecutorService.java b/core/src/main/java/org/jclouds/http/internal/BaseHttpCommandExecutorService.java
index 6921aa5..1eda6a9 100644
--- a/core/src/main/java/org/jclouds/http/internal/BaseHttpCommandExecutorService.java
+++ b/core/src/main/java/org/jclouds/http/internal/BaseHttpCommandExecutorService.java
@@ -134,6 +134,6 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
protected abstract HttpResponse invoke(Q nativeRequest) throws IOException, InterruptedException;
- protected abstract void cleanup(Q nativeResponse);
+ protected abstract void cleanup(Q nativeRequest);
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/core/src/test/java/org/jclouds/http/BaseHttpCommandExecutorServiceIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/http/BaseHttpCommandExecutorServiceIntegrationTest.java b/core/src/test/java/org/jclouds/http/BaseHttpCommandExecutorServiceIntegrationTest.java
index 29f1778..4f5892c 100644
--- a/core/src/test/java/org/jclouds/http/BaseHttpCommandExecutorServiceIntegrationTest.java
+++ b/core/src/test/java/org/jclouds/http/BaseHttpCommandExecutorServiceIntegrationTest.java
@@ -619,14 +619,21 @@ public abstract class BaseHttpCommandExecutorServiceIntegrationTest extends Base
.method("GET")
.endpoint(server.getUrl("/").toURI())
.build());
- InputStream is = response.getPayload().getInput();
+ InputStream is = response.getPayload().openStream();
long now = System.currentTimeMillis();
is.close();
long diff = System.currentTimeMillis() - now;
assertTrue(diff < timeoutMillis / 2, "expected " + diff + " to be less than " + (timeoutMillis / 2));
} finally {
closeQuietly(client);
- server.shutdown();
+ try {
+ server.shutdown();
+ } catch (IOException ex) {
+ // MockWebServer 2.1.0 introduces an active wait for its executor termination.
+ // That active wait is a hardcoded value and throws an IOE if the executor has not
+ // terminated in that timeout. It is safe to ignore this exception (related to how
+ // throttling works internally in MWS), as the functionality has been properly verified.
+ }
}
}
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/core/src/test/java/org/jclouds/http/BaseMockWebServerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/http/BaseMockWebServerTest.java b/core/src/test/java/org/jclouds/http/BaseMockWebServerTest.java
index 553ff47..6ec09b3 100644
--- a/core/src/test/java/org/jclouds/http/BaseMockWebServerTest.java
+++ b/core/src/test/java/org/jclouds/http/BaseMockWebServerTest.java
@@ -33,14 +33,11 @@ import org.jclouds.providers.AnonymousProviderMetadata;
import org.testng.annotations.BeforeClass;
import com.google.common.collect.ImmutableSet;
-import com.google.common.net.HttpHeaders;
import com.google.inject.Module;
import com.squareup.okhttp.internal.SslContextBuilder;
import com.squareup.okhttp.mockwebserver.Dispatcher;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
-import com.squareup.okhttp.mockwebserver.QueueDispatcher;
-import com.squareup.okhttp.mockwebserver.RecordedRequest;
/**
* Base class for integration tests that use {@link MockWebServer} to verify the
@@ -61,19 +58,6 @@ public abstract class BaseMockWebServerTest {
}
}
- protected static class GlobalChecksRequestDispatcher extends QueueDispatcher {
- @Override
- public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
- MockResponse response = responseQueue.take();
- if (!HttpRequest.NON_PAYLOAD_METHODS.contains(request.getMethod())
- && request.getHeader(HttpHeaders.CONTENT_LENGTH) == null) {
- response.setResponseCode(500);
- response.setBody("No content length!");
- }
- return response;
- }
- }
-
/**
* Creates a {@link MockWebServer} that uses the
* {@link GlobalChecksRequestDispatcher}.
@@ -81,7 +65,6 @@ public abstract class BaseMockWebServerTest {
protected static MockWebServer mockWebServer(MockResponse... responses) throws IOException {
MockWebServer server = new MockWebServer();
server.play();
- server.setDispatcher(new GlobalChecksRequestDispatcher());
for (MockResponse response : responses) {
server.enqueue(response);
}
@@ -120,7 +103,7 @@ public abstract class BaseMockWebServerTest {
* tests.
* <p>
* Unless a concrete HTTP is required, subclasses may want to use the
- * {@link JavaUrlHttpCommandExecutorServiceModule}.
+ * {@link org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule}.
*/
protected abstract Module createConnectionModule();
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/drivers/okhttp/README.md
----------------------------------------------------------------------
diff --git a/drivers/okhttp/README.md b/drivers/okhttp/README.md
index cf41849..2c51352 100644
--- a/drivers/okhttp/README.md
+++ b/drivers/okhttp/README.md
@@ -3,8 +3,6 @@ jclouds OkHttp driver
A driver to use the OkHttp (http://square.github.io/okhttp/) client as an HTTP library in jclouds.
-This driver adds support for use of modern HTTP verbs such as PATCH in providers and APIs, and also supports SPDY.
-
To use the driver, you just need to include the `OkHttpCommandExecutorServiceModule` when creating
the context:
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/OkHttpCommandExecutorService.java
----------------------------------------------------------------------
diff --git a/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/OkHttpCommandExecutorService.java b/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/OkHttpCommandExecutorService.java
index edecc29..d6610fb 100644
--- a/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/OkHttpCommandExecutorService.java
+++ b/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/OkHttpCommandExecutorService.java
@@ -16,78 +16,162 @@
*/
package org.jclouds.http.okhttp;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.net.HttpHeaders.ACCEPT;
+import static com.google.common.net.HttpHeaders.USER_AGENT;
+import static org.jclouds.http.HttpUtils.filterOutContentHeaders;
+import static org.jclouds.io.Payloads.newInputStreamPayload;
+
import java.io.IOException;
-import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URI;
-import java.net.URL;
+import java.util.Map;
-import javax.inject.Named;
-import javax.inject.Singleton;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLContext;
+import okio.BufferedSink;
+import okio.Okio;
+import okio.Source;
+import org.jclouds.JcloudsVersion;
import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.IOExceptionRetryHandler;
import org.jclouds.http.handlers.DelegatingErrorHandler;
import org.jclouds.http.handlers.DelegatingRetryHandler;
+import org.jclouds.http.internal.BaseHttpCommandExecutorService;
import org.jclouds.http.internal.HttpWire;
-import org.jclouds.http.internal.JavaUrlHttpCommandExecutorService;
import org.jclouds.io.ContentMetadataCodec;
+import org.jclouds.io.MutableContentMetadata;
+import org.jclouds.io.Payload;
import com.google.common.base.Function;
-import com.google.common.base.Supplier;
-import com.google.common.net.HttpHeaders;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.inject.Inject;
+import com.squareup.okhttp.Headers;
+import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.RequestBody;
+import com.squareup.okhttp.Response;
-/**
- * Implementation of the <code>HttpCommandExecutorService</code> that uses the
- * OkHttp client to support modern HTTP methods such as PATCH.
- */
-@Singleton
-public class OkHttpCommandExecutorService extends JavaUrlHttpCommandExecutorService {
+public final class OkHttpCommandExecutorService extends BaseHttpCommandExecutorService<Request> {
+
+ private static final String DEFAULT_USER_AGENT = String.format("jclouds/%s java/%s", JcloudsVersion.get(),
+ System.getProperty("java.version"));
+
+ private final Function<URI, Proxy> proxyForURI;
+ private final OkHttpClient globalClient;
@Inject
- public OkHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
+ OkHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
- DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier,
- @Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider, Function<URI, Proxy> proxyForURI)
- throws SecurityException, NoSuchFieldException {
- super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, verifier,
- untrustedSSLContextProvider, proxyForURI);
+ DelegatingErrorHandler errorHandler, HttpWire wire, Function<URI, Proxy> proxyForURI, OkHttpClient okHttpClient) {
+ super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire);
+ this.proxyForURI = proxyForURI;
+ this.globalClient = okHttpClient;
}
@Override
- protected HttpURLConnection initConnection(HttpRequest request) throws IOException {
- OkHttpClient client = new OkHttpClient();
- URL url = request.getEndpoint().toURL();
- client.setProxy(proxyForURI.apply(request.getEndpoint()));
- if (url.getProtocol().equalsIgnoreCase("https")) {
- if (utils.relaxHostname()) {
- client.setHostnameVerifier(verifier);
- }
- if (sslContextSupplier != null) {
- // used for providers which e.g. use certs for authentication (like
- // FGCP) Provider provides SSLContext impl (which inits context with
- // key manager)
- client.setSslSocketFactory(sslContextSupplier.get().getSocketFactory());
- } else if (utils.trustAllCerts()) {
- client.setSslSocketFactory(untrustedSSLContextProvider.get().getSocketFactory());
+ protected Request convert(HttpRequest request) throws IOException, InterruptedException {
+ Request.Builder builder = new Request.Builder();
+
+ builder.url(request.getEndpoint().toString());
+ populateHeaders(request, builder);
+
+ RequestBody body = null;
+ Payload payload = request.getPayload();
+
+ if (payload != null) {
+ Long length = checkNotNull(payload.getContentMetadata().getContentLength(), "payload.getContentLength");
+ if (length > 0) {
+ body = generateRequestBody(request, payload);
}
}
- return client.open(url);
+
+ builder.method(request.getMethod(), body);
+
+ return builder.build();
}
- @Override
- protected void configureRequestHeaders(HttpURLConnection connection, HttpRequest request) {
- super.configureRequestHeaders(connection, request);
+ protected void populateHeaders(HttpRequest request, Request.Builder builder) {
// OkHttp does not set the Accept header if not present in the request.
// Make sure we send a flexible one.
- if (request.getFirstHeaderOrNull(HttpHeaders.ACCEPT) == null) {
- connection.setRequestProperty(HttpHeaders.ACCEPT, "*/*");
+ if (request.getFirstHeaderOrNull(ACCEPT) == null) {
+ builder.addHeader(ACCEPT, "*/*");
+ }
+ if (request.getFirstHeaderOrNull(USER_AGENT) == null) {
+ builder.addHeader(USER_AGENT, DEFAULT_USER_AGENT);
+ }
+ for (Map.Entry<String, String> entry : request.getHeaders().entries()) {
+ builder.addHeader(entry.getKey(), entry.getValue());
+ }
+ if (request.getPayload() != null) {
+ MutableContentMetadata md = request.getPayload().getContentMetadata();
+ for (Map.Entry<String, String> entry : contentMetadataCodec.toHeaders(md).entries()) {
+ builder.addHeader(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
+ protected RequestBody generateRequestBody(final HttpRequest request, final Payload payload) {
+ checkNotNull(payload.getContentMetadata().getContentType(), "payload.getContentType");
+ return new RequestBody() {
+ @Override
+ public void writeTo(BufferedSink sink) throws IOException {
+ Source source = Okio.source(payload.openStream());
+ try {
+ sink.writeAll(source);
+ } catch (IOException ex) {
+ logger.error(ex, "error writing bytes to %s", request.getEndpoint());
+ throw ex;
+ } finally {
+ source.close();
+ }
+ }
+
+ @Override
+ public MediaType contentType() {
+ return MediaType.parse(payload.getContentMetadata().getContentType());
+ }
+ };
+ }
+
+ @Override
+ protected HttpResponse invoke(Request nativeRequest) throws IOException, InterruptedException {
+ OkHttpClient requestScopedClient = globalClient.clone();
+ requestScopedClient.setProxy(proxyForURI.apply(nativeRequest.uri()));
+
+ Response response = requestScopedClient.newCall(nativeRequest).execute();
+
+ HttpResponse.Builder<?> builder = HttpResponse.builder();
+ builder.statusCode(response.code());
+ builder.message(response.message());
+
+ Builder<String, String> headerBuilder = ImmutableMultimap.builder();
+ Headers responseHeaders = response.headers();
+ for (String header : responseHeaders.names()) {
+ headerBuilder.putAll(header, responseHeaders.values(header));
}
+
+ ImmutableMultimap<String, String> headers = headerBuilder.build();
+
+ if (response.code() == 204 && response.body() != null) {
+ response.body().close();
+ } else {
+ Payload payload = newInputStreamPayload(response.body().byteStream());
+ contentMetadataCodec.fromHeaders(payload.getContentMetadata(), headers);
+ builder.payload(payload);
+ }
+
+ builder.headers(filterOutContentHeaders(headers));
+
+ return builder.build();
+ }
+
+ @Override
+ protected void cleanup(Request nativeResponse) {
+
}
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/config/OkHttpCommandExecutorServiceModule.java
----------------------------------------------------------------------
diff --git a/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/config/OkHttpCommandExecutorServiceModule.java b/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/config/OkHttpCommandExecutorServiceModule.java
index 81326af..07a92e7 100644
--- a/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/config/OkHttpCommandExecutorServiceModule.java
+++ b/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/config/OkHttpCommandExecutorServiceModule.java
@@ -16,17 +16,28 @@
*/
package org.jclouds.http.okhttp.config;
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Named;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+
import org.jclouds.http.HttpCommandExecutorService;
+import org.jclouds.http.HttpUtils;
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
import org.jclouds.http.config.SSLModule;
import org.jclouds.http.okhttp.OkHttpCommandExecutorService;
+import com.google.common.base.Supplier;
import com.google.inject.AbstractModule;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
import com.google.inject.Scopes;
+import com.squareup.okhttp.OkHttpClient;
/**
* Configures the {@link OkHttpCommandExecutorService}.
- *
+ *
* Note that this uses threads.
*/
@ConfiguresHttpCommandExecutorService
@@ -36,6 +47,50 @@ public class OkHttpCommandExecutorServiceModule extends AbstractModule {
protected void configure() {
install(new SSLModule());
bind(HttpCommandExecutorService.class).to(OkHttpCommandExecutorService.class).in(Scopes.SINGLETON);
+ bind(OkHttpClient.class).toProvider(OkHttpClientProvider.class).in(Scopes.SINGLETON);
+ }
+
+ private static final class OkHttpClientProvider implements Provider<OkHttpClient> {
+
+ @Inject(optional = true)
+ private Supplier<SSLContext> sslContextSupplier;
+ private final HostnameVerifier verifier;
+ private final Supplier<SSLContext> untrustedSSLContextProvider;
+ private final HttpUtils utils;
+
+ @Inject
+ OkHttpClientProvider(HttpUtils utils, @Named("untrusted") HostnameVerifier verifier,
+ @Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider) {
+ this.utils = utils;
+ this.verifier = verifier;
+ this.untrustedSSLContextProvider = untrustedSSLContextProvider;
+ }
+
+ @Override
+ public OkHttpClient get() {
+ OkHttpClient client = new OkHttpClient();
+ client.setConnectTimeout(utils.getConnectionTimeout(), TimeUnit.MILLISECONDS);
+ client.setReadTimeout(utils.getSocketOpenTimeout(), TimeUnit.MILLISECONDS);
+ // do not follow redirects since https redirects don't work properly
+ // ex. Caused by: java.io.IOException: HTTPS hostname wrong: should be
+ // <adriancole.s3int0.s3-external-3.amazonaws.com>
+ client.setFollowRedirects(false);
+
+ if (utils.relaxHostname()) {
+ client.setHostnameVerifier(verifier);
+ }
+ if (sslContextSupplier != null) {
+ // used for providers which e.g. use certs for authentication (like
+ // FGCP) Provider provides SSLContext impl (which inits context with
+ // key manager)
+ client.setSslSocketFactory(sslContextSupplier.get().getSocketFactory());
+ } else if (utils.trustAllCerts()) {
+ client.setSslSocketFactory(untrustedSSLContextProvider.get().getSocketFactory());
+ }
+
+ return client;
+ }
+
}
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/project/pom.xml
----------------------------------------------------------------------
diff --git a/project/pom.xml b/project/pom.xml
index 0d465d8..1297272 100644
--- a/project/pom.xml
+++ b/project/pom.xml
@@ -206,7 +206,7 @@
<maven.site.url.base>gitsite:git@github.com/jclouds/jclouds-maven-site.git</maven.site.url.base>
<clojure.version>1.3.0</clojure.version>
<guava.version>16.0.1</guava.version>
- <okhttp.version>1.6.0</okhttp.version>
+ <okhttp.version>2.1.0</okhttp.version>
<surefire.version>2.17</surefire.version>
<assertj-core.version>1.6.1</assertj-core.version>
<assertj-guava.version>1.2.0</assertj-guava.version>
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java
index bc21706..f55c949 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java
@@ -75,10 +75,11 @@ public class BaseAWSEC2ApiMockTest {
}
protected ContextBuilder builder(Properties overrides) {
+ MockWebServer defaultServer = regionToServers.get(DEFAULT_REGION);
overrides.setProperty(Constants.PROPERTY_MAX_RETRIES, "1");
return ContextBuilder.newBuilder(new AWSEC2ProviderMetadata())
.credentials(ACCESS_KEY, SECRET_KEY)
- .endpoint("http://localhost:" + regionToServers.get(DEFAULT_REGION).getPort())
+ .endpoint(defaultServer.getUrl("").toString())
.overrides(overrides)
.modules(modules);
}
@@ -102,7 +103,8 @@ public class BaseAWSEC2ApiMockTest {
@Override public String region(String host) {
for (Map.Entry<String, MockWebServer> regionToServer : regionToServers.entrySet()) {
- if (host.equals("localhost:" + regionToServer.getValue().getPort())) {
+ MockWebServer server = regionToServer.getValue();
+ if (host.equals(server.getHostName() + ":" + regionToServer.getValue().getPort())) {
return regionToServer.getKey();
}
}
@@ -141,7 +143,8 @@ public class BaseAWSEC2ApiMockTest {
server.play();
regionToServers.put(region, server);
}
- String regionEndpoint = "http://localhost:" + regionToServers.get(region).getPort();
+ MockWebServer server = regionToServers.get(region);
+ String regionEndpoint = server.getUrl("").toString();
describeRegionsResponse.append("<regionEndpoint>").append(regionEndpoint).append("</regionEndpoint>");
describeRegionsResponse.append("</item>");
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/902f1b41/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/internal/BaseHPCloudObjectStorageMockTest.java
----------------------------------------------------------------------
diff --git a/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/internal/BaseHPCloudObjectStorageMockTest.java b/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/internal/BaseHPCloudObjectStorageMockTest.java
index 8491708..64c410b 100644
--- a/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/internal/BaseHPCloudObjectStorageMockTest.java
+++ b/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/internal/BaseHPCloudObjectStorageMockTest.java
@@ -70,7 +70,7 @@ public class BaseHPCloudObjectStorageMockTest {
public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
MockResponse response = responseQueue.take();
if (response.getBody() != null) {
- String newBody = new String(response.getBody()).replace(":\"URL", ":\"" + url.toString());
+ String newBody = new String(response.getBody().readByteArray()).replace(":\"URL", ":\"" + url.toString());
response = response.setBody(newBody);
}
return response;