diff --git a/gae/pom.xml b/extensions/gae/pom.xml
similarity index 94%
rename from gae/pom.xml
rename to extensions/gae/pom.xml
index f381b8034f..fada3c9ae7 100644
--- a/gae/pom.xml
+++ b/extensions/gae/pom.xml
@@ -31,7 +31,7 @@
org.jclouds
jclouds-project
1.0-SNAPSHOT
- ../project/pom.xml
+ ../../project/pom.xml
4.0.0
org.jclouds
@@ -41,9 +41,9 @@
Google App Engine Components
- scm:svn:http://jclouds.googlecode.com/svn/trunk/gae
- scm:svn:https://jclouds.googlecode.com/svn/trunk/gae
- http://jclouds.googlecode.com/svn/trunk/gae
+ scm:svn:http://jclouds.googlecode.com/svn/trunk/extensions/gae
+ scm:svn:https://jclouds.googlecode.com/svn/trunk/extensions/gae
+ http://jclouds.googlecode.com/svn/trunk/extensions/gae
diff --git a/gae/src/main/java/org/jclouds/gae/config/URLFetchServiceClientModule.java b/extensions/gae/src/main/java/org/jclouds/gae/config/URLFetchServiceClientModule.java
similarity index 100%
rename from gae/src/main/java/org/jclouds/gae/config/URLFetchServiceClientModule.java
rename to extensions/gae/src/main/java/org/jclouds/gae/config/URLFetchServiceClientModule.java
diff --git a/gae/src/test/java/org/jclouds/gae/URLFetchServiceClientIntegrationTest.java b/extensions/gae/src/test/java/org/jclouds/gae/URLFetchServiceClientIntegrationTest.java
similarity index 100%
rename from gae/src/test/java/org/jclouds/gae/URLFetchServiceClientIntegrationTest.java
rename to extensions/gae/src/test/java/org/jclouds/gae/URLFetchServiceClientIntegrationTest.java
diff --git a/gae/src/test/java/org/jclouds/gae/config/URLFetchServiceClientModuleTest.java b/extensions/gae/src/test/java/org/jclouds/gae/config/URLFetchServiceClientModuleTest.java
similarity index 100%
rename from gae/src/test/java/org/jclouds/gae/config/URLFetchServiceClientModuleTest.java
rename to extensions/gae/src/test/java/org/jclouds/gae/config/URLFetchServiceClientModuleTest.java
diff --git a/gae/src/main/java/org/jclouds/gae/URLFetchServiceClient.java b/gae/src/main/java/org/jclouds/gae/URLFetchServiceClient.java
deleted file mode 100644
index 0e1e110929..0000000000
--- a/gae/src/main/java/org/jclouds/gae/URLFetchServiceClient.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Adrian Cole
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.List;
-
-import org.apache.commons.io.IOUtils;
-import org.jclouds.http.BaseHttpFutureCommandClient;
-import org.jclouds.http.HttpFutureCommand;
-import org.jclouds.http.HttpFutureCommandClient;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpRequestFilter;
-import org.jclouds.http.HttpResponse;
-
-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.common.annotations.VisibleForTesting;
-import com.google.inject.Inject;
-
-/**
- * Google App Engine version of {@link HttpFutureCommandClient}
- *
- * @author Adrian Cole
- */
-public class URLFetchServiceClient extends BaseHttpFutureCommandClient {
- private final URLFetchService urlFetchService;
-
- @Inject
- public URLFetchServiceClient(URL target, URLFetchService urlFetchService)
- throws MalformedURLException {
- super(target);
- this.urlFetchService = urlFetchService;
- }
-
- public void submit(HttpFutureCommand> command) {
- HttpRequest request = command.getRequest();
- HTTPResponse gaeResponse = null;
- try {
- for (HttpRequestFilter filter : requestFilters) {
- filter.filter(request);
- }
- HttpResponse response = null;
- for (;;) {
- logger.trace("%1s - converting request %2s", target, request);
- HTTPRequest gaeRequest = convert(request);
- if (logger.isTraceEnabled())
- logger.trace("%1s - submitting request %2s, headers: %3s",
- target, gaeRequest.getURL(),
- headersAsString(gaeRequest.getHeaders()));
- gaeResponse = this.urlFetchService.fetch(gaeRequest);
- if (logger.isTraceEnabled())
- logger.trace(
- "%1s - received response code %2s, headers: %3s",
- target, gaeResponse.getResponseCode(),
- headersAsString(gaeResponse.getHeaders()));
- response = convert(gaeResponse);
- if (isRetryable(command, response))
- continue;
- break;
- }
- handleResponse(command, response);
- } catch (Exception e) {
- if (gaeResponse != null && gaeResponse.getContent() != null) {
- logger.error(e,
- "error encountered during the execution: %1s%n%2s",
- gaeResponse, new String(gaeResponse.getContent()));
- }
- command.setException(e);
- }
- }
-
- String headersAsString(List headers) {
- StringBuilder builder = new StringBuilder("");
- for (HTTPHeader header : headers)
- builder.append("[").append(header.getName()).append("=").append(
- header.getValue()).append("],");
- return builder.toString();
- }
-
- /**
- * 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) throws IOException {
- Object content = request.getPayload();
- if (content == null || content instanceof byte[]) {
- return;
- } else if (content instanceof String) {
- String string = (String) content;
- request.setPayload(string.getBytes());
- } else if (content instanceof InputStream || content instanceof File) {
- InputStream i = content instanceof InputStream ? (InputStream) content
- : new FileInputStream((File) content);
- try {
- request.setPayload(IOUtils.toByteArray(i));
- } finally {
- IOUtils.closeQuietly(i);
- }
- } else {
- throw new UnsupportedOperationException("Content not supported "
- + content.getClass());
- }
-
- }
-
- @VisibleForTesting
- HttpResponse convert(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;
- }
-
- @VisibleForTesting
- HTTPRequest convert(HttpRequest request) throws IOException {
- URL url = new URL(target, request.getUri());
- HTTPRequest gaeRequest = new HTTPRequest(url, HTTPMethod
- .valueOf(request.getMethod()), disallowTruncate());
- for (String header : request.getHeaders().keySet()) {
- for (String value : request.getHeaders().get(header))
- gaeRequest.addHeader(new HTTPHeader(header, value));
- }
- if (request.getPayload() != null) {
- changeRequestContentToBytes(request);
- gaeRequest.setPayload((byte[]) request.getPayload());
- }
- return gaeRequest;
- }
-}
diff --git a/gae/src/test/java/org/jclouds/gae/URLFetchServiceClientTest.java b/gae/src/test/java/org/jclouds/gae/URLFetchServiceClientTest.java
deleted file mode 100644
index 8b3229667b..0000000000
--- a/gae/src/test/java/org/jclouds/gae/URLFetchServiceClientTest.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/**
- *
- * Copyright (C) 2009 Adrian Cole
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 org.easymock.EasyMock.expect;
-import static org.easymock.classextension.EasyMock.createMock;
-import static org.easymock.classextension.EasyMock.createNiceMock;
-import static org.easymock.classextension.EasyMock.replay;
-import static org.testng.Assert.assertEquals;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import org.apache.commons.io.IOUtils;
-import org.jclouds.http.HttpHeaders;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.Parameters;
-import org.testng.annotations.Test;
-
-import com.google.appengine.api.urlfetch.HTTPHeader;
-import com.google.appengine.api.urlfetch.HTTPRequest;
-import com.google.appengine.api.urlfetch.HTTPResponse;
-import com.google.appengine.api.urlfetch.URLFetchService;
-
-/**
- *
- * @author Adrian Cole
- */
-@Test
-public class URLFetchServiceClientTest {
- URLFetchServiceClient client;
- URL url;
-
- @BeforeTest
- void setupClient() throws MalformedURLException {
- url = new URL("http://localhost:80");
- client = new URLFetchServiceClient(url,
- createNiceMock(URLFetchService.class));
- }
-
- @Test
- void testConvertWithHeaders() {
- HTTPResponse gaeResponse = createMock(HTTPResponse.class);
- expect(gaeResponse.getResponseCode()).andReturn(200);
- List headers = new ArrayList();
- headers.add(new HTTPHeader(HttpHeaders.CONTENT_TYPE, "text/xml"));
- expect(gaeResponse.getHeaders()).andReturn(headers);
- expect(gaeResponse.getContent()).andReturn(null).atLeastOnce();
- replay(gaeResponse);
- HttpResponse response = client.convert(gaeResponse);
- assertEquals(response.getStatusCode(), 200);
- assertEquals(response.getContent(), null);
- assertEquals(response.getHeaders().size(), 1);
- assertEquals(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE),
- "text/xml");
- }
-
- @Test
- void testConvertWithContent() throws IOException {
- HTTPResponse gaeResponse = createMock(HTTPResponse.class);
- expect(gaeResponse.getResponseCode()).andReturn(200);
- List headers = new ArrayList();
- headers.add(new HTTPHeader(HttpHeaders.CONTENT_TYPE, "text/xml"));
- expect(gaeResponse.getHeaders()).andReturn(headers);
- expect(gaeResponse.getContent()).andReturn("hello".getBytes())
- .atLeastOnce();
- replay(gaeResponse);
- HttpResponse response = client.convert(gaeResponse);
- assertEquals(response.getStatusCode(), 200);
- assertEquals(IOUtils.toString(response.getContent()), "hello");
- assertEquals(response.getHeaders().size(), 1);
- assertEquals(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE),
- "text/xml");
- }
-
- @Test
- void testConvertRequestGetsTargetAndUri() throws IOException {
- HttpRequest request = new HttpRequest("GET", "foo");
- HTTPRequest gaeRequest = client.convert(request);
- assertEquals(gaeRequest.getURL().getPath(), "/foo");
- }
-
- @Test
- void testConvertRequestSetsFetchOptions() throws IOException {
- HttpRequest request = new HttpRequest("GET", "foo");
- HTTPRequest gaeRequest = client.convert(request);
- assert gaeRequest.getFetchOptions() != null;
- }
-
- @Test
- void testConvertRequestSetsHeaders() throws IOException {
- HttpRequest request = new HttpRequest("GET", "foo");
- request.getHeaders().put("foo", "bar");
- HTTPRequest gaeRequest = client.convert(request);
- assertEquals(gaeRequest.getHeaders().get(0).getName(), "foo");
- assertEquals(gaeRequest.getHeaders().get(0).getValue(), "bar");
- }
-
- @Test
- void testConvertRequestNoContent() throws IOException {
- HttpRequest request = new HttpRequest("GET", "foo");
- HTTPRequest gaeRequest = client.convert(request);
- assert gaeRequest.getPayload() == null;
- assertEquals(gaeRequest.getHeaders().size(), 0);
- }
-
- @Test
- void testConvertRequestStringContent() throws IOException {
- HttpRequest request = new HttpRequest("GET", "foo");
- request.setPayload("hoot!");
- testHoot(request);
- }
-
- @Test
- void testConvertRequestInputStreamContent() throws IOException {
- HttpRequest request = new HttpRequest("GET", "foo");
- request.setPayload(IOUtils.toInputStream("hoot!"));
- testHoot(request);
- }
-
- @Test
- void testConvertRequestBytesContent() throws IOException {
- HttpRequest request = new HttpRequest("GET", "foo");
- request.setPayload("hoot!".getBytes());
- testHoot(request);
- }
-
- @Test(expectedExceptions = UnsupportedOperationException.class)
- void testConvertRequestBadContent() throws IOException {
- HttpRequest request = new HttpRequest("GET", "foo");
- request.setPayload(new Date());
- client.convert(request);
-
- }
-
- @Test
- @Parameters("basedir")
- void testConvertRequestFileContent(String basedir) throws IOException {
- File file = new File(basedir, "target/testfiles/hoot");
- file.getParentFile().mkdirs();
- IOUtils.write("hoot!", new FileOutputStream(file));
- HttpRequest request = new HttpRequest("GET", "foo");
- request.setPayload(file);
- testHoot(request);
- }
-
- private void testHoot(HttpRequest request) throws IOException {
- request.getHeaders().put(HttpHeaders.CONTENT_TYPE,"text/plain");
- HTTPRequest gaeRequest = client.convert(request);
- assertEquals(gaeRequest.getHeaders().get(0).getName(),
- HttpHeaders.CONTENT_TYPE);
- assertEquals(gaeRequest.getHeaders().get(0).getValue(), "text/plain");
- assertEquals(new String(gaeRequest.getPayload()), "hoot!");
- }
-
-}