io.uploader.drive.DriveUploader.java Source code

Java tutorial

Introduction

Here is the source code for io.uploader.drive.DriveUploader.java

Source

/*
 * Copyright 2014 Loic Merckel
 * Copyright (c) 2013 Google Inc.
 * 
 * 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.
 */

/*
* 
* The original version of this file (i.e., the one that is copyrighted 2013 Google Inc.) 
* can  be found here:
*
*  https://code.google.com/p/google-api-java-client/source/browse/drive-cmdline-sample/src/main/java/com/google/api/services/samples/drive/cmdline/DriveSample.java?repo=samples
*  
*/

package io.uploader.drive;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import io.uploader.drive.auth.DriveUploaderAuthorizationCodeInstalledApp;
import io.uploader.drive.auth.webbrowser.Browser;
import io.uploader.drive.auth.webbrowser.SimpleBrowserImpl;
import io.uploader.drive.config.Configuration;
import io.uploader.drive.config.auth.AuthenticationSettingsImpl;
import io.uploader.drive.gui.MainWindow;
import io.uploader.drive.gui.dlg.MessageDialogs;
import io.uploader.drive.gui.dlg.MessageDialogs.Response;
import io.uploader.drive.util.Callback;
import io.uploader.drive.util.ObserverService;

import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import org.apache.commons.configuration.ConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.VerificationCodeReceiver;
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.http.HttpTransport;
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.common.base.Preconditions;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.EventHandler;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

public class DriveUploader extends Application {

    private static final Logger logger = LoggerFactory.getLogger(DriveUploader.class);

    private static final boolean activateNativeLookAndFeelForMacOs = true;

    public static boolean isMacOsX() {
        if (!activateNativeLookAndFeelForMacOs) {
            return false;
        }
        String os = System.getProperty("os.name");
        return (os != null && os.toLowerCase().contains("mac"));
    }

    /**
     * Be sure to specify the name of your application. If the application name
     * is {@code null} or blank, the application will log a warning. Suggested
     * format is "MyCompany-ProductName/1.0".
     */
    private static final String APPLICATION_NAME = Configuration.INSTANCE.getAppName();

    /** Directory to store user credentials. */
    private static final java.io.File DATA_STORE_DIR = new java.io.File(
            Configuration.INSTANCE.getDataStoreDirectory());

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

    /** Global instance of the JSON factory. */
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

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

    private static Drive client;

    private static final AppEvent appEvent = new AppEvent();

    public static void main(String[] args) {

        if (isMacOsX()) {
            System.setProperty("apple.laf.useScreenMenuBar", "true");
            System.setProperty("com.apple.mrj.application.apple.menu.about.name",
                    Configuration.INSTANCE.getAppName());
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
                    | UnsupportedLookAndFeelException e) {
                logger.error("Error occurred while initializing the UI", e);
            }
        }

        Platform.setImplicitExit(false);

        // load the settings
        String settingsFile = "driveuploader-settings.xml";
        if (!new java.io.File(settingsFile).exists())
            settingsFile = null;
        try {
            Configuration.INSTANCE.load(settingsFile);
        } catch (ConfigurationException e) {
            logger.error("Error occurred while initializing the configuration", e);
        }

