You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ed...@apache.org on 2013/01/15 03:04:54 UTC

[39/44] Revert "Merge remote-tracking branch 'origin/javelin' into javelin"

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/110465b5/awsapi/src/com/cloud/bridge/service/controller/s3/S3BucketAction.java
----------------------------------------------------------------------
diff --git a/awsapi/src/com/cloud/bridge/service/controller/s3/S3BucketAction.java b/awsapi/src/com/cloud/bridge/service/controller/s3/S3BucketAction.java
index 8f77916..c98de34 100644
--- a/awsapi/src/com/cloud/bridge/service/controller/s3/S3BucketAction.java
+++ b/awsapi/src/com/cloud/bridge/service/controller/s3/S3BucketAction.java
@@ -21,19 +21,16 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
-import java.io.PrintWriter;
 import java.io.Reader;
 import java.io.StringWriter;
 import java.io.Writer;
-import java.util.ArrayList;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
-import java.util.List;
 
+import javax.inject.Inject;
 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 javax.xml.stream.XMLStreamException;
@@ -52,24 +49,17 @@ import com.cloud.bridge.io.MTOMAwareResultStreamWriter;
 import com.cloud.bridge.model.BucketPolicyVO;
 import com.cloud.bridge.model.SAcl;
 import com.cloud.bridge.model.SAclVO;
-import com.cloud.bridge.model.SBucket;
 import com.cloud.bridge.model.SBucketVO;
-import com.cloud.bridge.model.SHost;
 import com.cloud.bridge.persist.dao.BucketPolicyDao;
-import com.cloud.bridge.persist.dao.BucketPolicyDaoImpl;
 import com.cloud.bridge.persist.dao.MultipartLoadDao;
-import com.cloud.bridge.persist.dao.SAclDaoImpl;
 import com.cloud.bridge.persist.dao.SBucketDao;
-import com.cloud.bridge.persist.dao.SBucketDaoImpl;
 import com.cloud.bridge.service.S3Constants;
 import com.cloud.bridge.service.S3RestServlet;
-import com.cloud.bridge.service.controller.s3.ServiceProvider;
 import com.cloud.bridge.service.UserContext;
 import com.cloud.bridge.service.core.s3.S3AccessControlList;
 import com.cloud.bridge.service.core.s3.S3AccessControlPolicy;
-import com.cloud.bridge.service.core.s3.S3AuthParams;
-import com.cloud.bridge.service.core.s3.S3BucketAdapter;
 import com.cloud.bridge.service.core.s3.S3BucketPolicy;
+import com.cloud.bridge.service.core.s3.S3BucketPolicy.PolicyAccess;
 import com.cloud.bridge.service.core.s3.S3CanonicalUser;
 import com.cloud.bridge.service.core.s3.S3CreateBucketConfiguration;
 import com.cloud.bridge.service.core.s3.S3CreateBucketRequest;
@@ -86,1083 +76,1077 @@ import com.cloud.bridge.service.core.s3.S3ListBucketObjectEntry;
 import com.cloud.bridge.service.core.s3.S3ListBucketRequest;
 import com.cloud.bridge.service.core.s3.S3ListBucketResponse;
 import com.cloud.bridge.service.core.s3.S3MultipartUpload;
+import com.cloud.bridge.service.core.s3.S3PolicyAction.PolicyActions;
+import com.cloud.bridge.service.core.s3.S3PolicyCondition.ConditionKeys;
 import com.cloud.bridge.service.core.s3.S3PolicyContext;
 import com.cloud.bridge.service.core.s3.S3Response;
 import com.cloud.bridge.service.core.s3.S3SetBucketAccessControlPolicyRequest;
-import com.cloud.bridge.service.core.s3.S3BucketPolicy.PolicyAccess;
-import com.cloud.bridge.service.core.s3.S3PolicyAction.PolicyActions;
-import com.cloud.bridge.service.core.s3.S3PolicyCondition.ConditionKeys;
-import com.cloud.bridge.service.exception.InvalidBucketName;
 import com.cloud.bridge.service.exception.InvalidRequestContentException;
 import com.cloud.bridge.service.exception.NetworkIOException;
 import com.cloud.bridge.service.exception.NoSuchObjectException;
 import com.cloud.bridge.service.exception.ObjectAlreadyExistsException;
-import com.cloud.bridge.service.exception.OutOfServiceException;
 import com.cloud.bridge.service.exception.PermissionDeniedException;
 import com.cloud.bridge.util.Converter;
-import com.cloud.bridge.util.DateHelper;
-import com.cloud.bridge.util.HeaderParam;
+import com.cloud.bridge.util.OrderedPair;
 import com.cloud.bridge.util.PolicyParser;
 import com.cloud.bridge.util.StringHelper;
-import com.cloud.bridge.util.OrderedPair;
-import com.cloud.bridge.util.Triple;
 import com.cloud.bridge.util.XSerializer;
 import com.cloud.bridge.util.XSerializerXmlAdapter;
 import com.cloud.bridge.util.XmlHelper;
