package com.ciandt.techgallery.utils;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.InputStreamContent;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.storage.Storage;
import com.google.api.services.storage.StorageScopes;
import com.google.api.services.storage.model.Bucket;
import com.google.api.services.storage.model.BucketAccessControl;
import com.google.api.services.storage.model.ObjectAccessControl;
import com.google.api.services.storage.model.StorageObject;
import com.google.appengine.api.utils.SystemProperty;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.logging.Logger;
/**
* Handler to connect with the Storage.
*
* @author <a href="mailto:joaom@ciandt.com"> João Felipe de Medeiros Moreira </a>
* @since 15/10/2015
*
*/
public class StorageHandler {
/*
* Constants --------------------------------------------
*/
private static final Logger logger = Logger.getLogger(StorageHandler.class.getName());
private static final String ALL_USERS = "allUsers";
private static final String READER = "READER";
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final String APPLICATION_NAME = SystemProperty.applicationId.get();
private static final String LOCATION = "US";
private static final String BUCKET_NAME = SystemProperty.applicationId.get() + "-";
private static final String FULL = "full";
private static final String PROJECT_EDITORS = "project-editors-";
private static final String WRITER = "WRITER";
/*
* Attributes --------------------------------------------
*/
private static StorageHandler instance;
private static Storage storageService;
/*
* Constructors --------------------------------------------
*/
public StorageHandler() {}
/**
* Singleton method for the DAO.
*
* @author <a href="mailto:joaom@ciandt.com"> João Felipe de Medeiros Moreira </a>
* @since 15/10/2015
*
* @return StorageHandler instance.
*/
public static StorageHandler getInstance() {
if (instance == null) {
instance = new StorageHandler();
}
return instance;
}
/*
* Methods --------------------------------------------
*/
/**
* Method to insert a image into the bucket of the cloud storage.
*
* @author <a href="mailto:joaom@ciandt.com"> João Felipe de Medeiros Moreira </a>
* @since 15/10/2015
*
* @param name of the image.
* @param contentStream to be converted.
*
* @return the media link of the image.
*
* @throws IOException in case a IO problem.
* @throws GeneralSecurityException in case a security problem.
*/
public static String saveImage(String name, InputStreamContent contentStream)
throws IOException, GeneralSecurityException {
logger.finest("###### Saving a image");
StorageObject objectMetadata = new StorageObject()
// Set the destination object name
.setName(name)
// Set the access control list to publicly read-only
.setAcl(Arrays.asList(new ObjectAccessControl().setEntity(ALL_USERS).setRole(READER)));
Storage client = getService();
String bucketName = getBucket().getName();
Storage.Objects.Insert insertRequest =
client.objects().insert(bucketName, objectMetadata, contentStream);
return insertRequest.execute().getMediaLink();
}
/**
* Method to get the bucket of the application version.
*
* @author <a href="mailto:joaom@ciandt.com"> João Felipe de Medeiros Moreira </a>
* @since 13/10/2015
*
* @return the bucket of this application version.
*
* @throws IOException in case a IO problem.
* @throws GeneralSecurityException in case a security problem.
*/
private static Bucket getBucket() throws IOException, GeneralSecurityException {
logger.finest("###### Getting the bucket");
String applicationVersion = TechGalleryUtil.getApplicationVersion();
Bucket createdBucket = getExistingBucket(applicationVersion);
if (createdBucket == null) {
return createBucket(applicationVersion);
}
return createdBucket;
}
/**
* Method to create a new bucket on cloud storage.
*
* @author <a href="mailto:joaom@ciandt.com"> João Felipe de Medeiros Moreira </a>
* @since 13/10/2015
*
* @param applicationVersion to create the bucket.
*
* @return the bucket created.
*
* @throws IOException in case a IO problem.
* @throws GeneralSecurityException in case a security problem.
*/
private static Bucket createBucket(String applicationVersion)
throws IOException, GeneralSecurityException {
logger.finest("###### Creating the bucket");
Storage client = getService();
Bucket newBucket = new Bucket().setName(BUCKET_NAME + applicationVersion).setLocation(LOCATION)
.setAcl(Arrays.asList(new BucketAccessControl().setEntity(ALL_USERS).setRole(READER),
new BucketAccessControl().setEntity(PROJECT_EDITORS + TechGalleryUtil.getAppId())
.setRole(WRITER)));
Storage.Buckets.Insert bucketToCreate = client.buckets().insert(APPLICATION_NAME, newBucket);
return bucketToCreate.execute();
}
/**
* Method to get a bucket that already exists.
*
* @author <a href="mailto:joaom@ciandt.com"> João Felipe de Medeiros Moreira </a>
* @since 13/10/2015
*
* @param bucketName to be founded.
*
* @return the bucket founded.
*
* @throws IOException in case a IO problem.
* @throws GeneralSecurityException in case a security problem.
*/
public static Bucket getExistingBucket(String bucketName)
throws IOException, GeneralSecurityException {
logger.finest("###### Searching a bucket");
Storage client = getService();
Storage.Buckets.Get bucketRequest = client.buckets().get(BUCKET_NAME + bucketName);
// Fetch the full set of the bucket's properties (e.g. include the ACLs in the response)
bucketRequest.setProjection(FULL);
try {
return bucketRequest.execute();
} catch (Exception e) {
// If the bucket doesn't exists, return null to create a new one.
return null;
}
}
/**
* Method to create the service or get the service if is already created.
*
* @author <a href="mailto:joaom@ciandt.com"> João Felipe de Medeiros Moreira </a>
* @since 13/10/2015
*
* @return the Storage service already created.
*
* @throws IOException in case a IO problem.
* @throws GeneralSecurityException in case a security problem.
*/
private static Storage getService() throws IOException, GeneralSecurityException {
logger.finest("###### Getting the storage service");
if (null == storageService) {
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential credential = GoogleCredential.getApplicationDefault();
// Depending on the environment that provides the default credentials (e.g. Compute Engine,
// App Engine), the credentials may require us to specify the scopes we need explicitly.
// Check for this case, and inject the Cloud Storage scope if required.
if (credential.createScopedRequired()) {
credential = credential.createScoped(StorageScopes.all());
}
storageService = new Storage.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME).build();
}
return storageService;
}
}