JCLOUDS-458: Addressing suggestions in PR-31

minor changes

minor changes

minor changes

minor changes

Added ErrorHandler with tests

Changed BucketApi method descriptions

Minor change in error handler
This commit is contained in:
hsbhathiya 2014-07-06 23:15:06 +05:30 committed by Matt Stephenson
parent 4e4558cf18
commit 1f3517380f
35 changed files with 526 additions and 288 deletions

View File

@ -111,7 +111,7 @@
<jclouds.blobstore.httpstream.md5>${jclouds.blobstore.httpstream.md5}</jclouds.blobstore.httpstream.md5>
<test.google-cloud-storage.identity>${test.google-cloud-storage.identity}</test.google-cloud-storage.identity>
<test.google-cloud-storage.credential>${test.google-cloud-storage.credential}</test.google-cloud-storage.credential>
<test.google-cloud-storage.project-number>${test.google-cloud-storage.project-number}</test.google-cloud-storage.project-number>
<test.google-cloud-storage.project-number>${test.google-cloud-storage.project-number}</test.google-cloud-storage.project-number>
<test.google-cloud-storage.api-version>${test.google-cloud-storage.api-version}</test.google-cloud-storage.api-version>
<test.google-cloud-storage.build-version>${test.google-cloud-storage.build-version}</test.google-cloud-storage.build-version>
</systemPropertyVariables>

View File

@ -51,5 +51,5 @@ public interface GoogleCloudStorageApi extends Closeable {
*/
@Delegate
@Path("")
BucketApi getBucketsApi();
BucketApi getBucketApi();
}

View File

