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

com.github.wuic.nut.gstorage.GStorageNutDao Maven / Gradle / Ivy

/*
 * "Copyright (c) 2014   Capgemini Technology Services (hereinafter "Capgemini")
 *
 * License/Terms of Use
 * Permission is hereby granted, free of charge and for the term of intellectual
 * property rights on the Software, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to use, copy, modify and
 * propagate free of charge, anywhere in the world, all or part of the Software
 * subject to the following mandatory conditions:
 *
 * -   The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * Any failure to comply with the above shall automatically terminate the license
 * and be construed as a breach of these Terms of Use causing significant harm to
 * Capgemini.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, PEACEFUL ENJOYMENT,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Except as contained in this notice, the name of Capgemini shall not be used in
 * advertising or otherwise to promote the use or other dealings in this Software
 * without prior written authorization from Capgemini.
 *
 * These Terms of Use are subject to French law.
 *
 * IMPORTANT NOTICE: The WUIC software implements software components governed by
 * open source software licenses (BSD and Apache) of which CAPGEMINI is not the
 * author or the editor. The rights granted on the said software components are
 * governed by the specific terms and conditions specified by Apache 2.0 and BSD
 * licenses."
 */


package com.github.wuic.nut.gstorage;

import com.github.wuic.NutType;
import com.github.wuic.exception.wrapper.StreamException;
import com.github.wuic.nut.AbstractNutDao;
import com.github.wuic.nut.Nut;
import com.github.wuic.nut.core.ByteArrayNut;
import com.github.wuic.util.IOUtils;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.javanet.NetHttpTransport;
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.Objects;
import com.google.api.services.storage.model.StorageObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 

* A {@link com.github.wuic.nut.NutDao} implementation for Google Cloud Storage accesses. *

