Skip to content

Commit 87bc1a1

Browse files
committed
Provide a way to unset values in blob metadata
- Use HashMap instead of ImmutableMap in builder.metadata - Use Collections.unmodifiableMap in blobInfo.metadata getter - Convert null values in metadata to Data.nullOf in blobInfo.toPb - Add integration tests - Add javadoc to mark BlobInfo.ImmutableEmptyMap as internal
1 parent 04cf0a7 commit 87bc1a1

2 files changed

Lines changed: 60 additions & 7 deletions

File tree

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

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,14 @@
2727
import com.google.common.base.Function;
2828
import com.google.common.base.MoreObjects;
2929
import com.google.common.collect.ImmutableList;
30-
import com.google.common.collect.ImmutableMap;
3130
import com.google.common.collect.ImmutableSet;
3231
import com.google.common.collect.Lists;
3332

3433
import java.io.Serializable;
3534
import java.math.BigInteger;
3635
import java.util.AbstractMap;
36+
import java.util.Collections;
37+
import java.util.HashMap;
3738
import java.util.List;
3839
import java.util.Map;
3940
import java.util.Objects;
@@ -84,6 +85,9 @@ public StorageObject apply(BlobInfo blobInfo) {
8485
private final String contentLanguage;
8586
private final Integer componentCount;
8687

88+
/**
89+
* This class is meant for internal use only. Users are discouraged from using this class.
90+
*/
8791
public static final class ImmutableEmptyMap<K, V> extends AbstractMap<K, V> {
8892

8993
@Override
@@ -200,7 +204,7 @@ Builder mediaLink(String mediaLink) {
200204

201205
public Builder metadata(Map<String, String> metadata) {
202206
this.metadata = metadata != null ?
203-
ImmutableMap.copyOf(metadata) : Data.<Map>nullOf(ImmutableEmptyMap.class);
207+
new HashMap(metadata) : Data.<Map>nullOf(ImmutableEmptyMap.class);
204208
return this;
205209
}
206210

@@ -327,7 +331,7 @@ public String mediaLink() {
327331
}
328332

329333
public Map<String, String> metadata() {
330-
return Data.isNull(metadata) ? null : metadata;
334+
return metadata == null || Data.isNull(metadata) ? null : Collections.unmodifiableMap(metadata);
331335
}
332336

333337
public Long generation() {
@@ -414,14 +418,21 @@ public ObjectAccessControl apply(Acl acl) {
414418
if (owner != null) {
415419
storageObject.setOwner(new Owner().setEntity(owner.toPb()));
416420
}
421+
Map<String, String> pbMetadata = metadata;
422+
if (metadata != null && !Data.isNull(metadata)) {
423+
pbMetadata = new HashMap<>();
424+
for (String key : metadata.keySet()) {
425+
pbMetadata.put(key, firstNonNull(metadata.get(key), Data.<String>nullOf(String.class)));
426+
}
427+
}
428+
storageObject.setMetadata(pbMetadata);
417429
storageObject.setCacheControl(cacheControl);
418430
storageObject.setContentEncoding(contentEncoding);
419431
storageObject.setCrc32c(crc32c);
420432
storageObject.setContentType(contentType);
421433
storageObject.setGeneration(generation);
422434
storageObject.setMd5Hash(md5);
423435
storageObject.setMediaLink(mediaLink);
424-
storageObject.setMetadata(metadata);
425436
storageObject.setMetageneration(metageneration);
426437
storageObject.setContentDisposition(contentDisposition);
427438
storageObject.setComponentCount(componentCount);

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

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@
3737
import java.net.URLConnection;
3838
import java.nio.ByteBuffer;
3939
import java.util.Arrays;
40+
import java.util.HashMap;
4041
import java.util.Iterator;
4142
import java.util.List;
43+
import java.util.Map;
4244
import java.util.concurrent.ExecutionException;
4345
import java.util.concurrent.TimeUnit;
4446
import java.util.concurrent.TimeoutException;
@@ -174,17 +176,57 @@ public void testUpdateBlob() {
174176
@Test
175177
public void testUpdateBlobReplaceMetadata() {
176178
String blobName = "test-update-blob-replace-metadata";
179+
ImmutableMap<String, String> metadata = ImmutableMap.of("k1", "a");
180+
ImmutableMap<String, String> newMetadata = ImmutableMap.of("k2", "b");
177181
BlobInfo blob = BlobInfo.builder(bucket, blobName)
178182
.contentType(CONTENT_TYPE)
179-
.metadata(ImmutableMap.of("k1", "a"))
183+
.metadata(metadata)
180184
.build();
181185
assertNotNull(storage.create(blob));
182186
BlobInfo updatedBlob = storage.update(blob.toBuilder().metadata(null).build());
183187
assertNotNull(updatedBlob);
184188
assertNull(updatedBlob.metadata());
185-
updatedBlob = storage.update(blob.toBuilder().metadata(ImmutableMap.of("k2", "b")).build());
189+
updatedBlob = storage.update(blob.toBuilder().metadata(newMetadata).build());
186190
assertEquals(blob.blobId(), updatedBlob.blobId());
187-
assertEquals(ImmutableMap.of("k2", "b"), updatedBlob.metadata());
191+
assertEquals(newMetadata, updatedBlob.metadata());
192+
assertTrue(storage.delete(bucket, blobName));
193+
}
194+
195+
@Test
196+
public void testUpdateBlobMergeMetadata() {
197+
String blobName = "test-update-blob-merge-metadata";
198+
ImmutableMap<String, String> metadata = ImmutableMap.of("k1", "a");
199+
ImmutableMap<String, String> newMetadata = ImmutableMap.of("k2", "b");
200+
ImmutableMap<String, String> expectedMetadata = ImmutableMap.of("k1", "a", "k2", "b");
201+
BlobInfo blob = BlobInfo.builder(bucket, blobName)
202+
.contentType(CONTENT_TYPE)
203+
.metadata(metadata)
204+
.build();
205+
assertNotNull(storage.create(blob));
206+
BlobInfo updatedBlob = storage.update(blob.toBuilder().metadata(newMetadata).build());
207+
assertNotNull(updatedBlob);
208+
assertEquals(blob.blobId(), updatedBlob.blobId());
209+
assertEquals(expectedMetadata, updatedBlob.metadata());
210+
assertTrue(storage.delete(bucket, blobName));
211+
}
212+
213+
@Test
214+
public void testUpdateBlobUnsetMetadata() {
215+
String blobName = "test-update-blob-unset-metadata";
216+
ImmutableMap<String, String> metadata = ImmutableMap.of("k1", "a", "k2", "b");
217+
Map<String, String> newMetadata = new HashMap<>();
218+
newMetadata.put("k1", "a");
219+
newMetadata.put("k2", null);
220+
ImmutableMap<String, String> expectedMetadata = ImmutableMap.of("k1", "a");
221+
BlobInfo blob = BlobInfo.builder(bucket, blobName)
222+
.contentType(CONTENT_TYPE)
223+
.metadata(metadata)
224+
.build();
225+
assertNotNull(storage.create(blob));
226+
BlobInfo updatedBlob = storage.update(blob.toBuilder().metadata(newMetadata).build());
227+
assertNotNull(updatedBlob);
228+
assertEquals(blob.blobId(), updatedBlob.blobId());
229+
assertEquals(expectedMetadata, updatedBlob.metadata());
188230
assertTrue(storage.delete(bucket, blobName));
189231
}
190232

0 commit comments

Comments
 (0)