edu.ucsb.eucalyptus.cloud.ws.WalrusManager.java Source code

Java tutorial

Introduction

Here is the source code for edu.ucsb.eucalyptus.cloud.ws.WalrusManager.java

Source

/*******************************************************************************
 *Copyright (c) 2009  Eucalyptus Systems, Inc.
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, only version 3 of the License.
 * 
 * 
 *  This file is distributed in the hope that it will be useful, but WITHOUT
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 *  for more details.
 * 
 *  You should have received a copy of the GNU General Public License along
 *  with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 *  Please contact Eucalyptus Systems, Inc., 130 Castilian
 *  Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/>
 *  if you need additional information or have any questions.
 * 
 *  This file may incorporate work covered under the following copyright and
 *  permission notice:
 * 
 *    Software License Agreement (BSD License)
 * 
 *    Copyright (c) 2008, Regents of the University of California
 *    All rights reserved.
 * 
 *    Redistribution and use of this software in source and binary forms, with
 *    or without modification, are permitted provided that the following
 *    conditions are met:
 * 
 *      Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 * 
 *      Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * 
 *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 *    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 *    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 *    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 *    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF
 *    THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE
 *    LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS
 *    SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
 *    IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
 *    BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
 *    THE REGENTS DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
 *    OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
 *    WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
 *    ANY SUCH LICENSES OR RIGHTS.
 *******************************************************************************/
package edu.ucsb.eucalyptus.cloud.ws;

/*
 *
 * Author: Sunil Soman sunils@cs.ucsb.edu
 */

import java.io.*;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.sql.*;
import java.util.*;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import javax.persistence.EntityManager;

import com.eucalyptus.context.SbxRequest;
import com.eucalyptus.ws.util.SbxPayloadLog;
import com.eucalyptus.ws.util.SbxPutJobQueue;
import com.eucalyptus.ws.util.SbxPutRequest;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import edu.ucsb.eucalyptus.cloud.*;

import edu.ucsb.eucalyptus.util.*;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.tools.ant.util.DateUtils;
import org.hibernate.CacheMode;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.jdbc.Work;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.HttpVersion;
import org.mortbay.log.Log;

import com.eucalyptus.auth.NoSuchUserException;
import com.eucalyptus.auth.Users;
import com.eucalyptus.auth.crypto.Digest;
import com.eucalyptus.auth.principal.User;
import com.eucalyptus.auth.util.Hashes;
import com.eucalyptus.bootstrap.Component;
import com.eucalyptus.context.Contexts;
import com.eucalyptus.entities.EntityWrapper;
import com.eucalyptus.util.EucalyptusCloudException;
import com.eucalyptus.util.WalrusProperties;
import com.eucalyptus.ws.client.ServiceDispatcher;
import com.eucalyptus.ws.handlers.WalrusRESTBinding;

import edu.ucsb.eucalyptus.cloud.entities.BucketInfo;
import edu.ucsb.eucalyptus.cloud.entities.GrantInfo;
import edu.ucsb.eucalyptus.cloud.entities.ImageCacheInfo;
import edu.ucsb.eucalyptus.cloud.entities.MetaDataInfo;
import edu.ucsb.eucalyptus.cloud.entities.ObjectInfo;
import edu.ucsb.eucalyptus.cloud.entities.SystemConfiguration;
import edu.ucsb.eucalyptus.cloud.entities.TorrentInfo;
import edu.ucsb.eucalyptus.cloud.entities.WalrusInfo;
import edu.ucsb.eucalyptus.cloud.entities.WalrusSnapshotInfo;
import edu.ucsb.eucalyptus.msgs.AccessControlListType;
import edu.ucsb.eucalyptus.msgs.AccessControlPolicyType;
import edu.ucsb.eucalyptus.msgs.AddObjectResponseType;
import edu.ucsb.eucalyptus.msgs.AddObjectType;
import edu.ucsb.eucalyptus.msgs.BucketListEntry;
import edu.ucsb.eucalyptus.msgs.CanonicalUserType;
import edu.ucsb.eucalyptus.msgs.CopyObjectResponseType;
import edu.ucsb.eucalyptus.msgs.CopyObjectType;
import edu.ucsb.eucalyptus.msgs.CreateBucketResponseType;
import edu.ucsb.eucalyptus.msgs.CreateBucketType;
import edu.ucsb.eucalyptus.msgs.DeleteBucketResponseType;
import edu.ucsb.eucalyptus.msgs.DeleteBucketType;
import edu.ucsb.eucalyptus.msgs.DeleteMarkerEntry;
import edu.ucsb.eucalyptus.msgs.DeleteObjectResponseType;
import edu.ucsb.eucalyptus.msgs.DeleteObjectType;
import edu.ucsb.eucalyptus.msgs.DeleteVersionResponseType;
import edu.ucsb.eucalyptus.msgs.DeleteVersionType;
import edu.ucsb.eucalyptus.msgs.GetBucketAccessControlPolicyResponseType;
import edu.ucsb.eucalyptus.msgs.GetBucketAccessControlPolicyType;
import edu.ucsb.eucalyptus.msgs.GetBucketLocationResponseType;
import edu.ucsb.eucalyptus.msgs.GetBucketLocationType;
import edu.ucsb.eucalyptus.msgs.GetBucketLoggingStatusResponseType;
import edu.ucsb.eucalyptus.msgs.GetBucketLoggingStatusType;
import edu.ucsb.eucalyptus.msgs.GetBucketVersioningStatusResponseType;
import edu.ucsb.eucalyptus.msgs.GetBucketVersioningStatusType;
import edu.ucsb.eucalyptus.msgs.GetObjectAccessControlPolicyResponseType;
import edu.ucsb.eucalyptus.msgs.GetObjectAccessControlPolicyType;
import edu.ucsb.eucalyptus.msgs.GetObjectExtendedResponseType;
import edu.ucsb.eucalyptus.msgs.GetObjectExtendedType;
import edu.ucsb.eucalyptus.msgs.GetObjectResponseType;
import edu.ucsb.eucalyptus.msgs.GetObjectType;
import edu.ucsb.eucalyptus.msgs.Grant;
import edu.ucsb.eucalyptus.msgs.Grantee;
import edu.ucsb.eucalyptus.msgs.Group;
import edu.ucsb.eucalyptus.msgs.ListAllMyBucketsList;
import edu.ucsb.eucalyptus.msgs.ListAllMyBucketsResponseType;
import edu.ucsb.eucalyptus.msgs.ListAllMyBucketsType;
import edu.ucsb.eucalyptus.msgs.ListBucketResponseType;
import edu.ucsb.eucalyptus.msgs.ListBucketType;
import edu.ucsb.eucalyptus.msgs.ListEntry;
import edu.ucsb.eucalyptus.msgs.ListVersionsResponseType;
import edu.ucsb.eucalyptus.msgs.ListVersionsType;
import edu.ucsb.eucalyptus.msgs.LoggingEnabled;
import edu.ucsb.eucalyptus.msgs.MetaDataEntry;
import edu.ucsb.eucalyptus.msgs.PostObjectResponseType;
import edu.ucsb.eucalyptus.msgs.PostObjectType;
import edu.ucsb.eucalyptus.msgs.PrefixEntry;
import edu.ucsb.eucalyptus.msgs.PutObjectInlineResponseType;
import edu.ucsb.eucalyptus.msgs.PutObjectInlineType;
import edu.ucsb.eucalyptus.msgs.PutObjectResponseType;
import edu.ucsb.eucalyptus.msgs.PutObjectType;
import edu.ucsb.eucalyptus.msgs.RemoveARecordType;
import edu.ucsb.eucalyptus.msgs.SetBucketAccessControlPolicyResponseType;
import edu.ucsb.eucalyptus.msgs.SetBucketAccessControlPolicyType;
import edu.ucsb.eucalyptus.msgs.SetBucketLoggingStatusResponseType;
import edu.ucsb.eucalyptus.msgs.SetBucketLoggingStatusType;
import edu.ucsb.eucalyptus.msgs.SetBucketVersioningStatusResponseType;
import edu.ucsb.eucalyptus.msgs.SetBucketVersioningStatusType;
import edu.ucsb.eucalyptus.msgs.SetObjectAccessControlPolicyResponseType;
import edu.ucsb.eucalyptus.msgs.SetObjectAccessControlPolicyType;
import edu.ucsb.eucalyptus.msgs.SetRESTBucketAccessControlPolicyResponseType;
import edu.ucsb.eucalyptus.msgs.SetRESTBucketAccessControlPolicyType;
import edu.ucsb.eucalyptus.msgs.SetRESTObjectAccessControlPolicyResponseType;
import edu.ucsb.eucalyptus.msgs.SetRESTObjectAccessControlPolicyType;
import edu.ucsb.eucalyptus.msgs.Status;
import edu.ucsb.eucalyptus.msgs.TargetGrants;
import edu.ucsb.eucalyptus.msgs.UpdateARecordType;
import edu.ucsb.eucalyptus.msgs.VersionEntry;
import edu.ucsb.eucalyptus.storage.StorageManager;
import edu.ucsb.eucalyptus.storage.fs.FileIO;

public class WalrusManager {
    private static Logger LOG = Logger.getLogger(WalrusManager.class);

    private StorageManager storageManager;
    private WalrusImageManager walrusImageManager;
    private static WalrusStatistics walrusStatistics = null;

    private static String strSBXContentTypeFolder = "application/x-directory";

    private long getSyncId(String eventType, String account) throws EucalyptusCloudException {
        long syncid = -1;

        if (eventType == null)
            throw new AccessDeniedException("GetSyncIdError", account + ": no client type", true);

        if ("webApp".equals(eventType)) {
            syncid = 0;
        } else if ("mobileApp".equals(eventType)) {
            syncid = 0;
        } else {
            syncid = Long.valueOf(eventType);
            if (syncid <= 0)
                throw new AccessDeniedException("GetSyncIdError", account + ": error syncid=" + syncid + "(<=0)",
                        true);
        }
        return syncid;
    }

    private void writeEvent(EntityManager em, final String eventType, final String account, final String opt,
            final String object_key, final Long size, final Boolean isFolder, final long syncid,
            final long lastModified, final String reqid, final int objseq) throws EucalyptusCloudException {

        Session sess = null;
        try {
            sess = ((Session) em.getDelegate());
        } catch (Throwable t) {
            sess = null;
        }

        final java.sql.Timestamp mtime = new java.sql.Timestamp(lastModified);

        if ("webApp".equals(eventType)) {
            final String sql = "insert into web_opt_log(id,rectime,time,cssact,op,fpth,fsz,file_version,syncid,isfolder,rslt,inst_id, reqid) values(DEFAULT,CURRENT_TIMESTAMP AT TIME ZONE 'UTC +0',?,?,?,?,?,?,NULL,?,'succ','dummy',?)";
            if (sess != null) {
                sess.doWork(new Work() {
                    public void execute(Connection connection) throws SQLException {
                        PreparedStatement stmt = null;
                        try {
                            stmt = connection.prepareStatement(sql);
                            stmt.setTimestamp(1, mtime);
                            stmt.setString(2, account);
                            stmt.setString(3, opt);
                            stmt.setString(4, object_key);
                            stmt.setLong(5, size);
                            stmt.setInt(6, objseq);
                            stmt.setBoolean(7, isFolder);
                            stmt.setString(8, reqid);
                            stmt.executeUpdate();
                        } finally {
                            if (stmt != null)
                                stmt.close();
                        }
                    }
                });
            } else {
                em.createNativeQuery(sql).setParameter(1, mtime).setParameter(2, account).setParameter(3, opt)
                        .setParameter(4, object_key).setParameter(5, size).setParameter(6, objseq)
                        .setParameter(7, isFolder).setParameter(8, reqid).executeUpdate();
            }
        } else if ("mobileApp".equals(eventType)) {
        } else {
            final String sql = "insert into opt_log(id,rectime,time,cssact,op,fpth,fsz,file_version,syncid,isfolder,rslt,inst_id, reqid) values(DEFAULT,CURRENT_TIMESTAMP AT TIME ZONE 'UTC +0',?,?,?,?,?,?,?,?,'succ','dummy',?)";
            if (sess != null) {
                sess.doWork(new Work() {
                    public void execute(Connection connection) throws SQLException {
                        PreparedStatement stmt = null;
                        try {
                            stmt = connection.prepareStatement(sql);
                            stmt.setTimestamp(1, mtime);
                            stmt.setString(2, account);
                            stmt.setString(3, opt);
                            stmt.setString(4, object_key);
                            stmt.setLong(5, size);
                            stmt.setInt(6, objseq);
                            stmt.setLong(7, syncid);
                            stmt.setBoolean(8, isFolder);
                            stmt.setString(9, reqid);
                            stmt.executeUpdate();
                        } finally {
                            if (stmt != null)
                                stmt.close();
                        }

                    }
                }

                );
            } else {
                em.createNativeQuery(sql).setParameter(1, mtime).setParameter(2, account).setParameter(3, opt)
                        .setParameter(4, object_key).setParameter(5, size).setParameter(6, objseq)
                        .setParameter(7, syncid).setParameter(8, isFolder).setParameter(9, reqid).executeUpdate();
            }
        }
    }

    private void writeRenameEvent(EntityManager em, final String eventType, final String account,
            final String bucketName, final String object_key, final String renameTo, final long syncid,
            final String reqid, final int objseq) throws EucalyptusCloudException {

        Session sess = null;
        try {
            sess = ((Session) em.getDelegate());
        } catch (Throwable t) {
            sess = null;
        }

        if ("webApp".equals(eventType)) {
            final String sql = "insert into web_opt_log(rectime,time,cssact,op,fpth,fsz,file_version,syncid,isfolder,rslt,inst_id,reqid)"
                    + "select ?,to_timestamp(coalesce(value::bigint,0)/1000),?,'Rename',?,size,?,?,content_type='application/x-directory','succ','dummy',? from objects "
                    + "obj left join metadata mtd on obj.object_name=mtd.object_id and mtd.\"name\"='mtime' "
                    + "where object_key = ? AND bucket_name = ? AND owner_id = ? limit 1";

            if (sess != null) {
                sess.doWork(new Work() {
                    public void execute(Connection connection) throws SQLException {
                        PreparedStatement stmt = null;
                        try {
                            stmt = connection.prepareStatement(sql);
                            Calendar c = Calendar.getInstance();
                            stmt.setTimestamp(1,
                                    new Timestamp(c.getTimeInMillis() - c.getTimeZone().getRawOffset()));
                            stmt.setString(2, account);
                            stmt.setString(3, object_key + "||" + renameTo);
                            stmt.setInt(4, objseq);
                            stmt.setLong(5, syncid);
                            stmt.setString(6, reqid);
                            stmt.setString(7, renameTo);
                            stmt.setString(8, bucketName);
                            stmt.setString(9, account);
                            stmt.executeUpdate();
                        } finally {
                            try {
                                if (stmt != null)
                                    stmt.close();
                            } catch (Throwable t) {
                                /*NOP*/}
                        }
                    }
                });
            } else {
                Calendar c = Calendar.getInstance();
                em.createNativeQuery(sql)
                        .setParameter(1, new Timestamp(c.getTimeInMillis() - c.getTimeZone().getRawOffset()))
                        .setParameter(2, account).setParameter(3, object_key + "||" + renameTo)
                        .setParameter(4, objseq).setParameter(5, syncid).setParameter(6, reqid)
                        .setParameter(7, renameTo).setParameter(8, bucketName).setParameter(9, account)
                        .executeUpdate();
            }

        } else if ("mobileApp".equals(eventType)) {
        } else {

            final String sql = "insert into opt_log(rectime,time,cssact,op,fpth,fsz,file_version,syncid,isfolder,rslt,inst_id,reqid) "
                    + "select ?,to_timestamp(coalesce(value::bigint,0)/1000),?,'Rename',?,size,?,?,content_type='application/x-directory','succ','dummy',? from objects "
                    + "obj left join metadata mtd on obj.object_name=mtd.object_id and mtd.\"name\"='mtime' "
                    + "where object_key = ? AND bucket_name = ? AND owner_id = ? limit 1";

            if (sess != null) {
                sess.doWork(new Work() {
                    public void execute(Connection connection) throws SQLException {
                        PreparedStatement stmt = null;
                        try {
                            stmt = connection.prepareStatement(sql);
                            Calendar c = Calendar.getInstance();
                            stmt.setTimestamp(1,
                                    new Timestamp(c.getTimeInMillis() - c.getTimeZone().getRawOffset()));
                            stmt.setString(2, account);
                            stmt.setString(3, object_key + "||" + renameTo);
                            stmt.setInt(4, objseq);
                            stmt.setLong(5, syncid);
                            stmt.setString(6, reqid);
                            stmt.setString(7, renameTo);
                            stmt.setString(8, bucketName);
                            stmt.setString(9, account);
                            stmt.executeUpdate();
                        } finally {
                            try {
                                if (stmt != null)
                                    stmt.close();
                            } catch (Throwable t) {
                                /*NOP*/}
                        }
                    }
                });
            } else {
                Calendar c = Calendar.getInstance();
                em.createNativeQuery(sql)
                        .setParameter(1, new Timestamp(c.getTimeInMillis() - c.getTimeZone().getRawOffset()))
                        .setParameter(2, account).setParameter(3, object_key + "||" + renameTo)
                        .setParameter(4, objseq).setParameter(5, syncid).setParameter(6, reqid)
                        .setParameter(7, renameTo).setParameter(8, bucketName).setParameter(9, account)
                        .executeUpdate();
            }
        }
    }

    private void doRenameEvent(EntityManager em, final String account, final String bucketName,
            final String object_key, final String renameTo) throws EucalyptusCloudException {

        Session sess = null;
        try {
            sess = ((Session) em.getDelegate());
        } catch (Throwable t) {
            sess = null;
        }

        final String sql = "UPDATE objects SET object_key=regexp_replace(object_key, ?, ?, 'q') "
                + "where bucket_name = ? and owner_id = ? and (object_key LIKE ? or object_key = ?)";

        final String like_key = object_key.replaceAll("%", "\\%").replaceAll("_", "\\_");
        if (sess != null) {
            sess.doWork(new Work() {
                public void execute(Connection connection) throws SQLException {
                    PreparedStatement stmt = null;
                    try {
                        stmt = connection.prepareStatement(sql);
                        stmt.setString(1, object_key);
                        stmt.setString(2, renameTo);
                        stmt.setString(3, bucketName);
                        stmt.setString(4, account);
                        //stmt.setString(5, "^" + object_key + "/");
                        stmt.setString(5, like_key + "/%");
                        stmt.setString(6, object_key);
                        int exR = stmt.executeUpdate();
                        if (exR == 0) {
                            throw new SQLException("CssError", account + ":" + bucketName + ":" + object_key + "***"
                                    + "no objects are renamed");
                        }
                    } finally {
                        try {
                            if (stmt != null)
                                stmt.close();
                        } catch (Throwable t) {
                            /*NOP*/}
                    }
                }
            });
        } else {
            int exR = em.createNativeQuery(sql).setParameter(1, object_key).setParameter(2, renameTo)
                    .setParameter(3, bucketName).setParameter(4, account)
                    //.setParameter(5, "^" + object_key + "/")
                    .setParameter(5, like_key + "/%").setParameter(6, object_key).executeUpdate();
            if (exR == 0) {
                throw new AccessDeniedException("CssError",
                        account + ":" + bucketName + ":" + object_key + "***" + "no objects are renamed", true);
            }
        }
    }

