// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF 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 com.cloud.bridge.service;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URLEncoder;
import java.security.KeyStore;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;

import javax.inject.Inject;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMFactory;
import org.apache.axis2.AxisFault;
import org.apache.axis2.databinding.ADBBean;
import org.apache.axis2.databinding.ADBException;
import org.apache.axis2.databinding.utils.writer.MTOMAwareXMLSerializer;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;

import com.amazon.ec2.AllocateAddressResponse;
import com.amazon.ec2.AssociateAddressResponse;
import com.amazon.ec2.AttachVolumeResponse;
import com.amazon.ec2.AuthorizeSecurityGroupIngressResponse;
import com.amazon.ec2.CreateImageResponse;
import com.amazon.ec2.CreateKeyPairResponse;
import com.amazon.ec2.CreateSecurityGroupResponse;
import com.amazon.ec2.CreateSnapshotResponse;
import com.amazon.ec2.CreateTagsResponse;
import com.amazon.ec2.CreateVolumeResponse;
import com.amazon.ec2.DeleteKeyPairResponse;
import com.amazon.ec2.DeleteSecurityGroupResponse;
import com.amazon.ec2.DeleteSnapshotResponse;
import com.amazon.ec2.DeleteTagsResponse;
import com.amazon.ec2.DeleteVolumeResponse;
import com.amazon.ec2.DeregisterImageResponse;
import com.amazon.ec2.DescribeAvailabilityZonesResponse;
import com.amazon.ec2.DescribeImageAttributeResponse;
import com.amazon.ec2.DescribeImagesResponse;
import com.amazon.ec2.DescribeInstanceAttributeResponse;
import com.amazon.ec2.DescribeInstancesResponse;
import com.amazon.ec2.DescribeKeyPairsResponse;
import com.amazon.ec2.DescribeSecurityGroupsResponse;
import com.amazon.ec2.DescribeSnapshotsResponse;
import com.amazon.ec2.DescribeTagsResponse;
import com.amazon.ec2.DescribeVolumesResponse;
import com.amazon.ec2.DetachVolumeResponse;
import com.amazon.ec2.DisassociateAddressResponse;
import com.amazon.ec2.GetPasswordDataResponse;
import com.amazon.ec2.ImportKeyPairResponse;
import com.amazon.ec2.ModifyImageAttributeResponse;
import com.amazon.ec2.ModifyInstanceAttributeResponse;
import com.amazon.ec2.RebootInstancesResponse;
import com.amazon.ec2.RegisterImageResponse;
import com.amazon.ec2.ReleaseAddressResponse;
import com.amazon.ec2.ResetImageAttributeResponse;
import com.amazon.ec2.RevokeSecurityGroupIngressResponse;
import com.amazon.ec2.RunInstancesResponse;
import com.amazon.ec2.StartInstancesResponse;
import com.amazon.ec2.StopInstancesResponse;
import com.amazon.ec2.TerminateInstancesResponse;
import com.cloud.bridge.model.UserCredentialsVO;
import com.cloud.bridge.persist.dao.CloudStackUserDaoImpl;
import com.cloud.bridge.persist.dao.OfferingDaoImpl;
import com.cloud.bridge.persist.dao.UserCredentialsDaoImpl;
import com.cloud.bridge.service.controller.s3.ServiceProvider;
import com.cloud.bridge.service.core.ec2.EC2AddressFilterSet;
import com.cloud.bridge.service.core.ec2.EC2AssociateAddress;
import com.cloud.bridge.service.core.ec2.EC2AuthorizeRevokeSecurityGroup;
import com.cloud.bridge.service.core.ec2.EC2AvailabilityZonesFilterSet;
import com.cloud.bridge.service.core.ec2.EC2CreateImage;
import com.cloud.bridge.service.core.ec2.EC2CreateKeyPair;
import com.cloud.bridge.service.core.ec2.EC2CreateVolume;
import com.cloud.bridge.service.core.ec2.EC2DeleteKeyPair;
import com.cloud.bridge.service.core.ec2.EC2DescribeAddresses;
import com.cloud.bridge.service.core.ec2.EC2DescribeAvailabilityZones;
import com.cloud.bridge.service.core.ec2.EC2DescribeImageAttribute;
import com.cloud.bridge.service.core.ec2.EC2DescribeImages;
import com.cloud.bridge.service.core.ec2.EC2DescribeInstances;
import com.cloud.bridge.service.core.ec2.EC2DescribeKeyPairs;
import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroups;
import com.cloud.bridge.service.core.ec2.EC2DescribeSnapshots;
import com.cloud.bridge.service.core.ec2.EC2DescribeTags;
import com.cloud.bridge.service.core.ec2.EC2DescribeVolumes;
import com.cloud.bridge.service.core.ec2.EC2DisassociateAddress;
import com.cloud.bridge.service.core.ec2.EC2Engine;
import com.cloud.bridge.service.core.ec2.EC2Filter;
import com.cloud.bridge.service.core.ec2.EC2GroupFilterSet;
import com.cloud.bridge.service.core.ec2.EC2Image;
import com.cloud.bridge.service.core.ec2.EC2ImageAttributes.ImageAttribute;
import com.cloud.bridge.service.core.ec2.EC2ImageFilterSet;
import com.cloud.bridge.service.core.ec2.EC2ImageLaunchPermission;
import com.cloud.bridge.service.core.ec2.EC2ImportKeyPair;
import com.cloud.bridge.service.core.ec2.EC2InstanceFilterSet;
import com.cloud.bridge.service.core.ec2.EC2IpPermission;
import com.cloud.bridge.service.core.ec2.EC2KeyPairFilterSet;
import com.cloud.bridge.service.core.ec2.EC2ModifyImageAttribute;
import com.cloud.bridge.service.core.ec2.EC2ModifyInstanceAttribute;
import com.cloud.bridge.service.core.ec2.EC2RebootInstances;
import com.cloud.bridge.service.core.ec2.EC2RegisterImage;
import com.cloud.bridge.service.core.ec2.EC2ReleaseAddress;
import com.cloud.bridge.service.core.ec2.EC2RunInstances;
import com.cloud.bridge.service.core.ec2.EC2SecurityGroup;
import com.cloud.bridge.service.core.ec2.EC2SnapshotFilterSet;
import com.cloud.bridge.service.core.ec2.EC2StartInstances;
import com.cloud.bridge.service.core.ec2.EC2StopInstances;
import com.cloud.bridge.service.core.ec2.EC2Tags;
import com.cloud.bridge.service.core.ec2.EC2TagsFilterSet;
import com.cloud.bridge.service.core.ec2.EC2Volume;
import com.cloud.bridge.service.core.ec2.EC2VolumeFilterSet;
import com.cloud.bridge.service.exception.EC2ServiceException;
import com.cloud.bridge.service.exception.EC2ServiceException.ClientError;
import com.cloud.bridge.service.exception.NoSuchObjectException;
import com.cloud.bridge.service.exception.PermissionDeniedException;
import com.cloud.bridge.util.AuthenticationUtils;
import com.cloud.bridge.util.ConfigurationHelper;
import com.cloud.bridge.util.EC2RestAuth;
import com.cloud.stack.models.CloudStackAccount;
import com.cloud.utils.db.TransactionLegacy;

@Component("EC2RestServlet")
public class EC2RestServlet extends HttpServlet {

    private static final long serialVersionUID = -6168996266762804888L;
    @Inject
    UserCredentialsDaoImpl ucDao;
    @Inject
    OfferingDaoImpl ofDao;
    @Inject
    CloudStackUserDaoImpl userDao;

    public static final Logger logger = Logger.getLogger(EC2RestServlet.class);

    private final OMFactory factory = OMAbstractFactory.getOMFactory();
    private final XMLOutputFactory xmlOutFactory = XMLOutputFactory.newInstance();

    private String pathToKeystore = null;
    private String keystorePassword = null;
    private String wsdlVersion = null;
    private String version = null;

    boolean debug = true;

    public EC2RestServlet() {
    }

