Skip to content

Commit 1410494

Browse files
committed
Update CopyRequest to check target content type
- Add CopyRequest.target(BlobId) to add target with no contentType checks - Change CopyRequest.target(BlobInfo) to CopyRequest.target(BlobInfo, BlobTargetOptions...) - Remove CopyRequest.targetOptions method, options are only set with a BlobInfo target - Add new CopyRequest.of methods - Update tests and example
1 parent ec10ca6 commit 1410494

File tree

6 files changed

+236
-26
lines changed

6 files changed

+236
-26
lines changed

gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ CopyRequest parse(String... args) {
376376
if (args.length != 4) {
377377
throw new IllegalArgumentException();
378378
}
379-
return CopyRequest.of(args[0], args[1], BlobInfo.builder(args[2], args[3]).build());
379+
return CopyRequest.of(args[0], args[1], BlobId.of(args[2], args[3]));
380380
}
381381

382382
@Override
@@ -544,11 +544,14 @@ public static void main(String... args) throws Exception {
544544
StorageOptions.Builder optionsBuilder =
545545
StorageOptions.builder().retryParams(RetryParams.getDefaultInstance());
546546
StorageAction action;
547+
String actionName;
547548
if (args.length >= 2 && !ACTIONS.containsKey(args[0])) {
549+
actionName = args[1];
548550
optionsBuilder.projectId(args[0]);
549551
action = ACTIONS.get(args[1]);
550552
args = Arrays.copyOfRange(args, 2, args.length);
551553
} else {
554+
actionName = args[0];
552555
action = ACTIONS.get(args[0]);
553556
args = Arrays.copyOfRange(args, 1, args.length);
554557
}
@@ -562,7 +565,7 @@ public static void main(String... args) throws Exception {
562565
try {
563566
request = action.parse(args);
564567
} catch (IllegalArgumentException ex) {
565-
System.out.println("Invalid input for action '" + args[1] + "'");
568+
System.out.println("Invalid input for action '" + actionName + "'");
566569
System.out.println("Expected: " + action.params());
567570
return;
568571
} catch (Exception ex) {

gcloud-java-storage/src/main/java/com/google/gcloud/storage/Blob.java

+2-6
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,8 @@ public Blob update(BlobInfo blobInfo, BlobTargetOption... options) {
223223
* @throws StorageException upon failure
224224
*/
225225
public CopyWriter copyTo(BlobId targetBlob, BlobSourceOption... options) {
226-
BlobInfo updatedInfo = BlobInfo.builder(targetBlob).build();
227226
CopyRequest copyRequest = CopyRequest.builder().source(info.bucket(), info.name())
228-
.sourceOptions(convert(info, options)).target(updatedInfo).build();
227+
.sourceOptions(convert(info, options)).target(targetBlob).build();
229228
return storage.copy(copyRequest);
230229
}
231230

@@ -266,10 +265,7 @@ public CopyWriter copyTo(String targetBucket, BlobSourceOption... options) {
266265
* @throws StorageException upon failure
267266
*/
268267
public CopyWriter copyTo(String targetBucket, String targetBlob, BlobSourceOption... options) {
269-
BlobInfo updatedInfo = BlobInfo.builder(targetBucket, targetBlob).build();
270-
CopyRequest copyRequest = CopyRequest.builder().source(info.bucket(), info.name())
271-
.sourceOptions(convert(info, options)).target(updatedInfo).build();
272-
return storage.copy(copyRequest);
268+
return copyTo(BlobId.of(targetBucket, targetBlob), options);
273269
}
274270

275271
/**

gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java

+96-12
Original file line numberDiff line numberDiff line change
@@ -555,27 +555,37 @@ public Builder sourceOptions(Iterable<BlobSourceOption> options) {
555555
*
556556
* @return the builder.
557557
*/
558-
public Builder target(BlobInfo target) {
559-
this.target = target;
558+
public Builder target(BlobId target) {
559+
this.target = BlobInfo.builder(target).build();
560560
return this;
561561
}
562562

563563
/**
564-
* Sets blob's target options.
564+
* Sets the copy target and target options. Copied blob metadata is set to {@code target}.
565+
* This method throws an exception if target blob's content type is {@code null}.
565566
*
566567
* @return the builder.
568+
* @throws IllegalArgumentException if {@code target.contentType} is {@code null}
567569
*/
568-
public Builder targetOptions(BlobTargetOption... options) {
570+
public Builder target(BlobInfo target, BlobTargetOption... options)
571+
throws IllegalArgumentException {
572+
checkContentType(target);
573+
this.target = target;
569574
Collections.addAll(targetOptions, options);
570575
return this;
571576
}
572577

573578
/**
574-
* Sets blob's target options.
579+
* Sets the copy target and target options. Copied blob metadata is set to {@code target}.
580+
* This method throws an exception if target blob's content type is {@code null}.
575581
*
576582
* @return the builder.
583+
* @throws IllegalArgumentException if {@code target.contentType} is {@code null}
577584
*/
578-
public Builder targetOptions(Iterable<BlobTargetOption> options) {
585+
public Builder target(BlobInfo target, Iterable<BlobTargetOption> options)
586+
throws IllegalArgumentException {
587+
checkContentType(target);
588+
this.target = target;
579589
Iterables.addAll(targetOptions, options);
580590
return this;
581591
}
@@ -647,27 +657,101 @@ public Long megabytesCopiedPerChunk() {
647657
return megabytesCopiedPerChunk;
648658
}
649659

650-
public static CopyRequest of(String sourceBucket, String sourceBlob, BlobInfo target) {
660+
/**
661+
* Creates a copy request. Copied blob metadata is set to {@code target}. This method throws an
662+
* exception if target blob's content type is {@code null}.
663+
*
664+
* @param sourceBucket name of the bucket containing the source blob
665+
* @param sourceBlob name of the source blob
666+
* @param target a {@code BlobInfo} object for the target blob
667+
* @return a copy request.
668+
* @throws IllegalArgumentException if {@code target.contentType} is {@code null}
669+
*/
670+
public static CopyRequest of(String sourceBucket, String sourceBlob, BlobInfo target)
671+
throws IllegalArgumentException {
672+
checkContentType(target);
651673
return builder().source(sourceBucket, sourceBlob).target(target).build();
652674
}
653675

654-
public static CopyRequest of(BlobId sourceBlobId, BlobInfo target) {
676+
/**
677+
* Creates a copy request. Copied blob metadata is set to {@code target}. This method throws an
678+
* exception if target blob's content type is {@code null}.
679+
*
680+
* @param sourceBlobId a {@code BlobId} object for the source blob
681+
* @param target a {@code BlobInfo} object for the target blob
682+
* @return a copy request.
683+
* @throws IllegalArgumentException if {@code target.contentType} is {@code null}
684+
*/
685+
public static CopyRequest of(BlobId sourceBlobId, BlobInfo target)
686+
throws IllegalArgumentException {
687+
checkContentType(target);
655688
return builder().source(sourceBlobId).target(target).build();
656689
}
657690

691+
/**
692+
* Creates a copy request.
693+
*
694+
* @param sourceBucket name of the bucket containing both the source and the target blob
695+
* @param sourceBlob name of the source blob
696+
* @param targetBlob name of the target blob
697+
* @return a copy request.
698+
*/
658699
public static CopyRequest of(String sourceBucket, String sourceBlob, String targetBlob) {
659-
return of(sourceBucket, sourceBlob,
660-
BlobInfo.builder(BlobId.of(sourceBucket, targetBlob)).build());
700+
return CopyRequest.builder()
701+
.source(sourceBucket, sourceBlob)
702+
.target(BlobId.of(sourceBucket, targetBlob))
703+
.build();
704+
}
705+
706+
/**
707+
* Creates a copy request.
708+
*
709+
* @param sourceBucket name of the bucket containing the source blob
710+
* @param sourceBlob name of the source blob
711+
* @param target a {@code BlobId} object for the target blob
712+
* @return a copy request.
713+
*/
714+
public static CopyRequest of(String sourceBucket, String sourceBlob, BlobId target) {
715+
return builder().source(sourceBucket, sourceBlob).target(target).build();
661716
}
662717

718+
/**
719+
* Creates a copy request.
720+
*
721+
* @param sourceBlobId a {@code BlobId} object for the source blob
722+
* @param targetBlob name of the target blob, in the same bucket of the source blob
723+
* @return a copy request.
724+
*/
663725
public static CopyRequest of(BlobId sourceBlobId, String targetBlob) {
664-
return of(sourceBlobId,
665-
BlobInfo.builder(BlobId.of(sourceBlobId.bucket(), targetBlob)).build());
726+
return CopyRequest.builder()
727+
.source(sourceBlobId)
728+
.target(BlobId.of(sourceBlobId.bucket(), targetBlob))
729+
.build();
730+
}
731+
732+
/**
733+
* Creates a copy request.
734+
*
735+
* @param sourceBlobId a {@code BlobId} object for the source blob
736+
* @param targetBlobId a {@code BlobId} object for the target blob
737+
* @return a copy request.
738+
*/
739+
public static CopyRequest of(BlobId sourceBlobId, BlobId targetBlobId) {
740+
return CopyRequest.builder()
741+
.source(sourceBlobId)
742+
.target(targetBlobId)
743+
.build();
666744
}
667745

668746
public static Builder builder() {
669747
return new Builder();
670748
}
749+
750+
private static void checkContentType(BlobInfo blobInfo) throws IllegalArgumentException {
751+
if (blobInfo.contentType() == null) {
752+
throw new IllegalArgumentException("Blob content type can not be null");
753+
}
754+
}
671755
}
672756

673757
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright 2015 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.gcloud.storage;
18+
19+
import static com.google.gcloud.storage.Storage.PredefinedAcl.PUBLIC_READ;
20+
import static org.junit.Assert.assertEquals;
21+
22+
import com.google.common.collect.ImmutableList;
23+
import com.google.gcloud.storage.Storage.BlobSourceOption;
24+
import com.google.gcloud.storage.Storage.BlobTargetOption;
25+
26+
import org.junit.Rule;
27+
import org.junit.Test;
28+
import org.junit.rules.ExpectedException;
29+
30+
public class CopyRequestTest {
31+
32+
private static final String SOURCE_BUCKET_NAME = "b0";
33+
private static final String SOURCE_BLOB_NAME = "o0";
34+
private static final String TARGET_BUCKET_NAME = "b1";
35+
private static final String TARGET_BLOB_NAME = "o1";
36+
private static final String TARGET_BLOB_CONTENT_TYPE = "contentType";
37+
private static final BlobId SOURCE_BLOB_ID = BlobId.of(SOURCE_BUCKET_NAME, SOURCE_BLOB_NAME);
38+
private static final BlobId TARGET_BLOB_ID = BlobId.of(TARGET_BUCKET_NAME, TARGET_BLOB_NAME);
39+
private static final BlobInfo TARGET_BLOB_INFO = BlobInfo.builder(TARGET_BLOB_ID)
40+
.contentType(TARGET_BLOB_CONTENT_TYPE).build();
41+
42+
@Rule
43+
public ExpectedException thrown = ExpectedException.none();
44+
45+
@Test
46+
public void testCopyRequest() {
47+
Storage.CopyRequest copyRequest1 = Storage.CopyRequest.builder()
48+
.source(SOURCE_BLOB_ID)
49+
.sourceOptions(BlobSourceOption.generationMatch(1))
50+
.target(TARGET_BLOB_INFO, BlobTargetOption.predefinedAcl(PUBLIC_READ))
51+
.build();
52+
assertEquals(SOURCE_BLOB_ID, copyRequest1.source());
53+
assertEquals(1, copyRequest1.sourceOptions().size());
54+
assertEquals(BlobSourceOption.generationMatch(1), copyRequest1.sourceOptions().get(0));
55+
assertEquals(TARGET_BLOB_INFO, copyRequest1.target());
56+
assertEquals(1, copyRequest1.targetOptions().size());
57+
assertEquals(BlobTargetOption.predefinedAcl(PUBLIC_READ), copyRequest1.targetOptions().get(0));
58+
59+
Storage.CopyRequest copyRequest2 = Storage.CopyRequest.builder()
60+
.source(SOURCE_BUCKET_NAME, SOURCE_BLOB_NAME)
61+
.target(TARGET_BLOB_ID)
62+
.build();
63+
assertEquals(SOURCE_BLOB_ID, copyRequest2.source());
64+
assertEquals(BlobInfo.builder(TARGET_BLOB_ID).build(), copyRequest2.target());
65+
66+
Storage.CopyRequest copyRequest3 = Storage.CopyRequest.builder()
67+
.source(SOURCE_BLOB_ID)
68+
.target(TARGET_BLOB_INFO, ImmutableList.of(BlobTargetOption.predefinedAcl(PUBLIC_READ)))
69+
.build();
70+
assertEquals(SOURCE_BLOB_ID, copyRequest3.source());
71+
assertEquals(TARGET_BLOB_INFO, copyRequest3.target());
72+
assertEquals(ImmutableList.of(BlobTargetOption.predefinedAcl(PUBLIC_READ)),
73+
copyRequest3.targetOptions());
74+
}
75+
76+
@Test
77+
public void testCopyRequestOf() {
78+
Storage.CopyRequest copyRequest1 = Storage.CopyRequest.of(SOURCE_BLOB_ID, TARGET_BLOB_INFO);
79+
assertEquals(SOURCE_BLOB_ID, copyRequest1.source());
80+
assertEquals(TARGET_BLOB_INFO, copyRequest1.target());
81+
82+
Storage.CopyRequest copyRequest2 = Storage.CopyRequest.of(SOURCE_BLOB_ID, TARGET_BLOB_NAME);
83+
assertEquals(SOURCE_BLOB_ID, copyRequest2.source());
84+
assertEquals(BlobInfo.builder(SOURCE_BUCKET_NAME, TARGET_BLOB_NAME).build(),
85+
copyRequest2.target());
86+
87+
Storage.CopyRequest copyRequest3 =
88+
Storage.CopyRequest.of(SOURCE_BUCKET_NAME, SOURCE_BLOB_NAME, TARGET_BLOB_INFO);
89+
assertEquals(SOURCE_BLOB_ID, copyRequest3.source());
90+
assertEquals(TARGET_BLOB_INFO, copyRequest3.target());
91+
92+
Storage.CopyRequest copyRequest4 =
93+
Storage.CopyRequest.of(SOURCE_BUCKET_NAME, SOURCE_BLOB_NAME, TARGET_BLOB_NAME);
94+
assertEquals(SOURCE_BLOB_ID, copyRequest4.source());
95+
assertEquals(BlobInfo.builder(SOURCE_BUCKET_NAME, TARGET_BLOB_NAME).build(),
96+
copyRequest4.target());
97+
98+
Storage.CopyRequest copyRequest5 = Storage.CopyRequest.of(SOURCE_BLOB_ID, TARGET_BLOB_ID);
99+
assertEquals(SOURCE_BLOB_ID, copyRequest5.source());
100+
assertEquals(BlobInfo.builder(TARGET_BLOB_ID).build(), copyRequest5.target());
101+
102+
Storage.CopyRequest copyRequest6 =
103+
Storage.CopyRequest.of(SOURCE_BUCKET_NAME, SOURCE_BLOB_NAME, TARGET_BLOB_ID);
104+
assertEquals(SOURCE_BLOB_ID, copyRequest6.source());
105+
assertEquals(BlobInfo.builder(TARGET_BLOB_ID).build(), copyRequest6.target());
106+
}
107+
108+
@Test
109+
public void testCopyRequestFail() {
110+
thrown.expect(IllegalArgumentException.class);
111+
Storage.CopyRequest.builder()
112+
.source(SOURCE_BLOB_ID)
113+
.target(BlobInfo.builder(TARGET_BLOB_ID).build())
114+
.build();
115+
}
116+
117+
@Test
118+
public void testCopyRequestOfBlobInfoFail() {
119+
thrown.expect(IllegalArgumentException.class);
120+
Storage.CopyRequest.of(SOURCE_BLOB_ID, BlobInfo.builder(TARGET_BLOB_ID).build());
121+
}
122+
123+
@Test
124+
public void testCopyRequestOfStringFail() {
125+
thrown.expect(IllegalArgumentException.class);
126+
Storage.CopyRequest.of(
127+
SOURCE_BUCKET_NAME, SOURCE_BLOB_NAME, BlobInfo.builder(TARGET_BLOB_ID).build());
128+
}
129+
}

gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,7 @@ public void testCopyBlob() {
325325
.build();
326326
assertNotNull(storage.create(blob, BLOB_BYTE_CONTENT));
327327
String targetBlobName = "test-copy-blob-target";
328-
BlobInfo target = BlobInfo.builder(BUCKET, targetBlobName).build();
329-
Storage.CopyRequest req = Storage.CopyRequest.of(source, target);
328+
Storage.CopyRequest req = Storage.CopyRequest.of(source, BlobId.of(BUCKET, targetBlobName));
330329
CopyWriter copyWriter = storage.copy(req);
331330
assertEquals(BUCKET, copyWriter.result().bucket());
332331
assertEquals(targetBlobName, copyWriter.result().name());

gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ public void testComposeWithOptions() {
591591

592592
@Test
593593
public void testCopy() {
594-
CopyRequest request = Storage.CopyRequest.of(BLOB_INFO1.blobId(), BLOB_INFO2);
594+
CopyRequest request = Storage.CopyRequest.of(BLOB_INFO1.blobId(), BLOB_INFO2.blobId());
595595
StorageRpc.RewriteRequest rpcRequest = new StorageRpc.RewriteRequest(request.source().toPb(),
596596
EMPTY_RPC_OPTIONS, request.target().toPb(), EMPTY_RPC_OPTIONS, null);
597597
StorageRpc.RewriteResponse rpcResponse = new StorageRpc.RewriteResponse(rpcRequest, null, 42L,
@@ -610,8 +610,7 @@ public void testCopyWithOptions() {
610610
CopyRequest request = Storage.CopyRequest.builder()
611611
.source(BLOB_INFO2.blobId())
612612
.sourceOptions(BLOB_SOURCE_GENERATION, BLOB_SOURCE_METAGENERATION)
613-
.target(BLOB_INFO1)
614-
.targetOptions(BLOB_TARGET_GENERATION, BLOB_TARGET_METAGENERATION)
613+
.target(BLOB_INFO1, BLOB_TARGET_GENERATION, BLOB_TARGET_METAGENERATION)
615614
.build();
616615
StorageRpc.RewriteRequest rpcRequest = new StorageRpc.RewriteRequest(request.source().toPb(),
617616
BLOB_SOURCE_OPTIONS_COPY, request.target().toPb(), BLOB_TARGET_OPTIONS_COMPOSE, null);
@@ -628,7 +627,7 @@ public void testCopyWithOptions() {
628627

629628
@Test
630629
public void testCopyMultipleRequests() {
631-
CopyRequest request = Storage.CopyRequest.of(BLOB_INFO1.blobId(), BLOB_INFO2);
630+
CopyRequest request = Storage.CopyRequest.of(BLOB_INFO1.blobId(), BLOB_INFO2.blobId());
632631
StorageRpc.RewriteRequest rpcRequest = new StorageRpc.RewriteRequest(request.source().toPb(),
633632
EMPTY_RPC_OPTIONS, request.target().toPb(), EMPTY_RPC_OPTIONS, null);
634633
StorageRpc.RewriteResponse rpcResponse1 = new StorageRpc.RewriteResponse(rpcRequest, null, 42L,

0 commit comments

Comments
 (0)