        try {
            // initialize the transport
            httpTransport = GoogleNetHttpTransport.newTrustedTransport();

            // initialize the data store factory
            dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);

        } catch (IOException e) {
            logger.error("Error occurred while initializing the drive", e);
            Platform.exit();
        } catch (Throwable t) {
            logger.error("Error occurred while initializing the drive", t);
            Platform.exit();
        }

        launch(args);
    }

    private static void authorize(final Browser browser, final Callback<Credential> callback) {
        try {
            // load client secrets
            GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY,
                    new InputStreamReader(AuthenticationSettingsImpl.getClientSecretJson()));
            if (clientSecrets.getDetails().getClientId().startsWith("Enter")
                    || clientSecrets.getDetails().getClientSecret().startsWith("Enter ")) {
                System.out.println(
                        "Overwrite the src/main/resources/client_secrets.json file with the client secrets file "
                                + "you downloaded from the Quickstart tool or manually enter your Client ID and Secret "
                                + "from https://code.google.com/apis/console/?api=drive#project:94720202188 "
                                + "into src/main/resources/client_secrets.json");
                System.exit(1);
            }

            Configuration.INSTANCE.setAuthenticationSettingsImpl(new AuthenticationSettingsImpl(clientSecrets));

            // Set up authorization code flow.
            Set<String> scopes = new HashSet<String>();
            scopes.add(DriveScopes.DRIVE);
            // old api for large file support (where upload takes more than one hour)
            scopes.add("https://docs.google.com/feeds");

            final GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(httpTransport,
                    JSON_FACTORY, clientSecrets, scopes).setDataStoreFactory(dataStoreFactory)
                            .setAccessType("offline").setApprovalPrompt("force").build();

            // authorize
            final VerificationCodeReceiver receiver = new LocalServerReceiver();

            ObserverService<Credential> service = new ObserverService<Credential>() {

                private volatile DriveUploaderAuthorizationCodeInstalledApp driveUploaderAuthorizationCodeInstalledApp = null;

                @Override
                protected Task<Credential> createTask() {
                    Task<Credential> task = new Task<Credential>() {

                        @Override
                        protected Credential call() throws Exception {

                            driveUploaderAuthorizationCodeInstalledApp = new DriveUploaderAuthorizationCodeInstalledApp(
                                    flow, receiver, browser);
                            Credential credential = driveUploaderAuthorizationCodeInstalledApp.authorize("user");
                            return credential;
                        }
                    };
                    return task;
                }
            };

            service.setOnSucceeded(new EventHandler<WorkerStateEvent>() {

                @Override
                public void handle(WorkerStateEvent t) {
                    logger.info("Login success");
                    Credential ret = (Credential) t.getSource().getValue();
                    callback.onSuccess(ret);
                }
            });

            appEvent.addObserver(service);
            service.start();

        } catch (Exception e) {
            callback.onFailure(e);
        }
    }

    @Override
    public void stop() throws Exception {
        logger.info("Stop!");
        super.stop();
    }

    @Override
    public void start(final Stage stage) throws Exception {

        Preconditions.checkNotNull(stage);

        try {
            stage.onCloseRequestProperty().set(new EventHandler<WindowEvent>() {
                public void handle(WindowEvent e) {
                    logger.info("Close request");

                    if (Response.NO == MessageDialogs.showConfirmDialog(stage,
                            "Are you sure you want to close the application?", "Confirmation")) {
                        e.consume();
                        return;
                    }
                    appEvent.exit();
                    Platform.exit();

                    // TODO: 
                    // Investigate why when we shutdown the authentication service
                    // before the end of the process, the app hangs after closing the main window...
                    // http://stackoverflow.com/questions/4425350/how-to-terminate-a-thread-blocking-on-socket-io-operation-instantly
                    //if (client == null) {
                    System.exit(0);
                    //}
                }
            });

            final List<Integer> logoSizeList = Arrays.asList(16, 32, 64, 128, 256, 512);
            final String logoNameBase = "DriveUploader";
            final String logoNameExt = ".png";
            for (Integer size : logoSizeList) {
                StringBuilder logoName = new StringBuilder();
                logoName.append(logoNameBase);
                logoName.append(size);
                logoName.append(logoNameExt);
                Image logo = new Image(getClass().getResourceAsStream("/images/" + logoName));
                stage.getIcons().add(logo);
            }

            //final Browser browser = new SimpleBrowser (new Stage (), null) ;
            final Browser browser = new SimpleBrowserImpl(stage, null);
            authorize(browser, new Callback<Credential>() {

                @Override
                public void onSuccess(Credential result) {
                    logger.info("Received credential");

                    client = new Drive.Builder(httpTransport, JSON_FACTORY, result)
                            .setApplicationName(APPLICATION_NAME).build();

                    Configuration.INSTANCE.setCredential(result);

                    //browser.close () ;
                    try {
                        MainWindow mainWindow = new MainWindow(client, stage, appEvent, Configuration.INSTANCE);
                        mainWindow.show();
                    } catch (IOException e) {
                        logger.error("Error occurred while creating the main window", e);
                        Platform.exit();
                    }
                }

                @Override
                public void onFailure(Throwable cause) {
                    logger.error("Error occurred while authenticating", cause);
                    Platform.exit();
                }
            });
        } catch (Exception e) {
            Platform.exit();
            throw e;
        }
    }
}