Skip to content

Commit

Permalink
fix: handle SSE in copyObject() properly and have one source code.
Browse files Browse the repository at this point in the history
Added new version of copyObject(). Note: this method makes source and
destination argument swapping correctly to denote on which bucket and
object the request is sent.

```
public void copyObject(String bucketName, String objectName, Map<String,String> headerMap, ServerSideEncryption sse,
                       String srcBucketName, String srcObjectName, ServerSideEncryption srcSse,
                       CopyConditions copyConditions)
```
  • Loading branch information
balamurugana committed Jul 15, 2019
1 parent 6d6141c commit 7c2a2e4
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 84 deletions.
191 changes: 131 additions & 60 deletions api/src/main/java/io/minio/MinioClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -1300,6 +1300,19 @@ private void checkReadRequestSse(ServerSideEncryption sse) throws InvalidArgumen
}
}

private void checkWriteRequestSse(ServerSideEncryption sse) throws InvalidArgumentException {
if (sse == null) {
return;
}

if (!this.baseUrl.isHttps()) {
if (sse.getType() == ServerSideEncryption.Type.SSE_C || sse.getType() == ServerSideEncryption.Type.SSE_KMS) {
throw new InvalidArgumentException(sse.getType().name()
+ " operations must be performed over a secure connection.");
}
}
}

/**
* Executes GET method for given request parameters.
*
Expand Down Expand Up @@ -2002,13 +2015,15 @@ public void getObject(String bucketName, String objectName, ServerSideEncryption
* @throws XmlPullParserException upon parsing response xml
* @throws InvalidArgumentException upon invalid value is passed to a method.
* @throws InvalidResponseException upon a non-xml response from server
*
* @deprecated As of release 6.1
*/
@Deprecated
public void copyObject(String bucketName, String objectName, String destBucketName)
throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException,
NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException,
InvalidArgumentException, InvalidResponseException {

copyObject(bucketName, objectName, destBucketName, null, null, null);
copyObject(destBucketName, objectName, null, null, bucketName, objectName, null, null);
}

/**
Expand Down Expand Up @@ -2045,13 +2060,18 @@ public void copyObject(String bucketName, String objectName, String destBucketNa
* @throws XmlPullParserException upon parsing response xml
* @throws InvalidArgumentException upon invalid value is passed to a method.
* @throws InvalidResponseException upon a non-xml response from server
*
* @deprecated As of release 6.1
*/
@Deprecated
public void copyObject(String bucketName, String objectName, String destBucketName, String destObjectName)
throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException,
NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException,
InvalidArgumentException, InvalidResponseException {

copyObject(bucketName, objectName, destBucketName, destObjectName, null, null);
if (destObjectName == null) {
destObjectName = objectName;
}
copyObject(destBucketName, destObjectName, null, null, bucketName, objectName, null, null);
}

/**
Expand Down Expand Up @@ -2090,14 +2110,15 @@ public void copyObject(String bucketName, String objectName, String destBucketNa
* @throws XmlPullParserException upon parsing response xml
* @throws InvalidArgumentException upon invalid value is passed to a method.
* @throws InvalidResponseException upon a non-xml response from server
*
* @deprecated As of release 6.1
*/
public void copyObject(String bucketName, String objectName, String destBucketName,
CopyConditions copyConditions)
@Deprecated
public void copyObject(String bucketName, String objectName, String destBucketName, CopyConditions copyConditions)
throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException,
NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException,
InvalidArgumentException, InvalidResponseException {

copyObject(bucketName, objectName, destBucketName, null, copyConditions, null);
copyObject(destBucketName, objectName, null, null, bucketName, objectName, null, copyConditions);
}

/**
Expand Down Expand Up @@ -2139,14 +2160,19 @@ public void copyObject(String bucketName, String objectName, String destBucketNa
* @throws XmlPullParserException upon parsing response xml
* @throws InvalidArgumentException upon invalid value is passed to a method.
* @throws InvalidResponseException upon a non-xml response from server
*
* @deprecated As of release 6.1
*/
public void copyObject(String bucketName, String objectName, String destBucketName,
String destObjectName, CopyConditions copyConditions)
@Deprecated
public void copyObject(String bucketName, String objectName, String destBucketName, String destObjectName,
CopyConditions copyConditions)
throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException,
NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException,
InvalidArgumentException, InvalidResponseException {

copyObject(bucketName, objectName, destBucketName, destObjectName, copyConditions, null);
if (destObjectName == null) {
destObjectName = objectName;
}
copyObject(destBucketName, destObjectName, null, null, bucketName, objectName, null, copyConditions);
}

