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

Java tutorial

Introduction

Here is the source code for com.google.gct.idea.appengine.deploy.AppEngineUpdateDialog.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.dom.AppEngineWebApp;
import com.google.gct.idea.appengine.gradle.facet.AppEngineConfigurationProperties;
import com.google.gct.idea.appengine.gradle.facet.AppEngineGradleFacet;
import com.google.gct.idea.elysium.ProjectSelector;
import com.google.gct.login.CredentialedUser;
import com.google.gct.login.GoogleLogin;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ui.configuration.ModulesCombobox;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.ui.SortedComboBoxModel;
import com.intellij.ui.components.JBLabel;
import com.intellij.xml.util.XmlStringUtil;
import git4idea.DialogManager;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

/**
 * AppEngineUpdateDialog shows a dialog allowing the user to select a module and deploy.
 */
public class AppEngineUpdateDialog extends DialogWrapper {
    private static final Logger LOG = Logger.getInstance(AppEngineUpdateDialog.class);
    private static final String DEFAULT_APPID = "myApplicationId";

    private ModulesCombobox myModuleComboBox;
    private ProjectSelector myElysiumProjectId;
    private JTextField myVersion;
    private JPanel myPanel;
    private JBLabel moduleLabel;
    private List<Module> myDeployableModules;
    private Project myProject;
    private Module myInitiallySelectedModule;

    private AppEngineUpdateDialog(Project project, List<Module> deployableModules,
            @Nullable Module selectedModule) {
        super(project, true);
        myDeployableModules = deployableModules;
        myProject = project;
        myInitiallySelectedModule = selectedModule;

        init();
        initValidation();
        setTitle("Deploy to App Engine");
        setOKButtonText("Deploy");

        Window myWindow = getWindow();
        if (myWindow != null) {
            myWindow.setPreferredSize(new Dimension(310, 135));
        }
    }

    /**
     * Shows a dialog to deploy a module to AppEngine.  Will force a login if required
     * If either the login fails or there are no valid modules to upload, it will return  after
     * displaying an error.
     *
     * @param project The project whose modules will be uploaded.
     * @param selectedModule The module selected by default in the deploy dialog.  Can be null.  If null or not a valid app engine module,
     *                       no module will be selected by default.
     */
    static void show(final Project project, Module selectedModule) {

        final java.util.List<Module> modules = new ArrayList<Module>();

        // Filter the module list by whether we can actually deploy them to appengine.
        for (Module module : ModuleManager.getInstance(project).getModules()) {
            AppEngineGradleFacet facet = AppEngineGradleFacet.getAppEngineFacetByModule(module);
            if (facet != null) {
                modules.add(module);
            }
        }

        // Tell the user what he has to do if he has none.
        if (modules.size() == 0) {
            //there are no modules to upload -- or we hit a bug due to gradle sync.
            //TODO do we need to use the mainwindow as owner?
            Messages.showErrorDialog(XmlStringUtil.wrapInHtml(
                    "This project does not contain any App Engine modules. To add an App Engine module for your project, <br> open File > New Module? menu and choose one of App Engine modules."),
                    "Error");
            return;
        }

        if (selectedModule != null && !modules.contains(selectedModule)) {
            selectedModule = null;
        }

        if (selectedModule == null && modules.size() == 1) {
            selectedModule = modules.get(0);
        }

        // To invoke later, we need a final local.
        final Module passedSelectedModule = selectedModule;

        AppEngineUpdateDialog dialog = new AppEngineUpdateDialog(project, modules, passedSelectedModule);
        dialog.show();
    }

