com.google.gct.idea.appengine.deploy.AppEngineUpdater.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gct.idea.appengine.deploy.AppEngineUpdater.java

Source

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * 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.gct.idea.appengine.deploy;

import com.google.common.base.Strings;
import com.google.gct.idea.appengine.gradle.GradleInvoker;
import com.google.gct.idea.appengine.sdk.AppEngineSdk;
import com.google.gct.idea.stats.UsageTracker;
import com.google.gct.idea.util.GctTracking;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionManager;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.CommandLineBuilder;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.configurations.ParametersList;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.filters.TextConsoleBuilderFactory;
import com.intellij.execution.process.*;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.ui.RunnerLayoutUi;
import com.intellij.execution.ui.actions.CloseAction;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemBeforeRunTask;
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
import com.intellij.openapi.externalSystem.task.TaskCallback;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.KeyValue;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.net.HttpConfigurable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.awt.*;
import java.util.List;

/**
 * Compiles and deploys a module to AppEngine using AppCfg.
 *
 * @author benwu
 */
class AppEngineUpdater {
    private static final Logger LOG = Logger.getInstance("#com.google.gct.idea.appengine.deploy.AppEngineUpdater");
    private final Project myProject;
    private final Module myModule;
    private final String myExplodedWarPath;
    private final String mySdkPath;
    private final String myClientSecret;
    private final String myClientId;
    private final String myRefreshToken;
    private final String myVersion;
    private final String myAppEngineProject;

    AppEngineUpdater(Project project, Module module, String sdkPath, String explodedWarPath,
            String appEngineProject, String version, String clientSecret, String clientId, String refreshToken) {
        myProject = project;
        myModule = module;
        mySdkPath = sdkPath;
        myExplodedWarPath = explodedWarPath;
        myClientSecret = clientSecret;
        myClientId = clientId;
        myRefreshToken = refreshToken;
        myVersion = version;
        myAppEngineProject = appEngineProject;
    }

    /**
     * Starts the compile and upload async process.
     */
    void startUploading() {
        FileDocumentManager.getInstance().saveAllDocuments();
        ProgressManager.getInstance()
                .run(new Task.Backgroundable(myModule.getProject(), "Deploying application", true, null) {
                    @Override
                    public void run(@NotNull ProgressIndicator indicator) {
                        compileAndUpload();
                    }
                });
    }

    private void compileAndUpload() {
        GradleInvoker.executeTask(":assemble", myModule, new TaskCallback() {
            @Override
            public void onSuccess() {
                ApplicationManager.getApplication().invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        startUploadingProcess();
                    }
                });
            }

            @Override
            public void onFailure() {
                LOG.warn("unable to upload the module because it did not build successfully.");
            }
        }, ProgressExecutionMode.IN_BACKGROUND_ASYNC);
    }

    private void startUploadingProcess() {
        final Process process;
        final GeneralCommandLine commandLine;

        try {
            JavaParameters parameters = new JavaParameters();
            parameters.configureByModule(myModule, JavaParameters.JDK_ONLY);
            parameters.setMainClass("com.google.appengine.tools.admin.AppCfg");
            AppEngineSdk mySdk = new AppEngineSdk(mySdkPath);
            if (mySdk.getToolsApiJarFile() == null) {
                Messages.showErrorDialog("Cannot start uploading: The tools sdk jar could not be located.",
                        "Error");
                return;
            }
            parameters.getClassPath().add(mySdk.getToolsApiJarFile().getAbsolutePath());

            final List<KeyValue<String, String>> list = HttpConfigurable.getJvmPropertiesList(false, null);
            if (!list.isEmpty()) {
                final ParametersList parametersList = parameters.getVMParametersList();
                for (KeyValue<String, String> value : list) {
                    parametersList.defineProperty(value.getKey(), value.getValue());
                }
            }

            final ParametersList programParameters = parameters.getProgramParametersList();
            programParameters.add("--application=" + myAppEngineProject);
            if (!Strings.isNullOrEmpty(myVersion)) {
                programParameters.add("--version=" + myVersion);
            }
            programParameters.add("--oauth2");
            programParameters.add("--oauth2_client_secret=" + myClientSecret);
            programParameters.add("--oauth2_client_id=" + myClientId);
            programParameters.add("--oauth2_refresh_token=" + myRefreshToken);
            programParameters.add("update");
            programParameters.add(FileUtil.toSystemDependentName(myExplodedWarPath));

            commandLine = CommandLineBuilder.createFromJavaParameters(parameters);

            process = commandLine.createProcess();
        } catch (ExecutionException e) {
            final String message = e.getMessage();
            LOG.error("Cannot start uploading: " + message);

            if (!EventQueue.isDispatchThread()) {
                EventQueue.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        Messages.showErrorDialog("Cannot start uploading: " + message, "Error");
                    }
                });
            } else {
                Messages.showErrorDialog("Cannot start uploading: " + message, "Error");
            }

            return;
        }

        UsageTracker.getInstance().trackEvent(GctTracking.CATEGORY, GctTracking.DEPLOY, "upload.app", null);

        final ProcessHandler processHandler = new FilteredOSProcessHandler(process,
                commandLine.getCommandLineString(), new String[] { myRefreshToken, myClientSecret, myClientId });
        final Executor executor = DefaultRunExecutor.getRunExecutorInstance();
        final ConsoleView console = TextConsoleBuilderFactory.getInstance().createBuilder(myModule.getProject())
                .getConsole();
        final RunnerLayoutUi ui = RunnerLayoutUi.Factory.getInstance(myModule.getProject()).create("Deploy",
                "Deploy to AppEngine", "Deploy Application", myModule.getProject());
        final DefaultActionGroup group = new DefaultActionGroup();
        ui.getOptions().setLeftToolbar(group, ActionPlaces.UNKNOWN);
        ui.addContent(ui.createContent("upload", console.getComponent(), "Deploy Application", null,
                console.getPreferredFocusableComponent()));

        console.attachToProcess(processHandler);
        final RunContentDescriptor contentDescriptor = new RunContentDescriptor(console, processHandler,
                ui.getComponent(), "Deploy to AppEngine");
        group.add(ActionManager.getInstance().getAction(IdeActions.ACTION_STOP_PROGRAM));
        group.add(new CloseAction(executor, contentDescriptor, myModule.getProject()));

        ExecutionManager.getInstance(myModule.getProject()).getContentManager().showRunContent(executor,
                contentDescriptor);
        processHandler.startNotify();
    }

    private class FilteredOSProcessHandler extends OSProcessHandler {
        String[] tokensToFilter;

        FilteredOSProcessHandler(@NotNull final Process process, @Nullable final String commandLine,
                String[] filteredTokens) {
            super(process, commandLine);
            tokensToFilter = filteredTokens;
        }

        @Override
        public void notifyTextAvailable(final String text, final Key outputType) {
            String newText = text;
            if (tokensToFilter != null) {
                for (String token : tokensToFilter) {
                    newText = newText.replace(token, "*****");
                }
            }
            super.notifyTextAvailable(newText, outputType);
        }
    }
}