// 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.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.SignatureException;
import java.sql.SQLException;
import java.util.Enumeration;

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.bind.DatatypeConverter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.axis2.AxisFault;
import org.apache.log4j.Logger;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.cloud.bridge.io.MultiPartDimeInputStream;
import com.cloud.bridge.model.SAcl;
import com.cloud.bridge.model.UserCredentialsVO;
import com.cloud.bridge.persist.dao.CloudStackConfigurationDao;
import com.cloud.bridge.persist.dao.UserCredentialsDao;
import com.cloud.bridge.service.controller.s3.S3BucketAction;
import com.cloud.bridge.service.controller.s3.S3ObjectAction;
import com.cloud.bridge.service.controller.s3.ServiceProvider;
import com.cloud.bridge.service.controller.s3.ServletAction;
import com.cloud.bridge.service.core.s3.S3AccessControlList;
import com.cloud.bridge.service.core.s3.S3AuthParams;
import com.cloud.bridge.service.core.s3.S3Engine;
import com.cloud.bridge.service.core.s3.S3Grant;
import com.cloud.bridge.service.core.s3.S3MetaDataEntry;
import com.cloud.bridge.service.core.s3.S3PutObjectRequest;
import com.cloud.bridge.service.core.s3.S3PutObjectResponse;
import com.cloud.bridge.service.exception.InvalidBucketName;
import com.cloud.bridge.service.exception.PermissionDeniedException;
import com.cloud.bridge.util.ConfigurationHelper;
import com.cloud.bridge.util.HeaderParam;
import com.cloud.bridge.util.RestAuth;
import com.cloud.bridge.util.S3SoapAuth;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Transaction;
public class S3RestServlet extends HttpServlet {
    private static final long serialVersionUID = -6168996266762804877L;
    public static final String ENABLE_S3_API="enable.s3.api";
    private static boolean isS3APIEnabled = false;

