diff --git a/extensions/ning/pom.xml b/extensions/ning/pom.xml index 5bdfcd29b8..48c5fc3351 100644 --- a/extensions/ning/pom.xml +++ b/extensions/ning/pom.xml @@ -1,26 +1,26 @@ - - 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. - ==================================================================== - ---> - - + 4.0.0 jclouds-extensions-project @@ -40,10 +40,16 @@ - com.ning - async-http-client - 1.0.0-SNAPSHOT - + com.ning + async-http-client + 1.0.0 + + + com.google.collections + google-collections + + + org.mortbay.jetty jetty diff --git a/extensions/ning/src/main/java/org/jclouds/http/ning/NingHttpCommandExecutorService.java b/extensions/ning/src/main/java/org/jclouds/http/ning/NingHttpCommandExecutorService.java index 559e739c60..4c96e6caa6 100644 --- a/extensions/ning/src/main/java/org/jclouds/http/ning/NingHttpCommandExecutorService.java +++ b/extensions/ning/src/main/java/org/jclouds/http/ning/NingHttpCommandExecutorService.java @@ -20,196 +20,177 @@ package org.jclouds.http.ning; import java.io.IOException; +import java.io.OutputStream; +import java.util.List; +import java.util.Map.Entry; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + import javax.inject.Singleton; import javax.ws.rs.HttpMethod; import javax.ws.rs.core.HttpHeaders; -import com.google.common.annotations.VisibleForTesting; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpCommandExecutorService; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpRequestFilter; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.Payload; +import org.jclouds.http.handlers.DelegatingErrorHandler; +import org.jclouds.http.handlers.DelegatingRetryHandler; + import com.google.common.base.Function; import com.google.common.base.Throwables; -import com.google.common.io.ByteStreams; -import com.google.common.io.Closeables; import com.google.common.util.concurrent.AbstractFuture; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import com.ning.http.client.*; - -import java.io.InputStream; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -import com.ning.http.collection.Pair; -import org.jclouds.http.*; - import com.google.inject.Inject; -import org.jclouds.http.handlers.DelegatingErrorHandler; -import org.jclouds.http.handlers.DelegatingRetryHandler; -import org.jclouds.http.payloads.ByteArrayPayload; -import org.jclouds.http.payloads.FilePayload; -import org.jclouds.http.payloads.InputStreamPayload; -import org.jclouds.http.payloads.StringPayload; -import org.jclouds.util.Utils; +import com.ning.http.client.AsyncHttpClient; +import com.ning.http.client.Request; +import com.ning.http.client.Response; +import com.ning.http.client.Request.EntityWriter; /** * Todo Write me - * + * * @author Sam Tunnicliffe * @author Adrian Cole */ public class NingHttpCommandExecutorService implements HttpCommandExecutorService { - public static final String USER_AGENT = "jclouds/1.0 ning http/1.0.0"; + public static final String USER_AGENT = "jclouds/1.0 ning http/1.0.0"; - private final AsyncHttpClient client; - private final ConvertToNingRequest convertToNingRequest; - private final ConvertToJCloudsResponse convertToJCloudsResponse; - private final DelegatingRetryHandler retryHandler; - private final DelegatingErrorHandler errorHandler; + private final AsyncHttpClient client; + private final ConvertToNingRequest convertToNingRequest; + private final ConvertToJCloudsResponse convertToJCloudsResponse; + private final DelegatingRetryHandler retryHandler; + private final DelegatingErrorHandler errorHandler; - @Inject - public NingHttpCommandExecutorService(AsyncHttpClient client, - ConvertToNingRequest convertToNingRequest, - ConvertToJCloudsResponse convertToJCloudsResponse, - DelegatingRetryHandler retryHandler, - DelegatingErrorHandler errorHandler) { - this.client = client; - this.convertToNingRequest = convertToNingRequest; - this.convertToJCloudsResponse = convertToJCloudsResponse; - this.retryHandler = retryHandler; - this.errorHandler = errorHandler; - } + @Inject + public NingHttpCommandExecutorService(AsyncHttpClient client, + ConvertToNingRequest convertToNingRequest, + ConvertToJCloudsResponse convertToJCloudsResponse, DelegatingRetryHandler retryHandler, + DelegatingErrorHandler errorHandler) { + this.client = client; + this.convertToNingRequest = convertToNingRequest; + this.convertToJCloudsResponse = convertToJCloudsResponse; + this.retryHandler = retryHandler; + this.errorHandler = errorHandler; + } - @Override - public ListenableFuture submit(HttpCommand command) { - try { - for(;;) { - Future responseF = client.executeRequest(convertToNingRequest.apply(command.getRequest())); - final HttpResponse httpResponse = convertToJCloudsResponse.apply(responseF.get()); - int statusCode = httpResponse.getStatusCode(); - if (statusCode >= 300) { - if (retryHandler.shouldRetryRequest(command, httpResponse)) { - continue; - } else { - errorHandler.handleError(command, httpResponse); - return wrapAsFuture(httpResponse); - } - } else { - return wrapAsFuture(httpResponse); - } - } - - } catch(IOException e) { - throw Throwables.propagate(e); - } catch(InterruptedException e) { - throw Throwables.propagate(e); - } catch(ExecutionException e) { - throw Throwables.propagate(e); - } - } - - private ListenableFuture wrapAsFuture(final HttpResponse httpResponse) { - return Futures.makeListenable(new AbstractFuture() { - @Override - public HttpResponse get() throws InterruptedException, ExecutionException { - return httpResponse; - } - }); - } - - @Singleton - public static class ConvertToNingRequest implements Function { - - public Request apply(HttpRequest request) { - - for (HttpRequestFilter filter : request.getFilters()) { - filter.filter(request); - } - - AsyncHttpClient client = new AsyncHttpClient(); - AsyncHttpClient.BoundRequestBuilder nativeRequestBuilder; - String endpoint = request.getEndpoint().toASCIIString(); - - if (request.getMethod().equals(HttpMethod.HEAD)) { - nativeRequestBuilder = client.prepareHead(endpoint); - } else if (request.getMethod().equals(HttpMethod.GET)) { - nativeRequestBuilder = client.prepareGet(endpoint); - } else if (request.getMethod().equals(HttpMethod.DELETE)) { - nativeRequestBuilder = client.prepareDelete(endpoint); - } else if (request.getMethod().equals(HttpMethod.PUT)) { - nativeRequestBuilder = client.preparePut(endpoint); - } else if (request.getMethod().equals(HttpMethod.POST)) { - nativeRequestBuilder = client.preparePost(endpoint); + @Override + public ListenableFuture submit(HttpCommand command) { + try { + for (;;) { + Future responseF = client.executeRequest(convertToNingRequest.apply(command + .getRequest())); + final HttpResponse httpResponse = convertToJCloudsResponse.apply(responseF.get()); + int statusCode = httpResponse.getStatusCode(); + if (statusCode >= 300) { + if (retryHandler.shouldRetryRequest(command, httpResponse)) { + continue; + } else { + errorHandler.handleError(command, httpResponse); + return wrapAsFuture(httpResponse); + } } else { - throw new UnsupportedOperationException(request.getMethod()); - } - Payload payload = request.getPayload(); - if(payload != null) { - //changeRequestContentToBytes(request); - setPayload(nativeRequestBuilder, payload); - } else { - nativeRequestBuilder.addHeader(HttpHeaders.CONTENT_LENGTH, "0"); + return wrapAsFuture(httpResponse); } + } - nativeRequestBuilder.addHeader(HttpHeaders.USER_AGENT, USER_AGENT); - for (String header : request.getHeaders().keySet()) { - for (String value : request.getHeaders().get(header)) { - nativeRequestBuilder.addHeader(header, value); - } - } + } catch (IOException e) { + throw Throwables.propagate(e); + } catch (InterruptedException e) { + throw Throwables.propagate(e); + } catch (ExecutionException e) { + throw Throwables.propagate(e); + } + } - return nativeRequestBuilder.build(); - } + private ListenableFuture wrapAsFuture(final HttpResponse httpResponse) { + return Futures.makeListenable(new AbstractFuture() { + @Override + public HttpResponse get() throws InterruptedException, ExecutionException { + return httpResponse; + } + }); + } - @VisibleForTesting - void changeRequestContentToBytes(HttpRequest request) { - Payload content = request.getPayload(); - if (content == null || content instanceof ByteArrayPayload) { - //just return - } else if (content instanceof StringPayload) { - String string = ((StringPayload) content).getRawContent(); - request.setPayload(string.getBytes()); - } else if (content instanceof InputStreamPayload || content instanceof FilePayload) { - InputStream i = content.getContent(); - try { - try { - request.setPayload(ByteStreams.toByteArray(i)); - } catch (IOException e) { - throw Throwables.propagate(e); - } - } finally { - Closeables.closeQuietly(i); - } - } else { - throw new UnsupportedOperationException("Content not supported " + content.getClass()); - } - } + @Singleton + public static class ConvertToNingRequest implements Function { - void setPayload(AsyncHttpClient.BoundRequestBuilder requestBuilder, Payload payload) { - try { - requestBuilder.setBody(ByteStreams.toByteArray(payload.getContent())); - } catch(IOException e) { - throw Throwables.propagate(e); - } - } - } + private static class PayloadEntityWriter implements EntityWriter { + private final Payload payload; - @Singleton - public static class ConvertToJCloudsResponse implements Function { - public HttpResponse apply(Response nativeResponse) { - HttpResponse response = new HttpResponse(); - response.setStatusCode(nativeResponse.getStatusCode()); - for (Pair header : nativeResponse.getHeaders()) { - response.getHeaders().put(header.getFirst(), header.getSecond()); + public PayloadEntityWriter(Payload payload) { + this.payload = payload; + } + + @Override + public void writeEntity(OutputStream out) throws IOException { + payload.writeTo(out); + + } + } + + public Request apply(HttpRequest request) { + + for (HttpRequestFilter filter : request.getFilters()) { + filter.filter(request); + } + + AsyncHttpClient client = new AsyncHttpClient(); + AsyncHttpClient.BoundRequestBuilder nativeRequestBuilder; + String endpoint = request.getEndpoint().toASCIIString(); + if (request.getMethod().equals(HttpMethod.HEAD)) { + nativeRequestBuilder = client.prepareHead(endpoint); + } else if (request.getMethod().equals(HttpMethod.GET)) { + nativeRequestBuilder = client.prepareGet(endpoint); + } else if (request.getMethod().equals(HttpMethod.DELETE)) { + nativeRequestBuilder = client.prepareDelete(endpoint); + } else if (request.getMethod().equals(HttpMethod.PUT)) { + nativeRequestBuilder = client.preparePut(endpoint); + } else if (request.getMethod().equals(HttpMethod.POST)) { + nativeRequestBuilder = client.preparePost(endpoint); + } else { + throw new UnsupportedOperationException(request.getMethod()); + } + Payload payload = request.getPayload(); + if (payload != null) { + setPayload(nativeRequestBuilder, payload); + } else { + nativeRequestBuilder.addHeader(HttpHeaders.CONTENT_LENGTH, "0"); + } + + nativeRequestBuilder.addHeader(HttpHeaders.USER_AGENT, USER_AGENT); + for (String header : request.getHeaders().keySet()) { + for (String value : request.getHeaders().get(header)) { + nativeRequestBuilder.addHeader(header, value); } - try { - String responseBody = nativeResponse.getResponseBody(); - if(responseBody != null) { - response.setContent(Utils.toInputStream(responseBody)); - } - } catch(IOException e) { - throw Throwables.propagate(e); - } - return response; - } - } + } + + return nativeRequestBuilder.build(); + } + + void setPayload(AsyncHttpClient.BoundRequestBuilder requestBuilder, Payload payload) { + requestBuilder.setBody(new PayloadEntityWriter(payload)); + } + } + + @Singleton + public static class ConvertToJCloudsResponse implements Function { + public HttpResponse apply(Response nativeResponse) { + HttpResponse response = new HttpResponse(); + response.setStatusCode(nativeResponse.getStatusCode()); + for (Entry> header : nativeResponse.getHeaders()) { + response.getHeaders().putAll(header.getKey(), header.getValue()); + } + try { + response.setContent(nativeResponse.getResponseBodyAsStream()); + } catch (IOException e) { + throw Throwables.propagate(e); + } + return response; + } + } } diff --git a/extensions/ning/src/main/java/org/jclouds/http/ning/config/NingHttpCommandExecutorServiceModule.java b/extensions/ning/src/main/java/org/jclouds/http/ning/config/NingHttpCommandExecutorServiceModule.java index 291ec7a4e0..5f73811b44 100644 --- a/extensions/ning/src/main/java/org/jclouds/http/ning/config/NingHttpCommandExecutorServiceModule.java +++ b/extensions/ning/src/main/java/org/jclouds/http/ning/config/NingHttpCommandExecutorServiceModule.java @@ -18,19 +18,19 @@ */ package org.jclouds.http.ning.config; -import com.google.inject.Provides; -import com.ning.http.client.AsyncHttpClient; -import com.ning.http.client.AsyncHttpClientConfig; +import javax.inject.Singleton; + import org.jclouds.http.HttpCommandExecutorService; import org.jclouds.http.TransformingHttpCommandExecutorService; import org.jclouds.http.TransformingHttpCommandExecutorServiceImpl; -import org.jclouds.http.ning.NingHttpCommandExecutorService; import org.jclouds.http.config.ConfiguresHttpCommandExecutorService; +import org.jclouds.http.ning.NingHttpCommandExecutorService; import com.google.inject.AbstractModule; +import com.google.inject.Provides; import com.google.inject.Scopes; - -import javax.inject.Singleton; +import com.ning.http.client.AsyncHttpClient; +import com.ning.http.client.AsyncHttpClientConfig; /** * Configures {@link NingHttpCommandExecutorService}. @@ -51,94 +51,10 @@ public class NingHttpCommandExecutorServiceModule extends AbstractModule { @Singleton @Provides AsyncHttpClient provideNingClient() { - AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder(). - setFollowRedirects(true). - build(); - return new AsyncHttpClient(config); + AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder().setFollowRedirects(true) + .build(); + return new AsyncHttpClient(config); } -// -// @Singleton -// @Provides -// HttpParams newBasicHttpParams(HttpUtils utils) { -// BasicHttpParams params = new BasicHttpParams(); -// -// params.setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024) -// .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, true) -// .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true).setParameter( -// CoreProtocolPNames.ORIGIN_SERVER, "jclouds/1.0"); -// -// if (utils.getConnectionTimeout() > 0) { -// params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, utils -// .getConnectionTimeout()); -// } -// -// if (utils.getSocketOpenTimeout() > 0) { -// params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, utils.getSocketOpenTimeout()); -// } -// -// if (utils.getMaxConnections() > 0) -// ConnManagerParams.setMaxTotalConnections(params, utils.getMaxConnections()); -// -// if (utils.getMaxConnectionsPerHost() > 0) { -// ConnPerRoute connectionsPerRoute = new ConnPerRouteBean(utils.getMaxConnectionsPerHost()); -// ConnManagerParams.setMaxConnectionsPerRoute(params, connectionsPerRoute); -// } -// HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); -// return params; -// } -// -// @Singleton -// @Provides -// X509HostnameVerifier newHostnameVerifier(HttpUtils utils) { -// return utils.relaxHostname() ? SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER -// : SSLSocketFactory.STRICT_HOSTNAME_VERIFIER; -// } -// -// @Singleton -// @Provides -// ClientConnectionManager newClientConnectionManager(HttpParams params, -// X509HostnameVerifier verifier, Closer closer) throws NoSuchAlgorithmException, -// KeyManagementException { -// -// SchemeRegistry schemeRegistry = new SchemeRegistry(); -// -// Scheme http = new Scheme("http", PlainSocketFactory.getSocketFactory(), 80); -// SSLContext context = SSLContext.getInstance("TLS"); -// -// context.init(null, null, null); -// SSLSocketFactory sf = new SSLSocketFactory(context); -// sf.setHostnameVerifier(verifier); -// -// Scheme https = new Scheme("https", sf, 443); -// -// SchemeRegistry sr = new SchemeRegistry(); -// sr.register(http); -// sr.register(https); -// -// schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); -// schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); -// final ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry); -// closer.addToClose(new Closeable() { -// @Override -// public void close() throws IOException { -// cm.shutdown(); -// } -// }); -// return cm; -// } -// -// @Provides -// @Singleton -// HttpClient newDefaultHttpClient(HttpUtils utils, BasicHttpParams params, -// ClientConnectionManager cm) { -// DefaultHttpClient client = new DefaultHttpClient(cm, params); -// if (utils.useSystemProxies()) { -// ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner(client -// .getConnectionManager().getSchemeRegistry(), ProxySelector.getDefault()); -// client.setRoutePlanner(routePlanner); -// } -// return client; -// } protected void bindClient() { bind(HttpCommandExecutorService.class).to(NingHttpCommandExecutorService.class).in( diff --git a/extensions/ning/src/test/java/org/jclouds/http/ning/NingHttpCommandExecutorServiceTest.java b/extensions/ning/src/test/java/org/jclouds/http/ning/NingHttpCommandExecutorServiceTest.java index 2d8b598345..defcf61a35 100644 --- a/extensions/ning/src/test/java/org/jclouds/http/ning/NingHttpCommandExecutorServiceTest.java +++ b/extensions/ning/src/test/java/org/jclouds/http/ning/NingHttpCommandExecutorServiceTest.java @@ -18,9 +18,11 @@ */ package org.jclouds.http.ning; +import static org.jclouds.Constants.PROPERTY_CONNECTION_TIMEOUT; import static org.jclouds.Constants.PROPERTY_IO_WORKER_THREADS; -import static org.jclouds.Constants.*; +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_SO_TIMEOUT; import static org.jclouds.Constants.PROPERTY_USER_THREADS; import static org.testng.Assert.assertEquals; @@ -28,13 +30,9 @@ import java.net.MalformedURLException; import java.util.Properties; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicInteger; -import com.google.common.collect.ImmutableMap; import org.jclouds.http.BaseHttpCommandExecutorServiceIntegrationTest; import org.jclouds.http.ning.config.NingHttpCommandExecutorServiceModule; -import org.jclouds.http.options.GetOptions; -import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -42,36 +40,46 @@ import com.google.inject.Module; /** * Tests the functionality of the {@link ApacheHCHttpCommandExecutorService} - * + * * @author Adrian Cole */ @Test -public class NingHttpCommandExecutorServiceTest extends BaseHttpCommandExecutorServiceIntegrationTest { - static { - System.setProperty("http.conn-manager.timeout", 1000 + ""); - } +public class NingHttpCommandExecutorServiceTest extends + BaseHttpCommandExecutorServiceIntegrationTest { + static { + System.setProperty("http.conn-manager.timeout", 1000 + ""); + } - protected Module createConnectionModule() { - return new NingHttpCommandExecutorServiceModule(); - } + @DataProvider(name = "gets") + @Override + // ning doesn't support spaces + public Object[][] createData() { + return new Object[][] { { "object" }, { "/path" }, { "unic₪de" }, { "qu?stion" } }; + } - protected void addConnectionProperties(Properties props) { - props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_CONTEXT, 20 + ""); - props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_HOST, 0 + ""); - props.setProperty(PROPERTY_CONNECTION_TIMEOUT, 100 + ""); - props.setProperty(PROPERTY_SO_TIMEOUT, 100 + ""); - props.setProperty(PROPERTY_IO_WORKER_THREADS, 3 + ""); - props.setProperty(PROPERTY_USER_THREADS, 0 + ""); - } + protected Module createConnectionModule() { + return new NingHttpCommandExecutorServiceModule(); + } - @Test(invocationCount = 1, timeOut = 50000) - public void testSpaceInUri() throws MalformedURLException, ExecutionException, + protected void addConnectionProperties(Properties props) { + props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_CONTEXT, 20 + ""); + props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_HOST, 0 + ""); + props.setProperty(PROPERTY_CONNECTION_TIMEOUT, 100 + ""); + props.setProperty(PROPERTY_SO_TIMEOUT, 100 + ""); + props.setProperty(PROPERTY_IO_WORKER_THREADS, 3 + ""); + props.setProperty(PROPERTY_USER_THREADS, 0 + ""); + } + + // ning doesn't support spaces + @Test(invocationCount = 1, expectedExceptions = RuntimeException.class) + public void testSpaceInUri() throws MalformedURLException, ExecutionException, InterruptedException, TimeoutException { - assertEquals(client.synch("sp ace").trim(), XML); - } + assertEquals(client.synch("sp ace").trim(), XML); + } - @Override - public void testGetBigFile() throws MalformedURLException, ExecutionException, InterruptedException, TimeoutException { - //don't run it - } + @Override + public void testGetBigFile() throws MalformedURLException, ExecutionException, + InterruptedException, TimeoutException { + // don't run it + } } \ No newline at end of file diff --git a/extensions/pom.xml b/extensions/pom.xml index 226510fcd2..159afdb32c 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -34,6 +34,7 @@ gae apachehc + ning joda bouncycastle log4j