added all operations except batch

This commit is contained in:
Adrian Cole 2012-09-13 17:09:26 -07:00
parent 4da4146062
commit 00da07aec4
14 changed files with 1006 additions and 23 deletions

View File

@ -25,8 +25,10 @@ import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.sqs.domain.Action;
import org.jclouds.sqs.domain.Message;
import org.jclouds.sqs.domain.MessageIdAndMD5;
import org.jclouds.sqs.domain.QueueAttributes;
import org.jclouds.sqs.options.CreateQueueOptions;
import org.jclouds.sqs.options.ListQueuesOptions;
import org.jclouds.sqs.options.ReceiveMessageOptions;
@ -208,6 +210,57 @@ public interface SQSApi {
*/
void changeMessageVisibility(URI queue, String receiptHandle, int visibilityTimeout);
/**
* The AddPermission action adds a permission to a queue for a specific
* principal. This allows for sharing access to the queue.
*
* When you create a queue, you have full control access rights for the
* queue. Only you (as owner of the queue) can grant or deny permissions to
* the queue. For more information about these permissions, see Shared Queues
* in the Amazon SQS Developer Guide.
*
* Note
*
* AddPermission writes an SQS-generated policy. If you want to write your
* own policy, use SetQueueAttributes to upload your policy.
*
* @param queue
* queue to change permissions on
* @param label
*
* The unique identification of the permission you're setting.
* example: AliceSendMessage
*
* Constraints: Maximum 80 characters; alphanumeric characters,
* hyphens (-), and underscores (_) are allowed.
* @param permission
* The action you want to allow for the specified principal.
* @param accountId
* The AWS account number of the principal who will be given
* permission. The principal must have an AWS account, but does not
* need to be signed up for Amazon SQS. For information about
* locating the AWS account identification, see Your AWS
* Identifiers in the Amazon SQS Developer Guide.
*
* Constraints: Valid 12-digit AWS account number, without hyphens
*
*/
void addPermissionToAccount(URI queue, String label, Action permission, String accountId);
/**
* The RemovePermission action revokes any permissions in the queue policy
* that matches the Label parameter. Only the owner of the queue can remove
* permissions.
*
* @param queue
* queue to change permissions on
*
* @param label
* The identification of the permission you want to remove. This is
* the label you added in AddPermission. example: AliceSendMessage
*/
void removePermission(URI queue, String label);
/**
* The SendMessage action delivers a message to the specified queue. The
* maximum allowed message size is 64 KB.
@ -295,7 +348,7 @@ public interface SQSApi {
* @param queue
* queue to get the attributes of
*/
Map<String, String> getQueueAttributes(URI queue);
QueueAttributes getQueueAttributes(URI queue);
/**
* The SetQueueAttributes action sets one attribute of a queue per request.
@ -362,6 +415,14 @@ public interface SQSApi {
*/
Map<String, String> getQueueAttributes(URI queue, Iterable<String> attributeNames);
/**
* returns an attribute of a queue.
*
* @param queue
* queue to get the attributes of
*/
String getQueueAttribute(URI queue, String attributeName);
/**
* same as {@link #receiveMessages(URI, int)} except you can provide options
* like VisibilityTimeout parameter in your request, which will be applied to

View File

@ -35,14 +35,20 @@ import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.sqs.binders.BindAttributeNamesToIndexedFormParams;
import org.jclouds.sqs.domain.Action;
import org.jclouds.sqs.domain.Message;
import org.jclouds.sqs.domain.MessageIdAndMD5;
import org.jclouds.sqs.domain.QueueAttributes;
import org.jclouds.sqs.functions.MapToQueueAttributes;
import org.jclouds.sqs.options.CreateQueueOptions;
import org.jclouds.sqs.options.ListQueuesOptions;
import org.jclouds.sqs.options.ReceiveMessageOptions;
@ -53,6 +59,7 @@ import org.jclouds.sqs.xml.ReceiveMessageResponseHandler;
import org.jclouds.sqs.xml.RegexListQueuesResponseHandler;
import org.jclouds.sqs.xml.RegexMessageIdAndMD5Handler;
import org.jclouds.sqs.xml.RegexQueueHandler;
import org.jclouds.sqs.xml.ValueHandler;
import com.google.common.util.concurrent.ListenableFuture;
@ -142,7 +149,8 @@ public interface SQSAsyncApi {
@Path("/")
@FormParams(keys = ACTION, values = "SendMessage")
@ResponseParser(RegexMessageIdAndMD5Handler.class)
ListenableFuture<MessageIdAndMD5> sendMessage(@EndpointParam URI queue, @FormParam("MessageBody") String message);
ListenableFuture<? extends MessageIdAndMD5> sendMessage(@EndpointParam URI queue,
@FormParam("MessageBody") String message);
/**
* @see SQSApi#sendMessage
@ -151,8 +159,8 @@ public interface SQSAsyncApi {
@Path("/")
@FormParams(keys = ACTION, values = "SendMessage")
@ResponseParser(RegexMessageIdAndMD5Handler.class)
ListenableFuture<MessageIdAndMD5> sendMessage(@EndpointParam URI queue, @FormParam("MessageBody") String message,
SendMessageOptions options);
ListenableFuture<? extends MessageIdAndMD5> sendMessage(@EndpointParam URI queue,
@FormParam("MessageBody") String message, SendMessageOptions options);
/**
* @see SQSApi#receiveMessage
@ -170,7 +178,7 @@ public interface SQSAsyncApi {
@Path("/")
@FormParams(keys = ACTION, values = "ReceiveMessage")
@XMLResponseParser(MessageHandler.class)
ListenableFuture<Message> receiveMessage(@EndpointParam URI queue, ReceiveMessageOptions options);
ListenableFuture<? extends Message> receiveMessage(@EndpointParam URI queue, ReceiveMessageOptions options);
/**
* @see SQSApi#getQueueAttributes(URI)
@ -178,8 +186,10 @@ public interface SQSAsyncApi {
@POST
@Path("/")
@FormParams(keys = { ACTION, "AttributeName.1" }, values = { "GetQueueAttributes", "All" })
@Transform(MapToQueueAttributes.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@XMLResponseParser(AttributesHandler.class)
ListenableFuture<Map<String, String>> getQueueAttributes(@EndpointParam URI queue);
ListenableFuture<? extends QueueAttributes> getQueueAttributes(@EndpointParam URI queue);
/**
* @see SQSApi#getQueueAttributes(URI, Iterable)
@ -191,6 +201,16 @@ public interface SQSAsyncApi {
ListenableFuture<Map<String, String>> getQueueAttributes(@EndpointParam URI queue,
@BinderParam(BindAttributeNamesToIndexedFormParams.class) Iterable<String> attributeNames);
/**
* @see SQSApi#getQueueAttribute
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "GetQueueAttributes")
@XMLResponseParser(ValueHandler.class)
ListenableFuture<String> getQueueAttribute(@EndpointParam URI queue,
@FormParam("AttributeName.1") String attributeName);
/**
* @see SQSApi#setQueueAttribute
*/
@ -207,7 +227,8 @@ public interface SQSAsyncApi {
@Path("/")
@FormParams(keys = ACTION, values = "ReceiveMessage")
@XMLResponseParser(ReceiveMessageResponseHandler.class)
ListenableFuture<Set<Message>> receiveMessages(@EndpointParam URI queue, @FormParam("MaxNumberOfMessages") int max);
ListenableFuture<? extends Set<? extends Message>> receiveMessages(@EndpointParam URI queue,
@FormParam("MaxNumberOfMessages") int max);
/**
* @see SQSApi#receiveMessages
@ -216,7 +237,24 @@ public interface SQSAsyncApi {
@Path("/")
@FormParams(keys = ACTION, values = "ReceiveMessage")
@XMLResponseParser(ReceiveMessageResponseHandler.class)
ListenableFuture<Set<Message>> receiveMessages(@EndpointParam URI queue, @FormParam("MaxNumberOfMessages") int max,
ReceiveMessageOptions options);
ListenableFuture<? extends Set<? extends Message>> receiveMessages(@EndpointParam URI queue,
@FormParam("MaxNumberOfMessages") int max, ReceiveMessageOptions options);
/**
* @see SQSApi#addPermissionToAccount
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "AddPermission")
ListenableFuture<Void> addPermissionToAccount(@EndpointParam URI queue, @FormParam("Label") String label,
@FormParam("ActionName.1") Action permission, @FormParam("AWSAccountId.1") String accountId);
/**
* @see SQSApi#removePermission
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "RemovePermission")
ListenableFuture<Void> removePermission(@EndpointParam URI queue, @FormParam("Label") String label);
}

View File

@ -0,0 +1,80 @@
/**
* 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 com.google.common.base.CaseFormat;
/**
*
* The action you want to allow for the specified principal.
*
* @see <a href=
* "http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/acp-overview.html#PermissionTypes"
* />
* @author Adrian Cole
*/
public enum Action {
/**
* This permission type grants the following actions to a principal on a
* shared queue: receive messages, send messages, delete messages, change a
* message's visibility, get a queue's attributes.
*/
ALL,
/**
* This grants permission to receive messages in the queue.
*/
RECEIVE_MESSAGE,
/**
* This grants permission to send messages to the queue. SendMessageBatch
* inherits permissions associated with SendMessage.
*/
SEND_MESSAGE,
/**
* This grants permission to delete messages from the queue.
* DeleteMessageBatch inherits permissions associated with DeleteMessage.
*/
DELETE_MESSAGE,
/**
* This grants permission to extend or terminate the read lock timeout of a
* specified message. ChangeMessageVisibilityBatch inherits permissions
* associated with ChangeMessageVisibility. For more information about
* visibility timeout, see Visibility Timeout. For more information about
* this permission type, see the ChangeMessageVisibility operation.
*/
CHANGE_MESSAGE_VISIBILITY,
/**
* This grants permission to receive all of the queue attributes except the
* policy, which can only be accessed by the queue's owner. For more
* information, see the GetQueueAttributes operation.
*/
GET_QUEUE_ATTRIBUTES,
/**
* This grants permission to get the url of a queue by name.
*/
GET_QUEUE_URL;
public String value() {
return this == ALL ? "*" : CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
}
@Override
public String toString() {
return value();
}
}

View File

@ -0,0 +1,88 @@
/**
* 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;
/**
*
* The action you want to allow for the specified principal.
*
* @see <a href=
* "http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/acp-overview.html#PermissionTypes"
* />
* @author Adrian Cole
*/
public interface Attribute {
/**
* approximate number of visible messages in a queue.
*/
public static final String APPROXIMATE_NUMBER_OF_MESSAGES = "ApproximateNumberOfMessages";
/**
* approximate number of messages that are not timed-out and not deleted.
*/
public static final String APPROXIMATE_NUMBER_OF_MESSAGES_NOT_VISIBLE = "ApproximateNumberOfMessagesNotVisible";
/**
* approximate number of messages that are not visible because you have set a
* positive delay value on the queue
*/
public static final String APPROXIMATE_NUMBER_OF_MESSAGES_DELAYED = "ApproximateNumberOfMessagesDelayed";
/**
* visibility timeout for the queue.
*/
public static final String VISIBILITY_TIMEOUT = "VisibilityTimeout";
/**
* time when the queue was created (epoch time in seconds).
*/
public static final String CREATED_TIMESTAMP = "CreatedTimestamp";
/**
* time when the queue was last changed (epoch time in seconds).
*/
public static final String LAST_MODIFIED_TIMESTAMP = "LastModifiedTimestamp";
/**
* queue's policy.
*/
public static final String POLICY = "Policy";
/**
* limit of how many bytes a message can contain before Amazon SQS rejects
* it.
*/
public static final String MAXIMUM_MESSAGE_SIZE = "MaximumMessageSize";
/**
* number of seconds Amazon SQS retains a message.
*/
public static final String MESSAGE_RETENTION_PERIOD = "MessageRetentionPeriod";
/**
* queue's Amazon resource name (ARN).
*/
public static final String QUEUE_ARN = "QueueArn";
/**
* The time in seconds that the delivery of all messages in the queue will be
* delayed.
*/
public static final String DELAY_SECONDS = "DelaySeconds";
}

View File

@ -0,0 +1,314 @@
/**
* 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.util.Date;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
/**
*
* @author Adrian Cole
*
* @see <a href=
* "http://docs.amazonwebservices.com/AWSSimpleQueueService/2011-10-01/APIReference/Query_QueryGetQueueAttributes.html"
* />
*/
public class QueueAttributes {
public static Builder<?> builder() {
return new ConcreteBuilder();
}
public Builder<?> toBuilder() {
return new ConcreteBuilder().fromQueueAttributes(this);
}
public static abstract class Builder<T extends Builder<T>> {
protected abstract T self();
protected String queueArn;
protected long approximateNumberOfMessages;
protected long approximateNumberOfMessagesNotVisible;
protected long approximateNumberOfMessagesDelayed;
protected int visibilityTimeout;
protected Date createdTimestamp;
protected Date lastModifiedTimestamp;
protected Optional<String> rawPolicy = Optional.absent();
protected int maximumMessageSize;
protected int messageRetentionPeriod;
protected int delaySeconds;
/**
* @see QueueAttributes#getQueueArn()
*/
public T queueArn(String queueArn) {
this.queueArn = queueArn;
return self();
}
/**
* @see QueueAttributes#getApproximateNumberOfMessages()
*/
public T approximateNumberOfMessages(long approximateNumberOfMessages) {
this.approximateNumberOfMessages = approximateNumberOfMessages;
return self();
}
/**
* @see QueueAttributes#getApproximateNumberOfMessagesNotVisible()
*/
public T approximateNumberOfMessagesNotVisible(long approximateNumberOfMessagesNotVisible) {
this.approximateNumberOfMessagesNotVisible = approximateNumberOfMessagesNotVisible;
return self();
}
/**
* @see QueueAttributes#getApproximateNumberOfMessagesDelayed()
*/
public T approximateNumberOfMessagesDelayed(long approximateNumberOfMessagesDelayed) {
this.approximateNumberOfMessagesDelayed = approximateNumberOfMessagesDelayed;
return self();
}
/**
* @see QueueAttributes#getVisibilityTimeout()
*/
public T visibilityTimeout(int visibilityTimeout) {
this.visibilityTimeout = visibilityTimeout;
return self();
}
/**
* @see QueueAttributes#getCreatedTimestamp()
*/
public T createdTimestamp(Date createdTimestamp) {
this.createdTimestamp = createdTimestamp;
return self();
}
/**
* @see QueueAttributes#getLastModifiedTimestamp()
*/
public T lastModifiedTimestamp(Date lastModifiedTimestamp) {
this.lastModifiedTimestamp = lastModifiedTimestamp;
return self();
}
/**
* @see QueueAttributes#getRawPolicy()
*/
public T rawPolicy(String rawPolicy) {
this.rawPolicy = Optional.fromNullable(rawPolicy);
return self();
}
/**
* @see QueueAttributes#getMaximumMessageSize()
*/
public T maximumMessageSize(int maximumMessageSize) {
this.maximumMessageSize = maximumMessageSize;
return self();
}
/**
* @see QueueAttributes#getMessageRetentionPeriod()
*/
public T messageRetentionPeriod(int messageRetentionPeriod) {
this.messageRetentionPeriod = messageRetentionPeriod;
return self();
}
/**
* @see QueueAttributes#getDelaySeconds()
*/
public T delaySeconds(int delaySeconds) {
this.delaySeconds = delaySeconds;
return self();
}
public QueueAttributes build() {
return new QueueAttributes(queueArn, approximateNumberOfMessages, approximateNumberOfMessagesNotVisible,
approximateNumberOfMessagesDelayed, visibilityTimeout, createdTimestamp, lastModifiedTimestamp,
rawPolicy, maximumMessageSize, messageRetentionPeriod, delaySeconds);
}
public T fromQueueAttributes(QueueAttributes in) {
return queueArn(in.queueArn).approximateNumberOfMessages(in.approximateNumberOfMessages)
.approximateNumberOfMessagesNotVisible(in.approximateNumberOfMessagesNotVisible)
.approximateNumberOfMessagesDelayed(in.approximateNumberOfMessagesDelayed)
.visibilityTimeout(in.visibilityTimeout).createdTimestamp(in.createdTimestamp)
.lastModifiedTimestamp(in.lastModifiedTimestamp).rawPolicy(in.rawPolicy.orNull())
.maximumMessageSize(in.maximumMessageSize).messageRetentionPeriod(in.messageRetentionPeriod)
.delaySeconds(in.delaySeconds);
}
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
@Override
protected ConcreteBuilder self() {
return this;
}
}
protected final long approximateNumberOfMessages;
protected final long approximateNumberOfMessagesNotVisible;
protected final int visibilityTimeout;
protected final Date createdTimestamp;
protected final Date lastModifiedTimestamp;
protected final long approximateNumberOfMessagesDelayed;
protected final Optional<String> rawPolicy;
protected final int maximumMessageSize;
protected final int messageRetentionPeriod;
protected final String queueArn;
protected int delaySeconds;
protected QueueAttributes(String queueArn, long approximateNumberOfMessages,
long approximateNumberOfMessagesNotVisible, long approximateNumberOfMessagesDelayed, int visibilityTimeout,
Date createdTimestamp, Date lastModifiedTimestamp, Optional<String> rawPolicy, int maximumMessageSize,
int messageRetentionPeriod, int delaySeconds) {
this.queueArn = checkNotNull(queueArn, "queueArn");
this.approximateNumberOfMessages = approximateNumberOfMessages;
this.approximateNumberOfMessagesNotVisible = approximateNumberOfMessagesNotVisible;
this.approximateNumberOfMessagesDelayed = approximateNumberOfMessagesDelayed;
this.visibilityTimeout = visibilityTimeout;
this.createdTimestamp = checkNotNull(createdTimestamp, "createdTimestamp of %s", queueArn);
this.lastModifiedTimestamp = checkNotNull(lastModifiedTimestamp, "lastModifiedTimestamp of %s", queueArn);
this.rawPolicy = checkNotNull(rawPolicy, "rawPolicy of %s", queueArn);
this.maximumMessageSize = maximumMessageSize;
this.messageRetentionPeriod = messageRetentionPeriod;
this.delaySeconds = delaySeconds;
}
/**
* @see Attribute#QUEUE_ARN
*/
public String getQueueArn() {
return queueArn;
}
/**
* @see Attribute#APPROXIMATE_NUMBER_OF_MESSAGES
*/
public long getApproximateNumberOfMessages() {
return approximateNumberOfMessages;
}
/**
* @see Attribute#APPROXIMATE_NUMBER_OF_MESSAGES_NOT_VISIBLE
*/
public long getApproximateNumberOfMessagesNotVisible() {
return approximateNumberOfMessagesNotVisible;
}
/**
* @see Attribute#APPROXIMATE_NUMBER_OF_MESSAGES_DELAYED
*/
public long getApproximateNumberOfMessagesDelayed() {
return approximateNumberOfMessagesDelayed;
}
/**
* @see Attribute#VISIBILITY_TIMEOUT
*/
public int getVisibilityTimeout() {
return visibilityTimeout;
}
/**
* @see Attribute#CREATED_TIMESTAMP
*/
public Date getCreatedTimestamp() {
return createdTimestamp;
}
/**
* @see Attribute#LAST_MODIFIED_TIMESTAMP
*/
public Date getLastModifiedTimestamp() {
return lastModifiedTimestamp;
}
/**
* Note this is in raw Json
*
* @see Attribute#POLICY
*/
public Optional<String> getRawPolicy() {
return rawPolicy;
}
/**
* @see Attribute#MAXIMUM_MESSAGE_SIZE
*/
public int getMaximumMessageSize() {
return maximumMessageSize;
}
/**
* @see Attribute#MESSAGE_RETENTION_PERIOD
*/
public int getMessageRetentionPeriod() {
return messageRetentionPeriod;
}
/**
* @see Attribute#DELAY_SECONDS
*/
public int getDelaySeconds() {
return delaySeconds;
}
@Override
public int hashCode() {
return Objects.hashCode(queueArn);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
QueueAttributes other = (QueueAttributes) obj;
return Objects.equal(this.queueArn, other.queueArn);
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return Objects.toStringHelper(this).omitNullValues().add("queueArn", queueArn)
.add("approximateNumberOfMessages", approximateNumberOfMessages)
.add("approximateNumberOfMessagesNotVisible", approximateNumberOfMessagesNotVisible)
.add("approximateNumberOfMessagesDelayed", approximateNumberOfMessagesDelayed)
.add("visibilityTimeout", visibilityTimeout).add("createdTimestamp", createdTimestamp)
.add("lastModifiedTimestamp", lastModifiedTimestamp).add("rawPolicy", rawPolicy.orNull())
.add("maximumMessageSize", maximumMessageSize).add("messageRetentionPeriod", messageRetentionPeriod)
.add("delaySeconds", delaySeconds).toString();
}
}

View File

@ -0,0 +1,57 @@
/**
* 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.functions;
import java.util.Date;
import java.util.Map;
import org.jclouds.sqs.domain.Attribute;
import org.jclouds.sqs.domain.QueueAttributes;
import org.jclouds.sqs.domain.QueueAttributes.Builder;
import com.google.common.base.Function;
/**
* Converts a Map to a typed QueueAttributes object
*
* @author Adrian Cole
*/
public class MapToQueueAttributes implements Function<Map<String, String>, QueueAttributes> {
@Override
public QueueAttributes apply(Map<String, String> input) {
if (input == null)
return null;
Builder<?> builder = QueueAttributes.builder();
builder.queueArn(input.get(Attribute.QUEUE_ARN));
builder.approximateNumberOfMessages(Long.parseLong(input.get(Attribute.APPROXIMATE_NUMBER_OF_MESSAGES)));
builder.approximateNumberOfMessagesNotVisible(Long.parseLong(input
.get(Attribute.APPROXIMATE_NUMBER_OF_MESSAGES_NOT_VISIBLE)));
builder.approximateNumberOfMessagesDelayed(Long.parseLong(input
.get(Attribute.APPROXIMATE_NUMBER_OF_MESSAGES_DELAYED)));
builder.visibilityTimeout(Integer.parseInt(input.get(Attribute.VISIBILITY_TIMEOUT)));
builder.createdTimestamp(new Date(Long.parseLong(input.get(Attribute.CREATED_TIMESTAMP))));
builder.lastModifiedTimestamp(new Date(Long.parseLong(input.get(Attribute.LAST_MODIFIED_TIMESTAMP))));
builder.rawPolicy(input.get(Attribute.POLICY));
builder.maximumMessageSize(Integer.parseInt(input.get(Attribute.MAXIMUM_MESSAGE_SIZE)));
builder.messageRetentionPeriod(Integer.parseInt(input.get(Attribute.MESSAGE_RETENTION_PERIOD)));
builder.delaySeconds(Integer.parseInt(input.get(Attribute.DELAY_SECONDS)));
return builder.build();
}
}

View File

@ -40,7 +40,7 @@ import com.google.inject.Singleton;
*/
@Singleton
public class RegexMessageIdAndMD5Handler implements Function<HttpResponse, MessageIdAndMD5> {
Pattern pattern = Pattern.compile("<MessageId>([\\S&&[^<]]+)</MessageId>\\s*<MD5OfMessageBody>([\\S&&[^<]]+)</MD5OfMessageBody>", Pattern.DOTALL);
private static final Pattern pattern = Pattern.compile("<MessageId>([\\S&&[^<]]+)</MessageId>\\s*<MD5OfMessageBody>([\\S&&[^<]]+)</MD5OfMessageBody>", Pattern.DOTALL);
private final ReturnStringIf2xx returnStringIf200;
@Inject

View File

@ -0,0 +1,56 @@
/**
* 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.jclouds.util.SaxUtils.currentOrNull;
import org.jclouds.http.functions.ParseSax;
/**
* @see <a href=
* "http://docs.amazonwebservices.com/AWSSimpleQueueService/2011-10-01/APIReference/Query_QueryGetQueueAttributes.html"
* />
*
* @author Adrian Cole
*/
public class ValueHandler extends ParseSax.HandlerForGeneratedRequestWithResult<String> {
private StringBuilder currentText = new StringBuilder();
private String value;
@Override
public String getResult() {
return value;
}
// this could be done with regex, if we had an unescaper
@Override
public void endElement(String uri, String name, String qName) {
if (qName.equals("Value")) {
value = currentOrNull(currentText);
}
currentText = new StringBuilder();
}
@Override
public void characters(char ch[], int start, int length) {
currentText.append(ch, start, length);
}
}

View File

@ -24,6 +24,8 @@ import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.sqs.domain.Action;
import org.jclouds.sqs.functions.MapToQueueAttributesTest;
import org.jclouds.sqs.internal.BaseSQSApiExpectTest;
import org.jclouds.sqs.parse.CreateQueueResponseTest;
import org.jclouds.sqs.parse.GetQueueAttributesResponseTest;
@ -195,6 +197,33 @@ public class SQSApiExpectTest extends BaseSQSApiExpectTest {
"eXJYhj5rDr9cAe", 10);
}
public HttpRequest getQueueAttribute = HttpRequest.builder()
.method("POST")
.endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")
.addHeader("Host", "sqs.us-east-1.amazonaws.com")
.addFormParam("Action", "GetQueueAttributes")
.addFormParam("AttributeName.1", "VisibilityTimeout")
.addFormParam("Signature", "AfydayBBaIk4UGikHHY1CFNmOOAcTnogpFWydZyNass%3D")
.addFormParam("SignatureMethod", "HmacSHA256")
.addFormParam("SignatureVersion", "2")
.addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
.addFormParam("Version", "2011-10-01")
.addFormParam("AWSAccessKeyId", "identity").build();
public void testGetQueueAttributeWhenResponseIs2xx() throws Exception {
HttpResponse getQueueAttributeResponse = HttpResponse.builder()
.statusCode(200)
.payload(
payloadFromStringWithContentType(
"<GetQueueAttributesResponse><GetQueueAttributesResult><Attribute><Name>VisibilityTimeout</Name><Value>30</Value></Attribute></GetQueueAttributesResult></GetQueueAttributesResponse>",
"text/xml")).build();
SQSApi apiWhenExist = requestSendsResponse(getQueueAttribute, getQueueAttributeResponse);
assertEquals(apiWhenExist.getQueueAttribute(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/"), "VisibilityTimeout"), "30");
}
public HttpRequest getQueueAttributes = HttpRequest.builder()
.method("POST")
.endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")
@ -215,7 +244,7 @@ public class SQSApiExpectTest extends BaseSQSApiExpectTest {
SQSApi apiWhenExist = requestSendsResponse(getQueueAttributes, getQueueAttributesResponse);
assertEquals(apiWhenExist.getQueueAttributes(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")).toString(), new GetQueueAttributesResponseTest().expected().toString());
assertEquals(apiWhenExist.getQueueAttributes(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")).toString(), new MapToQueueAttributesTest().expected().toString());
}
public HttpRequest getQueueAttributesSubset = HttpRequest.builder()
@ -274,5 +303,60 @@ public class SQSApiExpectTest extends BaseSQSApiExpectTest {
apiWhenExist.setQueueAttribute(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/"),
"MaximumMessageSize", "1");
}
public HttpRequest addPermission = HttpRequest.builder()
.method("POST")
.endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")
.addHeader("Host", "sqs.us-east-1.amazonaws.com")
.addFormParam("Action", "AddPermission")
.addFormParam("ActionName.1", "ReceiveMessage")
.addFormParam("AWSAccountId.1", "125074342641")
.addFormParam("Label", "testLabel")
.addFormParam("Signature", "J9sV4q1rJ7dWYJDQp9JxsfEKNXQhpQBYIwBYi1IeXV0%3D")
.addFormParam("SignatureMethod", "HmacSHA256")
.addFormParam("SignatureVersion", "2")
.addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
.addFormParam("Version", "2011-10-01")
.addFormParam("AWSAccessKeyId", "identity").build();
public void testAddPermissionWhenResponseIs2xx() throws Exception {
HttpResponse addPermissionResponse = HttpResponse.builder()
.statusCode(200)
.payload(
payloadFromStringWithContentType(
"<AddPermissionsResponse><ResponseMetadata><RequestId>b5293cb5-d306-4a17-9048-b263635abe42</RequestId></ResponseMetadata></AddPermissionsResponse>",
"text/xml")).build();
SQSApi apiWhenExist = requestSendsResponse(addPermission, addPermissionResponse);
apiWhenExist.addPermissionToAccount(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/"), "testLabel", Action.RECEIVE_MESSAGE, "125074342641");
}
public HttpRequest removePermission = HttpRequest.builder()
.method("POST")
.endpoint("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/")
.addHeader("Host", "sqs.us-east-1.amazonaws.com")
.addFormParam("Action", "RemovePermission")
.addFormParam("Label", "testLabel")
.addFormParam("Signature", "VOA0L1uRVKQDQL1Klt0cYUajGoxN4Ur%2B7ISQ2I4RpRs%3D")
.addFormParam("SignatureMethod", "HmacSHA256")
.addFormParam("SignatureVersion", "2")
.addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
.addFormParam("Version", "2011-10-01")
.addFormParam("AWSAccessKeyId", "identity").build();
public void testRemovePermissionWhenResponseIs2xx() throws Exception {
HttpResponse removePermissionResponse = HttpResponse.builder()
.statusCode(200)
.payload(
payloadFromStringWithContentType(
"<RemovePermissionsResponse><ResponseMetadata><RequestId>b5293cb5-d306-4a17-9048-b263635abe42</RequestId></ResponseMetadata></RemovePermissionsResponse>",
"text/xml")).build();
SQSApi apiWhenExist = requestSendsResponse(removePermission, removePermissionResponse);
apiWhenExist.removePermission(URI.create("https://sqs.us-east-1.amazonaws.com/993194456877/adrian-sqs11/"), "testLabel");
}
}

View File

@ -18,8 +18,11 @@
*/
package org.jclouds.sqs;
import static org.jclouds.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.providers.AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint;
import static org.jclouds.sqs.options.ListQueuesOptions.Builder.queuePrefix;
import static org.jclouds.sqs.options.ReceiveMessageOptions.Builder.attribute;
import static org.jclouds.sqs.reference.SQSParameters.ACTION;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
@ -28,16 +31,32 @@ import java.net.URI;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.TimeUnit;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.jclouds.ContextBuilder;
import org.jclouds.concurrent.Timeout;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.sqs.domain.Action;
import org.jclouds.sqs.domain.QueueAttributes;
import org.jclouds.sqs.internal.BaseSQSApiLiveTest;
import org.jclouds.sqs.xml.ValueHandler;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
import com.google.common.base.Charsets;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Module;
/**
* Tests behavior of {@code SQSApi}
@ -82,24 +101,69 @@ public class SQSApiLiveTest extends BaseSQSApiLiveTest {
return queueName;
}
String message = "hardyharhar";
HashCode md5 = Hashing.md5().hashString(message, Charsets.UTF_8);
@Test(dependsOnMethods = "testCanRecreateQueueGracefully")
protected void testGetQueueAttributes() {
for (URI queue : queues) {
Map<String, String> attributes = api().getQueueAttributes(queue);
Map<String, String> attributes = api().getQueueAttributes(queue, ImmutableSet.of("All"));
assertEquals(api().getQueueAttributes(queue, attributes.keySet()), attributes);
}
}
@Test(dependsOnMethods = "testCanRecreateQueueGracefully")
String message = "hardyharhar";
HashCode md5 = Hashing.md5().hashString(message, Charsets.UTF_8);
@Timeout(duration = 5, timeUnit = TimeUnit.SECONDS)
static interface AnonymousAttributesApi {
String getQueueArn();
}
static interface AnonymousAttributesAsyncApi {
@POST
@Path("/")
@FormParams(keys = { ACTION, "AttributeName.1" }, values = { "GetQueueAttributes", "QueueArn" })
@XMLResponseParser(ValueHandler.class)
ListenableFuture<String> getQueueArn();
}
@Test(dependsOnMethods = "testGetQueueAttributes")
protected void testAddAnonymousPermission() throws InterruptedException {
for (URI queue : queues) {
QueueAttributes attributes = api().getQueueAttributes(queue);
assertNoPermissions(queue);
String accountToAuthorize = getAccountToAuthorize(queue);
api().addPermissionToAccount(queue, "fubar", Action.GET_QUEUE_ATTRIBUTES, accountToAuthorize);
String policyForAuthorizationByAccount = assertPolicyPresent(queue);
String policyForAnonymous = policyForAuthorizationByAccount.replace("\"" + accountToAuthorize + "\"", "\"*\"");
api().setQueueAttribute(queue, "Policy", policyForAnonymous);
assertEquals(getAnonymousAttributesApi(queue).getQueueArn(), attributes.getQueueArn());
}
}
protected String getAccountToAuthorize(URI queue) {
return Iterables.get(Splitter.on('/').split(queue.getPath()), 1);
}
@Test(dependsOnMethods = "testAddAnonymousPermission")
protected void testRemovePermission() throws InterruptedException {
for (URI queue : queues) {
api().removePermission(queue, "fubar");
assertNoPermissions(queue);
}
}
@Test(dependsOnMethods = "testGetQueueAttributes")
protected void testSetQueueAttribute() {
for (URI queue : queues) {
api().setQueueAttribute(queue, "MaximumMessageSize", "1024");
assertEquals(api().getQueueAttributes(queue).get("MaximumMessageSize"), "1024");
assertEquals(api().getQueueAttributes(queue).getMaximumMessageSize(), 1024);
}
}
@Test(dependsOnMethods = "testCanRecreateQueueGracefully")
@Test(dependsOnMethods = "testGetQueueAttributes")
protected void testSendMessage() {
for (URI queue : queues) {
assertEquals(api().sendMessage(queue, message).getMD5(), md5);
@ -112,7 +176,7 @@ public class SQSApiLiveTest extends BaseSQSApiLiveTest {
assertEquals(api().receiveMessage(queue, attribute("All").visibilityTimeout(0)).getMD5(), md5);
}
}
String receiptHandle;
@Test(dependsOnMethods = "testReceiveMessageWithoutHidingMessage")
@ -149,4 +213,14 @@ public class SQSApiLiveTest extends BaseSQSApiLiveTest {
protected SQSApi api() {
return context.getApi();
}
private AnonymousAttributesApi getAnonymousAttributesApi(URI queue) {
return ContextBuilder
.newBuilder(
forClientMappedToAsyncClientOnEndpoint(AnonymousAttributesApi.class,
AnonymousAttributesAsyncApi.class, queue.toASCIIString()))
.modules(ImmutableSet.<Module> of(new ExecutorServiceModule(sameThreadExecutor(), sameThreadExecutor())))
.buildInjector().getInstance(AnonymousAttributesApi.class);
}
}

View File

@ -0,0 +1,64 @@
/**
* 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.functions;
import static org.testng.Assert.assertEquals;
import java.util.Date;
import org.jclouds.sqs.domain.QueueAttributes;
import org.jclouds.sqs.parse.GetQueueAttributesResponseTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during
// surefire
@Test(groups = "unit", testName = "MapToQueueAttributesTest")
public class MapToQueueAttributesTest {
public void test() {
QueueAttributes expected = expected();
MapToQueueAttributes fn = new MapToQueueAttributes();
QueueAttributes result = fn.apply(new GetQueueAttributesResponseTest().expected());
assertEquals(result.toString(), expected.toString());
}
public QueueAttributes expected() {
return QueueAttributes.builder()
.queueArn("arn:aws:sqs:us-east-1:993194456877:adrian-sqs1")
.approximateNumberOfMessages(0)
.approximateNumberOfMessagesNotVisible(0)
.approximateNumberOfMessagesDelayed(0)
.createdTimestamp(new Date(1347566436l))
.lastModifiedTimestamp(new Date(1347566436))
.visibilityTimeout(30)
.maximumMessageSize(65536)
.messageRetentionPeriod(345600)
.delaySeconds(0)
.build();
}
}

View File

@ -24,6 +24,7 @@ import static org.testng.Assert.assertTrue;
import java.net.URI;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import org.jclouds.apis.BaseContextLiveTest;
import org.jclouds.rest.RestContext;
@ -51,6 +52,28 @@ public class BaseSQSApiLiveTest extends BaseContextLiveTest<RestContext<SQSApi,
return SQSApiMetadata.CONTEXT_TOKEN;
}
protected String assertPolicyPresent(final URI queue) throws InterruptedException {
final AtomicReference<String> policy = new AtomicReference<String>();
assertEventually(new Runnable() {
public void run() {
String policyForAuthorizationByAccount = api().getQueueAttribute(queue, "Policy");
assertNotNull(policyForAuthorizationByAccount);
policy.set(policyForAuthorizationByAccount);
}
});
return policy.get();
}
protected void assertNoPermissions(final URI queue) throws InterruptedException {
assertEventually(new Runnable() {
public void run() {
String policy = api().getQueueAttribute(queue, "Policy");
assertTrue(policy == null || policy.indexOf("\"Statement\":[]") != -1, policy);
}
});
}
protected void assertNoMessages(final URI queue) throws InterruptedException {
assertEventually(new Runnable() {
public void run() {

View File

@ -51,8 +51,16 @@ public class GetQueueAttributesResponseTest extends BaseHandlerTest {
public Map<String, String> expected() {
return ImmutableMap.<String, String>builder()
.put("VisibilityTimeout", "30")
.put("DelaySeconds", "0")
.build();
.put("QueueArn", "arn:aws:sqs:us-east-1:993194456877:adrian-sqs1")
.put("ApproximateNumberOfMessages", "0")
.put("ApproximateNumberOfMessagesNotVisible", "0")
.put("ApproximateNumberOfMessagesDelayed", "0")
.put("CreatedTimestamp", "1347566436")
.put("LastModifiedTimestamp", "1347566436")
.put("VisibilityTimeout","30")
.put("MaximumMessageSize", "65536")
.put("MessageRetentionPeriod", "345600")
.put("DelaySeconds", "0")
.build();
}
}

View File

@ -1,12 +1,48 @@
<GetQueueAttributesResponse>
<?xml version="1.0"?>
<GetQueueAttributesResponse xmlns="http://queue.amazonaws.com/doc/2011-10-01/">
<GetQueueAttributesResult>
<Attribute>
<Name>QueueArn</Name>
<Value>arn:aws:sqs:us-east-1:993194456877:adrian-sqs1</Value>
</Attribute>
<Attribute>
<Name>ApproximateNumberOfMessages</Name>
<Value>0</Value>
</Attribute>
<Attribute>
<Name>ApproximateNumberOfMessagesNotVisible</Name>
<Value>0</Value>
</Attribute>
<Attribute>
<Name>ApproximateNumberOfMessagesDelayed</Name>
<Value>0</Value>
</Attribute>
<Attribute>
<Name>CreatedTimestamp</Name>
<Value>1347566436</Value>
</Attribute>
<Attribute>
<Name>LastModifiedTimestamp</Name>
<Value>1347566436</Value>
</Attribute>
<Attribute>
<Name>VisibilityTimeout</Name>
<Value>30</Value>
</Attribute>
<Attribute>
<Name>MaximumMessageSize</Name>
<Value>65536</Value>
</Attribute>
<Attribute>
<Name>MessageRetentionPeriod</Name>
<Value>345600</Value>
</Attribute>
<Attribute>
<Name>DelaySeconds</Name>
<Value>0</Value>
</Attribute>
</GetQueueAttributesResult>
<ResponseMetadata>
<RequestId>35566a87-caa1-5841-b60b-224bf7068bf5</RequestId>
</ResponseMetadata>
</GetQueueAttributesResponse>