    public static final Logger logger = Logger.getLogger(S3RestServlet.class);
    @Inject CloudStackConfigurationDao csDao;
    @Inject UserCredentialsDao ucDao;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        processRequest( req, resp, "GET" );
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
    {
        // -> DIME requests are authenticated via the SOAP auth mechanism
        String type = req.getHeader( "Content-Type" );
        if ( null != type && type.equalsIgnoreCase( "application/dime" )) 	
            processDimeRequest(req, resp);
        else processRequest( req, resp, "POST" );
    }

    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) {
        processRequest( req, resp, "PUT" );
    }

    @Override
    protected void doHead(HttpServletRequest req, HttpServletResponse resp) {
        processRequest( req, resp, "HEAD" );
    }

    @Override
    protected void doOptions(HttpServletRequest req, HttpServletResponse resp) {
        processRequest( req, resp, "OPTIONS" );
    }

    @Override
    protected void doDelete( HttpServletRequest req, HttpServletResponse resp ) {
        processRequest( req, resp, "DELETE" );
    }

    @Override
    public void init( ServletConfig config ) throws ServletException {
        try{
        	SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext());       	
       	
            ConfigurationHelper.preConfigureConfigPathFromServletContext(config.getServletContext());
            // check if API is enabled
            String value = csDao.getConfigValue(ENABLE_S3_API);
            if(value != null) {
                isS3APIEnabled = Boolean.valueOf(value);
            }
            logger.info("S3Engine :: Configuration value is : " + value);

        }catch(Exception e){
            throw new ServletException("Error initializing awsapi: " + e.getMessage());
        }

    }



    /**
     * POST requests do not get authenticated on entry.   The associated
     * access key and signature headers are embedded in the message not encoded
     * as HTTP headers.
     */
    private void processRequest( HttpServletRequest request, HttpServletResponse response, String method ) 
    {
        Transaction txn = Transaction.open("cloudbridge", Transaction.AWSAPI_DB, true);
        try {
            logRequest(request);

            // Our extensions to the S3 REST API for simple management actions
            // are conveyed with Request parameter "Action".
            // The present extensions are either to set up the user credentials
            // (see the cloud-bridge-register script for more detail) or
            // to report our version of this capability.
            // -> unauthenticated calls, should still be done over HTTPS
            String cloudAction = request.getParameter( "Action" );

            if(!isS3APIEnabled){
                throw new RuntimeException("Amazon S3 API is disabled.");
            }


            if (null != cloudAction) 
            {
                if (cloudAction.equalsIgnoreCase( "SetUserKeys" )) {
                    setUserKeys(request, response);
                    return;
                }

                if (cloudAction.equalsIgnoreCase( "SetCertificate" ))
                    // At present a noop
                    return;

                if (cloudAction.equalsIgnoreCase( "CloudS3Version" )) {
                    cloudS3Version(request, response);
                    return;
                }
            }


            txn.start();
            // -> authenticated calls
            if ( !((method.equalsIgnoreCase( "POST" ) && !(request.getQueryString().equalsIgnoreCase("delete"))) ) ){
                S3AuthParams params = extractRequestHeaders( request );
                authenticateRequest( request, params );
            }

            ServletAction action = routeRequest(request);
            if ( action != null ) {
                action.execute(request, response);
            } 
            else {
                response.setStatus(404);
                endResponse(response, "File not found");
            }
            txn.close();
        } 
        catch( InvalidBucketName e) {
            logger.error("Unexpected exception " + e.getMessage(), e);
            response.setStatus(400);
            endResponse(response, "Invalid Bucket Name - " + e.toString());    	
        } 
        catch(PermissionDeniedException e) {
            logger.error("Unexpected exception " + e.getMessage(), e);
            response.setStatus(403);
            endResponse(response, "Access denied - " + e.toString());
        } 
        catch(Throwable e) {
            logger.error("Unexpected exception " + e.getMessage(), e);
            response.setStatus(404);
            endResponse(response, "Bad request");

        } 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 cloudS3Version( HttpServletRequest request, HttpServletResponse response ) {
        String version = new String( "<?xml version=\"1.0\" encoding=\"utf-8\"?><CloudS3Version>1.04</CloudS3Version>" );       		
        response.setStatus(200);
        endResponse(response, version);
    }

    /**
     * This request registers the user Cloud.com account holder to the S3 service.   The Cloud.com
     * account holder saves his API access and secret keys with the S3 service so that 
     * each rest call he makes can be verified was originated from him.   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.
     */
    @DB
    private void setUserKeys( HttpServletRequest request, HttpServletResponse response ) {
        String[] accessKey = null;
        String[] secretKey = null;

        try {
            // -> both 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 {
            // -> use the keys to see if the account actually exists
            //ServiceProvider.getInstance().getEC2Engine().validateAccount( accessKey[0], secretKey[0] );
            //UserCredentialsDaoImpl credentialDao = new UserCredentialsDao();
            Transaction txn = Transaction.open(Transaction.AWSAPI_DB);
            txn.start();
            UserCredentialsVO user = new UserCredentialsVO(accessKey[0], secretKey[0]);
            user = ucDao.persist(user);
            txn.commit();
            txn.close();
            //credentialDao.setUserKeys( accessKey[0], secretKey[0] ); 

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

    /**
     * We are using the S3AuthParams class to hide where the header values are coming
     * from so that the authenticateRequest call can be made from several places.
     */
    public static S3AuthParams extractRequestHeaders( HttpServletRequest request ) {
        S3AuthParams params = new S3AuthParams();

        Enumeration headers = request.getHeaderNames();
        if (null != headers) 
        {
            while( headers.hasMoreElements()) 
            {
                HeaderParam oneHeader = new HeaderParam();
                String headerName = (String)headers.nextElement();
                oneHeader.setName( headerName );
                oneHeader.setValue( request.getHeader( headerName ));
                params.addHeader( oneHeader );
            }
        }
        return params;
    }

    public static void authenticateRequest( HttpServletRequest request, S3AuthParams params ) 
            throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException 
            {
        RestAuth auth          = new RestAuth(ServiceProvider.getInstance().getUseSubDomain()); 	
        String   AWSAccessKey  = null;
        String   signature     = null;
        String   authorization = null;

        // [A] Is it an annonymous request?
        if (null == (authorization = params.getHeader( "Authorization" ))) {
            UserContext.current().initContext();
            return;
        }

        // [B] Is it an authenticated request?
        int offset = authorization.indexOf( "AWS" );
        if (-1 != offset) {
            String temp = authorization.substring( offset+3 ).trim();
            offset = temp.indexOf( ":" );
            AWSAccessKey = temp.substring( 0, offset );
            signature    = temp.substring( offset+1 );
        }

        // [C] Calculate the signature from the request's headers
        auth.setDateHeader( request.getHeader( "Date" ));
        auth.setContentTypeHeader( request.getHeader( "Content-Type" ));
        auth.setContentMD5Header( request.getHeader( "Content-MD5" ));
        auth.setHostHeader( request.getHeader( "Host" ));
        auth.setQueryString( request.getQueryString());
        auth.addUriPath( request.getRequestURI());

        // -> are their any Amazon specific (i.e. 'x-amz-' ) headers?
        HeaderParam[] headers = params.getHeaders();
        for( int i=0; null != headers && i < headers.length; i++ )
        {
            String headerName = headers[i].getName();
            String ignoreCase = headerName.toLowerCase();
            if (ignoreCase.startsWith( "x-amz-" ))
                auth.addAmazonHeader( headerName + ":" + headers[i].getValue());
        }

        UserInfo info = ServiceProvider.getInstance().getUserInfo(AWSAccessKey);
        if (info == null) throw new PermissionDeniedException("Unable to authenticate access key: " + AWSAccessKey);

        try {
            if (auth.verifySignature( request.getMethod(), info.getSecretKey(), signature )) {
                UserContext.current().initContext(AWSAccessKey, info.getSecretKey(), AWSAccessKey, info.getDescription(), request);
                return;
            }


        } catch (SignatureException e) {
            throw new PermissionDeniedException(e);

        } catch (UnsupportedEncodingException e) {
            throw new PermissionDeniedException(e);
        }
        throw new PermissionDeniedException("Invalid signature");
            }



    private ServletAction routeRequest(HttpServletRequest request) 
    {
        //  URL routing for S3 REST calls.
        String pathInfo = request.getPathInfo();
        String bucketName = null;
        String key = null;

        String serviceEndpoint = ServiceProvider.getInstance().getServiceEndpoint();
        String host            = request.getHeader("Host");

        // Check for unrecognized forms of URI information in request

        if ( ( pathInfo == null ) || ( pathInfo.indexOf('/') != 0 ) )
            if ( "POST".equalsIgnoreCase(request.getMethod()) )
                // Case where request is POST operation with no pathinfo
                // This is the POST alternative to PUT described at s3.amazonaws.com API doc page 141
            { 
                return routePlainPostRequest (request);       	
            }


        // Irrespective of whether the requester is using subdomain or full host naming of path expressions
        // to buckets, wherever the request is made up of a service endpoint followed by a /, in AWS S3 this always
        // conveys a ListAllMyBuckets command

        if  ( (serviceEndpoint.equalsIgnoreCase( host )) && (pathInfo.equalsIgnoreCase("/")) ) {
            request.setAttribute(S3Constants.BUCKET_ATTR_KEY, "/");
            return new S3BucketAction();   // for ListAllMyBuckets
        }

        // Because there is a leading / at position 0 of pathInfo, now subtract this to process the remainder	
        pathInfo = pathInfo.substring(1); 

        if (ServiceProvider.getInstance().getUseSubDomain()) 

        {   		
            // -> verify the format of the bucket name
            int endPos = host.indexOf( ServiceProvider.getInstance().getMasterDomain());
            if ( endPos > 0 ) 
            {
                bucketName = host.substring(0, endPos);
                S3Engine.verifyBucketName( bucketName, false );
                request.setAttribute(S3Constants.BUCKET_ATTR_KEY, bucketName);
            }
            else request.setAttribute(S3Constants.BUCKET_ATTR_KEY, "");

            if (pathInfo == null || pathInfo.equalsIgnoreCase("/")) 
            {
                return new S3BucketAction();
            } 
            else {
                String objectKey = pathInfo.substring(1);
                request.setAttribute(S3Constants.OBJECT_ATTR_KEY, objectKey);
                return new S3ObjectAction();
            }
        }

        else 

        {

            int endPos = pathInfo.indexOf('/');  // Subsequent / character?

            if (endPos < 1)
            {
                bucketName = pathInfo;
                S3Engine.verifyBucketName( bucketName, false );
                request.setAttribute(S3Constants.BUCKET_ATTR_KEY, bucketName);
                return new S3BucketAction();
            }
            else
            {
                bucketName = pathInfo.substring(0, endPos);
                key        = pathInfo.substring(endPos + 1);			
                S3Engine.verifyBucketName( bucketName, false );

                if (!key.isEmpty()) 
                {
                    request.setAttribute(S3Constants.BUCKET_ATTR_KEY, bucketName);
                    request.setAttribute(S3Constants.OBJECT_ATTR_KEY, pathInfo.substring(endPos + 1));
                    return new S3ObjectAction();
                } 
                else {
                    request.setAttribute(S3Constants.BUCKET_ATTR_KEY, bucketName);
                    return new S3BucketAction();
                }
            }
        }
    }


    public 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);
        }
    }

    public static void writeResponse(HttpServletResponse response, String content) throws IOException {
        byte[] data = content.getBytes();
        OutputStream os = response.getOutputStream();
        os.write(data);
    }

    public static void writeResponse(HttpServletResponse response, InputStream is) throws IOException {
        byte[] data = new byte[4096];
        int length = 0;
        while((length = is.read(data)) > 0) {
            response.getOutputStream().write(data, 0, length);
        }
    }

    // Route for the case where request is POST operation with no pathinfo
    // This is the POST alternative to PUT described at s3.amazonaws.com API doc, Amazon Simple
    // Storage Service API Reference API Version 2006-03-01 page 141.
    // The purpose of the plain POST operation is to add an object to a specified bucket using HTML forms.

    private S3ObjectAction routePlainPostRequest (HttpServletRequest request)    
    {	
        // TODO - Remove the unnecessary fields below    
        // Obtain the mandatory fields from the HTML form or otherwise fail with a logger message
        String keyString = request.getParameter("key");
        String metatagString = request.getParameter("x-amz-meta-tag");
        String bucketString = request.getParameter("Bucket");
        String aclString = request.getParameter("acl");
        String fileString = request.getParameter("file");

        String accessKeyString = request.getParameter("AWSAccessKeyId");
        String signatureString = request.getParameter("Signature");

        // Obtain the discretionary fields from the HTML form 
        String policyKeyString = request.getParameter("Policy");
        String metauuidString = request.getParameter("x-amz-meta-uuid");
        String redirectString = request.getParameter("redirect");  

        // if none of the above are null then ...
        request.setAttribute(S3Constants.BUCKET_ATTR_KEY, bucketString);
        request.setAttribute(S3Constants.OBJECT_ATTR_KEY, keyString);
        request.setAttribute(S3Constants.PLAIN_POST_ACCESS_KEY, accessKeyString);
        request.setAttribute(S3Constants.PLAIN_POST_SIGNATURE, signatureString);

        // -> authenticated calls
        try {
            // S3AuthParams params = extractRequestHeaders( request );
            S3AuthParams params = new S3AuthParams();
            HeaderParam headerParam1 = new HeaderParam("accessKey", accessKeyString);
            params.addHeader(headerParam1);
            HeaderParam headerParam2 = new HeaderParam("secretKey", signatureString);
            params.addHeader(headerParam2);
            authenticateRequest( request, params );
        }
        catch (Exception e)
        { logger.warn("Authentication details insufficient"); }

        return new S3ObjectAction();

    }

    /**
     * A DIME request is really a SOAP request that we are dealing with, and so its
     * authentication is the SOAP authentication approach.   Since Axis2 does not handle
     * DIME messages we deal with them here.
     * 
     * @param request
     * @param response
     */
    private void processDimeRequest(HttpServletRequest request, HttpServletResponse response) {
        S3PutObjectRequest  putRequest  = null;
        S3PutObjectResponse putResponse = null;
        int                 bytesRead   = 0;

        S3Engine engine = new S3Engine();

        try {   
            logRequest(request);

            MultiPartDimeInputStream ds = new MultiPartDimeInputStream( request.getInputStream());

            // -> the first stream MUST be the SOAP party
            if (ds.nextInputStream())
            {
                //logger.debug( "DIME msg [" + ds.getStreamType() + "," + ds.getStreamTypeFormat() + "," + ds.getStreamId() + "]" );
                byte[] buffer = new byte[8192];
                bytesRead = ds.read( buffer, 0, 8192 ); 
                //logger.debug( "DIME SOAP Bytes read: " + bytesRead );
                ByteArrayInputStream bis = new ByteArrayInputStream( buffer, 0, bytesRead );
                putRequest = toEnginePutObjectRequest( bis ); 
            }

            // -> we only need to support a DIME message with two bodyparts
            if (null != putRequest && ds.nextInputStream())
            {
                InputStream is = ds.getInputStream();
                putRequest.setData( is );
            }

            // -> need to do SOAP level auth here, on failure return the SOAP fault
            StringBuffer xml = new StringBuffer();
            String AWSAccessKey = putRequest.getAccessKey();
            UserInfo info = ServiceProvider.getInstance().getUserInfo(AWSAccessKey);
            try 
            {   S3SoapAuth.verifySignature( putRequest.getSignature(), "PutObject", putRequest.getRawTimestamp(), AWSAccessKey, info.getSecretKey());   	

            } catch( AxisFault e ) {
                String reason = e.toString();
                int start = reason.indexOf( ".AxisFault:" );
                if (-1 != start) reason = reason.substring( start+11 );

                xml.append( "<?xml version=\"1.0\" encoding=\"utf-8\"?>" );
                xml.append( "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" >\n" );
                xml.append( "<soap:Body>\n" );               
                xml.append( "<soap:Fault>\n" );
                xml.append( "<faultcode>" ).append( e.getFaultCode().toString()).append( "</faultcode>\n" );
                xml.append( "<faultstring>" ).append( reason ).append( "</faultstring>\n" );
                xml.append( "</soap:Fault>\n" );
                xml.append( "</soap:Body></soap:Envelope>" );

                endResponse(response, xml.toString());
                return;
            }

            // -> PutObject S3 Bucket Policy would be done in the engine.handleRequest() call
            UserContext.current().initContext( AWSAccessKey, info.getSecretKey(), AWSAccessKey, "S3 DIME request", request );
            putResponse = engine.handleRequest( putRequest );

            xml.append( "<?xml version=\"1.0\" encoding=\"utf-8\"?>" );
            xml.append( "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:tns=\"http://s3.amazonaws.com/doc/2006-03-01/\">" );
            xml.append( "<soap:Body>" );
            xml.append( "<tns:PutObjectResponse>" );
            xml.append( "<tns:PutObjectResponse>" );
            xml.append( "<tns:ETag>\"").append( putResponse.getETag()).append( "\"</tns:ETag>" );
            xml.append( "<tns:LastModified>").append( DatatypeConverter.printDateTime(putResponse.getLastModified())).append( "</tns:LastModified>" );
            xml.append( "</tns:PutObjectResponse></tns:PutObjectResponse>" );
            xml.append( "</soap:Body></soap:Envelope>" );

            endResponse(response, xml.toString());
        } 
        catch(PermissionDeniedException e) {
            logger.error("Unexpected exception " + e.getMessage(), e);
            response.setStatus(403);
            endResponse(response, "Access denied");   	
        }
        catch(Throwable e) 
        {
            logger.error("Unexpected exception " + e.getMessage(), e);
        } 
        finally 
        {
        }
    }


    /**
     * Convert the SOAP XML we extract from the DIME message into our local object.
     * Here Axis2 is not parsing the SOAP for us.   I tried to use the Amazon PutObject
     * parser but it keep throwing exceptions.
     * 
     * @param putObjectInline
     * @return 
     * @throws Exception 
     */
    public static S3PutObjectRequest toEnginePutObjectRequest( InputStream is ) throws Exception 
    {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware( true );

        DocumentBuilder db       = dbf.newDocumentBuilder();
        Document        doc      = db.parse( is );
        Node            parent   = null;
        Node            contents = null;
        NodeList        children = null;
        String          temp     = null;
        String          element  = null;
        int             count    = 0;

        S3PutObjectRequest request = new S3PutObjectRequest();

        // [A] Pull out the simple nodes first
        NodeList part = getElement( doc, "http://s3.amazonaws.com/doc/2006-03-01/", "Bucket" );
        if (null != part)
        {
            if (null != (contents = part.item( 0 )))
                request.setBucketName( contents.getFirstChild().getNodeValue());
        }	
        part = getElement( doc, "http://s3.amazonaws.com/doc/2006-03-01/", "Key" );
        if (null != part)
        {
            if (null != (contents = part.item( 0 )))
                request.setKey( contents.getFirstChild().getNodeValue());
        }		
        part = getElement( doc, "http://s3.amazonaws.com/doc/2006-03-01/", "ContentLength" );
        if (null != part)
        {
            if (null != (contents = part.item( 0 )))
            {
                String length = contents.getFirstChild().getNodeValue();
                if (null != length) request.setContentLength( Long.decode( length ));
            }
        }		
        part = getElement( doc, "http://s3.amazonaws.com/doc/2006-03-01/", "AWSAccessKeyId" );
        if (null != part)
        {
            if (null != (contents = part.item( 0 )))
                request.setAccessKey( contents.getFirstChild().getNodeValue());
        }		
        part = getElement( doc, "http://s3.amazonaws.com/doc/2006-03-01/", "Signature" );
        if (null != part)
        {
            if (null != (contents = part.item( 0 )))
                request.setSignature( contents.getFirstChild().getNodeValue());
        }		
        part = getElement( doc, "http://s3.amazonaws.com/doc/2006-03-01/", "Timestamp" );
        if (null != part)
        {
            if (null != (contents = part.item( 0 )))
                request.setRawTimestamp( contents.getFirstChild().getNodeValue());
        }	
        part = getElement( doc, "http://s3.amazonaws.com/doc/2006-03-01/", "StorageClass" );
        if (null != part)
        {
            if (null != (contents = part.item( 0 )))
                request.setStorageClass( contents.getFirstChild().getNodeValue());
        }		
        part = getElement( doc, "http://s3.amazonaws.com/doc/2006-03-01/", "Credential" );
        if (null != part)
        {
            if (null != (contents = part.item( 0 )))
                request.setCredential( contents.getFirstChild().getNodeValue());
        }


        // [B] Get a list of all 'Metadata' elements
        part = getElement( doc, "http://s3.amazonaws.com/doc/2006-03-01/", "Metadata" );
        if (null != part)
        {
            count = part.getLength();
            S3MetaDataEntry[] metaEntry = new S3MetaDataEntry[ count ];

            for( int i=0; i < count; i++ )
            {
                parent = part.item(i);
                metaEntry[i] = new S3MetaDataEntry();

                // -> get a list of all the children elements of the 'Metadata' parent element
                if (null != (children = parent.getChildNodes()))
                {
                    int numChildren = children.getLength();
                    for( int j=0; j < numChildren; j++ )
                    {
                        contents = children.item( j );
                        element = contents.getNodeName().trim();
                        if ( element.endsWith( "Name" ))
                        {
                            temp = contents.getFirstChild().getNodeValue();
                            if (null != temp) metaEntry[i].setName( temp );
                        }
                        else if (element.endsWith( "Value" ))
                        {
                            temp = contents.getFirstChild().getNodeValue();
                            if (null != temp) metaEntry[i].setValue( temp );
                        }
                    }
                }
            }
            request.setMetaEntries( metaEntry );
        }

        // [C] Get a list of all Grant elements in an AccessControlList
        part = getElement( doc, "http://s3.amazonaws.com/doc/2006-03-01/", "Grant" );
        if (null != part)
        {
            S3AccessControlList engineAcl = new S3AccessControlList();

            count = part.getLength();
            for( int i=0; i < count; i++ )
            {
                parent = part.item(i);
                S3Grant engineGrant = new S3Grant();

                // -> get a list of all the children elements of the 'Grant' parent element
                if (null != (children = parent.getChildNodes()))
                {
                    int numChildren = children.getLength();
                    for( int j=0; j < numChildren; j++ )
                    {
                        contents = children.item( j );
                        element  = contents.getNodeName().trim();
                        if ( element.endsWith( "Grantee" ))
                        {
                            NamedNodeMap attbs = contents.getAttributes();
                            if (null != attbs)
                            {
                                Node type = attbs.getNamedItemNS( "http://www.w3.org/2001/XMLSchema-instance", "type" );
                                if ( null != type ) 
                                    temp = type.getFirstChild().getNodeValue().trim();
                                else temp = null;

                                if ( null != temp && temp.equalsIgnoreCase( "CanonicalUser" ))
                                {
                                    engineGrant.setGrantee(SAcl.GRANTEE_USER);
                                    engineGrant.setCanonicalUserID( getChildNodeValue( contents, "ID" ));
                                } 
                                else throw new UnsupportedOperationException( "Missing http://www.w3.org/2001/XMLSchema-instance:type value" ); 
                            }
                        }
                        else if (element.endsWith( "Permission" ))
                        {
                            temp = contents.getFirstChild().getNodeValue().trim();
                            if (temp.equalsIgnoreCase("READ"        )) engineGrant.setPermission(SAcl.PERMISSION_READ);
                            else if (temp.equalsIgnoreCase("WRITE"       )) engineGrant.setPermission(SAcl.PERMISSION_WRITE);
                            else if (temp.equalsIgnoreCase("READ_ACP"    )) engineGrant.setPermission(SAcl.PERMISSION_READ_ACL);
                            else if (temp.equalsIgnoreCase("WRITE_ACP"   )) engineGrant.setPermission(SAcl.PERMISSION_WRITE_ACL);
                            else if (temp.equalsIgnoreCase("FULL_CONTROL")) engineGrant.setPermission(SAcl.PERMISSION_FULL);
                            else throw new UnsupportedOperationException( "Unsupported permission: " + temp ); 
                        }
                    }
                    engineAcl.addGrant( engineGrant );
                }
            }
            request.setAcl( engineAcl );
        }
        return request;
    }

    /**
     * Have to deal with XML with and without namespaces.
     */
    public static NodeList getElement( Document doc, String namespace, String tagName ) 
    {
        NodeList part = doc.getElementsByTagNameNS( namespace, tagName );
        if (null == part || 0 == part.getLength()) part = doc.getElementsByTagName( tagName );

        return part;
    }

    /**
     * Looking for the value of a specific child of the given parent node.
     * 
     * @param parent
     * @param childName
     * @return
     */
    private static String getChildNodeValue( Node parent, String childName )
    {
        NodeList children = null;
        Node     element  = null;

        if (null != (children = parent.getChildNodes()))
        {
            int numChildren = children.getLength();
            for( int i=0; i < numChildren; i++ )
            {
                if (null != (element = children.item( i )))
                {
                    // -> name may have a namespace on it
                    String name = element.getNodeName().trim();
                    if ( name.endsWith( childName )) 
                    {
                        String value = element.getFirstChild().getNodeValue();
                        if (null != value) value = value.trim();
                        return value;
                    }
                }
            }
        }
        return null;
    }

    private void logRequest(HttpServletRequest request) {
        if(logger.isInfoEnabled()) {
            logger.info("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));
                }
            }
            logger.info( "- End of request -" );
        }
    }
}
