Package siena.sdb.ws

Source Code of siena.sdb.ws.PlainHandler

/*
* Copyright 2009 Alberto Gimeno <gimenete at gmail.com>
*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*   limitations under the License.
*/
package siena.sdb.ws;

import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.TreeMap;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SimpleDB {

  private static final String VERSION = "2009-04-15";
  private static final String SIGNATURE_METHOD = "HmacSHA256";
  private static final String SIGNATURE_VERSION = "2";
  private static final String ENCODING = "UTF-8";

  private static final String HOST = "sdb.amazonaws.com";
  private static final String PROTOCOL = "http";
  private static final String PATH = "/";
  private static final String METHOD = "POST";

  private String awsAccessKeyId = null;
  private String awsSecretAccessKey = null;

  private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") {
    private static final long serialVersionUID = 1L;
    {
      setTimeZone(TimeZone.getTimeZone("UTC"));
    }
  };

  public SimpleDB(String awsAccessKeyId, String awsSecretAccessKey) {
    this.awsAccessKeyId = awsAccessKeyId;
    this.awsSecretAccessKey = awsSecretAccessKey;
  }

  private String sign(String data, String key) {
    try {
      SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(ENCODING), SIGNATURE_METHOD);
      Mac mac = Mac.getInstance(SIGNATURE_METHOD);
      mac.init(signingKey);
      byte[] rawHmac = mac.doFinal(data.getBytes(ENCODING));
      return Base64.encodeBytes(rawHmac);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  private void signParams(String httpverb, String host, String uri, String secretAccessKey, TreeMap<String, String> parameters) {
    parameters.put("AWSAccessKeyId", awsAccessKeyId);
    parameters.put("SignatureVersion", SIGNATURE_VERSION);
    parameters.put("SignatureMethod", SIGNATURE_METHOD);
    parameters.put("Timestamp", timestamp());
    parameters.put("Version", VERSION);
    String signature = signature(httpverb, host, uri, parameters);
    parameters.put("Signature", sign(signature, secretAccessKey));
  }

  private String query(TreeMap<String, String> parameters) {
    if(parameters.isEmpty()) return "";
    StringBuilder params = new StringBuilder();
    for (String key : parameters.keySet()) {
      params.append("&");
      params.append(urlEncode(key));
      params.append("=");
      params.append(urlEncode(parameters.get(key)));
    }

    return params.toString().substring(1);
  }

  private String signature(String httpverb, String host, String uri, TreeMap<String, String> parameters) {
    return httpverb+"\n"+host+"\n"+uri+"\n"+query(parameters);
  }

  private String urlEncode(String s) {
    try {
      return URLEncoder.encode(s, ENCODING).replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    }
  }

  public Response createDomain(String domain) {
    TreeMap<String, String> parameters = new TreeMap<String, String>();
    parameters.put("Action", "CreateDomain");
    parameters.put("DomainName", domain);

    return request(parameters, new PlainHandler());
  }

  public Response putAttributes(String domain, Item item) {
    TreeMap<String, String> parameters = new TreeMap<String, String>();
    parameters.put("Action", "PutAttributes");
    parameters.put("DomainName", domain);
    parameters.put("ItemName", item.name);
   
    int i = 0;
    for (Map.Entry<String, List<String>> entry : item.attributes.entrySet()) {
      List<String> values = entry.getValue();
      for (String value : values) {
        parameters.put("Attribute."+i+".Name", entry.getKey());
        parameters.put("Attribute."+i+".Value", value);
        parameters.put("Attribute."+i+".Replace", "true"); // FIXME always replaces
        i++;
      }
    }

    return request(parameters, new PlainHandler());
  }
 
  public GetAttributesResponse getAttributes(String domain, String itemName) {
    TreeMap<String, String> parameters = new TreeMap<String, String>();
    parameters.put("Action", "GetAttributes");
    parameters.put("DomainName", domain);
    parameters.put("ItemName", itemName);
   
    return request(parameters, new GetAttributesHandler(itemName));
  }
 
  public ListDomainsResponse listDomains(String maxNumberOfDomains, String nextToken) {
    TreeMap<String, String> parameters = new TreeMap<String, String>();
    parameters.put("Action", "ListDomains");
    if(maxNumberOfDomains != null)
      parameters.put("MaxNumberOfDomains", maxNumberOfDomains);
    if(nextToken != null)
      parameters.put("NextToken", nextToken);
   
    return request(parameters, new ListDomainsHandler());
  }
 
  public Response deleteDomain(String domain) {
    TreeMap<String, String> parameters = new TreeMap<String, String>();
    parameters.put("Action", "DeleteDomain");
    parameters.put("DomainName", domain);

    return request(parameters, new PlainHandler());
  }
 
  public DomainMetadataResponse domainMetadata(String domain) {
    TreeMap<String, String> parameters = new TreeMap<String, String>();
    parameters.put("Action", "DomainMetadata");
    parameters.put("DomainName", domain);

    return request(parameters, new DomainMetadataHandler());
  }
 
  public Response deleteAttributes(String domain, Item item) {
    TreeMap<String, String> parameters = new TreeMap<String, String>();
    parameters.put("Action", "DeleteAttributes");
    parameters.put("DomainName", domain);
    parameters.put("ItemName", item.name);

    int i = 0;
    for (Map.Entry<String, List<String>> entry : item.attributes.entrySet()) {
      List<String> values = entry.getValue();
      for (String value : values) {
        parameters.put("Attribute."+i+".Name", entry.getKey());
        parameters.put("Attribute."+i+".Value", value);
        i++;
      }
    }

    return request(parameters, new PlainHandler());
  }
 
  public SelectResponse select(String selectExpression, String nextToken) {
    TreeMap<String, String> parameters = new TreeMap<String, String>();
    parameters.put("Action", "Select");
    if(selectExpression != null)
      parameters.put("SelectExpression", selectExpression);
    if(nextToken != null)
      parameters.put("NextToken", nextToken);

    return request(parameters, new SelectHandler());
  }

  private static String timestamp() {
    return DATE_FORMAT.format(new Date());
  }

  private <T extends Response> T request(TreeMap<String, String> parameters, BasicHandler<T> handler) {
    signParams(METHOD, HOST, PATH, awsSecretAccessKey, parameters);
    try {
      SAXParserFactory factory = SAXParserFactory.newInstance();
      factory.setValidating(false);
      factory.setNamespaceAware(false);
      SAXParser parser = factory.newSAXParser();

      URL url = new URL(PROTOCOL+"://"+HOST+PATH);
      URLConnection connection = url.openConnection();
      connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded;charset="+ENCODING);
      connection.setDoOutput(true);
      connection.setDoInput(true);
      OutputStream os = connection.getOutputStream();
      // System.out.println(PROTOCOL+"://"+HOST+PATH+"?"+query(parameters));
      os.write(query(parameters).getBytes(ENCODING));
      os.close();
      parser.parse(connection.getInputStream(), handler);
      return handler.response;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
 
  public static String quote(String s) {
    if(s != null){
      return "\""+s.replace("'", "''")+"\"";
    }
    return null;
  }

} abstract class BaseHandler extends DefaultHandler {

  protected StringBuilder buffer = new StringBuilder();

  @Override
  public void characters(char[] ch, int start, int length) throws SAXException {
    buffer.append(ch, start, length);
  }

  @Override
  public void endElement(String uri, String localName, String name) throws SAXException {
    read(name, buffer.toString());
    buffer = new StringBuilder();
  }

  public abstract void read(String name, String value);

} class BasicHandler<T extends Response> extends BaseHandler {

  protected T response = null;
 
  public BasicHandler(T response) {
    this.response = response;
  }

  @Override
  public void read(String name, String value) {
    if(name.equals("RequestId"))
      response.metadata.requestId = value;
    else if(name.equals("BoxUsage"))
      response.metadata.boxUsage = value;
  }
 
  public T getResponse() {
    return response;
  }

} class PlainHandler extends BasicHandler<Response> {
 
  public PlainHandler() {
    super(new Response());
  }

} class GetAttributesHandler extends BasicHandler<GetAttributesResponse> {

  private String attrname;
  private String attrvalue;
 
  public GetAttributesHandler(String itemName) {
    super(new GetAttributesResponse(itemName));
  }
 
  @Override
  public void read(String name, String value) {
    super.read(name, value);
    if(name.equals("Attribute")) {
      response.item.add(attrname, attrvalue);
    } else if(name.equals("Name")) {
      attrname = value;
    } else if(name.equals("Value")) {
      attrvalue = value;
    }
  }
 
} class ListDomainsHandler extends BasicHandler<ListDomainsResponse> {
 
  public ListDomainsHandler() {
    super(new ListDomainsResponse());
  }
 
  @Override
  public void read(String name, String value) {
    super.read(name, value);
    if(name.equals("DomainName"))
      response.domains.add(value);
  }
 
} class DomainMetadataHandler extends BasicHandler<DomainMetadataResponse> {
 
  public DomainMetadataHandler() {
    super(new DomainMetadataResponse());
  }
 
  @Override
  public void read(String name, String value) {
    super.read(name, value);
    if(name.equals("Timestamp"))
      response.domainMetadata.timestamp = Long.parseLong(value);
    else if(name.equals("ItemCount"))
      response.domainMetadata.itemCount = Long.parseLong(value);
    else if(name.equals("AttributeValueCount"))
      response.domainMetadata.attributeValueCount = Long.parseLong(value);
    else if(name.equals("AttributeNameCount"))
      response.domainMetadata.attributeNameCount = Long.parseLong(value);
    else if(name.equals("ItemNamesSizeBytes"))
      response.domainMetadata.itemNamesSizeBytes = Long.parseLong(value);
    else if(name.equals("AttributeValuesSizeBytes"))
      response.domainMetadata.attributeValuesSizeBytes = Long.parseLong(value);
    else if(name.equals("AttributeNamesSizeBytes"))
      response.domainMetadata.attributeNamesSizeBytes = Long.parseLong(value);
  }

} class SelectHandler extends BasicHandler<SelectResponse> {
 
  private Item item;
  private boolean attribute;

  private String attrname;
  private String attrvalue;
 
  public SelectHandler() {
    super(new SelectResponse());
  }
 
  @Override
  public void startElement(String uri, String localName, String name,
      Attributes attributes) throws SAXException {
    super.startElement(uri, localName, name, attributes);
    if(name.equals("Item")) {
      item = new Item();
      response.items.add(item);
    } else if(name.equals("Attribute")) {
      attribute = true;
    }
  }
 
  @Override
  public void read(String name, String value) {
    super.read(name, value);
    if(name.equals("Name")) {
      if(attribute)
        attrname = value;
      else
        item.name = value;
    } else if(name.equals("Value")) {
      attrvalue = value;
    } else if(name.equals("NextToken")) {
      response.nextToken = value;
    } else if(name.equals("Attribute")) {
      attribute = false;
      item.add(attrname, attrvalue);
    }
  }
 
}
TOP

Related Classes of siena.sdb.ws.PlainHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.