Skip to content

Commit

Permalink
Merge branch 'master' into merge-master
Browse files Browse the repository at this point in the history
  • Loading branch information
mderka committed Mar 3, 2016
2 parents bf194b4 + 6a82859 commit 7800074
Show file tree
Hide file tree
Showing 9 changed files with 787 additions and 19 deletions.
8 changes: 5 additions & 3 deletions java-core/google-cloud-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ This module provides common functionality required by service-specific modules o
[![Build Status](https://travis-ci.org/GoogleCloudPlatform/gcloud-java.svg?branch=master)](https://travis-ci.org/GoogleCloudPlatform/gcloud-java)
[![Coverage Status](https://coveralls.io/repos/GoogleCloudPlatform/gcloud-java/badge.svg?branch=master)](https://coveralls.io/r/GoogleCloudPlatform/gcloud-java?branch=master)
[![Maven](https://img.shields.io/maven-central/v/com.google.gcloud/gcloud-java-core.svg)](https://img.shields.io/maven-central/v/com.google.gcloud/gcloud-java-core.svg)
[![Codacy Badge](https://api.codacy.com/project/badge/grade/9da006ad7c3a4fe1abd142e77c003917)](https://www.codacy.com/app/mziccard/gcloud-java)
[![Dependency Status](https://www.versioneye.com/user/projects/56bd8ee72a29ed002d2b0969/badge.svg?style=flat)](https://www.versioneye.com/user/projects/56bd8ee72a29ed002d2b0969)

- [Homepage] (https://googlecloudplatform.github.io/gcloud-java/)
- [API Documentation] (http://googlecloudplatform.github.io/gcloud-java/apidocs/index.html?com/google/gcloud/package-summary.html)
Expand All @@ -17,16 +19,16 @@ If you are using Maven, add this to your pom.xml file
<dependency>
<groupId>com.google.gcloud</groupId>
<artifactId>gcloud-java-core</artifactId>
<version>0.1.2</version>
<version>0.1.4</version>
</dependency>
```
If you are using Gradle, add this to your dependencies
```Groovy
compile 'com.google.gcloud:gcloud-java-core:0.1.2'
compile 'com.google.gcloud:gcloud-java-core:0.1.4'
```
If you are using SBT, add this to your dependencies
```Scala
libraryDependencies += "com.google.gcloud" % "gcloud-java-core" % "0.1.2"
libraryDependencies += "com.google.gcloud" % "gcloud-java-core" % "0.1.4"
```

Troubleshooting
Expand Down
19 changes: 9 additions & 10 deletions java-core/google-cloud-core/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.gcloud</groupId>
<artifactId>gcloud-java-core</artifactId>
<packaging>jar</packaging>
<name>GCloud Java core</name>
Expand All @@ -11,7 +10,7 @@
<parent>
<groupId>com.google.gcloud</groupId>
<artifactId>gcloud-java-pom</artifactId>
<version>0.1.3-SNAPSHOT</version>
<version>0.1.5-SNAPSHOT</version>
</parent>
<properties>
<site.installationModule>gcloud-java-core</site.installationModule>
Expand All @@ -36,24 +35,24 @@
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client</artifactId>
<version>1.20.0</version>
<version>1.21.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client</artifactId>
<version>1.20.0</version>
<version>1.21.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
<version>19.0</version>
</dependency>
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client-appengine</artifactId>
<version>1.20.0</version>
<version>1.21.0</version>
<scope>compile</scope>
<exclusions>
<exclusion>
Expand All @@ -65,7 +64,7 @@
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson</artifactId>
<version>1.20.0</version>
<version>1.21.0</version>
<scope>compile</scope>
<exclusions>
<exclusion>
Expand All @@ -83,19 +82,19 @@
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.8.2</version>
<version>2.9.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20090211</version>
<version>20151123</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.3</version>
<version>3.4</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.io.IOException;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.util.Arrays;
import java.util.Objects;

Expand Down Expand Up @@ -114,9 +115,9 @@ private void flush() {
}
}

private void validateOpen() throws IOException {
private void validateOpen() throws ClosedChannelException {
if (!isOpen) {
throw new IOException("stream is closed");
throw new ClosedChannelException();
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
/*
* Copyright 2016 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 com.google.common.base.Preconditions.checkArgument;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
* Base class for Identity and Access Management (IAM) policies. IAM policies are used to specify
* access settings for Cloud Platform resources. A policy is a map of bindings. A binding assigns
* a set of identities to a role, where the identities can be user accounts, Google groups, Google
* domains, and service accounts. A role is a named list of permissions defined by IAM.
*
* @param <R> the data type of roles (should be serializable)
* @see <a href="https://cloud.google.com/iam/reference/rest/v1/Policy">Policy</a>
*/
public abstract class IamPolicy<R> implements Serializable {

private static final long serialVersionUID = 1114489978726897720L;

private final Map<R, Set<Identity>> bindings;
private final String etag;
private final Integer version;

/**
* Builder for an IAM Policy.
*
* @param <R> the data type of roles
* @param <B> the subclass extending this abstract builder
*/
public abstract static class Builder<R, B extends Builder<R, B>> {

private final Map<R, Set<Identity>> bindings = new HashMap<>();
private String etag;
private Integer version;

/**
* Constructor for IAM Policy builder.
*/
protected Builder() {}

/**
* Replaces the builder's map of bindings with the given map of bindings.
*
* @throws IllegalArgumentException if the provided map is null or contain any null values
*/
public final B bindings(Map<R, Set<Identity>> bindings) {
checkArgument(bindings != null, "The provided map of bindings cannot be null.");
for (Map.Entry<R, Set<Identity>> binding : bindings.entrySet()) {
verifyBinding(binding.getKey(), binding.getValue());
}
this.bindings.clear();
for (Map.Entry<R, Set<Identity>> binding : bindings.entrySet()) {
this.bindings.put(binding.getKey(), new HashSet<Identity>(binding.getValue()));
}
return self();
}

/**
* Adds a binding to the policy.
*
* @throws IllegalArgumentException if the policy already contains a binding with the same role
* or if the role or any identities are null
*/
public final B addBinding(R role, Set<Identity> identities) {
verifyBinding(role, identities);
checkArgument(!bindings.containsKey(role),
"The policy already contains a binding with the role " + role.toString() + ".");
bindings.put(role, new HashSet<Identity>(identities));
return self();
}

/**
* Adds a binding to the policy.
*
* @throws IllegalArgumentException if the policy already contains a binding with the same role
* or if the role or any identities are null
*/
public final B addBinding(R role, Identity first, Identity... others) {
HashSet<Identity> identities = new HashSet<>();
identities.add(first);
identities.addAll(Arrays.asList(others));
return addBinding(role, identities);
}

private void verifyBinding(R role, Collection<Identity> identities) {
checkArgument(role != null, "The role cannot be null.");
verifyIdentities(identities);
}

private void verifyIdentities(Collection<Identity> identities) {
checkArgument(identities != null, "A role cannot be assigned to a null set of identities.");
checkArgument(!identities.contains(null), "Null identities are not permitted.");
}

/**
* Removes the binding associated with the specified role.
*/
public final B removeBinding(R role) {
bindings.remove(role);
return self();
}

/**
* Adds one or more identities to an existing binding.
*
* @throws IllegalArgumentException if the policy doesn't contain a binding with the specified
* role or any identities are null
*/
public final B addIdentity(R role, Identity first, Identity... others) {
checkArgument(bindings.containsKey(role),
"The policy doesn't contain the role " + role.toString() + ".");
List<Identity> toAdd = new LinkedList<>();
toAdd.add(first);
toAdd.addAll(Arrays.asList(others));
verifyIdentities(toAdd);
bindings.get(role).addAll(toAdd);
return self();
}

/**
* Removes one or more identities from an existing binding.
*
* @throws IllegalArgumentException if the policy doesn't contain a binding with the specified
* role
*/
public final B removeIdentity(R role, Identity first, Identity... others) {
checkArgument(bindings.containsKey(role),
"The policy doesn't contain the role " + role.toString() + ".");
bindings.get(role).remove(first);
bindings.get(role).removeAll(Arrays.asList(others));
return self();
}

/**
* Sets the policy's etag.
*
* <p>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.
*/
protected final B etag(String etag) {
this.etag = etag;
return self();
}

/**
* Sets the version of the policy. The default version is 0, meaning only the "owner", "editor",
* and "viewer" roles are permitted. If the version is 1, you may also use other roles.
*/
protected final B version(Integer version) {
this.version = version;
return self();
}

@SuppressWarnings("unchecked")
private B self() {
return (B) this;
}

public abstract IamPolicy<R> build();
}

protected IamPolicy(Builder<R, ? extends Builder<R, ?>> builder) {
ImmutableMap.Builder<R, Set<Identity>> bindingsBuilder = ImmutableMap.builder();
for (Map.Entry<R, Set<Identity>> binding : builder.bindings.entrySet()) {
bindingsBuilder.put(binding.getKey(), ImmutableSet.copyOf(binding.getValue()));
}
this.bindings = bindingsBuilder.build();
this.etag = builder.etag;
this.version = builder.version;
}

/**
* Returns a builder containing the properties of this IAM Policy.
*/
public abstract Builder<R, ? extends Builder<R, ?>> toBuilder();

/**
* The map of bindings that comprises the policy.
*/
public Map<R, Set<Identity>> bindings() {
return bindings;
}

/**
* The policy's etag.
*
* <p>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;
}

/**
* Sets the version of the policy. The default version is 0, meaning only the "owner", "editor",
* and "viewer" roles are permitted. If the version is 1, you may also use other roles.
*/
public Integer version() {
return version;
}

@Override
public final int hashCode() {
return Objects.hash(getClass(), bindings, etag, version);
}

@Override
public final boolean equals(Object obj) {
if (obj == null || !getClass().equals(obj.getClass())) {
return false;
}
@SuppressWarnings("rawtypes")
IamPolicy other = (IamPolicy) obj;
return Objects.equals(bindings, other.bindings())
&& Objects.equals(etag, other.etag())
&& Objects.equals(version, other.version());
}
}
Loading

0 comments on commit 7800074

Please sign in to comment.