mirror of https://github.com/apache/jclouds.git
Issue 211: added gae, but waiting for service to go live
This commit is contained in:
parent
1ca3919442
commit
38b2bef023
|
@ -101,7 +101,7 @@
|
|||
<dependency>
|
||||
<groupId>com.google.appengine</groupId>
|
||||
<artifactId>appengine-tools-api</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<version>1.3.2</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${appengine.home}/lib/appengine-tools-api.jar</systemPath>
|
||||
</dependency>
|
||||
|
|
|
@ -156,12 +156,12 @@
|
|||
<dependency>
|
||||
<groupId>com.google.appengine</groupId>
|
||||
<artifactId>appengine-api-labs</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<version>1.3.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.appengine</groupId>
|
||||
<artifactId>appengine-tools-api</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<version>1.3.2</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${appengine.home}/lib/appengine-tools-api.jar</systemPath>
|
||||
</dependency>
|
||||
|
|
|
@ -146,12 +146,12 @@
|
|||
<dependency>
|
||||
<groupId>com.google.appengine</groupId>
|
||||
<artifactId>appengine-api-labs</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<version>1.3.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.appengine</groupId>
|
||||
<artifactId>appengine-tools-api</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<version>1.3.2</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${appengine.home}/lib/appengine-tools-api.jar</systemPath>
|
||||
</dependency>
|
||||
|
|
|
@ -44,26 +44,27 @@
|
|||
<artifactId>jclouds-joda</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>jclouds-bouncycastle</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.appengine</groupId>
|
||||
<artifactId>appengine-api</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<version>1.3.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.appengine</groupId>
|
||||
<artifactId>appengine-api-stubs</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<version>1.3.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.appengine</groupId>
|
||||
<artifactId>appengine-testing</artifactId>
|
||||
<version>1.3.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.appengine</groupId>
|
||||
<artifactId>appengine-local-runtime</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<version>1.3.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
/**
|
||||
*
|
||||
* 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.gae;
|
||||
|
||||
import static com.google.appengine.api.urlfetch.FetchOptions.Builder.disallowTruncate;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
|
||||
import org.jclouds.concurrent.ConcurrentUtils;
|
||||
import org.jclouds.concurrent.SingleThreaded;
|
||||
import org.jclouds.http.HttpCommand;
|
||||
import org.jclouds.http.HttpCommandExecutorService;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.Payload;
|
||||
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 com.google.appengine.api.urlfetch.FetchOptions;
|
||||
import com.google.appengine.api.urlfetch.HTTPHeader;
|
||||
import com.google.appengine.api.urlfetch.HTTPMethod;
|
||||
import com.google.appengine.api.urlfetch.HTTPRequest;
|
||||
import com.google.appengine.api.urlfetch.HTTPResponse;
|
||||
import com.google.appengine.api.urlfetch.URLFetchService;
|
||||
import com.google.appengine.repackaged.com.google.common.base.Throwables;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.io.Closeables;
|
||||
import com.google.common.util.concurrent.Executors;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* Google App Engine version of {@link HttpCommandExecutorService} using their fetchAsync call
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@SingleThreaded
|
||||
@Singleton
|
||||
public class AsyncGaeHttpCommandExecutorService implements HttpCommandExecutorService {
|
||||
public static final String USER_AGENT = "jclouds/1.0 urlfetch/1.3.2";
|
||||
|
||||
private final URLFetchService urlFetchService;
|
||||
private final ConvertToGaeRequest convertToGaeRequest;
|
||||
private final ConvertToJcloudsResponse convertToJcloudsResponse;
|
||||
|
||||
@Inject
|
||||
public AsyncGaeHttpCommandExecutorService(URLFetchService urlFetchService,
|
||||
ConvertToGaeRequest convertToGaeRequest,
|
||||
ConvertToJcloudsResponse convertToJcloudsResponse) {
|
||||
this.urlFetchService = urlFetchService;
|
||||
this.convertToGaeRequest = convertToGaeRequest;
|
||||
this.convertToJcloudsResponse = convertToJcloudsResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
||||
// TODO: this needs to handle retrying and filtering
|
||||
return Futures.compose(ConcurrentUtils.makeListenable(urlFetchService
|
||||
.fetchAsync(convertToGaeRequest.apply(command.getRequest())), Executors
|
||||
.sameThreadExecutor()), convertToJcloudsResponse);
|
||||
}
|
||||
|
||||
@Singleton
|
||||
public static class ConvertToJcloudsResponse implements Function<HTTPResponse, HttpResponse> {
|
||||
|
||||
@Override
|
||||
public HttpResponse apply(HTTPResponse gaeResponse) {
|
||||
HttpResponse response = new HttpResponse();
|
||||
response.setStatusCode(gaeResponse.getResponseCode());
|
||||
for (HTTPHeader header : gaeResponse.getHeaders()) {
|
||||
response.getHeaders().put(header.getName(), header.getValue());
|
||||
}
|
||||
if (gaeResponse.getContent() != null) {
|
||||
response.setContent(new ByteArrayInputStream(gaeResponse.getContent()));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@Singleton
|
||||
public static class ConvertToGaeRequest implements Function<HttpRequest, HTTPRequest> {
|
||||
/**
|
||||
* byte [] content is replayable and the only content type supportable by GAE. As such, we
|
||||
* convert the original request content to a byte array.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void changeRequestContentToBytes(HttpRequest request) {
|
||||
Payload content = request.getPayload();
|
||||
if (content == null || content instanceof ByteArrayPayload) {
|
||||
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) {
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
} finally {
|
||||
Closeables.closeQuietly(i);
|
||||
}
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Content not supported " + content.getClass());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public HTTPRequest apply(HttpRequest request) {
|
||||
URL url = null;
|
||||
try {
|
||||
url = request.getEndpoint().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
|
||||
FetchOptions options = disallowTruncate();
|
||||
options.followRedirects();
|
||||
|
||||
HTTPRequest gaeRequest = new HTTPRequest(url, HTTPMethod.valueOf(request.getMethod()
|
||||
.toString()), options);
|
||||
|
||||
for (String header : request.getHeaders().keySet()) {
|
||||
for (String value : request.getHeaders().get(header)) {
|
||||
gaeRequest.addHeader(new HTTPHeader(header, value));
|
||||
}
|
||||
}
|
||||
gaeRequest.addHeader(new HTTPHeader(HttpHeaders.USER_AGENT, USER_AGENT));
|
||||
|
||||
if (request.getPayload() != null) {
|
||||
changeRequestContentToBytes(request);
|
||||
gaeRequest.setPayload(((ByteArrayPayload) request.getPayload()).getRawContent());
|
||||
} else {
|
||||
gaeRequest.addHeader(new HTTPHeader(HttpHeaders.CONTENT_LENGTH, "0"));
|
||||
}
|
||||
return gaeRequest;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -33,7 +33,6 @@ import javax.ws.rs.core.HttpHeaders;
|
|||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.concurrent.SingleThreaded;
|
||||
import org.jclouds.http.HttpCommand;
|
||||
import org.jclouds.http.HttpCommandExecutorService;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
|
@ -56,7 +55,6 @@ import com.google.appengine.api.urlfetch.URLFetchService;
|
|||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.io.Closeables;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* Google App Engine version of {@link HttpCommandExecutorService}
|
||||
|
@ -66,7 +64,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||
@SingleThreaded
|
||||
@Singleton
|
||||
public class GaeHttpCommandExecutorService extends BaseHttpCommandExecutorService<HTTPRequest> {
|
||||
public static final String USER_AGENT = "jclouds/1.0 urlfetch/1.3.0";
|
||||
public static final String USER_AGENT = "jclouds/1.0 urlfetch/1.3.2";
|
||||
|
||||
private final URLFetchService urlFetchService;
|
||||
|
||||
|
@ -78,12 +76,6 @@ public class GaeHttpCommandExecutorService extends BaseHttpCommandExecutorServic
|
|||
this.urlFetchService = urlFetchService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
||||
convertHostHeaderToEndPoint(command);
|
||||
return super.submit(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* byte [] content is replayable and the only content type supportable by GAE. As such, we
|
||||
* convert the original request content to a byte array.
|
||||
|
@ -149,22 +141,6 @@ public class GaeHttpCommandExecutorService extends BaseHttpCommandExecutorServic
|
|||
return gaeRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* As host headers are not supported in GAE/J v1.2.1, we'll change the hostname of the
|
||||
* destination to the same value as the host header
|
||||
*
|
||||
* @param command
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static void convertHostHeaderToEndPoint(HttpCommand command) {
|
||||
HttpRequest request = command.getRequest();
|
||||
String hostHeader = request.getFirstHeaderOrNull(HttpHeaders.HOST);
|
||||
if (hostHeader != null) {
|
||||
command.changeSchemeHostAndPortTo(request.getEndpoint().getScheme(), hostHeader, request
|
||||
.getEndpoint().getPort());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nothing to clean up.
|
||||
*/
|
||||
|
|
|
@ -22,7 +22,6 @@ import org.jclouds.concurrent.SingleThreaded;
|
|||
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.gae.GaeHttpCommandExecutorService;
|
||||
import org.jclouds.http.HttpCommandExecutorService;
|
||||
import org.jclouds.http.TransformingHttpCommandExecutorService;
|
||||
|
@ -51,7 +50,6 @@ public class GoogleAppEngineConfigurationModule extends ExecutorServiceModule {
|
|||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
install(new BouncyCastleEncryptionServiceModule());
|
||||
install(new JodaDateServiceModule());
|
||||
bind(HttpCommandExecutorService.class).to(GaeHttpCommandExecutorService.class);
|
||||
bind(TransformingHttpCommandExecutorService.class).to(
|
||||
|
|
|
@ -20,9 +20,7 @@ package org.jclouds.gae;
|
|||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
@ -30,12 +28,10 @@ import java.util.concurrent.TimeoutException;
|
|||
import org.jclouds.gae.config.GoogleAppEngineConfigurationModule;
|
||||
import org.jclouds.http.BaseHttpCommandExecutorServiceTest;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
import org.testng.v6.Maps;
|
||||
|
||||
import com.google.appengine.tools.development.ApiProxyLocalImpl;
|
||||
import com.google.apphosting.api.ApiProxy;
|
||||
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
|
||||
import com.google.appengine.tools.development.testing.LocalURLFetchServiceTestConfig;
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
|
@ -79,21 +75,9 @@ public class GaeHttpCommandExecutorServiceIntegrationTest extends
|
|||
super.testPostBinder();
|
||||
}
|
||||
|
||||
@BeforeTest
|
||||
void validateExecutor() {
|
||||
// ExecutorService executorService = injector.getInstance(ExecutorService.class);
|
||||
// assert executorService.getClass().isAnnotationPresent(SingleThreadCompatible.class) :
|
||||
// Arrays
|
||||
// .asList(executorService.getClass().getAnnotations()).toString()
|
||||
// + executorService.getClass().getName();
|
||||
|
||||
}
|
||||
|
||||
@BeforeMethod
|
||||
void setupApiProxy() {
|
||||
ApiProxy.setEnvironmentForCurrentThread(new TestEnvironment());
|
||||
ApiProxy.setDelegate(new ApiProxyLocalImpl(new File(".")) {
|
||||
});
|
||||
new LocalServiceTestHelper(new LocalURLFetchServiceTestConfig()).setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -177,11 +161,11 @@ public class GaeHttpCommandExecutorServiceIntegrationTest extends
|
|||
}
|
||||
|
||||
@Override
|
||||
@Test(enabled = false)
|
||||
@Test(invocationCount = 50, timeOut = 3000)
|
||||
public void testGetStringWithHeader() throws MalformedURLException, ExecutionException,
|
||||
InterruptedException, TimeoutException {
|
||||
// GAE does not support sending headers in their test stub as of version
|
||||
// 1.2.0
|
||||
setupApiProxy();
|
||||
super.testGetStringWithHeader();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -192,52 +176,12 @@ public class GaeHttpCommandExecutorServiceIntegrationTest extends
|
|||
super.testHead();
|
||||
}
|
||||
|
||||
@Test(enabled = false)
|
||||
@Override
|
||||
@Test(invocationCount = 50, timeOut = 3000)
|
||||
public void testRequestFilter() throws MalformedURLException, ExecutionException,
|
||||
InterruptedException, TimeoutException {
|
||||
// GAE does not support sending headers in their test stub as of version
|
||||
// 1.2.0
|
||||
}
|
||||
|
||||
class TestEnvironment implements ApiProxy.Environment {
|
||||
public String getAppId() {
|
||||
return "Unit Tests";
|
||||
}
|
||||
|
||||
public String getVersionId() {
|
||||
return "1.0";
|
||||
}
|
||||
|
||||
public void setDefaultNamespace(String s) {
|
||||
}
|
||||
|
||||
public String getRequestNamespace() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getDefaultNamespace() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getAuthDomain() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isLoggedIn() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isAdmin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Map<String, Object> getAttributes() {
|
||||
return Maps.newHashMap();
|
||||
}
|
||||
setupApiProxy();
|
||||
super.testRequestFilter();
|
||||
}
|
||||
|
||||
protected Module createConnectionModule() {
|
||||
|
|
|
@ -138,7 +138,7 @@ public class GaeHttpCommandExecutorServiceTest {
|
|||
assert gaeRequest.getPayload() == null;
|
||||
assertEquals(gaeRequest.getHeaders().size(), 2);// content length, user agent
|
||||
assertEquals(gaeRequest.getHeaders().get(0).getName(), HttpHeaders.USER_AGENT);
|
||||
assertEquals(gaeRequest.getHeaders().get(0).getValue(), "jclouds/1.0 urlfetch/1.3.0");
|
||||
assertEquals(gaeRequest.getHeaders().get(0).getValue(), "jclouds/1.0 urlfetch/1.3.2");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue