You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ga...@apache.org on 2014/06/21 00:50:50 UTC

git commit: JCLOUDS-458: Add BucketAccessControls

Repository: jclouds-labs-google
Updated Branches:
  refs/heads/master 785d915fc -> ac9cc36cb


JCLOUDS-458: Add BucketAccessControls

This commit includes expect tests but needs not-yet-implemented bucket
operations to implement live tests.


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/commit/ac9cc36c
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/tree/ac9cc36c
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/diff/ac9cc36c

Branch: refs/heads/master
Commit: ac9cc36cb42034d4c88af05d4a3a1ec65c77b4b4
Parents: 785d915
Author: hsbhathiya <hs...@gmail.com>
Authored: Fri Jun 20 08:32:07 2014 +0530
Committer: Andrew Gaul <ga...@apache.org>
Committed: Fri Jun 20 15:49:50 2014 -0700

----------------------------------------------------------------------
 .../GoogleCloudStorageApi.java                  |   7 +
 .../domain/BucketAccessControls.java            | 254 +++++++++++++++++++
 .../domain/ListBucketAccessControls.java        | 112 ++++++++
 .../features/BucketAccessControlsApi.java       | 187 ++++++++++++++
 .../handlers/BucketAccessControlsBinder.java    |  42 +++
 .../BucketAccessControlsApiExpectTest.java      | 201 +++++++++++++++
 .../parse/BucketAclGetTest.java                 |  43 ++++
 .../parse/BucketAclInsertTest.java              |  46 ++++
 .../parse/BucketAclListTest.java                |  58 +++++
 .../parse/BucketAclUpdateTest.java              |  42 +++
 .../src/test/resources/bucketacl_get.json       |   9 +
 .../resources/bucketacl_insert_response.json    |   9 +
 .../src/test/resources/bucketacl_list.json      |  27 ++
 .../resources/bucketacl_update_initial.json     |   9 +
 .../resources/bucketacl_update_response.json    |   9 +
 15 files changed, 1055 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApi.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApi.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApi.java
index 8bdd0bf..b59f518 100644
--- a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApi.java
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/GoogleCloudStorageApi.java
@@ -20,6 +20,7 @@ import java.io.Closeable;
 
 import javax.ws.rs.Path;
 
+import org.jclouds.googlecloudstorage.features.BucketAccessControlsApi;
 import org.jclouds.googlecloudstorage.features.DefaultObjectAccessControlsApi;
 import org.jclouds.rest.annotations.Delegate;
 