    public static void callWalrusHeartBeat(String account, String instid, String API) throws Throwable {
        HttpClient client = null;
        HttpMethod method = null;
        NameValuePair[] queryString = null;
        if (account == null || instid == null) {
            LOG.debug(API + ":callWalrusHeartBeat error: #account=" + account + "#instid=" + instid + "#");
            return;
        }
        try {
            client = new HttpClient();
            String URL = "http://127.0.0.1/sbx_svr/rest/EBS/walrusheartbeat";
            queryString = new NameValuePair[] { new NameValuePair("account", account),
                    new NameValuePair("instanceid", instid) };
            method = new PostMethod(URL);
            method.addRequestHeader(new Header("Connection", "close"));
            method.setQueryString(queryString);
            int statusCode = client.executeMethod(method);
            if (statusCode == HttpStatus.SC_OK) {
                // Read the response body.
                StringBuffer stb = new StringBuffer();
                InputStream ins = method.getResponseBodyAsStream();
                InputStreamReader insReader = new InputStreamReader(ins);
                BufferedReader br = new BufferedReader(insReader);
                String buffText = br.readLine();
                while (null != buffText) {
                    stb.append(buffText);
                    buffText = br.readLine();
                }
                if (stb.length() == 0 || StringUtils.isEmpty(stb.toString())) {
                    LOG.debug(API + ":callWalrusHeartBeat: Http Response Body is empty!");
                }
            } else {
                LOG.debug(API + ":callWalrusHeartBeat: Http Response Error:" + statusCode + "#account=" + account
                        + "#instid=" + instid);
            }
        } catch (Throwable t) {
            LOG.debug(API + ":callWalrusHeartBeat: Http Response Error: #account=" + account + "#instid=" + instid
                    + "#" + t.toString());
            throw t;
        } finally {
            try {
                if (method != null)
                    method.releaseConnection();
            } catch (Throwable t) {
                /*NOP*/}
            ;
        }
    }

    public static void configure() {
        walrusStatistics = new WalrusStatistics();
    }

    public WalrusManager(StorageManager storageManager, WalrusImageManager walrusImageManager) {
        this.storageManager = storageManager;
        this.walrusImageManager = walrusImageManager;
    }

    public void initialize() throws EucalyptusCloudException {
        check();
    }

    public void check() throws EucalyptusCloudException {
        File bukkitDir = new File(WalrusInfo.getWalrusInfo().getStorageDir());
        if (!bukkitDir.exists()) {
            if (!bukkitDir.mkdirs()) {
                LOG.fatal("Unable to make bucket root directory: " + WalrusInfo.getWalrusInfo().getStorageDir());
                throw new EucalyptusCloudException("Invalid bucket root directory");
            }
        } else if (!bukkitDir.canWrite()) {
            LOG.fatal("Cannot write to bucket root directory: " + WalrusInfo.getWalrusInfo().getStorageDir());
            throw new EucalyptusCloudException("Invalid bucket root directory");
        }
        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo = new BucketInfo();
        List<BucketInfo> bucketInfos = db.query(bucketInfo);
        for (BucketInfo bucket : bucketInfos) {
            if (!storageManager.bucketExists(bucket.getBucketName()))
                bucket.setHidden(true);
            else
                bucket.setHidden(false);
        }
        db.commit();
    }

    static Cache<String, ArrayList<BucketListEntry>> cache_buckets = CacheBuilder.newBuilder().maximumSize(1000)
            .build();
    static Cache<String, CanonicalUserType> cache_owner = CacheBuilder.newBuilder().maximumSize(1000).build();

    public ListAllMyBucketsResponseType listAllMyBuckets(ListAllMyBucketsType request)
            throws EucalyptusCloudException {
        ListAllMyBucketsResponseType reply = (ListAllMyBucketsResponseType) request.getReply();
        String userId = request.getUserId();

        if (userId == null) {
            throw new AccessDeniedException("no such user");
        }

        ArrayList<BucketListEntry> buckets = null;
        CanonicalUserType owner = null;

        // cache
        boolean bCache = false;
        String key_buckets = userId + "_buckets";
        String key_owner = userId + "_owner";
        if (Contexts.SBXSVR) {
            try {
                buckets = cache_buckets.getIfPresent(key_buckets);
            } catch (Throwable t) {
                LOG.error("Cache error: " + t);
            }
            try {
                owner = cache_owner.getIfPresent(key_owner);
            } catch (Throwable t) {
                LOG.error("Cache error: " + t);
            }

            if (buckets == null) {
                EntityWrapper<BucketInfo> db = null;
                try {
                    db = WalrusControl.getEntityWrapper();
                    BucketInfo searchBucket = new BucketInfo();
                    searchBucket.setOwnerId(userId);
                    searchBucket.setHidden(false);
                    List<BucketInfo> bucketInfoList = db.query(searchBucket);

                    buckets = new ArrayList<BucketListEntry>();
                    for (BucketInfo bucketInfo : bucketInfoList) {
                        if (request.isAdministrator()) {
                            EntityWrapper<WalrusSnapshotInfo> dbSnap = db.recast(WalrusSnapshotInfo.class);
                            WalrusSnapshotInfo walrusSnapInfo = new WalrusSnapshotInfo();
                            walrusSnapInfo.setSnapshotBucket(bucketInfo.getBucketName());
                            List<WalrusSnapshotInfo> walrusSnaps = dbSnap.query(walrusSnapInfo);
                            if (walrusSnaps.size() > 0)
                                continue;
                        }
                        buckets.add(new BucketListEntry(bucketInfo.getBucketName(),
                                DateUtils.format(bucketInfo.getCreationDate().getTime(),
                                        DateUtils.ISO8601_DATETIME_PATTERN) + ".000Z"));
                    }
                    db.commit();
                } catch (Throwable t) {
                    if (db != null)
                        db.rollback();
                    throw new AccessDeniedException("CssError", userId + "***" + t.toString(), true);
                }
                try {
                    if (buckets.size() > 0)
                        cache_buckets.put(key_buckets, buckets);
                } catch (Throwable t) {
                    LOG.error("Cache error: " + t);
                }
            }

            if (owner == null) {
                try {
                    owner = new CanonicalUserType(Users.lookupUser(userId).getQueryId(), userId);
                } catch (Exception ex) {
                    throw new AccessDeniedException("User: " + userId + " not found");
                } catch (Throwable t) {
                    throw new AccessDeniedException("CssError", userId + "***" + t.toString(), true);
                }
                try {
                    cache_owner.put(key_owner, owner);
                } catch (Throwable t) {
                    LOG.error("Cache error: " + t);
                }
            }

            try {
                ListAllMyBucketsList bucketList = new ListAllMyBucketsList();
                reply.setOwner(owner);
                bucketList.setBuckets(buckets);
                reply.setBucketList(bucketList);
            } catch (Throwable t) {
                throw new AccessDeniedException("CssError", userId + "***" + t.toString(), true);
            }
            return reply;
        }

        try {
            EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
            BucketInfo searchBucket = new BucketInfo();
            searchBucket.setOwnerId(userId);
            searchBucket.setHidden(false);
            List<BucketInfo> bucketInfoList = db.query(searchBucket);

            buckets = new ArrayList<BucketListEntry>();
            for (BucketInfo bucketInfo : bucketInfoList) {
                if (request.isAdministrator()) {
                    EntityWrapper<WalrusSnapshotInfo> dbSnap = db.recast(WalrusSnapshotInfo.class);
                    WalrusSnapshotInfo walrusSnapInfo = new WalrusSnapshotInfo();
                    walrusSnapInfo.setSnapshotBucket(bucketInfo.getBucketName());
                    List<WalrusSnapshotInfo> walrusSnaps = dbSnap.query(walrusSnapInfo);
                    if (walrusSnaps.size() > 0)
                        continue;
                }
                buckets.add(new BucketListEntry(bucketInfo.getBucketName(),
                        DateUtils.format(bucketInfo.getCreationDate().getTime(), DateUtils.ISO8601_DATETIME_PATTERN)
                                + ".000Z"));
            }
            try {
                owner = new CanonicalUserType(Users.lookupUser(userId).getQueryId(), userId);

                ListAllMyBucketsList bucketList = new ListAllMyBucketsList();
                reply.setOwner(owner);
                bucketList.setBuckets(buckets);
                reply.setBucketList(bucketList);
            } catch (Exception ex) {
                db.rollback();
                LOG.error(ex);
                throw new AccessDeniedException("User: " + userId + " not found");
            }
            db.commit();
        } catch (AccessDeniedException e) {
            throw e;
        } catch (Throwable t) {
            throw new AccessDeniedException("CssError", userId + "***" + t.toString(), true);
        }
        return reply;
    }

    public CreateBucketResponseType createBucket(CreateBucketType request) throws EucalyptusCloudException {
        CreateBucketResponseType reply = (CreateBucketResponseType) request.getReply();
        String userId = request.getUserId();

        String bucketName = request.getBucket();
        String locationConstraint = request.getLocationConstraint();

        if (userId == null) {
            throw new AccessDeniedException("Bucket", bucketName);
        }

        if (Contexts.SBXSVR) {
            if (bucketName.equals("bkt-")) {
                throw new InvalidBucketNameException(bucketName);
            }
        }

        AccessControlListType accessControlList = request.getAccessControlList();
        if (accessControlList == null) {
            accessControlList = new AccessControlListType();
        }

        if (!checkBucketName(bucketName))
            throw new InvalidBucketNameException(bucketName);

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();

        if (WalrusProperties.shouldEnforceUsageLimits && !request.isAdministrator()) {
            BucketInfo searchBucket = new BucketInfo();
            searchBucket.setOwnerId(userId);
            List<BucketInfo> bucketList = db.query(searchBucket);
            if (bucketList.size() >= WalrusInfo.getWalrusInfo().getStorageMaxBucketsPerUser()) {
                db.rollback();
                throw new TooManyBucketsException(bucketName);
            }
        }

        BucketInfo bucketInfo = new BucketInfo(bucketName);
        List<BucketInfo> bucketList = db.query(bucketInfo);

        if (bucketList.size() > 0) {
            if (bucketList.get(0).getOwnerId().equals(userId)) {
                // bucket already exists and you created it
                db.rollback();
                throw new BucketAlreadyOwnedByYouException(bucketName);
            }
            // bucket already exists
            db.rollback();
            throw new BucketAlreadyExistsException(bucketName);
        } else {
            // create bucket and set its acl
            BucketInfo bucket = new BucketInfo(userId, bucketName, new Date());
            ArrayList<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
            bucket.addGrants(userId, grantInfos, accessControlList);
            bucket.setGrants(grantInfos);
            bucket.setBucketSize(0L);
            bucket.setLoggingEnabled(false);
            bucket.setVersioning(WalrusProperties.VersioningStatus.Disabled.toString());
            bucket.setHidden(false);
            if (locationConstraint != null)
                bucket.setLocation(locationConstraint);
            else
                bucket.setLocation("US");
            db.add(bucket);
            // call the storage manager to save the bucket to disk
            try {
                storageManager.createBucket(bucketName);
                if (WalrusProperties.trackUsageStatistics)
                    walrusStatistics.incrementBucketCount();
            } catch (IOException ex) {
                LOG.error(ex);
                db.rollback();
                throw new AccessDeniedException("Unable to create bucket: " + bucketName);
            }
        }
        db.commit();

        if (WalrusProperties.enableVirtualHosting) {
            if (checkDNSNaming(bucketName)) {
                UpdateARecordType updateARecord = new UpdateARecordType();
                updateARecord.setUserId(userId);
                URI walrusUri;
                String address = null;
                try {
                    walrusUri = new URI(SystemConfiguration.getWalrusUrl());
                    address = walrusUri.getHost();
                } catch (URISyntaxException e) {
                    throw new AccessDeniedException("Could not get Walrus URL");
                }
                String zone = WalrusProperties.WALRUS_SUBDOMAIN + ".";
                updateARecord.setAddress(address);
                updateARecord.setName(bucketName + "." + zone);
                updateARecord.setTtl(604800);
                updateARecord.setZone(zone);
                try {
                    ServiceDispatcher.lookupSingle(Component.dns).send(updateARecord);
                    LOG.info("Mapping " + updateARecord.getName() + " to " + address);
                } catch (Exception ex) {
                    LOG.error("Could not update DNS record", ex);
                }
            } else {
                LOG.error(
                        "Bucket: " + bucketName + " fails to meet DNS requirements. Unable to create DNS mapping.");
            }
        }

        reply.setBucket(bucketName);
        return reply;
    }

    private boolean checkBucketName(String bucketName) {
        if (!(bucketName.matches("^[A-Za-z0-9].*") || bucketName.contains(".") || bucketName.contains("-")))
            return false;
        if (bucketName.length() < 3 || bucketName.length() > 255)
            return false;
        String[] addrParts = bucketName.split("\\.");
        boolean ipFormat = true;
        if (addrParts.length == 4) {
            for (String addrPart : addrParts) {
                try {
                    Integer.parseInt(addrPart);
                } catch (NumberFormatException ex) {
                    ipFormat = false;
                    break;
                }
            }
        } else {
            ipFormat = false;
        }
        if (ipFormat)
            return false;
        return true;
    }

    private boolean checkDNSNaming(String bucketName) {
        if (bucketName.contains("_"))
            return false;
        if (bucketName.length() < 3 || bucketName.length() > 63)
            return false;
        if (bucketName.endsWith("-"))
            return false;
        if (bucketName.contains("-.") || bucketName.contains(".-"))
            return false;
        return true;
    }

    public DeleteBucketResponseType deleteBucket(DeleteBucketType request) throws EucalyptusCloudException {
        DeleteBucketResponseType reply = (DeleteBucketResponseType) request.getReply();
        String bucketName = request.getBucket();
        String userId = request.getUserId();
        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo searchBucket = new BucketInfo(bucketName);
        List<BucketInfo> bucketList = db.query(searchBucket);

        if (bucketList.size() > 0) {
            BucketInfo bucketFound = bucketList.get(0);
            BucketLogData logData = bucketFound.getLoggingEnabled() ? request.getLogData() : null;
            if (bucketFound.canWrite(userId)) {
                EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
                ObjectInfo searchObject = new ObjectInfo();
                searchObject.setBucketName(bucketName);
                searchObject.setDeleted(false);
                List<ObjectInfo> objectInfos = dbObject.query(searchObject);
                if (objectInfos.size() == 0) {
                    // check if the bucket contains any images
                    EntityWrapper<ImageCacheInfo> dbIC = db.recast(ImageCacheInfo.class);
                    ImageCacheInfo searchImageCacheInfo = new ImageCacheInfo();
                    searchImageCacheInfo.setBucketName(bucketName);
                    List<ImageCacheInfo> foundImageCacheInfos = dbIC.query(searchImageCacheInfo);

                    if (foundImageCacheInfos.size() > 0) {
                        db.rollback();
                        throw new BucketNotEmptyException(bucketName, logData);
                    }
                    // remove any delete markers
                    ObjectInfo searchDeleteMarker = new ObjectInfo();
                    searchDeleteMarker.setBucketName(bucketName);
                    searchDeleteMarker.setDeleted(true);
                    List<ObjectInfo> deleteMarkers = dbObject.query(searchDeleteMarker);
                    for (ObjectInfo deleteMarker : deleteMarkers) {
                        dbObject.delete(deleteMarker);
                    }
                    db.delete(bucketFound);
                    // Actually remove the bucket from the backing store
                    try {
                        storageManager.deleteBucket(bucketName);
                        if (WalrusProperties.trackUsageStatistics)
                            walrusStatistics.decrementBucketCount();
                    } catch (IOException ex) {
                        // set exception code in reply
                        LOG.error(ex);
                    }

                    if (WalrusProperties.enableVirtualHosting) {
                        URI walrusUri;
                        String address;
                        RemoveARecordType removeARecordType = new RemoveARecordType();
                        removeARecordType.setUserId(userId);
                        String zone = WalrusProperties.WALRUS_SUBDOMAIN + ".";
                        removeARecordType.setName(bucketName + "." + zone);
                        removeARecordType.setZone(zone);
                        try {
                            walrusUri = new URI(SystemConfiguration.getWalrusUrl());
                            address = walrusUri.getHost();
                        } catch (URISyntaxException e) {
                            db.rollback();
                            throw new AccessDeniedException("Could not get Walrus URL");
                        }
                        removeARecordType.setAddress(address);
                        try {
                            ServiceDispatcher.lookupSingle(Component.dns).send(removeARecordType);
                            LOG.info("Removing mapping for " + removeARecordType.getName());
                        } catch (Exception ex) {
                            LOG.error("Could not update DNS record", ex);
                        }
                    }

                    Status status = new Status();
                    status.setCode(204);
                    status.setDescription("No Content");
                    reply.setStatus(status);
                    if (logData != null) {
                        updateLogData(bucketFound, logData);
                        reply.setLogData(logData);
                    }
                } else {
                    db.rollback();
                    throw new BucketNotEmptyException(bucketName, logData);
                }
            } else {
                db.rollback();
                throw new AccessDeniedException("Bucket", bucketName, logData);
            }
        } else {
            db.rollback();
            throw new NoSuchBucketException(bucketName);
        }
        db.commit();
        return reply;
    }

    public GetBucketAccessControlPolicyResponseType getBucketAccessControlPolicy(
            GetBucketAccessControlPolicyType request) throws EucalyptusCloudException {
        GetBucketAccessControlPolicyResponseType reply = (GetBucketAccessControlPolicyResponseType) request
                .getReply();

        String bucketName = request.getBucket();
        String userId = request.getUserId();
        String ownerId = null;

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo = new BucketInfo(bucketName);
        List<BucketInfo> bucketList = db.query(bucketInfo);

        AccessControlListType accessControlList = new AccessControlListType();
        BucketLogData logData;

        if (bucketList.size() > 0) {
            // construct access control policy from grant infos
            BucketInfo bucket = bucketList.get(0);
            logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
            List<GrantInfo> grantInfos = bucket.getGrants();
            if (bucket.canReadACP(userId)) {
                if (logData != null) {
                    updateLogData(bucket, logData);
                    reply.setLogData(logData);
                }
                ownerId = bucket.getOwnerId();
                ArrayList<Grant> grants = new ArrayList<Grant>();
                bucket.readPermissions(grants);
                for (GrantInfo grantInfo : grantInfos) {
                    String uId = grantInfo.getUserId();
                    try {
                        if (uId != null) {
                            User grantUserInfo = Users.lookupUser(uId);
                            addPermission(grants, grantUserInfo, grantInfo);
                        } else {
                            addPermission(grants, grantInfo);
                        }
                    } catch (NoSuchUserException e) {
                        db.rollback();
                        throw new AccessDeniedException("Bucket", bucketName, logData);
                    }
                }
                accessControlList.setGrants(grants);
            }
        } else {
            db.rollback();
            throw new NoSuchBucketException(bucketName);
        }

        AccessControlPolicyType accessControlPolicy = new AccessControlPolicyType();
        try {
            User ownerUserInfo = Users.lookupUser(ownerId);
            accessControlPolicy
                    .setOwner(new CanonicalUserType(ownerUserInfo.getQueryId(), ownerUserInfo.getName()));
            accessControlPolicy.setAccessControlList(accessControlList);
        } catch (NoSuchUserException e) {
            db.rollback();
            throw new AccessDeniedException("Bucket", bucketName, logData);
        }
        reply.setAccessControlPolicy(accessControlPolicy);
        db.commit();
        return reply;
    }

    private static void addPermission(ArrayList<Grant> grants, User userInfo, GrantInfo grantInfo) {
        CanonicalUserType user = new CanonicalUserType(userInfo.getQueryId(), userInfo.getName());

        if (grantInfo.canRead() && grantInfo.canWrite() && grantInfo.canReadACP() && grantInfo.isWriteACP()) {
            grants.add(new Grant(new Grantee(user), "FULL_CONTROL"));
            return;
        }

        if (grantInfo.canRead()) {
            grants.add(new Grant(new Grantee(user), "READ"));
        }

        if (grantInfo.canWrite()) {
            grants.add(new Grant(new Grantee(user), "WRITE"));
        }

        if (grantInfo.canReadACP()) {
            grants.add(new Grant(new Grantee(user), "READ_ACP"));
        }

        if (grantInfo.isWriteACP()) {
            grants.add(new Grant(new Grantee(user), "WRITE_ACP"));
        }
    }

    private static void addPermission(ArrayList<Grant> grants, GrantInfo grantInfo) {
        if (grantInfo.getGrantGroup() != null) {
            Group group = new Group(grantInfo.getGrantGroup());

            if (grantInfo.canRead() && grantInfo.canWrite() && grantInfo.canReadACP() && grantInfo.isWriteACP()) {
                grants.add(new Grant(new Grantee(group), "FULL_CONTROL"));
                return;
            }

            if (grantInfo.canRead()) {
                grants.add(new Grant(new Grantee(group), "READ"));
            }

            if (grantInfo.canWrite()) {
                grants.add(new Grant(new Grantee(group), "WRITE"));
            }

            if (grantInfo.canReadACP()) {
                grants.add(new Grant(new Grantee(group), "READ_ACP"));
            }

            if (grantInfo.isWriteACP()) {
                grants.add(new Grant(new Grantee(group), "WRITE_ACP"));
            }
        }
    }

    protected PutObjectResponseType renameObject(PutObjectType request, SbxRequest r) throws WalrusException {
        PutObjectResponseType reply = (PutObjectResponseType) request.getReply();

        String userId = request.getUserId(), bucketName = request.getBucket(), objectKey = request.getKey(),
                renameTo = request.getRenameto(), account = request.getAccount(),
                instanceId = request.getInstanceid();

        if (Contexts.SBXSVR) {
            try {
                String myaccount = userId;
                String myinstid = instanceId;
                WalrusControl.walrusManager.callWalrusHeartBeat(myaccount, myinstid, "RENAMEOBJECT");
            } catch (Throwable t) {
                Log.debug("CSS callWalrusHeartBeat error (renameObject) " + "***" + t.toString());
            }
        }

        long syncid = -1;
        if (Contexts.SBXSVR) {
            // mac: get sync id before putObject
            try {
                syncid = this.getSyncId(request.getMetaClientType(), userId);
                // syncid must LOCK (syncid == 0 for mobile and browser)
                if (syncid > 0 && r != null && r.reqId != null) {
                    if (SbxDB.syncidlock(syncid) == false) {
                        throw new AccessDeniedException("GetSyncIdError", userId + ":" + bucketName + ":"
                                + objectKey + "*** syncid=" + syncid + " need be locked", true);
                    }
                }
            } catch (AccessDeniedException ex) {
                throw ex;
            } catch (Throwable t) {
                throw new AccessDeniedException("GetSyncIdError",
                        userId + ":" + bucketName + ":" + objectKey + "***" + t.toString(), true);
            }
        }

        int objSeq = -1;
        if (Contexts.SBXSVR) {
            try {
                if (r != null && StringUtils.isNotEmpty(r.objSeq)) {
                    objSeq = Integer.parseInt(r.objSeq);
                }
                if (objSeq != -1) {
                    // compare objSeq with Object's obj-seq
                    int dbObjSeq = SbxDB.getObjSeq(userId, bucketName, objectKey);
                    if (objSeq != dbObjSeq) {
                        throw new AccessDeniedException("GetObjSeq", userId + ":" + bucketName + ":" + objectKey
                                + "#obj-seq are different: " + objSeq + " != " + dbObjSeq, true);
                    }
                }
            } catch (AccessDeniedException t) {
                throw t;
            } catch (Throwable t) {
                throw new AccessDeniedException("GetObjSeq",
                        userId + ":" + bucketName + ":" + objectKey + "***" + t.toString(), true);
            }
        }

        String md5 = "";
        Date lastModified = new Date();
        long size = 0;
        AccessControlListType accessControlList = request.getAccessControlList();
        if (accessControlList == null) {
            accessControlList = new AccessControlListType();
        }

        //====empty and remove data queue
        String key = bucketName + "." + objectKey;
        String randomKey = request.getRandomKey();
        WalrusDataMessenger messenger = WalrusRESTBinding.getWriteMessenger();
        WalrusDataQueue<WalrusDataMessage> putQueue = messenger.getQueue(key, randomKey);
        putQueue.clear();
        messenger.removeQueue(key, randomKey);
        //====      

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
        try {

            List<BucketInfo> bucketList = db.query(new BucketInfo(bucketName));
            if (bucketList.size() <= 0) {
                throw new NoSuchBucketException(bucketName);
            }

            BucketInfo bucket = bucketList.get(0);
            BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
            if (!bucket.canWrite(userId)) {
                throw new AccessDeniedException("Bucket", bucketName, logData);
            }

            String objectName;
            String versionId;
            ObjectInfo objectInfo = null;
            if (bucket.isVersioningEnabled()) {//new an object by hibernate
                Log.debug(userId + ":" + bucketName + ":" + objectKey + "***"
                        + "Error rename does not support version");
                throw new AccessDeniedException("NotSupportVersion", userId + ":" + bucketName + ":" + objectKey
                        + "***" + "Error rename does not support version", true);
            } else {//modify object

                /*
                versionId = WalrusProperties.NULL_VERSION_ID;
                ObjectInfo searchObject = new ObjectInfo(bucketName, objectKey);
                       searchObject.setVersionId(versionId);
                    
                ObjectInfo sourceObject=null,targetObject=new ObjectInfo(bucketName,renameTo);
                     
                 //=======to check source exsit and target doesn't.
                 try{
                  sourceObject = dbObject.getUnique(searchObject);
                 }catch(EucalyptusCloudException ec){throw new NoSuchEntityException(objectKey);}  
                 if (!sourceObject.canWrite(userId)) {throw new AccessDeniedException("Key", objectKey, logData);}
                     
                 //===========
                 List tmpL=dbObject.query(targetObject);int tmpLsize=tmpL.size();tmpL.clear();
                 if(tmpLsize!=0){throw new AccessDeniedException("Key",renameTo,logData);};
                 //==========*/

                //                String sql="UPDATE objects SET object_key=regexp_replace(object_key, ?, ?, 'q') " +
                //                        "where bucket_name = ? and owner_id = ? and (object_key ~ ? or object_key = ?)";
                //
                //                SQLQuery query=dbObject.getSession().createSQLQuery(sql);
                //                query.setString(0, objectKey);
                //                query.setString(1, renameTo);
                //                query.setString(2, bucketName);
                //                query.setString(3, account);
                //                query.setString(4, "^" + objectKey + "/");
                //                query.setString(5, objectKey);
                //                int exR=query.executeUpdate();
                //
                //                if(exR==0){
                //                    Log.debug(userId + ":" + bucketName + ":" + objectKey + "***" + "Error rename in sql");
                //                    throw new AccessDeniedException("SqlError", userId + ":" + bucketName + ":" + objectKey + "***" + "Error rename in sql", true);

                doRenameEvent(dbObject.getEntityManager(), account, bucketName, objectKey, renameTo);
            }

            if (Contexts.SBXSVR) {
                String reqid = request.getMetaReqId();
                if (reqid == null)
                    reqid = "null";
                if (objSeq == -1) {
                    objSeq = 0;
                }
                try {
                    writeRenameEvent(dbObject.getEntityManager(), instanceId, account, bucketName, objectKey,
                            renameTo, syncid, reqid, objSeq);
                } catch (Throwable t) {
                    throw new AccessDeniedException("WriteRenameEventError",
                            userId + ":" + bucketName + ":" + objectKey + "***" + "Error rename in sql", true);
                }
            }

            db.commit();

            reply.setLogData(logData);
            reply.setEtag(md5);
            reply.setSize(size);
            reply.setLastModified(
                    DateUtils.format(lastModified.getTime(), DateUtils.ISO8601_DATETIME_PATTERN) + ".000Z");

        } catch (AccessDeniedException we) {
            db.rollback();
            throw we;
        } catch (Throwable t) {
            Log.debug(userId + ":" + bucketName + ":" + objectKey + "***" + "Error" + "***" + t);
            db.rollback();
            throw new AccessDeniedException("CssError",
                    userId + ":" + bucketName + ":" + objectKey + "***" + "Error" + "***" + t.getMessage(), true);
        } finally {
        }
        return reply;

    }

    public PostObjectResponseType postObject(PostObjectType request) throws EucalyptusCloudException {
        PostObjectResponseType reply = (PostObjectResponseType) request.getReply();

        String bucketName = request.getBucket();
        String key = request.getKey();

        PutObjectType putObject = new PutObjectType();
        putObject.setUserId(request.getUserId());
        putObject.setBucket(bucketName);
        putObject.setKey(key);
        putObject.setRandomKey(request.getRandomKey());
        putObject.setAccessControlList(request.getAccessControlList());
        putObject.setContentType(request.getContentType());
        putObject.setContentLength(request.getContentLength());
        putObject.setAccessKeyID(request.getAccessKeyID());
        putObject.setEffectiveUserId(request.getEffectiveUserId());
        putObject.setCredential(request.getCredential());
        putObject.setIsCompressed(request.getIsCompressed());
        putObject.setMetaData(request.getMetaData());
        putObject.setStorageClass(request.getStorageClass());

        PutObjectResponseType putObjectResponse = putObjectRefactor(putObject);

        String etag = putObjectResponse.getEtag();
        reply.setEtag(etag);
        reply.setLastModified(putObjectResponse.getLastModified());
        reply.set_return(putObjectResponse.get_return());
        reply.setMetaData(putObjectResponse.getMetaData());
        reply.setErrorCode(putObjectResponse.getErrorCode());
        reply.setStatusMessage(putObjectResponse.getStatusMessage());
        reply.setLogData(putObjectResponse.getLogData());

        String successActionRedirect = request.getSuccessActionRedirect();
        if (successActionRedirect != null) {
            try {
                java.net.URI addrUri = new URL(successActionRedirect).toURI();
                InetAddress.getByName(addrUri.getHost());
            } catch (Exception ex) {
                LOG.warn(ex);
            }
            String paramString = "bucket=" + bucketName + "&key=" + key + "&etag=quot;" + etag + "quot;";
            reply.setRedirectUrl(successActionRedirect + "?" + paramString);
        } else {
            Integer successActionStatus = request.getSuccessActionStatus();
            if (successActionStatus != null) {
                if ((successActionStatus == 200) || (successActionStatus == 201)) {
                    reply.setSuccessCode(successActionStatus);
                    if (successActionStatus == 200) {
                        return reply;
                    } else {
                        reply.setBucket(bucketName);
                        reply.setKey(key);
                        reply.setLocation(SystemConfiguration.getWalrusUrl() + "/" + bucketName + "/" + key);
                    }
                } else {
                    reply.setSuccessCode(204);
                    return reply;
                }
            }
        }
        return reply;
    }

    public PutObjectInlineResponseType putObjectInline(PutObjectInlineType request)
            throws EucalyptusCloudException {
        PutObjectInlineResponseType reply = (PutObjectInlineResponseType) request.getReply();
        String userId = request.getUserId();

        String bucketName = request.getBucket();
        String objectKey = request.getKey();

        String md5 = "";
        Long oldBucketSize = 0L;
        Date lastModified;

        AccessControlListType accessControlList = request.getAccessControlList();
        if (accessControlList == null) {
            accessControlList = new AccessControlListType();
        }

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo = new BucketInfo(bucketName);
        List<BucketInfo> bucketList = db.query(bucketInfo);

        if (bucketList.size() > 0) {
            BucketInfo bucket = bucketList.get(0);
            BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
            if (bucket.canWrite(userId)) {
                EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
                ObjectInfo searchObjectInfo = new ObjectInfo();
                searchObjectInfo.setBucketName(bucketName);

                ObjectInfo foundObject = null;
                List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
                for (ObjectInfo objectInfo : objectInfos) {
                    if (objectInfo.getObjectKey().equals(objectKey)) {
                        // key (object) exists. check perms
                        if (!objectInfo.canWrite(userId)) {
                            db.rollback();
                            throw new AccessDeniedException("Key", objectKey, logData);
                        }
                        foundObject = objectInfo;
                        oldBucketSize = -foundObject.getSize();
                        break;
                    }
                }
                // write object to bucket
                String objectName;
                if (foundObject == null) {
                    // not found. create an object info
                    foundObject = new ObjectInfo(bucketName, objectKey);
                    foundObject.setOwnerId(userId);
                    List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
                    foundObject.addGrants(userId, grantInfos, accessControlList);
                    foundObject.setGrants(grantInfos);
                    objectName = UUID.randomUUID().toString();
                    foundObject.setObjectName(objectName);
                    dbObject.add(foundObject);
                } else {
                    // object already exists. see if we can modify acl
                    if (foundObject.canWriteACP(userId)) {
                        List<GrantInfo> grantInfos = foundObject.getGrants();
                        foundObject.addGrants(userId, grantInfos, accessControlList);
                    }
                    objectName = foundObject.getObjectName();
                }
                foundObject.setObjectKey(objectKey);

                try {
                    // writes are unconditional
                    if (request.getBase64Data().getBytes().length > WalrusProperties.MAX_INLINE_DATA_SIZE) {
                        db.rollback();
                        throw new InlineDataTooLargeException(bucketName + "/" + objectKey);
                    }
                    byte[] base64Data = Hashes.base64decode(request.getBase64Data()).getBytes();
                    foundObject.setObjectName(objectName);
                    FileIO fileIO = null;
                    try {
                        fileIO = storageManager.prepareForWrite(bucketName, objectName);
                        if (fileIO != null) {
                            fileIO.write(base64Data);
                            fileIO.finish();
                        }
                    } catch (Exception ex) {
                        db.rollback();
                        throw new EucalyptusCloudException(ex);
                    } finally {
                        if (fileIO != null)
                            fileIO.finish();
                    }
                    md5 = Hashes.getHexString(Digest.MD5.get().digest(base64Data));
                    foundObject.setEtag(md5);
                    Long size = (long) base64Data.length;
                    foundObject.setSize(size);
                    if (WalrusProperties.shouldEnforceUsageLimits && !request.isAdministrator()) {
                        Long bucketSize = bucket.getBucketSize();
                        long newSize = bucketSize + oldBucketSize + size;
                        if (newSize > (WalrusInfo.getWalrusInfo().getStorageMaxBucketSizeInMB()
                                * WalrusProperties.M)) {
                            db.rollback();
                            throw new EntityTooLargeException("Key", objectKey, logData);
                        }
                        bucket.setBucketSize(newSize);
                    }
                    if (WalrusProperties.trackUsageStatistics) {
                        walrusStatistics.updateBytesIn(size);
                        walrusStatistics.updateSpaceUsed(size);
                    }
                    // Add meta data if specified
                    if (request.getMetaData() != null)
                        foundObject.replaceMetaData(request.getMetaData());

                    // TODO: add support for other storage classes
                    foundObject.setStorageClass("STANDARD");
                    lastModified = new Date();
                    foundObject.setLastModified(lastModified);
                    if (logData != null) {
                        updateLogData(bucket, logData);
                        logData.setObjectSize(size);
                        reply.setLogData(logData);
                    }
                } catch (Exception ex) {
                    LOG.error(ex);
                    db.rollback();
                    throw new EucalyptusCloudException(bucketName);
                }
            } else {
                db.rollback();
                throw new AccessDeniedException("Bucket", bucketName, logData);
            }
        } else {
            db.rollback();
            throw new NoSuchBucketException(bucketName);
        }

        db.commit();

        reply.setEtag(md5);
        reply.setLastModified(
                DateUtils.format(lastModified.getTime(), DateUtils.ISO8601_DATETIME_PATTERN) + ".000Z");
        return reply;
    }

    public AddObjectResponseType addObject(AddObjectType request) throws EucalyptusCloudException {

        AddObjectResponseType reply = (AddObjectResponseType) request.getReply();
        String bucketName = request.getBucket();
        String key = request.getKey();
        String userId = request.getUserId();
        String objectName = request.getObjectName();

        AccessControlListType accessControlList = request.getAccessControlList();
        if (accessControlList == null) {
            accessControlList = new AccessControlListType();
        }

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo = new BucketInfo(bucketName);
        List<BucketInfo> bucketList = db.query(bucketInfo);

        if (bucketList.size() > 0) {
            BucketInfo bucket = bucketList.get(0);
            if (bucket.canWrite(userId)) {
                EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
                ObjectInfo searchObjectInfo = new ObjectInfo();
                searchObjectInfo.setBucketName(bucketName);
                List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
                for (ObjectInfo objectInfo : objectInfos) {
                    if (objectInfo.getObjectKey().equals(key)) {
                        // key (object) exists.
                        db.rollback();
                        throw new EucalyptusCloudException("object already exists " + key);
                    }
                }
                // write object to bucket
                ObjectInfo objectInfo = new ObjectInfo(bucketName, key);
                objectInfo.setObjectName(objectName);
                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
                objectInfo.addGrants(userId, grantInfos, accessControlList);
                objectInfo.setGrants(grantInfos);
                dbObject.add(objectInfo);

                objectInfo.setObjectKey(key);
                objectInfo.setOwnerId(userId);
                objectInfo.setSize(storageManager.getSize(bucketName, objectName));
                objectInfo.setEtag(request.getEtag());
                objectInfo.setLastModified(new Date());
                objectInfo.setStorageClass("STANDARD");
            } else {
                db.rollback();
                throw new AccessDeniedException("Bucket", bucketName);
            }
        } else {
            db.rollback();
            throw new NoSuchBucketException(bucketName);
        }
        db.commit();
        return reply;
    }

    public DeleteObjectResponseType deleteObject(DeleteObjectType request) throws EucalyptusCloudException {
        return deleteObject(request, null);
    }