/**
Expand Down Expand Up @@ -2192,30 +2218,19 @@ public void copyObject(String bucketName, String objectName, String destBucketNa
* @throws XmlPullParserException upon parsing response xml
* @throws InvalidArgumentException upon invalid value is passed to a method.
* @throws InvalidResponseException upon a non-xml response from server
*
* @deprecated As of release 6.1
*/
@Deprecated
public void copyObject(String bucketName, String objectName, ServerSideEncryption sseSource, String destBucketName,
String destObjectName, CopyConditions copyConditions, ServerSideEncryption sseTarget)
throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException,
NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException,
InvalidArgumentException, InvalidResponseException {

if ((sseTarget.getType() == ServerSideEncryption.Type.SSE_C) && (!this.baseUrl.isHttps())) {
throw new InvalidArgumentException("SSE_C operations must be performed over a secure connection.");
} else if ((sseTarget.getType() == (ServerSideEncryption.Type.SSE_KMS)) && (!this.baseUrl.isHttps())) {
throw new InvalidArgumentException("SSE_KMS operations must be performed over a secure connection.");
}
Map<String, String> headerTarget = new HashMap<>();
Map<String, String> headers = new HashMap<>();
sseTarget.marshal(headerTarget);
if (sseTarget.getType() == ServerSideEncryption.Type.SSE_C) {
Map<String, String> headerSource = new HashMap<>();
sseSource.marshal(headerSource);
headers.putAll(headerSource);
headers.putAll(headerTarget);
} else {
headers.putAll(headerTarget);
if (destObjectName == null) {
destObjectName = objectName;
}
copyObject(bucketName, objectName, destBucketName, destObjectName, copyConditions, headers);
copyObject(destBucketName, destObjectName, null, sseTarget, bucketName, objectName, sseSource, copyConditions);
}

/**
Expand Down Expand Up @@ -2260,49 +2275,114 @@ public void copyObject(String bucketName, String objectName, ServerSideEncryptio
* @throws InternalException upon internal library error
* @throws InvalidArgumentException upon invalid value is passed to a method.
* @throws InvalidResponseException upon a non-xml response from server
*
* @deprecated As of release 6.1
*/
@Deprecated
public void copyObject(String bucketName, String objectName, String destBucketName,
String destObjectName, CopyConditions copyConditions,
Map<String,String> metadata)
throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException,
NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException,
InvalidArgumentException, InvalidResponseException {
if (destObjectName == null) {
destObjectName = objectName;
}
copyObject(destBucketName, destObjectName, metadata, null, bucketName, objectName, null, copyConditions);
}


/**
* Copy a source object into a new object with the provided name in the provided bucket.
* optionally can take a key value CopyConditions and server side encryption as well for
* conditionally attempting copyObject.
*
* </p>
* <b>Example:</b><br>
*
* <pre>
* {@code minioClient.copyObject("my-bucketname", "my-objectname", headers, sse, "my-srcbucketname",
* "my-srcobjname", srcSse, copyConditions);}
* </pre>
*
* @param bucketName
* Destination bucket name.
* @param objectName
* Destination object name.
* @param headerMap
* Destination object custom metadata.
* @param sse
* Server side encryption of destination object.
* @param srcBucketName
* Source bucket name.
* @param srcObjectName
* Source object name.
* @param srcSse
* Server side encryption of source object.
* @param copyConditions
* CopyConditions object with collection of supported CopyObject conditions.
*
* @throws InvalidBucketNameException upon invalid bucket name is given
* @throws NoSuchAlgorithmException
* upon requested algorithm was not found during signature calculation
* @throws InsufficientDataException upon getting EOFException while reading given
* InputStream even before reading given length
* @throws IOException upon connection error
* @throws InvalidKeyException
* upon an invalid access key or secret key
* @throws NoResponseException upon no response from server
* @throws XmlPullParserException upon parsing response xml
* @throws ErrorResponseException upon unsuccessful execution
* @throws InternalException upon internal library error
* @throws InvalidArgumentException upon invalid value is passed to a method.
* @throws InvalidResponseException upon a non-xml response from server
*/
public void copyObject(String bucketName, String objectName, Map<String,String> headerMap, ServerSideEncryption sse,
String srcBucketName, String srcObjectName, ServerSideEncryption srcSse,
CopyConditions copyConditions)
throws InvalidKeyException, InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException,
NoResponseException, ErrorResponseException, InternalException, IOException, XmlPullParserException,
InvalidArgumentException, InvalidResponseException {
if (bucketName == null) {
throw new InvalidArgumentException("Source bucket name cannot be empty");
throw new InvalidArgumentException("bucket name cannot be empty");
}

if (objectName == null) {
throw new InvalidArgumentException("Source object name cannot be empty");
throw new InvalidArgumentException("object name cannot be empty");
}
if (destBucketName == null) {
throw new InvalidArgumentException("Destination bucket name cannot be empty");

checkWriteRequestSse(sse);

if (srcBucketName == null) {
throw new InvalidArgumentException("Source bucket name cannot be empty");
}

// Source object name is optional, if empty default to object name.
if (srcObjectName == null) {
srcObjectName = objectName;
}

// Escape source object path.
String sourceObjectPath = S3Escaper.encodePath(bucketName + "/" + objectName);
checkReadRequestSse(srcSse);

// Destination object name is optional, if empty default to source object name.
if (destObjectName == null) {
destObjectName = objectName;
if (headerMap == null) {
headerMap = new HashMap<>();
}

Map<String, String> headerMap = new HashMap<>();
headerMap.put("x-amz-copy-source", S3Escaper.encodePath(srcBucketName + "/" + srcObjectName));

// Set the object source
headerMap.put("x-amz-copy-source", sourceObjectPath);
if (sse != null) {
sse.marshal(headerMap);
}

// If no conditions available, skip addition else add the conditions to the header
if (copyConditions != null) {
headerMap.putAll(copyConditions.getConditions());
if (srcSse != null) {
srcSse.marshal(headerMap);
}

// Set metadata on the destination of object.
if (metadata != null) {
headerMap.putAll(metadata);
if (copyConditions != null) {
headerMap.putAll(copyConditions.getConditions());
}

HttpResponse response = executePut(destBucketName, destObjectName, headerMap,
null, "", 0);
HttpResponse response = executePut(bucketName, objectName, headerMap, null, "", 0);

// For now ignore the copyObjectResult, just read and parse it.
CopyObjectResult result = new CopyObjectResult();
Expand Down Expand Up @@ -4285,23 +4365,14 @@ private void putObject(String bucketName, String objectName, Long size, Object d
}

if (sse != null) {
if (sse.getType() == ServerSideEncryption.Type.SSE_C && !this.baseUrl.isHttps()) {
throw new InvalidArgumentException("SSE_C operations must be performed over a secure connection.");
} else if (sse.getType() == ServerSideEncryption.Type.SSE_KMS && !this.baseUrl.isHttps()) {
throw new InvalidArgumentException("SSE_KMS operations must be performed over a secure connection.");
}

checkWriteRequestSse(sse);
// The correct approach is see.marshal() needs to accept boolean isHttps and do above checks inside.
sse.marshal(headerMap);
}


if (size <= MIN_MULTIPART_SIZE) {
// Single put object.
if (sse != null) {
sse.marshal(headerMap);
}
putObject(bucketName, objectName, data, size.intValue(),headerMap , null, 0);
putObject(bucketName, objectName, data, size.intValue(), headerMap, null, 0);
return;
}

Expand Down
4 changes: 2 additions & 2 deletions examples/CopyObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ public static void main(String[] args)
bais.close();
System.out.println("my-objectname is uploaded successfully");

minioClient.copyObject("my-bucketname", "my-objectname", "my-destbucketname",
"my-objectname-copy");
minioClient.copyObject("my-destbucketname", "my-objectname-copy", null, null,
"my-bucketname", "my-objectname", null, null);
System.out.println("my-objectname-copy copied to my-destbucketname successfully");
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
Expand Down
4 changes: 2 additions & 2 deletions examples/CopyObjectEncrypted.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ public static void main(String[] args)
minioClient.putObject("my-bucketname", "my-objectname", bais, Long.valueOf(bais.available()), null, ssePut, null);
System.out.println("my-objectname is uploaded successfully");

minioClient.copyObject("my-bucketname", "my-objectname", sseSource, "my-destbucketname",
"my-objectname-copy", null, sseTarget);
minioClient.copyObject("my-destbucketname", "my-objectname-copy", null, sseTarget,
"my-bucketname", "my-objectname", sseSource, null);

bais.close();

Expand Down
6 changes: 3 additions & 3 deletions examples/CopyObjectEncryptedKms.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ public static void main(String[] args)
bais.close();
System.out.println("my-objectname is uploaded successfully");

minioClient.copyObject("my-bucketname", "my-objectname", null, "my-destbucketname",
"my-objectname-copy", null, sse);
minioClient.copyObject("my-destbucketname", "my-objectname-copy", null, sse,
"my-bucketname", "my-objectname", null, null);
System.out.println("my-objectname-copy copied to my-destbucketname successfully");

} catch (MinioException e) {
System.out.println("Error occurred: " + e);
}
System.out.println("finished");
}
}
}
6 changes: 3 additions & 3 deletions examples/CopyObjectEncryptedS3.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ public static void main(String[] args)
bais.close();
System.out.println("my-objectname is uploaded successfully");

minioClient.copyObject("my-bucketname", "my-objectname", null, "my-destbucketname",
"my-objectname-copy", null, sse);
minioClient.copyObject("my-destbucketname", "my-objectname-copy", null, sse,
"my-bucketname", "my-objectname", null, null);
System.out.println("my-objectname-copy copied to my-destbucketname successfully");
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
}
System.out.println("finished");
}
}
}
4 changes: 2 additions & 2 deletions examples/CopyObjectMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ public static void main(String[] args)
Map<String, String> metadata = new HashMap<>();
metadata.put("Content-Type", "application/javascript");

minioClient.copyObject("my-bucketname", "my-objectname", "my-destbucketname",
"my-objectname-copy", copyConditions, metadata);
minioClient.copyObject("my-destbucketname", "my-objectname-copy", metadata, null,
"my-bucketname", "my-objectname", null, copyConditions);
System.out.println("my-objectname-copy copied to my-destbucketname successfully");
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
Expand Down
Loading

0 comments on commit 7c2a2e4

Please sign in to comment.