@ -17,6 +17,11 @@
package org.jclouds.googlecloudstorage.config;
import org.jclouds.googlecloudstorage.GoogleCloudStorageApi;
import org.jclouds.googlecloudstorage.handlers.GoogleCloudStorageErrorHandler;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.config.HttpApiModule;
@ -27,4 +32,12 @@ import org.jclouds.rest.config.HttpApiModule;
public class GoogleCloudStorageHttpApiModule extends HttpApiModule<GoogleCloudStorageApi> {
public GoogleCloudStorageHttpApiModule() {
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(GoogleCloudStorageErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(GoogleCloudStorageErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(GoogleCloudStorageErrorHandler.class);
}
}

View File

@ -18,9 +18,9 @@ package org.jclouds.googlecloudstorage.config;
import java.lang.reflect.Type;
import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.googlecloudstorage.domain.BucketTemplate;
import org.jclouds.json.config.GsonModule.DateAdapter;
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
import org.jclouds.oauth.v2.domain.ClaimSet;
@ -29,6 +29,10 @@ import org.jclouds.oauth.v2.json.ClaimSetTypeAdapter;
import org.jclouds.oauth.v2.json.HeaderTypeAdapter;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
@ -43,6 +47,46 @@ public class GoogleCloudStorageParserModule extends AbstractModule {
@Singleton
public Map<Type, Object> provideCustomAdapterBindings() {
return new ImmutableMap.Builder<Type, Object>().put(Header.class, new HeaderTypeAdapter())
.put(ClaimSet.class, new ClaimSetTypeAdapter()).build();
.put(ClaimSet.class, new ClaimSetTypeAdapter())
.put(BucketTemplate.class, new BucketTemplateTypeAdapter())
.build();
}
@Singleton
private static class BucketTemplateTypeAdapter implements JsonSerializer<BucketTemplate> {
@Override
public JsonElement serialize(BucketTemplate src, Type typeOfSrc, JsonSerializationContext context) {
BucketTemplateInternal template = new BucketTemplateInternal(src);
JsonObject bucketTemplate = (JsonObject) context.serialize(template, BucketTemplateInternal.class);
// deal with bucketAccessControls
if (!(src.getAcl() == null) && (src.getAcl().isEmpty())) {
bucketTemplate.add("acl", null);
}
// deal with DefaultObjectAccessControls
if (!(src.getDefaultObjectAccessControls() == null) && (src.getDefaultObjectAccessControls().isEmpty())) {
bucketTemplate.add("defaultObjectAccessControls", null);
}
// deal with Cors
if (!(src.getCors() == null) && (src.getCors().isEmpty())) {
bucketTemplate.add("cors", null);
}
return bucketTemplate;
}
private static class BucketTemplateInternal extends BucketTemplate {
private BucketTemplateInternal(BucketTemplate template) {
name(template.getName()).projectNumber(template.getProjectNumber()).acl(template.getAcl())
.defaultObjectAccessControls(template.getDefaultObjectAccessControls()).owner(template.getOwner())
.location(template.getLocation()).website(template.getWebsite()).logging(template.getLogging())
.versioning(template.getVersioning()).cors(template.getCors()).lifeCycle(template.getLifeCycle())
.storageClass(template.getStorageClass());
}
}
}
}

View File

@ -33,14 +33,14 @@ import org.jclouds.googlecloudstorage.domain.internal.Owner;
import org.jclouds.googlecloudstorage.domain.internal.Versioning;
import org.jclouds.googlecloudstorage.domain.internal.Website;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
/**
* The Bucket represents a bucket in Google Cloud Storage There is a single global namespace shared by all buckets
*
* The Bucket represents a bucket in Google Cloud Storage. There is a single global namespace shared by all buckets.
*
* @see <a href = " https://developers.google.com/storage/docs/json_api/v1/buckets"/>
*/
public class Bucket extends Resource {
@ -60,10 +60,11 @@ public class Bucket extends Resource {
private final BucketLifeCycle lifeCycle;
private final StorageClass storageClass;
public Bucket(String id, URI selfLink, String name, String etag, Long projectNumber, Date timeCreated,
private Bucket(String id, URI selfLink, String name, String etag, @Nullable Long projectNumber, Date timeCreated,
Long metageneration, Set<BucketAccessControls> acl, Set<DefaultObjectAccessControls> defaultObjectAcl,
Owner owner, Location location, Website website, Logging logging, Versioning versioning, Set<BucketCors> cors,
BucketLifeCycle lifeCycle, StorageClass storageClass) {
Owner owner, @Nullable Location location, @Nullable Website website, @Nullable Logging logging,
@Nullable Versioning versioning, Set<BucketCors> cors, @Nullable BucketLifeCycle lifeCycle,
@Nullable StorageClass storageClass) {
super(Kind.BUCKET, id, selfLink, etag);
this.projectNumber = projectNumber;
@ -72,7 +73,7 @@ public class Bucket extends Resource {
this.acl = acl.isEmpty() ? null : acl;
this.defaultObjectAcl = defaultObjectAcl.isEmpty() ? null : defaultObjectAcl;
this.owner = checkNotNull(owner, "Owner");
this.location = checkNotNull(location, "location");
this.location = location;
this.website = website;
this.logging = logging;
this.versioning = versioning;
@ -197,7 +198,6 @@ public class Bucket extends Resource {
public Builder projectNumber(Long projectNumber) {
this.projectNumber = projectNumber;
return this;
}
public Builder timeCreated(Date timeCreated) {

View File

@ -23,6 +23,7 @@ import java.net.URI;
import org.jclouds.googlecloudstorage.domain.DomainResourceRefferences.Role;
import org.jclouds.googlecloudstorage.domain.internal.ProjectTeam;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
@ -33,22 +34,23 @@ import com.google.common.base.Objects;
*/
public class BucketAccessControls extends Resource {
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;
private final String bucket;
private final String entity;
private final Role role;
private final String email;
private final String domain;
private final String entityId;
private 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) {
private BucketAccessControls(@Nullable String id, @Nullable URI selfLink, @Nullable String etag, String bucket,
String entity, @Nullable String entityId, Role role, @Nullable String email, @Nullable String domain,
@Nullable 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.role = checkNotNull(role, "role");
this.email = email;
this.domain = domain;
this.projectTeam = projectTeam;
@ -117,13 +119,13 @@ public class BucketAccessControls extends Resource {
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;
private String bucket;
private String entity;
private String entityId;
private Role role;
private String email;
private String domain;
private ProjectTeam projectTeam;
public Builder bucket(String bucket) {
this.bucket = bucket;

View File

@ -32,18 +32,18 @@ import com.google.common.collect.Sets;
public class BucketTemplate {
private String name;
private Long projectNumber;
private Set<BucketAccessControls> acl;
private Set<DefaultObjectAccessControls> defaultObjectAccessControls;
private Owner owner;
private Location location;
private Website website;
private Logging logging;
private Versioning versioning;
private Set<BucketCors> cors;
private BucketLifeCycle lifeCycle;
private StorageClass storageClass;
protected String name;
protected Long projectNumber;
protected Set<BucketAccessControls> acl = Sets.newHashSet();
protected Set<DefaultObjectAccessControls> defaultObjectAccessControls = Sets.newHashSet();
protected Owner owner;
protected Location location;
protected Website website;
protected Logging logging;
protected Versioning versioning;
protected Set<BucketCors> cors = Sets.newHashSet();
protected BucketLifeCycle lifeCycle;
protected StorageClass storageClass;
public BucketTemplate name(String name) {
this.name = name;
@ -91,54 +91,32 @@ public class BucketTemplate {
}
public BucketTemplate addAcl(BucketAccessControls bucketAccessControls) {
if (this.acl == null) {
this.acl = Sets.newLinkedHashSet();
}
this.acl.add(bucketAccessControls);
return this;
}
public BucketTemplate acl(Set<BucketAccessControls> acl) {
if (this.acl == null) {
this.acl = Sets.newLinkedHashSet();
}
this.acl.addAll(acl);
return this;
}
public BucketTemplate addDefaultObjectAccessControls(DefaultObjectAccessControls oac) {
if (this.defaultObjectAccessControls == null) {
this.defaultObjectAccessControls = Sets.newLinkedHashSet();
}
this.defaultObjectAccessControls.add(oac);
return this;
}
public BucketTemplate defaultObjectAccessControls(Set<DefaultObjectAccessControls> defaultObjectAcl) {
if (this.defaultObjectAccessControls == null) {
this.defaultObjectAccessControls = Sets.newLinkedHashSet();
}
this.defaultObjectAccessControls.addAll(defaultObjectAcl);
return this;
}
public BucketTemplate addCORS(BucketCors cors) {
if (this.cors == null) {
this.cors = Sets.newLinkedHashSet();
}
this.cors.add(cors);
return this;
}
public BucketTemplate cors(Set<BucketCors> cors) {
if (this.cors == null) {
this.cors = Sets.newLinkedHashSet();
}
this.cors.addAll(cors);
return this;
}

View File

@ -23,6 +23,7 @@ import java.net.URI;
import org.jclouds.googlecloudstorage.domain.DomainResourceRefferences.ObjectRole;
import org.jclouds.googlecloudstorage.domain.internal.ProjectTeam;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
@ -33,16 +34,17 @@ import com.google.common.base.Objects;
*/
public class DefaultObjectAccessControls extends Resource {
protected final String bucket;
protected final String entity;
protected final ObjectRole role;
protected final String email;
protected final String entityId;
protected final String domain;
protected final ProjectTeam projectTeam;
private final String bucket;
private final String entity;
private final ObjectRole role;
private final String email;
private final String entityId;
private final String domain;
private final ProjectTeam projectTeam;
protected DefaultObjectAccessControls(String id, URI selfLink, String etag, String bucket, String entity,
String entityId, ObjectRole role, String email, String domain, ProjectTeam projectTeam) {
private DefaultObjectAccessControls(@Nullable String id, @Nullable URI selfLink, @Nullable String etag,
@Nullable String bucket, String entity, @Nullable String entityId, ObjectRole role, @Nullable String email,
@Nullable String domain, @Nullable ProjectTeam projectTeam) {
super(Kind.OBJECT_ACCESS_CONTROL, id, selfLink, etag);
this.bucket = bucket;
@ -117,13 +119,13 @@ public class DefaultObjectAccessControls extends Resource {
public static final class Builder extends Resource.Builder<Builder> {
protected String bucket;
protected String entity;
protected String entityId;
protected ObjectRole role;
protected String email;
protected String domain;
protected ProjectTeam projectTeam;
private String bucket;
private String entity;
private String entityId;
private ObjectRole role;
private String email;
private String domain;
private ProjectTeam projectTeam;
public Builder bucket(String bucket) {
this.bucket = bucket;

View File

@ -25,8 +25,8 @@ import org.jclouds.googlecloudstorage.domain.DomainResourceRefferences.ObjectRol
*/
public class DefaultObjectAccessControlsTemplate {
protected String entity;
protected ObjectRole role;
private String entity;
private ObjectRole role;
public DefaultObjectAccessControlsTemplate role(ObjectRole role) {
this.role = role;

View File

@ -35,16 +35,16 @@ public final class DomainResourceRefferences {
ASIA, EU, US, ASIA_EAST1, US_CENTRAL1, US_CENTRAL2, US_EAST1, US_EAST2, US_EAST3, US_WEST1;
public String value() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name()).toUpperCase();
return name().replace('_', '-');
}
@Override
public String toString() {
return value().toUpperCase();
return value();
}
public static Location fromValue(String location) {
return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, location.toLowerCase()));
return valueOf(location.replace('-', '_'));
}
}

View File

@ -35,10 +35,10 @@ import com.google.common.collect.ImmutableSet;
public class ListBucketAccessControls {
protected final Kind kind;
protected final Set<BucketAccessControls> items;
private final Kind kind;
private final Set<BucketAccessControls> items;
protected ListBucketAccessControls(Kind kind, Set<BucketAccessControls> items) {
private ListBucketAccessControls(Kind kind, Set<BucketAccessControls> items) {
this.kind = checkNotNull(kind, "kind");
this.items = checkNotNull(items, "items");

View File

@ -35,10 +35,10 @@ import com.google.common.collect.ImmutableSet;
public class ListDefaultObjectAccessControls {
protected final Kind kind;
protected final Set<DefaultObjectAccessControls> items;
private final Kind kind;
private final Set<DefaultObjectAccessControls> items;
protected ListDefaultObjectAccessControls(Kind kind, Set<DefaultObjectAccessControls> items) {
private ListDefaultObjectAccessControls(Kind kind, Set<DefaultObjectAccessControls> items) {
this.kind = checkNotNull(kind, "kind");
this.items = checkNotNull(items, "items");
@ -110,4 +110,3 @@ public class ListDefaultObjectAccessControls {
}
}
}

View File

@ -24,6 +24,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.beans.ConstructorProperties;
import java.net.URI;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.CaseFormat;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
@ -62,7 +64,7 @@ public class Resource {
protected final String etag;
@ConstructorProperties({ "kind", "id", "selfLink", "etag" })
protected Resource(Kind kind, String id, URI selfLink, String etag) {
protected Resource(Kind kind, @Nullable String id, @Nullable URI selfLink, @Nullable String etag) {
this.kind = checkNotNull(kind, "kind");
this.id = id;
this.selfLink = selfLink;

View File

@ -27,7 +27,7 @@ import com.google.common.base.Objects;
public class Action {
private final String type;
public Action(String type) {
private Action(String type) {
this.type = type;
}
@ -84,9 +84,7 @@ public class Action {
public Builder fromAction(Action in) {
return this.type(in.getType());
}
}
}

View File

@ -21,8 +21,6 @@ import static com.google.common.base.Objects.toStringHelper;
import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
@ -32,31 +30,30 @@ import com.google.common.collect.ImmutableSet;
* @see <a href= "https://developers.google.com/storage/docs/cross-origin" />
*/
public final class BucketCors {
private final Set<String> origins;
private final Set<String> methods;
private final Set<String> responseHeaders;
public class BucketCors {
private final Set<String> origin;
private final Set<String> method;
private final Set<String> responseHeader;
private final Integer maxAgeSeconds;
public BucketCors(@Nullable Set<String> origin, @Nullable Set<String> method, @Nullable Set<String> responseHeader,
private BucketCors(Set<String> origin, Set<String> method, Set<String> responseHeader,
Integer maxAgeSeconds) {
this.origins = origin == null ? ImmutableSet.<String> of() : origin;
this.methods = method == null ? ImmutableSet.<String> of() : method;
this.responseHeaders = responseHeader == null ? ImmutableSet.<String> of() : responseHeader;
this.origin = origin.isEmpty() ? null : origin;
this.method = method.isEmpty() ? null : method;
this.responseHeader = responseHeader.isEmpty() ? null : responseHeader;
this.maxAgeSeconds = maxAgeSeconds;
}
public Set<String> getOrigin() {
return origins;
return origin;
}
public Set<String> getMethod() {
return methods;
return method;
}
public Set<String> getResponseHeader() {
return responseHeaders;
return responseHeader;
}
public Integer getMaxAgeSeconds() {
@ -65,10 +62,9 @@ public final class BucketCors {
@Override
public int hashCode() {
return Objects.hashCode(origins, methods, responseHeaders, maxAgeSeconds);
return Objects.hashCode(origin, method, responseHeader, maxAgeSeconds);
}
/* TODO -Check equals */
@Override
public boolean equals(Object obj) {
if (this == obj)
@ -76,12 +72,12 @@ public final class BucketCors {
if (obj == null || getClass() != obj.getClass())
return false;
BucketCors that = BucketCors.class.cast(obj);
return equal(this.origins, that.origins) && equal(this.methods, that.methods)
&& equal(this.responseHeaders, that.responseHeaders) && equal(this.maxAgeSeconds, that.maxAgeSeconds);
return equal(this.origin, that.origin) && equal(this.method, that.method)
&& equal(this.responseHeader, that.responseHeader) && equal(this.maxAgeSeconds, that.maxAgeSeconds);
}
protected Objects.ToStringHelper string() {
return toStringHelper(this).add("origin", origins).add("method", methods).add("responseHeader", responseHeaders)
return toStringHelper(this).omitNullValues().add("origin", origin).add("method", method).add("responseHeader", responseHeader)
.add("maxAgeSeconds", maxAgeSeconds);
}
@ -94,40 +90,40 @@ public final class BucketCors {
return new Builder();
}
public static final class Builder {
public static class Builder {
private ImmutableSet.Builder<String> origins = ImmutableSet.builder();
private ImmutableSet.Builder<String> methods = ImmutableSet.builder();
private ImmutableSet.Builder<String> reponseHeaders = ImmutableSet.builder();
private ImmutableSet.Builder<String> origin = ImmutableSet.builder();
private ImmutableSet.Builder<String> method = ImmutableSet.builder();
private ImmutableSet.Builder<String> reponseHeader = ImmutableSet.builder();
private Integer maxAgeSeconds;
public Builder addOrigin(String origin) {
this.origins.add(origin);
this.origin.add(origin);
return this;
}
public Builder origin(Set<String> origin) {
this.origins.addAll(origin);
this.origin.addAll(origin);
return this;
}
public Builder addMethod(String method) {
this.methods.add(method);
this.method.add(method);
return this;
}
public Builder method(Set<String> method) {
this.methods.addAll(method);
this.method.addAll(method);
return this;
}
public Builder addResponseHeader(String responseHeader) {
this.reponseHeaders.add(responseHeader);
this.reponseHeader.add(responseHeader);
return this;
}
public Builder responseHeader(Set<String> responseHeader) {
this.reponseHeaders.addAll(responseHeader);
public Builder responseHeaders(Set<String> responseHeaders) {
this.reponseHeader.addAll(responseHeaders);
return this;
}
@ -137,13 +133,13 @@ public final class BucketCors {
}
public BucketCors build() {
return new BucketCors(this.origins.build(), this.methods.build(), this.reponseHeaders.build(),
return new BucketCors(this.origin.build(), this.method.build(), this.reponseHeader.build(),
this.maxAgeSeconds);
}
public Builder fromCors(BucketCors c) {
return this.maxAgeSeconds(c.getMaxAgeSeconds()).origin(c.getOrigin()).method(c.getMethod())
.responseHeader(c.getResponseHeader());
public Builder fromCors(BucketCors in) {
return this.maxAgeSeconds(in.getMaxAgeSeconds()).origin(in.getOrigin()).method(in.getMethod())
.responseHeaders(in.getResponseHeader());
}
}

View File

@ -33,11 +33,11 @@ public class BucketLifeCycle {
private final Set<Rule> rules;
public BucketLifeCycle(Set<Rule> rule) {
this.rules = rule == null ? ImmutableSet.<Rule> of() : rule;
private BucketLifeCycle(Set<Rule> rules) {
this.rules = rules.isEmpty() ? null : rules;
}
public Set<Rule> getRule() {
public Set<Rule> getRules() {
return rules;
}
@ -77,6 +77,7 @@ public class BucketLifeCycle {
}
public static class Builder {
ImmutableSet.Builder<Rule> rules = ImmutableSet.builder();
public Builder addRule(Rule rule) {
@ -84,8 +85,8 @@ public class BucketLifeCycle {
return this;
}
public Builder rule(Set<Rule> rule) {
this.rules.addAll(rule);
public Builder rule(Set<Rule> rules) {
this.rules.addAll(rules);
return this;
}
@ -94,8 +95,8 @@ public class BucketLifeCycle {
}
public Builder fromLifeCycle(BucketLifeCycle in) {
return this.rule(in.getRule());
return this.rule(in.getRules());
}
}
}

View File

@ -20,6 +20,8 @@ import static com.google.common.base.Objects.toStringHelper;
import java.util.Date;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
/**
@ -32,7 +34,8 @@ public class Condition {
private final Boolean isLive;
private final Integer numNewerVersions;
public Condition(Integer age, Date createdBefore, Boolean isLive, Integer numNewerVersions) {
private Condition(@Nullable Integer age, @Nullable Date createdBefore, @Nullable Boolean isLive,
@Nullable Integer numNewerVersions) {
this.age = age;
this.createdBefore = createdBefore;
this.isLive = isLive;

View File

@ -18,6 +18,7 @@ package org.jclouds.googlecloudstorage.domain.internal;
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 com.google.common.base.Objects;
@ -28,14 +29,14 @@ import com.google.common.base.Objects;
* @see <a href= "https://developers.google.com/storage/docs/accesslogs" />
*/
public final class Logging {
public class Logging {
private final String logBucket;
private final String logObjectPrefix;
public Logging(String logBucket, String logObjectPrefix) {
private Logging(String logBucket, String logObjectPrefix) {
this.logBucket = logBucket;
this.logObjectPrefix = logObjectPrefix;
this.logBucket = checkNotNull(logBucket, "logBucket");
this.logObjectPrefix = checkNotNull(logObjectPrefix , "logObjectPrefix");
}
public String getLogBucket() {

View File

@ -18,6 +18,9 @@ package org.jclouds.googlecloudstorage.domain.internal;
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 org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
@ -25,13 +28,12 @@ import com.google.common.base.Objects;
* This is an internal object used in both Bucket and Object representation
*/
public final class Owner {
public class Owner {
private final String entity;
private final String entityId;
public Owner(String entity, String entityId) {
this.entity = entity;
private Owner(String entity, @Nullable String entityId) {
this.entity = checkNotNull(entity, "entity");
this.entityId = entityId;
}
@ -59,7 +61,7 @@ public final class Owner {
}
protected Objects.ToStringHelper string() {
return toStringHelper(this).omitNullValues().add("entiy", entity).add("entityId", entityId);
return toStringHelper(this).omitNullValues().add("entity", entity).add("entityId", entityId);
}
@Override

View File

@ -19,8 +19,6 @@ package org.jclouds.googlecloudstorage.domain.internal;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import java.beans.ConstructorProperties;
import com.google.common.base.Objects;
/**
@ -31,14 +29,27 @@ import com.google.common.base.Objects;
public final class ProjectTeam {
public enum Team {
owners, editors, viewers;
OWNERS, EDITORS, VIEWERS;
public String value() {
return name().toLowerCase();
}
@Override
public String toString() {
return value();
}
public static Team fromValue(String team) {
return valueOf(team.toUpperCase());
}
}
private final String projectId;
private final Team team;
@ConstructorProperties({ "projectId", "team" })
public ProjectTeam(String projectId, Team team) {
private ProjectTeam(String projectId, Team team) {
this.projectId = projectId;
this.team = team;
}
@ -75,6 +86,10 @@ public final class ProjectTeam {
return string().toString();
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String projectId;

View File

@ -17,6 +17,7 @@
package org.jclouds.googlecloudstorage.domain.internal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Objects;
@ -29,9 +30,9 @@ public class Rule {
private final Action action;
private final Condition condition;
public Rule(Action action, Condition condition) {
this.action = action;
this.condition = condition;
private Rule(Action action, Condition condition) {
this.action = checkNotNull(action, "action");
this.condition = checkNotNull(condition, "condition");
}
public Action getAction() {

View File

@ -29,7 +29,7 @@ import com.google.common.base.Objects;
public final class Versioning {
private final Boolean enabled;
public Versioning(Boolean enabled) {
private Versioning(Boolean enabled) {
this.enabled = enabled;
}

View File

@ -19,6 +19,8 @@ package org.jclouds.googlecloudstorage.domain.internal;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
/**
@ -28,11 +30,10 @@ import com.google.common.base.Objects;
*/
public class Website {
private final String mainPageSuffix;
private final String notFoundPage;
public Website(String mainPageSuffix, String notFoundPage) {
private Website(@Nullable String mainPageSuffix, @Nullable String notFoundPage) {
this.mainPageSuffix = mainPageSuffix;
this.notFoundPage = notFoundPage;

View File

@ -41,7 +41,6 @@ import org.jclouds.googlecloudstorage.options.GetBucketOptions;
import org.jclouds.googlecloudstorage.options.InsertBucketOptions;
import org.jclouds.googlecloudstorage.options.ListOptions;
import org.jclouds.googlecloudstorage.options.UpdateBucketOptions;
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;
@ -57,7 +56,7 @@ import org.jclouds.rest.binders.BindToJsonPayload;
/**
* Provides access to Bucket entities via their REST API.
*
* @see <a href = " https://developers.google.com/storage/docs/json_api/v1/buckets"/>
* @see <a href = "https://developers.google.com/storage/docs/json_api/v1/buckets"/>
*/
@SkipEncoding({ '/', '=' })
@ -72,7 +71,6 @@ public interface BucketApi {
*
* @return a {@link Bucket} resource
*/
@Named("Bucket:get")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@ -81,7 +79,7 @@ public interface BucketApi {
@OAuthScopes(STORAGE_READONLY_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Bucket getBuckets(@PathParam("bucket") String bucketName);
Bucket getBucket(@PathParam("bucket") String bucketName);
/**
* Returns metadata for the specified bucket
@ -93,7 +91,6 @@ public interface BucketApi {
*
* @return a {@link Bucket} resource
*/
@Named("Bucket:get")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@ -102,7 +99,7 @@ public interface BucketApi {
@OAuthScopes(STORAGE_READONLY_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
Bucket getBuckets(@PathParam("bucket") String bucketName, GetBucketOptions options);
Bucket getBucket(@PathParam("bucket") String bucketName, GetBucketOptions options);
/**
* Creates a new bucket
@ -110,90 +107,78 @@ public interface BucketApi {
* @param projectId
* A valid API project identifier
* @param bucketTemplate
* In the request body, supply a bucket resource
* supply a {@link BucketTemplate} resource
*
* @return If successful, this method returns a {@link Bucket} resource in the response body
* @return If successful, this method returns a {@link Bucket} resource.
*/
@Named("Bucket:insert")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Path("/b")
@OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
@MapBinder(BucketBinder.class)
Bucket createBuckets(@QueryParam("project") String projectId,
@PayloadParam("template") BucketTemplate bucketTemplate);
Bucket createBucket(@QueryParam("project") String projectId, @PayloadParam("template") BucketTemplate bucketTemplate);
/**
* Creates a new Bucket
*
* @param projectNumber
* @param projectId
* A valid API project identifier
*
* @param bucketTemplate
* In the request body, supply a {@link Bucket} resource
* Supply a {@link BucketTemplate} resource
* @param options
* Supply {@link InsertBucketOptions} with optional query parameters
*
* @return If successful, this method returns a {@link Bucket} resource in the response body
* @return If successful, this method returns a {@link Bucket} resource.
*/
@Named("Bucket:insert")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Path("/b")
@OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
@MapBinder(BucketBinder.class)
Bucket createBuckets(@QueryParam("project") String projectNumber,
Bucket createBucket(@QueryParam("project") String projectId,
@PayloadParam("template") BucketTemplate bucketTemplate, InsertBucketOptions options);
/**
* Permanently deletes an empty Bucket
* Permanently deletes an empty Bucket.If bucket is not empty 409 error to indicate the conflict.
*
* @param bucketName
* Name of the bucket
*
* @return If successful, this method returns an empty response body
*/
@Named("Bucket:delete")
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
@Path("/b/{bucket}")
@OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
HttpResponse deleteBuckets(@PathParam("bucket") String bucketName);
void deleteBucket(@PathParam("bucket") String bucketName);
/**
* Permanently deletes an empty Bucket
* Permanently deletes an empty Bucket.If bucket is not empty 409 error to indicate the conflict.
*
* @param bucketName
* Name of the bucket
* @param options
* Supply {@link DeleteBucketOptions} with optional query parameters
*
* @return If successful, this method returns an empty response body.
*/
@Named("Bucket:delete")
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
@Path("/b/{bucket}")
@OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
HttpResponse deleteBuckets(@PathParam("bucket") String bucketName, DeleteBucketOptions options);
void deleteBucket(@PathParam("bucket") String bucketName, DeleteBucketOptions options);
/**
* Retrieves a list of buckets for a given project
*
* @param project
* Name of the project to retrieve the buckets
* @param projectId
* A valid API project identifier
*
* @return a {@link ListPage<Bucket>}
*/
@Named("Bucket:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@ -202,19 +187,16 @@ public interface BucketApi {
@OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
ListPage<Bucket> listBuckets(@QueryParam("project") String project);
ListPage<Bucket> listBucket(@QueryParam("project") String projectId);
/**
* Retrieves a list of buckets for a given project
*
* @param project
* Name of the project to retrieve the buckets
* @param projectId
* A valid API project identifier
* @param options
* Supply {@link ListOptions} with optional query parameters
*
*
*/
@Named("Bucket:list")
@GET
@Consumes(MediaType.APPLICATION_JSON)
@ -223,19 +205,18 @@ public interface BucketApi {
@OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
@Nullable
ListPage<Bucket> listBuckets(@QueryParam("project") String project, ListOptions options);
ListPage<Bucket> listBucket(@QueryParam("project") String projectId, ListOptions options);
/**
* Updates a bucket
*
* @param bucketName
* Name of the bucket
* @param bucket
* In the request body, supply a bucket resource with list of {@link BucketAccessControls}
* @param bucketTemplate
* Supply a {@link BucketTemplate} resource with list of {@link BucketAccessControls}
*
* @return If successful, this method returns a {@link Bucket} resource in the response body
* @return If successful, this method returns the updated {@link Bucket} resource.
*/
@Named("Bucket:update")
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@ -243,20 +224,21 @@ public interface BucketApi {
@Path("/b/{bucket}")
@OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
Bucket updateBuckets(@PathParam("bucket") String bucketName,
Bucket updateBucket(@PathParam("bucket") String bucketName,
@BinderParam(BindToJsonPayload.class) BucketTemplate bucketTemplate);
/**
* Updates a bucket
*
* @param bucketName
* In the request body, supply a bucket resource with list of {@link BucketAccessControls} (acl[])
* Name of the bucket
* @param bucketTemplate
* Supply a {@link BucketTemplate} resource with list of {@link BucketAccessControls}
* @param options
* Supply {@link UpdateBucketOptions} with optional query parameters
*
* @return If successful,this method returns a {@link Bucket} resource in the response body
* @return If successful,this method returns the updated {@link Bucket} resource.
*/
@Named("Bucket:update")
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@ -264,20 +246,21 @@ public interface BucketApi {
@Path("/b/{bucket}")
@OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
Bucket updateBuckets(@PathParam("bucket") String bucketName,
Bucket updateBucket(@PathParam("bucket") String bucketName,
@BinderParam(BindToJsonPayload.class) BucketTemplate bucketTemplate, UpdateBucketOptions options);
/**
* Updates a bucket supporting patch semantics.
*
* @param bucketName
* In the request body, supply a bucket resource with list of {@link BucketAccessControls} (acl[])
* @param bucketTemplate
* In the request body, supply the relevant portions of a bucket resource
* @see <a href = "https://developers.google.com/storage/docs/json_api/v1/how-tos/performance#patch"/>
*
* @return If successful, this method returns a {@link Bucket} resource in the response body
* @param bucketName
* Name of the bucket
* @param bucketTemplate
* Supply a {@link BucketTemplate} resource with list of {@link BucketAccessControls}
*
* @return If successful, this method returns the updated {@link Bucket} resource.
*/
@Named("Bucket:patch")
@PATCH
@Consumes(MediaType.APPLICATION_JSON)
@ -285,22 +268,23 @@ public interface BucketApi {
@Path("/b/{bucket}")
@OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
Bucket patchBuckets(@PathParam("bucket") String bucketName,
Bucket patchBucket(@PathParam("bucket") String bucketName,
@BinderParam(BindToJsonPayload.class) BucketTemplate bucketTemplate);
/**
* Updates a bucket supporting patch semantics.
*
* @see <a href = "https://developers.google.com/storage/docs/json_api/v1/how-tos/performance#patch"/>
*
* @param bucketName
* In the request body, supply a bucket resource with list of {@link BucketAccessControls} (acl[])
* Name of the bucket
* @param bucketTemplate
* In the request body, supply the relevant portions of a bucket resource
* Supply a {@link BucketTemplate} resource with list of {@link BucketAccessControls}
* @param options
* Supply {@link UpdateBucketOptions} with optional query parameters
*
* @return If successful, this method returns a {@link Bucket} resource in the response body
* @return If successful, this method returns the updated {@link Bucket} resource.
*/
@Named("Bucket:patch")
@PATCH
@Consumes(MediaType.APPLICATION_JSON)
@ -308,6 +292,6 @@ public interface BucketApi {
@Path("/b/{bucket}")
@OAuthScopes(STORAGE_FULLCONTROL_SCOPE)
@Fallback(NullOnNotFoundOr404.class)
Bucket patchBuckets(@PathParam("bucket") String bucketName,
Bucket patchBucket(@PathParam("bucket") String bucketName,
@BinderParam(BindToJsonPayload.class) BucketTemplate bucketTemplate, UpdateBucketOptions options);
}

View File

@ -31,9 +31,9 @@ public class BucketBinder implements MapBinder {
private BindToJsonPayload jsonBinder;
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
BucketTemplate postBucket = (BucketTemplate) postParams.get("template");
return bindToRequest(request, postBucket);
public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) throws IllegalArgumentException {
BucketTemplate postBucket = (BucketTemplate) postParams.get("template");
return bindToRequest(request, postBucket);
}
@Override

View File

@ -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.handlers;
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
import javax.inject.Singleton;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException;
/**
* This will parse and set an appropriate exception on the command object.
*/
@Singleton
public class GoogleCloudStorageErrorHandler implements HttpErrorHandler {
public void handleError(HttpCommand command, HttpResponse response) {
// it is important to always read fully and close streams
byte[] data = closeClientButKeepContentStream(response);
String message = data != null ? new String(data) : null;
Exception exception = message != null ? new HttpResponseException(command, response, message)
: new HttpResponseException(command, response);
message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
response.getStatusLine());
switch (response.getStatusCode()) {
case 401:
case 403:
exception = new AuthorizationException(message, exception);
break;
case 404:
exception = new ResourceNotFoundException(message, exception);
break;
case 409:
exception = new IllegalStateException(message, exception);
break;
}
command.setException(exception);
}
}

View File

@ -73,9 +73,9 @@ public class BucketApiExpectTest extends BaseGoogleCloudStorageApiExpectTest {
public void testGetBucketWithNoOptionsResponseIs2xx() throws Exception {
BucketApi api = requestsSendResponses(requestForScopes(STORAGE_READONLY_SCOPE), TOKEN_RESPONSE,
GET_BUCKET_REQUEST, BUCKET_RESPONSE).getBucketsApi();
GET_BUCKET_REQUEST, BUCKET_RESPONSE).getBucketApi();
assertEquals(api.getBuckets(EXPECTED_TEST_BUCKET), new NoAclBucketTest().expected());
assertEquals(api.getBucket(EXPECTED_TEST_BUCKET), new NoAclBucketTest().expected());
}
public void testGetBucketResponseIs4xx() throws Exception {
@ -83,40 +83,40 @@ public class BucketApiExpectTest extends BaseGoogleCloudStorageApiExpectTest {
HttpResponse getResponse = HttpResponse.builder().statusCode(404).build();
BucketApi api = requestsSendResponses(requestForScopes(STORAGE_READONLY_SCOPE), TOKEN_RESPONSE,
GET_BUCKET_REQUEST, getResponse).getBucketsApi();
GET_BUCKET_REQUEST, getResponse).getBucketApi();
assertNull("404", api.getBuckets(EXPECTED_TEST_BUCKET));
assertNull("404", api.getBucket(EXPECTED_TEST_BUCKET));
}
// Test getBucket with options
public void testGetBucketWithOptionsResponseIs2xx() throws Exception {
BucketApi api = requestsSendResponses(requestForScopes(STORAGE_READONLY_SCOPE), TOKEN_RESPONSE,
GET_BUCKET_REQUEST_WITHOPTIONS, BUCKET_RESPONSE).getBucketsApi();
GET_BUCKET_REQUEST_WITHOPTIONS, BUCKET_RESPONSE).getBucketApi();
GetBucketOptions options = new GetBucketOptions().ifMetagenerationNotMatch(Long.valueOf(100)).projection(
Projection.FULL);
assertEquals(api.getBuckets(EXPECTED_TEST_BUCKET, options), new NoAclBucketTest().expected());
assertEquals(api.getBucket(EXPECTED_TEST_BUCKET, options), new NoAclBucketTest().expected());
}
// Test listBucket without options
public void testListBucketWithNoOptionsResponseIs2xx() throws Exception {
BucketApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
LIST_BUCKET_REQUEST, LIST_BUCKET_RESPONSE).getBucketsApi();
LIST_BUCKET_REQUEST, LIST_BUCKET_RESPONSE).getBucketApi();
assertEquals(api.listBuckets(EXPECTED_TEST_PROJECT_NUMBER), new NoAclBucketListTest().expected());
assertEquals(api.listBucket(EXPECTED_TEST_PROJECT_NUMBER), new NoAclBucketListTest().expected());
}
public void testListBucketWithOptionsResponseIs2xx() throws Exception {
BucketApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
LIST_BUCKET_REQUEST_WITHOPTIONS, LIST_BUCKET_RESPONSE).getBucketsApi();
LIST_BUCKET_REQUEST_WITHOPTIONS, LIST_BUCKET_RESPONSE).getBucketApi();
ListOptions options = new ListOptions().maxResults(2).pageToken("jcloudtestbucket500");
assertEquals(api.listBuckets(EXPECTED_TEST_PROJECT_NUMBER, options), new NoAclBucketListTest().expected());
assertEquals(api.listBucket(EXPECTED_TEST_PROJECT_NUMBER, options), new NoAclBucketListTest().expected());
}
@ -124,9 +124,9 @@ public class BucketApiExpectTest extends BaseGoogleCloudStorageApiExpectTest {
HttpResponse listResponse = HttpResponse.builder().statusCode(404).build();
BucketApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
LIST_BUCKET_REQUEST, listResponse).getBucketsApi();
LIST_BUCKET_REQUEST, listResponse).getBucketApi();
assertNull(api.listBuckets(EXPECTED_TEST_PROJECT_NUMBER));
assertNull(api.listBucket(EXPECTED_TEST_PROJECT_NUMBER));
}
// Test createBucket without options
@ -143,11 +143,11 @@ public class BucketApiExpectTest extends BaseGoogleCloudStorageApiExpectTest {
MediaType.APPLICATION_JSON)).build();
BucketApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
createRequest, BUCKET_RESPONSE).getBucketsApi();
createRequest, BUCKET_RESPONSE).getBucketApi();
BucketTemplate template = new BucketTemplate().name("bhashbucket");
assertEquals(api.createBuckets(EXPECTED_TEST_PROJECT_NUMBER, template), new NoAclBucketTest().expected());
assertEquals(api.createBucket(EXPECTED_TEST_PROJECT_NUMBER, template), new NoAclBucketTest().expected());
}
@ -171,9 +171,9 @@ public class BucketApiExpectTest extends BaseGoogleCloudStorageApiExpectTest {
.payload(staticPayloadFromResource("/bucket_update_response.json")).build();
BucketApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
updateRequest, updateResponse).getBucketsApi();
updateRequest, updateResponse).getBucketApi();
assertEquals(api.updateBuckets(EXPECTED_TEST_BUCKET, template), new BucketUpdateTest().expected());
assertEquals(api.updateBucket(EXPECTED_TEST_BUCKET, template), new BucketUpdateTest().expected());
}
public void testUpdateBucketWithOptionsResponseIs2xx() throws Exception {
@ -199,9 +199,9 @@ public class BucketApiExpectTest extends BaseGoogleCloudStorageApiExpectTest {
.payload(staticPayloadFromResource("/bucket_update_response.json")).build();
BucketApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE,
updateRequest, updateResponse).getBucketsApi();
updateRequest, updateResponse).getBucketApi();
assertEquals(api.updateBuckets(EXPECTED_TEST_BUCKET, template, options), new BucketUpdateTest().expected());
assertEquals(api.updateBucket(EXPECTED_TEST_BUCKET, template, options), new BucketUpdateTest().expected());
}
public void testPatchBucketWithNoOptionsResponseIs2xx() throws Exception {
@ -224,9 +224,9 @@ public class BucketApiExpectTest extends BaseGoogleCloudStorageApiExpectTest {
.payload(staticPayloadFromResource("/bucket_update_response.json")).build();
BucketApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE, patchRequest,
patchResponse).getBucketsApi();
patchResponse).getBucketApi();
assertEquals(api.patchBuckets(EXPECTED_TEST_BUCKET, template), new BucketUpdateTest().expected());
assertEquals(api.patchBucket(EXPECTED_TEST_BUCKET, template), new BucketUpdateTest().expected());
}
public void testPatchBucketWithOptionsResponseIs2xx() throws Exception {
@ -252,8 +252,8 @@ public class BucketApiExpectTest extends BaseGoogleCloudStorageApiExpectTest {
.payload(staticPayloadFromResource("/bucket_update_response.json")).build();
BucketApi api = requestsSendResponses(requestForScopes(STORAGE_FULLCONTROL_SCOPE), TOKEN_RESPONSE, patchRequest,
patchResponse).getBucketsApi();
patchResponse).getBucketApi();
assertEquals(api.updateBuckets(EXPECTED_TEST_BUCKET, template, options), new BucketUpdateTest().expected());
assertEquals(api.updateBucket(EXPECTED_TEST_BUCKET, template, options), new BucketUpdateTest().expected());
}
}

View File

@ -43,72 +43,82 @@ import org.jclouds.googlecloudstorage.options.DeleteBucketOptions;
import org.jclouds.googlecloudstorage.options.GetBucketOptions;
import org.jclouds.googlecloudstorage.options.InsertBucketOptions;
import org.jclouds.googlecloudstorage.options.UpdateBucketOptions;
import org.jclouds.http.HttpResponse;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test;
import com.google.common.collect.Lists;
public class BucketApiLiveTest extends BaseGoogleCloudStorageApiLiveTest {
private static final String BUCKET_NAME = "jcloudtestbucket" + (int) (Math.random() * 10000);
private static final String BUCKET_NAME = "jcloudstestbucket" + (int) (Math.random() * 10000);
private static final String BUCKET_NAME_WITHOPTIONS = "jcloudtestbucketoptions" + (int) (Math.random() * 10000);
private static final String LOG_BUCKET_NAME = "jcloudtestbucket" + (int) (Math.random() * 10000);
private static final String LOG_BUCKET_NAME = "jcloudslogbucket" + (int) (Math.random() * 10000);
private Long metageneration;
private BucketApi api() {
return api.getBucketsApi();
return api.getBucketApi();
}
@Test(groups = "live")
public void testCreateBucket() {
BucketTemplate logTemplate = new BucketTemplate().name(LOG_BUCKET_NAME);
Bucket logResponse = api().createBuckets(PROJECT_NUMBER, logTemplate);
Bucket logResponse = api().createBucket(PROJECT_NUMBER, logTemplate);
assertNotNull(logResponse);
BucketAccessControls acl = BucketAccessControls.builder().bucket(BUCKET_NAME).entity("allUsers").role(Role.OWNER)
.build();
DefaultObjectAccessControls oac = DefaultObjectAccessControls.builder().bucket(BUCKET_NAME).entity("allUsers")
.role(ObjectRole.OWNER).build();
BucketCors bucketCors = BucketCors.builder().addOrigin("http://example.appspot.com").addMethod("GET").addMethod("HEAD")
.addResponseHeader("x-meta-goog-custom").maxAgeSeconds(10).build();
BucketCors bucketCors = BucketCors.builder().addOrigin("http://example.appspot.com").addMethod("GET")
.addMethod("HEAD").addResponseHeader("x-meta-goog-custom").maxAgeSeconds(10).build();
Versioning version = Versioning.builder().enalbled(true).build();
Logging log = new Logging(LOG_BUCKET_NAME, BUCKET_NAME);
Logging log = Logging.builder().logBucket(LOG_BUCKET_NAME).logObjectPrefix(BUCKET_NAME).build();
BucketTemplate template = new BucketTemplate().name(BUCKET_NAME).addAcl(acl)
.addDefaultObjectAccessControls(oac).versioning(version).location(Location.US_CENTRAL2).logging(log)
BucketTemplate template = new BucketTemplate().name(BUCKET_NAME).addAcl(acl).addDefaultObjectAccessControls(oac)
.versioning(version).location(Location.US_CENTRAL2).logging(log)
.storageClass(StorageClass.DURABLE_REDUCED_AVAILABILITY).addCORS(bucketCors);
Bucket response = api().createBuckets(PROJECT_NUMBER, template);
Bucket response = api().createBucket(PROJECT_NUMBER, template);
assertNotNull(response);
assertNotNull(response.getCors());
assertTrue(response.getCors().size() == 1);
assertEquals(response.getKind(), Kind.BUCKET);
assertEquals(response.getName(), BUCKET_NAME);
assertEquals(response.getLocation(), Location.US_CENTRAL2);
assertTrue(response.getVersioning().isEnabled());
}
@Test(groups = "live", dependsOnMethods = { "testCreateBucket" }, expectedExceptions = { IllegalStateException.class })
public void testCreateAlreadyExistBucket() {
BucketTemplate template = new BucketTemplate().name(BUCKET_NAME).location(Location.US_CENTRAL2)
.storageClass(StorageClass.DURABLE_REDUCED_AVAILABILITY);
api().createBucket(PROJECT_NUMBER, template);
}
@Test(groups = "live")
public void testCreateBucketWithOptions() {
DefaultObjectAccessControls oac = DefaultObjectAccessControls.builder().bucket(BUCKET_NAME_WITHOPTIONS)
.entity("allUsers").role(ObjectRole.OWNER).build();
BucketCors bucketCors = BucketCors.builder().addOrigin("http://example.appspot.com").addMethod("GET").addMethod("HEAD")
.addResponseHeader("x-meta-goog-custom").maxAgeSeconds(10).build();
BucketCors bucketCors = BucketCors.builder().addOrigin("http://example.appspot.com").addMethod("GET")
.addMethod("HEAD").addResponseHeader("x-meta-goog-custom").maxAgeSeconds(10).build();
Versioning version = Versioning.builder().enalbled(true).build();
BucketTemplate template = new BucketTemplate().name(BUCKET_NAME_WITHOPTIONS)
.addDefaultObjectAccessControls(oac).versioning(version).location(Location.US_CENTRAL2)
BucketTemplate template = new BucketTemplate().name(BUCKET_NAME_WITHOPTIONS).addDefaultObjectAccessControls(oac)
.versioning(version).location(Location.US_CENTRAL2)
.storageClass(StorageClass.DURABLE_REDUCED_AVAILABILITY).addCORS(bucketCors);
InsertBucketOptions options = new InsertBucketOptions().projection(Projection.FULL);
Bucket response = api().createBuckets(PROJECT_NUMBER, template, options);
Bucket response = api().createBucket(PROJECT_NUMBER, template, options);
assertNotNull(response);
assertNotNull(response.getCors());
@ -123,7 +133,7 @@ public class BucketApiLiveTest extends BaseGoogleCloudStorageApiLiveTest {
BucketAccessControls bucketacl = BucketAccessControls.builder().bucket(BUCKET_NAME)
.entity("allAuthenticatedUsers").role(Role.OWNER).build();
BucketTemplate template = new BucketTemplate().name(BUCKET_NAME).addAcl(bucketacl);
Bucket response = api().updateBuckets(BUCKET_NAME, template);
Bucket response = api().updateBucket(BUCKET_NAME, template);
assertNotNull(response);
assertEquals(response.getName(), BUCKET_NAME);
@ -136,7 +146,7 @@ public class BucketApiLiveTest extends BaseGoogleCloudStorageApiLiveTest {
.entity("allAuthenticatedUsers").role(Role.OWNER).build();
UpdateBucketOptions options = new UpdateBucketOptions().projection(Projection.FULL);
BucketTemplate template = new BucketTemplate().name(BUCKET_NAME_WITHOPTIONS).addAcl(bucketacl);
Bucket response = api().updateBuckets(BUCKET_NAME_WITHOPTIONS, template, options);
Bucket response = api().updateBucket(BUCKET_NAME_WITHOPTIONS, template, options);
assertNotNull(response);
@ -148,7 +158,7 @@ public class BucketApiLiveTest extends BaseGoogleCloudStorageApiLiveTest {
@Test(groups = "live", dependsOnMethods = "testCreateBucket")
public void testGetBucket() {
Bucket response = api().getBuckets(BUCKET_NAME);
Bucket response = api().getBucket(BUCKET_NAME);
assertNotNull(response);
assertEquals(response.getName(), BUCKET_NAME);
@ -158,7 +168,7 @@ public class BucketApiLiveTest extends BaseGoogleCloudStorageApiLiveTest {
@Test(groups = "live", dependsOnMethods = "testUpdateBucketWithOptions")
public void testGetBucketWithOptions() {
GetBucketOptions options = new GetBucketOptions().ifMetagenerationMatch(metageneration);
Bucket response = api().getBuckets(BUCKET_NAME_WITHOPTIONS, options);
Bucket response = api().getBucket(BUCKET_NAME_WITHOPTIONS, options);
assertNotNull(response);
assertEquals(response.getName(), BUCKET_NAME_WITHOPTIONS);
@ -167,25 +177,25 @@ public class BucketApiLiveTest extends BaseGoogleCloudStorageApiLiveTest {
@Test(groups = "live", dependsOnMethods = "testCreateBucket")
public void testListBucket() {
ListPage<Bucket> bucket = api().listBuckets(PROJECT_NUMBER);
ListPage<Bucket> bucket = api().listBucket(PROJECT_NUMBER);
Iterator<Bucket> pageIterator = bucket.iterator();
assertTrue(pageIterator.hasNext());
Bucket singlePageIterator = pageIterator.next();
List<Bucket> bucketAsList = Lists.newArrayList(singlePageIterator);
Bucket iteratedBucket = pageIterator.next();
List<Bucket> bucketAsList = Lists.newArrayList(iteratedBucket);
assertNotNull(singlePageIterator);
assertNotNull(iteratedBucket);
assertSame(bucketAsList.size(), 1);
}
@Test(groups = "live", dependsOnMethods = "testCreateBucket")
public void testPatchBucket() {
Logging logging = new Logging(LOG_BUCKET_NAME, BUCKET_NAME);
Logging logging = Logging.builder().logBucket(LOG_BUCKET_NAME).logObjectPrefix(BUCKET_NAME).build();
BucketTemplate template = new BucketTemplate().name(BUCKET_NAME).logging(logging);
Bucket response = api().patchBuckets(BUCKET_NAME, template);
Bucket response = api().patchBucket(BUCKET_NAME, template);
assertNotNull(response);
assertEquals(response.getName(), BUCKET_NAME);
@ -194,14 +204,13 @@ public class BucketApiLiveTest extends BaseGoogleCloudStorageApiLiveTest {
@Test(groups = "live", dependsOnMethods = { "testListBucket", "testGetBucket", "testUpdateBucket" })
public void testDeleteBucket() {
HttpResponse response = api().deleteBuckets(BUCKET_NAME);
HttpResponse response2 = api().deleteBuckets(LOG_BUCKET_NAME);
assertNotNull(response);
assertEquals(response.getStatusCode(), 204);
assertNotNull(response2);
assertEquals(response2.getStatusCode(), 204);
api().deleteBucket(BUCKET_NAME);
api().deleteBucket(LOG_BUCKET_NAME);
}
@Test(groups = "live", dependsOnMethods = { "testDeleteBucket" }, expectedExceptions = { ResourceNotFoundException.class })
public void testDeleteNotExistingBucket() {
api().deleteBucket(BUCKET_NAME);
}
@Test(groups = "live", dependsOnMethods = { "testGetBucketWithOptions" })
@ -210,10 +219,8 @@ public class BucketApiLiveTest extends BaseGoogleCloudStorageApiLiveTest {
DeleteBucketOptions options = new DeleteBucketOptions().ifMetagenerationMatch(metageneration)
.ifMetagenerationNotMatch(metageneration + 1);
HttpResponse response = api().deleteBuckets(BUCKET_NAME_WITHOPTIONS, options);
api().deleteBucket(BUCKET_NAME_WITHOPTIONS, options);
assertNotNull(response);
assertEquals(response.getStatusCode(), 204);
}
}

View File

@ -0,0 +1,107 @@
/*
* 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 static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reportMatcher;
import static org.easymock.EasyMock.verify;
import java.net.URI;
import org.easymock.IArgumentMatcher;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "GoogleStorageErrorHandlerTest")
public class GoogleCloudStorageErrorHandlerTest {
@Test
public void test409MakesIllegalStateException() {
assertCodeMakes("POST", URI.create("https://www.googleapis.com/storage/v1"), 409, "HTTP/1.1 409 Conflict",
"\"{\"code\":\"InvalidState\",\"message\":\"An incompatible transition has already been queued for this"
+ " resource\"}\"", IllegalStateException.class);
}
@Test
public void test401MakesAuthorizationException() {
assertCodeMakes("POST", URI.create("https://www.googleapis.com/storage/v1"), 401, "HTTP/1.1 401 Unauthorized",
"Login Required", AuthorizationException.class);
}
@Test
public void test403MakesAuthorizationException() {
assertCodeMakes("POST", URI.create("https://www.googleapis.com/storage/v1"), 403, "HTTP/1.1 403 Forbidden",
"Login Required", AuthorizationException.class);
}
@Test
public void test404MakesResourceNotFoundException() {
assertCodeMakes("POST", URI.create("https://www.googleapis.com/storage/v1"), 404, "HTTP/1.1 404 Not Found",
"Not Found", ResourceNotFoundException.class);
}
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content,
Class<? extends Exception> expected) {
assertCodeMakes(method, uri, statusCode, message, "application/json", content, expected);
}
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
String content, Class<? extends Exception> expected) {
GoogleCloudStorageErrorHandler function = new GoogleCloudStorageErrorHandler();
HttpCommand command = createMock(HttpCommand.class);
HttpRequest request = HttpRequest.builder().method(method).endpoint(uri).build();
HttpResponse response = HttpResponse.builder().statusCode(statusCode).message(message).payload(content).build();
response.getPayload().getContentMetadata().setContentType(contentType);
expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
command.setException(classEq(expected));
replay(command);
function.handleError(command, response);
verify(command);
}
public static Exception classEq(final Class<? extends Exception> in) {
reportMatcher(new IArgumentMatcher() {
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("classEq(");
buffer.append(in);
buffer.append(")");
}
@Override
public boolean matches(Object arg) {
return arg.getClass() == in;
}
});
return null;
}
}

View File

@ -42,8 +42,8 @@ public class BucketAclListTest extends BaseGoogleCloudStorageParseTest<ListBucke
.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();
.projectTeam(ProjectTeam.builder().projectId("1082289308625").team(Team.OWNERS).build())
.bucket("jcloudtestbucket").entity("project-owners-1082289308625").role(Role.OWNER).etag("CAc=").build();
@Override
public String resource() {

View File

@ -36,6 +36,7 @@ public class DefaultObjectAclGetTest extends BaseGoogleCloudStorageParseTest<Def
@Consumes(MediaType.APPLICATION_JSON)
public DefaultObjectAccessControls expected() {
return DefaultObjectAccessControls.builder().entity("project-owners-1082289308625").role(ObjectRole.OWNER)
.etag("CAk=").projectTeam(new ProjectTeam("1082289308625", Team.owners)).build();
.etag("CAk=").projectTeam(ProjectTeam.builder().projectId("1082289308625").team(Team.OWNERS).build())
.build();
}
}

View File

@ -33,7 +33,8 @@ public class DefaultObjectAclListTest extends BaseGoogleCloudStorageParseTest<Li
private DefaultObjectAccessControls item_1 = DefaultObjectAccessControls.builder()
.entity("project-owners-1082289308625").role(ObjectRole.OWNER)
.projectTeam(new ProjectTeam("1082289308625", Team.owners)).etag("CAk=").build();
.projectTeam(ProjectTeam.builder().projectId("1082289308625").team(Team.OWNERS).build()).etag("CAk=")
.build();
@Override
public String resource() {

View File

@ -29,6 +29,7 @@ import org.jclouds.googlecloudstorage.domain.Bucket;
import org.jclouds.googlecloudstorage.domain.DefaultObjectAccessControls;
import org.jclouds.googlecloudstorage.domain.DomainResourceRefferences.Role;
import org.jclouds.googlecloudstorage.domain.DomainResourceRefferences.StorageClass;
import org.jclouds.googlecloudstorage.domain.internal.BucketCors;
import org.jclouds.googlecloudstorage.domain.internal.Owner;
import org.jclouds.googlecloudstorage.domain.internal.ProjectTeam;
import org.jclouds.googlecloudstorage.domain.internal.ProjectTeam.Team;
@ -36,16 +37,21 @@ import org.jclouds.googlecloudstorage.internal.BaseGoogleCloudStorageParseTest;
public class FullBucketGetTest extends BaseGoogleCloudStorageParseTest<Bucket> {
private final BucketAccessControls acl_1 = BucketAccessControls
private final BucketAccessControls acl1 = BucketAccessControls
.builder()
.id("jcloudtestbucket3500/project-owners-1082289308625")
.selfLink(
URI.create("https://www.googleapis.com/storage/v1/b/jcloudtestbucket3500/acl/project-owners-1082289308625"))
.bucket("jcloudtestbucket3500").entity("project-owners-1082289308625").role(Role.OWNER)
.projectTeam(new ProjectTeam("1082289308625", Team.owners)).etag("CAo=").build();
.projectTeam(ProjectTeam.builder().projectId("1082289308625").team(Team.OWNERS).build()).etag("CAo=")
.build();
private final DefaultObjectAccessControls defObjectAcl = DefaultObjectAccessControls.builder()
.entity("project-owners-1082289308625").role(ObjectRole.OWNER).etag("CAo=").build();
private final BucketCors bucketCors = BucketCors.builder().addOrigin("http://example.appspot.com").addMethod("GET")
.addMethod("HEAD").addResponseHeader("x-meta-goog-custom").maxAgeSeconds(10).build();
@Override
public String resource() {
return "/full_bucket_get.json";
@ -59,8 +65,8 @@ public class FullBucketGetTest extends BaseGoogleCloudStorageParseTest<Bucket> {
.name("jcloudtestbucket3500").projectNumber(Long.valueOf("1082289308625"))
.timeCreated(new SimpleDateFormatDateService().iso8601DateParse("2014-06-19T14:03:22.345Z"))
.metageneration(Long.valueOf(10)).owner(Owner.builder().entity("project-owners-1082289308625").build())
.location(Location.US).storageClass(StorageClass.STANDARD).etag("CAo=").addAcl(acl_1)
.addDefaultObjectAcl(defObjectAcl).build();
.location(Location.US).storageClass(StorageClass.STANDARD).etag("CAo=").addAcl(acl1)
.addDefaultObjectAcl(defObjectAcl).addCORS(bucketCors).build();
}
}

View File

@ -32,7 +32,7 @@ import org.jclouds.googlecloudstorage.internal.BaseGoogleCloudStorageParseTest;
public class NoAclBucketListTest extends BaseGoogleCloudStorageParseTest<ListPage<Bucket>> {
private Bucket item_1 = Bucket.builder().id("bhashbucket")
private Bucket item1 = Bucket.builder().id("bhashbucket")
.selfLink(URI.create("https://content.googleapis.com/storage/v1/b/bhashbucket")).name("bhashbucket")
.projectNumber(Long.valueOf("1082289308625"))
.timeCreated(new SimpleDateFormatDateService().iso8601DateParse("2014-06-02T19:19:41.112z"))
@ -47,7 +47,7 @@ public class NoAclBucketListTest extends BaseGoogleCloudStorageParseTest<ListPag
@Override
@Consumes(MediaType.APPLICATION_JSON)
public ListPage<Bucket> expected() {
return ListPage.<Bucket> builder().kind(Kind.BUCKETS).nextPageToken("bhashbucket").addItem(item_1).build();
return ListPage.<Bucket> builder().kind(Kind.BUCKETS).nextPageToken("bhashbucket").addItem(item1).build();
}
}

View File

@ -29,6 +29,22 @@
"etag": "CAo="
}
],
"cors": [
{
"maxAgeSeconds": 10,
"origin": [
"http://example.appspot.com"
],
"responseHeader": [
"x-meta-goog-custom"
],
"method": [
"GET",
"HEAD"
]
}
],
"owner": {
"entity": "project-owners-1082289308625"
},