    /**
     * We build the path to where the keystore holding the WS-Security X509 certificates
     * are stored.
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext());

        File propertiesFile = ConfigurationHelper.findConfigurationFile("ec2-service.properties");
        Properties EC2Prop = null;

        if (null != propertiesFile) {
            logger.info("Use EC2 properties file: " + propertiesFile.getAbsolutePath());
            EC2Prop = new Properties();
            FileInputStream ec2PropFile = null;
            try {
                ec2PropFile = new FileInputStream(propertiesFile);
                EC2Prop.load(ec2PropFile);
            } catch (FileNotFoundException e) {
                logger.warn("Unable to open properties file: " + propertiesFile.getAbsolutePath(), e);
            } catch (IOException e) {
                logger.warn("Unable to read properties file: " + propertiesFile.getAbsolutePath(), e);
            } finally {
                IOUtils.closeQuietly(ec2PropFile);
            }
            String keystore = EC2Prop.getProperty("keystore");
            keystorePassword = EC2Prop.getProperty("keystorePass");
            wsdlVersion = EC2Prop.getProperty("WSDLVersion", "2012-08-15");
            version = EC2Prop.getProperty("cloudbridgeVersion", "UNKNOWN VERSION");

            String installedPath = System.getenv("CATALINA_HOME");
            if (installedPath == null)
                installedPath = System.getenv("CATALINA_BASE");
            if (installedPath == null)
                installedPath = System.getProperty("catalina.home");
            String webappPath = config.getServletContext().getRealPath("/");
            //pathToKeystore = new String( installedPath + File.separator + "webapps" + File.separator + webappName + File.separator + "WEB-INF" + File.separator + "classes" + File.separator + keystore );
            pathToKeystore = new String(webappPath + File.separator + "WEB-INF" + File.separator + "classes" + File.separator + keystore);
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        doGetOrPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
        doGetOrPost(req, resp);
    }

    protected void doGetOrPost(HttpServletRequest request, HttpServletResponse response) {

        if (debug) {
            System.out.println("EC2RestServlet.doGetOrPost: javax.servlet.forward.request_uri: " + request.getAttribute("javax.servlet.forward.request_uri"));
            System.out.println("EC2RestServlet.doGetOrPost: javax.servlet.forward.context_path: " + request.getAttribute("javax.servlet.forward.context_path"));
            System.out.println("EC2RestServlet.doGetOrPost: javax.servlet.forward.servlet_path: " + request.getAttribute("javax.servlet.forward.servlet_path"));
            System.out.println("EC2RestServlet.doGetOrPost: javax.servlet.forward.path_info: " + request.getAttribute("javax.servlet.forward.path_info"));
            System.out.println("EC2RestServlet.doGetOrPost: javax.servlet.forward.query_string: " + request.getAttribute("javax.servlet.forward.query_string"));

        }

        String action = request.getParameter("Action");
        logRequest(request);

        // -> unauthenticated calls, should still be done over HTTPS
        if (action.equalsIgnoreCase("SetUserKeys")) {
            setUserKeys(request, response);
            return;
        }

        if (action.equalsIgnoreCase("CloudEC2Version")) {
            cloudEC2Version(request, response);
            return;
        }

        // -> authenticated calls
        try {
            if (!authenticateRequest(request, response))
                return;

            if (action.equalsIgnoreCase("AllocateAddress"))
                allocateAddress(request, response);
            else if (action.equalsIgnoreCase("AssociateAddress"))
                associateAddress(request, response);
            else if (action.equalsIgnoreCase("AttachVolume"))
                attachVolume(request, response);
            else if (action.equalsIgnoreCase("AuthorizeSecurityGroupIngress"))
                authorizeSecurityGroupIngress(request, response);
            else if (action.equalsIgnoreCase("CreateImage"))
                createImage(request, response);
            else if (action.equalsIgnoreCase("CreateSecurityGroup"))
                createSecurityGroup(request, response);
            else if (action.equalsIgnoreCase("CreateSnapshot"))
                createSnapshot(request, response);
            else if (action.equalsIgnoreCase("CreateVolume"))
                createVolume(request, response);
            else if (action.equalsIgnoreCase("DeleteSecurityGroup"))
                deleteSecurityGroup(request, response);
            else if (action.equalsIgnoreCase("DeleteSnapshot"))
                deleteSnapshot(request, response);
            else if (action.equalsIgnoreCase("DeleteVolume"))
                deleteVolume(request, response);
            else if (action.equalsIgnoreCase("DeregisterImage"))
                deregisterImage(request, response);
            else if (action.equalsIgnoreCase("DescribeAddresses"))
                describeAddresses(request, response);
            else if (action.equalsIgnoreCase("DescribeAvailabilityZones"))
                describeAvailabilityZones(request, response);
            else if (action.equalsIgnoreCase("DescribeImageAttribute"))
                describeImageAttribute(request, response);
            else if (action.equalsIgnoreCase("DescribeImages"))
                describeImages(request, response);
            else if (action.equalsIgnoreCase("DescribeInstanceAttribute"))
                describeInstanceAttribute(request, response);
            else if (action.equalsIgnoreCase("DescribeInstances"))
                describeInstances(request, response);
            else if (action.equalsIgnoreCase("DescribeSecurityGroups"))
                describeSecurityGroups(request, response);
            else if (action.equalsIgnoreCase("DescribeSnapshots"))
                describeSnapshots(request, response);
            else if (action.equalsIgnoreCase("DescribeVolumes"))
                describeVolumes(request, response);
            else if (action.equalsIgnoreCase("DetachVolume"))
                detachVolume(request, response);
            else if (action.equalsIgnoreCase("DisassociateAddress"))
                disassociateAddress(request, response);
            else if (action.equalsIgnoreCase("ModifyImageAttribute"))
                modifyImageAttribute(request, response);
            else if (action.equalsIgnoreCase("ModifyInstanceAttribute"))
                modifyInstanceAttribute(request, response);
            else if (action.equalsIgnoreCase("RebootInstances"))
                rebootInstances(request, response);
            else if (action.equalsIgnoreCase("RegisterImage"))
                registerImage(request, response);
            else if (action.equalsIgnoreCase("ReleaseAddress"))
                releaseAddress(request, response);
            else if (action.equalsIgnoreCase("ResetImageAttribute"))
                resetImageAttribute(request, response);
            else if (action.equalsIgnoreCase("RevokeSecurityGroupIngress"))
                revokeSecurityGroupIngress(request, response);
            else if (action.equalsIgnoreCase("RunInstances"))
                runInstances(request, response);
            else if (action.equalsIgnoreCase("StartInstances"))
                startInstances(request, response);
            else if (action.equalsIgnoreCase("StopInstances"))
                stopInstances(request, response);
            else if (action.equalsIgnoreCase("TerminateInstances"))
                terminateInstances(request, response);
            else if (action.equalsIgnoreCase("SetCertificate"))
                setCertificate(request, response);
            else if (action.equalsIgnoreCase("DeleteCertificate"))
                deleteCertificate(request, response);
            else if (action.equalsIgnoreCase("SetOfferMapping"))
                setOfferMapping(request, response);
            else if (action.equalsIgnoreCase("DeleteOfferMapping"))
                deleteOfferMapping(request, response);
            else if (action.equalsIgnoreCase("CreateKeyPair"))
                createKeyPair(request, response);
            else if (action.equalsIgnoreCase("ImportKeyPair"))
                importKeyPair(request, response);
            else if (action.equalsIgnoreCase("DeleteKeyPair"))
                deleteKeyPair(request, response);
            else if (action.equalsIgnoreCase("DescribeKeyPairs"))
                describeKeyPairs(request, response);
            else if (action.equalsIgnoreCase("CreateTags"))
                createTags(request, response);
            else if (action.equalsIgnoreCase("DeleteTags"))
                deleteTags(request, response);
            else if (action.equalsIgnoreCase("DescribeTags"))
                describeTags(request, response);
            else if (action.equalsIgnoreCase("GetPasswordData"))
                getPasswordData(request, response);
            else {
                logger.error("Unsupported action " + action);
                throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
            }

        } catch (EC2ServiceException e) {
            response.setStatus(e.getErrorCode());

            if (e.getCause() != null && e.getCause() instanceof AxisFault) {
                String errorCode = ((AxisFault)e.getCause()).getFaultCode().getLocalPart();
                if (errorCode.startsWith("Client.")) // only in a SOAP API client error code is prefixed with Client.
                    errorCode = errorCode.split("Client.")[1];
                else if (errorCode.startsWith("Server.")) // only in a SOAP API server error code is prefixed with Server.
                    errorCode = errorCode.split("Server.")[1];
                faultResponse(response, errorCode, e.getMessage());
            } else {
                logger.error("EC2ServiceException: " + e.getMessage(), e);
                endResponse(response, e.toString());
            }
        } catch (PermissionDeniedException e) {
            logger.error("Unexpected exception: " + e.getMessage(), e);
            response.setStatus(403);
            endResponse(response, "Access denied");

        } catch (Exception e) {
            logger.error("Unexpected exception: " + e.getMessage(), e);
            response.setStatus(500);
            endResponse(response, e.toString());

        } finally {
            try {
                response.flushBuffer();
            } catch (IOException e) {
                logger.error("Unexpected exception " + e.getMessage(), e);
            }
        }
    }

    /**
     * Provide an easy way to determine the version of the implementation running.
     *
     * This is an unauthenticated REST call.
     */
    private void cloudEC2Version(HttpServletRequest request, HttpServletResponse response) {
        String version_response = new String("<?xml version=\"1.0\" encoding=\"utf-8\"?><CloudEC2Version>" + version + "</CloudEC2Version>");
        response.setStatus(200);
        endResponse(response, version_response);
    }

    /**
     * This request registers the Cloud.com account holder to the EC2 service.   The Cloud.com
     * account holder saves his API access and secret keys with the EC2 service so that
     * the EC2 service can make Cloud.com API calls on his behalf.   The given API access
     * and secret key are saved into the "usercredentials" database table.
     *
     * This is an unauthenticated REST call.   The only required parameters are 'accesskey' and
     * 'secretkey'.
     *
     * To verify that the given keys represent an existing account they are used to execute the
     * Cloud.com's listAccounts API function.   If the keys do not represent a valid account the
     * listAccounts function will fail.
     *
     * A user can call this REST function any number of times, on each call the Cloud.com secret
     * key is simply over writes any previously stored value.
     *
     * As with all REST calls HTTPS should be used to ensure their security.
     */
    private void setUserKeys(HttpServletRequest request, HttpServletResponse response) {
        String[] accessKey = null;
        String[] secretKey = null;
        TransactionLegacy txn = null;
        try {
            // -> all these parameters are required
            accessKey = request.getParameterValues("accesskey");
            if (null == accessKey || 0 == accessKey.length) {
                response.sendError(530, "Missing accesskey parameter");
                return;
            }

            secretKey = request.getParameterValues("secretkey");
            if (null == secretKey || 0 == secretKey.length) {
                response.sendError(530, "Missing secretkey parameter");
                return;
            }
        } catch (Exception e) {
            logger.error("SetUserKeys exception " + e.getMessage(), e);
            response.setStatus(500);
            endResponse(response, "SetUserKeys exception " + e.getMessage());
            return;
        }
        try {
            txn = TransactionLegacy.open(TransactionLegacy.AWSAPI_DB);
            txn.start();
            // -> use the keys to see if the account actually exists
            ServiceProvider.getInstance().getEC2Engine().validateAccount(accessKey[0], secretKey[0]);
            UserCredentialsVO user = new UserCredentialsVO(accessKey[0], secretKey[0]);
            ucDao.persist(user);
            txn.commit();
        } catch (Exception e) {
            logger.error("SetUserKeys " + e.getMessage(), e);
            response.setStatus(401);
            endResponse(response, e.toString());
            txn.close();
            return;
        }
        response.setStatus(200);
        endResponse(response, "User keys set successfully");
    }

