/*******************************************************************************
*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.File;
import java.io.IOException;
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.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import org.apache.log4j.Logger;
import org.apache.tools.ant.util.DateUtils;
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 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.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.AccessDeniedException;
import edu.ucsb.eucalyptus.cloud.BucketAlreadyExistsException;
import edu.ucsb.eucalyptus.cloud.BucketAlreadyOwnedByYouException;
import edu.ucsb.eucalyptus.cloud.BucketLogData;
import edu.ucsb.eucalyptus.cloud.BucketNotEmptyException;
import edu.ucsb.eucalyptus.cloud.EntityTooLargeException;
import edu.ucsb.eucalyptus.cloud.InlineDataTooLargeException;
import edu.ucsb.eucalyptus.cloud.InvalidBucketNameException;
import edu.ucsb.eucalyptus.cloud.InvalidRangeException;
import edu.ucsb.eucalyptus.cloud.InvalidTargetBucketForLoggingException;
import edu.ucsb.eucalyptus.cloud.NoSuchBucketException;
import edu.ucsb.eucalyptus.cloud.NoSuchEntityException;
import edu.ucsb.eucalyptus.cloud.NotModifiedException;
import edu.ucsb.eucalyptus.cloud.PreconditionFailedException;
import edu.ucsb.eucalyptus.cloud.TooManyBucketsException;
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;
import edu.ucsb.eucalyptus.util.WalrusDataMessage;
import edu.ucsb.eucalyptus.util.WalrusDataMessenger;
import edu.ucsb.eucalyptus.util.WalrusDataQueue;
import edu.ucsb.eucalyptus.util.WalrusMonitor;
public class WalrusManager {
private static Logger LOG = Logger.getLogger(WalrusManager.class);
private StorageManager storageManager;
private WalrusImageManager walrusImageManager;
private static WalrusStatistics walrusStatistics = null;
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();
}
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");
}
EntityWrapper<BucketInfo> db = WalrusControl.getEntityWrapper();
BucketInfo searchBucket = new BucketInfo();
searchBucket.setOwnerId(userId);
searchBucket.setHidden(false);
List<BucketInfo> bucketInfoList = db.query(searchBucket);
ArrayList<BucketListEntry> 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 {
CanonicalUserType 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();
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);
}
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 EucalyptusCloudException("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 EucalyptusCloudException("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 EucalyptusCloudException("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"));
}
}
}
public PutObjectResponseType putObject(PutObjectType request)
throws EucalyptusCloudException {
PutObjectResponseType reply = (PutObjectResponseType) request
.getReply();
String userId = request.getUserId();
String bucketName = request.getBucket();
String objectKey = request.getKey();
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();
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)) {
if (logData != null)
reply.setLogData(logData);
String objectName;
String versionId;
ObjectInfo objectInfo = null;
if (bucket.isVersioningEnabled()) {
objectInfo = new ObjectInfo(bucketName, objectKey);
objectInfo.setOwnerId(userId);
List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
objectInfo.addGrants(userId, grantInfos, accessControlList);
objectInfo.setGrants(grantInfos);
objectName = UUID.randomUUID().toString();
objectInfo.setObjectName(objectName);
objectInfo.setSize(0L);
versionId = UUID.randomUUID().toString().replaceAll("-", "");
} else {
versionId = WalrusProperties.NULL_VERSION_ID;
ObjectInfo searchObject = new ObjectInfo(bucketName, objectKey);
searchObject.setVersionId(versionId);
EntityWrapper<ObjectInfo> dbObject = db.recast(ObjectInfo.class);
try {
ObjectInfo foundObject = dbObject.getUnique(searchObject);
if (!foundObject.canWrite(userId)) {
db.rollback();
messenger.removeQueue(key, randomKey);
throw new AccessDeniedException("Key", objectKey,
logData);
}
objectName = foundObject.getObjectName();
} catch(AccessDeniedException ex) {
throw ex;
} catch(EucalyptusCloudException ex) {
objectInfo = new ObjectInfo(bucketName, objectKey);
objectInfo.setOwnerId(userId);
List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
objectInfo.addGrants(userId, grantInfos, accessControlList);
objectInfo.setGrants(grantInfos);
objectName = UUID.randomUUID().toString();
objectInfo.setObjectName(objectName);
objectInfo.setSize(0L);
}
}
db.commit();
// writes are unconditional
WalrusDataQueue<WalrusDataMessage> putQueue = messenger
.getQueue(key, randomKey);
try {
WalrusDataMessage dataMessage;
String tempObjectName = objectName;
MessageDigest digest = null;
long size = 0;
FileIO fileIO = null;
while ((dataMessage = putQueue.take()) != null) {
if(putQueue.getInterrupted()) {
if(WalrusDataMessage.isEOF(dataMessage)) {
WalrusMonitor monitor = messenger.getMonitor(key);
if(monitor.getLastModified() == null) {
synchronized (monitor) {
monitor.wait();
}
}
lastModified = monitor.getLastModified();
md5 = monitor.getMd5();
//ok we are done here
if(fileIO != null)
fileIO.finish();
ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, tempObjectName, -1L);
objectDeleter.start();
LOG.info("Transfer interrupted: "+ key);
messenger.removeQueue(key, randomKey);
break;
}
continue;
}
if (WalrusDataMessage.isStart(dataMessage)) {
tempObjectName = UUID.randomUUID().toString();
digest = Digest.MD5.get();
try {
fileIO = storageManager.prepareForWrite(
bucketName, tempObjectName);
} catch (Exception ex) {
messenger.removeQueue(key, randomKey);
throw new EucalyptusCloudException(ex);
}
} else if (WalrusDataMessage.isEOF(dataMessage)) {
// commit object
try {
if (fileIO != null)
fileIO.finish();
storageManager.renameObject(bucketName,
tempObjectName, objectName);
} catch (IOException ex) {
LOG.error(ex);
messenger.removeQueue(key, randomKey);
throw new EucalyptusCloudException(objectKey);
}
if (digest != null)
md5 = Hashes.bytesToHex(digest.digest());
lastModified = new Date();
ObjectInfo searchObject = new ObjectInfo(bucketName, objectKey);
searchObject.setVersionId(versionId);
EntityWrapper<ObjectInfo> dbObject = WalrusControl.getEntityWrapper();
List<ObjectInfo> objectInfos = dbObject.query(new ObjectInfo(bucketName, objectKey));
for(ObjectInfo objInfo : objectInfos) {
objInfo.setLast(false);
}
ObjectInfo foundObject;
try {
foundObject = dbObject.getUnique(searchObject);
if (foundObject.canWriteACP(userId)) {
List<GrantInfo> grantInfos = new ArrayList<GrantInfo>();
foundObject.addGrants(userId, grantInfos,
accessControlList);
foundObject.setGrants(grantInfos);
}
if (WalrusProperties.enableTorrents) {
EntityWrapper<TorrentInfo> dbTorrent = dbObject
.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");
}
} catch (EucalyptusCloudException ex) {
if(objectInfo != null) {
foundObject = objectInfo;
} else {
db.rollback();
throw new EucalyptusCloudException("Unable to update object: " + bucketName + "/" + objectKey);
}
}
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);
reply.setSize(size);
ObjectInfo deleteMarker = new ObjectInfo(bucketName, objectKey);
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: " + bucketName + "/" + objectKey);
}
if (bucket.isVersioningEnabled()) {
reply.setVersionId(versionId);
}
EntityWrapper<BucketInfo> dbBucket = dbObject.recast(BucketInfo.class);
try {
bucket = dbBucket.getUnique(new BucketInfo(bucketName));
} catch(EucalyptusCloudException e) {
LOG.error(e);
dbObject.rollback();
throw new NoSuchBucketException(bucketName);
}
Long bucketSize = bucket.getBucketSize();
long newSize = bucketSize + oldBucketSize
+ size;
if (WalrusProperties.shouldEnforceUsageLimits
&& !request.isAdministrator()) {
if (newSize > (WalrusInfo.getWalrusInfo().getStorageMaxBucketSizeInMB() * WalrusProperties.M)) {
messenger.removeQueue(key, randomKey);
dbObject.rollback();
throw new EntityTooLargeException(
"Key", objectKey);
}
}
bucket.setBucketSize(newSize);
if (WalrusProperties.trackUsageStatistics) {
walrusStatistics.updateBytesIn(size);
walrusStatistics.updateSpaceUsed(size);
}
if (logData != null) {
logData.setObjectSize(size);
updateLogData(bucket, logData);
}
if(objectInfo != null)
dbObject.add(foundObject);
dbObject.commit();
if (logData != null) {
logData.setTurnAroundTime(Long
.parseLong(new String(dataMessage
.getPayload())));
}
// 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);
break;
} 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);
}
}
} catch (InterruptedException ex) {
LOG.error(ex, ex);
messenger.removeQueue(key, randomKey);
throw new EucalyptusCloudException("Transfer interrupted: "
+ key + "." + randomKey);
}
} else {
db.rollback();
messenger.removeQueue(key, randomKey);
throw new AccessDeniedException("Bucket", bucketName, logData);
}
} else {
db.rollback();
messenger.removeQueue(key, randomKey);
throw new NoSuchBucketException(bucketName);
}
reply.setEtag(md5);
reply.setLastModified(DateUtils.format(lastModified.getTime(),
DateUtils.ISO8601_DATETIME_PATTERN)
+ ".000Z");
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 = putObject(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);
try {
FileIO fileIO = storageManager.prepareForWrite(
bucketName, objectName);
if (fileIO != null) {
fileIO.write(base64Data);
fileIO.finish();
}
} catch (Exception ex) {
db.rollback();
throw new EucalyptusCloudException(ex);
}
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 {
DeleteObjectResponseType reply = (DeleteObjectResponseType) 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;
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)) {
dbObject.delete(nullObject);
String objectName = nullObject.getObjectName();
for (GrantInfo grantInfo : nullObject
.getGrants()) {
db.getEntityManager().remove(grantInfo);
}
Long size = nullObject.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);
}
if(bucketInfo.isVersioningSuspended()) {
//add delete marker
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);
}
} 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;
}
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)
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 (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.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);
if (objectInfos.size() > 0) {
int howManyProcessed = 0;
if (marker != null || objectInfos.size() < maxKeys)
Collections.sort(objectInfos);
ArrayList<ListEntry> contents = new ArrayList<ListEntry>();
for (ObjectInfo objectInfo : objectInfos) {
String objectKey = objectInfo.getObjectKey();
if (marker != null) {
if (objectKey.compareTo(marker) <= 0)
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;
}
}
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) {
db.rollback();
throw new AccessDeniedException("Bucket",
bucketName, logData);
}
ArrayList<MetaDataEntry> metaData = new ArrayList<MetaDataEntry>();
objectInfo.returnMetaData(metaData);
reply.setMetaData(metaData);
listEntry.setSize(objectInfo.getSize());
listEntry.setStorageClass(objectInfo.getStorageClass());
contents.add(listEntry);
}
reply.setContents(contents);
if (prefixes.size() > 0) {
reply.setCommonPrefixes(prefixes);
}
}
} else {
db.rollback();
throw new AccessDeniedException("Bucket", bucketName, logData);
}
} else {
db.rollback();
throw new NoSuchBucketException(bucketName);
}
db.commit();
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)
throws EucalyptusCloudException {
GetObjectResponseType reply = (GetObjectResponseType) request
.getReply();
String bucketName = request.getBucket();
String objectKey = request.getKey();
String userId = request.getUserId();
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();
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();
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());
}
}
if (getTorrent) {
if (objectInfo.isGlobalRead()) {
if (!WalrusProperties.enableTorrents) {
LOG
.warn("Bittorrent support has been disabled. Please check pre-requisites");
throw new EucalyptusCloudException(
"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 EucalyptusCloudException(
"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 EucalyptusCloudException(errorString);
}
} else {
db.rollback();
throw new AccessDeniedException("Key", objectKey,
logData);
}
}
Date lastModified = objectInfo.getLastModified();
Long size = objectInfo.getSize();
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 = "";
try {
FileIO 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 EucalyptusCloudException(e);
}
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);
}
}
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;
}
}