    public DeleteObjectResponseType deleteObject(DeleteObjectType request, SbxRequest r)
            throws EucalyptusCloudException {
        String bucketName = null;
        String objectKey = null;
        String userId = null;

        DeleteObjectResponseType reply = (DeleteObjectResponseType) request.getReply();
        bucketName = request.getBucket();
        objectKey = request.getKey();
        userId = request.getUserId();

        if (Contexts.SBXSVR) {
            try {
                String myaccount = userId;
                String myinstid = request.getMetaInstId();
                WalrusControl.walrusManager.callWalrusHeartBeat(myaccount, myinstid, "DELETEOBJECT");
            } catch (Throwable t) {
                Log.debug("CSS callWalrusHeartBeat error (deleteObject) " + "***" + t.toString());
            }
        }

        long syncid = -1;
        if (Contexts.SBXSVR) {
            // mac: get sync id before putObject
            try {
                syncid = this.getSyncId(request.getMetaClientType(), userId);
                // syncid must LOCK (syncid == 0 for mobile and browser)
                if (syncid > 0 && r != null && r.reqId != null) {
                    if (SbxDB.syncidlock(syncid) == false) {
                        throw new AccessDeniedException("GetSyncIdError", userId + ":" + bucketName + ":"
                                + objectKey + "*** syncid=" + syncid + " need be locked", true);
                    }
                }
            } catch (AccessDeniedException ex) {
                throw ex;
            } catch (Throwable t) {
                throw new AccessDeniedException("GetSyncIdError",
                        userId + ":" + bucketName + ":" + objectKey + "***" + "Error get syncid", true);
            }
        }

        int objSeq = -1;
        if (Contexts.SBXSVR) {
            try {
                if (r != null && StringUtils.isNotEmpty(r.objSeq)) {
                    objSeq = Integer.parseInt(r.objSeq);
                }
                if (objSeq != -1) {
                    // compare objSeq with Object's obj-seq
                    int dbObjSeq = SbxDB.getObjSeq(userId, bucketName, objectKey);
                    if (objSeq != dbObjSeq) {
                        throw new AccessDeniedException("GetObjSeq", userId + ":" + bucketName + ":" + objectKey
                                + "#obj-seq are different: " + objSeq + " != " + dbObjSeq, true);
                    }
                }
            } catch (AccessDeniedException t) {
                throw t;
            } catch (Throwable t) {
                throw new AccessDeniedException("GetObjSeq",
                        userId + ":" + bucketName + ":" + objectKey + "***" + t.toString(), true);
            }
        }

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfos = new BucketInfo(bucketName);
        String[] backup = new String[1];
        String objectName = null;
        try {
            List<BucketInfo> bucketList = db.query(bucketInfos);
            if (bucketList.size() > 0) {
                BucketInfo bucketInfo = bucketList.get(0);
                BucketLogData logData = bucketInfo.getLoggingEnabled() ? request.getLogData() : null;

                if (bucketInfo.isVersioningEnabled()) {
                    EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
                    ObjectInfo searchDeletedObjectInfo = new ObjectInfo(bucketName, objectKey);
                    searchDeletedObjectInfo.setDeleted(true);
                    try {
                        dbObject.getUnique(searchDeletedObjectInfo);
                        db.rollback();
                        throw new NoSuchEntityException(objectKey, logData);
                    } catch (NoSuchEntityException ex) {
                        throw ex;
                    } catch (EucalyptusCloudException ex) {
                        ObjectInfo searchObjectInfo = new ObjectInfo(bucketName, objectKey);
                        searchObjectInfo.setLast(true);
                        List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
                        for (ObjectInfo objInfo : objectInfos) {
                            objInfo.setLast(false);
                        }
                        ObjectInfo deleteMarker = new ObjectInfo(bucketName, objectKey);
                        deleteMarker.setDeleted(true);
                        deleteMarker.setLast(true);
                        deleteMarker.setOwnerId(userId);
                        deleteMarker.setLastModified(new Date());
                        deleteMarker.setVersionId(UUID.randomUUID().toString().replaceAll("-", ""));
                        dbObject.add(deleteMarker);
                        reply.setCode("200");
                        reply.setDescription("OK");
                    }
                } else {
                    // versioning disabled or suspended.
                    ObjectInfo searchObjectInfo = new ObjectInfo(bucketName, objectKey);
                    searchObjectInfo.setVersionId(WalrusProperties.NULL_VERSION_ID);
                    EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
                    List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
                    if (objectInfos.size() > 0) {
                        ObjectInfo nullObject = objectInfos.get(0);
                        if (nullObject.canWrite(userId)) {
                            if (Contexts.SBXSVR) {
                                //mac: deny delete folder if there are objects inside the folder
                                if (strSBXContentTypeFolder.equals(nullObject.getContentType())) {
                                    if (SbxDB.containObjects(userId, bucketName, objectKey)) {
                                        db.rollback();
                                        throw new AccessDeniedException("CssError", userId + ":" + bucketName + ":"
                                                + objectKey + "***" + "folder is not empty (cannot delete)", true);
                                    }
                                }
                            }

                            dbObject.delete(nullObject);
                            objectName = nullObject.getObjectName();
                            for (GrantInfo grantInfo : nullObject.getGrants()) {
                                db.getEntityManager().remove(grantInfo);
                            }
                            Long size = nullObject.getSize();
                            /*
                             * bucketInfo.setBucketSize(bucketInfo .getBucketSize()
                             * - size);
                             */

                            reply.setCode("200");
                            reply.setDescription("OK");
                            if (logData != null) {
                                updateLogData(bucketInfo, logData);
                                reply.setLogData(logData);
                            }
                            Date lastModified = new Date();
                            if (bucketInfo.isVersioningSuspended()) {
                                // add delete marker
                                ObjectInfo deleteMarker = new ObjectInfo(bucketName, objectKey);
                                deleteMarker.setDeleted(true);
                                deleteMarker.setLast(true);
                                deleteMarker.setOwnerId(userId);
                                deleteMarker.setLastModified(lastModified);
                                deleteMarker.setVersionId(UUID.randomUUID().toString().replaceAll("-", ""));
                                dbObject.add(deleteMarker);
                            }

                            long mtime = 0;
                            //                            try {
                            //                                // mac : delete does not need lastModifiedTime
                            //                                List<MetaDataInfo> metaDataInfos = nullObject.getMetaData();
                            //                                for (MetaDataInfo metaDataInfo : metaDataInfos) {
                            //                                    String name = metaDataInfo.getName();
                            //                                    if (name != null && name.equals("mtime")) {
                            //                                        mtime = Integer.valueOf(metaDataInfo.getValue());
                            //                                        break;
                            //                                    }
                            //                                }
                            //                            }catch (Throwable t) {
                            //                                Log.debug("CSS error: cannot get mtime from client: " + userId+":"+bucketName+":"+objectKey + " ***" + t.toString());
                            //                            }

                            if (Contexts.SBXSVR) {
                                String reqid = request.getMetaReqId();
                                if (reqid == null)
                                    reqid = "null";
                                if (objSeq == -1) {
                                    objSeq = 0;
                                }
                                writeEvent(dbObject.getEntityManager(), request.getMetaClientType(), userId,
                                        "Delete", nullObject.getObjectKey(), nullObject.getSize(),
                                        strSBXContentTypeFolder.equals(nullObject.getContentType()), syncid, mtime,
                                        reqid, objSeq);
                            }
                            //                  ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, objectName, size);
                            //                  objectDeleter.start();
                            try {
                                storageManager.deleteObject(backup, bucketName, objectName);
                            } catch (Throwable t) {
                                storageManager.deleteObjectRollback(backup, bucketName, objectName);
                                throw t;
                            }
                            if (WalrusProperties.trackUsageStatistics && (size > 0))
                                walrusStatistics.updateSpaceUsed(-size);
                        } else {
                            db.rollback();
                            throw new AccessDeniedException("Key", objectKey, logData);
                        }
                    } else {
                        db.rollback();
                        throw new NoSuchEntityException(objectKey, logData);
                    }
                }
            } else {
                db.rollback();
                throw new NoSuchBucketException(bucketName);
            }
            try {
                db.commit();
            } catch (Throwable t) {
                storageManager.deleteObjectRollback(backup, bucketName, objectName);
                throw t;
            }
            try {
                storageManager.confirm(backup);
            } catch (Throwable t) {
                //NOP
            }
        } catch (AccessDeniedException t) {
            throw t;
        } catch (NoSuchEntityException t) {
            throw t;
        } catch (NoSuchBucketException t) {
            throw t;
        } catch (Throwable t) {
            db.rollback();
            throw new AccessDeniedException("CssError", userId + ":" + bucketName + ":" + objectKey + "***" + t,
                    true);
        }
        return reply;
    } //deleteObject

    private class ObjectDeleter extends Thread {
        String bucketName;
        String objectName;
        Long size;

        public ObjectDeleter(String bucketName, String objectName, Long size) {
            this.bucketName = bucketName;
            this.objectName = objectName;
            this.size = size;
        }

        public void run() {
            try {
                storageManager.deleteObject(bucketName, objectName);
                if (WalrusProperties.trackUsageStatistics && (size > 0))
                    walrusStatistics.updateSpaceUsed(-size);
            } catch (IOException ex) {
                LOG.error(ex, ex);
            }
        }
    }

    public ListBucketResponseType listBucket(ListBucketType request) throws EucalyptusCloudException {
        ListBucketResponseType reply = (ListBucketResponseType) request.getReply();
        String bucketName = request.getBucket();
        String userId = request.getUserId();
        String prefix = request.getPrefix();
        if (prefix == null)
            prefix = "";

        String marker = request.getMarker();
        int maxKeys = -1;
        String maxKeysString = request.getMaxKeys();
        if (maxKeysString != null) {
            try {
                maxKeys = Integer.parseInt(maxKeysString);
            } catch (Throwable t) {
                maxKeys = WalrusProperties.MAX_KEYS;
            }
        } else {
            maxKeys = WalrusProperties.MAX_KEYS;
        }
        String delimiter = request.getDelimiter();

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        try {
            BucketInfo bucketInfo = new BucketInfo(bucketName);
            bucketInfo.setHidden(false);
            List<BucketInfo> bucketList = db.query(bucketInfo);

            ArrayList<PrefixEntry> prefixes = new ArrayList<PrefixEntry>();

            if (bucketList.size() > 0) {
                BucketInfo bucket = bucketList.get(0);
                BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
                if (bucket.canRead(userId)) {
                    if (logData != null) {
                        updateLogData(bucket, logData);
                        reply.setLogData(logData);
                    }
                    if (request.isAdministrator()) {
                        EntityWrapper<WalrusSnapshotInfo> dbSnap = db.recast(WalrusSnapshotInfo.class);
                        WalrusSnapshotInfo walrusSnapInfo = new WalrusSnapshotInfo();
                        walrusSnapInfo.setSnapshotBucket(bucketName);
                        List<WalrusSnapshotInfo> walrusSnaps = dbSnap.query(walrusSnapInfo);
                        if (walrusSnaps.size() > 0) {
                            throw new NoSuchBucketException(bucketName);
                        }
                    }
                    reply.setName(bucketName);
                    reply.setIsTruncated(false);
                    if (maxKeys >= 0)
                        reply.setMaxKeys(maxKeys);
                    reply.setPrefix(prefix);
                    reply.setMarker(marker);
                    if (delimiter != null)
                        reply.setDelimiter(delimiter);
                    EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
                    ObjectInfo searchObjectInfo = new ObjectInfo();
                    searchObjectInfo.setBucketName(bucketName);
                    searchObjectInfo.setDeleted(false);
                    searchObjectInfo.setLast(true);
                    List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo, maxKeys, marker,
                            new String[] { "objectKey" });
                    if (objectInfos.size() > 0) {
                        int howManyProcessed = 0;

                        // mac
                        // if (marker != null || objectInfos.size() < maxKeys)
                        // Collections.sort(objectInfos);

                        boolean isFoundMarker = false;
                        ArrayList<ListEntry> contents = new ArrayList<ListEntry>();
                        for (ObjectInfo objectInfo : objectInfos) {
                            String objectKey = objectInfo.getObjectKey();

                            // if (marker != null) {
                            // if (objectKey.compareTo(marker) <= 0)
                            // continue;
                            // }

                            if (marker != null && !isFoundMarker) {
                                if (objectKey.compareTo(marker) == 0) {
                                    isFoundMarker = true;
                                }
                                continue;
                            }

                            if (prefix != null) {
                                if (!objectKey.startsWith(prefix)) {
                                    continue;
                                } else {
                                    if (delimiter != null) {
                                        String[] parts = objectKey.substring(prefix.length()).split(delimiter);
                                        if (parts.length > 1) {
                                            String prefixString = parts[0] + delimiter;
                                            boolean foundPrefix = false;
                                            for (PrefixEntry prefixEntry : prefixes) {
                                                if (prefixEntry.getPrefix().equals(prefixString)) {
                                                    foundPrefix = true;
                                                    break;
                                                }
                                            }
                                            if (!foundPrefix) {
                                                if (maxKeys >= 0) {
                                                    if (howManyProcessed++ > maxKeys) {
                                                        reply.setIsTruncated(true);
                                                        break;
                                                    }
                                                }
                                                prefixes.add(new PrefixEntry(prefixString));
                                            }
                                            continue;
                                        }
                                    }
                                }
                            }
                            if (maxKeys >= 0) {
                                howManyProcessed++;
                                if (howManyProcessed > maxKeys) {
                                    reply.setIsTruncated(true);
                                    break;
                                }
                            }
                            ListEntry listEntry = new ListEntry();
                            listEntry.setKey(objectKey);
                            listEntry.setEtag(objectInfo.getEtag());
                            listEntry.setLastModified(DateUtils.format(objectInfo.getLastModified().getTime(),
                                    DateUtils.ISO8601_DATETIME_PATTERN) + ".000Z");
                            listEntry.setStorageClass(objectInfo.getStorageClass());
                            String displayName = objectInfo.getOwnerId();
                            try {
                                User userInfo = Users.lookupUser(displayName);
                                listEntry.setOwner(new CanonicalUserType(userInfo.getQueryId(), displayName));
                            } catch (NoSuchUserException e) {
                                throw new AccessDeniedException("Bucket", bucketName, logData);
                            }
                            ArrayList<MetaDataEntry> metaData = new ArrayList<MetaDataEntry>();
                            objectInfo.returnMetaData(metaData);
                            reply.setMetaData(metaData);

                            // added by keanu 20120709, added obj-seq metadata for each object
                            try {
                                listEntry.setObjSeq(String.valueOf(objectInfo.getObjSeq()));
                            } catch (Throwable t) {
                                LOG.debug("cannot add obj-seq");
                            }
                            listEntry.setSize(objectInfo.getSize());
                            listEntry.setStorageClass(objectInfo.getStorageClass());
                            contents.add(listEntry);
                        }
                        reply.setContents(contents);
                        if (prefixes.size() > 0) {
                            reply.setCommonPrefixes(prefixes);
                        }
                    }
                } else {
                    throw new AccessDeniedException("Bucket", bucketName, logData);
                }
            } else {
                throw new NoSuchBucketException(bucketName);
            }
            db.commit();
        } catch (NoSuchBucketException t) {
            db.rollback();
            throw t;
        } catch (AccessDeniedException t) {
            db.rollback();
            throw t;
        } catch (Throwable t) {
            db.rollback();
            throw new AccessDeniedException("CssError", userId + "***" + t.toString(), true);
        }

