All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.cloud.storage.BucketInfo Maven / Gradle / Ivy

There is a newer version: 0.2.8
Show newest version
/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.cloud.storage;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Lists.transform;

import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.Data;
import com.google.api.client.util.DateTime;
import com.google.api.services.storage.model.Bucket.Lifecycle;
import com.google.api.services.storage.model.Bucket.Lifecycle.Rule;
import com.google.api.services.storage.model.Bucket.Owner;
import com.google.api.services.storage.model.Bucket.Versioning;
import com.google.api.services.storage.model.Bucket.Website;
import com.google.api.services.storage.model.BucketAccessControl;
import com.google.api.services.storage.model.ObjectAccessControl;
import com.google.cloud.storage.Acl.Entity;
import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.List;
import java.util.Objects;

/**
 * Google Storage bucket metadata;
 *
 * @see Concepts and
 *      Terminology
 */
public class BucketInfo implements Serializable {

  static final Function FROM_PB_FUNCTION =
      new Function() {
        @Override
        public BucketInfo apply(com.google.api.services.storage.model.Bucket pb) {
          return BucketInfo.fromPb(pb);
        }
      };
  static final Function TO_PB_FUNCTION =
      new Function() {
        @Override
        public com.google.api.services.storage.model.Bucket apply(BucketInfo bucketInfo) {
          return bucketInfo.toPb();
        }
      };
  private static final long serialVersionUID = -4712013629621638459L;
  private final String generatedId;
  private final String name;
  private final Acl.Entity owner;
  private final String selfLink;
  private final Boolean versioningEnabled;
  private final String indexPage;
  private final String notFoundPage;
  private final List deleteRules;
  private final String etag;
  private final Long createTime;
  private final Long metageneration;
  private final List cors;
  private final List acl;
  private final List defaultAcl;
  private final String location;
  private final String storageClass;

  /**
   * Base class for bucket's delete rules. Allows to configure automatic deletion of blobs and blobs
   * versions.
   *
   * @see Object Lifecycle Management
   */
  public abstract static class DeleteRule implements Serializable {

    private static final long serialVersionUID = 3137971668395933033L;
    private static final String SUPPORTED_ACTION = "Delete";
    private final Type type;

    public enum Type {
      AGE, CREATE_BEFORE, NUM_NEWER_VERSIONS, IS_LIVE, UNKNOWN
    }

    DeleteRule(Type type) {
      this.type = type;
    }

    public Type type() {
      return type;
    }

    @Override
    public int hashCode() {
      return Objects.hash(type);
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) {
        return true;
      }
      if (obj == null || getClass() != obj.getClass()) {
        return false;
      }
      final DeleteRule other = (DeleteRule) obj;
      return Objects.equals(toPb(), other.toPb());
    }

    Rule toPb() {
      Rule rule = new Rule();
      rule.setAction(new Rule.Action().setType(SUPPORTED_ACTION));
      Rule.Condition condition = new Rule.Condition();
      populateCondition(condition);
      rule.setCondition(condition);
      return rule;
    }

    abstract void populateCondition(Rule.Condition condition);