    @Nullable
    @Override
    protected JComponent createCenterPanel() {
        @SuppressWarnings("unchecked")
        final SortedComboBoxModel<Module> model = (SortedComboBoxModel<Module>) myModuleComboBox.getModel();
        model.clear();
        model.addAll(myDeployableModules);

        if (myInitiallySelectedModule != null) {
            // Auto select if there is only one item
            model.setSelectedItem(myInitiallySelectedModule);
            populateFields();
        }

        myModuleComboBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                populateFields();
            }
        });
        return myPanel;
    }

    private void populateFields() {
        myElysiumProjectId.setText("");
        myVersion.setText("");

        Module appEngineModule = myModuleComboBox.getSelectedModule();
        if (appEngineModule != null) {
            AppEngineGradleFacet facet = AppEngineGradleFacet.getAppEngineFacetByModule(appEngineModule);
            if (facet == null) {
                Messages.showErrorDialog(this.getPeer().getOwner(),
                        "Could not acquire App Engine module information.", "Deploy");
                return;
            }

            final AppEngineWebApp appEngineWebApp = facet.getAppEngineWebXml();
            if (appEngineWebApp == null) {
                Messages.showErrorDialog(this.getPeer().getOwner(),
                        "Could not locate or parse the appengine-web.xml fle.", "Deploy");
                return;
            }

            String newProjectId = appEngineWebApp.getApplication().getRawText();
            if (!DEFAULT_APPID.equals(newProjectId)) {
                myElysiumProjectId.setText(newProjectId);
            }
            myVersion.setText(appEngineWebApp.getVersion().getRawText());
        }
    }

    @Override
    protected void doOKAction() {
        if (getOKAction().isEnabled()) {
            Module selectedModule = myModuleComboBox.getSelectedModule();
            String sdk = "";
            String war = "";
            AppEngineGradleFacet facet = AppEngineGradleFacet.getAppEngineFacetByModule(selectedModule);
            if (facet != null) {
                AppEngineConfigurationProperties model = facet.getConfiguration().getState();
                if (model != null) {
                    sdk = model.APPENGINE_SDKROOT;
                    war = model.WAR_DIR;
                }
            }

            String client_secret = null;
            String client_id = null;
            String refresh_token = null;

            CredentialedUser selectedUser = myElysiumProjectId.getSelectedUser();
            if (selectedUser == null) {
                selectedUser = GoogleLogin.getInstance().getActiveUser();
                // Ask the user if he wants to continue using the active user credentials.
                if (selectedUser != null) {
                    if (Messages.showYesNoDialog(this.getPeer().getOwner(),
                            "The Project ID you entered could not be found.  Do you want to deploy anyway using "
                                    + GoogleLogin.getInstance().getActiveUser().getEmail() + " for credentials?",
                            "Deploy", Messages.getQuestionIcon()) != Messages.YES) {
                        return;
                    }
                } else {
                    // This should not happen as its validated.
                    Messages.showErrorDialog(this.getPeer().getOwner(), "You need to be logged in to deploy.",
                            "Login");
                    return;
                }
            }

            if (selectedUser != null) {
                client_secret = selectedUser.getGoogleLoginState().fetchOAuth2ClientSecret();
                client_id = selectedUser.getGoogleLoginState().fetchOAuth2ClientId();
                refresh_token = selectedUser.getGoogleLoginState().fetchOAuth2RefreshToken();
            }

            if (Strings.isNullOrEmpty(client_secret) || Strings.isNullOrEmpty(client_id)
                    || Strings.isNullOrEmpty(refresh_token)) {
                // The login is somehow invalid, bail -- this shouldn't happen.
                LOG.error("StartUploading while logged in, but it doesn't have full credentials.");
                if (Strings.isNullOrEmpty(client_secret)) {
                    LOG.error("(null) client_secret");
                }
                if (Strings.isNullOrEmpty(client_id)) {
                    LOG.error("(null) client_id");
                }
                if (Strings.isNullOrEmpty(refresh_token)) {
                    LOG.error("(null) refresh_token");
                }
                Messages.showErrorDialog(this.getPeer().getOwner(),
                        "The project ID is not a valid Google Console Developer Project.", "Login");
                return;
            }

            // These should not fail as they are a part of the dialog validation.
            if (Strings.isNullOrEmpty(sdk) || Strings.isNullOrEmpty(war)
                    || Strings.isNullOrEmpty(myElysiumProjectId.getText()) || selectedModule == null) {
                Messages.showErrorDialog(this.getPeer().getOwner(),
                        "Could not deploy due to missing information (sdk/war/projectid).", "Deploy");
                LOG.error("StartUploading was called with bad module/sdk/war");
                return;
            }

            close(OK_EXIT_CODE); // We close before kicking off the update so it doesn't interfere with the output window coming to focus.

            // Kick off the upload.  detailed status will be shown in an output window.
            new AppEngineUpdater(myProject, selectedModule, sdk, war, myElysiumProjectId.getText(),
                    myVersion.getText(), client_secret, client_id, refresh_token).startUploading();
        }
    }

    @Override
    protected ValidationInfo doValidate() {
        // These should not normally occur..
        if (!GoogleLogin.getInstance().isLoggedIn()) {
            return new ValidationInfo("You must be logged in to perform this action.");
        }

        Module module = myModuleComboBox.getSelectedModule();
        if (module == null) {
            return new ValidationInfo("Select a module");
        }

        AppEngineGradleFacet facet = AppEngineGradleFacet.getAppEngineFacetByModule(module);
        if (facet == null) {
            return new ValidationInfo("Could not find App Engine gradle configuration on Module");
        }

        // We'll let AppCfg error if the project is wrong.  The user can see this in the console window.
        // Note that version can be blank to indicate current version.
        if (Strings.isNullOrEmpty(myElysiumProjectId.getText())) {
            return new ValidationInfo("Please enter a Project ID.");
        }

        return null;
    }

}