    /**
     * The SOAP API for EC2 uses WS-Security to sign all client requests.  This requires that
     * the client have a public/private key pair and the public key defined by a X509 certificate.
     * Thus in order for a Cloud.com account holder to use the EC2's SOAP API he must register
     * his X509 certificate with the EC2 service.   This function allows the Cloud.com account
     * holder to "load" his X509 certificate into the service.   Note, that the SetUserKeys REST
     * function must be called before this call.
     *
     * This is an authenticated REST call and as such must contain all the required REST parameters
     * including: Signature, Timestamp, Expires, etc.   The signature is calculated using the
     * Cloud.com account holder's API access and secret keys and the Amazon defined EC2 signature
     * algorithm.
     *
     * A user can call this REST function any number of times, on each call the X509 certificate
     * simply over writes any previously stored value.
     */
    private void setCertificate(HttpServletRequest request, HttpServletResponse response) throws Exception {
        TransactionLegacy txn = null;
        try {
            // [A] Pull the cert and cloud AccessKey from the request
            String[] certificate = request.getParameterValues("cert");
            if (null == certificate || 0 == certificate.length) {
                response.sendError(530, "Missing cert parameter");
                return;
            }
            // logger.debug( "SetCertificate cert: [" + certificate[0] + "]" );

            String[] accessKey = request.getParameterValues("AWSAccessKeyId");
            if (null == accessKey || 0 == accessKey.length) {
                response.sendError(530, "Missing AWSAccessKeyId parameter");
                return;
            }

            // [B] Open our keystore
            FileInputStream fsIn = new FileInputStream(pathToKeystore);
            KeyStore certStore = KeyStore.getInstance("JKS");
            certStore.load(fsIn, keystorePassword.toCharArray());

            // -> use the Cloud API key to save the cert in the keystore
            // -> write the cert into the keystore on disk
            Certificate userCert = null;
            CertificateFactory cf = CertificateFactory.getInstance("X.509");

            ByteArrayInputStream bs = new ByteArrayInputStream(certificate[0].getBytes());
            while (bs.available() > 0)
                userCert = cf.generateCertificate(bs);
            certStore.setCertificateEntry(accessKey[0], userCert);

            FileOutputStream fsOut = new FileOutputStream(pathToKeystore);
            certStore.store(fsOut, keystorePassword.toCharArray());

            // [C] Associate the cert's uniqueId with the Cloud API keys
            String uniqueId = AuthenticationUtils.X509CertUniqueId(userCert);
            logger.debug("SetCertificate, uniqueId: " + uniqueId);
            txn = TransactionLegacy.open(TransactionLegacy.AWSAPI_DB);
            txn.start();
            UserCredentialsVO user = ucDao.getByAccessKey(accessKey[0]);
            user.setCertUniqueId(uniqueId);
            ucDao.update(user.getId(), user);
            response.setStatus(200);
            endResponse(response, "User certificate set successfully");
            txn.commit();

        } catch (NoSuchObjectException e) {
            logger.error("SetCertificate exception " + e.getMessage(), e);
            response.sendError(404, "SetCertificate exception " + e.getMessage());

        } catch (Exception e) {
            logger.error("SetCertificate exception " + e.getMessage(), e);
            response.sendError(500, "SetCertificate exception " + e.getMessage());
        } finally {
            txn.close();
        }

    }

    /**
     * The SOAP API for EC2 uses WS-Security to sign all client requests.  This requires that
     * the client have a public/private key pair and the public key defined by a X509 certificate.
     * This REST call allows a Cloud.com account holder to remove a previouly "loaded" X509
     * certificate out of the EC2 service.
     *
     * This is an unauthenticated REST call and as such must contain all the required REST parameters
     * including: Signature, Timestamp, Expires, etc.   The signature is calculated using the
     * Cloud.com account holder's API access and secret keys and the Amazon defined EC2 signature
     * algorithm.
     */
    private void deleteCertificate(HttpServletRequest request, HttpServletResponse response) throws Exception {
        TransactionLegacy txn = null;
        try {
            String[] accessKey = request.getParameterValues("AWSAccessKeyId");
            if (null == accessKey || 0 == accessKey.length) {
                response.sendError(530, "Missing AWSAccessKeyId parameter");
                return;
            }

            // -> delete the specified entry and save back to disk
            FileInputStream fsIn = new FileInputStream(pathToKeystore);
            KeyStore certStore = KeyStore.getInstance("JKS");
            certStore.load(fsIn, keystorePassword.toCharArray());

            if (certStore.containsAlias(accessKey[0])) {
                certStore.deleteEntry(accessKey[0]);
                FileOutputStream fsOut = new FileOutputStream(pathToKeystore);
                certStore.store(fsOut, keystorePassword.toCharArray());

                // -> dis-associate the cert's uniqueId with the Cloud API keys
                /*                  UserCredentialsDao credentialDao = new UserCredentialsDao();
                 credentialDao.setCertificateId( accessKey[0], null );

                 */txn = TransactionLegacy.open(TransactionLegacy.AWSAPI_DB);
                UserCredentialsVO user = ucDao.getByAccessKey(accessKey[0]);
                user.setCertUniqueId(null);
                ucDao.update(user.getId(), user);
                response.setStatus(200);
                endResponse(response, "User certificate deleted successfully");
                txn.commit();
            } else
                response.setStatus(404);

        } catch (NoSuchObjectException e) {
            logger.error("SetCertificate exception " + e.getMessage(), e);
            response.sendError(404, "SetCertificate exception " + e.getMessage());

        } catch (Exception e) {
            logger.error("DeleteCertificate exception " + e.getMessage(), e);
            response.sendError(500, "DeleteCertificate exception " + e.getMessage());
        } finally {
            txn.close();
        }
    }

    /**
     * Allow the caller to define the mapping between the Amazon instance type strings
     * (e.g., m1.small, cc1.4xlarge) and the cloudstack service offering ids.  Setting
     * an existing mapping just over writes the prevous values.
     */
    private void setOfferMapping(HttpServletRequest request, HttpServletResponse response) {
        String amazonOffer = null;
        String cloudOffer = null;

        try {
            // -> all these parameters are required
            amazonOffer = request.getParameter("amazonoffer");
            if (null == amazonOffer) {
                response.sendError(530, "Missing amazonoffer parameter");
                return;
            }

            cloudOffer = request.getParameter("cloudoffer");
            if (null == cloudOffer) {
                response.sendError(530, "Missing cloudoffer parameter");
                return;
            }
        } catch (Exception e) {
            logger.error("SetOfferMapping exception " + e.getMessage(), e);
            response.setStatus(500);
            endResponse(response, "SetOfferMapping exception " + e.getMessage());
            return;
        }

        // validate account is admin level
        try {
            CloudStackAccount currentAccount = ServiceProvider.getInstance().getEC2Engine().getCurrentAccount();

            if (currentAccount.getAccountType() != 1) {
                logger.debug("SetOfferMapping called by non-admin user!");
                response.setStatus(500);
                endResponse(response, "Permission denied for non-admin user to setOfferMapping!");
                return;
            }
        } catch (Exception e) {
            logger.error("SetOfferMapping " + e.getMessage(), e);
            response.setStatus(401);
            endResponse(response, e.toString());
            return;
        }

        try {

            ofDao.setOfferMapping(amazonOffer, cloudOffer);

        } catch (Exception e) {
            logger.error("SetOfferMapping " + e.getMessage(), e);
            response.setStatus(401);
            endResponse(response, e.toString());
            return;
        }
        response.setStatus(200);
        endResponse(response, "offering mapping set successfully");
    }

    private void deleteOfferMapping(HttpServletRequest request, HttpServletResponse response) {
        String amazonOffer = null;

        try {
            // -> all these parameters are required
            amazonOffer = request.getParameter("amazonoffer");
            if (null == amazonOffer) {
                response.sendError(530, "Missing amazonoffer parameter");
                return;
            }

        } catch (Exception e) {
            logger.error("DeleteOfferMapping exception " + e.getMessage(), e);
            response.setStatus(500);
            endResponse(response, "DeleteOfferMapping exception " + e.getMessage());
            return;
        }

        // validate account is admin level
        try {
            CloudStackAccount currentAccount = ServiceProvider.getInstance().getEC2Engine().getCurrentAccount();

            if (currentAccount.getAccountType() != 1) {
                logger.debug("deleteOfferMapping called by non-admin user!");
                response.setStatus(500);
                endResponse(response, "Permission denied for non-admin user to deleteOfferMapping!");
                return;
            }
        } catch (Exception e) {
            logger.error("deleteOfferMapping " + e.getMessage(), e);
            response.setStatus(401);
            endResponse(response, e.toString());
            return;
        }

        try {
            ofDao.deleteOfferMapping(amazonOffer);
        } catch (Exception e) {
            logger.error("DeleteOfferMapping " + e.getMessage(), e);
            response.setStatus(401);
            endResponse(response, e.toString());
            return;
        }
        response.setStatus(200);
        endResponse(response, "offering mapping deleted successfully");
    }

