de.pfabulist.googledrive.GoogleDriveElsewhere.java Source code

Java tutorial

Introduction

Here is the source code for de.pfabulist.googledrive.GoogleDriveElsewhere.java

Source

package de.pfabulist.googledrive;

import com.esotericsoftware.minlog.Log;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.googleapis.media.MediaHttpDownloader;
import com.google.api.client.googleapis.media.MediaHttpUploader;
import com.google.api.client.http.AbstractInputStreamContent;
import com.google.api.client.http.GenericUrl;
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.client.util.store.DataStoreFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import com.google.api.services.samples.drive.cmdline.FileDownloadProgressListener;
import com.google.api.services.samples.drive.cmdline.FileUploadProgressListener;
import de.pfabulist.elsewhere.Elsewhere;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.UUID;

import static de.pfabulist.unchecked.Unchecked.u;

/**
 * ** BEGIN LICENSE BLOCK *****
 * BSD License (2 clause)
 * Copyright (c) 2006 - 2015, Stephan Pfab
 * All rights reserved.
 * <p>
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * <p>
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Stephan Pfab BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * **** END LICENSE BLOCK ****
 */

public class GoogleDriveElsewhere implements Elsewhere {

    private static final String APPLICATION_NAME = "google-drive-elsewhere/0.1";

    /**
     * Global instance of the JSON factory.
     */
    private final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
    /**
     * Global Drive API client.
     */
    private final Drive drive;

    /**
     * Global instance of the HTTP transport.
     */
    private final HttpTransport httpTransport;

    /**
     * Global instance of the {@link DataStoreFactory}. The best practice is to make it a single
     * globally shared instance across your application.
     */
    private final FileDataStoreFactory dataStoreFactory;

    private final Credential credential;

    public GoogleDriveElsewhere(Path credentialStore) {
        try {
            this.httpTransport = GoogleNetHttpTransport.newTrustedTransport();
            dataStoreFactory = new FileDataStoreFactory(credentialStore.toFile());
        } catch (GeneralSecurityException | IOException e) {
            throw u(e);
        }

        try {
            credential = authorize(GoogleDriveElsewhere.class.getResourceAsStream("/client_secrets.json"));
        } catch (Exception e) {
            throw u(e);
        }

        drive = new Drive.Builder(httpTransport, JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME)
                .build();

    }

    @Override
    public SaveResult put(String id, long version, InputStream is, long length) {
        File fileMetadata = new File();
        fileMetadata.setTitle("" + version);

        AbstractInputStreamContent mediaContent = new InputStreamContent(null /* "image/jpeg" */, is);

        Drive.Files.Insert insert = null;
        try {
            insert = drive.files().insert(fileMetadata, mediaContent);
        } catch (IOException e) {
            throw u(e);
        }
        MediaHttpUploader uploader = insert.getMediaHttpUploader();
        uploader.setDirectUploadEnabled(true); //useDirectUpload );
        uploader.setProgressListener(new FileUploadProgressListener());

        try {
            File res = insert.execute();
            return SaveResult.immediate(res.getId());
        } catch (IOException e) {
            return SaveResult.notImmediate(null);
        }
    }

    @Override
    public void get(String id, long version, OutputStream os) {

        try {
            File metadata = drive.files().get(id).execute();
            if (!metadata.getTitle().equals("" + version)) {
                Log.info("no such version");
                return;
            }
            MediaHttpDownloader downloader = new MediaHttpDownloader(httpTransport,
                    drive.getRequestFactory().getInitializer());
            downloader.setDirectDownloadEnabled(true); // todo false for large files ?
            downloader.setProgressListener(new FileDownloadProgressListener());
            downloader.download(new GenericUrl(metadata.getDownloadUrl()), os);
        } catch (IOException e) {
            throw u(e);
        }
    }

    @Override
    public boolean remove(String id) {

        try {
            Drive.Files.Delete delete = drive.files().delete(id);
            delete.execute();
            return true;
        } catch (IOException e) {
            return false;
        }
    }

    @Override
    public boolean exists(String id, long version) {
        try {
            Drive.Files.Get get = drive.files().get(id);
            if (get == null) {
                return false;
            }
            File metadata = get.execute();

            return metadata.getTitle().equals("" + version);

        } catch (IOException e) {
            return false; // offline ?
        }

    }

    @Override
    public long getLastVersion(String id) {
        try {
            Drive.Files.Get get = drive.files().get(id);
            if (get == null) {
                throw new NoSuchFileException(id);
            }
            File metadata = get.execute();

            return Long.getLong(metadata.getTitle());

        } catch (IOException e) {
            throw u(e);
        }
    }

    @Override
    public String getType() {
        return "google-drive";
    }

    @Override
    public UUID getUUID() {
        return null;
    }

    @Override
    public boolean offline() {
        return false;
    }

    @Override
    public long getTotalSpace() {
        return Long.MAX_VALUE;
    }

    @Override
    public long getUsableSpace() {
        return Long.MAX_VALUE;
    }

    public Drive getDrive() {
        return drive;
    }

    public HttpTransport getHttpTransport() {
        return httpTransport;
    }

    /**
     * Authorizes the installed application to access user's protected data.
     */
    private Credential authorize(InputStream jsonIS) throws Exception {
        // load client secrets
        GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(jsonIS));
        if (clientSecrets.getDetails().getClientId().startsWith("Enter")
                || clientSecrets.getDetails().getClientSecret().startsWith("Enter ")) {
            System.out.println("Enter Client ID and Secret from https://code.google.com/apis/console/?api=drive "
                    + "into drive-cmdline-sample/src/main/resources/client_secrets.json");
            System.exit(1);
        }
        // set up authorization code flow
        GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(httpTransport, JSON_FACTORY,
                clientSecrets, Collections.singleton(DriveScopes.DRIVE_FILE)).setDataStoreFactory(dataStoreFactory)
                        .build();
        // authorize
        return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
    }

}