acls) {
+ this.acls.clear();
+ this.acls.addAll(acls);
+ return this;
+ }
+
+ /**
+ * Adds one or more ACLs to the policy.
+ */
+ public Builder addAcl(Acl first, Acl... others) {
+ acls.add(first);
+ acls.addAll(Arrays.asList(others));
+ return this;
+ }
+
+ /**
+ * Removes the specified ACL.
+ */
+ public Builder removeAcl(Acl acl) {
+ acls.remove(acl);
+ return this;
+ }
+
+ /**
+ * Sets the policy's etag.
+ *
+ * Etags are used for optimistic concurrency control as a way to help prevent simultaneous
+ * updates of a policy from overwriting each other. It is strongly suggested that systems make
+ * use of the etag in the read-modify-write cycle to perform policy updates in order to avoid
+ * race conditions. An etag is returned in the response to getIamPolicy, and systems are
+ * expected to put that etag in the request to setIamPolicy to ensure that their change will be
+ * applied to the same version of the policy. If no etag is provided in the call to
+ * setIamPolicy, then the existing policy is overwritten blindly.
+ */
+ public Builder etag(String etag) {
+ this.etag = etag;
+ return this;
+ }
+
+ /**
+ * Sets the version of the policy. The default version is 0.
+ */
+ public Builder version(int version) {
+ this.version = version;
+ return this;
+ }
+
+ public IamPolicy build() {
+ return new IamPolicy(this);
+ }
+ }
+
+ IamPolicy(Builder builder) {
+ acls = ImmutableList.copyOf(builder.acls);
+ etag = builder.etag;
+ version = builder.version;
+ }
+
+ /**
+ * The list of ACLs specified in the policy.
+ */
+ public List acls() {
+ return acls;
+ }
+
+ /**
+ * The policy's etag.
+ *
+ * Etags are used for optimistic concurrency control as a way to help prevent simultaneous
+ * updates of a policy from overwriting each other. It is strongly suggested that systems make
+ * use of the etag in the read-modify-write cycle to perform policy updates in order to avoid
+ * race conditions. An etag is returned in the response to getIamPolicy, and systems are
+ * expected to put that etag in the request to setIamPolicy to ensure that their change will be
+ * applied to the same version of the policy. If no etag is provided in the call to
+ * setIamPolicy, then the existing policy is overwritten blindly.
+ */
+ public String etag() {
+ return etag;
+ }
+
+ /**
+ * The version of the policy. The default version is 0.
+ */
+ public int version() {
+ return version;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(acls, etag, version);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof IamPolicy)) {
+ return false;
+ }
+ IamPolicy other = (IamPolicy) obj;
+ return Objects.equals(toPb(), other.toPb());
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return new Builder().acls(acls).etag(etag).version(version);
+ }
+
+ com.google.api.services.cloudresourcemanager.model.Policy toPb() {
+ com.google.api.services.cloudresourcemanager.model.Policy policyPb =
+ new com.google.api.services.cloudresourcemanager.model.Policy();
+ policyPb.setBindings(Lists.transform(
+ acls, new Function() {
+ @Override
+ public com.google.api.services.cloudresourcemanager.model.Binding apply(Acl acl) {
+ return acl.toPb();
+ }
+ }));
+ policyPb.setEtag(etag);
+ policyPb.setVersion(version);
+ return policyPb;
+ }
+
+ static IamPolicy fromPb(com.google.api.services.cloudresourcemanager.model.Policy policyPb) {
+ Builder builder = new Builder();
+ builder.acls(Lists.transform(
+ policyPb.getBindings(),
+ new Function() {
+ @Override
+ public Acl apply(com.google.api.services.cloudresourcemanager.model.Binding binding) {
+ return Acl.fromPb(binding);
+ }
+ }));
+ return builder.etag(policyPb.getEtag()).version(policyPb.getVersion()).build();
+ }
+}
diff --git a/gcloud-java-core/src/test/java/com/google/gcloud/IamPolicyTest.java b/gcloud-java-core/src/test/java/com/google/gcloud/IamPolicyTest.java
new file mode 100644
index 000000000000..a87a0b5f287d
--- /dev/null
+++ b/gcloud-java-core/src/test/java/com/google/gcloud/IamPolicyTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2015 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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 com.google.gcloud;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.collect.ImmutableList;
+import com.google.gcloud.IamPolicy.Acl;
+import com.google.gcloud.IamPolicy.Identity;
+
+import org.junit.Test;
+
+public class IamPolicyTest {
+
+ private static final Identity ALL_USERS = Identity.allUsers();
+ private static final Identity ALL_AUTHENTICATED_USERS = Identity.allAuthenticatedUsers();
+ private static final Identity USER = Identity.user("abc@gmail.com");
+ private static final Identity SERVICE_ACCOUNT =
+ Identity.serviceAccount("service-account@gmail.com");
+ private static final Identity GROUP = Identity.group("group@gmail.com");
+ private static final Identity DOMAIN = Identity.domain("google.com");
+ private static final Acl ACL1 = Acl.of("viewer", USER, SERVICE_ACCOUNT, ALL_USERS);
+ private static final Acl ACL2 = Acl.of("editor", ALL_AUTHENTICATED_USERS, GROUP, DOMAIN);
+ private static final IamPolicy FULL_POLICY =
+ IamPolicy.builder().addAcl(ACL1, ACL2).etag("etag").version(1).build();
+ private static final IamPolicy SIMPLE_POLICY = IamPolicy.builder().addAcl(ACL1, ACL2).build();
+
+ @Test
+ public void testIdentityOf() {
+ assertEquals(Identity.Type.ALL_USERS, ALL_USERS.type());
+ assertEquals(null, ALL_USERS.id());
+ assertEquals(Identity.Type.ALL_AUTHENTICATED_USERS, ALL_AUTHENTICATED_USERS.type());
+ assertEquals(null, ALL_AUTHENTICATED_USERS.id());
+ assertEquals(Identity.Type.USER, USER.type());
+ assertEquals("abc@gmail.com", USER.id());
+ assertEquals(Identity.Type.SERVICE_ACCOUNT, SERVICE_ACCOUNT.type());
+ assertEquals("service-account@gmail.com", SERVICE_ACCOUNT.id());
+ assertEquals(Identity.Type.GROUP, GROUP.type());
+ assertEquals("group@gmail.com", GROUP.id());
+ assertEquals(Identity.Type.DOMAIN, DOMAIN.type());
+ assertEquals("google.com", DOMAIN.id());
+ }
+
+ @Test
+ public void testIdentityToAndFromPb() {
+ assertEquals(ALL_USERS, Identity.fromPb(ALL_USERS.toPb()));
+ assertEquals(ALL_AUTHENTICATED_USERS, Identity.fromPb(ALL_AUTHENTICATED_USERS.toPb()));
+ assertEquals(USER, Identity.fromPb(USER.toPb()));
+ assertEquals(SERVICE_ACCOUNT, Identity.fromPb(SERVICE_ACCOUNT.toPb()));
+ assertEquals(GROUP, Identity.fromPb(GROUP.toPb()));
+ assertEquals(DOMAIN, Identity.fromPb(DOMAIN.toPb()));
+ }
+
+ @Test
+ public void testAclBuilder() {
+ Acl acl = Acl.builder("owner").addIdentity(USER, GROUP).build();
+ assertEquals("owner", acl.role());
+ assertEquals(ImmutableList.of(USER, GROUP), acl.identities());
+ acl = acl.toBuilder().role("viewer").removeIdentity(GROUP).build();
+ assertEquals("viewer", acl.role());
+ assertEquals(ImmutableList.of(USER), acl.identities());
+ acl = acl.toBuilder().identities(ImmutableList.of(SERVICE_ACCOUNT)).build();
+ assertEquals("viewer", acl.role());
+ assertEquals(ImmutableList.of(SERVICE_ACCOUNT), acl.identities());
+ }
+
+ @Test
+ public void testAclOf() {
+ assertEquals("viewer", ACL1.role());
+ assertEquals(ImmutableList.of(USER, SERVICE_ACCOUNT, ALL_USERS), ACL1.identities());
+ Acl aclFromIdentitiesList = Acl.of("editor", ImmutableList.of(USER, SERVICE_ACCOUNT));
+ assertEquals("editor", aclFromIdentitiesList.role());
+ assertEquals(ImmutableList.of(USER, SERVICE_ACCOUNT), aclFromIdentitiesList.identities());
+ }
+
+ @Test
+ public void testAclToBuilder() {
+ assertEquals(ACL1, ACL1.toBuilder().build());
+ }
+
+ @Test
+ public void testAclToAndFromPb() {
+ assertEquals(ACL1, Acl.fromPb(ACL1.toPb()));
+ }
+
+ @Test
+ public void testIamPolicyBuilder() {
+ assertEquals(ImmutableList.of(ACL1, ACL2), FULL_POLICY.acls());
+ assertEquals("etag", FULL_POLICY.etag());
+ assertEquals(1, FULL_POLICY.version());
+ IamPolicy policy = FULL_POLICY.toBuilder().acls(ImmutableList.of(ACL2)).build();
+ assertEquals(ImmutableList.of(ACL2), policy.acls());
+ assertEquals("etag", policy.etag());
+ assertEquals(1, policy.version());
+ policy = SIMPLE_POLICY.toBuilder().removeAcl(ACL2).build();
+ assertEquals(ImmutableList.of(ACL1), policy.acls());
+ assertEquals(null, policy.etag());
+ assertEquals(0, policy.version());
+ }
+
+ @Test
+ public void testIamPolicyToBuilder() {
+ assertEquals(FULL_POLICY, FULL_POLICY.toBuilder().build());
+ assertEquals(SIMPLE_POLICY, SIMPLE_POLICY.toBuilder().build());
+ }
+
+ @Test
+ public void testToAndFromPb() {
+ assertEquals(FULL_POLICY, IamPolicy.fromPb(FULL_POLICY.toPb()));
+ assertEquals(SIMPLE_POLICY, IamPolicy.fromPb(SIMPLE_POLICY.toPb()));
+ }
+}
diff --git a/gcloud-java-core/src/test/java/com/google/gcloud/SerializationTest.java b/gcloud-java-core/src/test/java/com/google/gcloud/SerializationTest.java
new file mode 100644
index 000000000000..b529b2c09ff5
--- /dev/null
+++ b/gcloud-java-core/src/test/java/com/google/gcloud/SerializationTest.java
@@ -0,0 +1,49 @@
+package com.google.gcloud;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+
+import com.google.common.collect.ImmutableList;
+import com.google.gcloud.IamPolicy.Acl;
+import com.google.gcloud.IamPolicy.Identity;
+
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+public class SerializationTest {
+
+ private static final Identity IDENTITY = Identity.user("abc@gmail.com");
+ private static final Acl ACL = Acl.of("viewer", ImmutableList.of(IDENTITY));
+ private static final IamPolicy POLICY =
+ IamPolicy.builder().acls(ImmutableList.of(ACL)).etag("etag").version(1).build();
+
+ @Test
+ public void testModelAndRequests() throws Exception {
+ Serializable[] objects = {IDENTITY, ACL, POLICY};
+ for (Serializable obj : objects) {
+ Object copy = serializeAndDeserialize(obj);
+ assertEquals(obj, obj);
+ assertEquals(obj, copy);
+ assertNotSame(obj, copy);
+ assertEquals(copy, copy);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private T serializeAndDeserialize(T obj) throws IOException, ClassNotFoundException {
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ try (ObjectOutputStream output = new ObjectOutputStream(bytes)) {
+ output.writeObject(obj);
+ }
+ try (ObjectInputStream input =
+ new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()))) {
+ return (T) input.readObject();
+ }
+ }
+}
diff --git a/gcloud-java-resourcemanager/pom.xml b/gcloud-java-resourcemanager/pom.xml
index 1311e4dc1bb5..5e77ab48f5b5 100644
--- a/gcloud-java-resourcemanager/pom.xml
+++ b/gcloud-java-resourcemanager/pom.xml
@@ -21,18 +21,6 @@
gcloud-java-core
${project.version}