com.xerox.amazonws.common.AWSConnection.java Source code

Java tutorial

Introduction

Here is the source code for com.xerox.amazonws.common.AWSConnection.java

Source

//
// typica - A client library for Amazon Web Services
// Copyright (C) 2007 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.common;

import java.io.InputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.SortedMap;
import java.util.TimeZone;
import java.util.TreeMap;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

/**
 * This class provides common code to the query and rest connection classes
 *
 * @author D. Kavanagh
 * @author developer@dotech.com
 */
public abstract class AWSConnection {
    private String awsAccessId;
    private String awsSecretKey;
    private boolean isSecure;
    private String server;
    private int port;
    protected Map<String, List<String>> headers;
    // used for caching last used Mac obj.. to save time 99.99% of the time
    private static Mac mac;
    private static String lastSecretKey;

    /**
    * Initializes the queue 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 SQS.
     * @param server Which host to connect to.  Usually, this will be s3.amazonaws.com
     * @param port Which port to use.
     */
    public AWSConnection(String awsAccessId, String awsSecretKey, boolean isSecure, String server, int port) {
        this.awsAccessId = awsAccessId;
        this.awsSecretKey = awsSecretKey;
        this.isSecure = isSecure;
        this.server = server;
        this.port = port;
        this.headers = new TreeMap<String, List<String>>();
    }

    /**
     * This method provides the URL for the queue service based on initialization.
     *
     * @return generated queue service url
     */
    public URL getUrl() {
        try {
            return makeURL("");
        } catch (MalformedURLException ex) {
            return null;
        }
    }

    protected String getAwsAccessKeyId() {
        return this.awsAccessId;
    }

    protected String getSecretAccessKey() {
        return this.awsSecretKey;
    }

    protected boolean isSecure() {
        return this.isSecure;
    }

    protected String getServer() {
        return this.server;
    }

    protected int getPort() {
        return this.port;
    }

    /**
     * Create a new URL object for a given resource.
     * @param resource The resource name (bucketName + "/" + key).
     */
    protected URL makeURL(String resource) throws MalformedURLException {
        String protocol = this.isSecure ? "https" : "http";
        return new URL(protocol, this.server, this.port, "/" + resource);
    }

    /**
     * Calculate the HMAC/SHA1 on a string.
     * @param awsSecretKey passcode to sign it with
     * @param canonicalString data to sign
     * @return signature
     * @throws NoSuchAlgorithmException If the algorithm does not exist.  Unlikely
     * @throws InvalidKeyException If the key is invalid.
     */
    protected String encode(String awsSecretKey, String canonicalString, boolean urlencode) {
        // The following HMAC/SHA1 code for the signature is taken from the
        // AWS Platform's implementation of RFC2104 (amazon.webservices.common.Signature)
        //
        // Acquire an HMAC/SHA1 from the raw key bytes.
        SecretKeySpec signingKey = new SecretKeySpec(awsSecretKey.getBytes(), "HmacSHA1");

        // Acquire the MAC instance and initialize with the signing key.
        if (mac == null || !lastSecretKey.equals(awsSecretKey)) {
            try {
                mac = Mac.getInstance("HmacSHA1");
            } catch (NoSuchAlgorithmException e) {
                // should not happen
                throw new RuntimeException("Could not find sha1 algorithm", e);
            }
            try {
                mac.init(signingKey);
            } catch (InvalidKeyException e) {
                // also should not happen
                mac = null;
                throw new RuntimeException("Could not initialize the MAC algorithm", e);
            }
            lastSecretKey = awsSecretKey;
        }

        // Compute the HMAC on the digest, and set it.
        byte[] signedBytes = null;
        synchronized (mac) {
            signedBytes = mac.doFinal(canonicalString.getBytes());
        }
        String b64 = new String(Base64.encodeBase64(signedBytes));

        if (urlencode) {
            return urlencode(b64);
        } else {
            return b64;
        }
    }

    protected String urlencode(String unencoded) {
        try {
            return URLEncoder.encode(unencoded, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            // should never happen
            throw new RuntimeException("Could not url encode to UTF-8", e);
        }
    }
}