        return reply;
    }

    public GetObjectAccessControlPolicyResponseType getObjectAccessControlPolicy(
            GetObjectAccessControlPolicyType request) throws EucalyptusCloudException {
        GetObjectAccessControlPolicyResponseType reply = (GetObjectAccessControlPolicyResponseType) request
                .getReply();

        String bucketName = request.getBucket();
        String objectKey = request.getKey();
        String userId = request.getUserId();
        String ownerId = null;

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo = new BucketInfo(bucketName);
        List<BucketInfo> bucketList = db.query(bucketInfo);
        BucketLogData logData;

        AccessControlListType accessControlList = new AccessControlListType();
        if (bucketList.size() > 0) {
            // construct access control policy from grant infos
            BucketInfo bucket = bucketList.get(0);
            logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
            EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
            ObjectInfo searchObjectInfo = new ObjectInfo(bucketName, objectKey);
            if (bucket.isVersioningEnabled()) {
                if (request.getVersionId() == null)
                    searchObjectInfo.setLast(true);
            }
            String versionId = request.getVersionId() != null ? request.getVersionId()
                    : WalrusProperties.NULL_VERSION_ID;
            searchObjectInfo.setVersionId(versionId);
            searchObjectInfo.setDeleted(false);
            List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
            if (objectInfos.size() > 0) {
                ObjectInfo objectInfo = objectInfos.get(0);
                if (objectInfo.canReadACP(userId)) {
                    if (logData != null) {
                        updateLogData(bucket, logData);
                        logData.setObjectSize(objectInfo.getSize());
                        reply.setLogData(logData);
                    }

                    ownerId = objectInfo.getOwnerId();
                    ArrayList<Grant> grants = new ArrayList<Grant>();
                    List<GrantInfo> grantInfos = objectInfo.getGrants();
                    for (GrantInfo grantInfo : grantInfos) {
                        String uId = grantInfo.getUserId();
                        try {
                            User userInfo = Users.lookupUser(uId);
                            objectInfo.readPermissions(grants);
                            addPermission(grants, userInfo, grantInfo);
                        } catch (NoSuchUserException e) {
                            throw new AccessDeniedException("Key", objectKey, logData);
                        }
                    }
                    accessControlList.setGrants(grants);
                } else {
                    db.rollback();
                    throw new AccessDeniedException("Key", objectKey, logData);
                }
            } else {
                db.rollback();
                throw new NoSuchEntityException(objectKey, logData);
            }
        } else {
            db.rollback();
            throw new NoSuchBucketException(bucketName);
        }

        AccessControlPolicyType accessControlPolicy = new AccessControlPolicyType();
        try {
            User ownerUserInfo = Users.lookupUser(ownerId);
            accessControlPolicy
                    .setOwner(new CanonicalUserType(ownerUserInfo.getQueryId(), ownerUserInfo.getName()));
            accessControlPolicy.setAccessControlList(accessControlList);
        } catch (NoSuchUserException e) {
            throw new AccessDeniedException("Key", objectKey, logData);
        }
        reply.setAccessControlPolicy(accessControlPolicy);
        db.commit();
        return reply;
    }

    public SetBucketAccessControlPolicyResponseType setBucketAccessControlPolicy(
            SetBucketAccessControlPolicyType request) throws EucalyptusCloudException {
        SetBucketAccessControlPolicyResponseType reply = (SetBucketAccessControlPolicyResponseType) request
                .getReply();
        String userId = request.getUserId();
        AccessControlListType accessControlList = request.getAccessControlList();
        String bucketName = request.getBucket();
        if (accessControlList == null) {
            throw new AccessDeniedException("Bucket", bucketName);
        }

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo = new BucketInfo(bucketName);
        List<BucketInfo> bucketList = db.query(bucketInfo);

        if (bucketList.size() > 0) {
            BucketInfo bucket = bucketList.get(0);
            BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
            if (bucket.canWriteACP(userId)) {
                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
                bucket.resetGlobalGrants();
                bucket.addGrants(bucket.getOwnerId(), grantInfos, accessControlList);
                bucket.setGrants(grantInfos);
                reply.setCode("204");
                reply.setDescription("OK");
                if (logData != null) {
                    updateLogData(bucket, logData);
                    reply.setLogData(logData);
                }
            } else {
                db.rollback();
                throw new AccessDeniedException("Bucket", bucketName, logData);
            }
        } else {
            db.rollback();
            throw new NoSuchBucketException(bucketName);
        }
        db.commit();
        return reply;
    }

    public SetRESTBucketAccessControlPolicyResponseType setRESTBucketAccessControlPolicy(
            SetRESTBucketAccessControlPolicyType request) throws EucalyptusCloudException {
        SetRESTBucketAccessControlPolicyResponseType reply = (SetRESTBucketAccessControlPolicyResponseType) request
                .getReply();
        String userId = request.getUserId();
        AccessControlPolicyType accessControlPolicy = request.getAccessControlPolicy();
        String bucketName = request.getBucket();
        if (accessControlPolicy == null) {
            throw new AccessDeniedException("Bucket", bucketName);
        }
        AccessControlListType accessControlList = accessControlPolicy.getAccessControlList();

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo = new BucketInfo(bucketName);
        List<BucketInfo> bucketList = db.query(bucketInfo);

        if (bucketList.size() > 0) {
            BucketInfo bucket = bucketList.get(0);
            BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
            if (bucket.canWriteACP(userId)) {
                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
                bucket.resetGlobalGrants();
                bucket.addGrants(bucket.getOwnerId(), grantInfos, accessControlList);
                bucket.setGrants(grantInfos);
                reply.setCode("204");
                reply.setDescription("OK");
                if (logData != null) {
                    updateLogData(bucket, logData);
                    reply.setLogData(logData);
                }
            } else {
                db.rollback();
                throw new AccessDeniedException("Bucket", bucketName, logData);
            }
        } else {
            db.rollback();
            throw new NoSuchBucketException(bucketName);
        }
        db.commit();
        return reply;
    }

    public SetObjectAccessControlPolicyResponseType setObjectAccessControlPolicy(
            SetObjectAccessControlPolicyType request) throws EucalyptusCloudException {
        SetObjectAccessControlPolicyResponseType reply = (SetObjectAccessControlPolicyResponseType) request
                .getReply();
        String userId = request.getUserId();
        AccessControlListType accessControlList = request.getAccessControlList();
        String bucketName = request.getBucket();
        String objectKey = request.getKey();

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo = new BucketInfo(bucketName);
        List<BucketInfo> bucketList = db.query(bucketInfo);

        if (bucketList.size() > 0) {
            BucketInfo bucket = bucketList.get(0);
            BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
            EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
            ObjectInfo searchObjectInfo = new ObjectInfo(bucketName, objectKey);
            if (bucket.isVersioningEnabled()) {
                if (request.getVersionId() == null)
                    searchObjectInfo.setLast(true);
            }
            String versionId = request.getVersionId() != null ? request.getVersionId()
                    : WalrusProperties.NULL_VERSION_ID;
            searchObjectInfo.setVersionId(versionId);
            searchObjectInfo.setDeleted(false);
            List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
            if (objectInfos.size() > 0) {
                ObjectInfo objectInfo = objectInfos.get(0);
                if (!objectInfo.canWriteACP(userId)) {
                    db.rollback();
                    throw new AccessDeniedException("Key", objectKey, logData);
                }
                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
                objectInfo.resetGlobalGrants();
                objectInfo.addGrants(objectInfo.getOwnerId(), grantInfos, accessControlList);
                objectInfo.setGrants(grantInfos);

                if (WalrusProperties.enableTorrents) {
                    if (!objectInfo.isGlobalRead()) {
                        EntityWrapper<TorrentInfo> dbTorrent = db.recast(TorrentInfo.class);
                        TorrentInfo torrentInfo = new TorrentInfo(bucketName, objectKey);
                        List<TorrentInfo> torrentInfos = dbTorrent.query(torrentInfo);
                        if (torrentInfos.size() > 0) {
                            TorrentInfo foundTorrentInfo = torrentInfos.get(0);
                            TorrentClient torrentClient = Torrents.getClient(bucketName + objectKey);
                            if (torrentClient != null) {
                                torrentClient.bye();
                            }
                            dbTorrent.delete(foundTorrentInfo);
                        }
                    }
                } else {
                    LOG.warn("Bittorrent support has been disabled. Please check pre-requisites");
                }
                reply.setCode("204");
                reply.setDescription("OK");
                if (logData != null) {
                    updateLogData(bucket, logData);
                    logData.setObjectSize(objectInfo.getSize());
                    reply.setLogData(logData);
                }
            } else {
                db.rollback();
                throw new NoSuchEntityException(objectKey, logData);
            }
        } else {
            db.rollback();
            throw new NoSuchBucketException(bucketName);
        }
        db.commit();
        return reply;
    }

    public SetRESTObjectAccessControlPolicyResponseType setRESTObjectAccessControlPolicy(
            SetRESTObjectAccessControlPolicyType request) throws EucalyptusCloudException {
        SetRESTObjectAccessControlPolicyResponseType reply = (SetRESTObjectAccessControlPolicyResponseType) request
                .getReply();
        String userId = request.getUserId();
        AccessControlPolicyType accessControlPolicy = request.getAccessControlPolicy();
        if (accessControlPolicy == null) {
            throw new AccessDeniedException("Key", request.getKey());
        }
        AccessControlListType accessControlList = accessControlPolicy.getAccessControlList();
        String bucketName = request.getBucket();
        String objectKey = request.getKey();

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo = new BucketInfo(bucketName);
        List<BucketInfo> bucketList = db.query(bucketInfo);

        if (bucketList.size() > 0) {
            BucketInfo bucket = bucketList.get(0);
            BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
            EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
            ObjectInfo searchObjectInfo = new ObjectInfo(bucketName, objectKey);
            if (bucket.isVersioningEnabled()) {
                if (request.getVersionId() == null)
                    searchObjectInfo.setLast(true);
            }
            String versionId = request.getVersionId() != null ? request.getVersionId()
                    : WalrusProperties.NULL_VERSION_ID;
            searchObjectInfo.setVersionId(versionId);
            searchObjectInfo.setDeleted(false);
            List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
            if (objectInfos.size() > 0) {
                ObjectInfo objectInfo = objectInfos.get(0);
                if (!objectInfo.canWriteACP(userId)) {
                    db.rollback();
                    throw new AccessDeniedException("Key", objectKey, logData);
                }
                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
                objectInfo.resetGlobalGrants();
                objectInfo.addGrants(objectInfo.getOwnerId(), grantInfos, accessControlList);
                objectInfo.setGrants(grantInfos);

                if (WalrusProperties.enableTorrents) {
                    if (!objectInfo.isGlobalRead()) {
                        EntityWrapper<TorrentInfo> dbTorrent = db.recast(TorrentInfo.class);
                        TorrentInfo torrentInfo = new TorrentInfo(bucketName, objectKey);
                        List<TorrentInfo> torrentInfos = dbTorrent.query(torrentInfo);
                        if (torrentInfos.size() > 0) {
                            TorrentInfo foundTorrentInfo = torrentInfos.get(0);
                            TorrentClient torrentClient = Torrents.getClient(bucketName + objectKey);
                            if (torrentClient != null) {
                                torrentClient.bye();
                            }
                            dbTorrent.delete(foundTorrentInfo);
                        }
                    }
                } else {
                    LOG.warn("Bittorrent support has been disabled. Please check pre-requisites");
                }
                if (logData != null) {
                    updateLogData(bucket, logData);
                    logData.setObjectSize(objectInfo.getSize());
                    reply.setLogData(logData);
                }
                reply.setCode("204");
                reply.setDescription("OK");
            } else {
                db.rollback();
                throw new NoSuchEntityException(objectKey, logData);
            }
        } else {
            db.rollback();
            throw new NoSuchBucketException(bucketName);
        }
        db.commit();
        return reply;
    }

    public GetObjectResponseType getObject(GetObjectType request, SbxRequest req) throws EucalyptusCloudException {
        GetObjectResponseType reply = (GetObjectResponseType) request.getReply();
        String bucketName = request.getBucket();
        String objectKey = request.getKey();
        String userId = request.getUserId();

        if (Contexts.SBXSVR) {
            try {
                String myaccount = userId;
                String myinstid = request.getMetaInstId();
                WalrusControl.walrusManager.callWalrusHeartBeat(myaccount, myinstid, "GETOBJECT");
            } catch (Throwable t) {
                Log.debug("CSS callWalrusHeartBeat error (getObject) " + "***" + t.toString());
            }
        }

        Boolean deleteAfterGet = request.getDeleteAfterGet();
        if (deleteAfterGet == null)
            deleteAfterGet = false;

        Boolean getTorrent = request.getGetTorrent();
        if (getTorrent == null)
            getTorrent = false;

        Boolean getMetaData = request.getGetMetaData();
        if (getMetaData == null)
            getMetaData = false;

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        try {
            BucketInfo bucketInfo = new BucketInfo(bucketName);
            List<BucketInfo> bucketList = db.query(bucketInfo);

            if (bucketList.size() > 0) {
                BucketInfo bucket = bucketList.get(0);
                BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
                boolean versioning = false;
                if (bucket.isVersioningEnabled())
                    versioning = true;
                EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
                ObjectInfo searchObjectInfo = new ObjectInfo(bucketName, objectKey);
                searchObjectInfo.setVersionId(request.getVersionId());
                searchObjectInfo.setDeleted(false);
                if (request.getVersionId() == null)
                    searchObjectInfo.setLast(true);
                List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
                if (objectInfos.size() > 0) {
                    ObjectInfo objectInfo = objectInfos.get(0);
                    if (objectInfo.canRead(userId)) {
                        String objectName = objectInfo.getObjectName();

                        // check if file is exist
                        File file = new File(storageManager.getObjectPath(bucketName, objectName));
                        if (file.exists() == false) {
                            db.rollback();
                            throw new NoSuchEntityException(objectKey, logData);
                        }
                        DefaultHttpResponse httpResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1,
                                HttpResponseStatus.OK);
                        if (getMetaData) {
                            List<MetaDataInfo> metaDataInfos = objectInfo.getMetaData();
                            for (MetaDataInfo metaDataInfo : metaDataInfos) {
                                httpResponse.addHeader(
                                        WalrusProperties.AMZ_META_HEADER_PREFIX + metaDataInfo.getName(),
                                        metaDataInfo.getValue());
                            }
                        }

                        // added by keanu 20120709, add obj-seq metadata for each object
                        try {
                            httpResponse.addHeader(WalrusProperties.AMZ_META_HEADER_PREFIX + "obj-seq",
                                    String.valueOf(objectInfo.getObjSeq()));
                        } catch (Throwable t) {
                            LOG.debug("cannot add obj-seq");
                        }

                        if (getTorrent) {
                            if (objectInfo.isGlobalRead()) {
                                if (!WalrusProperties.enableTorrents) {
                                    LOG.warn("Bittorrent support has been disabled. Please check pre-requisites");
                                    throw new AccessDeniedException("Torrents disabled");
                                }
                                EntityWrapper<TorrentInfo> dbTorrent = WalrusControl.getEntityWrapper();
                                TorrentInfo torrentInfo = new TorrentInfo(bucketName, objectKey);
                                TorrentInfo foundTorrentInfo;
                                String absoluteObjectPath = storageManager.getObjectPath(bucketName, objectName);
                                try {
                                    foundTorrentInfo = dbTorrent.getUnique(torrentInfo);
                                } catch (EucalyptusCloudException ex) {
                                    String torrentFile = objectName + ".torrent";
                                    String torrentFilePath = storageManager.getObjectPath(bucketName, torrentFile);
                                    TorrentCreator torrentCreator = new TorrentCreator(absoluteObjectPath,
                                            objectKey, objectName, torrentFilePath,
                                            WalrusProperties.getTrackerUrl());
                                    try {
                                        torrentCreator.create();
                                    } catch (Exception e) {
                                        LOG.error(e);
                                        throw new AccessDeniedException(
                                                "could not create torrent file " + torrentFile);
                                    }
                                    torrentInfo.setTorrentFile(torrentFile);
                                    dbTorrent.add(torrentInfo);
                                    foundTorrentInfo = torrentInfo;
                                }
                                dbTorrent.commit();
                                String torrentFile = foundTorrentInfo.getTorrentFile();
                                String torrentFilePath = storageManager.getObjectPath(bucketName, torrentFile);
                                TorrentClient torrentClient = new TorrentClient(torrentFilePath,
                                        absoluteObjectPath);
                                Torrents.addClient(bucketName + objectKey, torrentClient);
                                torrentClient.start();
                                // send torrent
                                String key = bucketName + "." + objectKey;
                                String randomKey = key + "." + Hashes.getRandom(10);
                                request.setRandomKey(randomKey);

                                File torrent = new File(torrentFilePath);
                                if (torrent.exists()) {
                                    Date lastModified = objectInfo.getLastModified();
                                    db.commit();
                                    long torrentLength = torrent.length();
                                    if (logData != null) {
                                        updateLogData(bucket, logData);
                                        logData.setObjectSize(torrentLength);
                                    }
                                    storageManager.sendObject(request, httpResponse, bucketName, torrentFile,
                                            torrentLength, null,
                                            DateUtils.format(lastModified.getTime(),
                                                    DateUtils.ISO8601_DATETIME_PATTERN) + ".000Z",
                                            "application/x-bittorrent",
                                            "attachment; filename=" + objectKey + ".torrent;",
                                            request.getIsCompressed(), null, logData);
                                    if (WalrusProperties.trackUsageStatistics) {
                                        walrusStatistics.updateBytesOut(torrentLength);
                                    }
                                    return null;
                                } else {
                                    db.rollback();
                                    String errorString = "Could not get torrent file " + torrentFilePath;
                                    LOG.error(errorString);
                                    throw new AccessDeniedException(errorString);
                                }
                            } else {
                                db.rollback();
                                throw new AccessDeniedException("Key", objectKey, logData);
                            }
                        }
                        Date lastModified = objectInfo.getLastModified();
                        Long size = objectInfo.getSize();
                        if (req != null) {
                            req.content_length = size;
                        }
                        String etag = objectInfo.getEtag();
                        String contentType = objectInfo.getContentType();
                        String contentDisposition = objectInfo.getContentDisposition();
                        db.commit();
                        if (logData != null) {
                            updateLogData(bucket, logData);
                            logData.setObjectSize(size);
                        }
                        String versionId = null;
                        if (versioning) {
                            versionId = objectInfo.getVersionId();
                        }
                        if (request.getGetData()) {
                            if (request.getInlineData()) {
                                if ((size * 4) > WalrusProperties.MAX_INLINE_DATA_SIZE) {
                                    throw new InlineDataTooLargeException(bucketName + "/" + objectKey);
                                }
                                byte[] bytes = new byte[102400];
                                int bytesRead = 0, offset = 0;
                                String base64Data = "";
                                FileIO fileIO = null;
                                try {
                                    fileIO = storageManager.prepareForRead(bucketName, objectName);
                                    while ((bytesRead = fileIO.read(offset)) > 0) {
                                        ByteBuffer buffer = fileIO.getBuffer();
                                        if (buffer != null) {
                                            buffer.get(bytes, 0, bytesRead);
                                            base64Data += new String(bytes, 0, bytesRead);
                                            offset += bytesRead;
                                        }
                                    }
                                    fileIO.finish();
                                } catch (Exception e) {
                                    LOG.error(e, e);
                                    throw new AccessDeniedException(e);
                                } finally {
                                    if (fileIO != null)
                                        fileIO.finish();
                                }
                                reply.setBase64Data(Hashes.base64encode(base64Data));
                            } else {
                                // support for large objects
                                if (WalrusProperties.trackUsageStatistics) {
                                    walrusStatistics.updateBytesOut(objectInfo.getSize());
                                }
                                storageManager.sendObject(request, httpResponse, bucketName, objectName, size, etag,
                                        DateUtils.format(lastModified.getTime(), DateUtils.ISO8601_DATETIME_PATTERN)
                                                + ".000Z",
                                        contentType, contentDisposition, request.getIsCompressed(), versionId,
                                        logData);
                                return null;
                            }
                        } else {
                            storageManager.sendHeaders(request, httpResponse, size, etag,
                                    DateUtils.format(lastModified.getTime(), DateUtils.ISO8601_DATETIME_PATTERN)
                                            + ".000Z",
                                    contentType, contentDisposition, versionId, logData);
                            return null;

                        }
                        reply.setEtag(etag);
                        reply.setLastModified(
                                DateUtils.format(lastModified, DateUtils.ISO8601_DATETIME_PATTERN) + ".000Z");
                        reply.setSize(size);
                        reply.setContentType(contentType);
                        reply.setContentDisposition(contentDisposition);
                        Status status = new Status();
                        status.setCode(200);
                        status.setDescription("OK");
                        reply.setStatus(status);
                        return reply;
                    } else {
                        db.rollback();
                        throw new AccessDeniedException("Key", objectKey, logData);
                    }
                } else {
                    db.rollback();
                    throw new NoSuchEntityException(objectKey, logData);
                }
            } else {
                db.rollback();
                throw new NoSuchBucketException(bucketName);
            }
        } catch (AccessDeniedException t) {
            throw t;
        } catch (NoSuchEntityException t) {
            throw t;
        } catch (NoSuchBucketException t) {
            throw t;
        } catch (Throwable t) {
            db.rollback();
            throw new AccessDeniedException("CssError",
                    userId + ":" + bucketName + ":" + objectKey + "***" + t.toString(), true);
        }
    }

    public GetObjectResponseType getObject(GetObjectType request) throws EucalyptusCloudException {
        return getObject(request, null);
    }

    public GetObjectExtendedResponseType getObjectExtended(GetObjectExtendedType request)
            throws EucalyptusCloudException {
        GetObjectExtendedResponseType reply = (GetObjectExtendedResponseType) request.getReply();
        Long byteRangeStart = request.getByteRangeStart();
        if (byteRangeStart == null) {
            byteRangeStart = 0L;
        }
        Long byteRangeEnd = request.getByteRangeEnd();
        if (byteRangeEnd == null) {
            byteRangeEnd = -1L;
        }
        Date ifModifiedSince = request.getIfModifiedSince();
        Date ifUnmodifiedSince = request.getIfUnmodifiedSince();
        String ifMatch = request.getIfMatch();
        String ifNoneMatch = request.getIfNoneMatch();
        boolean returnCompleteObjectOnFailure = request.getReturnCompleteObjectOnConditionFailure();

        String bucketName = request.getBucket();
        String objectKey = request.getKey();
        String userId = request.getUserId();
        Status status = new Status();

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo = new BucketInfo(bucketName);
        List<BucketInfo> bucketList = db.query(bucketInfo);

        if (bucketList.size() > 0) {
            BucketInfo bucket = bucketList.get(0);
            BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
            boolean versioning = false;
            if (bucket.isVersioningEnabled())
                versioning = true;
            EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
            ObjectInfo searchObjectInfo = new ObjectInfo(bucketName, objectKey);
            List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
            if (objectInfos.size() > 0) {
                ObjectInfo objectInfo = objectInfos.get(0);

                if (objectInfo.canRead(userId)) {
                    String etag = objectInfo.getEtag();
                    String objectName = objectInfo.getObjectName();
                    if (byteRangeEnd == -1)
                        byteRangeEnd = objectInfo.getSize();
                    if ((byteRangeStart > objectInfo.getSize()) || (byteRangeStart > byteRangeEnd)
                            || (byteRangeEnd > objectInfo.getSize()) || (byteRangeStart < 0 || byteRangeEnd < 0)) {
                        throw new InvalidRangeException("Range: " + byteRangeStart + "-" + byteRangeEnd + "object: "
                                + bucketName + "/" + objectKey);
                    }
                    DefaultHttpResponse httpResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1,
                            HttpResponseStatus.OK);
                    if (ifMatch != null) {
                        if (!ifMatch.equals(etag) && !returnCompleteObjectOnFailure) {
                            db.rollback();
                            throw new PreconditionFailedException(objectKey + " etag: " + etag);
                        }

                    }
                    if (ifNoneMatch != null) {
                        if (ifNoneMatch.equals(etag) && !returnCompleteObjectOnFailure) {
                            db.rollback();
                            throw new NotModifiedException(objectKey + " ETag: " + etag);
                        }
                    }
                    Date lastModified = objectInfo.getLastModified();
                    if (ifModifiedSince != null) {
                        if ((ifModifiedSince.getTime() >= lastModified.getTime())
                                && !returnCompleteObjectOnFailure) {
                            db.rollback();
                            throw new NotModifiedException(objectKey + " LastModified: " + lastModified.toString());
                        }
                    }
                    if (ifUnmodifiedSince != null) {
                        if ((ifUnmodifiedSince.getTime() < lastModified.getTime())
                                && !returnCompleteObjectOnFailure) {
                            db.rollback();
                            throw new PreconditionFailedException(
                                    objectKey + " lastModified: " + lastModified.toString());
                        }
                    }
                    if (request.getGetMetaData()) {
                        List<MetaDataInfo> metaDataInfos = objectInfo.getMetaData();
                        for (MetaDataInfo metaDataInfo : metaDataInfos) {
                            httpResponse.addHeader(WalrusProperties.AMZ_META_HEADER_PREFIX + metaDataInfo.getName(),
                                    metaDataInfo.getValue());
                        }
                    }
                    Long size = objectInfo.getSize();
                    String contentType = objectInfo.getContentType();
                    String contentDisposition = objectInfo.getContentDisposition();
                    db.commit();
                    if (logData != null) {
                        updateLogData(bucket, logData);
                        logData.setObjectSize(size);
                    }
                    String versionId = null;
                    if (versioning) {
                        versionId = objectInfo.getVersionId() != null ? objectInfo.getVersionId()
                                : WalrusProperties.NULL_VERSION_ID;
                    }
                    if (request.getGetData()) {
                        if (WalrusProperties.trackUsageStatistics) {
                            walrusStatistics.updateBytesOut(size);
                        }
                        storageManager.sendObject(request, httpResponse, bucketName, objectName, byteRangeStart,
                                byteRangeEnd, size, etag,
                                DateUtils.format(lastModified.getTime(),
                                        DateUtils.ISO8601_DATETIME_PATTERN + ".000Z"),
                                contentType, contentDisposition, request.getIsCompressed(), versionId, logData);
                        return null;
                    } else {
                        storageManager.sendHeaders(request, httpResponse, size, etag,
                                DateUtils.format(lastModified.getTime(),
                                        DateUtils.ISO8601_DATETIME_PATTERN + ".000Z"),
                                contentType, contentDisposition, versionId, logData);
                        return null;
                    }
                } else {
                    db.rollback();
                    throw new AccessDeniedException("Key", objectKey);
                }
            } else {
                db.rollback();
                throw new NoSuchEntityException(objectKey);
            }
        } else {
            db.rollback();
            throw new NoSuchBucketException(bucketName);
        }
    }

    public GetBucketLocationResponseType getBucketLocation(GetBucketLocationType request)
            throws EucalyptusCloudException {
        GetBucketLocationResponseType reply = (GetBucketLocationResponseType) request.getReply();
        String bucketName = request.getBucket();
        String userId = request.getUserId();

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo = new BucketInfo(bucketName);
        List<BucketInfo> bucketList = db.query(bucketInfo);

        if (bucketList.size() > 0) {
            BucketInfo bucket = bucketList.get(0);
            BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
            if (bucket.canRead(userId)) {
                if (logData != null) {
                    updateLogData(bucket, logData);
                    reply.setLogData(logData);
                }
                String location = bucket.getLocation();
                if (location == null) {
                    location = "NotSupported";
                }
                reply.setLocationConstraint(location);
            } else {
                db.rollback();
                throw new AccessDeniedException("Bucket", bucketName, logData);
            }
        } else {
            db.rollback();
            throw new NoSuchBucketException(bucketName);
        }
        db.commit();
        return reply;
    }

    public CopyObjectResponseType copyObject(CopyObjectType request) throws EucalyptusCloudException {
        CopyObjectResponseType reply = (CopyObjectResponseType) request.getReply();
        String userId = request.getUserId();
        String sourceBucket = request.getSourceBucket();
        String sourceKey = request.getSourceObject();
        String sourceVersionId = request.getSourceVersionId();
        String destinationBucket = request.getDestinationBucket();
        String destinationKey = request.getDestinationObject();
        String metadataDirective = request.getMetadataDirective();
        AccessControlListType accessControlList = request.getAccessControlList();

        String copyIfMatch = request.getCopySourceIfMatch();
        String copyIfNoneMatch = request.getCopySourceIfNoneMatch();
        Date copyIfUnmodifiedSince = request.getCopySourceIfUnmodifiedSince();
        Date copyIfModifiedSince = request.getCopySourceIfModifiedSince();

        if (metadataDirective == null)
            metadataDirective = "COPY";
        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo = new BucketInfo(sourceBucket);
        List<BucketInfo> bucketList = db.query(bucketInfo);

        if (bucketList.size() > 0) {
            EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
            ObjectInfo searchObjectInfo = new ObjectInfo(sourceBucket, sourceKey);
            searchObjectInfo.setVersionId(sourceVersionId);
            if (sourceVersionId == null)
                searchObjectInfo.setLast(true);
            List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
            if (objectInfos.size() > 0) {
                ObjectInfo sourceObjectInfo = objectInfos.get(0);
                if (sourceObjectInfo.canRead(userId)) {
                    if (copyIfMatch != null) {
                        if (!copyIfMatch.equals(sourceObjectInfo.getEtag())) {
                            db.rollback();
                            throw new PreconditionFailedException(sourceKey + " CopySourceIfMatch: " + copyIfMatch);
                        }
                    }
                    if (copyIfNoneMatch != null) {
                        if (copyIfNoneMatch.equals(sourceObjectInfo.getEtag())) {
                            db.rollback();
                            throw new PreconditionFailedException(
                                    sourceKey + " CopySourceIfNoneMatch: " + copyIfNoneMatch);
                        }
                    }
                    if (copyIfUnmodifiedSince != null) {
                        long unmodifiedTime = copyIfUnmodifiedSince.getTime();
                        long objectTime = sourceObjectInfo.getLastModified().getTime();
                        if (unmodifiedTime < objectTime) {
                            db.rollback();
                            throw new PreconditionFailedException(sourceKey + " CopySourceIfUnmodifiedSince: "
                                    + copyIfUnmodifiedSince.toString());
                        }
                    }
                    if (copyIfModifiedSince != null) {
                        long modifiedTime = copyIfModifiedSince.getTime();
                        long objectTime = sourceObjectInfo.getLastModified().getTime();
                        if (modifiedTime > objectTime) {
                            db.rollback();
                            throw new PreconditionFailedException(
                                    sourceKey + " CopySourceIfModifiedSince: " + copyIfModifiedSince.toString());
                        }
                    }
                    BucketInfo destinationBucketInfo = new BucketInfo(destinationBucket);
                    List<BucketInfo> destinationBuckets = db.query(destinationBucketInfo);
                    if (destinationBuckets.size() > 0) {
                        BucketInfo foundDestinationBucketInfo = destinationBuckets.get(0);
                        if (foundDestinationBucketInfo.canWrite(userId)) {
                            // all ok
                            String destinationVersionId = sourceVersionId;
                            ObjectInfo destinationObjectInfo = null;
                            String destinationObjectName;
                            ObjectInfo destSearchObjectInfo = new ObjectInfo(destinationBucket, destinationKey);
                            if (foundDestinationBucketInfo.isVersioningEnabled()) {
                                if (sourceVersionId != null)
                                    destinationVersionId = sourceVersionId;
                                else
                                    destinationVersionId = UUID.randomUUID().toString().replaceAll("-", "");
                            } else {
                                destinationVersionId = WalrusProperties.NULL_VERSION_ID;
                            }
                            destSearchObjectInfo.setVersionId(destinationVersionId);
                            List<ObjectInfo> destinationObjectInfos = dbObject.query(destSearchObjectInfo);
                            if (destinationObjectInfos.size() > 0) {
                                destinationObjectInfo = destinationObjectInfos.get(0);
                                if (!destinationObjectInfo.canWrite(userId)) {
                                    db.rollback();
                                    throw new AccessDeniedException("Key", destinationKey);
                                }
                            }
                            boolean addNew = false;
                            if (destinationObjectInfo == null) {
                                // not found. create a new one
                                addNew = true;
                                destinationObjectInfo = new ObjectInfo();
                                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
                                destinationObjectInfo.setBucketName(destinationBucket);
                                destinationObjectInfo.setObjectKey(destinationKey);
                                destinationObjectInfo.addGrants(userId, grantInfos, accessControlList);
                                destinationObjectInfo.setGrants(grantInfos);
                                destinationObjectInfo.setObjectName(UUID.randomUUID().toString());
                            } else {
                                if (destinationObjectInfo.canWriteACP(userId)) {
                                    List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
                                    destinationObjectInfo.addGrants(userId, grantInfos, accessControlList);
                                    destinationObjectInfo.setGrants(grantInfos);
                                }
                            }
                            destinationObjectInfo.setSize(sourceObjectInfo.getSize());
                            destinationObjectInfo.setStorageClass(sourceObjectInfo.getStorageClass());
                            destinationObjectInfo.setOwnerId(sourceObjectInfo.getOwnerId());
                            destinationObjectInfo.setContentType(sourceObjectInfo.getContentType());
                            destinationObjectInfo.setContentDisposition(sourceObjectInfo.getContentDisposition());
                            String etag = sourceObjectInfo.getEtag();
                            Date lastModified = sourceObjectInfo.getLastModified();
                            destinationObjectInfo.setEtag(etag);
                            destinationObjectInfo.setLastModified(lastModified);
                            destinationObjectInfo.setVersionId(destinationVersionId);
                            destinationObjectInfo.setLast(true);
                            destinationObjectInfo.setDeleted(false);
                            if (!metadataDirective.equals("REPLACE")) {
                                destinationObjectInfo.setMetaData(sourceObjectInfo.cloneMetaData());
                            } else {
                                List<MetaDataEntry> metaData = request.getMetaData();
                                if (metaData != null)
                                    destinationObjectInfo.replaceMetaData(metaData);
                            }

                            String sourceObjectName = sourceObjectInfo.getObjectName();
                            destinationObjectName = destinationObjectInfo.getObjectName();

                            try {
                                storageManager.copyObject(sourceBucket, sourceObjectName, destinationBucket,
                                        destinationObjectName);
                                if (WalrusProperties.trackUsageStatistics)
                                    walrusStatistics.updateSpaceUsed(sourceObjectInfo.getSize());
                            } catch (Exception ex) {
                                LOG.error(ex);
                                db.rollback();
                                throw new EucalyptusCloudException(
                                        "Could not rename " + sourceObjectName + " to " + destinationObjectName);
                            }
                            if (addNew)
                                dbObject.add(destinationObjectInfo);

                            // get rid of delete marker
                            ObjectInfo deleteMarker = new ObjectInfo(destinationBucket, destinationKey);
                            deleteMarker.setDeleted(true);
                            try {
                                ObjectInfo foundDeleteMarker = dbObject.getUnique(deleteMarker);
                                dbObject.delete(foundDeleteMarker);
                            } catch (EucalyptusCloudException ex) {
                                // no delete marker found.
                                LOG.trace(
                                        "No delete marker found for: " + destinationBucket + "/" + destinationKey);
                            }

                            reply.setEtag(etag);
                            reply.setLastModified(
                                    DateUtils.format(lastModified.getTime(), DateUtils.ISO8601_DATETIME_PATTERN)
                                            + ".000Z");

                            if (foundDestinationBucketInfo.isVersioningEnabled()) {
                                reply.setCopySourceVersionId(sourceVersionId);
                                reply.setVersionId(destinationVersionId);
                            }
                            db.commit();
                            return reply;
                        } else {
                            db.rollback();
                            throw new AccessDeniedException("Bucket", destinationBucket);
                        }
                    } else {
                        db.rollback();
                        throw new NoSuchBucketException(destinationBucket);
                    }
                } else {
                    db.rollback();
                    throw new AccessDeniedException("Key", sourceKey);
                }
            } else {
                db.rollback();
                throw new NoSuchEntityException(sourceKey);
            }
        } else {
            db.rollback();
            throw new NoSuchBucketException(sourceBucket);
        }
    }

    public SetBucketLoggingStatusResponseType setBucketLoggingStatus(SetBucketLoggingStatusType request)
            throws EucalyptusCloudException {
        SetBucketLoggingStatusResponseType reply = (SetBucketLoggingStatusResponseType) request.getReply();
        String bucket = request.getBucket();

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo, targetBucketInfo;
        try {
            bucketInfo = db.getUnique(new BucketInfo(bucket));
        } catch (EucalyptusCloudException ex) {
            db.rollback();
            throw new NoSuchBucketException(bucket);
        }

        if (request.getLoggingEnabled() != null) {
            String targetBucket = request.getLoggingEnabled().getTargetBucket();
            String targetPrefix = request.getLoggingEnabled().getTargetPrefix();
            List<Grant> targetGrantsList = null;
            TargetGrants targetGrants = request.getLoggingEnabled().getTargetGrants();
            if (targetGrants != null)
                targetGrantsList = targetGrants.getGrants();
            if (targetPrefix == null)
                targetPrefix = "";
            try {
                targetBucketInfo = db.getUnique(new BucketInfo(targetBucket));
            } catch (EucalyptusCloudException ex) {
                db.rollback();
                throw new NoSuchBucketException(targetBucket);
            }
            if (!targetBucketInfo.hasLoggingPerms()) {
                db.rollback();
                throw new InvalidTargetBucketForLoggingException(targetBucket);
            }
            bucketInfo.setTargetBucket(targetBucket);
            bucketInfo.setTargetPrefix(targetPrefix);
            bucketInfo.setLoggingEnabled(true);
            if (targetGrantsList != null) {
                targetBucketInfo.addGrants(targetGrantsList);
            }
        } else {
            bucketInfo.setLoggingEnabled(false);
        }
        db.commit();
        return reply;
    }

    public GetBucketLoggingStatusResponseType getBucketLoggingStatus(GetBucketLoggingStatusType request)
            throws EucalyptusCloudException {
        GetBucketLoggingStatusResponseType reply = (GetBucketLoggingStatusResponseType) request.getReply();
        String bucket = request.getBucket();

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        try {
            BucketInfo bucketInfo = db.getUnique(new BucketInfo(bucket));
            if (bucketInfo.getLoggingEnabled()) {
                String targetBucket = bucketInfo.getTargetBucket();
                ArrayList<Grant> grants = new ArrayList<Grant>();
                try {
                    BucketInfo targetBucketInfo = db.getUnique(new BucketInfo(targetBucket));
                    List<GrantInfo> grantInfos = targetBucketInfo.getGrants();
                    for (GrantInfo grantInfo : grantInfos) {
                        String uId = grantInfo.getUserId();
                        try {
                            if (uId != null) {
                                User grantUserInfo = Users.lookupUser(uId);
                                addPermission(grants, grantUserInfo, grantInfo);
                            } else {
                                addPermission(grants, grantInfo);
                            }
                        } catch (NoSuchUserException e) {
                            db.rollback();
                            throw new AccessDeniedException("Bucket", targetBucket);
                        }
                    }
                } catch (EucalyptusCloudException ex) {
                    db.rollback();
                    throw new InvalidTargetBucketForLoggingException(targetBucket);
                }
                LoggingEnabled loggingEnabled = new LoggingEnabled();
                loggingEnabled.setTargetBucket(bucketInfo.getTargetBucket());
                loggingEnabled.setTargetPrefix(bucketInfo.getTargetPrefix());

                TargetGrants targetGrants = new TargetGrants();
                targetGrants.setGrants(grants);
                loggingEnabled.setTargetGrants(targetGrants);
                reply.setLoggingEnabled(loggingEnabled);
            }
        } catch (EucalyptusCloudException ex) {
            db.rollback();
            throw new NoSuchBucketException(bucket);
        }
        db.commit();
        return reply;
    }

    private void updateLogData(BucketInfo bucket, BucketLogData logData) {
        logData.setOwnerId(bucket.getOwnerId());
        logData.setTargetBucket(bucket.getTargetBucket());
        logData.setTargetPrefix(bucket.getTargetPrefix());
    }

    public GetBucketVersioningStatusResponseType getBucketVersioningStatus(GetBucketVersioningStatusType request)
            throws EucalyptusCloudException {
        GetBucketVersioningStatusResponseType reply = (GetBucketVersioningStatusResponseType) request.getReply();
        String bucket = request.getBucket();

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        try {
            BucketInfo bucketInfo = db.getUnique(new BucketInfo(bucket));
            if (bucketInfo.getVersioning() != null) {
                String status = bucketInfo.getVersioning();
                if (WalrusProperties.VersioningStatus.Disabled.toString().equals(status))
                    reply.setVersioningStatus(WalrusProperties.VersioningStatus.Suspended.toString());
                else
                    reply.setVersioningStatus(status);
            }
        } catch (EucalyptusCloudException ex) {
            db.rollback();
            throw new NoSuchBucketException(bucket);
        }
        db.commit();
        return reply;
    }

    public SetBucketVersioningStatusResponseType setBucketVersioningStatus(SetBucketVersioningStatusType request)
            throws EucalyptusCloudException {
        SetBucketVersioningStatusResponseType reply = (SetBucketVersioningStatusResponseType) request.getReply();
        String bucket = request.getBucket();

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo;
        try {
            bucketInfo = db.getUnique(new BucketInfo(bucket));
        } catch (EucalyptusCloudException ex) {
            db.rollback();
            throw new NoSuchBucketException(bucket);
        }

        if (request.getVersioningStatus() != null) {
            String status = request.getVersioningStatus();
            if (WalrusProperties.VersioningStatus.Enabled.toString().equals(status))
                bucketInfo.setVersioning(WalrusProperties.VersioningStatus.Enabled.toString());
            else if (WalrusProperties.VersioningStatus.Suspended.toString().equals(status)
                    && WalrusProperties.VersioningStatus.Enabled.toString().equals(bucketInfo.getVersioning()))
                bucketInfo.setVersioning(WalrusProperties.VersioningStatus.Suspended.toString());
        }
        db.commit();
        return reply;
    }

    public ListVersionsResponseType listVersions(ListVersionsType request) throws EucalyptusCloudException {
        ListVersionsResponseType reply = (ListVersionsResponseType) request.getReply();
        String bucketName = request.getBucket();
        String userId = request.getUserId();
        String prefix = request.getPrefix();
        if (prefix == null)
            prefix = "";

        String keyMarker = request.getKeyMarker();
        String versionIdMarker = request.getVersionIdMarker();

        int maxKeys = -1;
        String maxKeysString = request.getMaxKeys();
        if (maxKeysString != null)
            maxKeys = Integer.parseInt(maxKeysString);
        else
            maxKeys = WalrusProperties.MAX_KEYS;

        String delimiter = request.getDelimiter();

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfo = new BucketInfo(bucketName);
        bucketInfo.setHidden(false);
        List<BucketInfo> bucketList = db.query(bucketInfo);

        ArrayList<PrefixEntry> prefixes = new ArrayList<PrefixEntry>();

        if (bucketList.size() > 0) {
            BucketInfo bucket = bucketList.get(0);
            BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
            if (bucket.canRead(userId)) {
                if (bucket.isVersioningDisabled()) {
                    db.rollback();
                    throw new EucalyptusCloudException("Versioning has not been enabled for bucket: " + bucketName);
                }
                if (logData != null) {
                    updateLogData(bucket, logData);
                    reply.setLogData(logData);
                }
                if (request.isAdministrator()) {
                    EntityWrapper<WalrusSnapshotInfo> dbSnap = db.recast(WalrusSnapshotInfo.class);
                    WalrusSnapshotInfo walrusSnapInfo = new WalrusSnapshotInfo();
                    walrusSnapInfo.setSnapshotBucket(bucketName);
                    List<WalrusSnapshotInfo> walrusSnaps = dbSnap.query(walrusSnapInfo);
                    if (walrusSnaps.size() > 0) {
                        db.rollback();
                        throw new NoSuchBucketException(bucketName);
                    }
                }
                reply.setName(bucketName);
                reply.setIsTruncated(false);
                if (maxKeys >= 0)
                    reply.setMaxKeys(maxKeys);
                reply.setPrefix(prefix);
                reply.setKeyMarker(keyMarker);
                reply.setVersionIdMarker(versionIdMarker);
                if (delimiter != null)
                    reply.setDelimiter(delimiter);
                EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
                ObjectInfo searchObjectInfo = new ObjectInfo();
                searchObjectInfo.setBucketName(bucketName);
                List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
                if (objectInfos.size() > 0) {
                    int howManyProcessed = 0;
                    if (keyMarker != null || objectInfos.size() < maxKeys)
                        Collections.sort(objectInfos);
                    ArrayList<VersionEntry> versions = new ArrayList<VersionEntry>();
                    ArrayList<DeleteMarkerEntry> deleteMarkers = new ArrayList<DeleteMarkerEntry>();

                    for (ObjectInfo objectInfo : objectInfos) {
                        String objectKey = objectInfo.getObjectKey();

                        if (keyMarker != null) {
                            if (objectKey.compareTo(keyMarker) <= 0)
                                continue;
                        } else if (versionIdMarker != null) {
                            if (!objectInfo.getVersionId().equals(versionIdMarker))
                                continue;
                        }

                        if (prefix != null) {
                            if (!objectKey.startsWith(prefix)) {
                                continue;
                            } else {
                                if (delimiter != null) {
                                    String[] parts = objectKey.substring(prefix.length()).split(delimiter);
                                    if (parts.length > 1) {
                                        String prefixString = parts[0] + delimiter;
                                        boolean foundPrefix = false;
                                        for (PrefixEntry prefixEntry : prefixes) {
                                            if (prefixEntry.getPrefix().equals(prefixString)) {
                                                foundPrefix = true;
                                                break;
                                            }
                                        }
                                        if (!foundPrefix) {
                                            prefixes.add(new PrefixEntry(prefixString));
                                            if (maxKeys >= 0) {
                                                if (howManyProcessed++ >= maxKeys) {
                                                    reply.setIsTruncated(true);
                                                    break;
                                                }
                                            }
                                        }
                                        continue;
                                    }
                                }
                            }
                        }
                        if (maxKeys >= 0) {
                            if (howManyProcessed++ >= maxKeys) {
                                reply.setIsTruncated(true);
                                break;
                            }
                        }
                        if (!objectInfo.getDeleted()) {
                            VersionEntry versionEntry = new VersionEntry();
                            versionEntry.setKey(objectKey);
                            versionEntry.setVersionId(objectInfo.getVersionId());
                            versionEntry.setEtag(objectInfo.getEtag());
                            versionEntry.setLastModified(DateUtils.format(objectInfo.getLastModified().getTime(),
                                    DateUtils.ISO8601_DATETIME_PATTERN) + ".000Z");
                            String displayName = objectInfo.getOwnerId();
                            try {
                                User userInfo = Users.lookupUser(displayName);
                                versionEntry.setOwner(new CanonicalUserType(userInfo.getQueryId(), displayName));
                            } catch (NoSuchUserException e) {
                                db.rollback();
                                throw new AccessDeniedException("Bucket", bucketName, logData);
                            }
                            versionEntry.setSize(objectInfo.getSize());
                            versionEntry.setStorageClass(objectInfo.getStorageClass());
                            versionEntry.setIsLatest(objectInfo.getLast());
                            versions.add(versionEntry);
                        } else {
                            DeleteMarkerEntry deleteMarkerEntry = new DeleteMarkerEntry();
                            deleteMarkerEntry.setKey(objectKey);
                            deleteMarkerEntry.setVersionId(objectInfo.getVersionId());
                            deleteMarkerEntry
                                    .setLastModified(DateUtils.format(objectInfo.getLastModified().getTime(),
                                            DateUtils.ISO8601_DATETIME_PATTERN) + ".000Z");
                            String displayName = objectInfo.getOwnerId();
                            try {
                                User userInfo = Users.lookupUser(displayName);
                                deleteMarkerEntry
                                        .setOwner(new CanonicalUserType(userInfo.getQueryId(), displayName));
                            } catch (NoSuchUserException e) {
                                db.rollback();
                                throw new AccessDeniedException("Bucket", bucketName, logData);
                            }
                            deleteMarkerEntry.setIsLatest(objectInfo.getLast());
                            deleteMarkers.add(deleteMarkerEntry);
                        }
                    }
                    reply.setVersions(versions);
                    reply.setDeleteMarkers(deleteMarkers);
                    if (prefix != null) {
                        reply.setCommonPrefixes(prefixes);
                    }
                }
            } else {
                db.rollback();
                throw new AccessDeniedException("Bucket", bucketName, logData);
            }
        } else {
            db.rollback();
            throw new NoSuchBucketException(bucketName);
        }
        db.commit();
        return reply;
    }

    public DeleteVersionResponseType deleteVersion(DeleteVersionType request) throws EucalyptusCloudException {
        DeleteVersionResponseType reply = (DeleteVersionResponseType) request.getReply();
        String bucketName = request.getBucket();
        String objectKey = request.getKey();
        String userId = request.getUserId();

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        BucketInfo bucketInfos = new BucketInfo(bucketName);
        List<BucketInfo> bucketList = db.query(bucketInfos);

        if (bucketList.size() > 0) {
            BucketInfo bucketInfo = bucketList.get(0);
            BucketLogData logData = bucketInfo.getLoggingEnabled() ? request.getLogData() : null;
            ObjectInfo foundObject = null;
            EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
            ObjectInfo searchObjectInfo = new ObjectInfo(bucketName, objectKey);
            if (request.getVersionid() == null) {
                db.rollback();
                throw new EucalyptusCloudException("versionId is null");
            }
            searchObjectInfo.setVersionId(request.getVersionid());
            List<ObjectInfo> objectInfos = dbObject.query(searchObjectInfo);
            if (objectInfos.size() > 0) {
                foundObject = objectInfos.get(0);
            }

            if (foundObject != null) {
                if (foundObject.canWrite(userId)) {
                    dbObject.delete(foundObject);
                    if (!foundObject.getDeleted()) {
                        String objectName = foundObject.getObjectName();
                        for (GrantInfo grantInfo : foundObject.getGrants()) {
                            db.getEntityManager().remove(grantInfo);
                        }
                        Long size = foundObject.getSize();
                        bucketInfo.setBucketSize(bucketInfo.getBucketSize() - size);
                        ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, objectName, size);
                        objectDeleter.start();
                    }
                    reply.setCode("200");
                    reply.setDescription("OK");
                    if (logData != null) {
                        updateLogData(bucketInfo, logData);
                        reply.setLogData(logData);
                    }
                } else {
                    db.rollback();
                    throw new AccessDeniedException("Key", objectKey, logData);
                }
            } else {
                db.rollback();
                throw new NoSuchEntityException(objectKey, logData);
            }
        } else {
            db.rollback();
            throw new NoSuchBucketException(bucketName);
        }
        db.commit();
        return reply;
    }

    // Refactorred PutObject
    public PutObjectResponseType putObjectRefactor(PutObjectType request) throws EucalyptusCloudException {
        //call renameObject
        if (request.getRenameto() != null) {
            return this.renameObject(request, null);
        }

        //do putObject
        PutObjectResponseType reply = (PutObjectResponseType) request.getReply();
        String userId = request.getUserId();
        String bucketName = request.getBucket();
        String objectKey = request.getKey();

        //get channel
        Channel channel = null;
        try {
            channel = Contexts.lookup(request.getCorrelationId()).getChannel();
        } catch (Throwable t) {
            Log.debug(userId + ":" + bucketName + ":" + objectKey + "***" + "Error get channel" + "***"
                    + t.toString());
            throw new AccessDeniedException("GetChannelError",
                    userId + ":" + bucketName + ":" + objectKey + "***" + "Error get channel", true);
        }

        long syncid = -1;
        long mtime = 0;
        if (Contexts.SBXSVR) {
            //get sync id before putObject
            try {
                syncid = this.getSyncId(request.getMetaClientType(), userId);
                // syncid must LOCK
                //...
            } catch (AccessDeniedException ex) {
                Log.debug(userId + ":" + bucketName + ":" + objectKey + "***" + "Error get syncid" + "***"
                        + ex.toString());
                throw ex;
            } catch (Throwable t) {
                Log.debug(userId + ":" + bucketName + ":" + objectKey + "***" + "Error get syncid" + "***"
                        + t.toString());
                throw new AccessDeniedException("GetSyncIdError",
                        userId + ":" + bucketName + ":" + objectKey + "***" + "Error get syncid", true);
            }

            //get mtime before putObject
            try {
                String strModifiedTime = request.getMetaModifiedTime();
                if (strModifiedTime != null && strModifiedTime.isEmpty() == false) {
                    mtime = Long.valueOf(strModifiedTime);
                }
            } catch (Throwable t) {
                Log.debug(userId + ":" + bucketName + ":" + objectKey + "***" + "Error get mtime" + "***"
                        + t.toString());
                throw new AccessDeniedException("GetMtimeError",
                        userId + ":" + bucketName + ":" + objectKey + "***" + "Error get mtime", true);
            }
        }

        int objSeq = -1;
        if (Contexts.SBXSVR) {
            try {
                String rObjSeq = request.getMetaObjSeq();
                if (StringUtils.isNotEmpty(rObjSeq)) {
                    objSeq = Integer.parseInt(rObjSeq);
                }
                if (objSeq != -1) {
                    // compare objSeq with Object's obj-seq
                    int dbObjSeq = SbxDB.getObjSeq(userId, bucketName, objectKey);
                    if (dbObjSeq != -1 && objSeq != dbObjSeq) {
                        throw new AccessDeniedException("GetObjSeq", userId + ":" + bucketName + ":" + objectKey
                                + "#obj-seq are different: " + objSeq + " != " + dbObjSeq, true);
                    }
                }
            } catch (AccessDeniedException t) {
                throw t;
            } catch (Throwable t) {
                throw new AccessDeniedException("GetObjSeq",
                        userId + ":" + bucketName + ":" + objectKey + "***" + t.toString(), true);
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////
        // check bucket and object exist and writable
        ////////////////////////////////////////////////////////////////////////////////////
        Long oldBucketSize = 0L;

        String md5 = "";
        Date lastModified = null;

        AccessControlListType accessControlList = request.getAccessControlList();
        if (accessControlList == null) {
            accessControlList = new AccessControlListType();
        }
        String key = bucketName + "." + objectKey;
        String randomKey = request.getRandomKey();
        WalrusDataMessenger messenger = WalrusRESTBinding.getWriteMessenger();

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        String objectName;
        String versionId = WalrusProperties.NULL_VERSION_ID;
        boolean bAddObject = false;
        BucketLogData logData = null;
        BucketInfo bucket = null;
        try {
            // check if bucket is exist
            BucketInfo bucketInfo = new BucketInfo(bucketName);
            List<BucketInfo> bucketList = db.query(bucketInfo);
            if (bucketList.size() <= 0) {
                db.rollback();
                messenger.removeQueue(key, randomKey);
                throw new NoSuchBucketException(bucketName);
            }

            // check if bucket is writable
            bucket = bucketList.get(0);
            logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
            if (!bucket.canWrite(userId)) {
                db.rollback();
                messenger.removeQueue(key, randomKey);
                throw new AccessDeniedException("Bucket", bucketName, logData);
            }

            // Version is denied
            if (bucket.isVersioningEnabled()) {
                db.rollback();
                messenger.removeQueue(key, randomKey);
                throw new AccessDeniedException("Version is denied", bucketName, logData);
            }

            if (logData != null)
                reply.setLogData(logData);

            EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
            try {
                // To update object
                bAddObject = false;
                ObjectInfo searchObject = new ObjectInfo(bucketName, objectKey);
                searchObject.setVersionId(versionId);
                ObjectInfo foundObject = dbObject.getUnique(searchObject);
                // check if object is writable
                if (!foundObject.canWrite(userId)) {
                    db.rollback();
                    messenger.removeQueue(key, randomKey);
                    throw new AccessDeniedException("Key", objectKey, logData);
                }
                objectName = foundObject.getObjectName();
            } catch (EucalyptusCloudException ex) {
                // To insert object
                bAddObject = true;
                objectName = UUID.randomUUID().toString();
            }

            db.commit();
        } catch (NoSuchBucketException ex) {
            throw ex;
        } catch (AccessDeniedException ex) {
            throw ex;
        } catch (Throwable t) {
            db.rollback();
            messenger.removeQueue(key, randomKey);
            throw new AccessDeniedException("CssError",
                    userId + ":" + bucketName + ":" + objectKey + "***" + t.toString(), true);
        }

        ////////////////////////////////////////////////////////////////////////////////////
        // receive payload
        ////////////////////////////////////////////////////////////////////////////////////
        // writes are unconditional
        WalrusDataQueue<WalrusDataMessage> putQueue = messenger.getQueue(key, randomKey);
        String tempObjectName = UUID.randomUUID().toString() + ".tmp";
        FileIO fileIO = null;
        MessageDigest digest = null;
        long size = 0;
        WalrusDataMessage dataMessage = null;
        try {
            boolean isTimeout = true;
            while ((isTimeout = true)
                    && (dataMessage = putQueue.poll(SbxPutRequest.DATAQUEUE_TIMEOUT, TimeUnit.SECONDS)) != null) {
                isTimeout = false;
                // duplicate put object at a same time
                if (putQueue.getInterrupted()) {
                    if (WalrusDataMessage.isEOF(dataMessage) || WalrusDataMessage.isDisconnected(dataMessage)) {
                        break;
                    }
                    continue;
                }
                if (WalrusDataMessage.isStart(dataMessage)) {
                    digest = Digest.MD5.get();
                    try {
                        fileIO = storageManager.prepareForWrite(bucketName, tempObjectName);
                    } finally {
                        // To garbage collection
                        addPutObjectCallback(null, channel, fileIO, messenger, key, randomKey, putQueue, userId,
                                bucketName, objectKey, tempObjectName);
                    }
                } else if (WalrusDataMessage.isEOF(dataMessage)) {
                    break;
                } else if (WalrusDataMessage.isDisconnected(dataMessage)) {
                    LOG.debug(userId + ":" + bucketName + ":" + objectKey + "***" + "Disconnected Error");
                    messenger.removeQueue(key, randomKey);
                    throw new AccessDeniedException("CssError",
                            userId + ":" + bucketName + ":" + objectKey + "***" + "Disconnected Error", true);
                } else {
                    assert (WalrusDataMessage.isData(dataMessage));
                    byte[] data = dataMessage.getPayload();
                    // start writing object (but do not commit yet)
                    try {
                        if (fileIO != null)
                            fileIO.write(data);
                    } catch (IOException ex) {
                        LOG.error(ex);
                    }
                    // calculate md5 on the fly
                    size += data.length;
                    if (digest != null)
                        digest.update(data);
                }
            } // while
              // pubObject is interrupted (and/or timeout)
            if (putQueue.getInterrupted()) {
                LOG.debug(userId + ":" + bucketName + ":" + objectKey + "***" + "Duplicate putObject Error");
                if (fileIO != null)
                    fileIO.finish();
                ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, tempObjectName, -1L);
                objectDeleter.start();
                messenger.removeQueue(key, randomKey);
                throw new AccessDeniedException("CssError",
                        userId + ":" + bucketName + ":" + objectKey + "***" + "Duplicate putObject Error", true);
            }
            // pubObject is timeout
            if (isTimeout) {
                LOG.debug(userId + ":" + bucketName + ":" + objectKey + "***" + "DataQueue Timeout Error");
                if (fileIO != null)
                    fileIO.finish();
                ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, tempObjectName, -1L);
                objectDeleter.start();
                messenger.removeQueue(key, randomKey);
                throw new CSSException(
                        userId + ":" + bucketName + ":" + objectKey + "***" + "DataQueue Timeout Error");
            }
        } catch (AccessDeniedException ex) {
            throw ex;
        } catch (Throwable t) {
            LOG.debug(userId + ":" + bucketName + ":" + objectKey + "***" + t.toString());
            messenger.removeQueue(key, randomKey);
            throw new AccessDeniedException("CssError",
                    userId + ":" + bucketName + ":" + objectKey + "***" + t.toString(), true);
        } finally {
            if (fileIO != null)
                fileIO.finish();
        }

        ////////////////////////////////////////////////////////////////////////////////////
        // Insert or Update object
        ////////////////////////////////////////////////////////////////////////////////////
        EntityWrapper<ObjectInfo> dbObject = WalrusControl.getEntityWrapper();
        try {
            if (digest != null)
                md5 = Hashes.bytesToHex(digest.digest());
            lastModified = new Date();
            ObjectInfo searchObject = new ObjectInfo(bucketName, objectKey);
            searchObject.setVersionId(versionId);
            List<ObjectInfo> objectInfos = dbObject.query(new ObjectInfo(bucketName, objectKey));
            for (ObjectInfo objInfo : objectInfos) {
                objInfo.setLast(false);
            }
            ObjectInfo foundObject = null;
            ObjectInfo objectInfo = null;
            try {
                // bbAddObject should be false
                foundObject = dbObject.getUnique(searchObject);
                if (foundObject.canWriteACP(userId)) {
                    List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
                    foundObject.addGrants(userId, grantInfos, accessControlList);
                    foundObject.setGrants(grantInfos);
                }
            } catch (EucalyptusCloudException ex) {
                // bbAddObject should be true
                if (bAddObject == false) {
                    // After received payload, the original object is missing (deleted or renamed)
                    dbObject.rollback();
                    ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, tempObjectName, -1L);
                    objectDeleter.start();
                    messenger.removeQueue(key, randomKey);
                    throw new AccessDeniedException("CssError",
                            userId + ":" + bucketName + ":" + objectKey + "***" + "Unable to update object", true);
                }

                objectInfo = new ObjectInfo(bucketName, objectKey);
                objectInfo.setOwnerId(userId);
                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
                objectInfo.addGrants(userId, grantInfos, accessControlList);
                objectInfo.setGrants(grantInfos);
                objectInfo.setObjectName(objectName);
                objectInfo.setSize(0L);
                foundObject = objectInfo;
            }

            if (objSeq == -1) {
                objSeq = 0;
            } else {
                objSeq++;
            }

            foundObject.setVersionId(versionId);
            foundObject.replaceMetaData(request.getMetaData());
            foundObject.setEtag(md5);
            foundObject.setSize(size);
            foundObject.setLastModified(lastModified);
            foundObject.setStorageClass("STANDARD");
            foundObject.setContentType(request.getContentType());
            foundObject.setContentDisposition(request.getContentDisposition());
            foundObject.setLast(true);
            foundObject.setDeleted(false);
            foundObject.setObjSeq(objSeq);
            reply.setSize(size);

            String op = null;
            if (bAddObject) {
                dbObject.add(foundObject);
                op = "Create";
            } else {
                op = "Create";
                //mac: to change op to modify
                // op = "Modify";
            }

            if (Contexts.SBXSVR) {
                String reqid = request.getMetaReqId();
                if (reqid == null)
                    reqid = "null";
                //LOG.debug("CSS writeEvent " + op + "): " + userId+":"+bucketName+":"+objectKey);
                this.writeEvent(dbObject.getEntityManager(), request.getMetaClientType(), userId, op,
                        foundObject.getObjectKey(), foundObject.getSize(),
                        strSBXContentTypeFolder.equals(foundObject.getContentType()), syncid, mtime, reqid, objSeq);
            }

            storageManager.renameObject(bucketName, tempObjectName, objectName);

            dbObject.commit();

            try {
                if (bucket.isVersioningEnabled()) {
                    reply.setVersionId(versionId);
                }
                if (WalrusProperties.trackUsageStatistics) {
                    walrusStatistics.updateBytesIn(size);
                    walrusStatistics.updateSpaceUsed(size);
                }
                if (logData != null) {
                    logData.setObjectSize(size);
                    updateLogData(bucket, logData);
                    logData.setTurnAroundTime(Long.parseLong(new String(dataMessage.getPayload())));
                }
            } catch (Throwable t) {
                LOG.debug("Error Update Info: " + key);
            }

            // restart all interrupted puts
            WalrusMonitor monitor = messenger.getMonitor(key);
            synchronized (monitor) {
                monitor.setLastModified(lastModified);
                monitor.setMd5(md5);
                monitor.notifyAll();
            }
            messenger.removeMonitor(key);
            messenger.removeQueue(key, randomKey);
            LOG.info("Transfer complete: " + key);
        } catch (Throwable t) {
            LOG.debug(userId + ":" + bucketName + ":" + objectKey + "***" + t.toString());
            dbObject.rollback();
            messenger.removeQueue(key, randomKey);
            throw new AccessDeniedException("CssError",
                    userId + ":" + bucketName + ":" + objectKey + "***" + t.toString(), true);
        }

        try {
            reply.setEtag(md5);
            reply.setLastModified(
                    DateUtils.format(lastModified.getTime(), DateUtils.ISO8601_DATETIME_PATTERN) + ".000Z");
        } catch (Throwable t) {
            LOG.debug("Error Set Put Reply: " + key);
        }

        return reply;
    }//refactored putObject

    public void putObjectStage0(PutObjectType request, SbxPutRequest req) throws EucalyptusCloudException {
        /////////////////////////////////////////////////
        // get channel and check Safebox variables
        /////////////////////////////////////////////////
        req.reply = request.getReply();
        String userId = request.getUserId();
        String bucketName = request.getBucket();
        String objectKey = request.getKey();

        //get channel
        try {
            if (req.channel == null && req.channelctx != null) {
                req.channel = req.channelctx.getChannel();
            }
            if (req.channel == null) {
                req.channel = Contexts.getChannel(req);
            }
        } catch (Throwable t) {
            throw new AccessDeniedException("GetChannelError",
                    userId + ":" + bucketName + ":" + objectKey + "***" + "Error get channel", true);
        }

        if (Contexts.SBXSVR) {
            try {
                String myaccount = userId;
                String myinstid = request.getMetaInstId();
                WalrusControl.walrusManager.callWalrusHeartBeat(myaccount, myinstid, "PUTOBJECT");
            } catch (Throwable t) {
                Log.debug("CSS callWalrusHeartBeat error (putObject) " + "***" + t.toString());
            }
        }

        if (Contexts.SBXSVR) {
            //get sync id before putObject
            try {
                req.syncid = this.getSyncId(request.getMetaClientType(), userId);
                // syncid must LOCK (syncid == 0 for mobile and browser)
                if (req.syncid > 0 && req.reqId != null) {
                    if (SbxDB.syncidlock(req.syncid) == false) {
                        throw new AccessDeniedException("GetSyncIdError", userId + ":" + bucketName + ":"
                                + objectKey + "*** syncid=" + req.syncid + " need be locked", true);
                    }
                }
            } catch (AccessDeniedException ex) {
                throw ex;
            } catch (Throwable t) {
                throw new AccessDeniedException("GetSyncIdError",
                        userId + ":" + bucketName + ":" + objectKey + "***" + "Error get syncid", true);
            }

            //get mtime before putObject
            try {
                String strModifiedTime = request.getMetaModifiedTime();
                if (strModifiedTime != null && strModifiedTime.isEmpty() == false) {
                    req.mtime = Long.valueOf(strModifiedTime);
                }
            } catch (Throwable t) {
                throw new AccessDeniedException("GetMtimeError",
                        userId + ":" + bucketName + ":" + objectKey + "***" + "Error get mtime", true);
            }
        }

        int objSeq = -1;
        if (Contexts.SBXSVR) {
            try {
                if (StringUtils.isNotEmpty(req.objSeq)) {
                    objSeq = Integer.parseInt(req.objSeq);
                }
                if (objSeq != -1) {
                    // compare objSeq with Object's obj-seq
                    int dbObjSeq = SbxDB.getObjSeq(userId, bucketName, objectKey);
                    if (dbObjSeq != -1 && objSeq != dbObjSeq) {
                        throw new AccessDeniedException("GetObjSeq", userId + ":" + bucketName + ":" + objectKey
                                + "#obj-seq are different: " + objSeq + " != " + dbObjSeq, true);
                    }
                }
            } catch (AccessDeniedException t) {
                throw t;
            } catch (Throwable t) {
                throw new AccessDeniedException("GetObjSeq",
                        userId + ":" + bucketName + ":" + objectKey + "***" + t.toString(), true);
            }
        }

        /////////////////////////////////////////////////
        req.reqStage = SbxPutRequest.STAGE.S0;
        /////////////////////////////////////////////////
    }//putObjectStage0

    public void putObjectStage1(PutObjectType request, SbxPutRequest req) throws EucalyptusCloudException {
        /////////////////////////////////////////////////
        // check bucket and object permissions
        /////////////////////////////////////////////////
        String userId = request.getUserId();
        String bucketName = request.getBucket();
        String objectKey = request.getKey();

        Long oldBucketSize = 0L;

        req.accessControlList = request.getAccessControlList();
        if (req.accessControlList == null) {
            req.accessControlList = new AccessControlListType();
        }
        req.key = bucketName + "." + objectKey;
        req.randomKey = request.getRandomKey();
        req.messenger = WalrusRESTBinding.getWriteMessenger();

        EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
        try {
            // check if bucket is exist
            BucketInfo bucketInfo = new BucketInfo(bucketName);
            List<BucketInfo> bucketList = db.query(bucketInfo);
            if (bucketList.size() <= 0) {
                db.rollback();
                req.messenger.removeQueue(req.key, req.randomKey);
                throw new NoSuchBucketException(bucketName);
            }

            // check if bucket is writable
            req.bucket = bucketList.get(0);
            req.logData = req.bucket.getLoggingEnabled() ? request.getLogData() : null;
            if (!req.bucket.canWrite(userId)) {
                db.rollback();
                req.messenger.removeQueue(req.key, req.randomKey);
                throw new AccessDeniedException("Bucket", bucketName, req.logData);
            }

            // Version is denied
            if (req.bucket.isVersioningEnabled()) {
                db.rollback();
                req.messenger.removeQueue(req.key, req.randomKey);
                throw new AccessDeniedException("VersionError", "Version is not support yet" + bucketName, true);
            }

            if (req.logData != null)
                req.reply.setLogData(req.logData);

            EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
            try {
                // To update object
                req.bAddObject = false;
                ObjectInfo searchObject = new ObjectInfo(bucketName, objectKey);
                searchObject.setVersionId(req.versionId);
                ObjectInfo foundObject = dbObject.getUnique(searchObject);
                // check if object is writable
                if (!foundObject.canWrite(userId)) {
                    db.rollback();
                    req.messenger.removeQueue(req.key, req.randomKey);
                    throw new AccessDeniedException("Key", objectKey, req.logData);
                }
                req.objectName = foundObject.getObjectName();
            } catch (EucalyptusCloudException ex) {
                // To insert object
                req.bAddObject = true;
                req.objectName = UUID.randomUUID().toString();
            }

            db.commit();
        } catch (NoSuchBucketException ex) {
            throw ex;
        } catch (AccessDeniedException ex) {
            throw ex;
        } catch (Throwable t) {
            db.rollback();
            req.messenger.removeQueue(req.key, req.randomKey);
            throw new AccessDeniedException("CSSError",
                    userId + ":" + bucketName + ":" + objectKey + "***" + t.toString(), true);
        }

        /////////////////////////////////////////////////
        req.reqStage = SbxPutRequest.STAGE.S1;
        /////////////////////////////////////////////////
    }//putObjectStage1

    private void addPutObjectCallback(final SbxPutRequest req, final Channel channel, final FileIO myFileIO,
            final WalrusDataMessenger myMessenger, final String myKey, final String myRandomKey,
            final WalrusDataQueue<WalrusDataMessage> myPutQueue, final String myUserId, final String myBucketName,
            final String myObjectKey, final String myTempObjectName) {
        try {
            ChannelFuture closeFuture = channel.getCloseFuture();
            closeFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    try {
                        if (req != null) {
                            req.disconnect = true;
                        }
                    } catch (Throwable t) {
                        //NOP
                    }
                    try {
                        myFileIO.finish();
                    } catch (Throwable t) {
                        //NOP
                    }
                    try {
                        myMessenger.removeMonitor(myKey);
                    } catch (Throwable t) {
                        //NOP
                    }
                    try {
                        myMessenger.removeQueue(myKey, myRandomKey);
                    } catch (Throwable t) {
                        //NOP
                    }
                    // Delete orphaned files
                    try {
                        File file = new File(storageManager.getObjectPath(myBucketName, myTempObjectName));
                        if (file.exists() == true) {
                            ObjectDeleter objectDeleter = new ObjectDeleter(myBucketName, myTempObjectName, -1L);
                            objectDeleter.start();
                        }
                    } catch (Throwable t) {
                        //NOP
                    }
                }
            });
        } catch (Throwable t) {
            Log.debug("CSS error: putObject callback: " + myUserId + ":" + myBucketName + ":" + myObjectKey + ":"
                    + myTempObjectName + " ***" + t.toString());
        }
    }

    public void putObjectStage2(PutObjectType request, SbxPutRequest req) throws EucalyptusCloudException {
        /////////////////////////////////////////////////
        // receive payload
        /////////////////////////////////////////////////
        String userId = request.getUserId();
        String bucketName = request.getBucket();
        String objectKey = request.getKey();

        // writes are unconditional
        WalrusDataQueue<WalrusDataMessage> putQueue = req.messenger.getQueue(req.key, req.randomKey);
        try {
            boolean isTimeout = true;
            boolean bEOF = false;
            while ((isTimeout = true) && (req.dataMessage = putQueue.poll(SbxPutRequest.DATAQUEUE_TIMEOUT,
                    TimeUnit.SECONDS)) != null) {
                if (Contexts.SBXSVR) {
                    try {
                        String myaccount = userId;
                        String myinstid = request.getMetaInstId();
                        WalrusControl.walrusManager.callWalrusHeartBeat(myaccount, myinstid, "PUTOBJECT2");
                    } catch (Throwable t) {
                        Log.debug("CSS callWalrusHeartBeat error (putObject2) " + "***" + t.toString());
                    }
                }
                //reset timeout check
                isTimeout = false;
                //reset timeout count
                req.updatetime();
                // duplicate put object at a same time
                if (putQueue.getInterrupted()) {
                    if (WalrusDataMessage.isEOF(req.dataMessage)) {
                        bEOF = true;
                        putQueue.clear();
                        SbxPayloadLog.log(req, req.type, "Payload", "EOF", "Interrupt");
                        break;
                    } else {
                        SbxPayloadLog.log(req, req.type, "Payload", ".", "Interrupt");
                    }
                    continue;
                }
                if (WalrusDataMessage.isStart(req.dataMessage)) {
                    req.digest = Digest.MD5.get();
                    req.tempObjectName = UUID.randomUUID().toString() + ".tmp";
                    try {
                        req.fileIO = storageManager.prepareForWrite(bucketName, req.tempObjectName);
                    } finally {
                        SbxPayloadLog.log(req, req.type, "Payload", "START", ".");
                        // To garbage collection
                        addPutObjectCallback(req, req.channel, (FileIO) req.fileIO, req.messenger, req.key,
                                req.randomKey, putQueue, userId, bucketName, objectKey, req.tempObjectName);
                    }
                } else if (WalrusDataMessage.isEOF(req.dataMessage)) {
                    bEOF = true;
                    putQueue.clear();
                    SbxPayloadLog.log(req, req.type, "Payload", "EOF", ".");
                    break;
                } else {
                    assert (WalrusDataMessage.isData(req.dataMessage));
                    byte[] data = req.dataMessage.getPayload();
                    // start writing object (but do not commit yet)
                    try {
                        if (req.fileIO != null) {
                            ((FileIO) req.fileIO).write(data);
                        }
                    } catch (IOException ex) {
                        LOG.error(ex);
                    } finally {
                        SbxPayloadLog.log(req, req.type, "Payload", ".", ".");
                    }
                    // calculate md5 on the fly
                    req.size += data.length;
                    if (req.digest != null)
                        req.digest.update(data);
                }
            } // while
              // pubObject is interrupted
            if (putQueue.getInterrupted()) {
                if (bEOF) {
                    if (req.fileIO != null)
                        ((FileIO) req.fileIO).finish();
                    req.messenger.removeQueue(req.key, req.randomKey);
                    File file = new File(storageManager.getObjectPath(bucketName, req.tempObjectName));
                    if (file.exists() == true) {
                        ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, req.tempObjectName, -1L);
                        objectDeleter.start();
                    }
                    throw new AccessDeniedException("CssError",
                            userId + ":" + bucketName + ":" + objectKey + "***" + "Duplicate putObject Error (EOF)",
                            true);
                }
                if (req.disconnect) {
                    if (req.fileIO != null)
                        ((FileIO) req.fileIO).finish();
                    req.messenger.removeQueue(req.key, req.randomKey);
                    File file = new File(storageManager.getObjectPath(bucketName, req.tempObjectName));
                    if (file.exists() == true) {
                        ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, req.tempObjectName, -1L);
                        objectDeleter.start();
                    }
                    throw new AccessDeniedException("CssError", userId + ":" + bucketName + ":" + objectKey + "***"
                            + "Duplicate putObject Error (DISCONNECT)", true);
                }
            }
            // pubObject is timeout
            if (isTimeout) {
                if (req.disconnect) {
                    if (req.fileIO != null)
                        ((FileIO) req.fileIO).finish();
                    req.messenger.removeQueue(req.key, req.randomKey);
                    File file = new File(storageManager.getObjectPath(bucketName, req.tempObjectName));
                    if (file.exists() == true) {
                        ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, req.tempObjectName, -1L);
                        objectDeleter.start();
                    }
                    throw new AccessDeniedException("CssError", userId + ":" + bucketName + ":" + objectKey + "***"
                            + "Read Payload Timeout (DISCONNECT)", true);
                }
                if (req.idletimeout()) {
                    if (req.fileIO != null)
                        ((FileIO) req.fileIO).finish();
                    req.messenger.removeQueue(req.key, req.randomKey);
                    File file = new File(storageManager.getObjectPath(bucketName, req.tempObjectName));
                    if (file.exists() == true) {
                        ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, req.tempObjectName, -1L);
                        objectDeleter.start();
                    }
                    throw new AccessDeniedException("CssError",
                            userId + ":" + bucketName + ":" + objectKey + "***" + "Read Payload Timeout (IDLE)",
                            true);
                }
                SbxPutJobQueue.put(req);
                /////////////////////////////////////////////////
                req.reqStage = SbxPutRequest.STAGE.S2;
                /////////////////////////////////////////////////
                return;
            }
        } catch (AccessDeniedException ex) {
            throw ex;
        } catch (Throwable t) {
            if (req.fileIO != null)
                ((FileIO) req.fileIO).finish();
            req.messenger.removeQueue(req.key, req.randomKey);
            File file = new File(storageManager.getObjectPath(bucketName, req.tempObjectName));
            if (file.exists() == true) {
                ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, req.tempObjectName, -1L);
                objectDeleter.start();
            }
            throw new AccessDeniedException("CssError",
                    userId + ":" + bucketName + ":" + objectKey + "***" + t.toString(), true);
        }

        try {
            if (req.fileIO != null)
                ((FileIO) req.fileIO).finish();
        } catch (Throwable t) {
            LOG.debug(userId + ":" + bucketName + ":" + objectKey + "***" + t.toString());
        }
        /////////////////////////////////////////////////
        req.reqStage = SbxPutRequest.STAGE.UPDATE;
        /////////////////////////////////////////////////
    }//putObjectStage2

    public void putObjectStageUpdate(PutObjectType request, SbxPutRequest req) throws EucalyptusCloudException {
        /////////////////////////////////////////////////
        // Insert or Update object
        /////////////////////////////////////////////////
        String userId = request.getUserId();
        String bucketName = request.getBucket();
        String objectKey = request.getKey();

        EntityWrapper<ObjectInfo> dbObject = WalrusControl.getEntityWrapper();
        try {
            if (req.digest != null)
                req.md5 = Hashes.bytesToHex(req.digest.digest());
            req.lastModified = new Date();
            ObjectInfo searchObject = new ObjectInfo(bucketName, objectKey);
            searchObject.setVersionId(req.versionId);
            List<ObjectInfo> objectInfos = dbObject.query(new ObjectInfo(bucketName, objectKey));
            for (ObjectInfo objInfo : objectInfos) {
                objInfo.setLast(false);
            }
            ObjectInfo foundObject = null;
            ObjectInfo objectInfo = null;
            try {
                // bbAddObject should be false
                foundObject = dbObject.getUnique(searchObject);
                if (foundObject.canWriteACP(userId)) {
                    List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
                    foundObject.addGrants(userId, grantInfos, req.accessControlList);
                    foundObject.setGrants(grantInfos);
                }
            } catch (EucalyptusCloudException ex) {
                // bbAddObject should be true
                if (req.bAddObject == false) {
                    // After received payload, the original object is missing (deleted or renamed)
                    dbObject.rollback();
                    ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, req.tempObjectName, -1L);
                    objectDeleter.start();
                    req.messenger.removeQueue(req.key, req.randomKey);
                    throw new AccessDeniedException("CssError",
                            userId + ":" + bucketName + ":" + objectKey + "***" + "Unable to update object", true);
                }

                objectInfo = new ObjectInfo(bucketName, objectKey);
                objectInfo.setOwnerId(userId);
                List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
                objectInfo.addGrants(userId, grantInfos, req.accessControlList);
                objectInfo.setGrants(grantInfos);
                objectInfo.setObjectName(req.objectName);
                objectInfo.setSize(0L);
                foundObject = objectInfo;
            }

            int objSeq = -1;
            if (Contexts.SBXSVR) {
                try {
                    if (StringUtils.isNotEmpty(req.objSeq)) {
                        objSeq = Integer.parseInt(req.objSeq);
                    }
                } catch (Throwable t) {
                    throw new AccessDeniedException("GetObjSeq",
                            userId + ":" + bucketName + ":" + objectKey + "***" + t.toString(), true);
                }
            }
            if (objSeq == -1) {
                objSeq = 0;
            } else {
                objSeq++;
            }

            foundObject.setVersionId(req.versionId);
            foundObject.replaceMetaData(request.getMetaData());
            foundObject.setEtag(req.md5);
            foundObject.setSize(req.size);
            foundObject.setLastModified(req.lastModified);
            foundObject.setStorageClass("STANDARD");
            foundObject.setContentType(request.getContentType());
            foundObject.setContentDisposition(request.getContentDisposition());
            foundObject.setLast(true);
            foundObject.setDeleted(false);
            foundObject.setObjSeq(objSeq);
            req.reply.setSize(req.size);

            String op = null;
            if (req.bAddObject) {
                dbObject.add(foundObject);
                op = "Create";
            } else {
                op = "Create";
                //mac: to change op to modify
                // op = "Modify";
            }

            if (Contexts.SBXSVR) {
                // syncid must LOCK
                if (req.reqId != null) {
                    if (SbxDB.syncidlock(req.syncid) == false) {
                        throw new AccessDeniedException("GetSyncIdError",
                                userId + ":" + bucketName + ":" + objectKey + "*** syncid=" + req.syncid
                                        + " is not locked (may be released too early)",
                                true);
                    }
                }

                String reqid = request.getMetaReqId();
                if (reqid == null)
                    reqid = "null";
                //LOG.debug("CSS writeEvent " + op + "): " + userId+":"+bucketName+":"+objectKey);
                this.writeEvent(dbObject.getEntityManager(), request.getMetaClientType(), userId, op,
                        foundObject.getObjectKey(), foundObject.getSize(),
                        strSBXContentTypeFolder.equals(foundObject.getContentType()), req.syncid, req.mtime, reqid,
                        objSeq);
            }

            String[] backup = new String[1];
            try {
                storageManager.renameObject(backup, bucketName, req.tempObjectName, req.objectName);
            } catch (Throwable t) {
                storageManager.renameObjectRollback(backup, bucketName, req.tempObjectName, req.objectName);
                throw t;
            }
            try {
                dbObject.commit();
            } catch (Throwable t) {
                storageManager.renameObjectRollback(backup, bucketName, req.tempObjectName, req.objectName);
                throw t;
            }
            try {
                storageManager.confirm(backup);
            } catch (Throwable t) {
                //NOP
            }

            try {
                if (req.bucket.isVersioningEnabled()) {
                    req.reply.setVersionId(req.versionId);
                }
                if (WalrusProperties.trackUsageStatistics) {
                    walrusStatistics.updateBytesIn(req.size);
                    walrusStatistics.updateSpaceUsed(req.size);
                }
                if (req.logData != null) {
                    req.logData.setObjectSize(req.size);
                    updateLogData(req.bucket, req.logData);
                    req.logData.setTurnAroundTime(Long.parseLong(new String(req.dataMessage.getPayload())));
                }
            } catch (Throwable t) {
                LOG.debug("Error Update Info: " + req.key);
            }

            // restart all interrupted puts
            WalrusMonitor monitor = req.messenger.getMonitor(req.key);
            synchronized (monitor) {
                monitor.setLastModified(req.lastModified);
                monitor.setMd5(req.md5);
                monitor.notifyAll();
            }
            req.messenger.removeMonitor(req.key);
            req.messenger.removeQueue(req.key, req.randomKey);
            LOG.info("Transfer complete: " + req.key);
        } catch (Throwable t) {
            LOG.debug(userId + ":" + bucketName + ":" + objectKey + "***" + t.toString());
            dbObject.rollback();
            req.messenger.removeQueue(req.key, req.randomKey);
            File file = new File(storageManager.getObjectPath(bucketName, req.tempObjectName));
            if (file.exists() == true) {
                ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, req.tempObjectName, -1L);
                objectDeleter.start();
            }
            throw new AccessDeniedException("CssError",
                    userId + ":" + bucketName + ":" + objectKey + "***" + t.toString(), true);
        }

        try {
            req.reply.setEtag(req.md5);
            req.reply.setLastModified(
                    DateUtils.format(req.lastModified.getTime(), DateUtils.ISO8601_DATETIME_PATTERN) + ".000Z");
        } catch (Throwable t) {
            LOG.debug("Error Set Put Reply: " + req.key);
        }

        /////////////////////////////////////////////////
        req.reqStage = SbxPutRequest.STAGE.FINAL;
        /////////////////////////////////////////////////
    }

    public PutObjectResponseType putObject(PutObjectType request, SbxPutRequest r) throws EucalyptusCloudException {
        //do putObject
        if (r.reqStage == SbxPutRequest.STAGE.START) {
            putObjectStage0(request, r);
        }
        if (r.reqStage == SbxPutRequest.STAGE.S0) {
            putObjectStage1(request, r);
        }
        // Timeout Put will be in this stage for a long time
        if (r.reqStage == SbxPutRequest.STAGE.S1 || r.reqStage == SbxPutRequest.STAGE.S2) {
            putObjectStage2(request, r);
        }
        if (r.reqStage == SbxPutRequest.STAGE.UPDATE) {
            putObjectStageUpdate(request, r);
        }
        //return reply
        if (r.reqStage == SbxPutRequest.STAGE.FINAL) {
            return r.reply;
        }
        return null;
    }//staged putObject

    //mac: This method is used for RenameObject
    public PutObjectResponseType putObject(PutObjectType request) throws EucalyptusCloudException {
        //call renameObject
        if (request.getRenameto() != null) {
            return this.renameObject(request, null);
        }

        return putObjectRefactor(request);
    }
}