1919import static com .google .common .base .Preconditions .checkArgument ;
2020import static com .google .common .base .Preconditions .checkNotNull ;
2121
22+ import com .google .common .base .Function ;
23+ import com .google .common .base .MoreObjects ;
2224import com .google .common .collect .ImmutableMap ;
2325import com .google .common .collect .ImmutableSet ;
26+ import com .google .common .collect .Lists ;
27+ import com .google .common .io .BaseEncoding ;
28+ import com .google .protobuf .ByteString ;
2429
2530import java .io .Serializable ;
31+ import java .util .ArrayList ;
2632import java .util .Arrays ;
2733import java .util .HashMap ;
2834import java .util .HashSet ;
2935import java .util .LinkedHashSet ;
36+ import java .util .LinkedList ;
37+ import java .util .List ;
3038import java .util .Map ;
3139import java .util .Objects ;
3240import java .util .Set ;
3341
3442/**
35- * Base class for Identity and Access Management (IAM) policies. IAM policies are used to specify
36- * access settings for Cloud Platform resources. A policy is a map of bindings. A binding assigns
37- * a set of identities to a role, where the identities can be user accounts, Google groups, Google
38- * domains, and service accounts. A role is a named list of permissions defined by IAM.
43+ * Class for Identity and Access Management (IAM) policies. IAM policies are used to specify access
44+ * settings for Cloud Platform resources. A policy is a map of bindings. A binding assigns a set of
45+ * identities to a role, where the identities can be user accounts, Google groups, Google domains,
46+ * and service accounts. A role is a named list of permissions defined by IAM.
3947 *
40- * @param <R> the data type of roles (should be serializable)
4148 * @see <a href="https://cloud.google.com/iam/reference/rest/v1/Policy">Policy</a>
4249 */
43- public abstract class IamPolicy < R > implements Serializable {
50+ public final class Policy implements Serializable {
4451
45- private static final long serialVersionUID = 1114489978726897720L ;
52+ private static final long serialVersionUID = - 3348914530232544290L ;
4653
47- private final Map <R , Set <Identity >> bindings ;
54+ private final Map <Role , Set <Identity >> bindings ;
4855 private final String etag ;
49- private final Integer version ;
56+ private final int version ;
57+
58+ public abstract static class Marshaller <T > {
59+
60+ protected static final Function <String , Identity > IDENTITY_VALUE_OF_FUNCTION =
61+ new Function <String , Identity >() {
62+ @ Override
63+ public Identity apply (String identityPb ) {
64+ return Identity .valueOf (identityPb );
65+ }
66+ };
67+ protected static final Function <Identity , String > IDENTITY_STR_VALUE_FUNCTION =
68+ new Function <Identity , String >() {
69+ @ Override
70+ public String apply (Identity identity ) {
71+ return identity .strValue ();
72+ }
73+ };
74+
75+ protected abstract Policy fromPb (T policyPb );
76+
77+ protected abstract T toPb (Policy policy );
78+ }
79+
80+ public static class DefaultMarshaller extends Marshaller <com .google .iam .v1 .Policy > {
81+
82+ @ Override
83+ protected Policy fromPb (com .google .iam .v1 .Policy policyPb ) {
84+ Map <Role , Set <Identity >> bindings = new HashMap <>();
85+ for (com .google .iam .v1 .Binding bindingPb : policyPb .getBindingsList ()) {
86+ bindings .put (Role .of (bindingPb .getRole ()),
87+ ImmutableSet .copyOf (
88+ Lists .transform (bindingPb .getMembersList (), IDENTITY_VALUE_OF_FUNCTION )));
89+ }
90+ return builder ()
91+ .bindings (bindings )
92+ .etag (policyPb .getEtag ().isEmpty () ? null
93+ : BaseEncoding .base64 ().encode (policyPb .getEtag ().toByteArray ()))
94+ .version (policyPb .getVersion ())
95+ .build ();
96+ }
97+
98+ @ Override
99+ protected com .google .iam .v1 .Policy toPb (Policy policy ) {
100+ com .google .iam .v1 .Policy .Builder policyBuilder = com .google .iam .v1 .Policy .newBuilder ();
101+ List <com .google .iam .v1 .Binding > bindingPbList = new LinkedList <>();
102+ for (Map .Entry <Role , Set <Identity >> binding : policy .bindings ().entrySet ()) {
103+ com .google .iam .v1 .Binding .Builder bindingBuilder = com .google .iam .v1 .Binding .newBuilder ();
104+ bindingBuilder .setRole (binding .getKey ().value ());
105+ bindingBuilder .addAllMembers (
106+ Lists .transform (new ArrayList <>(binding .getValue ()), IDENTITY_STR_VALUE_FUNCTION ));
107+ bindingPbList .add (bindingBuilder .build ());
108+ }
109+ policyBuilder .addAllBindings (bindingPbList );
110+ if (policy .etag != null ) {
111+ policyBuilder .setEtag (ByteString .copyFrom (BaseEncoding .base64 ().decode (policy .etag )));
112+ }
113+ policyBuilder .setVersion (policy .version );
114+ return policyBuilder .build ();
115+ }
116+ }
50117
51118 /**
52- * Builder for an IAM Policy.
53- *
54- * @param <R> the data type of roles
55- * @param <B> the subclass extending this abstract builder
119+ * A builder for {@code Policy} objects.
56120 */
57- public abstract static class Builder < R , B extends Builder < R , B >> {
121+ public static class Builder {
58122
59- private final Map <R , Set <Identity >> bindings = new HashMap <>();
123+ private final Map <Role , Set <Identity >> bindings = new HashMap <>();
60124 private String etag ;
61- private Integer version ;
125+ private int version ;
62126
63- /**
64- * Constructor for IAM Policy builder.
65- */
66127 protected Builder () {}
67128
129+ protected Builder (Policy policy ) {
130+ bindings (policy .bindings );
131+ etag (policy .etag );
132+ version (policy .version );
133+ }
134+
68135 /**
69136 * Replaces the builder's map of bindings with the given map of bindings.
70137 *
71138 * @throws NullPointerException if the given map is null or contains any null keys or values
72139 * @throws IllegalArgumentException if any identities in the given map are null
73140 */
74- public final B bindings (Map <R , Set <Identity >> bindings ) {
141+ public final Builder bindings (Map <Role , Set <Identity >> bindings ) {
75142 checkNotNull (bindings , "The provided map of bindings cannot be null." );
76- for (Map .Entry <R , Set <Identity >> binding : bindings .entrySet ()) {
143+ for (Map .Entry <Role , Set <Identity >> binding : bindings .entrySet ()) {
77144 checkNotNull (binding .getKey (), "The role cannot be null." );
78145 Set <Identity > identities = binding .getValue ();
79146 checkNotNull (identities , "A role cannot be assigned to a null set of identities." );
80147 checkArgument (!identities .contains (null ), "Null identities are not permitted." );
81148 }
82149 this .bindings .clear ();
83- for (Map .Entry <R , Set <Identity >> binding : bindings .entrySet ()) {
84- this .bindings .put (binding .getKey (), new HashSet <Identity >(binding .getValue ()));
150+ for (Map .Entry <Role , Set <Identity >> binding : bindings .entrySet ()) {
151+ this .bindings .put (binding .getKey (), new HashSet <>(binding .getValue ()));
85152 }
86- return self () ;
153+ return this ;
87154 }
88155
89156 /**
90157 * Removes the role (and all identities associated with that role) from the policy.
91158 */
92- public final B removeRole (R role ) {
159+ public final Builder removeRole (Role role ) {
93160 bindings .remove (role );
94- return self () ;
161+ return this ;
95162 }
96163
97164 /**
98165 * Adds one or more identities to the policy under the role specified.
99166 *
100167 * @throws NullPointerException if the role or any of the identities is null.
101168 */
102- public final B addIdentity (R role , Identity first , Identity ... others ) {
169+ public final Builder addIdentity (Role role , Identity first , Identity ... others ) {
103170 String nullIdentityMessage = "Null identities are not permitted." ;
104171 checkNotNull (first , nullIdentityMessage );
105172 checkNotNull (others , nullIdentityMessage );
@@ -111,18 +178,18 @@ public final B addIdentity(R role, Identity first, Identity... others) {
111178 toAdd .addAll (Arrays .asList (others ));
112179 Set <Identity > identities = bindings .get (checkNotNull (role , "The role cannot be null." ));
113180 if (identities == null ) {
114- identities = new HashSet <Identity >();
181+ identities = new HashSet <>();
115182 bindings .put (role , identities );
116183 }
117184 identities .addAll (toAdd );
118- return self () ;
185+ return this ;
119186 }
120187
121188 /**
122189 * Removes one or more identities from an existing binding. Does nothing if the binding
123190 * associated with the provided role doesn't exist.
124191 */
125- public final B removeIdentity (R role , Identity first , Identity ... others ) {
192+ public final Builder removeIdentity (Role role , Identity first , Identity ... others ) {
126193 Set <Identity > identities = bindings .get (role );
127194 if (identities != null ) {
128195 identities .remove (first );
@@ -131,7 +198,7 @@ public final B removeIdentity(R role, Identity first, Identity... others) {
131198 if (identities != null && identities .isEmpty ()) {
132199 bindings .remove (role );
133200 }
134- return self () ;
201+ return this ;
135202 }
136203
137204 /**
@@ -145,31 +212,31 @@ public final B removeIdentity(R role, Identity first, Identity... others) {
145212 * applied to the same version of the policy. If no etag is provided in the call to
146213 * setIamPolicy, then the existing policy is overwritten blindly.
147214 */
148- protected final B etag (String etag ) {
215+ protected final Builder etag (String etag ) {
149216 this .etag = etag ;
150- return self () ;
217+ return this ;
151218 }
152219
153220 /**
154221 * Sets the version of the policy. The default version is 0, meaning only the "owner", "editor",
155222 * and "viewer" roles are permitted. If the version is 1, you may also use other roles.
156223 */
157- protected final B version (Integer version ) {
224+ protected final Builder version (int version ) {
158225 this .version = version ;
159- return self () ;
226+ return this ;
160227 }
161228
162- @ SuppressWarnings ("unchecked" )
163- private B self () {
164- return (B ) this ;
229+ /**
230+ * Creates a {@code Policy} object.
231+ */
232+ public final Policy build () {
233+ return new Policy (this );
165234 }
166-
167- public abstract IamPolicy <R > build ();
168235 }
169236
170- protected IamPolicy (Builder < R , ? extends Builder < R , ?>> builder ) {
171- ImmutableMap .Builder <R , Set <Identity >> bindingsBuilder = ImmutableMap .builder ();
172- for (Map .Entry <R , Set <Identity >> binding : builder .bindings .entrySet ()) {
237+ private Policy (Builder builder ) {
238+ ImmutableMap .Builder <Role , Set <Identity >> bindingsBuilder = ImmutableMap .builder ();
239+ for (Map .Entry <Role , Set <Identity >> binding : builder .bindings .entrySet ()) {
173240 bindingsBuilder .put (binding .getKey (), ImmutableSet .copyOf (binding .getValue ()));
174241 }
175242 this .bindings = bindingsBuilder .build ();
@@ -180,17 +247,19 @@ protected IamPolicy(Builder<R, ? extends Builder<R, ?>> builder) {
180247 /**
181248 * Returns a builder containing the properties of this IAM Policy.
182249 */
183- public abstract Builder <R , ? extends Builder <R , ?>> toBuilder ();
250+ public Builder toBuilder () {
251+ return new Builder (this );
252+ }
184253
185254 /**
186- * The map of bindings that comprises the policy.
255+ * Returns the map of bindings that comprises the policy.
187256 */
188- public Map <R , Set <Identity >> bindings () {
257+ public Map <Role , Set <Identity >> bindings () {
189258 return bindings ;
190259 }
191260
192261 /**
193- * The policy's etag.
262+ * Returns the policy's etag.
194263 *
195264 * <p>Etags are used for optimistic concurrency control as a way to help prevent simultaneous
196265 * updates of a policy from overwriting each other. It is strongly suggested that systems make
@@ -205,30 +274,45 @@ public String etag() {
205274 }
206275
207276 /**
208- * Sets the version of the policy. The default version is 0, meaning only the "owner", "editor ",
209- * and "viewer" roles are permitted. If the version is 1, you may also use other roles.
277+ * Returns the version of the policy. The default version is 0, meaning only the "owner",
278+ * "editor", and "viewer" roles are permitted. If the version is 1, you may also use other roles.
210279 */
211- public Integer version () {
280+ public int version () {
212281 return version ;
213282 }
214283
215284 @ Override
216- public final int hashCode () {
285+ public String toString () {
286+ return MoreObjects .toStringHelper (this )
287+ .add ("bindings" , bindings )
288+ .add ("etag" , etag )
289+ .add ("version" , version )
290+ .toString ();
291+ }
292+
293+ @ Override
294+ public int hashCode () {
217295 return Objects .hash (getClass (), bindings , etag , version );
218296 }
219297
220298 @ Override
221- public final boolean equals (Object obj ) {
299+ public boolean equals (Object obj ) {
222300 if (obj == this ) {
223301 return true ;
224302 }
225- if (obj == null || ! obj . getClass (). equals ( getClass () )) {
303+ if (!( obj instanceof Policy )) {
226304 return false ;
227305 }
228- @ SuppressWarnings ("rawtypes" )
229- IamPolicy other = (IamPolicy ) obj ;
306+ Policy other = (Policy ) obj ;
230307 return Objects .equals (bindings , other .bindings ())
231308 && Objects .equals (etag , other .etag ())
232309 && Objects .equals (version , other .version ());
233310 }
311+
312+ /**
313+ * Returns a builder for {@code Policy} objects.
314+ */
315+ public static Builder builder () {
316+ return new Builder ();
317+ }
234318}
0 commit comments