pulled SQS out of sandbox and into labs

This commit is contained in:
Adrian Cole 2012-09-10 18:02:07 -07:00
parent 499e47c5b4
commit 2efd9a76ca
31 changed files with 259 additions and 723 deletions

View File

@ -61,5 +61,6 @@
<module>fgcp</module>
<module>fgcp-au</module>
<module>fgcp-de</module>
<module>sqs</module>
</modules>
</project>

View File

@ -27,7 +27,7 @@
<version>1.5.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.api</groupId>
<groupId>org.jclouds.labs</groupId>
<artifactId>sqs</artifactId>
<name>jcloud sqs api</name>
<description>jclouds components to access an implementation of Simple Queue Service</description>

View File

@ -18,15 +18,14 @@
*/
package org.jclouds.sqs;
import java.net.URI;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import org.jclouds.sqs.domain.Queue;
import org.jclouds.concurrent.Timeout;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.sqs.options.CreateQueueOptions;
import org.jclouds.sqs.options.ListQueuesOptions;
import org.jclouds.concurrent.Timeout;
/**
* Provides access to SQS via their REST API.
@ -35,7 +34,7 @@ import org.jclouds.concurrent.Timeout;
* @author Adrian Cole
*/
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
public interface SQSClient {
public interface SQSApi {
/**
* The ListQueues action returns a list of your queues. The maximum number of queues that can be
@ -50,7 +49,7 @@ public interface SQSClient {
* @see <a href="http://docs.amazonwebservices.com/AWSSimpleQueueService/2009-02-01/APIReference/Query_QueryListQueues.html"
* />
*/
Set<Queue> listQueuesInRegion(@Nullable String region, ListQueuesOptions... options);
Set<URI> listQueuesInRegion(@Nullable String region, ListQueuesOptions... options);
/**
*
@ -80,7 +79,7 @@ public interface SQSClient {
* @param options
* like the visibility timeout (in seconds) to use for this queue.
*/
Queue createQueueInRegion(@Nullable String region, String queueName, CreateQueueOptions... options);
URI createQueueInRegion(@Nullable String region, String queueName, CreateQueueOptions... options);
/**
* The DeleteQueue action deletes the queue specified by the queue URL, regardless of whether the
@ -102,7 +101,7 @@ public interface SQSClient {
* @param queue
* queue you want to delete
*/
void deleteQueue(Queue queue);
void deleteQueue(URI queue);
/**
* The SendMessage action delivers a message to the specified queue. The maximum allowed message
@ -124,5 +123,5 @@ public interface SQSClient {
* characters, see the preceding important note
* @return md5 of the content sent
*/
byte[] sendMessage(Queue queue, String message);
byte[] sendMessage(URI queue, String message);
}

View File

@ -0,0 +1,97 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.sqs;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import java.net.URI;
import java.util.Properties;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
import org.jclouds.sqs.config.SQSRestClientModule;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import com.google.inject.Module;
/**
* Implementation of {@link ApiMetadata} for Amazon's Simple Queue Service api.
*
* @author Adrian Cole
*/
public class SQSApiMetadata extends BaseRestApiMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = -7077953935392202824L;
public static final TypeToken<RestContext<SQSApi, SQSAsyncApi>> CONTEXT_TOKEN = new TypeToken<RestContext<SQSApi, SQSAsyncApi>>() {
private static final long serialVersionUID = -5070937833892503232L;
};
@Override
public Builder toBuilder() {
return new Builder(getApi(), getAsyncApi()).fromApiMetadata(this);
}
public SQSApiMetadata() {
this(new Builder(SQSApi.class, SQSAsyncApi.class));
}
protected SQSApiMetadata(Builder builder) {
super(builder);
}
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
return properties;
}
public static class Builder extends BaseRestApiMetadata.Builder {
protected Builder(Class<?> api, Class<?> asyncApi) {
super(api, asyncApi);
id("sqs")
.name("Amazon Simple Queue Service API")
.identityName("Access Key ID")
.credentialName("Secret Access Key")
.version("2009-02-01")
.defaultProperties(SQSApiMetadata.defaultProperties())
.defaultEndpoint("https://sqs.us-east-1.amazonaws.com")
.documentation(URI.create("http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/APIReference"))
.defaultModules(ImmutableSet.<Class<? extends Module>>of(SQSRestClientModule.class));
}
@Override
public SQSApiMetadata build() {
return new SQSApiMetadata(this);
}
@Override
public Builder fromApiMetadata(ApiMetadata in) {
super.fromApiMetadata(in);
return this;
}
}
}

