mirror of https://github.com/apache/jclouds.git
issue 107: revised hc module, and included it in the enterprise config
This commit is contained in:
parent
4582c57c72
commit
268bc2ec04
|
@ -5,6 +5,7 @@ and reuse your java development skills. Our api allows you to freedom to use
|
|||
portable abstractions or cloud-specific features.
|
||||
|
||||
our current version is 1.0-beta-3
|
||||
our dev version is 1.0-SNAPSHOT
|
||||
|
||||
our compute api supports: ec2, rackspace, rimuhosting, vcloud, terremark,
|
||||
hosting.com
|
||||
|
|
|
@ -137,7 +137,7 @@ public abstract class BaseJettyTest {
|
|||
protected Injector injector;
|
||||
private AtomicInteger cycle = new AtomicInteger(0);
|
||||
private Server server2;
|
||||
private RestContext<IntegrationTestAsyncClient, IntegrationTestClient> context;
|
||||
protected RestContext<IntegrationTestAsyncClient, IntegrationTestClient> context;
|
||||
private int testPort;
|
||||
static final Pattern actionPattern = Pattern.compile("/objects/(.*)/action/([a-z]*);?(.*)");
|
||||
|
||||
|
|
|
@ -19,20 +19,20 @@
|
|||
|
||||
package org.jclouds.http.apachehc;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.apache.http.HttpEntityEnclosingRequest;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpVersion;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.conn.ClientConnectionManager;
|
||||
import org.apache.http.conn.params.ConnManagerParams;
|
||||
import org.apache.http.conn.params.ConnPerRoute;
|
||||
import org.apache.http.conn.params.ConnPerRouteBean;
|
||||
|
@ -43,19 +43,16 @@ import org.apache.http.conn.ssl.SSLSocketFactory;
|
|||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
|
||||
import org.apache.http.params.BasicHttpParams;
|
||||
import org.apache.http.params.HttpParams;
|
||||
import org.apache.http.params.HttpProtocolParams;
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
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 com.google.common.base.Function;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
|
@ -66,8 +63,11 @@ import com.google.inject.Inject;
|
|||
*/
|
||||
public class ApacheHCHttpCommandExecutorService extends
|
||||
BaseHttpCommandExecutorService<HttpEntityEnclosingRequest> {
|
||||
|
||||
private final ConcurrentMap<URI, HttpClient> poolMap;
|
||||
@VisibleForTesting
|
||||
boolean isOpen = true;
|
||||
private final BasicHttpParams params;
|
||||
private final ThreadSafeClientConnManager cm;
|
||||
private final ApacheHCUtils utils;
|
||||
|
||||
@Inject
|
||||
ApacheHCHttpCommandExecutorService(
|
||||
|
@ -76,58 +76,64 @@ public class ApacheHCHttpCommandExecutorService extends
|
|||
DelegatingErrorHandler errorHandler,
|
||||
HttpWire wire,
|
||||
@Named(Constants.PROPERTY_MAX_CONNECTIONS_PER_CONTEXT) final int globalMaxConnections,
|
||||
@Named(Constants.PROPERTY_MAX_CONNECTIONS_PER_HOST) final int globalMaxConnectionsPerHost) {
|
||||
@Named(Constants.PROPERTY_MAX_CONNECTIONS_PER_HOST) final int globalMaxConnectionsPerHost,
|
||||
ApacheHCUtils utils) {
|
||||
super(ioWorkerExecutor, retryHandler, errorHandler, wire);
|
||||
checkArgument(globalMaxConnections > 0, Constants.PROPERTY_MAX_CONNECTIONS_PER_CONTEXT
|
||||
+ " must be greater than zero");
|
||||
checkArgument(globalMaxConnectionsPerHost > 0, Constants.PROPERTY_MAX_CONNECTIONS_PER_HOST
|
||||
+ " must be greater than zero");
|
||||
poolMap = new MapMaker().makeComputingMap(new Function<URI, HttpClient>() {
|
||||
public HttpClient apply(URI endPoint) {
|
||||
checkArgument(endPoint.getHost() != null, String.format(
|
||||
"endPoint.getHost() is null for %s", endPoint));
|
||||
HttpParams params = new BasicHttpParams();
|
||||
try {
|
||||
// TODO: have this use our executor service
|
||||
// TODO: implement wire logging
|
||||
this.utils = utils;
|
||||
params = new BasicHttpParams();
|
||||
// TODO: have this use our executor service, if possible
|
||||
if (globalMaxConnections > 0)
|
||||
ConnManagerParams.setMaxTotalConnections(params, globalMaxConnections);
|
||||
if (globalMaxConnectionsPerHost > 0) {
|
||||
ConnPerRoute connectionsPerRoute = new ConnPerRouteBean(globalMaxConnectionsPerHost);
|
||||
ConnManagerParams.setMaxConnectionsPerRoute(params, connectionsPerRoute);
|
||||
}
|
||||
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
|
||||
SchemeRegistry schemeRegistry = new SchemeRegistry();
|
||||
if (endPoint.getScheme().equals("http"))
|
||||
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(),
|
||||
80));
|
||||
else
|
||||
schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(),
|
||||
443));
|
||||
ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
|
||||
return new DefaultHttpClient(cm, params);
|
||||
} catch (RuntimeException e) {
|
||||
logger.error(e, "error creating entry for %s", endPoint);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
});
|
||||
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
|
||||
schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
|
||||
cm = new ThreadSafeClientConnManager(params, schemeRegistry);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpEntityEnclosingRequest convert(HttpRequest request) throws IOException {
|
||||
return ApacheHCUtils.convertToApacheRequest(request);
|
||||
return utils.convertToApacheRequest(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpResponse invoke(HttpEntityEnclosingRequest nativeRequest) throws IOException {
|
||||
checkState(isOpen, "http executor not open");
|
||||
org.apache.http.HttpResponse nativeResponse = executeRequest(nativeRequest);
|
||||
return utils.convertToJCloudsResponse(nativeResponse);
|
||||
}
|
||||
|
||||
private org.apache.http.HttpResponse executeRequest(HttpEntityEnclosingRequest nativeRequest)
|
||||
throws IOException, ClientProtocolException {
|
||||
URI endpoint = URI.create(nativeRequest.getRequestLine().getUri());
|
||||
HttpClient client = poolMap.get(HttpUtils.createBaseEndpointFor(endpoint));
|
||||
assert (client != null) : "pool for endpoint null " + endpoint;
|
||||
HttpClient client = new DefaultHttpClient(cm, params);
|
||||
HttpHost host = new HttpHost(endpoint.getHost(), endpoint.getPort(), endpoint.getScheme());
|
||||
org.apache.http.HttpResponse nativeResponse = client.execute(host, nativeRequest);
|
||||
return ApacheHCUtils.convertToJCloudsResponse(nativeResponse);
|
||||
return nativeResponse;
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void close() {
|
||||
// TODO test
|
||||
isOpen = false;
|
||||
cm.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
close();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cleanup(HttpEntityEnclosingRequest nativeResponse) {
|
||||
// TODO
|
||||
// No cleanup necessary
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,13 @@
|
|||
package org.jclouds.http.apachehc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Singleton;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
|
||||
import org.apache.http.Header;
|
||||
|
@ -36,15 +39,20 @@ import org.apache.http.message.BasicHttpEntityEnclosingRequest;
|
|||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.Payload;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ApacheHCUtils {
|
||||
public static final String USER_AGENT = "jclouds/1.0 httpclient/4.0.1";
|
||||
|
||||
public static HttpEntityEnclosingRequest convertToApacheRequest(HttpRequest request) {
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
public HttpEntityEnclosingRequest convertToApacheRequest(HttpRequest request) {
|
||||
|
||||
String uri = request.getEndpoint().toASCIIString();
|
||||
if (request.getEndpoint().getQuery() != null)
|
||||
|
@ -77,7 +85,7 @@ public class ApacheHCUtils {
|
|||
return apacheRequest;
|
||||
}
|
||||
|
||||
public static void addEntityForContent(HttpEntityEnclosingRequest apacheRequest, Object content,
|
||||
public void addEntityForContent(HttpEntityEnclosingRequest apacheRequest, Object content,
|
||||
String contentType, long length) {
|
||||
if (content instanceof InputStream) {
|
||||
InputStream inputStream = (InputStream) content;
|
||||
|
@ -109,11 +117,12 @@ public class ApacheHCUtils {
|
|||
assert (apacheRequest.getEntity() != null);
|
||||
}
|
||||
|
||||
public static HttpResponse convertToJCloudsResponse(org.apache.http.HttpResponse apacheResponse)
|
||||
public HttpResponse convertToJCloudsResponse(org.apache.http.HttpResponse apacheResponse)
|
||||
throws IOException {
|
||||
HttpResponse response = new HttpResponse();
|
||||
if (apacheResponse.getEntity() != null) {
|
||||
response.setContent(apacheResponse.getEntity().getContent());
|
||||
response
|
||||
.setContent(new ConsumeOnCloseInputStream(apacheResponse.getEntity().getContent()));
|
||||
}
|
||||
for (Header header : apacheResponse.getAllHeaders()) {
|
||||
response.getHeaders().put(header.getName(), header.getValue());
|
||||
|
@ -122,4 +131,32 @@ public class ApacheHCUtils {
|
|||
response.setMessage(apacheResponse.getStatusLine().getReasonPhrase());
|
||||
return response;
|
||||
}
|
||||
|
||||
class ConsumeOnCloseInputStream extends FilterInputStream {
|
||||
|
||||
protected ConsumeOnCloseInputStream(InputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
boolean closed;
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
if (!closed) {
|
||||
int result = 0;
|
||||
while (result != -1) {
|
||||
result = read();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.warn(e, "error reading stream");
|
||||
} finally {
|
||||
closed = true;
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -18,11 +18,6 @@
|
|||
*/
|
||||
package org.jclouds.http.apachehc;
|
||||
|
||||
import static org.jclouds.Constants.PROPERTY_IO_WORKER_THREADS;
|
||||
import static org.jclouds.Constants.PROPERTY_MAX_CONNECTIONS_PER_CONTEXT;
|
||||
import static org.jclouds.Constants.PROPERTY_MAX_CONNECTIONS_PER_HOST;
|
||||
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.http.BaseHttpCommandExecutorServiceTest;
|
||||
|
@ -44,11 +39,7 @@ public class ApacheHCHttpCommandExecutorServiceTest extends BaseHttpCommandExecu
|
|||
}
|
||||
|
||||
protected void addConnectionProperties(Properties props) {
|
||||
props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_CONTEXT, 50 + "");
|
||||
props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_HOST, 50 + "");
|
||||
// IO workers not used in this executor
|
||||
props.setProperty(PROPERTY_IO_WORKER_THREADS, 0 + "");
|
||||
props.setProperty(PROPERTY_USER_THREADS, 5 + "");
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -47,13 +47,11 @@
|
|||
<artifactId>jclouds-bouncycastle</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- not reliable enough yet
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-httpnio</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<artifactId>jetty</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
-->
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -24,6 +24,8 @@ import org.jclouds.concurrent.config.ConfiguresExecutorService;
|
|||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||
import org.jclouds.date.joda.config.JodaDateServiceModule;
|
||||
import org.jclouds.encryption.bouncycastle.config.BouncyCastleEncryptionServiceModule;
|
||||
import org.jclouds.http.apachehc.config.ApacheHCHttpCommandExecutorServiceModule;
|
||||
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
|
||||
|
||||
/**
|
||||
* Configures Enterprise-grade components
|
||||
|
@ -32,6 +34,7 @@ import org.jclouds.encryption.bouncycastle.config.BouncyCastleEncryptionServiceM
|
|||
*
|
||||
*/
|
||||
@ConfiguresExecutorService
|
||||
@ConfiguresHttpCommandExecutorService
|
||||
public class EnterpriseConfigurationModule extends ExecutorServiceModule {
|
||||
|
||||
public EnterpriseConfigurationModule(ExecutorService userThreads, ExecutorService ioThreads) {
|
||||
|
@ -46,6 +49,7 @@ public class EnterpriseConfigurationModule extends ExecutorServiceModule {
|
|||
protected void configure() {
|
||||
install(new BouncyCastleEncryptionServiceModule());
|
||||
install(new JodaDateServiceModule());
|
||||
install(new ApacheHCHttpCommandExecutorServiceModule());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.enterprise.config;
|
||||
|
||||
import static org.jclouds.Constants.PROPERTY_IO_WORKER_THREADS;
|
||||
import static org.jclouds.Constants.PROPERTY_MAX_CONNECTIONS_PER_CONTEXT;
|
||||
import static org.jclouds.Constants.PROPERTY_MAX_CONNECTIONS_PER_HOST;
|
||||
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.http.BaseHttpCommandExecutorServiceTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
* Tests the functionality of the {@link EnterpriseConfigurationModule}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test
|
||||
public class EnterpriseConfigurationModuleTest extends BaseHttpCommandExecutorServiceTest {
|
||||
|
||||
protected Module createConnectionModule() {
|
||||
return new EnterpriseConfigurationModule();
|
||||
}
|
||||
|
||||
protected void addConnectionProperties(Properties props) {
|
||||
props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_CONTEXT, 50 + "");
|
||||
props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_HOST, 50 + "");
|
||||
// IO workers not used in this executor
|
||||
props.setProperty(PROPERTY_IO_WORKER_THREADS, 0 + "");
|
||||
props.setProperty(PROPERTY_USER_THREADS, 5 + "");
|
||||
}
|
||||
|
||||
}
|
|
@ -41,7 +41,12 @@
|
|||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-enterprise</artifactId>
|
||||
<artifactId>jclouds-joda</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-bouncycastle</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -20,7 +20,9 @@ package org.jclouds.gae.config;
|
|||
|
||||
import org.jclouds.concurrent.SingleThreaded;
|
||||
import org.jclouds.concurrent.config.ConfiguresExecutorService;
|
||||
import org.jclouds.enterprise.config.EnterpriseConfigurationModule;
|
||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||
import org.jclouds.date.joda.config.JodaDateServiceModule;
|
||||
import org.jclouds.encryption.bouncycastle.config.BouncyCastleEncryptionServiceModule;
|
||||
import org.jclouds.gae.GaeHttpCommandExecutorService;
|
||||
import org.jclouds.http.HttpCommandExecutorService;
|
||||
import org.jclouds.http.TransformingHttpCommandExecutorService;
|
||||
|
@ -40,7 +42,7 @@ import com.google.inject.Provides;
|
|||
@ConfiguresHttpCommandExecutorService
|
||||
@ConfiguresExecutorService
|
||||
@SingleThreaded
|
||||
public class GoogleAppEngineConfigurationModule extends EnterpriseConfigurationModule {
|
||||
public class GoogleAppEngineConfigurationModule extends ExecutorServiceModule {
|
||||
|
||||
public GoogleAppEngineConfigurationModule() {
|
||||
super(Executors.sameThreadExecutor(), Executors.sameThreadExecutor());
|
||||
|
@ -49,6 +51,8 @@ public class GoogleAppEngineConfigurationModule extends EnterpriseConfigurationM
|
|||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
install(new BouncyCastleEncryptionServiceModule());
|
||||
install(new JodaDateServiceModule());
|
||||
bind(HttpCommandExecutorService.class).to(GaeHttpCommandExecutorService.class);
|
||||
bind(TransformingHttpCommandExecutorService.class).to(
|
||||
TransformingHttpCommandExecutorServiceImpl.class);
|
||||
|
|
Loading…
Reference in New Issue