-import com.cloud.utils.component.ComponentLocator;
 import com.cloud.utils.db.Transaction;
 
 
 public class S3BucketAction implements ServletAction {
     protected final static Logger logger = Logger.getLogger(S3BucketAction.class);
-    protected final BucketPolicyDao bPolicyDao = ComponentLocator.inject(BucketPolicyDaoImpl.class);
-    protected final SBucketDao bucketDao = ComponentLocator.inject(SBucketDaoImpl.class);
-    
+    @Inject BucketPolicyDao bPolicyDao;
+    @Inject SBucketDao bucketDao;
+
     private DocumentBuilderFactory dbf = null;
-	public S3BucketAction() {
-		dbf = DocumentBuilderFactory.newInstance();
-		dbf.setNamespaceAware( true );
-
-	}
-	
-	public void execute(HttpServletRequest request, HttpServletResponse response) 
-	    throws IOException, XMLStreamException 
-	{
-		String method = request.getMethod(); 
-		String queryString = request.getQueryString();
-		
-		if ( method.equalsIgnoreCase("PUT")) 
-		{
-			 if ( queryString != null && queryString.length() > 0 ) 
-			 {
-			 	  if ( queryString.startsWith("acl")) {
-				 	   executePutBucketAcl(request, response);
-				 	   return;
-				  } 
-				  else if (queryString.startsWith("versioning")) {
-					   executePutBucketVersioning(request, response);
-					   return;
-				  } 
-				  else if (queryString.startsWith("policy")) {
-					   executePutBucketPolicy(request, response);
-					   return;
-				  }
-				  else if (queryString.startsWith("logging")) {
-					   executePutBucketLogging(request, response);
-					   return;
-				  }
-				  else if (queryString.startsWith("website")) {
-					   executePutBucketWebsite(request, response);
-					   return;
-				  }
-			 }
-			 executePutBucket(request, response);
-		} 
-		else if(method.equalsIgnoreCase("GET") || method.equalsIgnoreCase("HEAD")) 
-		{
-			 if (queryString != null && queryString.length() > 0) 
-			 {
-				 if ( queryString.startsWith("acl")) {
-					  executeGetBucketAcl(request, response);
-					  return;
-				 } 
-				 else if (queryString.startsWith("versioning")) {
-					  executeGetBucketVersioning(request, response);
-					  return;
-				 } 
-				 else if (queryString.contains("versions")) {
-					  executeGetBucketObjectVersions(request, response);
-					  return;
-				 } 
-				 else if (queryString.startsWith("location")) {
-					  executeGetBucketLocation(request, response);
-					  return;
-				 }
-				 else if (queryString.startsWith("uploads")) {
-					  executeListMultipartUploads(request, response);
-					  return;
-				 }
-				 else if (queryString.startsWith("policy")) {
-					  executeGetBucketPolicy(request, response);
-					  return;
-				 }
-				 else if (queryString.startsWith("logging")) {
-					  executeGetBucketLogging(request, response);
-					  return;
-				 } 
-				 else if (queryString.startsWith("website")) {
-					  executeGetBucketWebsite(request, response);
-					  return;
-				 } 
-			 }
-			
-			 String bucketAtr = (String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY);
-             if ( bucketAtr.equals( "/" ))
-            	  executeGetAllBuckets(request, response);
-             else executeGetBucket(request, response);
-		} 
-		else if (method.equalsIgnoreCase("DELETE")) 
-		{
-			 if (queryString != null && queryString.length() > 0) 
-			 {
-				 if ( queryString.startsWith("policy")) {
-					  executeDeleteBucketPolicy(request, response);
-					  return;
-				 }
-				 else if (queryString.startsWith("website")) {
-					  executeDeleteBucketWebsite(request, response);
-					  return;
-				 }
-
-			 }
-			 executeDeleteBucket(request, response);
-		}
-		else if ( (method.equalsIgnoreCase("POST")) && (queryString.equalsIgnoreCase("delete")) )
-		{
-			executeMultiObjectDelete(request, response);
-		}
-		else throw new IllegalArgumentException("Unsupported method in REST request");
-	}
-	
-	
-	
-private void executeMultiObjectDelete(HttpServletRequest request, HttpServletResponse response) throws IOException{
-
-		int contentLength = request.getContentLength();
-		StringBuffer  xmlDeleteResponse = null;
-		boolean quite = true;
-		
-		if(contentLength > 0) 
-		{
-			InputStream is = null;
-			String versionID =null;
-			try {
-				is = request.getInputStream();
-				String xml = StringHelper.stringFromStream(is);
-				String elements[] = {"Key","VersionId"};
-				Document doc = XmlHelper.parse(xml);
-				Node node = XmlHelper.getRootNode(doc);
-				
-				if(node == null) {
-					System.out.println("Invalid XML document, no root element");
-					return;
-				}
-				
-				xmlDeleteResponse = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
-						"<DeleteResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">");
-				
-				String bucket = (String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY);
-
-				S3DeleteObjectRequest engineRequest = new S3DeleteObjectRequest();
-				engineRequest.setBucketName( bucket );
-				is.close();
-				
-				doc.getDocumentElement().normalize();
-				NodeList qList = doc.getElementsByTagName("Quiet");
-
-				if (qList.getLength() == 1 ) {
-					Node qNode= qList.item(0);
-					if ( qNode.getFirstChild().getNodeValue().equalsIgnoreCase("true") == false )
-						quite = false;
-					
-					logger.debug("Quite value  :" + qNode.getFirstChild().getNodeValue());
-				}
-				
-				NodeList objList = doc.getElementsByTagName("Object");
-				
-				for (int i = 0; i < objList.getLength(); i++) {
-
-				   Node key = objList.item(i);
-				   NodeList key_data = key.getChildNodes();
-				   
-				   if (key.getNodeType() == Node.ELEMENT_NODE) {
-					  Element eElement = (Element) key;
-					  String key_name = getTagValue(elements[0], eElement);
-						engineRequest.setBucketName(bucket);
-						engineRequest.setKey(key_name);
-
-						if (key_data.getLength() == 2) {
-							  versionID = getTagValue(elements[1], eElement);
-							  engineRequest.setVersion(versionID);
-						  }
-
-						S3Response engineResponse = ServiceProvider.getInstance().getS3Engine().handleRequest( engineRequest );
-						int resultCode = engineResponse.getResultCode();
-						String resutlDesc = engineResponse.getResultDescription();
-						if(resultCode == 204) {
-							if (quite) { // show response depending on quite/verbose
-								xmlDeleteResponse.append("<Deleted><Key>"+key_name+"</Key>");
-								if (resutlDesc != null)
-									xmlDeleteResponse.append(resutlDesc);
-								xmlDeleteResponse.append("</Deleted>");
-							}
-						}
-						else {
-							logger.debug("Error in delete ::" + key_name + " eng response:: " + engineResponse.getResultDescription());
-							xmlDeleteResponse.append("<Error><Key>"+key_name+"</Key>" );
-							if (resutlDesc != null)
-								xmlDeleteResponse.append(resutlDesc);
-							xmlDeleteResponse.append("</Error>");
-						}
-						
-						
-				   }
-				}
-				
-				String version = engineRequest.getVersion();
-				if (null != version) response.addHeader( "x-amz-version-id", version );
-				
-				
-			} catch (IOException e) {
-				logger.error("Unable to read request data due to " + e.getMessage(), e);
-				throw new NetworkIOException(e);
-				
-			} finally {
-				if(is != null) is.close();
-			}
-
-			xmlDeleteResponse.append("</DeleteResult>");
-		
-		}
-		response.setStatus(200);
-		response.setContentType("text/xml; charset=UTF-8");
-    	S3RestServlet.endResponse(response, xmlDeleteResponse.toString());
-		
-	}
-
-	private String getTagValue(String sTag, Element eElement) {
-		
-		NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
-	    Node nValue = (Node) nlList.item(0);
-		return nValue.getNodeValue();
-	  }
-	
-	
-	/** 
-	 * In order to support a policy on the "s3:CreateBucket" action we must be able to set and get
-	 * policies before a bucket is actually created.
-	 * 
-	 * @param request
-	 * @param response
-	 * @throws IOException
-	 */
-	private void executePutBucketPolicy(HttpServletRequest request, HttpServletResponse response) throws IOException
-	{
-		String bucketName = (String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY);
-		String policy = streamToString( request.getInputStream());
-		        
-		// [A] Is there an owner of an existing policy or bucket?
+    public S3BucketAction() {
+        dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware( true );
+
+    }
+
+    @Override
+    public void execute(HttpServletRequest request, HttpServletResponse response) 
+            throws IOException, XMLStreamException 
+            {
+        String method = request.getMethod(); 
+        String queryString = request.getQueryString();
+
+        if ( method.equalsIgnoreCase("PUT")) 
+        {
+            if ( queryString != null && queryString.length() > 0 ) 
+            {
+                if ( queryString.startsWith("acl")) {
+                    executePutBucketAcl(request, response);
+                    return;
+                } 
+                else if (queryString.startsWith("versioning")) {
+                    executePutBucketVersioning(request, response);
+                    return;
+                } 
+                else if (queryString.startsWith("policy")) {
+                    executePutBucketPolicy(request, response);
+                    return;
+                }
+                else if (queryString.startsWith("logging")) {
+                    executePutBucketLogging(request, response);
+                    return;
+                }
+                else if (queryString.startsWith("website")) {
+                    executePutBucketWebsite(request, response);
+                    return;
+                }
+            }
+            executePutBucket(request, response);
+        } 
+        else if(method.equalsIgnoreCase("GET") || method.equalsIgnoreCase("HEAD")) 
+        {
+            if (queryString != null && queryString.length() > 0) 
+            {
+                if ( queryString.startsWith("acl")) {
+                    executeGetBucketAcl(request, response);
+                    return;
+                } 
+                else if (queryString.startsWith("versioning")) {
+                    executeGetBucketVersioning(request, response);
+                    return;
+                } 
+                else if (queryString.contains("versions")) {
+                    executeGetBucketObjectVersions(request, response);
+                    return;
+                } 
+                else if (queryString.startsWith("location")) {
+                    executeGetBucketLocation(request, response);
+                    return;
+                }
+                else if (queryString.startsWith("uploads")) {
+                    executeListMultipartUploads(request, response);
+                    return;
+                }
+                else if (queryString.startsWith("policy")) {
+                    executeGetBucketPolicy(request, response);
+                    return;
+                }
+                else if (queryString.startsWith("logging")) {
+                    executeGetBucketLogging(request, response);
+                    return;
+                } 
+                else if (queryString.startsWith("website")) {
+                    executeGetBucketWebsite(request, response);
+                    return;
+                } 
+            }
+
+            String bucketAtr = (String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY);
+            if ( bucketAtr.equals( "/" ))
+                executeGetAllBuckets(request, response);
+            else executeGetBucket(request, response);
+        } 
+        else if (method.equalsIgnoreCase("DELETE")) 
+        {
+            if (queryString != null && queryString.length() > 0) 
+            {
+                if ( queryString.startsWith("policy")) {
+                    executeDeleteBucketPolicy(request, response);
+                    return;
+                }
+                else if (queryString.startsWith("website")) {
+                    executeDeleteBucketWebsite(request, response);
+                    return;
+                }
+
+            }
+            executeDeleteBucket(request, response);
+        }
+        else if ( (method.equalsIgnoreCase("POST")) && (queryString.equalsIgnoreCase("delete")) )
+        {
+            executeMultiObjectDelete(request, response);
+        }
+        else throw new IllegalArgumentException("Unsupported method in REST request");
+            }
+
+
+
+    private void executeMultiObjectDelete(HttpServletRequest request, HttpServletResponse response) throws IOException{
+
+        int contentLength = request.getContentLength();
+        StringBuffer  xmlDeleteResponse = null;
+        boolean quite = true;
+
+        if(contentLength > 0) 
+        {
+            InputStream is = null;
+            String versionID =null;
+            try {
+                is = request.getInputStream();
+                String xml = StringHelper.stringFromStream(is);
+                String elements[] = {"Key","VersionId"};
+                Document doc = XmlHelper.parse(xml);
+                Node node = XmlHelper.getRootNode(doc);
+
+                if(node == null) {
+                    System.out.println("Invalid XML document, no root element");
+                    return;
+                }
+
+                xmlDeleteResponse = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+                        "<DeleteResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">");
+
+                String bucket = (String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY);
+
+                S3DeleteObjectRequest engineRequest = new S3DeleteObjectRequest();
+                engineRequest.setBucketName( bucket );
+                is.close();
+
+                doc.getDocumentElement().normalize();
+                NodeList qList = doc.getElementsByTagName("Quiet");
+
+                if (qList.getLength() == 1 ) {
+                    Node qNode= qList.item(0);
+                    if ( qNode.getFirstChild().getNodeValue().equalsIgnoreCase("true") == false )
+                        quite = false;
+
+                    logger.debug("Quite value  :" + qNode.getFirstChild().getNodeValue());
+                }
+
+                NodeList objList = doc.getElementsByTagName("Object");
+
+                for (int i = 0; i < objList.getLength(); i++) {
+
+                    Node key = objList.item(i);
+                    NodeList key_data = key.getChildNodes();
+
+                    if (key.getNodeType() == Node.ELEMENT_NODE) {
+                        Element eElement = (Element) key;
+                        String key_name = getTagValue(elements[0], eElement);
+                        engineRequest.setBucketName(bucket);
+                        engineRequest.setKey(key_name);
+
+                        if (key_data.getLength() == 2) {
+                            versionID = getTagValue(elements[1], eElement);
+                            engineRequest.setVersion(versionID);
+                        }
+
+                        S3Response engineResponse = ServiceProvider.getInstance().getS3Engine().handleRequest( engineRequest );
+                        int resultCode = engineResponse.getResultCode();
+                        String resutlDesc = engineResponse.getResultDescription();
+                        if(resultCode == 204) {
+                            if (quite) { // show response depending on quite/verbose
+                                xmlDeleteResponse.append("<Deleted><Key>"+key_name+"</Key>");
+                                if (resutlDesc != null)
+                                    xmlDeleteResponse.append(resutlDesc);
+                                xmlDeleteResponse.append("</Deleted>");
+                            }
+                        }
+                        else {
+                            logger.debug("Error in delete ::" + key_name + " eng response:: " + engineResponse.getResultDescription());
+                            xmlDeleteResponse.append("<Error><Key>"+key_name+"</Key>" );
+                            if (resutlDesc != null)
+                                xmlDeleteResponse.append(resutlDesc);
+                            xmlDeleteResponse.append("</Error>");
+                        }
+
+
+                    }
+                }
+
+                String version = engineRequest.getVersion();
+                if (null != version) response.addHeader( "x-amz-version-id", version );
+
+
+            } catch (IOException e) {
+                logger.error("Unable to read request data due to " + e.getMessage(), e);
+                throw new NetworkIOException(e);
+
+            } finally {
+                if(is != null) is.close();
+            }
+
+            xmlDeleteResponse.append("</DeleteResult>");
+
+        }
+        response.setStatus(200);
+        response.setContentType("text/xml; charset=UTF-8");
+        S3RestServlet.endResponse(response, xmlDeleteResponse.toString());
+
+    }
+
+    private String getTagValue(String sTag, Element eElement) {
+
+        NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
+        Node nValue = nlList.item(0);
+        return nValue.getNodeValue();
+    }
+
+
+    /** 
+     * In order to support a policy on the "s3:CreateBucket" action we must be able to set and get
+     * policies before a bucket is actually created.
+     * 
+     * @param request
+     * @param response
+     * @throws IOException
+     */
+    private void executePutBucketPolicy(HttpServletRequest request, HttpServletResponse response) throws IOException
+    {
+        String bucketName = (String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY);
+        String policy = streamToString( request.getInputStream());
+
+        // [A] Is there an owner of an existing policy or bucket?
         SBucketVO bucket = bucketDao.getByName( bucketName );
         String owner = null;
-        
+
         if ( null != bucket ) 
         {
             owner = bucket.getOwnerCanonicalId();
         }
         else 
         {    try {
-        	     owner = bPolicyDao.getByName(bucketName).getOwnerCanonicalID();
-             }
-             catch( Exception e ) {}
+            owner = bPolicyDao.getByName(bucketName).getOwnerCanonicalID();
+        }
+        catch( Exception e ) {}
         }
 
-        
-		// [B] "The bucket owner by default has permissions to attach bucket policies to their buckets using PUT Bucket policy." 
-		//  -> the bucket owner may want to restrict the IP address from where this can be executed
-	String client = UserContext.current().getCanonicalUserId();
-	S3PolicyContext context = new S3PolicyContext(
-		PolicyActions.PutBucketPolicy, bucketName);
-	
-	switch (S3Engine.verifyPolicy(context)) {
-	case ALLOW:
-	    break;
-
-	case DEFAULT_DENY:
-	    if (null != owner && !client.equals(owner)) {
-		response.setStatus(405);
-		return;
-	    }
-	    break;
-	case DENY:
-	    response.setStatus(403);
-	    return;
-	}			
-	    Transaction txn = Transaction.open(Transaction.AWSAPI_DB);
-	    // [B] Place the policy into the database over writting an existing policy
-    	try {
-    		// -> first make sure that the policy is valid by parsing it
-       		PolicyParser parser = new PolicyParser();
-    		S3BucketPolicy sbp = parser.parse( policy, bucketName );
-    		bPolicyDao.deletePolicy(bucketName);
-    		
-	        if (null != policy && !policy.isEmpty()) {
-	            BucketPolicyVO bpolicy = new BucketPolicyVO(bucketName, client, policy);
-	            bpolicy = bPolicyDao.persist(bpolicy);
-	            //policyDao.addPolicy( bucketName, client, policy );
-	        }
-	                
-    		if (null != sbp) ServiceProvider.getInstance().setBucketPolicy( bucketName, sbp );
-    		response.setStatus(200);
-    		txn.commit();
-    		txn.close();
-    	}
-    	catch( PermissionDeniedException e ) {
-			logger.error("Put Bucket Policy failed due to " + e.getMessage(), e);	
-			throw e; 		
-    	}
-    	catch( ParseException e ) {
-			logger.error("Put Bucket Policy failed due to " + e.getMessage(), e);	
-			throw new PermissionDeniedException( e.toString());		   		
-    	}
-		catch( Exception e ) {
-			logger.error("Put Bucket Policy failed due to " + e.getMessage(), e);	
-			response.setStatus(500);
-		}
-	}
-	
-	private void executeGetBucketPolicy(HttpServletRequest request, HttpServletResponse response) 
-	{
-		String bucketName = (String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY);
-
-		// [A] Is there an owner of an existing policy or bucket?
-	SBucketVO bucket = bucketDao.getByName(bucketName);
-	String owner = null;
-
-	if (null != bucket) {
-	    owner = bucket.getOwnerCanonicalId();
-	} else {
-	    try {
-		owner = bPolicyDao.getByName(bucketName).getOwnerCanonicalID();
-	    } catch (Exception e) {
-	    }
-	}
-
-	// [B]
-	// "The bucket owner by default has permissions to retrieve bucket policies using GET Bucket policy."
-	// -> the bucket owner may want to restrict the IP address from where
-	// this can be executed
-	String client = UserContext.current().getCanonicalUserId();
-	S3PolicyContext context = new S3PolicyContext(
-		PolicyActions.GetBucketPolicy, bucketName);
-	switch (S3Engine.verifyPolicy(context)) {
-	case ALLOW:
-	    break;
-
-	case DEFAULT_DENY:
-	    if (null != owner && !client.equals(owner)) {
-		response.setStatus(405);
-		return;
-	    }
-	    break;
-
-	case DENY:
-	    response.setStatus(403);
-	    return;
-	}
-
-	// [B] Pull the policy from the database if one exists
-	try {
-	    String policy = bPolicyDao.getByName(bucketName).getPolicy();
-	    if (null == policy) {
-		response.setStatus(404);
-	    } else {
-		response.setStatus(200);
-		response.setContentType("application/json");
-		S3RestServlet.endResponse(response, policy);
-	    }
-	} catch (Exception e) {
-	    logger.error("Get Bucket Policy failed due to " + e.getMessage(), e);
-	    response.setStatus(500);
-	}
+
+        // [B] "The bucket owner by default has permissions to attach bucket policies to their buckets using PUT Bucket policy." 
+        //  -> the bucket owner may want to restrict the IP address from where this can be executed
+        String client = UserContext.current().getCanonicalUserId();
+        S3PolicyContext context = new S3PolicyContext(
+                PolicyActions.PutBucketPolicy, bucketName);
+
+        switch (S3Engine.verifyPolicy(context)) {
+        case ALLOW:
+            break;
+
+        case DEFAULT_DENY:
+            if (null != owner && !client.equals(owner)) {
+                response.setStatus(405);
+                return;
+            }
+            break;
+        case DENY:
+            response.setStatus(403);
+            return;
+        }			
+        Transaction txn = Transaction.open(Transaction.AWSAPI_DB);
+        // [B] Place the policy into the database over writting an existing policy
+        try {
+            // -> first make sure that the policy is valid by parsing it
+            PolicyParser parser = new PolicyParser();
+            S3BucketPolicy sbp = parser.parse( policy, bucketName );
+            bPolicyDao.deletePolicy(bucketName);
+
+            if (null != policy && !policy.isEmpty()) {
+                BucketPolicyVO bpolicy = new BucketPolicyVO(bucketName, client, policy);
+                bpolicy = bPolicyDao.persist(bpolicy);
+                //policyDao.addPolicy( bucketName, client, policy );
+            }
+
+            if (null != sbp) ServiceProvider.getInstance().setBucketPolicy( bucketName, sbp );
+            response.setStatus(200);
+            txn.commit();
+            txn.close();
+        }
+        catch( PermissionDeniedException e ) {
+            logger.error("Put Bucket Policy failed due to " + e.getMessage(), e);	
+            throw e; 		
+        }
+        catch( ParseException e ) {
+            logger.error("Put Bucket Policy failed due to " + e.getMessage(), e);	
+            throw new PermissionDeniedException( e.toString());		   		
+        }
+        catch( Exception e ) {
+            logger.error("Put Bucket Policy failed due to " + e.getMessage(), e);	
+            response.setStatus(500);
+        }
+    }
+
+    private void executeGetBucketPolicy(HttpServletRequest request, HttpServletResponse response) 
+    {
+        String bucketName = (String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY);
+
+        // [A] Is there an owner of an existing policy or bucket?
+        SBucketVO bucket = bucketDao.getByName(bucketName);
+        String owner = null;
+
+        if (null != bucket) {
+            owner = bucket.getOwnerCanonicalId();
+        } else {
+            try {
+                owner = bPolicyDao.getByName(bucketName).getOwnerCanonicalID();
+            } catch (Exception e) {
+            }
+        }
+
+        // [B]
+        // "The bucket owner by default has permissions to retrieve bucket policies using GET Bucket policy."
+        // -> the bucket owner may want to restrict the IP address from where
+        // this can be executed
+        String client = UserContext.current().getCanonicalUserId();
+        S3PolicyContext context = new S3PolicyContext(
+                PolicyActions.GetBucketPolicy, bucketName);
+        switch (S3Engine.verifyPolicy(context)) {
+        case ALLOW:
+            break;
+
+        case DEFAULT_DENY:
+            if (null != owner && !client.equals(owner)) {
+                response.setStatus(405);
+                return;
+            }
+            break;
+
+        case DENY:
+            response.setStatus(403);
+            return;
+        }
+
+        // [B] Pull the policy from the database if one exists
+        try {
+            String policy = bPolicyDao.getByName(bucketName).getPolicy();
+            if (null == policy) {
+                response.setStatus(404);
+            } else {
+                response.setStatus(200);
+                response.setContentType("application/json");
+                S3RestServlet.endResponse(response, policy);
+            }
+        } catch (Exception e) {
+            logger.error("Get Bucket Policy failed due to " + e.getMessage(), e);
+            response.setStatus(500);
+        }
     }
 
     private void executeDeleteBucketPolicy(HttpServletRequest request,
-	    HttpServletResponse response) {
-	String bucketName = (String) request
-		.getAttribute(S3Constants.BUCKET_ATTR_KEY);
-
-	SBucketVO bucket = bucketDao.getByName(bucketName);
-	if (bucket != null) {
-	    String client = UserContext.current().getCanonicalUserId();
-	    if (!client.equals(bucket.getOwnerCanonicalId())) {
-		response.setStatus(405);
-		return;
-	    }
-	}
-
-	try {
-
-	    String policy = bPolicyDao.getByName(bucketName).getPolicy();
-	    if (null == policy) {
-		response.setStatus(204);
-	    } else {
-		ServiceProvider.getInstance().deleteBucketPolicy(bucketName);
-		bPolicyDao.deletePolicy(bucketName);
-		response.setStatus(200);
-	    }
-	} catch (Exception e) {
-	    logger.error(
-		    "Delete Bucket Policy failed due to " + e.getMessage(), e);
-	    response.setStatus(500);
-	}
+            HttpServletResponse response) {
+        String bucketName = (String) request
+                .getAttribute(S3Constants.BUCKET_ATTR_KEY);
+
+        SBucketVO bucket = bucketDao.getByName(bucketName);
+        if (bucket != null) {
+            String client = UserContext.current().getCanonicalUserId();
+            if (!client.equals(bucket.getOwnerCanonicalId())) {
+                response.setStatus(405);
+                return;
+            }
+        }
+
+        try {
+
+            String policy = bPolicyDao.getByName(bucketName).getPolicy();
+            if (null == policy) {
+                response.setStatus(204);
+            } else {
+                ServiceProvider.getInstance().deleteBucketPolicy(bucketName);
+                bPolicyDao.deletePolicy(bucketName);
+                response.setStatus(200);
+            }
+        } catch (Exception e) {
+            logger.error(
+                    "Delete Bucket Policy failed due to " + e.getMessage(), e);
+            response.setStatus(500);
+        }
     }
 
     public void executeGetAllBuckets(HttpServletRequest request,
-	    HttpServletResponse response) throws IOException,
-	    XMLStreamException {
-	Calendar cal = Calendar.getInstance();
-	cal.set(1970, 1, 1);
-	S3ListAllMyBucketsRequest engineRequest = new S3ListAllMyBucketsRequest();
-	engineRequest.setAccessKey(UserContext.current().getAccessKey());
-	engineRequest.setRequestTimestamp(cal);
-	engineRequest.setSignature("");
-
-	S3ListAllMyBucketsResponse engineResponse = ServiceProvider
-		.getInstance().getS3Engine().handleRequest(engineRequest);
-
-	// To allow the all buckets list to be serialized via Axiom classes
-	ListAllMyBucketsResponse allBuckets = S3SerializableServiceImplementation
-		.toListAllMyBucketsResponse(engineResponse);
-
-	OutputStream outputStream = response.getOutputStream();
-	response.setStatus(200);
-	response.setContentType("application/xml");
-	// The content-type literally should be "application/xml; charset=UTF-8"
-	// but any compliant JVM supplies utf-8 by default
-
-	// MTOMAwareResultStreamWriter resultWriter = new
-	// MTOMAwareResultStreamWriter ("ListAllMyBucketsResult", outputStream
-	// );
-	// resultWriter.startWrite();
-	// resultWriter.writeout(allBuckets);
-	// resultWriter.stopWrite();
-	StringBuffer xml = new StringBuffer();
-	xml.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
-	xml.append("<ListAllMyBucketsResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">");
-	xml.append("<Owner><ID>");
-	xml.append(engineResponse.getOwner().getID()).append("</ID>");
-	xml.append("<DisplayName>")
-		.append(engineResponse.getOwner().getDisplayName())
-		.append("</DisplayName>");
-	xml.append("</Owner>").append("<Buckets>");
-	SimpleDateFormat sdf = new SimpleDateFormat(
-		"yyyy-MM-dd'T'HH:mm:ss.SSSZ");
-	for (S3ListAllMyBucketsEntry entry : engineResponse.getBuckets()) {
-	    xml.append("<Bucket>").append("<Name>").append(entry.getName())
-		    .append("</Name>");
-	    xml.append("<CreationDate>")
-		    .append(sdf.format(entry.getCreationDate().getTime()))
-		    .append("</CreationDate>");
-	    xml.append("</Bucket>");
-	}
-	xml.append("</Buckets>").append("</ListAllMyBucketsResult>");
-	response.setStatus(200);
-	response.setContentType("text/xml; charset=UTF-8");
-	S3RestServlet.endResponse(response, xml.toString());
-		
-	}
-
-	public void executeGetBucket(HttpServletRequest request, HttpServletResponse response) 
-	    throws IOException, XMLStreamException 
-	{
-	S3ListBucketRequest engineRequest = new S3ListBucketRequest();
-	engineRequest.setBucketName((String) request
-		.getAttribute(S3Constants.BUCKET_ATTR_KEY));
-	engineRequest.setDelimiter(request.getParameter("delimiter"));
-	engineRequest.setMarker(request.getParameter("marker"));
-	engineRequest.setPrefix(request.getParameter("prefix"));
-
-	int maxKeys = Converter.toInt(request.getParameter("max-keys"), 1000);
-	engineRequest.setMaxKeys(maxKeys);
-	try {
-	    S3ListBucketResponse engineResponse = ServiceProvider.getInstance()
-		    .getS3Engine().listBucketContents(engineRequest, false);
-
-	    // To allow the all list buckets result to be serialized via Axiom
-	    // classes
-	    ListBucketResponse oneBucket = S3SerializableServiceImplementation
-		    .toListBucketResponse(engineResponse);
-
-	    OutputStream outputStream = response.getOutputStream();
-	    response.setStatus(200);
-	    response.setContentType("application/xml");
-	    // The content-type literally should be
-	    // "application/xml; charset=UTF-8"
-	    // but any compliant JVM supplies utf-8 by default;
-
-	    MTOMAwareResultStreamWriter resultWriter = new MTOMAwareResultStreamWriter(
-		    "ListBucketResult", outputStream);
-	    resultWriter.startWrite();
-	    resultWriter.writeout(oneBucket);
-	    resultWriter.stopWrite();
-	} catch (NoSuchObjectException nsoe) {
-	    response.setStatus(404);
-	    response.setContentType("application/xml");
-
-	    StringBuffer xmlError = new StringBuffer();
-	    xmlError.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
-		    .append("<Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message>")
-		    .append("<BucketName>")
-		    .append((String) request
-			    .getAttribute(S3Constants.BUCKET_ATTR_KEY))
-		    .append("</BucketName>")
-		    .append("<RequestId>1DEADBEEF9</RequestId>") // TODO
-		    .append("<HostId>abCdeFgHiJ1k2LmN3op4q56r7st89</HostId>") // TODO
-		    .append("</Error>");
-	    S3RestServlet.endResponse(response, xmlError.toString());
-
-	}
-
-	}
-	
-	public void executeGetBucketAcl(HttpServletRequest request, HttpServletResponse response) 
-	    throws IOException, XMLStreamException 
-	{
-		S3GetBucketAccessControlPolicyRequest engineRequest = new S3GetBucketAccessControlPolicyRequest();
-		Calendar cal = Calendar.getInstance();
-		cal.set( 1970, 1, 1 ); 
-		engineRequest.setAccessKey(UserContext.current().getAccessKey());
-		engineRequest.setRequestTimestamp( cal );
-		engineRequest.setSignature( "" );   // TODO - Consider providing signature in a future release which allows additional user description
-		engineRequest.setBucketName((String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY));
-
-		S3AccessControlPolicy engineResponse = ServiceProvider.getInstance().getS3Engine().handleRequest(engineRequest);
-		
-		// To allow the bucket acl policy result to be serialized via Axiom classes
-		GetBucketAccessControlPolicyResponse onePolicy = S3SerializableServiceImplementation.toGetBucketAccessControlPolicyResponse( engineResponse );
-
-		OutputStream outputStream = response.getOutputStream();
-		response.setStatus(200);	
-	    response.setContentType("application/xml");   
-	         // The content-type literally should be "application/xml; charset=UTF-8" 
-	         // but any compliant JVM supplies utf-8 by default;
-	    
-		MTOMAwareResultStreamWriter resultWriter = new MTOMAwareResultStreamWriter ("GetBucketAccessControlPolicyResult", outputStream );
-		resultWriter.startWrite();
-		resultWriter.writeout(onePolicy);
-		resultWriter.stopWrite();
-
-		
-	}
-	
-	public void executeGetBucketVersioning(HttpServletRequest request, HttpServletResponse response) throws IOException
-	{
-		// [A] Does the bucket exist?
-		String bucketName = (String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY);
-		String versioningStatus = null;
-		
-		if (null == bucketName) {
-			logger.error( "executeGetBucketVersioning - no bucket name given" );
-			response.setStatus( 400 ); 
-			return; 
-		}
-		
-		SBucketVO sbucket = bucketDao.getByName( bucketName );
-		if (sbucket == null) {
-			response.setStatus( 404 );
-			return;
-		}
-		
-		// [B] The owner may want to restrict the IP address at which this can be performed
-		String client = UserContext.current().getCanonicalUserId();
-		if (!client.equals( sbucket.getOwnerCanonicalId()))
-		    throw new PermissionDeniedException( "Access Denied - only the owner can read bucket versioning" );
-
-		S3PolicyContext context = new S3PolicyContext( PolicyActions.GetBucketVersioning, bucketName );
-	    if (PolicyAccess.DENY == S3Engine.verifyPolicy( context )) {
-             response.setStatus(403);
-             return;
-	    }
-
-
-	    // [C]
-		switch( sbucket.getVersioningStatus()) {
-		default:
-		case 0: versioningStatus = "";           break;
-		case 1: versioningStatus = "Enabled";    break;
-		case 2: versioningStatus = "Suspended";  break;
-		}
-
-		StringBuffer xml = new StringBuffer();
+            HttpServletResponse response) throws IOException,
+            XMLStreamException {
+        Calendar cal = Calendar.getInstance();
+        cal.set(1970, 1, 1);
+        S3ListAllMyBucketsRequest engineRequest = new S3ListAllMyBucketsRequest();
+        engineRequest.setAccessKey(UserContext.current().getAccessKey());
+        engineRequest.setRequestTimestamp(cal);
+        engineRequest.setSignature("");
+
+        S3ListAllMyBucketsResponse engineResponse = ServiceProvider
+                .getInstance().getS3Engine().handleRequest(engineRequest);
+
+        // To allow the all buckets list to be serialized via Axiom classes
+        ListAllMyBucketsResponse allBuckets = S3SerializableServiceImplementation
+                .toListAllMyBucketsResponse(engineResponse);
+
+        OutputStream outputStream = response.getOutputStream();
+        response.setStatus(200);
+        response.setContentType("application/xml");
+        // The content-type literally should be "application/xml; charset=UTF-8"
+        // but any compliant JVM supplies utf-8 by default
+
+        // MTOMAwareResultStreamWriter resultWriter = new
+        // MTOMAwareResultStreamWriter ("ListAllMyBucketsResult", outputStream
+        // );
+        // resultWriter.startWrite();
+        // resultWriter.writeout(allBuckets);
+        // resultWriter.stopWrite();
+        StringBuffer xml = new StringBuffer();
+        xml.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
+        xml.append("<ListAllMyBucketsResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">");
+        xml.append("<Owner><ID>");
+        xml.append(engineResponse.getOwner().getID()).append("</ID>");
+        xml.append("<DisplayName>")
+        .append(engineResponse.getOwner().getDisplayName())
+        .append("</DisplayName>");
+        xml.append("</Owner>").append("<Buckets>");
+        SimpleDateFormat sdf = new SimpleDateFormat(
+                "yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+        for (S3ListAllMyBucketsEntry entry : engineResponse.getBuckets()) {
+            xml.append("<Bucket>").append("<Name>").append(entry.getName())
+            .append("</Name>");
+            xml.append("<CreationDate>")
+            .append(sdf.format(entry.getCreationDate().getTime()))
+            .append("</CreationDate>");
+            xml.append("</Bucket>");
+        }
+        xml.append("</Buckets>").append("</ListAllMyBucketsResult>");
+        response.setStatus(200);
+        response.setContentType("text/xml; charset=UTF-8");
+        S3RestServlet.endResponse(response, xml.toString());
+
+    }
+
+    public void executeGetBucket(HttpServletRequest request, HttpServletResponse response) 
+            throws IOException, XMLStreamException 
+            {
+        S3ListBucketRequest engineRequest = new S3ListBucketRequest();
+        engineRequest.setBucketName((String) request
+                .getAttribute(S3Constants.BUCKET_ATTR_KEY));
+        engineRequest.setDelimiter(request.getParameter("delimiter"));
+        engineRequest.setMarker(request.getParameter("marker"));
+        engineRequest.setPrefix(request.getParameter("prefix"));
+
+        int maxKeys = Converter.toInt(request.getParameter("max-keys"), 1000);
+        engineRequest.setMaxKeys(maxKeys);
+        try {
+            S3ListBucketResponse engineResponse = ServiceProvider.getInstance()
+                    .getS3Engine().listBucketContents(engineRequest, false);
+
+            // To allow the all list buckets result to be serialized via Axiom
+            // classes
+            ListBucketResponse oneBucket = S3SerializableServiceImplementation
+                    .toListBucketResponse(engineResponse);
+
+            OutputStream outputStream = response.getOutputStream();
+            response.setStatus(200);
+            response.setContentType("application/xml");
+            // The content-type literally should be
+            // "application/xml; charset=UTF-8"
+            // but any compliant JVM supplies utf-8 by default;
+
+            MTOMAwareResultStreamWriter resultWriter = new MTOMAwareResultStreamWriter(
+                    "ListBucketResult", outputStream);
+            resultWriter.startWrite();
+            resultWriter.writeout(oneBucket);
+            resultWriter.stopWrite();
+        } catch (NoSuchObjectException nsoe) {
+            response.setStatus(404);
+            response.setContentType("application/xml");
+
+            StringBuffer xmlError = new StringBuffer();
+            xmlError.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
+            .append("<Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message>")
+            .append("<BucketName>")
+            .append((String) request
+                    .getAttribute(S3Constants.BUCKET_ATTR_KEY))
+                    .append("</BucketName>")
+                    .append("<RequestId>1DEADBEEF9</RequestId>") // TODO
+                    .append("<HostId>abCdeFgHiJ1k2LmN3op4q56r7st89</HostId>") // TODO
+                    .append("</Error>");
+            S3RestServlet.endResponse(response, xmlError.toString());
+
+        }
+
+            }
+
+    public void executeGetBucketAcl(HttpServletRequest request, HttpServletResponse response) 
+            throws IOException, XMLStreamException 
+            {
+        S3GetBucketAccessControlPolicyRequest engineRequest = new S3GetBucketAccessControlPolicyRequest();
+        Calendar cal = Calendar.getInstance();
+        cal.set( 1970, 1, 1 ); 
+        engineRequest.setAccessKey(UserContext.current().getAccessKey());
+        engineRequest.setRequestTimestamp( cal );
+        engineRequest.setSignature( "" );   // TODO - Consider providing signature in a future release which allows additional user description
+        engineRequest.setBucketName((String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY));
+
+        S3AccessControlPolicy engineResponse = ServiceProvider.getInstance().getS3Engine().handleRequest(engineRequest);
+
+        // To allow the bucket acl policy result to be serialized via Axiom classes
+        GetBucketAccessControlPolicyResponse onePolicy = S3SerializableServiceImplementation.toGetBucketAccessControlPolicyResponse( engineResponse );
+
+        OutputStream outputStream = response.getOutputStream();
+        response.setStatus(200);	
+        response.setContentType("application/xml");   
+        // The content-type literally should be "application/xml; charset=UTF-8" 
+        // but any compliant JVM supplies utf-8 by default;
+
+        MTOMAwareResultStreamWriter resultWriter = new MTOMAwareResultStreamWriter ("GetBucketAccessControlPolicyResult", outputStream );
+        resultWriter.startWrite();
+        resultWriter.writeout(onePolicy);
+        resultWriter.stopWrite();
+
+
+            }
+
+    public void executeGetBucketVersioning(HttpServletRequest request, HttpServletResponse response) throws IOException
+    {
+        // [A] Does the bucket exist?
+        String bucketName = (String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY);
+        String versioningStatus = null;
+
+        if (null == bucketName) {
+            logger.error( "executeGetBucketVersioning - no bucket name given" );
+            response.setStatus( 400 ); 
+            return; 
+        }
+
+        SBucketVO sbucket = bucketDao.getByName( bucketName );
+        if (sbucket == null) {
+            response.setStatus( 404 );
+            return;
+        }
+
+        // [B] The owner may want to restrict the IP address at which this can be performed
+        String client = UserContext.current().getCanonicalUserId();
+        if (!client.equals( sbucket.getOwnerCanonicalId()))
+            throw new PermissionDeniedException( "Access Denied - only the owner can read bucket versioning" );
+
+        S3PolicyContext context = new S3PolicyContext( PolicyActions.GetBucketVersioning, bucketName );
+        if (PolicyAccess.DENY == S3Engine.verifyPolicy( context )) {
+            response.setStatus(403);
+            return;
+        }
+
+
+        // [C]
+        switch( sbucket.getVersioningStatus()) {
+        default:
+        case 0: versioningStatus = "";           break;
+        case 1: versioningStatus = "Enabled";    break;
+        case 2: versioningStatus = "Suspended";  break;
+        }
+
+        StringBuffer xml = new StringBuffer();
         xml.append( "<?xml version=\"1.0\" encoding=\"utf-8\"?>" );
         xml.append( "<VersioningConfiguration xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">" );
         if (0 < versioningStatus.length()) xml.append( "<Status>" ).append( versioningStatus ).append( "</Status>" );
         xml.append( "</VersioningConfiguration>" );
-      
-		response.setStatus(200);
-	    response.setContentType("text/xml; charset=UTF-8");
-    	S3RestServlet.endResponse(response, xml.toString());
-	}
-	
-	public void executeGetBucketObjectVersions(HttpServletRequest request, HttpServletResponse response) throws IOException
-	{   
-		S3ListBucketRequest engineRequest = new S3ListBucketRequest();
-		String keyMarker       = request.getParameter("key-marker");
-		String versionIdMarker = request.getParameter("version-id-marker");
-		
-		engineRequest.setBucketName((String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY));
-		engineRequest.setDelimiter(request.getParameter("delimiter"));
-		engineRequest.setMarker( keyMarker );  
-		engineRequest.setPrefix(request.getParameter("prefix"));
-		engineRequest.setVersionIdMarker( versionIdMarker );
-		
-		int maxKeys = Converter.toInt(request.getParameter("max-keys"), 1000);
-		engineRequest.setMaxKeys(maxKeys);
-		S3ListBucketResponse engineResponse = ServiceProvider.getInstance().getS3Engine().listBucketContents( engineRequest, true );
-		
-		// -> the SOAP version produces different XML
-		StringBuffer xml = new StringBuffer();
+
+        response.setStatus(200);
+        response.setContentType("text/xml; charset=UTF-8");
+        S3RestServlet.endResponse(response, xml.toString());
+    }
+
+    public void executeGetBucketObjectVersions(HttpServletRequest request, HttpServletResponse response) throws IOException
+    {   
+        S3ListBucketRequest engineRequest = new S3ListBucketRequest();
+        String keyMarker       = request.getParameter("key-marker");
+        String versionIdMarker = request.getParameter("version-id-marker");
+
+        engineRequest.setBucketName((String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY));
+        engineRequest.setDelimiter(request.getParameter("delimiter"));
+        engineRequest.setMarker( keyMarker );  
+        engineRequest.setPrefix(request.getParameter("prefix"));
+        engineRequest.setVersionIdMarker( versionIdMarker );
+
+        int maxKeys = Converter.toInt(request.getParameter("max-keys"), 1000);
+        engineRequest.setMaxKeys(maxKeys);
+        S3ListBucketResponse engineResponse = ServiceProvider.getInstance().getS3Engine().listBucketContents( engineRequest, true );
+
+        // -> the SOAP version produces different XML
+        StringBuffer xml = new StringBuffer();
         xml.append( "<?xml version=\"1.0\" encoding=\"utf-8\"?>" );
         xml.append( "<ListVersionsResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">" );
         xml.append( "<Name>" ).append( engineResponse.getBucketName()).append( "</Name>" );
-        
+
         if ( null == keyMarker )
-        	 xml.append( "<KeyMarker/>" );
+            xml.append( "<KeyMarker/>" );
         else xml.append( "<KeyMarker>" ).append( keyMarker ).append( "</KeyMarker" ); 
-  
+
         if ( null == versionIdMarker )
-       	     xml.append( "<VersionIdMarker/>" );
+            xml.append( "<VersionIdMarker/>" );
         else xml.append( "<VersionIdMarker>" ).append( keyMarker ).append( "</VersionIdMarker" ); 
 
         xml.append( "<MaxKeys>" ).append( engineResponse.getMaxKeys()).append( "</MaxKeys>" );
         xml.append( "<IsTruncated>" ).append( engineResponse.isTruncated()).append( "</IsTruncated>" );
-        
+
         S3ListBucketObjectEntry[] versions = engineResponse.getContents();
         for( int i=0; null != versions && i < versions.length; i++ )
         {
-        	 S3CanonicalUser owner    = versions[i].getOwner();
-        	 boolean isDeletionMarker = versions[i].getIsDeletionMarker();
-        	 String displayName       = owner.getDisplayName();
-        	 String id                = owner.getID();
-        	 
-        	 if ( isDeletionMarker ) 
-        	 { 	  
-        		  xml.append( "<DeleteMarker>" );  	 
-                  xml.append( "<Key>" ).append( versions[i].getKey()).append( "</Key>" );
-                  xml.append( "<VersionId>" ).append( versions[i].getVersion()).append( "</VersionId>" );
-                  xml.append( "<IsLatest>" ).append( versions[i].getIsLatest()).append( "</IsLatest>" );
-                  xml.append( "<LastModified>" ).append( DatatypeConverter.printDateTime( versions[i].getLastModified())).append( "</LastModified>" );
-        	 }
-        	 else
-        	 { 	  xml.append( "<Version>" );  	 
-                  xml.append( "<Key>" ).append( versions[i].getKey()).append( "</Key>" );
-                  xml.append( "<VersionId>" ).append( versions[i].getVersion()).append( "</VersionId>" );
-                  xml.append( "<IsLatest>" ).append( versions[i].getIsLatest()).append( "</IsLatest>" );
-                  xml.append( "<LastModified>" ).append( DatatypeConverter.printDateTime( versions[i].getLastModified())).append( "</LastModified>" );
-                  xml.append( "<ETag>" ).append( versions[i].getETag()).append( "</ETag>" );
-                  xml.append( "<Size>" ).append( versions[i].getSize()).append( "</Size>" );
-                  xml.append( "<StorageClass>" ).append( versions[i].getStorageClass()).append( "</StorageClass>" );
-        	 }
-        	 
-             xml.append( "<Owner>" );
-             xml.append( "<ID>" ).append( id ).append( "</ID>" );
-             if ( null == displayName )
-              	  xml.append( "<DisplayName/>" );
-             else xml.append( "<DisplayName>" ).append( owner.getDisplayName()).append( "</DisplayName>" );
-             xml.append( "</Owner>" );
-        	 
-             if ( isDeletionMarker )
-            	  xml.append( "</DeleteMarker>" ); 
-             else xml.append( "</Version>" );
+            S3CanonicalUser owner    = versions[i].getOwner();
+            boolean isDeletionMarker = versions[i].getIsDeletionMarker();
+            String displayName       = owner.getDisplayName();
+            String id                = owner.getID();
+
+            if ( isDeletionMarker ) 
+            { 	  
+                xml.append( "<DeleteMarker>" );  	 
+                xml.append( "<Key>" ).append( versions[i].getKey()).append( "</Key>" );
+                xml.append( "<VersionId>" ).append( versions[i].getVersion()).append( "</VersionId>" );
+                xml.append( "<IsLatest>" ).append( versions[i].getIsLatest()).append( "</IsLatest>" );
+                xml.append( "<LastModified>" ).append( DatatypeConverter.printDateTime( versions[i].getLastModified())).append( "</LastModified>" );
+            }
+            else
+            { 	  xml.append( "<Version>" );  	 
+            xml.append( "<Key>" ).append( versions[i].getKey()).append( "</Key>" );
+            xml.append( "<VersionId>" ).append( versions[i].getVersion()).append( "</VersionId>" );
+            xml.append( "<IsLatest>" ).append( versions[i].getIsLatest()).append( "</IsLatest>" );
+            xml.append( "<LastModified>" ).append( DatatypeConverter.printDateTime( versions[i].getLastModified())).append( "</LastModified>" );
+            xml.append( "<ETag>" ).append( versions[i].getETag()).append( "</ETag>" );
+            xml.append( "<Size>" ).append( versions[i].getSize()).append( "</Size>" );
+            xml.append( "<StorageClass>" ).append( versions[i].getStorageClass()).append( "</StorageClass>" );
+            }
+
+            xml.append( "<Owner>" );
+            xml.append( "<ID>" ).append( id ).append( "</ID>" );
+            if ( null == displayName )
+                xml.append( "<DisplayName/>" );
+            else xml.append( "<DisplayName>" ).append( owner.getDisplayName()).append( "</DisplayName>" );
+            xml.append( "</Owner>" );
+
+            if ( isDeletionMarker )
+                xml.append( "</DeleteMarker>" ); 
+            else xml.append( "</Version>" );
         }
         xml.append( "</ListVersionsResult>" );
-      
-		response.setStatus(200);
-	    response.setContentType("text/xml; charset=UTF-8");
-    	S3RestServlet.endResponse(response, xml.toString());
-	}
-	
-	public void executeGetBucketLogging(HttpServletRequest request, HttpServletResponse response) throws IOException {
-		// TODO -- Review this in future.  Currently this is a beta feature of S3
-		response.setStatus(405);
-	}
-	
-	public void executeGetBucketLocation(HttpServletRequest request, HttpServletResponse response) throws IOException {
-              // TODO - This is a fakery! We don't actually store location in backend
-                  StringBuffer xml = new StringBuffer();
-                      xml.append( "<?xml version=\"1.0\" encoding=\"utf-8\"?>" );
-                      xml.append( "<LocationConstraint xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">" );
-                      // This is the real fakery
-                     xml.append( "us-west-2" );
-                      xml.append( "</LocationConstraint>" );
-                  response.setStatus(200);
-                    response.setContentType("text/xml; charset=UTF-8");
-                    S3RestServlet.endResponse(response, xml.toString());
-	}
-
-	public void executeGetBucketWebsite(HttpServletRequest request, HttpServletResponse response) throws IOException {
-		response.setStatus(405);
-	}
-
-	public void executeDeleteBucketWebsite(HttpServletRequest request, HttpServletResponse response) throws IOException {
-		response.setStatus(405);
-	}
-
-	public void executePutBucket(HttpServletRequest request, HttpServletResponse response) throws IOException 
-	{
-		int contentLength = request.getContentLength();
-		Object objectInContent = null;
-		
-		if(contentLength > 0) 
-		{
-			InputStream is = null;
-			try {
-				is = request.getInputStream();
-				String xml = StringHelper.stringFromStream(is);
-                                Class.forName("com.cloud.bridge.service.core.s3.S3CreateBucketConfiguration");
-				XSerializer serializer = new XSerializer(new XSerializerXmlAdapter()); 
-				objectInContent = serializer.serializeFrom(xml);
-				if(objectInContent != null && !(objectInContent instanceof S3CreateBucketConfiguration)) {
-					throw new InvalidRequestContentException("Invalid request content in create-bucket: " + xml);
-				}
-				is.close();
-				
-			} catch (IOException e) {
-				logger.error("Unable to read request data due to " + e.getMessage(), e);
-				throw new NetworkIOException(e);
-				
-			}  catch (ClassNotFoundException e) {
-                           logger.error("In a normal world this should never never happen:" + e.getMessage(), e);
-                           throw new RuntimeException("A required class was not found in the classpath:" + e.getMessage());
-                        }
-                        finally {
-				if(is != null) is.close();
-			}
-		}
-		
-		S3CreateBucketRequest engineRequest = new S3CreateBucketRequest();
-		engineRequest.setBucketName((String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY));
-		engineRequest.setConfig((S3CreateBucketConfiguration)objectInContent);
-		try {
-		S3CreateBucketResponse engineResponse = ServiceProvider.getInstance().getS3Engine().handleRequest(engineRequest);
-		response.addHeader("Location", "/" + engineResponse.getBucketName());
-		response.setContentLength(0);
-		response.setStatus(200);
-		response.flushBuffer();
-		} catch (ObjectAlreadyExistsException oaee) {
-		    response.setStatus(409);
-		    String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <Error><Code>OperationAborted</Code><Message>A conflicting conditional operation is currently in progress against this resource. Please try again..</Message>";
-		    response.setContentType("text/xml; charset=UTF-8");
-	        S3RestServlet.endResponse(response, xml.toString());
-		}
-	}
-	
-	public void executePutBucketAcl(HttpServletRequest request, HttpServletResponse response) throws IOException 
-	{ 
-		// [A] Determine that there is an applicable bucket which might have an ACL set
-
-	String bucketName = (String) request
-		.getAttribute(S3Constants.BUCKET_ATTR_KEY);
-	SBucketVO bucket = bucketDao.getByName(bucketName);
-	String owner = null;
-	if (null != bucket)
-	    owner = bucket.getOwnerCanonicalId();
-	if (null == owner) {
-	    logger.error("ACL update failed since " + bucketName
-		    + " does not exist");
-	    throw new IOException("ACL update failed");
-	}
-
-	// [B] Obtain the grant request which applies to the acl request string.
-	// This latter is supplied as the value of the x-amz-acl header.
-
-	S3SetBucketAccessControlPolicyRequest engineRequest = new S3SetBucketAccessControlPolicyRequest();
-	S3Grant grantRequest = new S3Grant();
-	S3AccessControlList aclRequest = new S3AccessControlList();
-
-	String aclRequestString = request.getHeader("x-amz-acl");
-	OrderedPair<Integer, Integer> accessControlsForBucketOwner = SAclVO.getCannedAccessControls(aclRequestString, "SBucket");
-	grantRequest.setPermission(accessControlsForBucketOwner.getFirst());
-	grantRequest.setGrantee(accessControlsForBucketOwner.getSecond());
-	grantRequest.setCanonicalUserID(owner);
-	aclRequest.addGrant(grantRequest);
-	engineRequest.setAcl(aclRequest);
-	engineRequest.setBucketName(bucketName);
-
-	// [C] Allow an S3Engine to handle the
-	// S3SetBucketAccessControlPolicyRequest
-	S3Response engineResponse = ServiceProvider.getInstance().getS3Engine()
-		.handleRequest(engineRequest);
-	response.setStatus(engineResponse.getResultCode());
-
-	}
-	
-	public void executePutBucketVersioning(HttpServletRequest request, HttpServletResponse response) throws IOException 
-	{
-	String bucketName = (String) request.getAttribute(S3Constants.BUCKET_ATTR_KEY);
-	String versioningStatus = null;
-	Node item = null;
-
-	if (null == bucketName) {
-	    logger.error("executePutBucketVersioning - no bucket name given");
-	    response.setStatus(400);
-	    return;
-	}
-
-	// -> is the XML as defined?
-	try {
-	    DocumentBuilder db = dbf.newDocumentBuilder();
-	    Document restXML = db.parse(request.getInputStream());
-	    NodeList match = S3RestServlet.getElement(restXML,
-		    "http://s3.amazonaws.com/doc/2006-03-01/", "Status");
-	    if (0 < match.getLength()) {
-		item = match.item(0);
-		versioningStatus = new String(item.getFirstChild()
-			.getNodeValue());
-	    } else {
-		logger.error("executePutBucketVersioning - cannot find Status tag in XML body");
-		response.setStatus(400);
-		return;
-	    }
-	} catch (Exception e) {
-	    logger.error(
-		    "executePutBucketVersioning - failed to parse XML due to "
-			    + e.getMessage(), e);
-	    response.setStatus(400);
-	    return;
-	}
-
-	try {
-	    // Irrespective of what the ACLs say only the owner can turn on
-	    // versioning on a bucket.
-	    // The bucket owner may want to restrict the IP address from which
-	    // this can occur.
-	    
-	    SBucketVO sbucket = bucketDao.getByName(bucketName);
-
-	    String client = UserContext.current().getCanonicalUserId();
-	    if (!client.equals(sbucket.getOwnerCanonicalId()))
-		throw new PermissionDeniedException(
-			"Access Denied - only the owner can turn on versioing on a bucket");
-
-	    S3PolicyContext context = new S3PolicyContext(
-		    PolicyActions.PutBucketVersioning, bucketName);
-	    if (PolicyAccess.DENY == S3Engine.verifyPolicy(context)) {
-		response.setStatus(403);
-		return;
-	    }
-
-	    if (versioningStatus.equalsIgnoreCase("Enabled"))
-		sbucket.setVersioningStatus(1);
-	    else if (versioningStatus.equalsIgnoreCase("Suspended"))
-		sbucket.setVersioningStatus(2);
-	    else {
-		logger.error("executePutBucketVersioning - unknown state: ["
-			+ versioningStatus + "]");
-		response.setStatus(400);
-		return;
-	    }
-	    bucketDao.update(sbucket.getId(), sbucket);
-
-	} catch (PermissionDeniedException e) {
-	    logger.error(
-		    "executePutBucketVersioning - failed due to "
-			    + e.getMessage(), e);
-	    throw e;
-
-	} catch (Exception e) {
-	    logger.error(
-		    "executePutBucketVersioning - failed due to "
-			    + e.getMessage(), e);
-	    response.setStatus(500);
-	    return;
-	}
-	response.setStatus(200);
-	}
-	
-	public void executePutBucketLogging(HttpServletRequest request, HttpServletResponse response) throws IOException {
-		// TODO -- Review this in future.  Currently this is a S3 beta feature
-		response.setStatus(501);
-	}
-	
-	public void executePutBucketWebsite(HttpServletRequest request, HttpServletResponse response) throws IOException {
-		// TODO -- LoPri - Undertake checks on Put Bucket Website
-		// Tested using configuration <Directory /Users/john1/S3-Mount>\nAllowOverride FileInfo AuthConfig Limit...</Directory> in httpd.conf
-	    // 	Need some way of using  AllowOverride to allow use of .htaccess and then pushing .httaccess file to bucket subdirectory of mount point
-		// Currently has noop effect in the sense that a running apachectl process sees the directory contents without further action
-		response.setStatus(200);
-	}
-
-	public void executeDeleteBucket(HttpServletRequest request, HttpServletResponse response) throws IOException 
-	{
-		S3DeleteBucketRequest engineRequest = new S3DeleteBucketRequest();
-		engineRequest.setBucketName((String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY));
-		S3Response engineResponse = ServiceProvider.getInstance().getS3Engine().handleRequest(engineRequest);  
-		response.setStatus(engineResponse.getResultCode());
-		response.flushBuffer();
-	}
-	
-	/**
-	 * Multipart upload is a complex operation with all the options defined by Amazon.   Part of the functionality is 
-	 * provided by the query done against the database.  The CommonPrefixes functionality is done the same way 
-	 * as done in the listBucketContents function (i.e., by iterating though the list to decide which output 
-	 * element each key is placed).
-	 * 
-	 * @param request
-	 * @param response
-	 * @throws IOException
-	 */
-	public void executeListMultipartUploads(HttpServletRequest request, HttpServletResponse response) throws IOException 
-	{
-		// [A] Obtain parameters and do basic bucket verification
-	String bucketName = (String) request
-		.getAttribute(S3Constants.BUCKET_ATTR_KEY);
-	String delimiter = request.getParameter("delimiter");
-	String keyMarker = request.getParameter("key-marker");
-	String prefix = request.getParameter("prefix");
-	int maxUploads = 1000;
-	int nextUploadId = 0;
-	String nextKey = null;
-	boolean isTruncated = false;
-	S3MultipartUpload[] uploads = null;
-	S3MultipartUpload onePart = null;
-	String temp = request.getParameter("max-uploads");
-	if (null != temp) {
-	    maxUploads = Integer.parseInt(temp);
-	    if (maxUploads > 1000 || maxUploads < 0)
-		maxUploads = 1000;
-	}
-
-	// -> upload-id-marker is ignored unless key-marker is also specified
-	String uploadIdMarker = request.getParameter("upload-id-marker");
-	if (null == keyMarker)
-	    uploadIdMarker = null;
-
-	// -> does the bucket exist, we may need it to verify access permissions
-	SBucketVO bucket = bucketDao.getByName(bucketName);
-	if (bucket == null) {
-	    logger.error("listMultipartUpload failed since " + bucketName
-		    + " does not exist");
-	    response.setStatus(404);
-	    return;
-	}
-
-	S3PolicyContext context = new S3PolicyContext(
-		PolicyActions.ListBucketMultipartUploads, bucketName);
-	context.setEvalParam(ConditionKeys.Prefix, prefix);
-	context.setEvalParam(ConditionKeys.Delimiter, delimiter);
-	S3Engine.verifyAccess(context, "SBucket", bucket.getId(),
-		SAcl.PERMISSION_READ);
-
-	// [B] Query the multipart table to get the list of current uploads
-	try {
-	    MultipartLoadDao uploadDao = new MultipartLoadDao();
-	    OrderedPair<S3MultipartUpload[], Boolean> result = uploadDao
-		    .getInitiatedUploads(bucketName, maxUploads, prefix,
-			    keyMarker, uploadIdMarker);
-	    uploads = result.getFirst();
-	    isTruncated = result.getSecond().booleanValue();
-	} catch (Exception e) {
-	    logger.error(
-		    "List Multipart Uploads failed due to " + e.getMessage(), e);
-	    response.setStatus(500);
-	}
-
-	StringBuffer xml = new StringBuffer();
-	xml.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
-	xml.append("<ListMultipartUploadsResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">");
-	xml.append("<Bucket>").append(bucketName).append("</Bucket>");
-	xml.append("<KeyMarker>").append((null == keyMarker ? "" : keyMarker))
-		.append("</KeyMarker>");
-	xml.append("<UploadIdMarker>")
-		.append((null == uploadIdMarker ? "" : uploadIdMarker))
-		.append("</UploadIdMarker>");
-
-	// [C] Construct the contents of the <Upload> element
-	StringBuffer partsList = new StringBuffer();
-	for (int i = 0; i < uploads.length; i++) {
-	    onePart = uploads[i];
-	    if (null == onePart)
-		break;
-
-	    if (delimiter != null && !delimiter.isEmpty()) {
-		// -> is this available only in the CommonPrefixes element?
-		if (StringHelper.substringInBetween(onePart.getKey(), prefix,
-			delimiter) != null)
-		    continue;
-	    }
-
-	    nextKey = onePart.getKey();
-	    nextUploadId = onePart.getId();
-	    partsList.append("<Upload>");
-	    partsList.append("<Key>").append(nextKey).append("</Key>");
-	    partsList.append("<UploadId>").append(nextUploadId)
-		    .append("</UploadId>");
-	    partsList.append("<Initiator>");
-	    partsList.append("<ID>").append(onePart.getAccessKey())
-		    .append("</ID>");
-	    partsList.append("<DisplayName></DisplayName>");
-	    partsList.append("</Initiator>");
-	    partsList.append("<Owner>");
-	    partsList.append("<ID>").append(onePart.getAccessKey())
-		    .append("</ID>");
-	    partsList.append("<DisplayName></DisplayName>");
-	    partsList.append("</Owner>");
-	    partsList.append("<StorageClass>STANDARD</StorageClass>");
-	    partsList
-		    .append("<Initiated>")
-		    .append(DatatypeConverter.printDateTime(onePart
-			    .getLastModified())).append("</Initiated>");
-	    partsList.append("</Upload>");
-	}
-
-	// [D] Construct the contents of the <CommonPrefixes> elements (if any)
-	for (int i = 0; i < uploads.length; i++) {
-	    onePart = uploads[i];
-	    if (null == onePart)
-		break;
-
-	    if (delimiter != null && !delimiter.isEmpty()) {
-		String subName = StringHelper.substringInBetween(
-			onePart.getKey(), prefix, delimiter);
-		if (subName != null) {
-		    partsList.append("<CommonPrefixes>");
-		    partsList.append("<Prefix>");
-		    if (prefix != null && prefix.length() > 0)
-			partsList.append(prefix + delimiter + subName);
-		    else
-			partsList.append(subName);
-		    partsList.append("</Prefix>");
-		    partsList.append("</CommonPrefixes>");
-		}
-	    }
-	}
-
-	// [D] Finish off the response
-	xml.append("<NextKeyMarker>").append((null == nextKey ? "" : nextKey))
-		.append("</NextKeyMarker>");
-	xml.append("<NextUploadIdMarker>")
-		.append((0 == nextUploadId ? "" : nextUploadId))
-		.append("</NextUploadIdMarker>");
-	xml.append("<MaxUploads>").append(maxUploads).append("</MaxUploads>");
-	xml.append("<IsTruncated>").append(isTruncated)
-		.append("</IsTruncated>");
-
-	xml.append(partsList.toString());
-	xml.append("</ListMultipartUploadsResult>");
-
-	response.setStatus(200);
-	response.setContentType("text/xml; charset=UTF-8");
-	S3RestServlet.endResponse(response, xml.toString());
-	}
-	
-	private String streamToString( InputStream is ) throws IOException 
-	{
-		int n = 0;
-		
-	    if ( null != is ) 
-	    {
-	         Writer writer = new StringWriter();
-	         char[] buffer = new char[1024];
-	         try {
-	             Reader reader = new BufferedReader( new InputStreamReader(is, "UTF-8"));
-	             while ((n = reader.read(buffer)) != -1) writer.write(buffer, 0, n);
-             } 
-	         finally {
-	             is.close();
-	         }
-	         return writer.toString();	        
-	    } 
-	    else return null;       
+
+        response.setStatus(200);
+        response.setContentType("text/xml; charset=UTF-8");
+        S3RestServlet.endResponse(response, xml.toString());
+    }
+
+    public void executeGetBucketLogging(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        // TODO -- Review this in future.  Currently this is a beta feature of S3
+        response.setStatus(405);
+    }
+
+    public void executeGetBucketLocation(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        // TODO - This is a fakery! We don't actually store location in backend
+        StringBuffer xml = new StringBuffer();
+        xml.append( "<?xml version=\"1.0\" encoding=\"utf-8\"?>" );
+        xml.append( "<LocationConstraint xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">" );
+        // This is the real fakery
+        xml.append( "us-west-2" );
+        xml.append( "</LocationConstraint>" );
+        response.setStatus(200);
+        response.setContentType("text/xml; charset=UTF-8");
+        S3RestServlet.endResponse(response, xml.toString());
+    }
+
+    public void executeGetBucketWebsite(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        response.setStatus(405);
+    }
+
+    public void executeDeleteBucketWebsite(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        response.setStatus(405);
+    }
+
+    public void executePutBucket(HttpServletRequest request, HttpServletResponse response) throws IOException 
+    {
+        int contentLength = request.getContentLength();
+        Object objectInContent = null;
+
+        if(contentLength > 0) 
+        {
+            InputStream is = null;
+            try {
+                is = request.getInputStream();
+                String xml = StringHelper.stringFromStream(is);
+                Class.forName("com.cloud.bridge.service.core.s3.S3CreateBucketConfiguration");
+                XSerializer serializer = new XSerializer(new XSerializerXmlAdapter()); 
+                objectInContent = serializer.serializeFrom(xml);
+                if(objectInContent != null && !(objectInContent instanceof S3CreateBucketConfiguration)) {
+                    throw new InvalidRequestContentException("Invalid request content in create-bucket: " + xml);
+                }
+                is.close();
+
+            } catch (IOException e) {
+                logger.error("Unable to read request data due to " + e.getMessage(), e);
+                throw new NetworkIOException(e);
+
+            }  catch (ClassNotFoundException e) {
+                logger.error("In a normal world this should never never happen:" + e.getMessage(), e);
+                throw new RuntimeException("A required class was not found in the classpath:" + e.getMessage());
+            }
+            finally {
+                if(is != null) is.close();
+            }
+        }
+
+        S3CreateBucketRequest engineRequest = new S3CreateBucketRequest();
+        engineRequest.setBucketName((String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY));
+        engineRequest.setConfig((S3CreateBucketConfiguration)objectInContent);
+        try {
+            S3CreateBucketResponse engineResponse = ServiceProvider.getInstance().getS3Engine().handleRequest(engineRequest);
+            response.addHeader("Location", "/" + engineResponse.getBucketName());
+            response.setContentLength(0);
+            response.setStatus(200);
+            response.flushBuffer();
+        } catch (ObjectAlreadyExistsException oaee) {
+            response.setStatus(409);
+            String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <Error><Code>OperationAborted</Code><Message>A conflicting conditional operation is currently in progress against this resource. Please try again..</Message>";
+            response.setContentType("text/xml; charset=UTF-8");
+            S3RestServlet.endResponse(response, xml.toString());
+        }
+    }
+
+    public void executePutBucketAcl(HttpServletRequest request, HttpServletResponse response) throws IOException 
+    { 
+        // [A] Determine that there is an applicable bucket which might have an ACL set
+
+        String bucketName = (String) request
+                .getAttribute(S3Constants.BUCKET_ATTR_KEY);
+        SBucketVO bucket = bucketDao.getByName(bucketName);
+        String owner = null;
+        if (null != bucket)
+            owner = bucket.getOwnerCanonicalId();
+        if (null == owner) {
+            logger.error("ACL update failed since " + bucketName
+                    + " does not exist");
+            throw new IOException("ACL update failed");
+        }
+
+        // [B] Obtain the grant request which applies to the acl request string.
+        // This latter is supplied as the value of the x-amz-acl header.
+
+        S3SetBucketAccessControlPolicyRequest engineRequest = new S3SetBucketAccessControlPolicyRequest();
+        S3Grant grantRequest = new S3Grant();
+        S3AccessControlList aclRequest = new S3AccessControlList();
+
+        String aclRequestString = request.getHeader("x-amz-acl");
+        OrderedPair<Integer, Integer> accessControlsForBucketOwner = SAclVO.getCannedAccessControls(aclRequestString, "SBucket");
+        grantRequest.setPermission(accessControlsForBucketOwner.getFirst());
+        grantRequest.setGrantee(accessControlsForBucketOwner.getSecond());
+        grantRequest.setCanonicalUserID(owner);
+        aclRequest.addGrant(grantRequest);
+        engineRequest.setAcl(aclRequest);
+        engineRequest.setBucketName(bucketName);
+
+        // [C] Allow an S3Engine to handle the
+        // S3SetBucketAccessControlPolicyRequest
+        S3Response engineResponse = ServiceProvider.getInstance().getS3Engine()
+                .handleRequest(engineRequest);
+        response.setStatus(engineResponse.getResultCode());
+
+    }
+
+    public void executePutBucketVersioning(HttpServletRequest request, HttpServletResponse response) throws IOException 
+    {
+        String bucketName = (String) request.getAttribute(S3Constants.BUCKET_ATTR_KEY);
+        String versioningStatus = null;
+        Node item = null;
+
+        if (null == bucketName) {
+            logger.error("executePutBucketVersioning - no bucket name given");
+            response.setStatus(400);
+            return;
+        }
+
+        // -> is the XML as defined?
+        try {
+            DocumentBuilder db = dbf.newDocumentBuilder();
+            Document restXML = db.parse(request.getInputStream());
+            NodeList match = S3RestServlet.getElement(restXML,
+                    "http://s3.amazonaws.com/doc/2006-03-01/", "Status");
+            if (0 < match.getLength()) {
+                item = match.item(0);
+                versioningStatus = new String(item.getFirstChild()
+                        .getNodeValue());
+            } else {
+                logger.error("executePutBucketVersioning - cannot find Status tag in XML body");
+                response.setStatus(400);
+                return;
+            }
+        } catch (Exception e) {
+            logger.error(
+                    "executePutBucketVersioning - failed to parse XML due to "
+                            + e.getMessage(), e);
+            response.setStatus(400);
+            return;
+        }
+
+        try {
+            // Irrespective of what the ACLs say only the owner can turn on
+            // versioning on a bucket.
+            // The bucket owner may want to restrict the IP address from which
+            // this can occur.
+
+            SBucketVO sbucket = bucketDao.getByName(bucketName);
+
+            String client = UserContext.current().getCanonicalUserId();
+            if (!client.equals(sbucket.getOwnerCanonicalId()))
+                throw new PermissionDeniedException(
+                        "Access Denied - only the owner can turn on versioing on a bucket");
+
+            S3PolicyContext context = new S3PolicyContext(
+                    PolicyActions.PutBucketVersioning, bucketName);
+            if (PolicyAccess.DENY == S3Engine.verifyPolicy(context)) {
+                response.setStatus(403);
+                return;
+            }
+
+            if (versioningStatus.equalsIgnoreCase("Enabled"))
+                sbucket.setVersioningStatus(1);
+            else if (versioningStatus.equalsIgnoreCase("Suspended"))
+                sbucket.setVersioningStatus(2);
+            else {
+                logger.error("executePutBucketVersioning - unknown state: ["
+                        + versioningStatus + "]");
+                response.setStatus(400);
+                return;
+            }
+            bucketDao.update(sbucket.getId(), sbucket);
+
+        } catch (PermissionDeniedException e) {
+            logger.error(
+                    "executePutBucketVersioning - failed due to "
+                            + e.getMessage(), e);
+            throw e;
+
+        } catch (Exception e) {
+            logger.error(
+                    "executePutBucketVersioning - failed due to "
+                            + e.getMessage(), e);
+            response.setStatus(500);
+            return;
+        }
+        response.setStatus(200);
+    }
+
+    public void executePutBucketLogging(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        // TODO -- Review this in future.  Currently this is a S3 beta feature
+        response.setStatus(501);
+    }
+
+    public void executePutBucketWebsite(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        // TODO -- LoPri - Undertake checks on Put Bucket Website
+        // Tested using configuration <Directory /Users/john1/S3-Mount>\nAllowOverride FileInfo AuthConfig Limit...</Directory> in httpd.conf
+        // 	Need some way of using  AllowOverride to allow use of .htaccess and then pushing .httaccess file to bucket subdirectory of mount point
+        // Currently has noop effect in the sense that a running apachectl process sees the directory contents without further action
+        response.setStatus(200);
+    }
+
+    public void executeDeleteBucket(HttpServletRequest request, HttpServletResponse response) throws IOException 
+    {
+        S3DeleteBucketRequest engineRequest = new S3DeleteBucketRequest();
+        engineRequest.setBucketName((String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY));
+        S3Response engineResponse = ServiceProvider.getInstance().getS3Engine().handleRequest(engineRequest);  
+        response.setStatus(engineResponse.getResultCode());
+        response.flushBuffer();
+    }
+
+    /**
+     * Multipart upload is a complex operation with all the options defined by Amazon.   Part of the functionality is 
+     * provided by the query done against the database.  The CommonPrefixes functionality is done the same way 
+     * as done in the listBucketContents function (i.e., by iterating though the list to decide which output 
+     * element each key is placed).
+     * 
+     * @param request
+     * @param response
+     * @throws IOException
+     */
+    public void executeListMultipartUploads(HttpServletRequest request, HttpServletResponse response) throws IOException 
+    {
+        // [A] Obtain parameters and do basic bucket verification
+        String bucketName = (String) request
+                .getAttribute(S3Constants.BUCKET_ATTR_KEY);
+        String delimiter = request.getParameter("delimiter");
+        String keyMarker = request.getParameter("key-marker");
+        String prefix = request.getParameter("prefix");
+        int maxUploads = 1000;
+        int nextUploadId = 0;
+        String nextKey = null;
+        boolean isTruncated = false;
+        S3MultipartUpload[] uploads = null;
+        S3MultipartUpload onePart = null;
+        String temp = request.getParameter("max-uploads");
+        if (null != temp) {
+            maxUploads = Integer.parseInt(temp);
+            if (maxUploads > 1000 || maxUploads < 0)
+                maxUploads = 1000;
+        }
+
+        // -> upload-id-marker is ignored unless key-marker is also specified
+        String uploadIdMarker = request.getParameter("upload-id-marker");
+        if (null == keyMarker)
+            uploadIdMarker = null;
+
+        // -> does the bucket exist, we may need it to verify access permissions
+        SBucketVO bucket = bucketDao.getByName(bucketName);
+        if (bucket == null) {
+            logger.error("listMultipartUpload failed since " + bucketName
+                    + " does not exist");
+            response.setStatus(404);
+            return;
+        }
+
+        S3PolicyContext context = new S3PolicyContext(
+                PolicyActions.ListBucketMultipartUploads, bucketName);
+        context.setEvalParam(ConditionKeys.Prefix, prefix);
+        context.setEvalParam(ConditionKeys.Delimiter, delimiter);
+        S3Engine.verifyAccess(context, "SBucket", bucket.getId(),
+                SAcl.PERMISSION_READ);
+
+        // [B] Query the multipart table to get the list of current uploads
+        try {
+            MultipartLoadDao uploadDao = new MultipartLoadDao();
+            OrderedPair<S3MultipartUpload[], Boolean> result = uploadDao
+                    .getInitiatedUploads(bucketName, maxUploads, prefix,
+                            keyMarker, uploadIdMarker);
+            uploads = result.getFirst();
+            isTruncated = result.getSecond().booleanValue();
+        } catch (Exception e) {
+            logger.error(
+                    "List Multipart Uploads failed due to " + e.getMessage(), e);
+            response.setStatus(500);
+        }
+
+        StringBuffer xml = new StringBuffer();
+        xml.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
+        xml.append("<ListMultipartUploadsResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">");
+        xml.append("<Bucket>").append(bucketName).append("</Bucket>");
+        xml.append("<KeyMarker>").append((null == keyMarker ? "" : keyMarker))
+        .append("</KeyMarker>");
+        xml.append("<UploadIdMarker>")
+        .append((null == uploadIdMarker ? "" : uploadIdMarker))
+        .append("</UploadIdMarker>");
+
+        // [C] Construct the contents of the <Upload> element
+        StringBuffer partsList = new StringBuffer();
+        for (int i = 0; i < uploads.length; i++) {
+            onePart = uploads[i];
+            if (null == onePart)
+                break;
+
+            if (delimiter != null && !delimiter.isEmpty()) {
+                // -> is this available only in the CommonPrefixes element?
+                if (StringHelper.substringInBetween(onePart.getKey(), prefix,
+                        delimiter) != null)
+                    continue;
+            }
+
+            nextKey = onePart.getKey();
+            nextUploadId = onePart.getId();
+            partsList.append("<Upload>");
+            partsList.append("<Key>").append(nextKey).append("</Key>");
+            partsList.append("<UploadId>").append(nextUploadId)
+            .append("</UploadId>");
+            partsList.append("<Initiator>");
+            partsList.append("<ID>").append(onePart.getAccessKey())
+            .append("</ID>");
+            partsList.append("<DisplayName></DisplayName>");
+            partsList.append("</Initiator>");
+            partsList.append("<Owner>");
+            partsList.append("<ID>").append(onePart.getAccessKey())
+            .append("</ID>");
+            partsList.append("<DisplayName></DisplayName>");
+            partsList.append("</Owner>");
+            partsList.append("<StorageClass>STANDARD</StorageClass>");
+            partsList
+            .append("<Initiated>")
+            .append(DatatypeConverter.printDateTime(onePart
+                    .getLastModified())).append("</Initiated>");
+            partsList.append("</Upload>");
+        }
+
+        // [D] Construct the contents of the <CommonPrefixes> elements (if any)
+        for (int i = 0; i < uploads.length; i++) {
+            onePart = uploads[i];
+            if (null == onePart)
+                break;
+
+            if (delimiter != null && !delimiter.isEmpty()) {
+                String subName = StringHelper.substringInBetween(
+                        onePart.getKey(), prefix, delimiter);
+                if (subName != null) {
+                    partsList.append("<CommonPrefixes>");
+                    partsList.append("<Prefix>");
+                    if (prefix != null && prefix.length() > 0)
+                        partsList.append(prefix + delimiter + subName);
+                    else
+                        partsList.append(subName);
+                    partsList.append("

<TRUNCATED>