View File

@ -21,22 +21,22 @@ package org.jclouds.sqs;
import static org.jclouds.sqs.reference.SQSParameters.ACTION;
import static org.jclouds.sqs.reference.SQSParameters.VERSION;
import java.net.URI;
import java.util.Set;
import javax.annotation.Nullable;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.jclouds.Constants;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.sqs.domain.Queue;
import org.jclouds.sqs.functions.QueueLocation;
import org.jclouds.sqs.options.CreateQueueOptions;
import org.jclouds.sqs.options.ListQueuesOptions;
import org.jclouds.sqs.xml.RegexListQueuesResponseHandler;
@ -52,49 +52,47 @@ import com.google.common.util.concurrent.ListenableFuture;
* @author Adrian Cole
*/
@RequestFilters(FormSigner.class)
@FormParams(keys = VERSION, values = SQSAsyncClient.VERSION)
@FormParams(keys = VERSION, values = "{" + Constants.PROPERTY_API_VERSION + "}")
@VirtualHost
public interface SQSAsyncClient {
public static final String VERSION = "2009-02-01";
public interface SQSAsyncApi {
/**
* @see SQSClient#listQueuesInRegion
* @see SQSApi#listQueuesInRegion
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "ListQueues")
@ResponseParser(RegexListQueuesResponseHandler.class)
ListenableFuture<? extends Set<Queue>> listQueuesInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
ListQueuesOptions... options);
ListenableFuture<Set<URI>> listQueuesInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
ListQueuesOptions... options);
/**
* @see SQSClient#createQueueInRegion
* @see SQSApi#createQueueInRegion
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "CreateQueue")
@ResponseParser(RegexQueueHandler.class)
ListenableFuture<Queue> createQueueInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("QueueName") String queueName, CreateQueueOptions... options);
ListenableFuture<URI> createQueueInRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@FormParam("QueueName") String queueName, CreateQueueOptions... options);
/**
* @see SQSClient#deleteQueue
* @see SQSApi#deleteQueue
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "DeleteQueue")
ListenableFuture<Void> deleteQueue(@EndpointParam(parser = QueueLocation.class) Queue queue);
ListenableFuture<Void> deleteQueue(@EndpointParam URI queue);
/**
* @see SQSClient#sendMessage
* @see SQSApi#sendMessage
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "SendMessage")
@ResponseParser(RegexMD5Handler.class)
ListenableFuture<byte[]> sendMessage(@EndpointParam(parser = QueueLocation.class) Queue queue,
@FormParam("MessageBody") String message);
ListenableFuture<byte[]> sendMessage(@EndpointParam URI queue, @FormParam("MessageBody") String message);
}

View File

@ -19,22 +19,22 @@
package org.jclouds.sqs.config;
import org.jclouds.aws.config.FormSigningRestClientModule;
import org.jclouds.http.RequiresHttp;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.sqs.SQSAsyncClient;
import org.jclouds.sqs.SQSClient;
import org.jclouds.sqs.SQSApi;
import org.jclouds.sqs.SQSAsyncApi;
import com.google.common.reflect.TypeToken;
/**
* Configures the SQS connection.
*
* @author Adrian Cole
*/
@RequiresHttp
@ConfiguresRestClient
public class SQSRestClientModule extends FormSigningRestClientModule<SQSClient, SQSAsyncClient> {
public class SQSRestClientModule extends FormSigningRestClientModule<SQSApi, SQSAsyncApi> {
public SQSRestClientModule() {
super(SQSClient.class, SQSAsyncClient.class);
super(TypeToken.of(SQSApi.class), TypeToken.of(SQSAsyncApi.class));
}
}

View File

@ -29,7 +29,7 @@ import org.jclouds.http.options.BaseHttpRequestOptions;
* <code>
* import static org.jclouds.sqs.options.CreateQueueOptions.Builder.*
* <p/>
* SQSClient connection = // get connection
* SQSApi connection = // get connection
* Queue queue = connection.createQueueInRegion(defaultVisibilityTimeout("foo"));
* <code>
*

View File

@ -29,7 +29,7 @@ import org.jclouds.http.options.BaseHttpRequestOptions;
* <code>
* import static org.jclouds.sqs.options.ListQueuesOptions.Builder.*
* <p/>
* SQSClient connection = // get connection
* SQSApi connection = // get connection
* Set<Queue> queues = connection.listQueuesInRegion(queuePrefix("foo"));
* <code>
*

View File

@ -17,7 +17,7 @@
* under the License.
*/
/**
* This package contains an Amazon SQS client implemented by {@link org.jclouds.http.HttpCommandExecutorService} commands.
* This package contains an Amazon SQS api implemented by {@link org.jclouds.http.HttpCommandExecutorService} commands.
*
* @see <a href="http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/APIReference/index.html"/>
* @author Adrian Cole

View File

@ -19,40 +19,35 @@
package org.jclouds.sqs.xml;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.sqs.domain.Queue;
import org.jclouds.sqs.xml.internal.BaseRegexQueueHandler;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ReturnStringIf2xx;
import org.jclouds.location.Region;
import org.jclouds.sqs.xml.internal.BaseRegexQueueHandler;
import com.google.common.base.Function;
/**
*
* @see <a href="http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/APIReference/Query_QueryListQueues.html"
* @see <a href=
* "http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/APIReference/Query_QueryListQueues.html"
* />
* @author Adrian Cole
*/
@Singleton
public class RegexListQueuesResponseHandler extends BaseRegexQueueHandler implements
Function<HttpResponse, Set<Queue>> {
public class RegexListQueuesResponseHandler extends BaseRegexQueueHandler implements Function<HttpResponse, Set<URI>> {
private final ReturnStringIf2xx returnStringIf200;
@Inject
RegexListQueuesResponseHandler(@Region Map<String, URI> regionMap,
ReturnStringIf2xx returnStringIf200) {
super(regionMap);
RegexListQueuesResponseHandler(ReturnStringIf2xx returnStringIf200) {
this.returnStringIf200 = returnStringIf200;
}
@Override
public Set<Queue> apply(HttpResponse response) {
public Set<URI> apply(HttpResponse response) {
return parse(returnStringIf200.apply(response));
}

View File

@ -19,39 +19,35 @@
package org.jclouds.sqs.xml;
import java.net.URI;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.sqs.domain.Queue;
import org.jclouds.sqs.xml.internal.BaseRegexQueueHandler;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ReturnStringIf2xx;
import org.jclouds.location.Region;
import org.jclouds.sqs.xml.internal.BaseRegexQueueHandler;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
/**
*
* @see <a href="http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/APIReference/Query_QueryListQueues.html"
* @see <a href=
* "http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/APIReference/Query_QueryListQueues.html"
* />
* @author Adrian Cole
*/
@Singleton
public class RegexQueueHandler extends BaseRegexQueueHandler implements
Function<HttpResponse, Queue> {
public class RegexQueueHandler extends BaseRegexQueueHandler implements Function<HttpResponse, URI> {
private final ReturnStringIf2xx returnStringIf200;
@Inject
RegexQueueHandler(@Region Map<String, URI> regionMap, ReturnStringIf2xx returnStringIf200) {
super(regionMap);
RegexQueueHandler(ReturnStringIf2xx returnStringIf200) {
this.returnStringIf200 = returnStringIf200;
}
@Override
public Queue apply(HttpResponse response) {
public URI apply(HttpResponse response) {
return Iterables.getOnlyElement(parse(returnStringIf200.apply(response)));
}
}

View File

@ -19,48 +19,36 @@
package org.jclouds.sqs.xml.internal;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.sqs.domain.Queue;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.Sets;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
/**
*
* @see <a href="http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/APIReference/Query_QueryListQueues.html"
* @see <a href=
* "http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/APIReference/Query_QueryListQueues.html"
* />
* @author Adrian Cole
*/
@Singleton
public class BaseRegexQueueHandler {
private final ImmutableBiMap<URI, String> uriToRegion;
Pattern pattern = Pattern.compile("<QueueUrl>(https://[\\S&&[^<]]+)</QueueUrl>");
protected final Pattern pattern = Pattern.compile("<QueueUrl>(https://[\\S&&[^<]]+)</QueueUrl>");
@Inject
protected BaseRegexQueueHandler(Map<String, URI> regionMap) {
this.uriToRegion = ImmutableBiMap.<String, URI> builder().putAll(regionMap).build().inverse();
}
public Set<Queue> parse(String in) {
Set<Queue> queues = Sets.newLinkedHashSet();
public Set<URI> parse(String in) {
Builder<URI> queues = ImmutableSet.<URI> builder();
Matcher matcher = pattern.matcher(in);
while (matcher.find()) {
String uriText = matcher.group(1);
String queueName = uriText.substring(uriText.lastIndexOf('/') + 1);
URI location = URI.create(uriText);
String regionString = uriText.substring(0, uriText.indexOf(".com/") + 4);
URI regionURI = URI.create(regionString);
String region = uriToRegion.get(regionURI);
queues.add(new Queue(region, queueName, location));
if (!Strings.isNullOrEmpty(uriText))
queues.add(URI.create(uriText));
}
return queues;
return queues.build();
}
}

View File

@ -0,0 +1 @@
org.jclouds.sqs.SQSApiMetadata

View File

@ -18,80 +18,33 @@
*/
package org.jclouds.sqs;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.sqs.options.ListQueuesOptions.Builder.queuePrefix;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.util.Properties;
import java.net.URI;
import java.util.Set;
import java.util.SortedSet;
import org.jclouds.Constants;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.crypto.CryptoStreams;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.RestContextFactory;
import org.jclouds.sqs.domain.Queue;
import org.jclouds.sqs.internal.BaseSQSApiLiveTest;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.inject.Module;
/**
* Tests behavior of {@code SQSClient}
* Tests behavior of {@code SQSApi}
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true)
public class SQSClientLiveTest {
@Test(groups = "live", singleThreaded = true, testName = "SQSApiLiveTest")
public class SQSApiLiveTest extends BaseSQSApiLiveTest {
private SQSClient client;
private RestContext<SQSClient, SQSAsyncClient> context;
private Set<Queue> queues = Sets.newHashSet();
protected String provider = "sqs";
protected String identity;
protected String credential;
protected String endpoint;
protected String apiVersion;
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
+ ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiVersion = System.getProperty("test." + provider + ".api-version");
}
protected Properties setupProperties() {
Properties overrides = new Properties();
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
if (credential != null)
overrides.setProperty(provider + ".credential", credential);
if (endpoint != null)
overrides.setProperty(provider + ".endpoint", endpoint);
if (apiVersion != null)
overrides.setProperty(provider + ".api-version", apiVersion);
return overrides;
}
@BeforeGroups(groups = { "live" })
public void setupClient() {
setupCredentials();
Properties overrides = setupProperties();
context = new RestContextFactory().createContext(provider, ImmutableSet.<Module> of(new Log4JLoggingModule()),
overrides);
this.client = context.getApi();
}
private Set<URI> queues = Sets.newHashSet();
@Test
protected void testListQueues() throws InterruptedException {
@ -99,10 +52,10 @@ public class SQSClientLiveTest {
}
protected void listQueuesInRegion(String region) throws InterruptedException {
SortedSet<Queue> allResults = Sets.newTreeSet(client.listQueuesInRegion(region));
SortedSet<URI> allResults = Sets.newTreeSet(context.getApi().listQueuesInRegion(region));
assertNotNull(allResults);
if (allResults.size() >= 1) {
Queue queue = allResults.last();
URI queue = allResults.last();
assertQueueInList(region, queue);
}
}
@ -116,20 +69,20 @@ public class SQSClientLiveTest {
public String createQueueInRegion(final String region, String queueName) throws InterruptedException {
try {
SortedSet<Queue> result = Sets.newTreeSet(client.listQueuesInRegion(region, queuePrefix(queueName)));
SortedSet<URI> result = Sets.newTreeSet(context.getApi().listQueuesInRegion(region, queuePrefix(queueName)));
if (result.size() >= 1) {
client.deleteQueue(result.last());
context.getApi().deleteQueue(result.last());
queueName += 1;// cannot recreate a queue within 60 seconds
}
} catch (Exception e) {
}
Queue queue = null;
URI queue = null;
int tries = 0;
while (queue == null && tries < 5) {
try {
tries++;
queue = client.createQueueInRegion(region, queueName);
queue = context.getApi().createQueueInRegion(region, queueName);
} catch (AWSResponseException e) {
queueName += "1";
if (e.getError().getCode().equals("AWS.SimpleQueueService.QueueDeletedRecently"))// TODO
@ -139,9 +92,6 @@ public class SQSClientLiveTest {
throw e;
}
}
if (region != null)
assertEquals(queue.getRegion(), region);
assertEquals(queue.getName(), queueName);
assertQueueInList(region, queue);
queues.add(queue);
return queueName;
@ -151,19 +101,19 @@ public class SQSClientLiveTest {
protected void testSendMessage() throws InterruptedException, IOException {
String message = "hardyharhar";
byte[] md5 = CryptoStreams.md5(message.getBytes());
for (Queue queue : queues) {
assertEquals(client.sendMessage(queue, message), md5);
for (URI queue : queues) {
assertEquals(context.getApi().sendMessage(queue, message), md5);
}
}
private void assertQueueInList(final String region, Queue queue) throws InterruptedException {
final Queue finalQ = queue;
private void assertQueueInList(final String region, URI queue) throws InterruptedException {
final URI finalQ = queue;
assertEventually(new Runnable() {
public void run() {
SortedSet<Queue> result = Sets.newTreeSet(client.listQueuesInRegion(region, queuePrefix(finalQ.getName())));
Set<URI> result = context.getApi().listQueuesInRegion(region);
assertNotNull(result);
assert result.size() >= 1 : result;
assertEquals(result.first(), finalQ);
assertTrue(result.contains(finalQ), finalQ + " not in " + result);
}
});
}
@ -171,8 +121,9 @@ public class SQSClientLiveTest {
private static final int INCONSISTENCY_WINDOW = 10000;
/**
* Due to eventual consistency, container commands may not return correctly immediately. Hence,
* we will try up to the inconsistency window to see if the assertion completes.
* Due to eventual consistency, container commands may not return correctly
* immediately. Hence, we will try up to the inconsistency window to see if
* the assertion completes.
*/
protected static void assertEventually(Runnable assertion) throws InterruptedException {
long start = System.currentTimeMillis();

View File

@ -16,25 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.sqs.functions;
package org.jclouds.sqs;
import java.net.URI;
import org.jclouds.View;
import org.jclouds.rest.internal.BaseRestApiMetadataTest;
import org.testng.annotations.Test;
import javax.inject.Singleton;
import org.jclouds.sqs.domain.Queue;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
/**
*
* @author Adrian Cole
*/
@Singleton
public class QueueLocation implements Function<Object, URI> {
@Test(groups = "unit", testName = "SQSApiMetadataTest")
public class SQSApiMetadataTest extends BaseRestApiMetadataTest {
public URI apply(Object from) {
return ((Queue) from).getLocation();
// no queue abstraction, yet
public SQSApiMetadataTest() {
super(new SQSApiMetadata(), ImmutableSet.<TypeToken<? extends View>> of());
}
}

View File

@ -23,19 +23,13 @@ import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.Properties;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.date.DateService;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.RequiresHttp;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.RestContextFactory;
import org.jclouds.rest.RestContextSpec;
import org.jclouds.rest.internal.BaseAsyncClientTest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.sqs.config.SQSRestClientModule;
import org.jclouds.sqs.options.CreateQueueOptions;
@ -48,27 +42,31 @@ import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code SQSAsyncClient}
* Tests behavior of {@code SQSAsyncApi}
*
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "SQSAsyncClientTest")
public class SQSAsyncClientTest extends RestClientTest<SQSAsyncClient> {
// NOTE:without testName, this will not call @Before* and fail w/NPE during
// surefire
@Test(groups = "unit", testName = "SQSAsyncApiTest")
public class SQSAsyncApiTest extends BaseAsyncClientTest<SQSAsyncApi> {
@Override
protected ApiMetadata createApiMetadata() {
return new SQSApiMetadata();
}
@RequiresHttp
@ConfiguresRestClient
private static final class TestSQSRestClientModule extends SQSRestClientModule {
private static final class TestSQSRestApiModule extends SQSRestClientModule {
@Override
protected String provideTimeStamp(final DateService dateService,
@Named(Constants.PROPERTY_SESSION_INTERVAL) int expiration) {
protected String provideTimeStamp(final DateService dateService) {
return "2009-11-08T15:54:08.897Z";
}
}
public void testListQueuesInRegion() throws SecurityException, NoSuchMethodException, IOException {
Method method = SQSAsyncClient.class.getMethod("listQueuesInRegion", String.class,
Method method = SQSAsyncApi.class.getMethod("listQueuesInRegion", String.class,
Array.newInstance(ListQueuesOptions.class, 0).getClass());
HttpRequest request = processor.createRequest(method, (String) null);
@ -84,7 +82,7 @@ public class SQSAsyncClientTest extends RestClientTest<SQSAsyncClient> {
}
public void testListQueuesInRegionOptions() throws SecurityException, NoSuchMethodException, IOException {
Method method = SQSAsyncClient.class.getMethod("listQueuesInRegion", String.class,
Method method = SQSAsyncApi.class.getMethod("listQueuesInRegion", String.class,
Array.newInstance(ListQueuesOptions.class, 0).getClass());
HttpRequest request = processor.createRequest(method, null, ListQueuesOptions.Builder.queuePrefix("prefix"));
@ -101,8 +99,8 @@ public class SQSAsyncClientTest extends RestClientTest<SQSAsyncClient> {
}
public void testCreateQueueInRegion() throws SecurityException, NoSuchMethodException, IOException {
Method method = SQSAsyncClient.class.getMethod("createQueueInRegion", String.class, String.class, Array
.newInstance(CreateQueueOptions.class, 0).getClass());
Method method = SQSAsyncApi.class.getMethod("createQueueInRegion", String.class, String.class,
Array.newInstance(CreateQueueOptions.class, 0).getClass());
HttpRequest request = processor.createRequest(method, null, "queueName");
assertRequestLineEquals(request, "POST https://sqs.us-east-1.amazonaws.com/ HTTP/1.1");
@ -118,8 +116,8 @@ public class SQSAsyncClientTest extends RestClientTest<SQSAsyncClient> {
}
public void testCreateQueueInRegionOptions() throws SecurityException, NoSuchMethodException, IOException {
Method method = SQSAsyncClient.class.getMethod("createQueueInRegion", String.class, String.class, Array
.newInstance(CreateQueueOptions.class, 0).getClass());
Method method = SQSAsyncApi.class.getMethod("createQueueInRegion", String.class, String.class,
Array.newInstance(CreateQueueOptions.class, 0).getClass());
HttpRequest request = processor.createRequest(method, null, "queueName",
CreateQueueOptions.Builder.defaultVisibilityTimeout(45));
@ -143,31 +141,14 @@ public class SQSAsyncClientTest extends RestClientTest<SQSAsyncClient> {
}
@Override
protected TypeLiteral<RestAnnotationProcessor<SQSAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<SQSAsyncClient>>() {
protected TypeLiteral<RestAnnotationProcessor<SQSAsyncApi>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<SQSAsyncApi>>() {
};
}
@Override
protected Module createModule() {
return new TestSQSRestClientModule();
}
protected String provider = "sqs";
@Override
protected Properties getProperties() {
Properties overrides = new Properties();
overrides.setProperty(provider + ".endpoint", "https://sqs.us-east-1.amazonaws.com");
overrides.setProperty(provider + ".propertiesbuilder", SQSPropertiesBuilder.class.getName());
overrides.setProperty(provider + ".contextbuilder", SQSContextBuilder.class.getName());
return overrides;
}
@Override
public RestContextSpec<?, ?> createContextSpec() {
return new RestContextFactory(getProperties()).createContextSpec(provider, "identity", "credential",
new Properties());
return new TestSQSRestApiModule();
}
}

View File

@ -0,0 +1,46 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.sqs.internal;
import org.jclouds.apis.BaseContextLiveTest;
import org.jclouds.rest.RestContext;
import org.jclouds.sqs.SQSApi;
import org.jclouds.sqs.SQSApiMetadata;
import org.jclouds.sqs.SQSAsyncApi;
import org.testng.annotations.Test;
import com.google.common.reflect.TypeToken;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live")
public class BaseSQSApiLiveTest extends BaseContextLiveTest<RestContext<SQSApi, SQSAsyncApi>> {
public BaseSQSApiLiveTest() {
provider = "sqs";
}
@Override
protected TypeToken<RestContext<SQSApi, SQSAsyncApi>> contextType() {
return SQSApiMetadata.CONTEXT_TOKEN;
}
}

View File

@ -1,55 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.sqs;
import java.util.List;
import java.util.Properties;
import org.jclouds.sqs.config.SQSRestClientModule;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.rest.RestContextBuilder;
import com.google.inject.Injector;
import com.google.inject.Module;
/**
* Creates {@link SQSContext} or {@link Injector} instances based on the most commonly requested
* arguments.
* <p/>
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
* <p/>
* <p/>
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
*
* @author Adrian Cole
* @see SQSContext
*/
public class SQSContextBuilder extends RestContextBuilder<SQSClient, SQSAsyncClient> {
public SQSContextBuilder(Properties props) {
super(SQSClient.class, SQSAsyncClient.class, props);
}
@Override
protected void addClientModule(List<Module> modules) {
modules.add(new SQSRestClientModule());
}
}

View File

@ -1,54 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.sqs;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG;
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
import java.util.Properties;
import org.jclouds.PropertiesBuilder;
/**
* Builds properties used in SQS Clients
*
* @author Adrian Cole
*/
public class SQSPropertiesBuilder extends PropertiesBuilder {
@Override
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
properties.setProperty(PROPERTY_HEADER_TAG, "amz");
properties.setProperty(PROPERTY_API_VERSION, SQSAsyncClient.VERSION);
properties.setProperty(PROPERTY_ENDPOINT, "https://sqs.us-east-1.amazonaws.com");
return properties;
}
public SQSPropertiesBuilder() {
super();
}
public SQSPropertiesBuilder(Properties properties) {
super(properties);
}
}

View File

@ -1,102 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.sqs.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
/**
*
* @see <a href="http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/APIReference/Query_QueryListQueues.html"
* />
* @author Adrian Cole
*/
public class Queue implements Comparable<Queue> {
private final String region;
private final String name;
private final URI location;
public Queue(String region, String name, URI location) {
this.region = checkNotNull(region,"region");
this.location = checkNotNull(location, "location");
this.name = checkNotNull(name, "name");
}
@Override
public int compareTo(Queue o) {
return location.toASCIIString().compareTo(o.location.toASCIIString());
}
public String getRegion() {
return region;
}
public URI getLocation() {
return location;
}
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((location == null) ? 0 : location.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((region == null) ? 0 : region.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Queue other = (Queue) obj;
if (location == null) {
if (other.location != null)
return false;
} else if (!location.equals(other.location))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (region == null) {
if (other.region != null)
return false;
} else if (!region.equals(other.region))
return false;
return true;
}
@Override
public String toString() {
return "Queue [location=" + location + ", name=" + name + ", region=" + region + "]";
}
}

View File

@ -1,61 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.sqs.xml;
import java.util.Set;
import javax.inject.Inject;
import org.jclouds.sqs.domain.Queue;
import org.jclouds.http.functions.ParseSax;
import com.google.common.collect.Sets;
/**
*
* @see <a href="http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/APIReference/Query_QueryListQueues.html"
* />
* @author Adrian Cole
*/
public class ListQueuesResponseHandler extends ParseSax.HandlerWithResult<Set<Queue>> {
Set<Queue> queues = Sets.newLinkedHashSet();
private final QueueHandler qHandler;
@Inject
ListQueuesResponseHandler(QueueHandler qHandler) {
this.qHandler = qHandler;
}
public Set<Queue> getResult() {
return queues;
}
public void endElement(String uri, String name, String qName) {
qHandler.endElement(uri, name, qName);
if (qName.equals("QueueUrl")) {
queues.add(qHandler.getResult());
}
}
public void characters(char ch[], int start, int length) {
qHandler.characters(ch, start, length);
}
}

View File

@ -1,75 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.sqs.xml;
import java.net.URI;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.ws.rs.core.UriBuilder;
import org.jclouds.sqs.domain.Queue;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.location.Region;
import com.google.common.collect.ImmutableBiMap;
/**
*
* @see <a href=
* "http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/APIReference/Query_QueryListQueues.html"
* />
* @author Adrian Cole
*/
public class QueueHandler extends ParseSax.HandlerWithResult<Queue> {
private StringBuilder currentText = new StringBuilder();
Queue queue;
private final ImmutableBiMap<URI, String> regionBiMap;
private final Provider<UriBuilder> uriBuilderProvider;
@Inject
QueueHandler(Provider<UriBuilder> uriBuilderProvider, @Region Map<String, URI> regionMap) {
this.uriBuilderProvider = uriBuilderProvider;
this.regionBiMap = ImmutableBiMap.<String, URI> copyOf(regionMap).inverse();
}
public Queue getResult() {
return queue;
}
public void endElement(String uri, String name, String qName) {
if (qName.equals("QueueUrl")) {
String uriText = currentText.toString().trim();
String queueName = uriText.substring(uriText.lastIndexOf('/') + 1);
URI location = URI.create(uriText);
URI regionURI = uriBuilderProvider.get().uri(location).replacePath("").build();
String region = regionBiMap.get(regionURI);
this.queue = new Queue(region, queueName, location);
}
currentText = new StringBuilder();
}
public void characters(char ch[], int start, int length) {
currentText.append(ch, start, length);
}
}

View File

@ -1,169 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.sqs.xml;
import static org.testng.Assert.assertEquals;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Singleton;
import javax.ws.rs.core.UriBuilder;
import org.jclouds.PerformanceTest;
import org.jclouds.aws.domain.Region;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ParseSax.Factory;
import org.jclouds.http.functions.config.SaxParserModule;
import org.jclouds.io.Payloads;
import org.jclouds.sqs.domain.Queue;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.ByteStreams;
import com.google.common.io.InputSupplier;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Provides;
import com.sun.jersey.api.uri.UriBuilderImpl;
/**
* Tests behavior of {@code ListQueuesResponseHandlerr}
*
* @author Adrian Cole
*/
// NOTE:without testName, this will fail w/NPE during surefire
@Test(groups = "performance", sequential = true, timeOut = 2 * 60 * 1000, testName = "ListQueuesResponseHandlerTest")
public class ListQueuesResponseHandlerTest extends PerformanceTest {
private Injector injector;
private Factory factory;
private RegexListQueuesResponseHandler handler;
private InputSupplier<ByteArrayInputStream> supplier;
@BeforeTest
protected void setUpInjector() throws IOException {
LOOP_COUNT = 100000;
THREAD_COUNT = 100;
System.out.printf("queue response handle speed test %d threads %d count%n", THREAD_COUNT,
LOOP_COUNT);
injector = Guice.createInjector(new SaxParserModule(), new AbstractModule() {
@Override
protected void configure() {
bind(UriBuilder.class).to(UriBuilderImpl.class);
}
@SuppressWarnings("unused")
@Provides
@Singleton
@org.jclouds.location.Region
Map<String, URI> provideRegions() {
return ImmutableMap.<String, URI> of(Region.EU_WEST_1, URI
.create("https://eu-west-1.queue.amazonaws.com"));
}
});
handler = injector.getInstance(RegexListQueuesResponseHandler.class);
factory = injector.getInstance(ParseSax.Factory.class);
InputStream inputStream = getClass().getResourceAsStream("/list_queues.xml");
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteStreams.copy(inputStream, out);
supplier = ByteStreams.newInputStreamSupplier(out.toByteArray());
assert factory != null;
}
Set<Queue> expected = ImmutableSet.of(new Queue(Region.EU_WEST_1, "adriancole-sqs1", URI
.create("https://eu-west-1.queue.amazonaws.com/993194456877/adriancole-sqs1")),
new Queue(Region.EU_WEST_1, "adriancole-sqs111", URI
.create("https://eu-west-1.queue.amazonaws.com/993194456877/adriancole-sqs111")));
public void testSax() {
ListQueuesResponseHandler handler = injector.getInstance(ListQueuesResponseHandler.class);
Set<Queue> result;
try {
result = factory.create(handler).parse(supplier.getInput());
assertEquals(result, expected);
} catch (Exception e) {
Throwables.propagate(e);
}
}
public void testRegex() {
try {
assertEquals(handler.apply(new HttpResponse(200, "ok", Payloads.newPayload(supplier
.getInput()))), expected);
} catch (IOException e) {
Throwables.propagate(e);
}
}
@Test(enabled = false)
void testRegexSerialResponseTime() throws IOException {
long now = System.currentTimeMillis();
for (int i = 0; i < LOOP_COUNT; i++)
testRegex();
System.out.println("testRegex serial: " + (System.currentTimeMillis() - now) + "");
}
@Test(enabled = false)
void testRegexParallelResponseTime() throws Throwable {
List<Runnable> tasks = ImmutableList.<Runnable> of(new Runnable() {
public void run() {
testRegex();
}
});
executeMultiThreadedPerformanceTest("testRegexParallelResponseTime", tasks);
}
@Test(enabled = false)
void testSaxSerialResponseTime() throws IOException {
long now = System.currentTimeMillis();
for (int i = 0; i < LOOP_COUNT; i++)
testSax();
System.out.println("testSax serial: " + (System.currentTimeMillis() - now) + "");
}
@Test(enabled = false)
void testSaxParallelResponseTime() throws Throwable {
List<Runnable> tasks = ImmutableList.<Runnable> of(new Runnable() {
public void run() {
testSax();
}
});
executeMultiThreadedPerformanceTest("testSaxParallelResponseTime", tasks);
}
}