Repository: googleapis/java-storage (java)

Issue:
Expose updateTime field of the bucket's
Expose `updateTime `field of the [bucket's](https://github.com/googleapis/google-api-java-client-services/blob/b39bb16a44aa99647d56b39054817ee6493ef8f5/clients/google-api-services-storage/v1/1.30.1/com/google/api/services/storage/model/Bucket.java#L226) it's look like missing here, [see](https://github.com/googleapis/java-storage/blob/master/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java#L75-L101).

~//cc: @frankyn 




Pull request description:
feat: expose updateTime field of the bucket
Fixes #448 


Patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f2dbdee0..39d1c88d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -48,6 +48,7 @@ integration tests.
 
 ```bash
 export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account.json
+export IT_SERVICE_ACCOUNT_EMAIL=my-service-account@my-project.gserviceaccount.com
 mvn -Penable-integration-tests clean verify
 ```
 
diff --git a/google-cloud-storage/clirr-ignored-differences.xml b/google-cloud-storage/clirr-ignored-differences.xml
index bca2faaf..114310c6 100644
--- a/google-cloud-storage/clirr-ignored-differences.xml
+++ b/google-cloud-storage/clirr-ignored-differences.xml
@@ -21,4 +21,9 @@
         <method>com.google.cloud.storage.BucketInfo$Builder deleteLifecycleRules()</method>
         <differenceType>7013</differenceType>
     </difference>
+    <difference>
+        <className>com/google/cloud/storage/BucketInfo$Builder</className>
+        <method>com.google.cloud.storage.BucketInfo$Builder setUpdateTime(java.lang.Long)</method>
+        <differenceType>7013</differenceType>
+    </difference>
 </differences>
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java
index c64a3dc5..3714e6e9 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java
@@ -601,6 +601,12 @@ public class Bucket extends BucketInfo {
       return this;
     }
 
+    @Override
+    Builder setUpdateTime(Long updateTime) {
+      infoBuilder.setUpdateTime(updateTime);
+      return this;
+    }
+
     @Override
     Builder setMetageneration(Long metageneration) {
       infoBuilder.setMetageneration(metageneration);
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java
index 36136363..b3e96113 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/BucketInfo.java
@@ -84,6 +84,7 @@ public class BucketInfo implements Serializable {
   private final List<LifecycleRule> lifecycleRules;
   private final String etag;
   private final Long createTime;
+  private final Long updateTime;
   private final Long metageneration;
   private final List<Cors> cors;
   private final List<Acl> acl;
@@ -1005,6 +1006,8 @@ public class BucketInfo implements Serializable {
 
     abstract Builder setCreateTime(Long createTime);
 
+    abstract Builder setUpdateTime(Long updateTime);
+
     abstract Builder setMetageneration(Long metageneration);
 
     abstract Builder setLocationType(String locationType);
@@ -1090,6 +1093,7 @@ public class BucketInfo implements Serializable {
     private String location;
     private String etag;
     private Long createTime;
+    private Long updateTime;
     private Long metageneration;
     private List<Cors> cors;
     private List<Acl> acl;
@@ -1113,6 +1117,7 @@ public class BucketInfo implements Serializable {
       name = bucketInfo.name;
       etag = bucketInfo.etag;
       createTime = bucketInfo.createTime;
+      updateTime = bucketInfo.updateTime;
       metageneration = bucketInfo.metageneration;
       location = bucketInfo.location;
       storageClass = bucketInfo.storageClass;
@@ -1232,6 +1237,12 @@ public class BucketInfo implements Serializable {
       return this;
     }
 
+    @Override
+    Builder setUpdateTime(Long updateTime) {
+      this.updateTime = updateTime;
+      return this;
+    }
+
     @Override
     Builder setMetageneration(Long metageneration) {
       this.metageneration = metageneration;
@@ -1337,6 +1348,7 @@ public class BucketInfo implements Serializable {
     name = builder.name;
     etag = builder.etag;
     createTime = builder.createTime;
+    updateTime = builder.updateTime;
     metageneration = builder.metageneration;
     location = builder.location;
     storageClass = builder.storageClass;
@@ -1468,6 +1480,14 @@ public class BucketInfo implements Serializable {
     return createTime;
   }
 
+  /**
+   * Returns the last modification time of the bucket's metadata expressed as the number of
+   * milliseconds since the Unix epoch.
+   */
+  public Long getUpdateTime() {
+    return updateTime;
+  }
+
   /** Returns the metadata generation of this bucket. */
   public Long getMetageneration() {
     return metageneration;
@@ -1650,6 +1670,9 @@ public class BucketInfo implements Serializable {
     if (createTime != null) {
       bucketPb.setTimeCreated(new DateTime(createTime));
     }
+    if (updateTime != null) {
+      bucketPb.setUpdated(new DateTime(updateTime));
+    }
     if (metageneration != null) {
       bucketPb.setMetageneration(metageneration);
     }
@@ -1797,6 +1820,9 @@ public class BucketInfo implements Serializable {
     if (bucketPb.getTimeCreated() != null) {
       builder.setCreateTime(bucketPb.getTimeCreated().getValue());
     }
+    if (bucketPb.getUpdated() != null) {
+      builder.setUpdateTime(bucketPb.getUpdated().getValue());
+    }
     if (bucketPb.getLocation() != null) {
       builder.setLocation(bucketPb.getLocation());
     }
diff --git a/pom.xml b/pom.xml
index 256dc915..ba836071 100644
--- a/pom.xml
+++ b/pom.xml
@@ -70,7 +70,7 @@
       <dependency>
         <groupId>com.google.cloud</groupId>
         <artifactId>google-cloud-shared-dependencies</artifactId>
-        <version>0.8.3</version>
+        <version>0.8.4</version>
         <type>pom</type>
         <scope>import</scope>
       </dependency>
diff --git a/synth.py b/synth.py
index 7e8a9a3d..23c93c7c 100644
--- a/synth.py
+++ b/synth.py
@@ -19,6 +19,7 @@ import synthtool.languages.java as java
 AUTOSYNTH_MULTIPLE_COMMITS = True
 
 java.common_templates(excludes=[
-  '.kokoro/presubmit/integration.cfg'
+  '.kokoro/presubmit/integration.cfg',
+  'CONTRIBUTING.md'
 ])
 


Test patch:
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java
index b1083942..425cfb70 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketInfoTest.java
@@ -56,6 +56,7 @@ public class BucketInfoTest {
   private static final User OWNER = new User("user@gmail.com");
   private static final String SELF_LINK = "http://storage/b/n";
   private static final Long CREATE_TIME = System.currentTimeMillis();
+  private static final Long UPDATE_TIME = CREATE_TIME;
   private static final List<Cors> CORS = Collections.singletonList(Cors.newBuilder().build());
   private static final List<Acl> DEFAULT_ACL =
       Collections.singletonList(Acl.of(User.ofAllAuthenticatedUsers(), Role.WRITER));
@@ -117,6 +118,7 @@ public class BucketInfoTest {
           .setSelfLink(SELF_LINK)
           .setCors(CORS)
           .setCreateTime(CREATE_TIME)
+          .setUpdateTime(UPDATE_TIME)
           .setDefaultAcl(DEFAULT_ACL)
           .setDeleteRules(DELETE_RULES)
           .setLifecycleRules(LIFECYCLE_RULES)
@@ -148,6 +150,7 @@ public class BucketInfoTest {
           .setSelfLink(SELF_LINK)
           .setCors(CORS)
           .setCreateTime(CREATE_TIME)
+          .setUpdateTime(UPDATE_TIME)
           .setDefaultAcl(DEFAULT_ACL)
           .setDeleteRules(DELETE_RULES)
           .setLifecycleRules(LIFECYCLE_RULES)
@@ -202,6 +205,7 @@ public class BucketInfoTest {
     assertEquals(OWNER, BUCKET_INFO.getOwner());
     assertEquals(SELF_LINK, BUCKET_INFO.getSelfLink());
     assertEquals(CREATE_TIME, BUCKET_INFO.getCreateTime());
+    assertEquals(UPDATE_TIME, BUCKET_INFO.getUpdateTime());
     assertEquals(CORS, BUCKET_INFO.getCors());
     assertEquals(DEFAULT_ACL, BUCKET_INFO.getDefaultAcl());
     assertEquals(DELETE_RULES, BUCKET_INFO.getDeleteRules());
@@ -223,6 +227,7 @@ public class BucketInfoTest {
   }
 
   @Test
+  @SuppressWarnings({"unchecked", "deprecation"})
   public void testToPbAndFromPb() {
     compareBuckets(BUCKET_INFO, BucketInfo.fromPb(BUCKET_INFO.toPb()));
     BucketInfo bucketInfo =
@@ -245,6 +250,7 @@ public class BucketInfoTest {
     assertEquals(expected.getOwner(), value.getOwner());
     assertEquals(expected.getSelfLink(), value.getSelfLink());
     assertEquals(expected.getCreateTime(), value.getCreateTime());
+    assertEquals(expected.getUpdateTime(), value.getUpdateTime());
     assertEquals(expected.getCors(), value.getCors());
     assertEquals(expected.getDefaultAcl(), value.getDefaultAcl());
     assertEquals(expected.getDeleteRules(), value.getDeleteRules());
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java
index 862fbb35..e8a8e3f4 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/BucketTest.java
@@ -69,6 +69,7 @@ public class BucketTest {
   private static final User OWNER = new User("user@gmail.com");
   private static final String SELF_LINK = "http://storage/b/n";
   private static final Long CREATE_TIME = System.currentTimeMillis();
+  private static final Long UPDATE_TIME = CREATE_TIME - 1L;
   private static final List<Cors> CORS = Collections.singletonList(Cors.newBuilder().build());
   private static final List<Acl> DEFAULT_ACL =
       Collections.singletonList(Acl.of(User.ofAllAuthenticatedUsers(), WRITER));
@@ -111,6 +112,7 @@ public class BucketTest {
           .setSelfLink(SELF_LINK)
           .setCors(CORS)
           .setCreateTime(CREATE_TIME)
+          .setUpdateTime(UPDATE_TIME)
           .setDefaultAcl(DEFAULT_ACL)
           .setDeleteRules(DELETE_RULES)
           .setLifecycleRules(LIFECYCLE_RULES)
@@ -803,6 +805,7 @@ public class BucketTest {
             .setSelfLink(SELF_LINK)
             .setCors(CORS)
             .setCreateTime(CREATE_TIME)
+            .setUpdateTime(UPDATE_TIME)
             .setDefaultAcl(DEFAULT_ACL)
             .setDeleteRules(DELETE_RULES)
             .setLifecycleRules(LIFECYCLE_RULES)
@@ -828,6 +831,7 @@ public class BucketTest {
     assertEquals(OWNER, bucket.getOwner());
     assertEquals(SELF_LINK, bucket.getSelfLink());
     assertEquals(CREATE_TIME, bucket.getCreateTime());
+    assertEquals(UPDATE_TIME, bucket.getUpdateTime());
     assertEquals(CORS, bucket.getCors());
     assertEquals(DEFAULT_ACL, bucket.getDefaultAcl());
     assertEquals(DELETE_RULES, bucket.getDeleteRules());
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
index 59000a07..a741f3eb 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
@@ -3535,4 +3535,26 @@ public class ITStorageTest {
       RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS);
     }
   }
+
+  @Test
+  public void testBucketUpdateTime() throws ExecutionException, InterruptedException {
+    String bucketName = RemoteStorageHelper.generateBucketName();
+    BucketInfo bucketInfo =
+        BucketInfo.newBuilder(bucketName).setLocation("us").setVersioningEnabled(true).build();
+    try {
+      Bucket bucket = storage.create(bucketInfo);
+      assertThat(bucket).isNotNull();
+      assertThat(bucket.versioningEnabled()).isTrue();
+      assertThat(bucket.getCreateTime()).isNotNull();
+      assertThat(bucket.getUpdateTime()).isEqualTo(bucket.getCreateTime());
+
+      Bucket updatedBucket = bucket.toBuilder().setVersioningEnabled(false).build().update();
+      assertThat(updatedBucket.versioningEnabled()).isFalse();
+      assertThat(updatedBucket.getUpdateTime()).isNotNull();
+      assertThat(updatedBucket.getCreateTime()).isEqualTo(bucket.getCreateTime());
+      assertThat(updatedBucket.getUpdateTime()).isGreaterThan(bucket.getCreateTime());
+    } finally {
+      RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS);
+    }
+  }
 }