    /**
     * The approach taken here is to map these REST calls into the same objects used
     * to implement the matching SOAP requests (e.g., AttachVolume).   This is done by parsing
     * out the URL parameters and loading them into the relevant EC2XXX object(s).   Once
     * the parameters are loaded the appropriate EC2Engine function is called to perform
     * the requested action.   The result of the EC2Engine function is a standard
     * Amazon WSDL defined object (e.g., AttachVolumeResponse Java object).   Finally the
     * serialize method is called on the returned response object to obtain the extected
     * response XML.
     */
    private void attachVolume(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2Volume EC2request = new EC2Volume();

        // -> all these parameters are required
        String[] volumeId = request.getParameterValues("VolumeId");
        if (null != volumeId && 0 < volumeId.length)
            EC2request.setId(volumeId[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - VolumeId");
        }

        String[] instanceId = request.getParameterValues("InstanceId");
        if (null != instanceId && 0 < instanceId.length)
            EC2request.setInstanceId(instanceId[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId");
        }

        String[] device = request.getParameterValues("Device");
        if (null != device && 0 < device.length)
            EC2request.setDevice(device[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Device");
        }

        // -> execute the request
        AttachVolumeResponse EC2response = EC2SoapServiceImpl.toAttachVolumeResponse(ServiceProvider.getInstance().getEC2Engine().attachVolume(EC2request));
        serializeResponse(response, EC2response);
    }

    /**
     * The SOAP equivalent of this function appears to allow multiple permissions per request, yet
     * in the REST API documentation only one permission is allowed.
     */
    private void revokeSecurityGroupIngress(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2AuthorizeRevokeSecurityGroup EC2request = new EC2AuthorizeRevokeSecurityGroup();

        String[] groupName = request.getParameterValues("GroupName");
        if (null != groupName && 0 < groupName.length)
            EC2request.setName(groupName[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - GroupName");
        }

        // -> not clear how many parameters there are until we fail to get IpPermissions.n.IpProtocol
        int nCount = 1, mCount;
        do {
            EC2IpPermission perm = new EC2IpPermission();

            String[] protocol = request.getParameterValues("IpPermissions." + nCount + ".IpProtocol");
            if (null != protocol && 0 < protocol.length)
                perm.setProtocol(protocol[0]);
            else
                break;

            String[] fromPort = request.getParameterValues("IpPermissions." + nCount + ".FromPort");
            if (null != fromPort && 0 < fromPort.length) {
                if (protocol[0].equalsIgnoreCase("icmp"))
                    perm.setIcmpType(fromPort[0]);
                else
                    perm.setFromPort(Integer.parseInt(fromPort[0]));
            }

            String[] toPort = request.getParameterValues("IpPermissions." + nCount + ".ToPort");
            if (null != toPort && 0 < toPort.length) {
                if (protocol[0].equalsIgnoreCase("icmp"))
                    perm.setIcmpCode(toPort[0]);
                else
                    perm.setToPort(Integer.parseInt(toPort[0]));
            }

            // -> list: IpPermissions.n.IpRanges.m.CidrIp
            mCount = 1;
            do {
                String[] ranges = request.getParameterValues("IpPermissions." + nCount + ".IpRanges." + mCount + ".CidrIp");
                if (null != ranges && 0 < ranges.length)
                    perm.addIpRange(ranges[0]);
                else
                    break;
                mCount++;
            } while (true);

            // -> list: IpPermissions.n.Groups.m.UserId and IpPermissions.n.Groups.m.GroupName
            mCount = 1;
            do {
                EC2SecurityGroup group = new EC2SecurityGroup();

                String[] user = request.getParameterValues("IpPermissions." + nCount + ".Groups." + mCount + ".UserId");
                if (null != user && 0 < user.length)
                    group.setAccount(user[0]);
                else
                    break;

                String[] name = request.getParameterValues("IpPermissions." + nCount + ".Groups." + mCount + ".GroupName");
                if (null != name && 0 < name.length)
                    group.setName(name[0]);
                else
                    break;

                perm.addUser(group);
                mCount++;
            } while (true);

            // -> multiple IP permissions can be specified per group name
            EC2request.addIpPermission(perm);
            nCount++;
        } while (true);

        if (1 == nCount) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - IpPermissions");
        }

        // -> execute the request
        RevokeSecurityGroupIngressResponse EC2response =
            EC2SoapServiceImpl.toRevokeSecurityGroupIngressResponse(ServiceProvider.getInstance().getEC2Engine().revokeSecurityGroup(EC2request));
        serializeResponse(response, EC2response);
    }

    private void authorizeSecurityGroupIngress(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        // -> parse the complicated paramters into our standard object
        EC2AuthorizeRevokeSecurityGroup EC2request = new EC2AuthorizeRevokeSecurityGroup();

        String[] groupName = request.getParameterValues("GroupName");
        if (null != groupName && 0 < groupName.length)
            EC2request.setName(groupName[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter 'Groupname'");
        }

        // -> not clear how many parameters there are until we fail to get IpPermissions.n.IpProtocol
        int nCount = 1;
        do {
            EC2IpPermission perm = new EC2IpPermission();

            String[] protocol = request.getParameterValues("IpPermissions." + nCount + ".IpProtocol");
            if (null != protocol && 0 < protocol.length)
                perm.setProtocol(protocol[0]);
            else
                break;

            String[] fromPort = request.getParameterValues("IpPermissions." + nCount + ".FromPort");
            if (null != fromPort && 0 < fromPort.length) {
                if (protocol[0].equalsIgnoreCase("icmp"))
                    perm.setIcmpType(fromPort[0]);
                else
                    perm.setFromPort(Integer.parseInt(fromPort[0]));
            }

            String[] toPort = request.getParameterValues("IpPermissions." + nCount + ".ToPort");
            if (null != toPort && 0 < toPort.length) {
                if (protocol[0].equalsIgnoreCase("icmp"))
                    perm.setIcmpCode(toPort[0]);
                else
                    perm.setToPort(Integer.parseInt(toPort[0]));
            }

            // -> list: IpPermissions.n.IpRanges.m.CidrIp
            int mCount = 1;
            do {
                String[] ranges = request.getParameterValues("IpPermissions." + nCount + ".IpRanges." + mCount + ".CidrIp");
                if (null != ranges && 0 < ranges.length)
                    perm.addIpRange(ranges[0]);
                else
                    break;
                mCount++;

            } while (true);

            // -> list: IpPermissions.n.Groups.m.UserId and IpPermissions.n.Groups.m.GroupName
            mCount = 1;
            do {
                String[] user = request.getParameterValues("IpPermissions." + nCount + ".Groups." + mCount + ".UserId");
                if (null == user || 0 == user.length)
                    break;

                String[] name = request.getParameterValues("IpPermissions." + nCount + ".Groups." + mCount + ".GroupName");
                if (null == name || 0 == name.length)
                    break;

                EC2SecurityGroup group = new EC2SecurityGroup();
                group.setAccount(user[0]);
                group.setName(name[0]);
                perm.addUser(group);
                mCount++;

            } while (true);

            // -> multiple IP permissions can be specified per group name
            EC2request.addIpPermission(perm);
            nCount++;

        } while (true);

        if (1 == nCount) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - IpPermissions");
        }

        // -> execute the request
        AuthorizeSecurityGroupIngressResponse EC2response =
            EC2SoapServiceImpl.toAuthorizeSecurityGroupIngressResponse(ServiceProvider.getInstance().getEC2Engine().authorizeSecurityGroup(EC2request));
        serializeResponse(response, EC2response);
    }

    private void detachVolume(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2Volume EC2request = new EC2Volume();

        String[] volumeId = request.getParameterValues("VolumeId");
        if (null != volumeId && 0 < volumeId.length)
            EC2request.setId(volumeId[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter 'VolumeId'");
        }

        String[] instanceId = request.getParameterValues("InstanceId");
        if (null != instanceId && 0 < instanceId.length)
            EC2request.setInstanceId(instanceId[0]);

        String[] device = request.getParameterValues("Device");
        if (null != device && 0 < device.length)
            EC2request.setDevice(device[0]);

        // -> execute the request
        DetachVolumeResponse EC2response = EC2SoapServiceImpl.toDetachVolumeResponse(ServiceProvider.getInstance().getEC2Engine().detachVolume(EC2request));
        serializeResponse(response, EC2response);
    }

    private void deleteVolume(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2Volume EC2request = new EC2Volume();

        String[] volumeId = request.getParameterValues("VolumeId");
        if (null != volumeId && 0 < volumeId.length)
            EC2request.setId(volumeId[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - VolumeId");
        }

        // -> execute the request
        DeleteVolumeResponse EC2response = EC2SoapServiceImpl.toDeleteVolumeResponse(ServiceProvider.getInstance().getEC2Engine().deleteVolume(EC2request));
        serializeResponse(response, EC2response);
    }

    private void createVolume(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2CreateVolume EC2request = new EC2CreateVolume();

        String[] zoneName = request.getParameterValues("AvailabilityZone");
        if (null != zoneName && 0 < zoneName.length)
            EC2request.setZoneName(zoneName[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing parameter - AvailabilityZone");
        }

        String[] size = request.getParameterValues("Size");
        String[] snapshotId = request.getParameterValues("SnapshotId");
        boolean useSnapshot = false;
        boolean useSize = false;

        if (null != size && 0 < size.length)
            useSize = true;

        if (snapshotId != null && snapshotId.length != 0)
            useSnapshot = true;

        if (useSize && !useSnapshot) {
            EC2request.setSize(size[0]);
        } else if (useSnapshot && !useSize) {
            EC2request.setSnapshotId(snapshotId[0]);
        } else if (useSize && useSnapshot) {
            throw new EC2ServiceException(ClientError.InvalidParameterCombination, "Parameters 'Size' and 'SnapshotId' are mutually exclusive");
        } else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Parameter 'Size' or 'SnapshotId' has to be specified");
        }

        // -> execute the request
        CreateVolumeResponse EC2response = EC2SoapServiceImpl.toCreateVolumeResponse(ServiceProvider.getInstance().getEC2Engine().createVolume(EC2request));
        serializeResponse(response, EC2response);
    }

    private void createSecurityGroup(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {

        String groupName, groupDescription = null;

        String[] name = request.getParameterValues("GroupName");
        if (null != name && 0 < name.length)
            groupName = name[0];
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - GroupName");
        }
        String[] desc = request.getParameterValues("GroupDescription");
        if (null != desc && 0 < desc.length)
            groupDescription = desc[0];
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - GroupDescription");
        }

        // -> execute the request
        CreateSecurityGroupResponse EC2response =
            EC2SoapServiceImpl.toCreateSecurityGroupResponse(ServiceProvider.getInstance().getEC2Engine().createSecurityGroup(groupName, groupDescription));
        serializeResponse(response, EC2response);
    }

    private void deleteSecurityGroup(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        String groupName = null;

        String[] name = request.getParameterValues("GroupName");
        if (null != name && 0 < name.length)
            groupName = name[0];
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - GroupName");
        }

        // -> execute the request
        DeleteSecurityGroupResponse EC2response =
            EC2SoapServiceImpl.toDeleteSecurityGroupResponse(ServiceProvider.getInstance().getEC2Engine().deleteSecurityGroup(groupName));
        serializeResponse(response, EC2response);
    }

    private void deleteSnapshot(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        String snapshotId = null;

        String[] snapSet = request.getParameterValues("SnapshotId");
        if (null != snapSet && 0 < snapSet.length)
            snapshotId = snapSet[0];
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - SnapshotId");
        }

        // -> execute the request
        DeleteSnapshotResponse EC2response = EC2SoapServiceImpl.toDeleteSnapshotResponse(ServiceProvider.getInstance().getEC2Engine().deleteSnapshot(snapshotId));
        serializeResponse(response, EC2response);
    }

    private void createSnapshot(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        String volumeId = null;

        String[] volSet = request.getParameterValues("VolumeId");
        if (null != volSet && 0 < volSet.length)
            volumeId = volSet[0];
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - VolumeId");
        }

        // -> execute the request
        EC2Engine engine = ServiceProvider.getInstance().getEC2Engine();
        CreateSnapshotResponse EC2response = EC2SoapServiceImpl.toCreateSnapshotResponse(engine.createSnapshot(volumeId), engine);
        serializeResponse(response, EC2response);
    }

    private void deregisterImage(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2Image image = new EC2Image();

        String[] imageId = request.getParameterValues("ImageId");
        if (null != imageId && 0 < imageId.length)
            image.setId(imageId[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - ImageId");
        }

        // -> execute the request
        DeregisterImageResponse EC2response = EC2SoapServiceImpl.toDeregisterImageResponse(ServiceProvider.getInstance().getEC2Engine().deregisterImage(image));
        serializeResponse(response, EC2response);
    }

    private void createImage(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2CreateImage EC2request = new EC2CreateImage();

        String[] instanceId = request.getParameterValues("InstanceId");
        if (null != instanceId && 0 < instanceId.length)
            EC2request.setInstanceId(instanceId[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId");
        }

        String[] name = request.getParameterValues("Name");
        if (null != name && 0 < name.length)
            EC2request.setName(name[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Name");
        }

        String[] description = request.getParameterValues("Description");
        if (null != description && 0 < description.length) {
            if (description[0].length() > 255)
                throw new EC2ServiceException(ClientError.InvalidParameterValue, "Length of the value of parameter Description should be less than 255");
            EC2request.setDescription(description[0]);
        }

        // -> execute the request
        CreateImageResponse EC2response = EC2SoapServiceImpl.toCreateImageResponse(ServiceProvider.getInstance().getEC2Engine().createImage(EC2request));
        serializeResponse(response, EC2response);
    }

    private void registerImage(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2RegisterImage EC2request = new EC2RegisterImage();

        String[] location = request.getParameterValues("ImageLocation");
        if (null != location && 0 < location.length)
            EC2request.setLocation(location[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing parameter - ImageLocation");
        }

        String[] cloudRedfined = request.getParameterValues("Architecture");
        if (null != cloudRedfined && 0 < cloudRedfined.length)
            EC2request.setArchitecture(cloudRedfined[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Architecture");
        }

        String[] name = request.getParameterValues("Name");
        if (null != name && 0 < name.length)
            EC2request.setName(name[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Name");
        }

        String[] description = request.getParameterValues("Description");
        if (null != description && 0 < description.length)
            EC2request.setDescription(description[0]);

        // -> execute the request
        RegisterImageResponse EC2response = EC2SoapServiceImpl.toRegisterImageResponse(ServiceProvider.getInstance().getEC2Engine().registerImage(EC2request));
        serializeResponse(response, EC2response);
    }

    private void modifyImageAttribute(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2ModifyImageAttribute ec2request = new EC2ModifyImageAttribute();

        String[] imageId = request.getParameterValues("ImageId");
        if (imageId != null && imageId.length > 0)
            ec2request.setImageId(imageId[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - ImageId");
        }

        String[] description = request.getParameterValues("Description.Value");
        if (description != null && description.length > 0) {
            ec2request.setAttribute(ImageAttribute.description);
            ec2request.setDescription(description[0]);
        } else {
            //add all launch permissions to ec2request
            ec2request = addLaunchPermImageAttribute(request, ec2request);
            if (ec2request.getLaunchPermissionSet().length > 0)
                ec2request.setAttribute(ImageAttribute.launchPermission);
            else {
                throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Description/LaunchPermission should be provided");
            }
        }

        // -> execute the request
        ModifyImageAttributeResponse EC2response =
            EC2SoapServiceImpl.toModifyImageAttributeResponse(ServiceProvider.getInstance().getEC2Engine().modifyImageAttribute(ec2request));
        serializeResponse(response, EC2response);
    }

    private EC2ModifyImageAttribute addLaunchPermImageAttribute(HttpServletRequest request, EC2ModifyImageAttribute ec2request) {
        String[] users = {".UserId", ".Group"};
        String[] operations = {"LaunchPermission.Add.", "LaunchPermission.Remove."};
        int nCount = 1;

        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                List<String> launchPermissionList = new ArrayList<String>();
                do {
                    String[] launchPermissionAddGroup = request.getParameterValues(operations[j] + nCount + users[i]);
                    if (launchPermissionAddGroup != null && launchPermissionAddGroup.length > 0)
                        launchPermissionList.add(launchPermissionAddGroup[0]);
                    else
                        break;
                    nCount++;
                } while (true);
                if (nCount != 1) {
                    EC2ImageLaunchPermission ec2LaunchPermission = new EC2ImageLaunchPermission();
                    if (operations[j].contains("Add"))
                        ec2LaunchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.add);
                    else
                        ec2LaunchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.remove);
                    for (String launchPerm : launchPermissionList) {
                        ec2LaunchPermission.addLaunchPermission(launchPerm);
                    }
                    ec2request.addLaunchPermission(ec2LaunchPermission);
                    nCount = 1;
                }
            }
        }

        return ec2request;
    }

    private void resetImageAttribute(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2ModifyImageAttribute ec2request = new EC2ModifyImageAttribute();

        String[] imageId = request.getParameterValues("ImageId");
        if (imageId != null && imageId.length > 0)
            ec2request.setImageId(imageId[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - ImageId");
        }

        String[] attribute = request.getParameterValues("Attribute");
        if (attribute != null && attribute.length > 0) {
            if (attribute[0].equalsIgnoreCase("launchPermission"))
                ec2request.setAttribute(ImageAttribute.launchPermission);
            else {
                throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Description/LaunchPermission should be provided");
            }
        } else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Attribute");
        }

        EC2ImageLaunchPermission launchPermission = new EC2ImageLaunchPermission();
        launchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.reset);
        ec2request.addLaunchPermission(launchPermission);

        // -> execute the request
        ResetImageAttributeResponse EC2response =
            EC2SoapServiceImpl.toResetImageAttributeResponse(ServiceProvider.getInstance().getEC2Engine().modifyImageAttribute(ec2request));
        serializeResponse(response, EC2response);
    }

    private void runInstances(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2RunInstances EC2request = new EC2RunInstances();

        // -> so in the Amazon docs for this REST call there is no userData even though there is in the SOAP docs
        String[] imageId = request.getParameterValues("ImageId");
        if (null != imageId && 0 < imageId.length)
            EC2request.setTemplateId(imageId[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - ImageId");
        }

        String[] minCount = request.getParameterValues("MinCount");
        if (minCount == null || minCount.length < 1) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - MinCount");
        } else if (Integer.parseInt(minCount[0]) < 1) {
            throw new EC2ServiceException(ClientError.InvalidParameterValue, "Value of parameter MinCount should be greater than 0");
        } else {
            EC2request.setMinCount(Integer.parseInt(minCount[0]));
        }

        String[] maxCount = request.getParameterValues("MaxCount");
        if (maxCount == null || maxCount.length < 1) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - MaxCount");
        } else if (Integer.parseInt(maxCount[0]) < 1) {
            throw new EC2ServiceException(ClientError.InvalidParameterValue, "Value of parameter MaxCount should be greater than 0");
        } else {
            EC2request.setMaxCount(Integer.parseInt(maxCount[0]));
        }

        String[] instanceType = request.getParameterValues("InstanceType");
        if (null != instanceType && 0 < instanceType.length)
            EC2request.setInstanceType(instanceType[0]);

        String[] zoneName = request.getParameterValues("Placement.AvailabilityZone");
        if (null != zoneName && 0 < zoneName.length)
            EC2request.setZoneName(zoneName[0]);

        String[] size = request.getParameterValues("size");
        if (size != null) {
            EC2request.setSize(Integer.valueOf(size[0]));
        }

        String[] keyName = request.getParameterValues("KeyName");
        if (keyName != null) {
            EC2request.setKeyName(keyName[0]);
        }

        String[] userData = request.getParameterValues("UserData");
        if (userData != null) {
            EC2request.setUserData(userData[0]);
        }

        Enumeration<?> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String key = (String)names.nextElement();
            if (key.startsWith("SecurityGroup")) {
                String[] value = request.getParameterValues(key);
                if (null != value && 0 < value.length) {
                    if (key.startsWith("SecurityGroupId"))
                        EC2request.addSecuritGroupId(value[0]);
                    else
                        EC2request.addSecuritGroupName(value[0]);
                }
            }
        }

        // -> execute the request
        EC2Engine engine = ServiceProvider.getInstance().getEC2Engine();
        RunInstancesResponse EC2response = EC2SoapServiceImpl.toRunInstancesResponse(engine.runInstances(EC2request), engine);
        serializeResponse(response, EC2response);
    }

    private void rebootInstances(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2RebootInstances EC2request = new EC2RebootInstances();
        int count = 0;

        // -> load in all the "InstanceId.n" parameters if any
        Enumeration<?> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String key = (String)names.nextElement();
            if (key.startsWith("InstanceId")) {
                String[] value = request.getParameterValues(key);
                if (null != value && 0 < value.length) {
                    EC2request.addInstanceId(value[0]);
                    count++;
                }
            }
        }
        if (0 == count) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId");
        }

        // -> execute the request
        RebootInstancesResponse EC2response = EC2SoapServiceImpl.toRebootInstancesResponse(ServiceProvider.getInstance().getEC2Engine().rebootInstances(EC2request));
        serializeResponse(response, EC2response);
    }

    private void startInstances(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2StartInstances EC2request = new EC2StartInstances();
        int count = 0;

        // -> load in all the "InstanceId.n" parameters if any
        Enumeration<?> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String key = (String)names.nextElement();
            if (key.startsWith("InstanceId")) {
                String[] value = request.getParameterValues(key);
                if (null != value && 0 < value.length) {
                    EC2request.addInstanceId(value[0]);
                    count++;
                }
            }
        }
        if (0 == count) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId");
        }

        // -> execute the request
        StartInstancesResponse EC2response = EC2SoapServiceImpl.toStartInstancesResponse(ServiceProvider.getInstance().getEC2Engine().startInstances(EC2request));
        serializeResponse(response, EC2response);
    }

    private void stopInstances(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2StopInstances EC2request = new EC2StopInstances();
        int count = 0;

        // -> load in all the "InstanceId.n" parameters if any
        Enumeration<?> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String key = (String)names.nextElement();
            if (key.startsWith("InstanceId")) {
                String[] value = request.getParameterValues(key);
                if (null != value && 0 < value.length) {
                    EC2request.addInstanceId(value[0]);
                    count++;
                }
            }
        }
        if (0 == count) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId");
        }

        String[] force = request.getParameterValues("Force");
        if (force != null) {
            EC2request.setForce(Boolean.parseBoolean(force[0]));
        }

        // -> execute the request
        StopInstancesResponse EC2response = EC2SoapServiceImpl.toStopInstancesResponse(ServiceProvider.getInstance().getEC2Engine().stopInstances(EC2request));
        serializeResponse(response, EC2response);
    }

    private void terminateInstances(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2StopInstances EC2request = new EC2StopInstances();
        int count = 0;

        // -> load in all the "InstanceId.n" parameters if any
        Enumeration<?> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String key = (String)names.nextElement();
            if (key.startsWith("InstanceId")) {
                String[] value = request.getParameterValues(key);
                if (null != value && 0 < value.length) {
                    EC2request.addInstanceId(value[0]);
                    count++;
                }
            }
        }
        if (0 == count) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId");
        }

        // -> execute the request
        EC2request.setDestroyInstances(true);
        TerminateInstancesResponse EC2response = EC2SoapServiceImpl.toTermInstancesResponse(ServiceProvider.getInstance().getEC2Engine().stopInstances(EC2request));
        serializeResponse(response, EC2response);
    }

    /**
     * We are reusing the SOAP code to process this request.   We then use Axiom to serialize the
     * resulting EC2 Amazon object into XML to return to the client.
     */
    private void describeAvailabilityZones(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2DescribeAvailabilityZones EC2request = new EC2DescribeAvailabilityZones();

        // -> load in all the "ZoneName.n" parameters if any
        Enumeration<?> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String key = (String)names.nextElement();
            if (key.startsWith("ZoneName")) {
                String[] value = request.getParameterValues(key);
                if (null != value && 0 < value.length)
                    EC2request.addZone(value[0]);
            }
        }

        // add filters
        EC2Filter[] filterSet = extractFilters(request);
        if (filterSet != null) {
            EC2AvailabilityZonesFilterSet afs = new EC2AvailabilityZonesFilterSet();
            for (int i = 0; i < filterSet.length; i++) {
                afs.addFilter(filterSet[i]);
            }
            EC2request.setFilterSet(afs);
        }

        // -> execute the request
        DescribeAvailabilityZonesResponse EC2response =
            EC2SoapServiceImpl.toDescribeAvailabilityZonesResponse(ServiceProvider.getInstance().getEC2Engine().describeAvailabilityZones(EC2request));
        serializeResponse(response, EC2response);
    }

    private void describeImages(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2DescribeImages EC2request = new EC2DescribeImages();

        // -> load in all the "ImageId.n" parameters if any, and ignore all other parameters
        Enumeration<?> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String key = (String)names.nextElement();
            if (key.startsWith("ImageId")) {
                String[] value = request.getParameterValues(key);
                if (null != value && 0 < value.length)
                    EC2request.addImageSet(value[0]);
            }
        }
        // add filters
        EC2Filter[] filterSet = extractFilters(request);
        if (filterSet != null) {
            EC2ImageFilterSet ifs = new EC2ImageFilterSet();
            for (int i = 0; i < filterSet.length; i++) {
                ifs.addFilter(filterSet[i]);
            }
            EC2request.setFilterSet(ifs);
        }
        // -> execute the request
        EC2Engine engine = ServiceProvider.getInstance().getEC2Engine();
        DescribeImagesResponse EC2response = EC2SoapServiceImpl.toDescribeImagesResponse(engine.describeImages(EC2request));
        serializeResponse(response, EC2response);
    }

    private void describeImageAttribute(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2DescribeImageAttribute ec2request = new EC2DescribeImageAttribute();

        String[] imageId = request.getParameterValues("ImageId");
        if (imageId != null && imageId.length > 0)
            ec2request.setImageId(imageId[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - ImageId");
        }

        String[] attribute = request.getParameterValues("Attribute");
        if (attribute != null && attribute.length > 0) {
            if (attribute[0].equalsIgnoreCase("description"))
                ec2request.setAttribute(ImageAttribute.description);
            else if (attribute[0].equalsIgnoreCase("launchPermission"))
                ec2request.setAttribute(ImageAttribute.launchPermission);
            else {
                throw new EC2ServiceException(ClientError.InvalidParameterValue, "Only values supported for paramter Attribute are - Description/LaunchPermission");
            }
        } else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Attribute");
        }

        DescribeImageAttributeResponse EC2response =
            EC2SoapServiceImpl.toDescribeImageAttributeResponse(ServiceProvider.getInstance().getEC2Engine().describeImageAttribute(ec2request));
        serializeResponse(response, EC2response);
    }

    private void describeInstances(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2DescribeInstances EC2request = new EC2DescribeInstances();

        // -> load in all the "InstanceId.n" parameters if any
        Enumeration<?> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String key = (String)names.nextElement();
            if (key.startsWith("InstanceId")) {
                String[] value = request.getParameterValues(key);
                if (null != value && 0 < value.length)
                    EC2request.addInstanceId(value[0]);
            }
        }

        // -> are there any filters with this request?
        EC2Filter[] filterSet = extractFilters(request);
        if (null != filterSet) {
            EC2InstanceFilterSet ifs = new EC2InstanceFilterSet();
            for (int i = 0; i < filterSet.length; i++)
                ifs.addFilter(filterSet[i]);
            EC2request.setFilterSet(ifs);
        }

        // -> execute the request
        EC2Engine engine = ServiceProvider.getInstance().getEC2Engine();
        DescribeInstancesResponse EC2response = EC2SoapServiceImpl.toDescribeInstancesResponse(engine.describeInstances(EC2request), engine);
        serializeResponse(response, EC2response);
    }

    private void describeAddresses(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2DescribeAddresses ec2Request = new EC2DescribeAddresses();

        // -> load in all the "PublicIp.n" parameters if any
        Enumeration<?> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String key = (String)names.nextElement();
            if (key.startsWith("PublicIp")) {
                String[] value = request.getParameterValues(key);
                if (null != value && 0 < value.length)
                    ec2Request.addPublicIp(value[0]);
            }
        }

        // add filters
        EC2Filter[] filterSet = extractFilters(request);
        if (filterSet != null) {
            EC2AddressFilterSet afs = new EC2AddressFilterSet();
            for (int i = 0; i < filterSet.length; i++)
                afs.addFilter(filterSet[i]);
            ec2Request.setFilterSet(afs);
        }
        // -> execute the request
        EC2Engine engine = ServiceProvider.getInstance().getEC2Engine();
        serializeResponse(response, EC2SoapServiceImpl.toDescribeAddressesResponse(engine.describeAddresses(ec2Request)));
    }

    private void allocateAddress(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {

        EC2Engine engine = ServiceProvider.getInstance().getEC2Engine();

        AllocateAddressResponse ec2Response = EC2SoapServiceImpl.toAllocateAddressResponse(engine.allocateAddress());

        serializeResponse(response, ec2Response);
    }

    private void releaseAddress(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {

        EC2Engine engine = ServiceProvider.getInstance().getEC2Engine();

        String publicIp = request.getParameter("PublicIp");
        if (publicIp == null) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - PublicIp");
        }

        EC2ReleaseAddress ec2Request = new EC2ReleaseAddress();
        if (ec2Request != null) {
            ec2Request.setPublicIp(publicIp);
        }

        ReleaseAddressResponse EC2Response = EC2SoapServiceImpl.toReleaseAddressResponse(engine.releaseAddress(ec2Request));

        serializeResponse(response, EC2Response);
    }

    private void associateAddress(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2Engine engine = ServiceProvider.getInstance().getEC2Engine();

        String publicIp = request.getParameter("PublicIp");
        if (null == publicIp) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - PublicIp");
        }
        String instanceId = request.getParameter("InstanceId");
        if (null == instanceId) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId");
        }

        EC2AssociateAddress ec2Request = new EC2AssociateAddress();
        if (ec2Request != null) {
            ec2Request.setInstanceId(instanceId);
            ec2Request.setPublicIp(publicIp);
        }

        AssociateAddressResponse ec2Response = EC2SoapServiceImpl.toAssociateAddressResponse(engine.associateAddress(ec2Request));

        serializeResponse(response, ec2Response);
    }

    private void disassociateAddress(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2Engine engine = ServiceProvider.getInstance().getEC2Engine();

        String publicIp = request.getParameter("PublicIp");
        if (null == publicIp) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - PublicIp");
        }

        EC2DisassociateAddress ec2Request = new EC2DisassociateAddress();
        if (ec2Request != null) {
            ec2Request.setPublicIp(publicIp);
        }

        DisassociateAddressResponse ec2Response = EC2SoapServiceImpl.toDisassociateAddressResponse(engine.disassociateAddress(ec2Request));

        serializeResponse(response, ec2Response);
    }

    private void describeSecurityGroups(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2DescribeSecurityGroups EC2request = new EC2DescribeSecurityGroups();

        // -> load in all the "GroupName.n" parameters if any
        Enumeration<?> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String key = (String)names.nextElement();
            if (key.startsWith("GroupName")) {
                String[] value = request.getParameterValues(key);
                if (null != value && 0 < value.length)
                    EC2request.addGroupName(value[0]);
            }
        }

        // -> are there any filters with this request?
        EC2Filter[] filterSet = extractFilters(request);
        if (null != filterSet) {
            EC2GroupFilterSet gfs = new EC2GroupFilterSet();
            for (EC2Filter filter : filterSet)
                gfs.addFilter(filter);
            EC2request.setFilterSet(gfs);
        }

        // -> execute the request
        EC2Engine engine = ServiceProvider.getInstance().getEC2Engine();

        DescribeSecurityGroupsResponse EC2response = EC2SoapServiceImpl.toDescribeSecurityGroupsResponse(engine.describeSecurityGroups(EC2request));
        serializeResponse(response, EC2response);
    }

    private void describeInstanceAttribute(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2DescribeInstances EC2request = new EC2DescribeInstances();
        String[] instanceId = request.getParameterValues("InstanceId");
        if (instanceId != null && instanceId.length > 0)
            EC2request.addInstanceId(instanceId[0]);
        else
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId");

        String[] attribute = request.getParameterValues("Attribute");
        if (attribute != null && attribute.length > 0) {
            if (!attribute[0].equalsIgnoreCase("instanceType")) {
                throw new EC2ServiceException(ClientError.InvalidParameterValue, "Only value supported for paramter Attribute is 'instanceType'");
            }
        } else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Attribute");
        }

        // -> execute the request
        DescribeInstanceAttributeResponse EC2response =
            EC2SoapServiceImpl.toDescribeInstanceAttributeResponse(ServiceProvider.getInstance().getEC2Engine().describeInstances(EC2request));
        serializeResponse(response, EC2response);
    }

    private void modifyInstanceAttribute(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2ModifyInstanceAttribute ec2Request = new EC2ModifyInstanceAttribute();

        String[] instanceId = request.getParameterValues("InstanceId");
        if (instanceId != null && instanceId.length > 0)
            ec2Request.setInstanceId(instanceId[0]);
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId");
        }

        String[] instanceType = request.getParameterValues("InstanceType.Value");
        String[] userData = request.getParameterValues("UserData.Value");

        if (instanceType != null && userData != null) {
            throw new EC2ServiceException(ClientError.InvalidParameterCombination, "Only one attribute can be" + " specified at a time");
        }
        if (instanceType != null && instanceType.length > 0) {
            ec2Request.setInstanceType(instanceType[0]);
        } else if (userData != null && userData.length > 0) {
            ec2Request.setUserData(userData[0]);
        } else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing parameter - InstanceType/UserData should be provided");
        }

        // -> execute the request
        ModifyInstanceAttributeResponse EC2response =
            EC2SoapServiceImpl.toModifyInstanceAttributeResponse(ServiceProvider.getInstance().getEC2Engine().modifyInstanceAttribute(ec2Request));
        serializeResponse(response, EC2response);
    }

    private void describeSnapshots(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2DescribeSnapshots EC2request = new EC2DescribeSnapshots();

        // -> load in all the "SnapshotId.n" parameters if any, and ignore any other parameters
        Enumeration<?> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String key = (String)names.nextElement();
            if (key.startsWith("SnapshotId")) {
                String[] value = request.getParameterValues(key);
                if (null != value && 0 < value.length)
                    EC2request.addSnapshotId(value[0]);
            }
        }

        // -> are there any filters with this request?
        EC2Filter[] filterSet = extractFilters(request);
        if (null != filterSet) {
            EC2SnapshotFilterSet sfs = new EC2SnapshotFilterSet();
            for (int i = 0; i < filterSet.length; i++)
                sfs.addFilter(filterSet[i]);
            EC2request.setFilterSet(sfs);
        }

        // -> execute the request
        EC2Engine engine = ServiceProvider.getInstance().getEC2Engine();
        DescribeSnapshotsResponse EC2response = EC2SoapServiceImpl.toDescribeSnapshotsResponse(engine.describeSnapshots(EC2request));
        serializeResponse(response, EC2response);
    }

    private void describeVolumes(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2DescribeVolumes EC2request = new EC2DescribeVolumes();

        // -> load in all the "VolumeId.n" parameters if any
        Enumeration<?> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String key = (String)names.nextElement();
            if (key.startsWith("VolumeId")) {
                String[] value = request.getParameterValues(key);
                if (null != value && 0 < value.length)
                    EC2request.addVolumeId(value[0]);
            }
        }

        // -> are there any filters with this request?
        EC2Filter[] filterSet = extractFilters(request);
        if (null != filterSet) {
            EC2VolumeFilterSet vfs = new EC2VolumeFilterSet();
            for (int i = 0; i < filterSet.length; i++)
                vfs.addFilter(filterSet[i]);
            EC2request.setFilterSet(vfs);
        }

        // -> execute the request
        EC2Engine engine = ServiceProvider.getInstance().getEC2Engine();
        DescribeVolumesResponse EC2response =
            EC2SoapServiceImpl.toDescribeVolumesResponse(ServiceProvider.getInstance().getEC2Engine().describeVolumes(EC2request), engine);
        serializeResponse(response, EC2response);
    }

    /**
     * Example of how the filters are defined in a REST request:
     * https://<server>/?Action=DescribeVolumes
     * &Filter.1.Name=attachment.instance-id
     * &Filter.1.Value.1=i-1a2b3c4d
     * &Filter.2.Name=attachment.delete-on-termination
     * &Filter.2.Value.1=true
     *
     * @param request
     * @return List<EC2Filter>
     */
    private EC2Filter[] extractFilters(HttpServletRequest request) {
        String filterName = null;
        String value = null;
        EC2Filter nextFilter = null;
        boolean timeFilter = false;
        int filterCount = 1;
        int valueCount = 1;

        List<EC2Filter> filterSet = new ArrayList<EC2Filter>();

        do {
            filterName = request.getParameter("Filter." + filterCount + ".Name");
            if (null != filterName) {
                nextFilter = new EC2Filter();
                nextFilter.setName(filterName);
                timeFilter = (filterName.equalsIgnoreCase("attachment.attach-time") || filterName.equalsIgnoreCase("create-time"));
                valueCount = 1;
                do {
                    value = request.getParameter("Filter." + filterCount + ".Value." + valueCount);
                    if (null != value) {
                        // -> time values are not encoded as regexes
                        if (timeFilter)
                            nextFilter.addValue(value);
                        else
                            nextFilter.addValueEncoded(value);

                        valueCount++;
                    }
                } while (null != value);

                filterSet.add(nextFilter);
                filterCount++;
            }
        } while (null != filterName);

        if (1 == filterCount)
            return null;
        else
            return filterSet.toArray(new EC2Filter[0]);
    }

    private void describeKeyPairs(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2DescribeKeyPairs ec2Request = new EC2DescribeKeyPairs();

        Enumeration<?> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String key = (String)names.nextElement();
            if (key.startsWith("KeyName")) {
                String[] value = request.getParameterValues(key);
                if (null != value && 0 < value.length)
                    ec2Request.addKeyName(value[0]);
            }
        }

        EC2Filter[] filterSet = extractFilters(request);
        if (null != filterSet) {
            EC2KeyPairFilterSet vfs = new EC2KeyPairFilterSet();
            for (EC2Filter filter : filterSet) {
                vfs.addFilter(filter);
            }
            ec2Request.setKeyFilterSet(vfs);
        }

        DescribeKeyPairsResponse EC2Response = EC2SoapServiceImpl.toDescribeKeyPairs(ServiceProvider.getInstance().getEC2Engine().describeKeyPairs(ec2Request));
        serializeResponse(response, EC2Response);
    }

    private void importKeyPair(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {

        String keyName = request.getParameter("KeyName");
        if (keyName == null) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - KeyName");
        }

        String publicKeyMaterial = request.getParameter("PublicKeyMaterial");
        if (publicKeyMaterial == null) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - PublicKeyMaterial");
        }

        if (!publicKeyMaterial.contains(" "))
            publicKeyMaterial = new String(Base64.decodeBase64(publicKeyMaterial.getBytes()));

        EC2ImportKeyPair ec2Request = new EC2ImportKeyPair();
        if (ec2Request != null) {
            ec2Request.setKeyName(request.getParameter("KeyName"));
            ec2Request.setPublicKeyMaterial(request.getParameter("PublicKeyMaterial"));
        }

        ImportKeyPairResponse EC2Response = EC2SoapServiceImpl.toImportKeyPair(ServiceProvider.getInstance().getEC2Engine().importKeyPair(ec2Request));
        serializeResponse(response, EC2Response);
    }

    private void createKeyPair(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        String keyName = request.getParameter("KeyName");
        if (keyName == null) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - KeyName");
        }

        EC2CreateKeyPair ec2Request = new EC2CreateKeyPair();
        if (ec2Request != null) {
            ec2Request.setKeyName(keyName);
        }

        CreateKeyPairResponse EC2Response = EC2SoapServiceImpl.toCreateKeyPair(ServiceProvider.getInstance().getEC2Engine().createKeyPair(ec2Request));
        serializeResponse(response, EC2Response);
    }

    private void deleteKeyPair(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        String keyName = request.getParameter("KeyName");
        if (keyName == null) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - KeyName");
        }

        EC2DeleteKeyPair ec2Request = new EC2DeleteKeyPair();
        ec2Request.setKeyName(keyName);

        DeleteKeyPairResponse EC2Response = EC2SoapServiceImpl.toDeleteKeyPair(ServiceProvider.getInstance().getEC2Engine().deleteKeyPair(ec2Request));
        serializeResponse(response, EC2Response);
    }

    private void getPasswordData(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        String instanceId = request.getParameter("InstanceId");
        if (instanceId == null) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceId");
        }

        GetPasswordDataResponse EC2Response = EC2SoapServiceImpl.toGetPasswordData(ServiceProvider.getInstance().getEC2Engine().getPasswordData(instanceId));
        serializeResponse(response, EC2Response);
    }

    private void createTags(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2Tags ec2Request = createTagsRequest(request, response);
        if (ec2Request == null)
            return;
        CreateTagsResponse EC2Response = EC2SoapServiceImpl.toCreateTagsResponse(ServiceProvider.getInstance().getEC2Engine().modifyTags(ec2Request, "create"));
        serializeResponse(response, EC2Response);
    }

    private void deleteTags(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2Tags ec2Request = createTagsRequest(request, response);
        if (ec2Request == null)
            return;
        DeleteTagsResponse EC2Response = EC2SoapServiceImpl.toDeleteTagsResponse(ServiceProvider.getInstance().getEC2Engine().modifyTags(ec2Request, "delete"));
        serializeResponse(response, EC2Response);
    }

    private EC2Tags createTagsRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
        EC2Tags ec2Request = new EC2Tags();
        ArrayList<String> resourceIdList = new ArrayList<String>();
        Map<String, String> resourceTagList = new HashMap<String, String>();

        int nCount = 1;
        do {
            String[] resourceIds = request.getParameterValues("ResourceId." + nCount);
            if (resourceIds != null && resourceIds.length > 0)
                resourceIdList.add(resourceIds[0]);
            else
                break;
            nCount++;
        } while (true);
        if (resourceIdList.isEmpty()) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - ResourceId");
        }
        ec2Request = EC2SoapServiceImpl.toResourceTypeAndIds(ec2Request, resourceIdList);

        nCount = 1;
        do {
            String[] tagKey = request.getParameterValues("Tag." + nCount + ".Key");
            if (tagKey != null && tagKey.length > 0) {
                String[] tagValue = request.getParameterValues("Tag." + nCount + ".Value");
                if (tagValue != null && tagValue.length > 0) {
                    resourceTagList.put(tagKey[0], tagValue[0]);
                } else
                    resourceTagList.put(tagKey[0], null);
            } else
                break;
            nCount++;
        } while (true);
        if (resourceTagList.isEmpty()) {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - ResourceTag");
        }
        ec2Request = EC2SoapServiceImpl.toResourceTag(ec2Request, resourceTagList);

        return ec2Request;
    }

    private void describeTags(HttpServletRequest request, HttpServletResponse response) throws ADBException, XMLStreamException, IOException {
        EC2DescribeTags ec2Request = new EC2DescribeTags();

        EC2Filter[] filterSet = extractFilters(request);
        if (null != filterSet) {
            EC2TagsFilterSet tfs = new EC2TagsFilterSet();
            for (int i = 0; i < filterSet.length; i++)
                tfs.addFilter(filterSet[i]);
            ec2Request.setFilterSet(tfs);
        }
        DescribeTagsResponse EC2Response = EC2SoapServiceImpl.toDescribeTagsResponse(ServiceProvider.getInstance().getEC2Engine().describeTags(ec2Request));
        serializeResponse(response, EC2Response);
    }

    /**
     * This function implements the EC2 REST authentication algorithm.   It uses the given
     * "AWSAccessKeyId" parameter to look up the Cloud.com account holder's secret key which is
     * used as input to the signature calculation.  In addition, it tests the given "Expires"
     * parameter to see if the signature has expired and if so the request fails.
     */
    private boolean authenticateRequest(HttpServletRequest request, HttpServletResponse response) throws SignatureException, IOException, InstantiationException,
        IllegalAccessException, ClassNotFoundException, SQLException, ParseException {
        String cloudSecretKey = null;
        String cloudAccessKey = null;
        String signature = null;
        String sigMethod = null;

        // [A] Basic parameters required for an authenticated rest request
        //  -> note that the Servlet engine will un-URL encode all parameters we extract via "getParameterValues()" calls
        String[] awsAccess = request.getParameterValues("AWSAccessKeyId");
        if (null != awsAccess && 0 < awsAccess.length)
            cloudAccessKey = awsAccess[0];
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - AWSAccessKeyId");
        }

        String[] clientSig = request.getParameterValues("Signature");
        if (null != clientSig && 0 < clientSig.length)
            signature = clientSig[0];
        else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Signature");
        }

        String[] method = request.getParameterValues("SignatureMethod");
        if (null != method && 0 < method.length) {
            sigMethod = method[0];
            if (!sigMethod.equals("HmacSHA256") && !sigMethod.equals("HmacSHA1")) {
                throw new EC2ServiceException(ClientError.InvalidParameterValue, "Unsupported SignatureMethod value: " + sigMethod + " expecting: HmacSHA256 or HmacSHA1");
            }
        } else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - SignatureMethod");
        }

        String[] version = request.getParameterValues("Version");
        if (null != version && 0 < version.length) {
            if (!version[0].equals(wsdlVersion)) {
                throw new EC2ServiceException(ClientError.InvalidParameterValue, "Unsupported Version value: " + version[0] + " expecting: " + wsdlVersion);
            }
        } else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - Version");
        }

        String[] sigVersion = request.getParameterValues("SignatureVersion");
        if (null != sigVersion && 0 < sigVersion.length) {
            if (!sigVersion[0].equals("2")) {
                throw new EC2ServiceException(ClientError.InvalidParameterValue, "Unsupported SignatureVersion value: " + sigVersion[0] + " expecting: 2");
            }
        } else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - SignatureVersion");
        }

        // -> can have only one but not both { Expires | Timestamp } headers
        String[] expires = request.getParameterValues("Expires");
        if (null != expires && 0 < expires.length) {
            // -> contains the date and time at which the signature included in the request EXPIRES
            if (hasSignatureExpired(expires[0])) { //InvalidSecurity.RequestHasExpired
                throw new EC2ServiceException(ClientError.InvalidSecurity_RequestHasExpired, "Expires parameter indicates signature has expired: " + expires[0]);
            }
        } else {    // -> contains the date and time at which the request is SIGNED
            String[] time = request.getParameterValues("Timestamp");
            if (null == time || 0 == time.length) {
                throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter -" + " Timestamp/Expires");
            }
        }

        // [B] Use the access key to get the users secret key from the cloud DB
        cloudSecretKey = userDao.getSecretKeyByAccessKey(cloudAccessKey);
        if (cloudSecretKey == null) {
            logger.debug("Access key '" + cloudAccessKey + "' not found in the the EC2 service ");
            throw new EC2ServiceException(ClientError.AuthFailure, "Access key '" + cloudAccessKey + "' not found in the the EC2 service ");
        }

        // [C] Verify the signature
        //  -> getting the query-string in this way maintains its URL encoding
        EC2RestAuth restAuth = new EC2RestAuth();
        restAuth.setHostHeader(request.getHeader("Host"));
        String requestUri = request.getRequestURI();

        // If forwarded from another basepath:
        String forwardedPath = (String)request.getAttribute("javax.servlet.forward.request_uri");
        if (forwardedPath != null) {
            requestUri = forwardedPath;
        }
        restAuth.setHTTPRequestURI(requestUri);

        String queryString = request.getQueryString();
        // getQueryString returns null (does it ever NOT return null for these),
        // we need to construct queryString to avoid changing the auth code...
        if (queryString == null) {
            // construct our idea of a queryString with parameters!
            Enumeration<?> params = request.getParameterNames();
            if (params != null) {
                while (params.hasMoreElements()) {
                    String paramName = (String)params.nextElement();
                    // exclude the signature string obviously. ;)
                    if (paramName.equalsIgnoreCase("Signature"))
                        continue;
                    // URLEncoder performs application/x-www-form-urlencoded-type encoding and not Percent encoding
                    // according to RFC 3986 as required by Amazon, we need to Percent-encode (URL Encode)
                    String encodedValue = URLEncoder.encode(request.getParameter(paramName), "UTF-8").replace("+", "%20").replace("*", "%2A");
                    if (queryString == null)
                        queryString = paramName + "=" + encodedValue;
                    else
                        queryString = queryString + "&" + paramName + "=" + encodedValue;
                }
            }
        }
        restAuth.setQueryString(queryString);

        if (restAuth.verifySignature(request.getMethod(), cloudSecretKey, signature, sigMethod)) {
            UserContext.current().initContext(cloudAccessKey, cloudSecretKey, cloudAccessKey, "REST request", null);
            return true;
        } else
            throw new EC2ServiceException(ClientError.SignatureDoesNotMatch, "The request signature calculated does not match the signature provided by the user.");
    }

    /**
     * We check this to reduce replay attacks.
     *
     * @param timeStamp
     * @return true - if the request is not longer valid, false otherwise
     * @throws ParseException
     */
    private boolean hasSignatureExpired(String timeStamp) {
        Calendar cal = EC2RestAuth.parseDateString(timeStamp);
        if (null == cal)
            return false;

        Date expiredTime = cal.getTime();
        Date today = new Date();   // -> gets set to time of creation
        if (0 >= expiredTime.compareTo(today)) {
            logger.debug("timestamp given: [" + timeStamp + "], now: [" + today.toString() + "]");
            return true;
        } else
            return false;
    }

    private static void endResponse(HttpServletResponse response, String content) {
        try {
            byte[] data = content.getBytes();
            response.setContentLength(data.length);
            OutputStream os = response.getOutputStream();
            os.write(data);
            os.close();

        } catch (Throwable e) {
            logger.error("Unexpected exception " + e.getMessage(), e);
        }
    }

    private void logRequest(HttpServletRequest request) {
        if (logger.isInfoEnabled()) {
            logger.info("EC2 Request method: " + request.getMethod());
            logger.info("Request contextPath: " + request.getContextPath());
            logger.info("Request pathInfo: " + request.getPathInfo());
            logger.info("Request pathTranslated: " + request.getPathTranslated());
            logger.info("Request queryString: " + request.getQueryString());
            logger.info("Request requestURI: " + request.getRequestURI());
            logger.info("Request requestURL: " + request.getRequestURL());
            logger.info("Request servletPath: " + request.getServletPath());
            Enumeration<?> headers = request.getHeaderNames();
            if (headers != null) {
                while (headers.hasMoreElements()) {
                    Object headerName = headers.nextElement();
                    logger.info("Request header " + headerName + ":" + request.getHeader((String)headerName));
                }
            }

            Enumeration<?> params = request.getParameterNames();
            if (params != null) {
                while (params.hasMoreElements()) {
                    Object paramName = params.nextElement();
                    logger.info("Request parameter " + paramName + ":" + request.getParameter((String)paramName));
                }
            }
        }
    }

    /**
     * Send out an error response according to Amazon convention.
     */
    private void faultResponse(HttpServletResponse response, String errorCode, String errorMessage) {
        try {
            OutputStreamWriter out = new OutputStreamWriter(response.getOutputStream());
            response.setContentType("text/xml; charset=UTF-8");
            out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            out.write("<Response><Errors><Error><Code>");
            out.write(errorCode);
            out.write("</Code><Message>");
            out.write(errorMessage);
            out.write("</Message></Error></Errors><RequestID>");
            out.write(UUID.randomUUID().toString());
            out.write("</RequestID></Response>");
            out.flush();
            out.close();
        } catch (IOException e) {
            logger.error("Unexpected exception " + e.getMessage(), e);
        }
    }

    /**
     * Serialize Axis beans to XML output.
     */
    private void serializeResponse(HttpServletResponse response, ADBBean EC2Response) throws ADBException, XMLStreamException, IOException {
        OutputStream os = response.getOutputStream();
        response.setStatus(200);
        response.setContentType("text/xml");
        XMLStreamWriter xmlWriter = xmlOutFactory.createXMLStreamWriter(os);
        xmlWriter.writeStartDocument("UTF-8", "1.0");
        MTOMAwareXMLSerializer MTOMWriter = new MTOMAwareXMLSerializer(xmlWriter);
        MTOMWriter.setDefaultNamespace("http://ec2.amazonaws.com/doc/" + wsdlVersion + "/");
        EC2Response.serialize(null, factory, MTOMWriter);
        xmlWriter.flush();
        xmlWriter.close();
        os.close();
    }
}