    static DeleteRule fromPb(Rule rule) {
      if (rule.getAction() != null && SUPPORTED_ACTION.endsWith(rule.getAction().getType())) {
        Rule.Condition condition = rule.getCondition();
        Integer age = condition.getAge();
        if (age != null) {
          return new AgeDeleteRule(age);
        }
        DateTime dateTime = condition.getCreatedBefore();
        if (dateTime != null) {
          return new CreatedBeforeDeleteRule(dateTime.getValue());
        }
        Integer numNewerVersions = condition.getNumNewerVersions();
        if (numNewerVersions != null) {
          return new NumNewerVersionsDeleteRule(numNewerVersions);
        }
        Boolean isLive = condition.getIsLive();
        if (isLive != null) {
          return new IsLiveDeleteRule(isLive);
        }
      }
      return new RawDeleteRule(rule);
    }
  }

  /**
   * Delete rule class that sets a Time To Live for blobs in the bucket.
   *
   * @see Object Lifecycle Management
   */
  public static class AgeDeleteRule extends DeleteRule {

    private static final long serialVersionUID = 5697166940712116380L;
    private final int daysToLive;

    /**
     * Creates an {@code AgeDeleteRule} object.
     *
     * @param daysToLive blobs' Time To Live expressed in days. The time when the age condition is
     *     considered to be satisfied is computed by adding {@code daysToLive} days to the
     *     midnight following blob's creation time in UTC.
     */
    public AgeDeleteRule(int daysToLive) {
      super(Type.AGE);
      this.daysToLive = daysToLive;
    }

    public int daysToLive() {
      return daysToLive;
    }

    @Override
    void populateCondition(Rule.Condition condition) {
      condition.setAge(daysToLive);
    }
  }

  static class RawDeleteRule extends DeleteRule {

    private static final long serialVersionUID = -7166938278642301933L;

    private transient Rule rule;

    RawDeleteRule(Rule rule) {
      super(Type.UNKNOWN);
      this.rule = rule;
    }

    @Override
    void populateCondition(Rule.Condition condition) {
      throw new UnsupportedOperationException();
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
      out.defaultWriteObject();
      out.writeUTF(rule.toString());
    }

    private void readObject(ObjectInputStream in) throws IOException,
        ClassNotFoundException {
      in.defaultReadObject();
      rule = new JacksonFactory().fromString(in.readUTF(), Rule.class);
    }

    @Override
    Rule toPb() {
      return rule;
    }
  }

  /**
   * Delete rule class for blobs in the bucket that have been created before a certain date.
   *
   * @see Object Lifecycle Management
   */
  public static class CreatedBeforeDeleteRule extends DeleteRule {

    private static final long serialVersionUID = 881692650279195867L;
    private final long timeMillis;

    /**
     * Creates an {@code CreatedBeforeDeleteRule} object.
     *
     * @param timeMillis a date in UTC. Blobs that have been created before midnight of the provided
     *     date meet the delete condition
     */
    public CreatedBeforeDeleteRule(long timeMillis) {
      super(Type.CREATE_BEFORE);
      this.timeMillis = timeMillis;
    }

    public long timeMillis() {
      return timeMillis;
    }

    @Override
    void populateCondition(Rule.Condition condition) {
      condition.setCreatedBefore(new DateTime(timeMillis));
    }
  }

  /**
   * Delete rule class for versioned blobs. Specifies when to delete a blob's version according to
   * the number of available newer versions for that blob.
   *
   * @see Object Lifecycle Management
   */
  public static class NumNewerVersionsDeleteRule extends DeleteRule {

    private static final long serialVersionUID = -1955554976528303894L;
    private final int numNewerVersions;

    /**
     * Creates an {@code NumNewerVersionsDeleteRule} object.
     *
     * @param numNewerVersions the number of newer versions. A blob's version meets the delete
     *     condition when {@code numNewerVersions} newer versions are available.
     */
    public NumNewerVersionsDeleteRule(int numNewerVersions) {
      super(Type.NUM_NEWER_VERSIONS);
      this.numNewerVersions = numNewerVersions;
    }

    public int numNewerVersions() {
      return numNewerVersions;
    }

    @Override
    void populateCondition(Rule.Condition condition) {
      condition.setNumNewerVersions(numNewerVersions);
    }
  }

  /**
   * Delete rule class to distinguish between live and archived blobs.
   *
   * @see Object Lifecycle Management
   */
  public static class IsLiveDeleteRule extends DeleteRule {

    private static final long serialVersionUID = -3502994563121313364L;
    private final boolean isLive;

    /**
     * Creates an {@code IsLiveDeleteRule} object.
     *
     * @param isLive if set to {@code true} live blobs meet the delete condition. If set to
     *     {@code false} delete condition is met by archived blobs.
     */
    public IsLiveDeleteRule(boolean isLive) {
      super(Type.IS_LIVE);
      this.isLive = isLive;
    }

    public boolean isLive() {
      return isLive;
    }

    @Override
    void populateCondition(Rule.Condition condition) {
      condition.setIsLive(isLive);
    }
  }

  /**
   * Builder for {@code BucketInfo}.
   */
  public abstract static class Builder {
    /**
     * Sets the bucket's name.
     */
    public abstract Builder name(String name);

    abstract Builder generatedId(String generatedId);

    abstract Builder owner(Acl.Entity owner);

    abstract Builder selfLink(String selfLink);

    /**
     * Sets whether versioning should be enabled for this bucket. When set to true, versioning is
     * fully enabled.
     */
    public abstract Builder versioningEnabled(Boolean enable);

    /**
     * Sets the bucket's website index page. Behaves as the bucket's directory index where missing
     * blobs are treated as potential directories.
     */
    public abstract Builder indexPage(String indexPage);

    /**
     * Sets the custom object to return when a requested resource is not found.
     */
    public abstract Builder notFoundPage(String notFoundPage);

    /**
     * Sets the bucket's lifecycle configuration as a number of delete rules.
     *
     * @see Lifecycle Management
     */
    public abstract Builder deleteRules(Iterable rules);

    /**
     * Sets the bucket's storage class. This defines how blobs in the bucket are stored and
     * determines the SLA and the cost of storage. A list of supported values is available
     * here.
     */
    public abstract Builder storageClass(String storageClass);

    /**
     * Sets the bucket's location. Data for blobs in the bucket resides in physical storage within
     * this region. A list of supported values is available
     * here.
     */
    public abstract Builder location(String location);

    abstract Builder etag(String etag);

    abstract Builder createTime(Long createTime);

    abstract Builder metageneration(Long metageneration);

    /**
     * Sets the bucket's Cross-Origin Resource Sharing (CORS) configuration.
     *
     * @see 
     *     Cross-Origin Resource Sharing (CORS)
     */
    public abstract Builder cors(Iterable cors);

    /**
     * Sets the bucket's access control configuration.
     *
     * @see 
     *     About Access Control Lists
     */
    public abstract Builder acl(Iterable acl);

    /**
     * Sets the default access control configuration to apply to bucket's blobs when no other
     * configuration is specified.
     *
     * @see 
     *     About Access Control Lists
     */
    public abstract Builder defaultAcl(Iterable acl);

    /**
     * Creates a {@code BucketInfo} object.
     */
    public abstract BucketInfo build();
  }

  static final class BuilderImpl extends Builder {

    private String generatedId;
    private String name;
    private Acl.Entity owner;
    private String selfLink;
    private Boolean versioningEnabled;
    private String indexPage;
    private String notFoundPage;
    private List deleteRules;
    private String storageClass;
    private String location;
    private String etag;
    private Long createTime;
    private Long metageneration;
    private List cors;
    private List acl;
    private List defaultAcl;

    BuilderImpl(String name) {
      this.name = name;
    }

    BuilderImpl(BucketInfo bucketInfo) {
      generatedId = bucketInfo.generatedId;
      name = bucketInfo.name;
      etag = bucketInfo.etag;
      createTime = bucketInfo.createTime;
      metageneration = bucketInfo.metageneration;
      location = bucketInfo.location;
      storageClass = bucketInfo.storageClass;
      cors = bucketInfo.cors;
      acl = bucketInfo.acl;
      defaultAcl = bucketInfo.defaultAcl;
      owner = bucketInfo.owner;
      selfLink = bucketInfo.selfLink;
      versioningEnabled = bucketInfo.versioningEnabled;
      indexPage = bucketInfo.indexPage;
      notFoundPage = bucketInfo.notFoundPage;
      deleteRules = bucketInfo.deleteRules;
    }

    @Override
    public Builder name(String name) {
      this.name = checkNotNull(name);
      return this;
    }

    @Override
    Builder generatedId(String generatedId) {
      this.generatedId = generatedId;
      return this;
    }

    @Override
    Builder owner(Acl.Entity owner) {
      this.owner = owner;
      return this;
    }

    @Override
    Builder selfLink(String selfLink) {
      this.selfLink = selfLink;
      return this;
    }

    @Override
    public Builder versioningEnabled(Boolean enable) {
      this.versioningEnabled = firstNonNull(enable, Data.nullOf(Boolean.class));
      return this;
    }

    @Override
    public Builder indexPage(String indexPage) {
      this.indexPage = indexPage;
      return this;
    }

    @Override
    public Builder notFoundPage(String notFoundPage) {
      this.notFoundPage = notFoundPage;
      return this;
    }

    @Override
    public Builder deleteRules(Iterable rules) {
      this.deleteRules = rules != null ? ImmutableList.copyOf(rules) : null;
      return this;
    }

    @Override
    public Builder storageClass(String storageClass) {
      this.storageClass = storageClass;
      return this;
    }

    @Override
    public Builder location(String location) {
      this.location = location;
      return this;
    }

    @Override
    Builder etag(String etag) {
      this.etag = etag;
      return this;
    }

    @Override
    Builder createTime(Long createTime) {
      this.createTime = createTime;
      return this;
    }

    @Override
    Builder metageneration(Long metageneration) {
      this.metageneration = metageneration;
      return this;
    }

    @Override
    public Builder cors(Iterable cors) {
      this.cors = cors != null ? ImmutableList.copyOf(cors) : null;
      return this;
    }

    @Override
    public Builder acl(Iterable acl) {
      this.acl = acl != null ? ImmutableList.copyOf(acl) : null;
      return this;
    }

    @Override
    public Builder defaultAcl(Iterable acl) {
      this.defaultAcl = acl != null ? ImmutableList.copyOf(acl) : null;
      return this;
    }

    @Override
    public BucketInfo build() {
      checkNotNull(name);
      return new BucketInfo(this);
    }
  }

  BucketInfo(BuilderImpl builder) {
    generatedId = builder.generatedId;
    name = builder.name;
    etag = builder.etag;
    createTime = builder.createTime;
    metageneration = builder.metageneration;
    location = builder.location;
    storageClass = builder.storageClass;
    cors = builder.cors;
    acl = builder.acl;
    defaultAcl = builder.defaultAcl;
    owner = builder.owner;
    selfLink = builder.selfLink;
    versioningEnabled = builder.versioningEnabled;
    indexPage = builder.indexPage;
    notFoundPage = builder.notFoundPage;
    deleteRules = builder.deleteRules;
  }

  /**
   * Returns the service-generated id for the bucket.
   */
  public String generatedId() {
    return generatedId;
  }

  /**
   * Returns the bucket's name.
   */
  public String name() {
    return name;
  }

  /**
   * Returns the bucket's owner. This is always the project team's owner group.
   */
  public Entity owner() {
    return owner;
  }

  /**
   * Returns the URI of this bucket as a string.
   */
  public String selfLink() {
    return selfLink;
  }

  /**
   * Returns {@code true} if versioning is fully enabled for this bucket, {@code false} otherwise.
   */
  public Boolean versioningEnabled() {
    return Data.isNull(versioningEnabled) ? null : versioningEnabled;
  }

  /**
   * Returns bucket's website index page. Behaves as the bucket's directory index where missing
   * blobs are treated as potential directories.
   */
  public String indexPage() {
    return indexPage;
  }

  /**
   * Returns the custom object to return when a requested resource is not found.
   */
  public String notFoundPage() {
    return notFoundPage;
  }

  /**
   * Returns bucket's lifecycle configuration as a number of delete rules.
   *
   * @see Lifecycle Management
   */
  public List deleteRules() {
    return deleteRules;
  }

  /**
   * Returns HTTP 1.1 Entity tag for the bucket.
   *
   * @see Entity Tags
   */
  public String etag() {
    return etag;
  }

  /**
   * Returns the time at which the bucket was created.
   */
  public Long createTime() {
    return createTime;
  }

  /**
   * Returns the metadata generation of this bucket.
   */
  public Long metageneration() {
    return metageneration;
  }

  /**
   * Returns the bucket's location. Data for blobs in the bucket resides in physical storage within
   * this region.
   *
   * @see Bucket Locations
   */
  public String location() {
    return location;
  }

  /**
   * Returns the bucket's storage class. This defines how blobs in the bucket are stored and
   * determines the SLA and the cost of storage.
   *
   * @see Storage Classes
   */
  public String storageClass() {
    return storageClass;
  }

  /**
   * Returns the bucket's Cross-Origin Resource Sharing (CORS) configuration.
   *
   * @see 
   *     Cross-Origin Resource Sharing (CORS)
   */
  public List cors() {
    return cors;
  }

  /**
   * Returns the bucket's access control configuration.
   *
   * @see 
   *     About Access Control Lists
   */
  public List acl() {
    return acl;
  }

  /**
   * Returns the default access control configuration for this bucket's blobs.
   *
   * @see 
   *     About Access Control Lists
   */
  public List defaultAcl() {
    return defaultAcl;
  }

  /**
   * Returns a builder for the current bucket.
   */
  public Builder toBuilder() {
    return new BuilderImpl(this);
  }

  @Override
  public int hashCode() {
    return Objects.hash(name);
  }

  @Override
  public boolean equals(Object obj) {
    return obj == this
        || obj != null
        && obj.getClass().equals(BucketInfo.class)
        && Objects.equals(toPb(), ((BucketInfo) obj).toPb());
  }

  @Override
  public String toString() {
    return MoreObjects.toStringHelper(this)
        .add("name", name())
        .toString();
  }

  com.google.api.services.storage.model.Bucket toPb() {
    com.google.api.services.storage.model.Bucket bucketPb =
        new com.google.api.services.storage.model.Bucket();
    bucketPb.setId(generatedId);
    bucketPb.setName(name);
    bucketPb.setEtag(etag);
    if (createTime != null) {
      bucketPb.setTimeCreated(new DateTime(createTime));
    }
    if (metageneration != null) {
      bucketPb.setMetageneration(metageneration);
    }
    if (location != null) {
      bucketPb.setLocation(location);
    }
    if (storageClass != null) {
      bucketPb.setStorageClass(storageClass);
    }
    if (cors != null) {
      bucketPb.setCors(transform(cors, Cors.TO_PB_FUNCTION));
    }
    if (acl != null) {
      bucketPb.setAcl(transform(acl, new Function() {
        @Override
        public BucketAccessControl apply(Acl acl) {
          return acl.toBucketPb();
        }
      }));
    }
    if (defaultAcl != null) {
      bucketPb.setDefaultObjectAcl(transform(defaultAcl, new Function() {
        @Override
        public ObjectAccessControl apply(Acl acl) {
          return acl.toObjectPb();
        }
      }));
    }
    if (owner != null) {
      bucketPb.setOwner(new Owner().setEntity(owner.toPb()));
    }
    bucketPb.setSelfLink(selfLink);
    if (versioningEnabled != null) {
      bucketPb.setVersioning(new Versioning().setEnabled(versioningEnabled));
    }
    if (indexPage != null || notFoundPage != null) {
      Website website = new Website();
      website.setMainPageSuffix(indexPage);
      website.setNotFoundPage(notFoundPage);
      bucketPb.setWebsite(website);
    }
    if (deleteRules != null) {
      Lifecycle lifecycle = new Lifecycle();
      lifecycle.setRule(transform(deleteRules, new Function() {
        @Override
        public Rule apply(DeleteRule deleteRule) {
          return deleteRule.toPb();
        }
      }));
      bucketPb.setLifecycle(lifecycle);
    }
    return bucketPb;
  }

  /**
   * Creates a {@code BucketInfo} object for the provided bucket name.
   */
  public static BucketInfo of(String name) {
    return builder(name).build();
  }

  /**
   * Returns a {@code BucketInfo} builder where the bucket's name is set to the provided name.
   */
  public static Builder builder(String name) {
    return new BuilderImpl(name);
  }

  static BucketInfo fromPb(com.google.api.services.storage.model.Bucket bucketPb) {
    Builder builder = new BuilderImpl(bucketPb.getName());
    if (bucketPb.getId() != null) {
      builder.generatedId(bucketPb.getId());
    }
    if (bucketPb.getEtag() != null) {
      builder.etag(bucketPb.getEtag());
    }
    if (bucketPb.getMetageneration() != null) {
      builder.metageneration(bucketPb.getMetageneration());
    }
    if (bucketPb.getSelfLink() != null) {
      builder.selfLink(bucketPb.getSelfLink());
    }
    if (bucketPb.getTimeCreated() != null) {
      builder.createTime(bucketPb.getTimeCreated().getValue());
    }
    if (bucketPb.getLocation() != null) {
      builder.location(bucketPb.getLocation());
    }
    if (bucketPb.getStorageClass() != null) {
      builder.storageClass(bucketPb.getStorageClass());
    }
    if (bucketPb.getCors() != null) {
      builder.cors(transform(bucketPb.getCors(), Cors.FROM_PB_FUNCTION));
    }
    if (bucketPb.getAcl() != null) {
      builder.acl(transform(bucketPb.getAcl(), new Function() {
        @Override
        public Acl apply(BucketAccessControl bucketAccessControl) {
          return Acl.fromPb(bucketAccessControl);
        }
      }));
    }
    if (bucketPb.getDefaultObjectAcl() != null) {
      builder.defaultAcl(transform(bucketPb.getDefaultObjectAcl(),
          new Function() {
            @Override
            public Acl apply(ObjectAccessControl objectAccessControl) {
              return Acl.fromPb(objectAccessControl);
            }
          }));
    }
    if (bucketPb.getOwner() != null) {
      builder.owner(Entity.fromPb(bucketPb.getOwner().getEntity()));
    }
    if (bucketPb.getVersioning() != null) {
      builder.versioningEnabled(bucketPb.getVersioning().getEnabled());
    }
    Website website = bucketPb.getWebsite();
    if (website != null) {
      builder.indexPage(website.getMainPageSuffix());
      builder.notFoundPage(website.getNotFoundPage());
    }
    if (bucketPb.getLifecycle() != null && bucketPb.getLifecycle().getRule() != null) {
      builder.deleteRules(transform(bucketPb.getLifecycle().getRule(),
          new Function() {
            @Override
            public DeleteRule apply(Rule rule) {
              return DeleteRule.fromPb(rule);
            }
          }));
    }
    return builder.build();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy