//
// typica - A client library for Amazon Web Services
// Copyright (C) 2007,2008 Xerox Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package com.xerox.amazonws.sns;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBException;
import org.xml.sax.SAXException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpException;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpGet;
import com.xerox.amazonws.common.AWSException;
import com.xerox.amazonws.common.AWSQueryConnection;
import com.xerox.amazonws.common.ListResult;
import com.xerox.amazonws.common.Result;
import com.xerox.amazonws.typica.sns.jaxb.AddPermissionResponse;
import com.xerox.amazonws.typica.sns.jaxb.ConfirmSubscriptionResponse;
import com.xerox.amazonws.typica.sns.jaxb.CreateTopicResponse;
import com.xerox.amazonws.typica.sns.jaxb.DeleteTopicResponse;
import com.xerox.amazonws.typica.sns.jaxb.GetTopicAttributesResponse;
import com.xerox.amazonws.typica.sns.jaxb.ListSubscriptionsResponse;
import com.xerox.amazonws.typica.sns.jaxb.ListSubscriptionsResult;
import com.xerox.amazonws.typica.sns.jaxb.ListSubscriptionsByTopicResponse;
import com.xerox.amazonws.typica.sns.jaxb.ListSubscriptionsByTopicResult;
import com.xerox.amazonws.typica.sns.jaxb.ListTopicsResponse;
import com.xerox.amazonws.typica.sns.jaxb.ListTopicsResult;
import com.xerox.amazonws.typica.sns.jaxb.PublishResponse;
import com.xerox.amazonws.typica.sns.jaxb.RemovePermissionResponse;
import com.xerox.amazonws.typica.sns.jaxb.SetTopicAttributesResponse;
import com.xerox.amazonws.typica.sns.jaxb.Subscription;
import com.xerox.amazonws.typica.sns.jaxb.SubscribeResponse;
import com.xerox.amazonws.typica.sns.jaxb.Topic;
import com.xerox.amazonws.typica.sns.jaxb.TopicAttributesMap;
import com.xerox.amazonws.typica.sns.jaxb.TopicAttributesMapEntry;
import com.xerox.amazonws.typica.sns.jaxb.UnsubscribeResponse;
/**
* This class provides an interface with the Amazon Simple Notification Service.
*
* @author D. Kavanagh
* @author developer@dotech.com
*/
public class NotificationService {
private static Log logger = LogFactory.getLog(NotificationService.class);
private AWSQueryConnection connection; // connection delegate
/**
* Initializes the Simple Notification service with your AWS login information.
*
* @param awsAccessId The your user key into AWS
* @param awsSecretKey The secret string used to generate signatures for authentication.
*/
public NotificationService(String awsAccessId, String awsSecretKey) {
this(awsAccessId, awsSecretKey, true);
}
/**
* Initializes the Simple Notification service with your AWS login information.
*
* @param awsAccessId The your user key into AWS
* @param awsSecretKey The secret string used to generate signatures for authentication.
* @param isSecure True if the data should be encrypted on the wire on the way to or from LS.
*/
public NotificationService(String awsAccessId, String awsSecretKey, boolean isSecure) {
this(awsAccessId, awsSecretKey, isSecure, "sns.us-east-1.amazonaws.com");
}
/**
* Initializes the Simple Notification service with your AWS login information.
*
* @param awsAccessId The your user key into AWS
* @param awsSecretKey The secret string used to generate signatures for authentication.
* @param isSecure True if the data should be encrypted on the wire on the way to or from LS.
* @param server Which host to connect to. Usually, this will be sns.amazonaws.com
*/
public NotificationService(String awsAccessId, String awsSecretKey, boolean isSecure,
String server)
{
this(awsAccessId, awsSecretKey, isSecure, server, isSecure ? 443 : 80);
}
/**
* Initializes the Simple Notification service with your AWS login information.
*
* @param awsAccessId The your user key into AWS
* @param awsSecretKey The secret string used to generate signatures for authentication.
* @param isSecure True if the data should be encrypted on the wire on the way to or from LS.
* @param server Which host to connect to. Usually, this will be sns.amazonaws.com
* @param port Which port to use.
*/
public NotificationService(String awsAccessId, String awsSecretKey, boolean isSecure,
String server, int port)
{
connection = new AWSQueryConnection(awsAccessId, awsSecretKey, isSecure, server, port);
setVersionHeader(connection);
}
/**
* Returns connection object, so connection params can be tweaked
*/
public AWSQueryConnection getConnectionDelegate() {
return connection;
}
/**
* Adds to the topic's access control policy.
*
* @param topicArn the ARN for the topic
* @param label the unique identifier for the new policy statement
* @param accountIds users being given access
* @param actionNames actions you are allowing
* @throws SNSException wraps checked exceptions
*/
public void addPermission(String topicArn, String label, List<String> accountIds, List<String> actionNames) throws SNSException {
Map<String, String> params = new HashMap<String, String>();
params.put("TopicArn", topicArn);
params.put("Label", label);
for (int i=0 ; i<accountIds.size(); i++) {
params.put("AWSAccountId.member."+(i+1), accountIds.get(i));
}
for (int i=0 ; i<actionNames.size(); i++) {
params.put("ActionName.member."+(i+1), actionNames.get(i));
}
HttpGet method = new HttpGet();
AddPermissionResponse response =
makeRequestInt(method, "AddPermission", params, AddPermissionResponse.class);
}
/**
* Verifies an endpoint intends to receive messages
*
* @param topicArn the ARN for the topic
* @param token subscription token
* @param authenticateOnUnsubscribe requires authenticated unsubscribe from the topic
* @return the subscription ARN
* @throws SNSException wraps checked exceptions
*/
public Result<String> confirmSubscription(String topicArn, String token, boolean authenticateOnUnsubscribe) throws SNSException {
Map<String, String> params = new HashMap<String, String>();
params.put("TopicArn", topicArn);
params.put("Token", token);
if (authenticateOnUnsubscribe) {
params.put("AuthenticateOnUnsubscribe", "true");
}
HttpGet method = new HttpGet();
ConfirmSubscriptionResponse response =
makeRequestInt(method, "ConfirmSubscription", params, ConfirmSubscriptionResponse.class);
return new Result<String>(response.getResponseMetadata().getRequestId(),
response.getConfirmSubscriptionResult().getSubscriptionArn());
}
/**
* Creates a topic
*
* @param name name of the new topic
* @return the topic ARN
* @throws SNSException wraps checked exceptions
*/
public Result<String> createTopic(String name) throws SNSException {
Map<String, String> params = new HashMap<String, String>();
params.put("Name", name);
HttpGet method = new HttpGet();
CreateTopicResponse response =
makeRequestInt(method, "CreateTopic", params, CreateTopicResponse.class);
return new Result<String>(response.getResponseMetadata().getRequestId(),
response.getCreateTopicResult().getTopicArn());
}
/**
* Deletes a topic
*
* @param topicArn the ARN for the topic
* @throws SNSException wraps checked exceptions
*/
public void deleteTopic(String topicArn) throws SNSException {
Map<String, String> params = new HashMap<String, String>();
params.put("TopicArn", topicArn);
HttpGet method = new HttpGet();
makeRequestInt(method, "DeleteTopic", params, DeleteTopicResponse.class);
}
/**
* Gets attributes for the topic
*
* @param topicArn the ARN for the topic
* @return a map of attributes
* @throws SNSException wraps checked exceptions
*/
public Map<String, String> getTopicAttributes(String topicArn) throws SNSException {
Map<String, String> params = new HashMap<String, String>();
params.put("TopicArn", topicArn);
HttpGet method = new HttpGet();
GetTopicAttributesResponse response =
makeRequestInt(method, "GetTopicAttributes", params, GetTopicAttributesResponse.class);
HashMap<String, String> ret = new HashMap<String, String>();
TopicAttributesMap attrs = response.getGetTopicAttributesResult().getAttributes();
for (TopicAttributesMapEntry e : attrs.getEntries()) {
ret.put(e.getKey(), e.getValue());
}
return ret;
}
/**
* Lists the subscriptions
*
* @param nextToken the user token
* @return the list of subscriptions
* @throws SNSException wraps checked exceptions
*/
public ListResult<SubscriptionInfo> listSubscriptions(String nextToken) throws SNSException {
Map<String, String> params = new HashMap<String, String>();
if (nextToken != null) {
params.put("NextToken", nextToken);
}
HttpGet method = new HttpGet();
ListSubscriptionsResponse response =
makeRequestInt(method, "ListSubscriptions", params, ListSubscriptionsResponse.class);
ListSubscriptionsResult result = response.getListSubscriptionsResult();
ListResult<SubscriptionInfo> ret = new ListResult<SubscriptionInfo>(
result.getNextToken(),
response.getResponseMetadata().getRequestId());
for (Subscription s : result.getSubscriptions().getMembers()) {
ret.getItems().add(new SubscriptionInfo(s.getTopicArn(), s.getProtocol(),
s.getSubscriptionArn(), s.getOwner(), s.getEndpoint()));
}
return ret;
}
/**
* Lists subscriptions for a topic
*
* @param nextToken the user token
* @return the list of subscriptions
* @throws SNSException wraps checked exceptions
*/
public ListResult<SubscriptionInfo> listSubscriptionsByTopic(String topicArn, String nextToken) throws SNSException {
Map<String, String> params = new HashMap<String, String>();
params.put("TopicArn", topicArn);
if (nextToken != null) {
params.put("NextToken", nextToken);
}
HttpGet method = new HttpGet();
ListSubscriptionsByTopicResponse response =
makeRequestInt(method, "ListSubscriptionsByTopic", params, ListSubscriptionsByTopicResponse.class);
ListSubscriptionsByTopicResult result = response.getListSubscriptionsByTopicResult();
ListResult<SubscriptionInfo> ret = new ListResult<SubscriptionInfo>(
result.getNextToken(),
response.getResponseMetadata().getRequestId());
for (Subscription s : result.getSubscriptions().getMembers()) {
ret.getItems().add(new SubscriptionInfo(s.getTopicArn(), s.getProtocol(),
s.getSubscriptionArn(), s.getOwner(), s.getEndpoint()));
}
return ret;
}
/**
* Lists topics for this account
*
* @param nextToken the user token
* @return the list of topics
* @throws SNSException wraps checked exceptions
*/
public ListResult<String> listTopics(String nextToken) throws SNSException {
Map<String, String> params = new HashMap<String, String>();
if (nextToken != null) {
params.put("NextToken", nextToken);
}
HttpGet method = new HttpGet();
ListTopicsResponse response =
makeRequestInt(method, "ListTopics", params, ListTopicsResponse.class);
ListTopicsResult result = response.getListTopicsResult();
ListResult<String> ret = new ListResult<String>(
result.getNextToken(),
response.getResponseMetadata().getRequestId());
for (Topic t : result.getTopics().getMembers()) {
ret.getItems().add(t.getTopicArn());
}
return ret;
}
/**
* Publishes a message to a topic's subscribed endpoints
*
* @param topicArn the ARN for the topic
* @param message the message to be sent
* @param subject the optional subject for the message
* @return true if product is subscribed
* @throws SNSException wraps checked exceptions
*/
public Result<String> publish(String topicArn, String message, String subject) throws SNSException {
Map<String, String> params = new HashMap<String, String>();
params.put("TopicArn", topicArn);
params.put("Message", message);
if (subject != null) {
params.put("Subject", subject);
}
HttpGet method = new HttpGet();
PublishResponse response =
makeRequestInt(method, "Publish", params, PublishResponse.class);
return new Result<String>(response.getResponseMetadata().getRequestId(),
response.getPublishResult().getMessageId());
}
/**
* Removes permissions from a topic
*
* @param topicArn the ARN for the topic
* @param label the label for the permission statement
* @throws SNSException wraps checked exceptions
*/
public void removePermission(String topicArn, String label) throws SNSException {
Map<String, String> params = new HashMap<String, String>();
params.put("TopicArn", topicArn);
params.put("Label", label);
HttpGet method = new HttpGet();
makeRequestInt(method, "RemovePermission", params, RemovePermissionResponse.class);
}
/**
* Set a topic attribute.
*
* @param topicArn the ARN for the topic
* @param name name of the attribute
* @param value value of the attribute
* @throws SNSException wraps checked exceptions
*/
public void setTopicAttributes(String topicArn, String name, String value) throws SNSException {
Map<String, String> params = new HashMap<String, String>();
params.put("TopicArn", topicArn);
params.put("AttributeName", name);
params.put("AttributeValue", value);
HttpGet method = new HttpGet();
makeRequestInt(method, "SetTopicAttributes", params, SetTopicAttributesResponse.class);
}
/**
* Subscribe this account to a topic
*
* @param topicArn the ARN for the topic
* @return subscription ARN
* @throws SNSException wraps checked exceptions
*/
public Result<String> subscribe(String topicArn, String protocol, String endpoint) throws SNSException {
Map<String, String> params = new HashMap<String, String>();
params.put("TopicArn", topicArn);
params.put("Protocol", protocol);
params.put("Endpoint", endpoint);
HttpGet method = new HttpGet();
SubscribeResponse response =
makeRequestInt(method, "Subscribe", params, SubscribeResponse.class);
return new Result<String>(response.getResponseMetadata().getRequestId(),
response.getSubscribeResult().getSubscriptionArn());
}
/**
* Unsubscribe this account from a topic
*
* @param topicArn the ARN for the topic
* @throws SNSException wraps checked exceptions
*/
public void unsubscribe(String subscriptionArn) throws SNSException {
Map<String, String> params = new HashMap<String, String>();
params.put("SubscriptionArn", subscriptionArn);
HttpGet method = new HttpGet();
makeRequestInt(method, "Unsubscribe", params, UnsubscribeResponse.class);
}
protected <T> T makeRequestInt(HttpRequestBase method, String action, Map<String, String> params, Class<T> respType)
throws SNSException {
try {
return connection.makeRequest(method, action, params, respType);
} catch (AWSException ex) {
throw new SNSException(ex);
} catch (JAXBException ex) {
throw new SNSException("Problem parsing returned message.", ex);
} catch (SAXException ex) {
throw new SNSException("Problem parsing returned message.", ex);
} catch (HttpException ex) {
throw new SNSException(ex.getMessage(), ex);
} catch (IOException ex) {
throw new SNSException(ex.getMessage(), ex);
}
}
static void setVersionHeader(AWSQueryConnection connection) {
ArrayList<String> vals = new ArrayList<String>();
vals.add("2010-03-31");
connection.getHeaders().put("Version", vals);
}
}