@@ -37,4 +38,10 @@ public interface GoogleCloudStorageApi extends Closeable {
    @Path("")
    DefaultObjectAccessControlsApi getDefaultObjectAccessControlsApi();
 
+   /**
+    * Provides access to Bucket Access Control features
+    */
+   @Delegate
+   @Path("")
+   BucketAccessControlsApi getBucketAccessControlsApi();
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/BucketAccessControls.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/BucketAccessControls.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/BucketAccessControls.java
new file mode 100644
index 0000000..93020cf
--- /dev/null
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/BucketAccessControls.java
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.domain;
+
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.beans.ConstructorProperties;
+import java.net.URI;
+
+import com.google.common.base.Objects;
+
+/**
+ * Represents a BucketAccessControls Resource
+ *
+ * @see <a href= "https://developers.google.com/storage/docs/json_api/v1/bucketAccessControls" />
+ */
+public class BucketAccessControls extends Resource {
+
+   public enum Role {
+      READER, WRITER, OWNER
+   }
+
+   protected final String bucket;
+   protected final String entity;
+   protected final Role role;
+   protected final String email;
+   protected final String domain;
+   protected final String entityId;
+   protected final ProjectTeam projectTeam;
+
+   protected BucketAccessControls(String id, URI selfLink, String etag, String bucket, String entity, String entityId,
+            Role role, String email, String domain, ProjectTeam projectTeam) {
+      super(Kind.BUCKET_ACCESS_CONTROL, id == null ? (bucket + "/" + entity) : id, selfLink, etag);
+
+      this.bucket = checkNotNull(bucket, "bucket");
+      this.entity = checkNotNull(entity, "entity");
+      this.entityId = entityId;
+      this.role = role;
+      this.email = email;
+      this.domain = domain;
+      this.projectTeam = projectTeam;
+   }
+
+   public String getBucket() {
+      return bucket;
+   }
+
+   public String getEntity() {
+      return entity;
+   }
+
+   public Role getRole() {
+      return role;
+   }
+
+   public String getEmail() {
+      return email;
+   }
+
+   public String getDomain() {
+      return domain;
+   }
+
+   public String getEntityId() {
+      return entityId;
+   }
+
+   public ProjectTeam getProjectTeam() {
+      return projectTeam;
+   }
+
+   public static class ProjectTeam {
+
+      public enum Team {
+         owners, editors, viewers;
+      }
+
+      private final String projectId;
+      private final Team team;
+
+      @ConstructorProperties({ "projectId", "team" })
+      public ProjectTeam(String projectId, Team team) {
+         this.projectId = projectId;
+         this.team = team;
+      }
+
+      public String getProjectId() {
+         return projectId;
+      }
+
+      public Team getTeam() {
+         return team;
+      }
+
+      @Override
+      public int hashCode() {
+         return Objects.hashCode(projectId, team);
+      }
+
+      @Override
+      public boolean equals(Object obj) {
+         if (this == obj)
+            return true;
+         if (obj == null || getClass() != obj.getClass())
+            return false;
+         ProjectTeam that = ProjectTeam.class.cast(obj);
+         return equal(this.projectId, that.projectId) && equal(this.team, that.team);
+      }
+
+      protected Objects.ToStringHelper string() {
+         return toStringHelper(this).add("projectId", projectId).add("team", team);
+      }
+
+      @Override
+      public String toString() {
+         return string().toString();
+      }
+
+      public static class Builder {
+
+         private String projectId;
+         private Team team;
+
+         public Builder projectId(String projectId) {
+            this.projectId = projectId;
+            return this;
+         }
+
+         public Builder team(Team team) {
+            this.team = team;
+            return this;
+         }
+
+         public ProjectTeam build() {
+            return new ProjectTeam(this.projectId, this.team);
+         }
+
+         public Builder fromProjectTeam(ProjectTeam in) {
+            return this.projectId(in.getProjectId()).team(in.getTeam());
+         }
+      }
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null || getClass() != obj.getClass())
+         return false;
+      BucketAccessControls that = BucketAccessControls.class.cast(obj);
+      return equal(this.kind, that.kind) && equal(this.bucket, that.bucket) && equal(this.entity, that.entity);
+   }
+
+   protected Objects.ToStringHelper string() {
+      return super.string().omitNullValues().add("bucket", bucket).add("entity", entity).add("entityId", entityId)
+               .add("role", role).add("email", email).add("domain", domain);
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(kind, bucket, entity);
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return new Builder().fromBucketACL(this);
+   }
+
+   public static final class Builder extends Resource.Builder<Builder> {
+
+      protected String bucket;
+      protected String entity;
+      protected String entityId;
+      protected Role role;
+      protected String email;
+      protected String domain;
+      protected ProjectTeam projectTeam;
+
+      public Builder bucket(String bucket) {
+         this.bucket = bucket;
+         return this;
+      }
+
+      public Builder entity(String entity) {
+         this.entity = entity;
+         return this;
+      }
+
+      public Builder entityId(String entityId) {
+         this.entityId = entityId;
+         return this;
+      }
+
+      public Builder role(Role role) {
+         this.role = role;
+         return this;
+      }
+
+      public Builder email(String email) {
+         this.email = email;
+         return this;
+      }
+
+      public Builder domain(String domain) {
+         this.domain = domain;
+         return this;
+      }
+
+      public Builder projectTeam(ProjectTeam projectTeam) {
+         this.projectTeam = projectTeam;
+         return this;
+      }
+
+      public BucketAccessControls build() {
+         return new BucketAccessControls(super.id, super.selfLink, super.etag, bucket, entity, entityId, role, email,
+                  domain, projectTeam);
+      }
+
+      public Builder fromBucketACL(BucketAccessControls bACL) {
+         return super.fromResource(bACL).bucket(bACL.getBucket()).entity(bACL.getEntity()).entityId(bACL.getEntityId())
+                  .role(bACL.getRole()).email(bACL.getEmail()).domain(bACL.getDomain())
+                  .projectTeam(bACL.getProjectTeam());
+      }
+
+      @Override
+      protected Builder self() {
+         return this;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ListBucketAccessControls.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ListBucketAccessControls.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ListBucketAccessControls.java
new file mode 100644
index 0000000..951fc41
--- /dev/null
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/domain/ListBucketAccessControls.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.domain;
+
+/**
+ * Represents the structure of a response from DefaultObjectAccessControls list operation
+ * @see <a href= "https://developers.google.com/storage/docs/json_api/v1/bucketAccessControls/list"/>
+ */
+
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Set;
+
+import org.jclouds.googlecloudstorage.domain.Resource.Kind;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+
+public class ListBucketAccessControls {
+
+   protected final Kind kind;
+   protected final Set<BucketAccessControls> items;
+
+   protected ListBucketAccessControls(Kind kind, Set<BucketAccessControls> items) {
+
+      this.kind = checkNotNull(kind, "kind");
+      this.items = checkNotNull(items, "items");
+   }
+
+   public Kind getKind() {
+      return kind;
+   }
+
+   public Set<BucketAccessControls> getItems() {
+      return items;
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj)
+         return true;
+      if (obj == null || getClass() != obj.getClass())
+         return false;
+      ListBucketAccessControls that = ListBucketAccessControls.class.cast(obj);
+      return equal(this.kind, that.kind) && equal(this.items, that.items);
+
+   }
+
+   protected Objects.ToStringHelper string() {
+      return toStringHelper(this).omitNullValues().add("kind", kind).add("items", items);
+
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() {
+      return new Builder();
+   }
+
+   public Builder toBuilder() {
+      return new Builder().fromListBucketAccessControls(this);
+   }
+
+   public static final class Builder {
+
+      private Kind kind;
+      private ImmutableSet.Builder<BucketAccessControls> items = ImmutableSet.builder();
+
+      public Builder kind(Kind kind) {
+         this.kind = kind;
+         return this;
+      }
+
+      public Builder addItems(BucketAccessControls bucketAccessControls) {
+         this.items.add(bucketAccessControls);
+         return this;
+      }
+
+      public Builder items(Set<BucketAccessControls> items) {
+         this.items.addAll(items);
+         return this;
+      }
+
+      public ListBucketAccessControls build() {
+         return new ListBucketAccessControls(this.kind, items.build());
+      }
+
+      public Builder fromListBucketAccessControls(ListBucketAccessControls in) {
+         return this.kind(in.getKind()).items(in.getItems());
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApi.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApi.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApi.java
new file mode 100644
index 0000000..cc2cad7
--- /dev/null
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApi.java
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.features;
+
+import static org.jclouds.googlecloudstorage.reference.GoogleCloudStorageConstants.STORAGE_FULLCONTROL_SCOPE;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.googlecloudstorage.domain.BucketAccessControls;
+import org.jclouds.googlecloudstorage.domain.ListBucketAccessControls;
+import org.jclouds.googlecloudstorage.handlers.BucketAccessControlsBinder;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.oauth.v2.config.OAuthScopes;
+import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PATCH;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+/**
+ * Provides access to BucketAccessControl entities via their REST API.
+ *
+ * @see <a href = " https://developers.google.com/storage/docs/json_api/v1/bucketAccessControls "/>
+ */
+
+@SkipEncoding({ '/', '=' })
+@RequestFilters(OAuthAuthenticator.class)
+public interface BucketAccessControlsApi {
+
+   /**
+    * Returns the ACL entry for the specified entity on the specified bucket.
+    *
+    * @param bucketName
+    *           Name of the bucket which ACL is related
+    * @param entity
+    *           The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId,
+    *           group-emailAddress, allUsers, or allAuthenticatedUsers.
+    *
+    * @return a BucketAccessControls resource
+    */
+
+   @Named("BucketAccessControls:get")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/b/{bucket}/acl/{entity}")
+   @OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   BucketAccessControls getBucketAccessControls(@PathParam("bucket") String bucketName,
+            @PathParam("entity") String entity);
+
+   /**
+    * Creates a new ACL entry on the specified bucket.
+    *
+    * @param bucketName
+    *           Name of the bucket of which ACL to be created
+    *
+    * @param bucketAccessControls
+    *           In the request body,supply a BucketAccessControls resource with role and entity
+    *
+    * @return If successful, this method returns a BucketAccessControls resource in the response body
+    */
+
+   @Named("BucketAccessControls:insert")
+   @POST
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/b/{bucket}/acl")
+   @OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
+   @MapBinder(BucketAccessControlsBinder.class)
+   BucketAccessControls createBucketAccessControls(@PathParam("bucket") String bucketName,
+            @PayloadParam("BACLInsert") BucketAccessControls bucketAccessControls);
+
+   /**
+    * Permanently deletes the ACL entry for the specified entity on the specified bucket.
+    *
+    * @param bucketName
+    *           Name of the bucket of that ACL is related
+    * @return If successful, this method returns an empty response body.
+    */
+
+   @Named("BucketAccessControls:delete")
+   @DELETE
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/b/{bucket}/acl/{entity}")
+   @OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   HttpResponse deleteBucketAccessControls(@PathParam("bucket") String bucketName, @PathParam("entity") String entity);
+
+   /**
+    * Retrieves all ACL entries on a specified bucket
+    *
+    * @param bucketName
+    *           Name of the bucket which ACL is related
+    *
+    * @return ListBucketAccessControls resource
+    */
+
+   @Named("BucketAccessControls:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Produces(MediaType.APPLICATION_JSON)
+   @Path("/b/{bucket}/acl")
+   @OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   ListBucketAccessControls listBucketAccessControls(@PathParam("bucket") String bucketName);
+
+   /**
+    * Updates an ACL entry on the specified bucket
+    *
+    * @param bucketName
+    *           Name of the bucket which ACL to be created
+    * @param entity
+    *           The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId,
+    *           group-emailAddress, allUsers, or allAuthenticatedUsers. In the request body, supply a
+    *           BucketAccessControls resource with role
+    *
+    * @return If successful, this method returns a BucketAccessControls resource in the response body
+    */
+
+   @Named("BucketAccessControls:update")
+   @PUT
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Produces(MediaType.APPLICATION_JSON)
+   @Path("/b/{bucket}/acl/{entity}")
+   @OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   BucketAccessControls updateBucketAccessControls(@PathParam("bucket") String bucketName,
+            @PathParam("entity") String entity,
+            @BinderParam(BindToJsonPayload.class) BucketAccessControls bucketAccessControls);
+
+   /**
+    * Updates an ACL entry on the specified bucket.
+    *
+    * @param bucketName
+    *           Name of the bucket which ACL to be created
+    * @param entity
+    *           The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId,
+    *           group-emailAddress, allUsers, or allAuthenticatedUsers
+    *
+    * @param bucketAccessControls
+    *           In the request body, supply a BucketAccessControls resource with role
+    *
+    * @return If successful, this method returns a BucketAccessControls resource in the response body
+    */
+
+   @Named("BucketAccessControls:patch")
+   @PATCH
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Produces(MediaType.APPLICATION_JSON)
+   @Path("/b/{bucket}/acl/{entity}")
+   @OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
+   @Fallback(NullOnNotFoundOr404.class)
+   BucketAccessControls patchBucketAccessControls(@PathParam("bucket") String bucketName,
+            @PathParam("entity") String entity,
+            @BinderParam(BindToJsonPayload.class) BucketAccessControls bucketAccessControls);
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/handlers/BucketAccessControlsBinder.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/handlers/BucketAccessControlsBinder.java b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/handlers/BucketAccessControlsBinder.java
new file mode 100644
index 0000000..b274c73
--- /dev/null
+++ b/google-cloud-storage/src/main/java/org/jclouds/googlecloudstorage/handlers/BucketAccessControlsBinder.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.handlers;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import org.jclouds.googlecloudstorage.domain.BucketAccessControls;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.MapBinder;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+public class BucketAccessControlsBinder implements MapBinder {
+
+   @Inject
+   private BindToJsonPayload jsonBinder;
+
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
+      BucketAccessControls postBucket = (BucketAccessControls) postParams.get("BACLInsert");
+      return bindToRequest(request, postBucket);
+   }
+
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      return jsonBinder.bindToRequest(request, input);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApiExpectTest.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApiExpectTest.java b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApiExpectTest.java
new file mode 100644
index 0000000..4177793
--- /dev/null
+++ b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/features/BucketAccessControlsApiExpectTest.java
@@ -0,0 +1,201 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.features;
+
+import static org.jclouds.googlecloudstorage.reference.GoogleCloudStorageConstants.STORAGE_FULLCONTROL_SCOPE;
+import static org.testng.Assert.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
+
+import java.net.URI;
+
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.googlecloudstorage.domain.BucketAccessControls;
+import org.jclouds.googlecloudstorage.domain.BucketAccessControls.Role;
+import org.jclouds.googlecloudstorage.internal.BaseGoogleCloudStorageApiExpectTest;
+import org.jclouds.googlecloudstorage.parse.BucketAclGetTest;
+import org.jclouds.googlecloudstorage.parse.BucketAclInsertTest;
+import org.jclouds.googlecloudstorage.parse.BucketAclListTest;
+import org.jclouds.googlecloudstorage.parse.BucketAclUpdateTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+@Test(groups = "unit")
+public class BucketAccessControlsApiExpectTest extends BaseGoogleCloudStorageApiExpectTest {
+
+   private static final String EXPECTED_TEST_BUCKET = "jcloudtestbucket";
+
+   public static final HttpRequest GET_BUCKETACL_REQUEST = HttpRequest.builder().method("GET")
+            .endpoint("https://www.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allUsers")
+            .addHeader("Accept", "application/json").addHeader("Authorization", "Bearer " + TOKEN).build();
+
+   private final HttpResponse GET_BUCKETACL_RESPONSE = HttpResponse.builder().statusCode(200)
+            .payload(staticPayloadFromResource("/bucketacl_get.json")).build();
+
+   private  final HttpResponse CREATE_BUCKETACL_RESPONSE = HttpResponse.builder().statusCode(200)
+            .payload(staticPayloadFromResource("/bucketacl_insert_response.json")).build();
+
+   private final HttpRequest LIST_BUCKETACL_REQUEST = HttpRequest.builder().method("GET")
+            .endpoint("https://www.googleapis.com/storage/v1/b/jcloudtestbucket/acl")
+            .addHeader("Accept", "application/json").addHeader("Authorization", "Bearer " + TOKEN).build();
+
+   private final HttpResponse LIST_BUCKETACL_RESPONSE = HttpResponse.builder().statusCode(200)
+            .payload(staticPayloadFromResource("/bucketacl_list.json")).build();
+
+   // Test getBucketAccessControls
+   public void testGetBucketAclResponseIs2xx() throws Exception {
+
+      BucketAccessControlsApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
+               GET_BUCKETACL_REQUEST, GET_BUCKETACL_RESPONSE).getBucketAccessControlsApi();
+
+      assertEquals(api.getBucketAccessControls(EXPECTED_TEST_BUCKET, "allUsers"), new BucketAclGetTest().expected());
+   }
+
+   public void testGetBucketAclResponseIs4xx() throws Exception {
+
+      HttpResponse getResponse = HttpResponse.builder().statusCode(404).build();
+
+      BucketAccessControlsApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
+               GET_BUCKETACL_REQUEST, getResponse).getBucketAccessControlsApi();
+
+      assertNull("404", api.getBucketAccessControls(EXPECTED_TEST_BUCKET, "allUsers"));
+
+   }
+
+   // Test listBucketAccessControls
+   public void testListBucketAclResponseIs2xx() throws Exception {
+
+      BucketAccessControlsApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
+               LIST_BUCKETACL_REQUEST, LIST_BUCKETACL_RESPONSE).getBucketAccessControlsApi();
+
+      assertEquals(api.listBucketAccessControls(EXPECTED_TEST_BUCKET), new BucketAclListTest().expected());
+
+   }
+
+   public void testListBucketAclResponseIs4xx() throws Exception {
+      HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
+
+      BucketAccessControlsApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
+               LIST_BUCKETACL_REQUEST, listResponse).getBucketAccessControlsApi();
+
+      assertNull(api.listBucketAccessControls("jcloudtestbucket"));
+   }
+
+   // Test insertBucketAccessControls
+   public void testInsertBucketAclResponseIs2xx() throws Exception {
+      HttpRequest insertRequest = HttpRequest
+               .builder()
+               .method("POST")
+               .endpoint("https://www.googleapis.com/storage/v1/b/jcloudtestbucket/acl")
+               .addHeader("Accept", "application/json")
+               .addHeader("Authorization", "Bearer " + TOKEN)
+               .payload(payloadFromResourceWithContentType("/bucketacl_insert_response.json",
+                        MediaType.APPLICATION_JSON)).build();
+
+      BucketAccessControlsApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
+               insertRequest, CREATE_BUCKETACL_RESPONSE).getBucketAccessControlsApi();
+
+      BucketAccessControls options = BucketAccessControls
+               .builder()
+               .id("jcloudtestbucket/allAuthenticatedUsers")
+               .selfLink(
+                        URI.create("https://content.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allAuthenticatedUsers"))
+               .bucket(EXPECTED_TEST_BUCKET).entity("allAuthenticatedUsers").role(Role.WRITER).etag("CAQ=").build();
+
+      assertEquals(api.createBucketAccessControls(EXPECTED_TEST_BUCKET, options), new BucketAclInsertTest().expected());
+
+   }
+
+   // Test deleteBucketAccessControls
+   public void testDeleteBucketAclResponseIs2xx() throws Exception {
+      HttpRequest delete = HttpRequest.builder().method("DELETE")
+               .endpoint("https://www.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allAuthenticatedUsers")
+               .addHeader("Accept", "application/json").addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse deleteResponse = HttpResponse.builder().statusCode(204).build();
+
+      BucketAccessControlsApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
+               delete, deleteResponse).getBucketAccessControlsApi();
+
+      assertEquals(api.deleteBucketAccessControls(EXPECTED_TEST_BUCKET, "allAuthenticatedUsers"), deleteResponse);
+   }
+
+   public void testDeleteBucketAclResponseIs4xx() throws Exception {
+      HttpRequest delete = HttpRequest.builder().method("DELETE")
+               .endpoint("https://www.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allAuthenticatedUsers")
+               .addHeader("Accept", "application/json").addHeader("Authorization", "Bearer " + TOKEN).build();
+
+      HttpResponse deleteResponse = HttpResponse.builder().statusCode(404).build();
+
+      BucketAccessControlsApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
+               delete, deleteResponse).getBucketAccessControlsApi();
+
+      assertNull(api.deleteBucketAccessControls(EXPECTED_TEST_BUCKET, "allAuthenticatedUsers"));
+   }
+
+   // Test updateBucketAccessControls
+   public void testUpdateBucketAclResponseIs2xx() throws Exception {
+      HttpRequest update = HttpRequest
+               .builder()
+               .method("PUT")
+               .endpoint("https://www.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allUsers")
+               .addHeader("Accept", "application/json")
+               .addHeader("Authorization", "Bearer " + TOKEN)
+               .payload(payloadFromResourceWithContentType("/bucketacl_update_response.json",
+                        MediaType.APPLICATION_JSON)).build();
+
+      HttpResponse updateResponse = HttpResponse.builder().statusCode(200)
+               .payload(staticPayloadFromResource("/bucketacl_update_initial.json")).build();
+
+      BucketAccessControlsApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
+               update, updateResponse).getBucketAccessControlsApi();
+
+      BucketAccessControls options = BucketAccessControls.builder().id("jcloudtestbucket/allUsers")
+               .selfLink(URI.create("https://content.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allUsers"))
+               .bucket(EXPECTED_TEST_BUCKET).entity("allUsers").role(Role.OWNER).etag("CAg=").build();
+
+      assertEquals(api.updateBucketAccessControls(EXPECTED_TEST_BUCKET, "allUsers", options),
+               new BucketAclUpdateTest().expected());
+   }
+
+   // Test updateBucketAccessControls
+   public void testPatchBucketAclResponseIs2xx() throws Exception {
+      HttpRequest patchRequest = HttpRequest
+               .builder()
+               .method("PATCH")
+               .endpoint("https://www.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allUsers")
+               .addHeader("Accept", "application/json")
+               .addHeader("Authorization", "Bearer " + TOKEN)
+               .payload(payloadFromResourceWithContentType("/bucketacl_update_response.json",
+                        MediaType.APPLICATION_JSON)).build();
+
+      HttpResponse patchResponse = HttpResponse.builder().statusCode(200)
+               .payload(staticPayloadFromResource("/bucketacl_update_initial.json")).build();
+
+      BucketAccessControlsApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
+               patchRequest, patchResponse).getBucketAccessControlsApi();
+
+      BucketAccessControls options = BucketAccessControls.builder().id("jcloudtestbucket/allUsers")
+               .selfLink(URI.create("https://content.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allUsers"))
+               .bucket(EXPECTED_TEST_BUCKET).entity("allUsers").role(Role.OWNER).etag("CAg=").build();
+
+      assertEquals(api.patchBucketAccessControls(EXPECTED_TEST_BUCKET, "allUsers", options),
+               new BucketAclUpdateTest().expected());
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclGetTest.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclGetTest.java b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclGetTest.java
new file mode 100644
index 0000000..a442ea8
--- /dev/null
+++ b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclGetTest.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.parse;
+
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.googlecloudstorage.domain.BucketAccessControls;
+import org.jclouds.googlecloudstorage.domain.BucketAccessControls.Role;
+import org.jclouds.googlecloudstorage.internal.BaseGoogleCloudStorageParseTest;
+
+public class BucketAclGetTest extends BaseGoogleCloudStorageParseTest<BucketAccessControls> {
+
+   @Override
+   public String resource() {
+      return "/bucketacl_get.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public BucketAccessControls expected() {
+      return BucketAccessControls.builder().bucket("jcloudtestbucket").entity("allUsers").role(Role.READER)
+               .etag("CAM=")
+               .selfLink(URI.create("https://content.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allUsers"))
+               .id("jcloudtestbucket/allUsers").build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclInsertTest.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclInsertTest.java b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclInsertTest.java
new file mode 100644
index 0000000..6cccff9
--- /dev/null
+++ b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclInsertTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.parse;
+
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.googlecloudstorage.domain.BucketAccessControls;
+import org.jclouds.googlecloudstorage.domain.BucketAccessControls.Role;
+import org.jclouds.googlecloudstorage.internal.BaseGoogleCloudStorageParseTest;
+
+public class BucketAclInsertTest extends BaseGoogleCloudStorageParseTest<BucketAccessControls> {
+
+   @Override
+   public String resource() {
+      return "/bucketacl_insert_response.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public BucketAccessControls expected() {
+      return BucketAccessControls
+               .builder()
+               .id("jcloudtestbucket/allAuthenticatedUsers")
+               .selfLink(
+                        URI.create("https://content.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allAuthenticatedUsers"))
+               .bucket("jcloudtestbucket").entity("allAuthenticatedUsers").role(Role.WRITER).etag("CAQ=").build();
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclListTest.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclListTest.java b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclListTest.java
new file mode 100644
index 0000000..960970d
--- /dev/null
+++ b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclListTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.parse;
+
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.googlecloudstorage.domain.BucketAccessControls;
+import org.jclouds.googlecloudstorage.domain.BucketAccessControls.ProjectTeam;
+import org.jclouds.googlecloudstorage.domain.BucketAccessControls.ProjectTeam.Team;
+import org.jclouds.googlecloudstorage.domain.BucketAccessControls.Role;
+import org.jclouds.googlecloudstorage.domain.ListBucketAccessControls;
+import org.jclouds.googlecloudstorage.domain.Resource.Kind;
+import org.jclouds.googlecloudstorage.internal.BaseGoogleCloudStorageParseTest;
+import com.google.common.collect.ImmutableSet;
+
+public class BucketAclListTest extends BaseGoogleCloudStorageParseTest<ListBucketAccessControls> {
+
+   private BucketAccessControls item_1 = BucketAccessControls.builder().id("jcloudtestbucket/allUsers")
+            .selfLink(URI.create("https://content.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allUsers"))
+            .bucket("jcloudtestbucket").entity("allUsers").role(Role.READER).etag("CAc=").build();
+
+   private BucketAccessControls item_2 = BucketAccessControls
+            .builder()
+            .id("jcloudtestbucket/project-owners-1082289308625")
+            .selfLink(
+                     URI.create("https://content.googleapis.com/storage/v1/b/jcloudtestbucket/acl/project-owners-1082289308625"))
+            .projectTeam(new ProjectTeam("1082289308625", Team.owners)).bucket("jcloudtestbucket")
+            .entity("project-owners-1082289308625").role(Role.OWNER).etag("CAc=").build();
+
+   @Override
+   public String resource() {
+      return "/bucketacl_list.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public ListBucketAccessControls expected() {
+      return ListBucketAccessControls.builder().kind(Kind.BUCKET_ACCESS_CONTROLS)
+               .items(ImmutableSet.of(item_1, item_2)).build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclUpdateTest.java
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclUpdateTest.java b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclUpdateTest.java
new file mode 100644
index 0000000..18abfaf
--- /dev/null
+++ b/google-cloud-storage/src/test/java/org/jclouds/googlecloudstorage/parse/BucketAclUpdateTest.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.jclouds.googlecloudstorage.parse;
+
+import java.net.URI;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.googlecloudstorage.domain.BucketAccessControls;
+import org.jclouds.googlecloudstorage.domain.BucketAccessControls.Role;
+import org.jclouds.googlecloudstorage.internal.BaseGoogleCloudStorageParseTest;
+
+public class BucketAclUpdateTest extends BaseGoogleCloudStorageParseTest<BucketAccessControls> {
+
+   @Override
+   public String resource() {
+      return "/bucketacl_update_response.json";
+   }
+
+   @Override
+   @Consumes(MediaType.APPLICATION_JSON)
+   public BucketAccessControls expected() {
+      return BucketAccessControls.builder().id("jcloudtestbucket/allUsers")
+               .selfLink(URI.create("https://content.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allUsers"))
+               .bucket("jcloudtestbucket").entity("allUsers").role(Role.OWNER).etag("CAg=").build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/test/resources/bucketacl_get.json
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/resources/bucketacl_get.json b/google-cloud-storage/src/test/resources/bucketacl_get.json
new file mode 100644
index 0000000..1df3d84
--- /dev/null
+++ b/google-cloud-storage/src/test/resources/bucketacl_get.json
@@ -0,0 +1,9 @@
+{
+   "kind": "storage#bucketAccessControl",
+   "id": "jcloudtestbucket/allUsers",
+   "selfLink": "https://content.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allUsers",
+   "bucket": "jcloudtestbucket",
+   "entity": "allUsers",
+   "role": "READER",
+   "etag": "CAM="
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/test/resources/bucketacl_insert_response.json
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/resources/bucketacl_insert_response.json b/google-cloud-storage/src/test/resources/bucketacl_insert_response.json
new file mode 100644
index 0000000..f03dae2
--- /dev/null
+++ b/google-cloud-storage/src/test/resources/bucketacl_insert_response.json
@@ -0,0 +1,9 @@
+{
+   "kind": "storage#bucketAccessControl",
+   "id": "jcloudtestbucket/allAuthenticatedUsers",
+   "selfLink": "https://content.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allAuthenticatedUsers",
+   "bucket": "jcloudtestbucket",
+   "entity": "allAuthenticatedUsers",
+   "role": "WRITER",
+   "etag": "CAQ="
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/test/resources/bucketacl_list.json
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/resources/bucketacl_list.json b/google-cloud-storage/src/test/resources/bucketacl_list.json
new file mode 100644
index 0000000..e0ed5a4
--- /dev/null
+++ b/google-cloud-storage/src/test/resources/bucketacl_list.json
@@ -0,0 +1,27 @@
+{
+   "kind": "storage#bucketAccessControls",
+   "items": [
+     {
+       "kind": "storage#bucketAccessControl",
+       "id": "jcloudtestbucket/allUsers",
+       "selfLink": "https://content.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allUsers",
+       "bucket": "jcloudtestbucket",
+       "entity": "allUsers",
+       "role": "READER",
+       "etag": "CAc="
+    },
+    {
+       "kind": "storage#bucketAccessControl",
+       "id": "jcloudtestbucket/project-owners-1082289308625",
+       "selfLink": "https://content.googleapis.com/storage/v1/b/jcloudtestbucket/acl/project-owners-1082289308625",
+       "bucket": "jcloudtestbucket",
+       "entity": "project-owners-1082289308625",
+       "role": "OWNER",
+       "projectTeam": {
+          "projectNumber": "1082289308625",
+          "team": "owners"
+       },
+       "etag": "CAc="
+    }
+   ]
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/test/resources/bucketacl_update_initial.json
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/resources/bucketacl_update_initial.json b/google-cloud-storage/src/test/resources/bucketacl_update_initial.json
new file mode 100644
index 0000000..1df3d84
--- /dev/null
+++ b/google-cloud-storage/src/test/resources/bucketacl_update_initial.json
@@ -0,0 +1,9 @@
+{
+   "kind": "storage#bucketAccessControl",
+   "id": "jcloudtestbucket/allUsers",
+   "selfLink": "https://content.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allUsers",
+   "bucket": "jcloudtestbucket",
+   "entity": "allUsers",
+   "role": "READER",
+   "etag": "CAM="
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds-labs-google/blob/ac9cc36c/google-cloud-storage/src/test/resources/bucketacl_update_response.json
----------------------------------------------------------------------
diff --git a/google-cloud-storage/src/test/resources/bucketacl_update_response.json b/google-cloud-storage/src/test/resources/bucketacl_update_response.json
new file mode 100644
index 0000000..f16f7a4
--- /dev/null
+++ b/google-cloud-storage/src/test/resources/bucketacl_update_response.json
@@ -0,0 +1,9 @@
+{
+   "kind": "storage#bucketAccessControl",
+   "id": "jcloudtestbucket/allUsers",
+   "selfLink": "https://content.googleapis.com/storage/v1/b/jcloudtestbucket/acl/allUsers",
+   "bucket": "jcloudtestbucket",
+   "entity": "allUsers",
+   "role": "OWNER",
+   "etag": "CAg="
+}