From f05e3dd4566b2dbc92fd869061f2afb67bdf21d8 Mon Sep 17 00:00:00 2001 From: JohnZ Date: Sat, 28 Apr 2012 13:35:32 +0100 Subject: [PATCH] Removal of S3SoapService from solution --- .../S3FileSystemBucketAdapter.java | 14 +- .../lifecycle/ServiceEngineLifecycle.java | 2 +- .../src/com/cloud/bridge/model/SAcl.java | 3 +- .../com/cloud/bridge/model/SObjectItem.java | 2 +- .../cloud/bridge/persist/PersistContext.java | 8 +- .../bridge/persist/dao/MultipartLoadDao.java | 12 +- .../cloud/bridge/service/EC2RestServlet.java | 1 + .../cloud/bridge/service/EC2SoapService.java | 1 + .../com/cloud/bridge/service/PWCBHandler.java | 42 --- .../cloud/bridge/service/S3RestServlet.java | 4 +- .../cloud/bridge/service/S3SoapService.java | 115 ------- .../com/cloud/bridge/service/UserContext.java | 2 +- .../service/controller/s3/S3BucketAction.java | 28 +- .../service/controller/s3/S3ObjectAction.java | 61 ++-- .../S3SerializableServiceImplementation.java} | 40 ++- .../{ => controller/s3}/ServiceProvider.java | 16 +- .../{ => controller/s3}/ServletAction.java | 2 +- .../{ => core/s3}/S3BucketAdapter.java | 7 +- .../bridge/service/core/s3/S3Engine.java | 162 ++++----- .../core/s3/S3PutObjectInlineRequest.java | 4 +- .../com/cloud/bridge/tool/CloudS3CmdTool.java | 325 ------------------ .../util/{Tuple.java => OrderedPair.java} | 17 +- .../src/com/cloud/bridge/util/RestAuth.java | 1 - 23 files changed, 201 insertions(+), 668 deletions(-) rename cloudbridge/src/com/cloud/bridge/{service => io}/S3FileSystemBucketAdapter.java (90%) delete mode 100644 cloudbridge/src/com/cloud/bridge/service/PWCBHandler.java delete mode 100644 cloudbridge/src/com/cloud/bridge/service/S3SoapService.java rename cloudbridge/src/com/cloud/bridge/service/{S3SoapServiceImpl.java => controller/s3/S3SerializableServiceImplementation.java} (93%) rename cloudbridge/src/com/cloud/bridge/service/{ => controller/s3}/ServiceProvider.java (91%) rename cloudbridge/src/com/cloud/bridge/service/{ => controller/s3}/ServletAction.java (92%) rename cloudbridge/src/com/cloud/bridge/service/{ => core/s3}/S3BucketAdapter.java (80%) delete mode 100644 cloudbridge/src/com/cloud/bridge/tool/CloudS3CmdTool.java rename cloudbridge/src/com/cloud/bridge/util/{Tuple.java => OrderedPair.java} (67%) diff --git a/cloudbridge/src/com/cloud/bridge/service/S3FileSystemBucketAdapter.java b/cloudbridge/src/com/cloud/bridge/io/S3FileSystemBucketAdapter.java similarity index 90% rename from cloudbridge/src/com/cloud/bridge/service/S3FileSystemBucketAdapter.java rename to cloudbridge/src/com/cloud/bridge/io/S3FileSystemBucketAdapter.java index 7621c6539dd..7cc45042efc 100644 --- a/cloudbridge/src/com/cloud/bridge/service/S3FileSystemBucketAdapter.java +++ b/cloudbridge/src/com/cloud/bridge/io/S3FileSystemBucketAdapter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.cloud.bridge.service; +package com.cloud.bridge.io; import java.io.File; import java.io.FileOutputStream; @@ -29,13 +29,13 @@ import javax.activation.DataSource; import org.apache.log4j.Logger; -import com.cloud.bridge.io.FileRangeDataSource; +import com.cloud.bridge.service.core.s3.S3BucketAdapter; import com.cloud.bridge.service.core.s3.S3MultipartPart; import com.cloud.bridge.service.exception.FileNotExistException; import com.cloud.bridge.service.exception.InternalErrorException; import com.cloud.bridge.service.exception.OutOfStorageException; import com.cloud.bridge.util.StringHelper; -import com.cloud.bridge.util.Tuple; +import com.cloud.bridge.util.OrderedPair; /** * @author Kelven Yang, John Zucker @@ -136,10 +136,10 @@ public class S3FileSystemBucketAdapter implements S3BucketAdapter { * @param sourceBucket - special bucket used to save uploaded file parts * @param parts - an array of file names in the sourceBucket * @param client - if not null, then keep the servlet connection alive while this potentially long concatentation takes place - * @return Tuple with the first value the MD5 of the final object, and the second value the length of the final object + * @return OrderedPair with the first value the MD5 of the final object, and the second value the length of the final object */ @Override - public Tuple concatentateObjects(String mountedRoot, String destBucket, String fileName, String sourceBucket, S3MultipartPart[] parts, OutputStream client) + public OrderedPair concatentateObjects(String mountedRoot, String destBucket, String fileName, String sourceBucket, S3MultipartPart[] parts, OutputStream client) { MessageDigest md5; long totalLength = 0; @@ -181,8 +181,8 @@ public class S3FileSystemBucketAdapter implements S3BucketAdapter { } } fos.close(); - return new Tuple(StringHelper.toHexString(md5.digest()), new Long(totalLength)); - //Create a tuple whose first element is the MD4 digest as a (lowercase) hex String + return new OrderedPair(StringHelper.toHexString(md5.digest()), new Long(totalLength)); + //Create an ordered pair whose first element is the MD4 digest as a (lowercase) hex String } catch(IOException e) { logger.error("concatentateObjects unexpected exception " + e.getMessage(), e); diff --git a/cloudbridge/src/com/cloud/bridge/lifecycle/ServiceEngineLifecycle.java b/cloudbridge/src/com/cloud/bridge/lifecycle/ServiceEngineLifecycle.java index e34eb15cfa9..1a353ca3236 100644 --- a/cloudbridge/src/com/cloud/bridge/lifecycle/ServiceEngineLifecycle.java +++ b/cloudbridge/src/com/cloud/bridge/lifecycle/ServiceEngineLifecycle.java @@ -19,7 +19,7 @@ import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.description.AxisService; import org.apache.axis2.engine.ServiceLifeCycle; -import com.cloud.bridge.service.ServiceProvider; +import com.cloud.bridge.service.controller.s3.ServiceProvider; /** * @author Kelven Yang diff --git a/cloudbridge/src/com/cloud/bridge/model/SAcl.java b/cloudbridge/src/com/cloud/bridge/model/SAcl.java index 119d1a124f3..eef2b88797e 100644 --- a/cloudbridge/src/com/cloud/bridge/model/SAcl.java +++ b/cloudbridge/src/com/cloud/bridge/model/SAcl.java @@ -19,7 +19,8 @@ import java.io.Serializable; import java.util.Date; /** - * @author Kelven Yang + * @author Kelven Yang, John Zucker + * A model of stored ACLs to remember the ACL permissions per canonicalUserID and grantee */ public class SAcl implements Serializable { private static final long serialVersionUID = 7900837117165018850L; diff --git a/cloudbridge/src/com/cloud/bridge/model/SObjectItem.java b/cloudbridge/src/com/cloud/bridge/model/SObjectItem.java index 64c1dd585c8..9c9ce9ec8e9 100644 --- a/cloudbridge/src/com/cloud/bridge/model/SObjectItem.java +++ b/cloudbridge/src/com/cloud/bridge/model/SObjectItem.java @@ -76,7 +76,7 @@ public class SObjectItem implements Serializable { } public void setStoredPath(String storedPath) { - this.storedPath = storedPath; + this.storedPath = storedPath; // TODO - storedpath holds integer, called from S3Engine.allocObjectItem } public long getStoredSize() { diff --git a/cloudbridge/src/com/cloud/bridge/persist/PersistContext.java b/cloudbridge/src/com/cloud/bridge/persist/PersistContext.java index 81001b32a8f..f41bca19d41 100644 --- a/cloudbridge/src/com/cloud/bridge/persist/PersistContext.java +++ b/cloudbridge/src/com/cloud/bridge/persist/PersistContext.java @@ -28,7 +28,7 @@ import org.hibernate.Session; import org.hibernate.Transaction; import com.cloud.bridge.util.CloudSessionFactory; -import com.cloud.bridge.util.Tuple; +import com.cloud.bridge.util.OrderedPair; /** * @author Kelven Yang @@ -212,7 +212,7 @@ public class PersistContext { @SuppressWarnings("deprecation") private static Connection getJDBCConnection(String name, boolean allocNew) { String registryKey = "JDBC-Connection." + name; - Tuple info = (Tuple)getThreadStoreObject(registryKey); + OrderedPair info = (OrderedPair)getThreadStoreObject(registryKey); if(info == null && allocNew) { Session session = sessionFactory.openSession(); Connection connection = session.connection(); @@ -234,7 +234,7 @@ public class PersistContext { return null; } - registerThreadStoreObject(registryKey, new Tuple(session, connection)); + registerThreadStoreObject(registryKey, new OrderedPair(session, connection)); return connection; } @@ -246,7 +246,7 @@ public class PersistContext { private static void releaseJDBCConnection(String name) { String registryKey = "JDBC-Connection." + name; - Tuple info = (Tuple)unregisterThreadStoreObject(registryKey); + OrderedPair info = (OrderedPair)unregisterThreadStoreObject(registryKey); if(info != null) { try { info.getSecond().close(); diff --git a/cloudbridge/src/com/cloud/bridge/persist/dao/MultipartLoadDao.java b/cloudbridge/src/com/cloud/bridge/persist/dao/MultipartLoadDao.java index 0be9f87a52f..e1a8e96f556 100644 --- a/cloudbridge/src/com/cloud/bridge/persist/dao/MultipartLoadDao.java +++ b/cloudbridge/src/com/cloud/bridge/persist/dao/MultipartLoadDao.java @@ -37,7 +37,7 @@ import com.cloud.bridge.service.core.s3.S3MetaDataEntry; import com.cloud.bridge.service.core.s3.S3MultipartPart; import com.cloud.bridge.service.core.s3.S3MultipartUpload; import com.cloud.bridge.util.ConfigurationHelper; -import com.cloud.bridge.util.Tuple; +import com.cloud.bridge.util.OrderedPair; public class MultipartLoadDao { public static final Logger logger = Logger.getLogger(MultipartLoadDao.class); @@ -74,7 +74,7 @@ public class MultipartLoadDao { * @return creator of the multipart upload, and NameKey of upload * @throws SQLException, ClassNotFoundException, IllegalAccessException, InstantiationException */ - public Tuple multipartExits( int uploadId ) + public OrderedPair multipartExits( int uploadId ) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException { PreparedStatement statement = null; @@ -89,7 +89,7 @@ public class MultipartLoadDao { if ( rs.next()) { accessKey = rs.getString( "AccessKey" ); nameKey = rs.getString( "NameKey" ); - return new Tuple( accessKey, nameKey ); + return new OrderedPair( accessKey, nameKey ); } else return null; @@ -334,10 +334,10 @@ public class MultipartLoadDao { * @param prefix - can be null * @param keyMarker - can be null * @param uploadIdMarker - can be null, should only be defined if keyMarker is not-null - * @return Tuple + * @return OrderedPair * @throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException */ - public Tuple getInitiatedUploads( String bucketName, int maxParts, String prefix, String keyMarker, String uploadIdMarker ) + public OrderedPair getInitiatedUploads( String bucketName, int maxParts, String prefix, String keyMarker, String uploadIdMarker ) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException { S3MultipartUpload[] inProgress = new S3MultipartUpload[maxParts]; @@ -383,7 +383,7 @@ public class MultipartLoadDao { statement.close(); if (i < maxParts) inProgress = (S3MultipartUpload[])resizeArray(inProgress,i); - return new Tuple(inProgress, isTruncated); + return new OrderedPair(inProgress, isTruncated); } finally { closeConnection(); diff --git a/cloudbridge/src/com/cloud/bridge/service/EC2RestServlet.java b/cloudbridge/src/com/cloud/bridge/service/EC2RestServlet.java index 48cf464d621..d135824395d 100644 --- a/cloudbridge/src/com/cloud/bridge/service/EC2RestServlet.java +++ b/cloudbridge/src/com/cloud/bridge/service/EC2RestServlet.java @@ -95,6 +95,7 @@ import com.amazon.ec2.TerminateInstancesResponse; import com.cloud.bridge.model.UserCredentials; import com.cloud.bridge.persist.dao.OfferingDao; import com.cloud.bridge.persist.dao.UserCredentialsDao; +import com.cloud.bridge.service.controller.s3.ServiceProvider; import com.cloud.bridge.service.core.ec2.EC2AssociateAddress; import com.cloud.bridge.service.core.ec2.EC2AuthorizeRevokeSecurityGroup; import com.cloud.bridge.service.core.ec2.EC2CreateImage; diff --git a/cloudbridge/src/com/cloud/bridge/service/EC2SoapService.java b/cloudbridge/src/com/cloud/bridge/service/EC2SoapService.java index 00262353baf..6de9edcb0a3 100644 --- a/cloudbridge/src/com/cloud/bridge/service/EC2SoapService.java +++ b/cloudbridge/src/com/cloud/bridge/service/EC2SoapService.java @@ -18,6 +18,7 @@ package com.cloud.bridge.service; import org.apache.log4j.Logger; import com.amazon.ec2.*; +import com.cloud.bridge.service.controller.s3.ServiceProvider; public class EC2SoapService implements AmazonEC2SkeletonInterface { protected final static Logger logger = Logger.getLogger(EC2SoapService.class); diff --git a/cloudbridge/src/com/cloud/bridge/service/PWCBHandler.java b/cloudbridge/src/com/cloud/bridge/service/PWCBHandler.java deleted file mode 100644 index 58fbec66a88..00000000000 --- a/cloudbridge/src/com/cloud/bridge/service/PWCBHandler.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.cloud.bridge.service; - -import java.io.IOException; - -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.UnsupportedCallbackException; - -import org.apache.ws.security.WSPasswordCallback; - -public class PWCBHandler implements CallbackHandler { - - @SuppressWarnings("deprecation") - public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { - for (int i = 0; i < callbacks.length; i++) { - WSPasswordCallback pwcb = (WSPasswordCallback)callbacks[i]; - String id = pwcb.getIdentifer(); - if ( "client".equals(id)) { - pwcb.setPassword("apache"); - } - else if("service".equals(id)) { - pwcb.setPassword("apache"); - } - } - } -} - diff --git a/cloudbridge/src/com/cloud/bridge/service/S3RestServlet.java b/cloudbridge/src/com/cloud/bridge/service/S3RestServlet.java index b21afd41f8a..0803e517011 100644 --- a/cloudbridge/src/com/cloud/bridge/service/S3RestServlet.java +++ b/cloudbridge/src/com/cloud/bridge/service/S3RestServlet.java @@ -44,6 +44,8 @@ import com.cloud.bridge.persist.PersistContext; import com.cloud.bridge.persist.dao.UserCredentialsDao; import com.cloud.bridge.service.controller.s3.S3BucketAction; import com.cloud.bridge.service.controller.s3.S3ObjectAction; +import com.cloud.bridge.service.controller.s3.ServiceProvider; +import com.cloud.bridge.service.controller.s3.ServletAction; import com.cloud.bridge.service.core.s3.S3AccessControlList; import com.cloud.bridge.service.core.s3.S3AuthParams; import com.cloud.bridge.service.core.s3.S3Engine; @@ -316,8 +318,6 @@ public class S3RestServlet extends HttpServlet { return; } - // TODO - Remove soon -> turn off auth - just for testing - //UserContext.current().initContext("Mark", "123", "Mark", "testing", request); } catch (SignatureException e) { throw new PermissionDeniedException(e); diff --git a/cloudbridge/src/com/cloud/bridge/service/S3SoapService.java b/cloudbridge/src/com/cloud/bridge/service/S3SoapService.java deleted file mode 100644 index 5732c8945fe..00000000000 --- a/cloudbridge/src/com/cloud/bridge/service/S3SoapService.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.cloud.bridge.service; - -import org.apache.axis2.AxisFault; -import org.apache.log4j.Logger; - -import com.amazon.s3.*; - -/** - * @author Kelven Yang - */ -public class S3SoapService implements AmazonS3SkeletonInterface { - protected final static Logger logger = Logger.getLogger(S3SoapService.class); - - public GetBucketLoggingStatusResponse getBucketLoggingStatus(GetBucketLoggingStatus getBucketLoggingStatus0) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.getBucketLoggingStatus(getBucketLoggingStatus0); - } - - public CopyObjectResponse copyObject(com.amazon.s3.CopyObject copyObject2) throws AxisFault { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.copyObject(copyObject2); - } - - public GetBucketAccessControlPolicyResponse getBucketAccessControlPolicy ( - GetBucketAccessControlPolicy getBucketAccessControlPolicy4) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.getBucketAccessControlPolicy (getBucketAccessControlPolicy4); - } - - public ListBucketResponse listBucket (ListBucket listBucket6) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.listBucket (listBucket6); - } - - public PutObjectResponse putObject(PutObject putObject8) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.putObject(putObject8); - } - - public CreateBucketResponse createBucket (CreateBucket createBucket) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.createBucket(createBucket); - } - - public ListAllMyBucketsResponse listAllMyBuckets ( - ListAllMyBuckets listAllMyBuckets12) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.listAllMyBuckets (listAllMyBuckets12); - } - - public GetObjectResponse getObject(com.amazon.s3.GetObject getObject14) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.getObject(getObject14); - } - - public DeleteBucketResponse deleteBucket(DeleteBucket deleteBucket16) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.deleteBucket(deleteBucket16); - } - - public SetBucketLoggingStatusResponse setBucketLoggingStatus( - SetBucketLoggingStatus setBucketLoggingStatus18) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.setBucketLoggingStatus(setBucketLoggingStatus18); - } - - - public GetObjectAccessControlPolicyResponse getObjectAccessControlPolicy( - GetObjectAccessControlPolicy getObjectAccessControlPolicy20) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.getObjectAccessControlPolicy(getObjectAccessControlPolicy20); - } - - public DeleteObjectResponse deleteObject (DeleteObject deleteObject22) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.deleteObject (deleteObject22); - } - - public SetBucketAccessControlPolicyResponse setBucketAccessControlPolicy( - SetBucketAccessControlPolicy setBucketAccessControlPolicy24) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.setBucketAccessControlPolicy(setBucketAccessControlPolicy24); - } - - public SetObjectAccessControlPolicyResponse setObjectAccessControlPolicy( - SetObjectAccessControlPolicy setObjectAccessControlPolicy26) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.setObjectAccessControlPolicy(setObjectAccessControlPolicy26); - } - - public PutObjectInlineResponse putObjectInline (PutObjectInline putObjectInline28) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.putObjectInline (putObjectInline28); - } - - public GetObjectExtendedResponse getObjectExtended(GetObjectExtended getObjectExtended30) { - AmazonS3SkeletonInterface s3Service = ServiceProvider.getInstance().getServiceImpl(AmazonS3SkeletonInterface.class); - return s3Service.getObjectExtended(getObjectExtended30); - } -} diff --git a/cloudbridge/src/com/cloud/bridge/service/UserContext.java b/cloudbridge/src/com/cloud/bridge/service/UserContext.java index 30919915bab..9fdc06ca134 100644 --- a/cloudbridge/src/com/cloud/bridge/service/UserContext.java +++ b/cloudbridge/src/com/cloud/bridge/service/UserContext.java @@ -33,7 +33,7 @@ public class UserContext { private boolean annonymous = false; private String accessKey; private String secretKey; - private String canonicalUserId; // -> for us this is the accessKey + private String canonicalUserId; // In our design, we re-use the accessKey to provide the canonicalUserId -- TODO loPri - reconsider? private String description; private HttpServletRequest request = null; diff --git a/cloudbridge/src/com/cloud/bridge/service/controller/s3/S3BucketAction.java b/cloudbridge/src/com/cloud/bridge/service/controller/s3/S3BucketAction.java index 55b5429fd2a..1306c9fb790 100644 --- a/cloudbridge/src/com/cloud/bridge/service/controller/s3/S3BucketAction.java +++ b/cloudbridge/src/com/cloud/bridge/service/controller/s3/S3BucketAction.java @@ -25,21 +25,13 @@ import java.io.StringWriter; import java.io.Writer; import java.util.Calendar; -import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.bind.DatatypeConverter; -import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; - -import org.apache.axiom.om.OMAbstractFactory; -import org.apache.axiom.om.OMFactory; -import org.apache.axis2.databinding.utils.writer.MTOMAwareXMLSerializer; import org.apache.log4j.Logger; import org.json.simple.parser.ParseException; @@ -58,9 +50,6 @@ import com.cloud.bridge.persist.dao.MultipartLoadDao; import com.cloud.bridge.persist.dao.SBucketDao; import com.cloud.bridge.service.S3Constants; import com.cloud.bridge.service.S3RestServlet; -import com.cloud.bridge.service.S3SoapServiceImpl; -import com.cloud.bridge.service.ServiceProvider; -import com.cloud.bridge.service.ServletAction; import com.cloud.bridge.service.UserContext; import com.cloud.bridge.service.core.s3.S3AccessControlPolicy; import com.cloud.bridge.service.core.s3.S3BucketPolicy; @@ -91,7 +80,7 @@ import com.cloud.bridge.service.exception.PermissionDeniedException; import com.cloud.bridge.util.Converter; import com.cloud.bridge.util.PolicyParser; import com.cloud.bridge.util.StringHelper; -import com.cloud.bridge.util.Tuple; +import com.cloud.bridge.util.OrderedPair; import com.cloud.bridge.util.XSerializer; import com.cloud.bridge.util.XSerializerXmlAdapter; @@ -103,9 +92,6 @@ public class S3BucketAction implements ServletAction { protected final static Logger logger = Logger.getLogger(S3BucketAction.class); private DocumentBuilderFactory dbf = null; - private OMFactory factory = OMAbstractFactory.getOMFactory(); - private XMLOutputFactory xmlOutFactory = XMLOutputFactory.newInstance(); - public S3BucketAction() { dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware( true ); @@ -400,7 +386,7 @@ public class S3BucketAction implements ServletAction { S3ListAllMyBucketsResponse engineResponse = ServiceProvider.getInstance().getS3Engine().handleRequest(engineRequest); // To allow the all buckets list to be serialized via Axiom classes - ListAllMyBucketsResponse allBuckets = S3SoapServiceImpl.toListAllMyBucketsResponse( engineResponse ); + ListAllMyBucketsResponse allBuckets = S3SerializableServiceImplementation.toListAllMyBucketsResponse( engineResponse ); OutputStream outputStream = response.getOutputStream(); response.setStatus(200); @@ -429,7 +415,7 @@ public class S3BucketAction implements ServletAction { S3ListBucketResponse engineResponse = ServiceProvider.getInstance().getS3Engine().listBucketContents( engineRequest, false ); // To allow the all list buckets result to be serialized via Axiom classes - ListBucketResponse oneBucket = S3SoapServiceImpl.toListBucketResponse( engineResponse ); + ListBucketResponse oneBucket = S3SerializableServiceImplementation.toListBucketResponse( engineResponse ); OutputStream outputStream = response.getOutputStream(); response.setStatus(200); @@ -452,13 +438,13 @@ public class S3BucketAction implements ServletAction { cal.set( 1970, 1, 1 ); engineRequest.setAccessKey(UserContext.current().getAccessKey()); engineRequest.setRequestTimestamp( cal ); - engineRequest.setSignature( "" ); + engineRequest.setSignature( "" ); // TODO - Provide signature engineRequest.setBucketName((String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY)); S3AccessControlPolicy engineResponse = ServiceProvider.getInstance().getS3Engine().handleRequest(engineRequest); // To allow the bucket acl policy result to be serialized via Axiom classes - GetBucketAccessControlPolicyResponse onePolicy = S3SoapServiceImpl.toGetBucketAccessControlPolicyResponse( engineResponse ); + GetBucketAccessControlPolicyResponse onePolicy = S3SerializableServiceImplementation.toGetBucketAccessControlPolicyResponse( engineResponse ); OutputStream outputStream = response.getOutputStream(); response.setStatus(200); @@ -757,7 +743,7 @@ public class S3BucketAction implements ServletAction { } public void executePutBucketWebsite(HttpServletRequest request, HttpServletResponse response) throws IOException { - // TODO -- HiPri - Undertake checks on Put Bucket Website + // TODO -- LoPri - Undertake checks on Put Bucket Website // Tested using configuration \nAllowOverride FileInfo AuthConfig Limit... in httpd.conf // Need some way of using AllowOverride to allow use of .htaccess and then pushing .httaccess file to bucket subdirectory of mount point // Currently has noop effect in the sense that a running apachectl process sees the directory contents without further action @@ -825,7 +811,7 @@ public class S3BucketAction implements ServletAction { // [B] Query the multipart table to get the list of current uploads try { MultipartLoadDao uploadDao = new MultipartLoadDao(); - Tuple result = uploadDao.getInitiatedUploads( bucketName, maxUploads, prefix, keyMarker, uploadIdMarker ); + OrderedPair result = uploadDao.getInitiatedUploads( bucketName, maxUploads, prefix, keyMarker, uploadIdMarker ); uploads = result.getFirst(); isTruncated = result.getSecond().booleanValue(); } diff --git a/cloudbridge/src/com/cloud/bridge/service/controller/s3/S3ObjectAction.java b/cloudbridge/src/com/cloud/bridge/service/controller/s3/S3ObjectAction.java index d57f809cc5d..79461bbc1e7 100644 --- a/cloudbridge/src/com/cloud/bridge/service/controller/s3/S3ObjectAction.java +++ b/cloudbridge/src/com/cloud/bridge/service/controller/s3/S3ObjectAction.java @@ -30,17 +30,11 @@ import javax.activation.DataHandler; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.bind.DatatypeConverter; -import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamWriter; -import org.apache.axiom.om.OMAbstractFactory; -import org.apache.axiom.om.OMFactory; -import org.apache.axis2.databinding.utils.writer.MTOMAwareXMLSerializer; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -55,9 +49,6 @@ import com.cloud.bridge.persist.dao.MultipartLoadDao; import com.cloud.bridge.persist.dao.SBucketDao; import com.cloud.bridge.service.S3Constants; import com.cloud.bridge.service.S3RestServlet; -import com.cloud.bridge.service.S3SoapServiceImpl; -import com.cloud.bridge.service.ServiceProvider; -import com.cloud.bridge.service.ServletAction; import com.cloud.bridge.service.UserContext; import com.cloud.bridge.service.core.s3.S3AccessControlPolicy; import com.cloud.bridge.service.core.s3.S3AuthParams; @@ -83,7 +74,7 @@ import com.cloud.bridge.util.Converter; import com.cloud.bridge.util.DateHelper; import com.cloud.bridge.util.HeaderParam; import com.cloud.bridge.util.ServletRequestDataSource; -import com.cloud.bridge.util.Tuple; +import com.cloud.bridge.util.OrderedPair; /** * @author Kelven Yang, John Zucker @@ -92,8 +83,6 @@ public class S3ObjectAction implements ServletAction { protected final static Logger logger = Logger.getLogger(S3ObjectAction.class); private DocumentBuilderFactory dbf = null; - private OMFactory factory = OMAbstractFactory.getOMFactory(); - private XMLOutputFactory xmlOutFactory = XMLOutputFactory.newInstance(); public S3ObjectAction() { dbf = DocumentBuilderFactory.newInstance(); @@ -216,7 +205,7 @@ public class S3ObjectAction implements ServletAction { if (null != versionId) response.addHeader( "x-amz-version-id", versionId ); // To allow the copy object result to be serialized via Axiom classes - CopyObjectResponse allBuckets = S3SoapServiceImpl.toCopyObjectResponse( engineResponse ); + CopyObjectResponse allBuckets = S3SerializableServiceImplementation.toCopyObjectResponse( engineResponse ); OutputStream outputStream = response.getOutputStream(); response.setStatus(200); @@ -255,7 +244,7 @@ public class S3ObjectAction implements ServletAction { // To allow the get object acl policy result to be serialized via Axiom classes - GetObjectAccessControlPolicyResponse onePolicy = S3SoapServiceImpl.toGetObjectAccessControlPolicyResponse( engineResponse ); + GetObjectAccessControlPolicyResponse onePolicy = S3SerializableServiceImplementation.toGetObjectAccessControlPolicyResponse( engineResponse ); OutputStream outputStream = response.getOutputStream(); response.setStatus(200); @@ -273,21 +262,29 @@ public class S3ObjectAction implements ServletAction { { S3PutObjectRequest putRequest = null; - // -> reuse the Access Control List parsing code that was added to support DIME + String ACLsetting = request.getHeader("x-amz-acl"); + String bucketName = (String)request.getAttribute(S3Constants.BUCKET_ATTR_KEY); String key = (String)request.getAttribute(S3Constants.OBJECT_ATTR_KEY); - try { - putRequest = S3RestServlet.toEnginePutObjectRequest( request.getInputStream()); - } - catch( Exception e ) { - throw new IOException( e.toString()); - } + + if ( null == ACLsetting ) + // -> reuse the Access Control List parsing code that was added to support DIME + try { + putRequest = S3RestServlet.toEnginePutObjectRequest( request.getInputStream()); + } + catch( Exception e ) { + throw new IOException( e.toString()); + } + // -> reuse the SOAP code to save the passed in ACLs S3SetObjectAccessControlPolicyRequest engineRequest = new S3SetObjectAccessControlPolicyRequest(); engineRequest.setBucketName( bucketName ); engineRequest.setKey( key ); - engineRequest.setAcl( putRequest.getAcl()); +// if (null == putRequest) +// engineRequest.setAcl (an S3AccessContolList) // (ACLsetting); +// else + engineRequest.setAcl( putRequest.getAcl()); // -> is this a request for a specific version of the object? look for "versionId=" in the query string String queryString = request.getQueryString(); @@ -357,7 +354,7 @@ public class S3ObjectAction implements ServletAction { S3RestServlet.writeResponse(response, "HTTP/1.1 100 Continue\r\n"); } - String contentType = request.getHeader( "Content-Type" ); + // String contentType = request.getHeader( "Content-Type" ); TODO - Needed? long contentLength = Converter.toLong(request.getHeader("Content-Length"), 0); String bucket = (String) request.getAttribute(S3Constants.BUCKET_ATTR_KEY); @@ -644,7 +641,7 @@ public class S3ObjectAction implements ServletAction { long contentLength = Converter.toLong(request.getHeader("Content-Length"), 0); - String md5 = request.getHeader( "Content-MD5" ); + // String md5 = request.getHeader( "Content-MD5" ); TODO _ Needed? String temp = request.getParameter("uploadId"); if (null != temp) uploadId = Integer.parseInt( temp ); @@ -753,7 +750,7 @@ public class S3ObjectAction implements ServletAction { // [C] Parse the given XML body part and perform error checking - Tuple match = verifyParts( request.getInputStream(), parts ); + OrderedPair match = verifyParts( request.getInputStream(), parts ); if (200 != match.getFirst().intValue()) { response.setStatus(match.getFirst().intValue()); returnErrorXML( match.getFirst().intValue(), match.getSecond(), outputStream ); @@ -840,7 +837,7 @@ public class S3ObjectAction implements ServletAction { try { MultipartLoadDao uploadDao = new MultipartLoadDao(); - Tuple exists = uploadDao.multipartExits( uploadId ); + OrderedPair exists = uploadDao.multipartExits( uploadId ); if (null == exists) { response.setStatus(404); return; @@ -1122,7 +1119,7 @@ public class S3ObjectAction implements ServletAction { * @return error code, and error string * @throws ParserConfigurationException, IOException, SAXException */ - private Tuple verifyParts( InputStream is, S3MultipartPart[] parts ) + private OrderedPair verifyParts( InputStream is, S3MultipartPart[] parts ) { try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); @@ -1147,7 +1144,7 @@ public class S3ObjectAction implements ServletAction { nodeSet = doc.getElementsByTagName( "Part" ); count = nodeSet.getLength(); } - if (count != parts.length) return new Tuple(400, "InvalidPart"); + if (count != parts.length) return new OrderedPair(400, "InvalidPart"); // -> get a list of all the children elements of the 'Part' parent element for( int i=0; i < count; i++ ) @@ -1179,20 +1176,20 @@ public class S3ObjectAction implements ServletAction { // -> do the parts given in the call XML match what was previously uploaded? if (lastNumber >= partNumber) { - return new Tuple(400, "InvalidPartOrder"); + return new OrderedPair(400, "InvalidPartOrder"); } if (partNumber != parts[i].getPartNumber() || eTag == null || !eTag.equalsIgnoreCase( "\"" + parts[i].getETag() + "\"" )) { - return new Tuple(400, "InvalidPart"); + return new OrderedPair(400, "InvalidPart"); } lastNumber = partNumber; } - return new Tuple(200, "Success"); + return new OrderedPair(200, "Success"); } catch( Exception e ) { - return new Tuple(500, e.toString()); + return new OrderedPair(500, e.toString()); } } } diff --git a/cloudbridge/src/com/cloud/bridge/service/S3SoapServiceImpl.java b/cloudbridge/src/com/cloud/bridge/service/controller/s3/S3SerializableServiceImplementation.java similarity index 93% rename from cloudbridge/src/com/cloud/bridge/service/S3SoapServiceImpl.java rename to cloudbridge/src/com/cloud/bridge/service/controller/s3/S3SerializableServiceImplementation.java index f0cf0cf197b..d4526d806ae 100644 --- a/cloudbridge/src/com/cloud/bridge/service/S3SoapServiceImpl.java +++ b/cloudbridge/src/com/cloud/bridge/service/controller/s3/S3SerializableServiceImplementation.java @@ -13,11 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.cloud.bridge.service; +package com.cloud.bridge.service.controller.s3; -import java.io.IOException; import java.util.Calendar; -import java.util.TimeZone; import org.apache.axis2.AxisFault; import org.apache.log4j.Logger; @@ -108,12 +106,38 @@ import com.cloud.bridge.service.core.s3.S3SetBucketAccessControlPolicyRequest; import com.cloud.bridge.service.core.s3.S3SetObjectAccessControlPolicyRequest; import com.cloud.bridge.service.exception.InternalErrorException; -public class S3SoapServiceImpl implements AmazonS3SkeletonInterface { - protected final static Logger logger = Logger.getLogger(S3SoapServiceImpl.class); +/* @Author Kelven Yang, John Zucker + * Implementation of S3 service requests as operations defined by the interface, com.amazon.s3.AmazonS3SkeletonInterface. + * The operations dispatched from this class are of the form of SOAP operations which define business logic to be executed by the request. + * The methods required for S3 services in accordance with the skeleton are either implementations of the following + * getBucketLoggingStatus + * copyObject + * getBucketAccessControlPolicy + * listBucket + * putObject + * createBucket + * listAllMyBuckets + * getObject + * deleteBucket + * setBucketLoggingStatus + * getObjectAccessControlPolicy + * deleteObject + * setBucketAccessControlPolicy + * setObjectAccessControlPolicy + * putObjectInline + * getObjectExtended + * or throw and Axis2 fault otherwise. + * These skeleton methods can be used as the implementation of services to satisfy SOAP calls, but also to provide the output + * to be serialized by the AXIOM XML processor. + * + * */ + +public class S3SerializableServiceImplementation implements AmazonS3SkeletonInterface { + protected final static Logger logger = Logger.getLogger(S3SerializableServiceImplementation.class); private S3Engine engine; - public S3SoapServiceImpl(S3Engine engine) { + public S3SerializableServiceImplementation(S3Engine engine) { this.engine = engine; } @@ -152,7 +176,7 @@ public class S3SoapServiceImpl implements AmazonS3SkeletonInterface { public GetBucketAccessControlPolicyResponse getBucketAccessControlPolicy( GetBucketAccessControlPolicy getBucketAccessControlPolicy) { - // after authentication, we should setup user context + // TODO - after authentication, we should setup user context return toGetBucketAccessControlPolicyResponse(engine.handleRequest( toEngineGetBucketAccessControlPolicyRequest(getBucketAccessControlPolicy))); } @@ -182,7 +206,7 @@ public class S3SoapServiceImpl implements AmazonS3SkeletonInterface { request.setBucketName(setBucketAccessControlPolicy.getBucket()); request.setAcl(toEngineAccessControlList(setBucketAccessControlPolicy.getAccessControlList())); - S3Response basicResponse = engine.handleRequest(request); + // S3Response basicResponse = engine.handleRequest(request); TODO - Needed? SetBucketAccessControlPolicyResponse response = new SetBucketAccessControlPolicyResponse(); return response; } diff --git a/cloudbridge/src/com/cloud/bridge/service/ServiceProvider.java b/cloudbridge/src/com/cloud/bridge/service/controller/s3/ServiceProvider.java similarity index 91% rename from cloudbridge/src/com/cloud/bridge/service/ServiceProvider.java rename to cloudbridge/src/com/cloud/bridge/service/controller/s3/ServiceProvider.java index 1545c14e712..96aa78340ff 100644 --- a/cloudbridge/src/com/cloud/bridge/service/ServiceProvider.java +++ b/cloudbridge/src/com/cloud/bridge/service/controller/s3/ServiceProvider.java @@ -15,7 +15,7 @@ * along with this program. If not, see . * */ -package com.cloud.bridge.service; +package com.cloud.bridge.service.controller.s3; import java.io.File; @@ -48,6 +48,8 @@ import com.cloud.bridge.persist.PersistException; import com.cloud.bridge.persist.dao.MHostDao; import com.cloud.bridge.persist.dao.SHostDao; import com.cloud.bridge.persist.dao.UserCredentialsDao; +import com.cloud.bridge.service.EC2SoapServiceImpl; +import com.cloud.bridge.service.UserInfo; import com.cloud.bridge.service.core.ec2.EC2Engine; import com.cloud.bridge.service.core.s3.S3BucketPolicy; import com.cloud.bridge.service.core.s3.S3Engine; @@ -55,7 +57,7 @@ import com.cloud.bridge.service.exception.ConfigurationException; import com.cloud.bridge.util.ConfigurationHelper; import com.cloud.bridge.util.DateHelper; import com.cloud.bridge.util.NetHelper; -import com.cloud.bridge.util.Tuple; +import com.cloud.bridge.util.OrderedPair; /** * @author Kelven Yang @@ -85,7 +87,7 @@ public class ServiceProvider { // register service implementation object engine = new S3Engine(); EC2_engine = new EC2Engine(); - serviceMap.put(AmazonS3SkeletonInterface.class, new S3SoapServiceImpl(engine)); + serviceMap.put(AmazonS3SkeletonInterface.class, new S3SerializableServiceImplementation(engine)); serviceMap.put(AmazonEC2SkeletonInterface.class, new EC2SoapServiceImpl(EC2_engine)); } @@ -117,18 +119,18 @@ public class ServiceProvider { * We return a tuple to distinguish between two cases: * (1) there is no entry in the map for bucketName, and (2) there is a null entry * in the map for bucketName. In case 2, the database was inspected for the - * bucket policy but it had none so we remember it here to reduce database lookups. + * bucket policy but it had none so we cache it here to reduce database lookups. * @param bucketName * @return Integer in the tuple means: -1 if no policy defined for the bucket, 0 if one defined * even if its set at null. */ - public Tuple getBucketPolicy(String bucketName) { + public OrderedPair getBucketPolicy(String bucketName) { if (policyMap.containsKey( bucketName )) { S3BucketPolicy policy = policyMap.get( bucketName ); - return new Tuple( policy, 0 ); + return new OrderedPair( policy, 0 ); } - else return new Tuple( null, -1 ); + else return new OrderedPair( null, -1 ); // For case (1) where the map has no entry for bucketName } /** diff --git a/cloudbridge/src/com/cloud/bridge/service/ServletAction.java b/cloudbridge/src/com/cloud/bridge/service/controller/s3/ServletAction.java similarity index 92% rename from cloudbridge/src/com/cloud/bridge/service/ServletAction.java rename to cloudbridge/src/com/cloud/bridge/service/controller/s3/ServletAction.java index 5355dca4ffd..14c898c5f88 100644 --- a/cloudbridge/src/com/cloud/bridge/service/ServletAction.java +++ b/cloudbridge/src/com/cloud/bridge/service/controller/s3/ServletAction.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.cloud.bridge.service; +package com.cloud.bridge.service.controller.s3; import java.io.IOException; diff --git a/cloudbridge/src/com/cloud/bridge/service/S3BucketAdapter.java b/cloudbridge/src/com/cloud/bridge/service/core/s3/S3BucketAdapter.java similarity index 80% rename from cloudbridge/src/com/cloud/bridge/service/S3BucketAdapter.java rename to cloudbridge/src/com/cloud/bridge/service/core/s3/S3BucketAdapter.java index 8c38b514576..0900a03c3f6 100644 --- a/cloudbridge/src/com/cloud/bridge/service/S3BucketAdapter.java +++ b/cloudbridge/src/com/cloud/bridge/service/core/s3/S3BucketAdapter.java @@ -13,15 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.cloud.bridge.service; +package com.cloud.bridge.service.core.s3; import java.io.InputStream; import java.io.OutputStream; import javax.activation.DataHandler; -import com.cloud.bridge.service.core.s3.S3MultipartPart; -import com.cloud.bridge.util.Tuple; +import com.cloud.bridge.util.OrderedPair; /** * @author Kelven Yang @@ -34,5 +33,5 @@ public interface S3BucketAdapter { DataHandler loadObject(String mountedRoot, String bucket, String fileName); DataHandler loadObjectRange(String mountedRoot, String bucket, String fileName, long startPos, long endPos); void deleteObject(String mountedRoot, String bucket, String fileName); - Tuple concatentateObjects(String mountedRoot, String destBucket, String fileName, String sourceBucket, S3MultipartPart[] parts, OutputStream os); + OrderedPair concatentateObjects(String mountedRoot, String destBucket, String fileName, String sourceBucket, S3MultipartPart[] parts, OutputStream os); } diff --git a/cloudbridge/src/com/cloud/bridge/service/core/s3/S3Engine.java b/cloudbridge/src/com/cloud/bridge/service/core/s3/S3Engine.java index 1ea90f5df53..43e860f62f8 100644 --- a/cloudbridge/src/com/cloud/bridge/service/core/s3/S3Engine.java +++ b/cloudbridge/src/com/cloud/bridge/service/core/s3/S3Engine.java @@ -39,6 +39,7 @@ import org.hibernate.LockMode; import org.hibernate.Session; import org.json.simple.parser.ParseException; +import com.cloud.bridge.io.S3FileSystemBucketAdapter; import com.cloud.bridge.model.MHost; import com.cloud.bridge.model.MHostMount; import com.cloud.bridge.model.SAcl; @@ -58,10 +59,8 @@ import com.cloud.bridge.persist.dao.SHostDao; import com.cloud.bridge.persist.dao.SMetaDao; import com.cloud.bridge.persist.dao.SObjectDao; import com.cloud.bridge.persist.dao.SObjectItemDao; -import com.cloud.bridge.service.S3BucketAdapter; -import com.cloud.bridge.service.S3FileSystemBucketAdapter; -import com.cloud.bridge.service.ServiceProvider; import com.cloud.bridge.service.UserContext; +import com.cloud.bridge.service.controller.s3.ServiceProvider; import com.cloud.bridge.service.core.s3.S3BucketPolicy.PolicyAccess; import com.cloud.bridge.service.core.s3.S3CopyObjectRequest.MetadataDirective; import com.cloud.bridge.service.core.s3.S3PolicyAction.PolicyActions; @@ -78,10 +77,10 @@ import com.cloud.bridge.service.exception.UnsupportedException; import com.cloud.bridge.util.DateHelper; import com.cloud.bridge.util.PolicyParser; import com.cloud.bridge.util.StringHelper; -import com.cloud.bridge.util.Tuple; +import com.cloud.bridge.util.OrderedPair; /** - * @author Kelven Yang + * @author Kelven Yang, John Zucker */ public class S3Engine { protected final static Logger logger = Logger.getLogger(S3Engine.class); @@ -172,7 +171,7 @@ public class S3Engine { if (PersistContext.acquireNamedLock("bucket.creation", LOCK_ACQUIRING_TIMEOUT_SECONDS)) { - Tuple shostTuple = null; + OrderedPair shostTuple = null; boolean success = false; try { SBucketDao bucketDao = new SBucketDao(); @@ -249,20 +248,20 @@ public class S3Engine { // -> delete the file - Tuple tupleBucketHost = getBucketStorageHost(sbucket); - S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(tupleBucketHost.getFirst()); - bucketAdapter.deleteContainer(tupleBucketHost.getSecond(), request.getBucketName()); + OrderedPair host_storagelocation_pair = getBucketStorageHost(sbucket); + S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(host_storagelocation_pair.getFirst()); + bucketAdapter.deleteContainer(host_storagelocation_pair.getSecond(), request.getBucketName()); // -> cascade-deleting can delete related SObject/SObjectItem objects, but not SAcl, SMeta and policy objects. We // need to perform deletion of these objects related to bucket manually. // Delete SMeta & SAcl objects: (1)Get all the objects in the bucket, (2)then all the items in each object, (3) then all meta & acl data for each item Set objectsInBucket = sbucket.getObjectsInBucket(); - Iterator it = objectsInBucket.iterator(); + Iterator it = objectsInBucket.iterator(); while( it.hasNext()) { SObject oneObject = (SObject)it.next(); Set itemsInObject = oneObject.getItems(); - Iterator is = itemsInObject.iterator(); + Iterator is = itemsInObject.iterator(); while( is.hasNext()) { SObjectItem oneItem = (SObjectItem)is.next(); @@ -446,12 +445,12 @@ public class S3Engine { return 404; } - Tuple tupleBucketHost = getBucketStorageHost(bucket); - S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(tupleBucketHost.getFirst()); + OrderedPair host_storagelocation_pair = getBucketStorageHost(bucket); + S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(host_storagelocation_pair.getFirst()); try { MultipartLoadDao uploadDao = new MultipartLoadDao(); - Tuple exists = uploadDao.multipartExits( uploadId ); + OrderedPair exists = uploadDao.multipartExits( uploadId ); if (null == exists) { logger.error( "initiateMultipartUpload failed since multipart upload" + uploadId + " does not exist" ); return 404; @@ -474,7 +473,7 @@ public class S3Engine { S3MultipartPart[] parts = uploadDao.getParts( uploadId, 10000, 0 ); for( int i=0; i < parts.length; i++ ) { - bucketAdapter.deleteObject( tupleBucketHost.getSecond(), ServiceProvider.getInstance().getMultipartDir(), parts[i].getPath()); + bucketAdapter.deleteObject( host_storagelocation_pair.getSecond(), ServiceProvider.getInstance().getMultipartDir(), parts[i].getPath()); } uploadDao.deleteUpload( uploadId ); @@ -558,14 +557,14 @@ public class S3Engine { context.setKeyName( request.getKey()); verifyAccess( context, "SBucket", bucket.getId(), SAcl.PERMISSION_WRITE ); - Tuple tupleBucketHost = getBucketStorageHost(bucket); - S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(tupleBucketHost.getFirst()); + OrderedPair host_storagelocation_pair = getBucketStorageHost(bucket); + S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(host_storagelocation_pair.getFirst()); String itemFileName = new String( uploadId + "-" + partNumber ); InputStream is = null; try { is = request.getDataInputStream(); - String md5Checksum = bucketAdapter.saveObject(is, tupleBucketHost.getSecond(), ServiceProvider.getInstance().getMultipartDir(), itemFileName); + String md5Checksum = bucketAdapter.saveObject(is, host_storagelocation_pair.getSecond(), ServiceProvider.getInstance().getMultipartDir(), itemFileName); response.setETag(md5Checksum); MultipartLoadDao uploadDao = new MultipartLoadDao(); @@ -622,17 +621,17 @@ public class S3Engine { // [B] Now we need to create the final re-assembled object // -> the allocObjectItem checks for the bucket policy PutObject permissions - Tuple tupleObjectItem = allocObjectItem(bucket, key, meta, null, request.getCannedAccess()); - Tuple tupleBucketHost = getBucketStorageHost(bucket); + OrderedPair object_objectitem_pair = allocObjectItem(bucket, key, meta, null, request.getCannedAccess()); + OrderedPair host_storagelocation_pair = getBucketStorageHost(bucket); - S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(tupleBucketHost.getFirst()); - String itemFileName = tupleObjectItem.getSecond().getStoredPath(); + S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(host_storagelocation_pair.getFirst()); + String itemFileName = object_objectitem_pair.getSecond().getStoredPath(); // -> Amazon defines that we must return a 200 response immediately to the client, but // -> we don't know the version header until we hit here httpResp.setStatus(200); httpResp.setContentType("text/xml; charset=UTF-8"); - String version = tupleObjectItem.getSecond().getVersion(); + String version = object_objectitem_pair.getSecond().getVersion(); if (null != version) httpResp.addHeader( "x-amz-version-id", version ); httpResp.flushBuffer(); @@ -642,12 +641,12 @@ public class S3Engine { // explicit transaction control to avoid holding transaction during long file concatenation process PersistContext.commitTransaction(); - Tuple result = bucketAdapter.concatentateObjects( tupleBucketHost.getSecond(), bucket.getName(), itemFileName, ServiceProvider.getInstance().getMultipartDir(), parts, os ); + OrderedPair result = bucketAdapter.concatentateObjects( host_storagelocation_pair.getSecond(), bucket.getName(), itemFileName, ServiceProvider.getInstance().getMultipartDir(), parts, os ); response.setETag(result.getFirst()); - response.setLastModified(DateHelper.toCalendar( tupleObjectItem.getSecond().getLastModifiedTime())); + response.setLastModified(DateHelper.toCalendar( object_objectitem_pair.getSecond().getLastModifiedTime())); SObjectItemDao itemDao = new SObjectItemDao(); - SObjectItem item = itemDao.get( tupleObjectItem.getSecond().getId()); + SObjectItem item = itemDao.get( object_objectitem_pair.getSecond().getId()); item.setMd5(result.getFirst()); item.setStoredSize(result.getSecond().longValue()); response.setResultCode(200); @@ -674,13 +673,13 @@ public class S3Engine { if (bucket == null) throw new NoSuchObjectException("Bucket " + bucketName + " does not exist"); - // -> is the caller allowed to write the object? - // -> the allocObjectItem checks for the bucket policy PutObject permissions - Tuple tupleObjectItem = allocObjectItem(bucket, key, meta, acl, request.getCannedAccess()); - Tuple tupleBucketHost = getBucketStorageHost(bucket); + // Is the caller allowed to write the object? + // The allocObjectItem checks for the bucket policy PutObject permissions + OrderedPair object_objectitem_pair = allocObjectItem(bucket, key, meta, acl, request.getCannedAccess()); + OrderedPair host_storagelocation_pair = getBucketStorageHost(bucket); - S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(tupleBucketHost.getFirst()); - String itemFileName = tupleObjectItem.getSecond().getStoredPath(); + S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(host_storagelocation_pair.getFirst()); + String itemFileName = object_objectitem_pair.getSecond().getStoredPath(); InputStream is = null; try { @@ -688,13 +687,13 @@ public class S3Engine { PersistContext.commitTransaction(); is = request.getDataInputStream(); - String md5Checksum = bucketAdapter.saveObject(is, tupleBucketHost.getSecond(), bucket.getName(), itemFileName); + String md5Checksum = bucketAdapter.saveObject(is, host_storagelocation_pair.getSecond(), bucket.getName(), itemFileName); response.setETag(md5Checksum); - response.setLastModified(DateHelper.toCalendar( tupleObjectItem.getSecond().getLastModifiedTime())); - response.setVersion( tupleObjectItem.getSecond().getVersion()); + response.setLastModified(DateHelper.toCalendar( object_objectitem_pair.getSecond().getLastModifiedTime())); + response.setVersion( object_objectitem_pair.getSecond().getVersion()); SObjectItemDao itemDao = new SObjectItemDao(); - SObjectItem item = itemDao.get( tupleObjectItem.getSecond().getId()); + SObjectItem item = itemDao.get( object_objectitem_pair.getSecond().getId()); item.setMd5(md5Checksum); item.setStoredSize(contentLength); PersistContext.getSession().save(item); @@ -729,25 +728,25 @@ public class S3Engine { SBucket bucket = bucketDao.getByName(bucketName); if(bucket == null) throw new NoSuchObjectException("Bucket " + bucketName + " does not exist"); - // -> is the caller allowed to write the object? - // -> the allocObjectItem checks for the bucket policy PutObject permissions - Tuple tupleObjectItem = allocObjectItem(bucket, key, meta, acl, null); - Tuple tupleBucketHost = getBucketStorageHost(bucket); + // Is the caller allowed to write the object? + // The allocObjectItem checks for the bucket policy PutObject permissions + OrderedPair object_objectitem_pair = allocObjectItem(bucket, key, meta, acl, null); + OrderedPair host_storagelocation_pair = getBucketStorageHost(bucket); - S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(tupleBucketHost.getFirst()); - String itemFileName = tupleObjectItem.getSecond().getStoredPath(); + S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(host_storagelocation_pair.getFirst()); + String itemFileName = object_objectitem_pair.getSecond().getStoredPath(); InputStream is = null; try { // explicit transaction control to avoid holding transaction during file-copy process PersistContext.commitTransaction(); is = request.getInputStream(); - String md5Checksum = bucketAdapter.saveObject(is, tupleBucketHost.getSecond(), bucket.getName(), itemFileName); + String md5Checksum = bucketAdapter.saveObject(is, host_storagelocation_pair.getSecond(), bucket.getName(), itemFileName); response.setETag(md5Checksum); - response.setLastModified(DateHelper.toCalendar( tupleObjectItem.getSecond().getLastModifiedTime())); + response.setLastModified(DateHelper.toCalendar( object_objectitem_pair.getSecond().getLastModifiedTime())); SObjectItemDao itemDao = new SObjectItemDao(); - SObjectItem item = itemDao.get( tupleObjectItem.getSecond().getId()); + SObjectItem item = itemDao.get( object_objectitem_pair.getSecond().getId()); item.setMd5(md5Checksum); item.setStoredSize(contentLength); PersistContext.getSession().save(item); @@ -1000,7 +999,7 @@ public class S3Engine { { int i = 0; S3MetaDataEntry[] metaEntries = new S3MetaDataEntry[ itemMetaData.size() ]; - ListIterator it = itemMetaData.listIterator(); + ListIterator it = itemMetaData.listIterator(); while( it.hasNext()) { SMeta oneTag = (SMeta)it.next(); S3MetaDataEntry oneEntry = new S3MetaDataEntry(); @@ -1025,7 +1024,7 @@ public class S3Engine { response.setVersion( item.getVersion()); if (request.isInlineData()) { - Tuple tupleSHostInfo = getBucketStorageHost(sbucket); + OrderedPair tupleSHostInfo = getBucketStorageHost(sbucket); S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(tupleSHostInfo.getFirst()); if ( 0 <= bytesStart && 0 <= bytesEnd ) @@ -1132,9 +1131,9 @@ public class S3Engine { // -> delete the file holding the object if (null != storedPath) { - Tuple tupleBucketHost = getBucketStorageHost( sbucket ); - S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter( tupleBucketHost.getFirst()); - bucketAdapter.deleteObject( tupleBucketHost.getSecond(), bucketName, storedPath ); + OrderedPair host_storagelocation_pair = getBucketStorageHost( sbucket ); + S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter( host_storagelocation_pair.getFirst()); + bucketAdapter.deleteObject( host_storagelocation_pair.getSecond(), bucketName, storedPath ); } response.setResultCode(204); @@ -1147,7 +1146,7 @@ public class S3Engine { List itemMetaData = metaDao.getByTarget( "SObjectItem", itemId ); if (null != itemMetaData) { - ListIterator it = itemMetaData.listIterator(); + ListIterator it = itemMetaData.listIterator(); while( it.hasNext()) { SMeta oneTag = (SMeta)it.next(); metaDao.delete( oneTag ); @@ -1160,7 +1159,7 @@ public class S3Engine { List itemAclData = aclDao.listGrants( target, itemId ); if (null != itemAclData) { - ListIterator it = itemAclData.listIterator(); + ListIterator it = itemAclData.listIterator(); while( it.hasNext()) { SAcl oneTag = (SAcl)it.next(); aclDao.delete( oneTag ); @@ -1173,7 +1172,7 @@ public class S3Engine { List bucketAclData = aclDao.listGrants( "SBucket", bucketId ); if (null != bucketAclData) { - ListIterator it = bucketAclData.listIterator(); + ListIterator it = bucketAclData.listIterator(); while( it.hasNext()) { SAcl oneTag = (SAcl)it.next(); aclDao.delete( oneTag ); @@ -1318,18 +1317,18 @@ public class S3Engine { return entry; } - public Tuple getBucketStorageHost(SBucket bucket) + public OrderedPair getBucketStorageHost(SBucket bucket) { MHostMountDao mountDao = new MHostMountDao(); SHost shost = bucket.getShost(); if(shost.getHostType() == SHost.STORAGE_HOST_TYPE_LOCAL) { - return new Tuple(shost, shost.getExportRoot()); + return new OrderedPair(shost, shost.getExportRoot()); } MHostMount mount = mountDao.getHostMount(ServiceProvider.getInstance().getManagementHostId(), shost.getId()); if(mount != null) { - return new Tuple(shost, mount.getMountPath()); + return new OrderedPair(shost, mount.getMountPath()); } // need to redirect request to other node @@ -1364,7 +1363,7 @@ public class S3Engine { * @param overrideName * @return */ - private Tuple allocBucketStorageHost(String bucketName, String overrideName) + private OrderedPair allocBucketStorageHost(String bucketName, String overrideName) { MHostDao mhostDao = new MHostDao(); SHostDao shostDao = new SHostDao(); @@ -1379,7 +1378,7 @@ public class S3Engine { MHostMount mount = mounts[random.nextInt(mounts.length)]; S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(mount.getShost()); bucketAdapter.createContainer(mount.getMountPath(), (null != overrideName ? overrideName : bucketName)); - return new Tuple(mount.getShost(), mount.getMountPath()); + return new OrderedPair(mount.getShost(), mount.getMountPath()); } // To make things simple, only allow one local mounted storage root @@ -1391,7 +1390,7 @@ public class S3Engine { S3BucketAdapter bucketAdapter = getStorageHostBucketAdapter(localSHost); bucketAdapter.createContainer(localSHost.getExportRoot(),(null != overrideName ? overrideName : bucketName)); - return new Tuple(localSHost, localStorageRoot); + return new OrderedPair(localSHost, localStorageRoot); } throw new OutOfStorageException("No storage host is available"); @@ -1415,7 +1414,7 @@ public class S3Engine { * @throws IOException */ @SuppressWarnings("deprecation") - public Tuple allocObjectItem(SBucket bucket, String nameKey, S3MetaDataEntry[] meta, S3AccessControlList acl, String cannedAccessPolicy) + public OrderedPair allocObjectItem(SBucket bucket, String nameKey, S3MetaDataEntry[] meta, S3AccessControlList acl, String cannedAccessPolicy) { SObjectDao objectDao = new SObjectDao(); SObjectItemDao objectItemDao = new SObjectItemDao(); @@ -1521,7 +1520,7 @@ public class S3Engine { } session.update(item); - return new Tuple(object, item); + return new OrderedPair(object, item); } @@ -1623,7 +1622,11 @@ public class S3Engine { { S3BucketPolicy policy = null; - // -> on error of getting a policy ignore it + // Ordinarily a REST request will pass in an S3PolicyContext for a given bucket by this stage. The HttpServletRequest object + // should be held in the UserContext ready for extraction of the S3BucketPolicy. + // If there is an error in obtaining the request object or in loading the policy then log the failure and return a S3PolicyContext + // which indicates DEFAULT_DENY. Where there is no failure, the policy returned should be specific to the Canonical User ID of the requester. + try { // -> in SOAP the HttpServletRequest object is hidden and not passed around if (null != context) { @@ -1669,14 +1672,14 @@ public class S3Engine { } /** - * This function verifies that the accessing client has the requested - * permission on the object/bucket/Acl represented by the tuble: + * This method verifies that the accessing client has the requested + * permission on the object/bucket/Acl represented by the tuple: * * For cases where an ACL is meant for any authenticated user we place a "*" for the - * Canonical User Id ("*" is not a legal Cloud Stack Access key). + * Canonical User Id. N.B. - "*" is not a legal Cloud (Bridge) Access key. * * For cases where an ACL is meant for any anonymous user (or 'AllUsers') we place a "A" for the - * Canonical User Id ("A" is not a legal Cloud Stack Access key). + * Canonical User Id. N.B. - "A" is not a legal Cloud (Bridge) Access key. */ public static void accessAllowed( String target, long targetId, int requestedPermission ) { @@ -1684,25 +1687,25 @@ public class S3Engine { SAclDao aclDao = new SAclDao(); - // -> if an annoymous request, then canonicalUserId is an empty string + // If an annoymous request, then canonicalUserId is an empty string String userId = UserContext.current().getCanonicalUserId(); if ( 0 == userId.length()) { - // -> is an anonymous principal ACL set for this ? + // Is an anonymous principal ACL set for this ? if (hasPermission( aclDao.listGrants( target, targetId, "A" ), requestedPermission )) return; } else - { // -> no priviledges means no access allowed + { if (hasPermission( aclDao.listGrants( target, targetId, userId ), requestedPermission )) return; - - // -> or maybe there is any principal authenticated ACL set for this ? + // Or alternatively is there is any principal authenticated ACL set for this ? if (hasPermission( aclDao.listGrants( target, targetId, "*" ), requestedPermission )) return; } + // No privileges implies that no access is allowed in the case of an anonymous user throw new PermissionDeniedException( "Access Denied - ACLs do not give user the required permission" ); } /** - * This function assumes that the bucket has been tested to make sure it exists before + * This method assumes that the bucket has been tested to make sure it exists before * it is called. * * @param context @@ -1712,7 +1715,7 @@ public class S3Engine { public static S3BucketPolicy loadPolicy( S3PolicyContext context ) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException, ParseException { - Tuple result = ServiceProvider.getInstance().getBucketPolicy( context.getBucketName()); + OrderedPair result = ServiceProvider.getInstance().getBucketPolicy( context.getBucketName()); S3BucketPolicy policy = result.getFirst(); if ( null == policy ) { @@ -1772,7 +1775,8 @@ public class S3Engine { int fourth = Integer.parseInt( parts[3] ); throw new InvalidBucketName( bucketName + " is formatted as an IP address" ); } - catch( NumberFormatException e ) {} + catch( NumberFormatException e ) + {throw new InvalidBucketName( bucketName);} } @@ -1804,12 +1808,12 @@ public class S3Engine { } } - private static boolean hasPermission( List priviledges, int requestedPermission ) + private static boolean hasPermission( List privileges, int requestedPermission ) { - ListIterator it = priviledges.listIterator(); + ListIterator it = privileges.listIterator(); while( it.hasNext()) { - // -> is the requested permission "contained" in one or the granted rights for this user + // True providing the requested permission is contained in one or the granted rights for this user. False otherwise. SAcl rights = (SAcl)it.next(); int permission = rights.getPermission(); if (requestedPermission == (permission & requestedPermission)) return true; @@ -1818,13 +1822,13 @@ public class S3Engine { } /** - * ifRange is true and IfUnmodifiedSince or IfMatch fails then we return the entire object (indicated by + * ifRange is true and ifUnmodifiedSince or IfMatch fails then we return the entire object (indicated by * returning a -1 as the function result. * * @param ifCond - conditional get defined by these tests * @param lastModified - value used on ifModifiedSince or ifUnmodifiedSince * @param ETag - value used on ifMatch and ifNoneMatch - * @param ifRange - using an If-Range HTTP functionality + * @param ifRange - using an if-Range HTTP functionality * @return -1 means return the entire object with an HTTP 200 (not a subrange) */ private int conditionPassed( S3ConditionalHeaders ifCond, Date lastModified, String ETag, boolean ifRange ) diff --git a/cloudbridge/src/com/cloud/bridge/service/core/s3/S3PutObjectInlineRequest.java b/cloudbridge/src/com/cloud/bridge/service/core/s3/S3PutObjectInlineRequest.java index 4a3ab7999ca..b37655cabd7 100644 --- a/cloudbridge/src/com/cloud/bridge/service/core/s3/S3PutObjectInlineRequest.java +++ b/cloudbridge/src/com/cloud/bridge/service/core/s3/S3PutObjectInlineRequest.java @@ -22,7 +22,7 @@ import java.io.InputStream; import javax.activation.DataHandler; /** - * @author Kelven Yang + * @author Kelven Yang, John Zucker */ public class S3PutObjectInlineRequest extends S3Request { protected String bucketName; @@ -30,7 +30,7 @@ public class S3PutObjectInlineRequest extends S3Request { protected long contentLength; protected S3MetaDataEntry[] metaEntries; protected S3AccessControlList acl; - protected String cannedAccessPolicy; // -> REST only sets an acl with a simple keyword + protected String cannedAccessPolicy; // Canned ACLs are public-read, public-read-write, private, authenticated-read or log-delivery-write protected DataHandler data; protected String dataAsString; diff --git a/cloudbridge/src/com/cloud/bridge/tool/CloudS3CmdTool.java b/cloudbridge/src/com/cloud/bridge/tool/CloudS3CmdTool.java deleted file mode 100644 index 85f770412fd..00000000000 --- a/cloudbridge/src/com/cloud/bridge/tool/CloudS3CmdTool.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.cloud.bridge.tool; - -import java.io.File; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; - -import javax.activation.DataHandler; - -import org.apache.axis2.AxisFault; -import org.apache.log4j.xml.DOMConfigurator; - -import com.amazon.s3.client.AmazonS3Stub; -import com.amazon.s3.client.AmazonS3Stub.CreateBucket; -import com.amazon.s3.client.AmazonS3Stub.CreateBucketResponse; -import com.amazon.s3.client.AmazonS3Stub.DeleteBucket; -import com.amazon.s3.client.AmazonS3Stub.DeleteBucketResponse; -import com.amazon.s3.client.AmazonS3Stub.DeleteObject; -import com.amazon.s3.client.AmazonS3Stub.DeleteObjectResponse; -import com.amazon.s3.client.AmazonS3Stub.ListBucket; -import com.amazon.s3.client.AmazonS3Stub.ListBucketResponse; -import com.amazon.s3.client.AmazonS3Stub.ListBucketResult; -import com.amazon.s3.client.AmazonS3Stub.ListEntry; -import com.amazon.s3.client.AmazonS3Stub.PrefixEntry; -import com.amazon.s3.client.AmazonS3Stub.PutObjectInline; -import com.amazon.s3.client.AmazonS3Stub.PutObjectInlineResponse; -import com.amazon.s3.client.AmazonS3Stub.Status; - -/** - * @author Kelven Yang - */ -public class CloudS3CmdTool { - private String serviceUrl; - - private AmazonS3Stub serviceStub; - - private static void configLog4j() { - URL configUrl = System.class.getResource("/conf/log4j-cloud-bridge.xml"); - if(configUrl == null) - configUrl = ClassLoader.getSystemResource("log4j-cloud-bridge.xml"); - - if(configUrl == null) - configUrl = ClassLoader.getSystemResource("conf/log4j-cloud-bridge.xml"); - - if(configUrl != null) { - try { - System.out.println("Configure log4j using " + configUrl.toURI().toString()); - } catch (URISyntaxException e1) { - e1.printStackTrace(); - } - - try { - File file = new File(configUrl.toURI()); - - System.out.println("Log4j configuration from : " + file.getAbsolutePath()); - DOMConfigurator.configureAndWatch(file.getAbsolutePath(), 10000); - } catch (URISyntaxException e) { - System.out.println("Unable to convert log4j configuration Url to URI"); - } - } else { - System.out.println("Configure log4j with default properties"); - } - } - - private static Map getNamedParameters(String[] args) { - Map params = new HashMap(); - for(int i = 1; i < args.length; i++) { - if(args[i].charAt(0) == '-') { - String[] tokens = args[i].substring(1).split("="); - if(tokens.length == 2) { - params.put(tokens[0], tokens[1]); - } - } - } - - return params; - } - - private static boolean validateNamedParameters(Map params, String... keys) { - for(String key : keys) { - if(params.get(key) == null || params.get(key).isEmpty()) - return false; - } - return true; - } - - public static void main(String[] args) { - configLog4j(); - (new CloudS3CmdTool()).run(args); - } - - private void run(String[] args) { - Map env = System.getenv(); - for (String envName : env.keySet()) { - if(envName.equals("CLOUD_SERVICE_URL")) - serviceUrl = env.get(envName); - } - - if(serviceUrl == null) { - System.out.println("Please set CLOUD_SERVICE_URL environment variable"); - System.exit(0); - } - - if(args.length < 1) { - System.out.println("Please specify a command to run"); - System.exit(0); - } - - try { - serviceStub = new AmazonS3Stub(serviceUrl); - } catch (AxisFault e) { - System.out.println("Unable to initialize service stub"); - e.printStackTrace(); - System.exit(0); - } - - // command dispatch - if(args[0].equals("bucket-create")) { - createBucket(args); - } else if(args[0].equals("bucket-delete")) { - deleteBucket(args); - } else if(args[0].equals("bucket-list")) { - listBucket(args); - } else if(args[0].equals("object-put-inline")) { - putObjectInline(args); - } else if(args[0].equals("object-delete")) { - deleteObject(args); - } - } - - private void createBucket(String[] args) { - if(args.length < 2) { - System.out.println("Usage: bucket-create "); - System.exit(0); - } - - try { - CreateBucket bucket = new CreateBucket(); - bucket.setBucket(args[1]); - bucket.setAWSAccessKeyId( "TODO1" ); - bucket.setSignature("TODO2"); - bucket.setTimestamp(Calendar.getInstance()); - - CreateBucketResponse response = serviceStub.createBucket(bucket); - System.out.println("Bucket " + response.getCreateBucketReturn().getBucketName() + " has been created successfully"); - } catch(Exception e) { - System.out.println("Failed to execute bucket-create due to " + e.getMessage()); - } - } - - private void deleteBucket(String[] args) { - if(args.length < 2) { - System.out.println("Usage: bucket-delete "); - System.exit(0); - } - - try { - DeleteBucket request = new DeleteBucket(); - request.setBucket(args[1]); - request.setSignature("TODO"); - request.setTimestamp(Calendar.getInstance()); - - DeleteBucketResponse response = serviceStub.deleteBucket(request); - Status status = response.getDeleteBucketResponse(); - if(status.getCode() == 200) { - System.out.println("Bucket " + args[1] + " has been deleted successfully"); - } else { - System.out.println("Unable to delete bucket " + args[1] + " - " + status.getDescription()); - } - } catch(Exception e) { - System.out.println("Failed to execute bucket-delete due to " + e.getMessage()); - } - } - - private void listBucket(String[] args) { - if(args.length < 2) { - System.out.println("Usage: bucket-list -prefix= -delimiter= -marker= -max= "); - System.exit(0); - } - - try { - ListBucket request = new ListBucket(); - Map params = getNamedParameters(args); - - request.setBucket(args[args.length - 1]); - request.setCredential("TODO"); - if(params.get("prefix") != null) - request.setPrefix(params.get("prefix")); - if(params.get("delimiter") != null) - request.setDelimiter(params.get("delimiter")); - if(params.get("marker") != null) - request.setMarker(params.get("marker")); - if(params.get("max") != null) { - try { - int maxKeys = Integer.parseInt(params.get("max")); - request.setMaxKeys(maxKeys); - } catch(Exception e){ - System.out.println("-max parameter should be a numeric value"); - } - } - request.setAWSAccessKeyId("TODO"); - request.setCredential("TODO"); - request.setSignature("TODO"); - request.setTimestamp(Calendar.getInstance()); - - ListBucketResponse response = serviceStub.listBucket(request); - ListBucketResult result = response.getListBucketResponse(); - System.out.println("\tContent of Bucket " + result.getName()); - System.out.println("\tListing with prefix: " + result.getPrefix() + ", delimiter: " - + result.getDelimiter() + ", marker: " + result.getMarker() + ", max: " + result.getMaxKeys()); - - ListEntry[] entries = result.getContents(); - if(entries != null) { - for(int i = 0; i < entries.length; i++) { - ListEntry entry = entries[i]; - System.out.print("\t"); - System.out.print(entry.getSize()); - System.out.print("\t"); - System.out.print(entry.getKey()); - System.out.print("\t"); - System.out.print(entry.getETag()); - System.out.print("\n"); - } - } - - PrefixEntry[] prefixEntries = result.getCommonPrefixes(); - if(prefixEntries != null) { - System.out.print("\n\n"); - - for(int i = 0; i < prefixEntries.length; i++) { - System.out.print("\t\t"); - System.out.print(prefixEntries[i].getPrefix()); - System.out.print("\n"); - } - } - } catch(Exception e) { - System.out.println("Failed to execute bucket-list due to " + e.getMessage()); - } - } - - private void putObjectInline(String[] args) { - if(args.length < 4) { - System.out.println("Usage: object-put-inline -bucket= -name= "); - System.exit(0); - } - - Map params = getNamedParameters(args); - if(!validateNamedParameters(params, "bucket", "name")) { - System.out.println("Usage: object-put-inline -bucket= -name= "); - System.exit(0); - } - - File file = new File(args[args.length -1]); - if(!file.exists()) { - System.out.println("Unable to find file " + args[args.length -1]); - System.exit(0); - } - - try { - PutObjectInline request = new PutObjectInline(); - request.setBucket(params.get("bucket")); - request.setKey(params.get("name")); - request.setContentLength(file.length()); - request.setAWSAccessKeyId("TODO"); - request.setCredential("TODO"); - request.setSignature("TODO"); - request.setTimestamp(Calendar.getInstance()); - request.setData(new DataHandler(file.toURL())); - - PutObjectInlineResponse response = serviceStub.putObjectInline(request); - System.out.println("Object has been posted successfully. ETag: " + response.getPutObjectInlineResponse().getETag()); - } catch(Exception e) { - System.out.println("Failed to execute object-put-inline due to " + e.getMessage()); - } - } - - private void deleteObject(String[] args) { - if(args.length < 3) { - System.out.println("Usage: object-delete -bucket= -name="); - System.exit(0); - } - - Map params = getNamedParameters(args); - if(!validateNamedParameters(params, "bucket", "name")) { - System.out.println("Usage: object-delete -bucket= -name="); - System.exit(0); - } - - try { - DeleteObject request = new DeleteObject(); - request.setAWSAccessKeyId("TODO"); - request.setBucket(params.get("bucket")); - request.setKey(params.get("name")); - request.setSignature("TODO"); - request.setCredential("TODO"); - request.setTimestamp(Calendar.getInstance()); - - DeleteObjectResponse response = serviceStub.deleteObject(request); - if(response.getDeleteObjectResponse().getCode() == 200) - System.out.println("Object " + params.get("name") + " has been deleted successfully"); - else - System.out.println("Object " + params.get("name") + " can not be deleted. Error: " - + response.getDeleteObjectResponse().getCode()); - } catch(Exception e) { - System.out.println("Failed to execute object-delete due to " + e.getMessage()); - } - } -} diff --git a/cloudbridge/src/com/cloud/bridge/util/Tuple.java b/cloudbridge/src/com/cloud/bridge/util/OrderedPair.java similarity index 67% rename from cloudbridge/src/com/cloud/bridge/util/Tuple.java rename to cloudbridge/src/com/cloud/bridge/util/OrderedPair.java index a620b55bbf5..beaae9baebb 100644 --- a/cloudbridge/src/com/cloud/bridge/util/Tuple.java +++ b/cloudbridge/src/com/cloud/bridge/util/OrderedPair.java @@ -15,18 +15,19 @@ */ package com.cloud.bridge.util; -/** - * - * @author Kelven Yang - * +/** + * @author Kelven Yang, John Zucker + * Reusable class whose instances encode any ordered pair (or 2-tuple) of values of types T1 and T2 + * Provide getters: getFirst(), getSecond() + * Provide setters: setFirst(val), setSecond(val) * @param * @param */ -public class Tuple { +public class OrderedPair { T1 first; T2 second; - public Tuple(T1 t1, T2 t2) { + public OrderedPair(T1 t1, T2 t2) { first = t1; second = t2; } @@ -35,7 +36,7 @@ public class Tuple { return first; } - public Tuple setFirst(T1 t1) { + public OrderedPair setFirst(T1 t1) { first = t1; return this; } @@ -44,7 +45,7 @@ public class Tuple { return second; } - public Tuple setSecond(T2 t2) { + public OrderedPair setSecond(T2 t2) { second = t2; return this; } diff --git a/cloudbridge/src/com/cloud/bridge/util/RestAuth.java b/cloudbridge/src/com/cloud/bridge/util/RestAuth.java index 93222c0716b..9c4eb8c095a 100755 --- a/cloudbridge/src/com/cloud/bridge/util/RestAuth.java +++ b/cloudbridge/src/com/cloud/bridge/util/RestAuth.java @@ -261,7 +261,6 @@ public class RestAuth { * @throws UnsupportedEncodingException */ - // TODO - Hi Pri - Make this validate correctly with StringToSign for verb POST and other cases public boolean verifySignature( String httpVerb, String secretKey, String signature ) throws SignatureException, UnsupportedEncodingException {