* * @author Corentin AZELART * @version 1.4 * @since 0.3.3 */ public class GStorageNutDao extends AbstractNutDao { /** * Logger. */ private final Logger log = LoggerFactory.getLogger(this.getClass()); /** * The client connected to the Google Cloud Storage. */ private Storage storage; /** * Bucket name. */ private String bucketName; /** * Google credential for OAuth2. */ private GoogleCredential googleCredential; /** * Private key path location. */ private String privateKeyFile; /** * Google service account id. */ private String serviceAccountId; /** *

* Builds a new instance. *

* * @param bucket the bucket name * @param accountId the Google user access ID * @param path the root path * @param basePathAsSysProp {@code true} if the base path is a system property * @param pollingInterleave the interleave for polling operations in seconds (-1 to deactivate) * @param proxyUris the proxies URIs in front of the nut * @param keyFile the private key path location * @param contentBasedVersionNumber {@code true} if version number is computed from nut content, {@code false} if based on timestamp */ public GStorageNutDao(final String path, final Boolean basePathAsSysProp, final String[] proxyUris, final Integer pollingInterleave, final String bucket, final String accountId, final String keyFile, final Boolean contentBasedVersionNumber) { super(path, basePathAsSysProp, proxyUris, pollingInterleave, contentBasedVersionNumber); bucketName = bucket; privateKeyFile = keyFile; serviceAccountId = accountId; } /** * Check if OAuth token is always alive. * @throws IOException if token can't be refresh */ private void checkGoogleOAuth2() throws IOException { // Check if we have build Google credential if (googleCredential == null) { this.buildOAuth2(); } // Check token if (googleCredential.getExpiresInSeconds() == null || googleCredential.getExpirationTimeMilliseconds() == 0) { googleCredential.refreshToken(); } } /** * Build OAuth 2 Google Credential. * @throws IOException if we have a problem to build Google credential */ private void buildOAuth2() throws IOException { final NetHttpTransport netHttpTransport = new NetHttpTransport(); final JsonFactory jsonFactory = new JacksonFactory(); try { // Configure Google credential final GoogleCredential.Builder builder = new GoogleCredential.Builder(); builder.setTransport(netHttpTransport); builder.setJsonFactory(jsonFactory); builder.setServiceAccountId(serviceAccountId); // TODO : raise exception if private key not found final String keyPath = IOUtils.mergePath("/", privateKeyFile); builder.setServiceAccountPrivateKeyFromP12File(new File(getClass().getResource(keyPath).getFile())); builder.setServiceAccountScopes(Arrays.asList(StorageScopes.DEVSTORAGE_FULL_CONTROL)); // Build Google credential googleCredential = builder.build(); // Build Google Storage connector storage = new Storage.Builder(netHttpTransport, jsonFactory, googleCredential).setApplicationName("Wuic").build(); } catch (GeneralSecurityException gse) { // Security exception (local check) throw new IOException("Can't build Google credential on bucket " + bucketName + " for key : " + getBasePath(), gse); } catch (IOException ioe) { // Private key path not found throw new IOException("Can't build Google credential on bucket " + bucketName + " for key : " + getBasePath() + " check your private key file", ioe); } } /** * {@inheritDoc} */ @Override public List listNutsPaths(final String pattern) throws StreamException { try { // Check if we are ready to read on Google Storage this.checkGoogleOAuth2(); return recursiveSearch(getBasePath(), Pattern.compile(pattern)); } catch (IOException ioe) { throw new StreamException(ioe); } } /** *

* Searches recursively in the given path any files matching the given entry. *

* * @param path the path * @param pattern the pattern to match * @return the list of matching files * @throws StreamException if the client can't move to a directory or any I/O error occurs */ private List recursiveSearch(final String path, final Pattern pattern) throws StreamException { Objects objectListing; try { objectListing = storage.objects().list(bucketName).execute(); } catch (IOException ioe) { throw new StreamException(new IOException(String.format("Can't get Google Storage Object on bucket %s for nut key : %s", bucketName, path), ioe)); } final List retval = new ArrayList(); for (final StorageObject storageObject : objectListing.getItems()) { // Ignore directories, all nuts are in the listing if (!storageObject.getName().endsWith("/")) { final Matcher matcher = pattern.matcher(storageObject.getName()); if (matcher.find()) { retval.add(storageObject.getName()); } } } return retval; } /** * {@inheritDoc} */ @Override public Nut accessFor(final String realPath, final NutType type) throws StreamException { try { // Try to get a Storage object final Storage.Objects.Get storageObject = storage.objects().get(bucketName, realPath); // Download path final ByteArrayOutputStream baos = new ByteArrayOutputStream(IOUtils.WUIC_BUFFER_LEN); storageObject.executeMediaAndDownloadTo(baos); // Create nut return new ByteArrayNut(baos.toByteArray(), realPath, type, getVersionNumber(realPath)); } catch (IOException ioe) { throw new StreamException(ioe); } } /** * {@inheritDoc} */ @Override protected Long getLastUpdateTimestampFor(final String path) throws StreamException { log.info("Polling GStorage nut '{}'", path); try { final String response = storage.objects().get(bucketName, path).execute().getMd5Hash(); log.info("Last MD5 response : {}", response); return storage.objects().get(bucketName, path).execute().getGeneration(); } catch (final IOException ioe) { throw new StreamException(ioe); } } /** * {@inheritDoc} */ @Override protected void finalize() throws Throwable { try { log.debug("Release Google credential ticket..."); // For security, we force Google credential expiration to now. googleCredential.setExpirationTimeMilliseconds(new Long(0)); } finally { super.finalize(); } } /** * {@inheritDoc} */ @Override public String toString() { return String.format("%s with base path %s", getClass().getName(), getBasePath()); } /** * {@inheritDoc} */ @Override public InputStream newInputStream(final String path) throws StreamException { try { // Try to get a Storage object return storage.objects().get(bucketName, path).executeMediaAsInputStream(); } catch (IOException ioe) { throw new StreamException(ioe); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy