// 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.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.EC2ImageFilterSet;
import com.cloud.bridge.service.core.ec2.EC2ImageAttributes.ImageAttribute;
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.Transaction;

@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();
            try {
                EC2Prop.load( new FileInputStream( propertiesFile ));
            } 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);
            }
            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;
        Transaction 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 = Transaction.open(Transaction.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 { 
        Transaction 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 = Transaction.open(Transaction.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 {
        Transaction 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 = Transaction.open(Transaction.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();
    }
}
