summaryrefslogtreecommitdiff
path: root/src/com/google/gct/idea/appengine/deploy/AppEngineUpdateDialog.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/google/gct/idea/appengine/deploy/AppEngineUpdateDialog.java')
-rw-r--r--src/com/google/gct/idea/appengine/deploy/AppEngineUpdateDialog.java275
1 files changed, 275 insertions, 0 deletions
diff --git a/src/com/google/gct/idea/appengine/deploy/AppEngineUpdateDialog.java b/src/com/google/gct/idea/appengine/deploy/AppEngineUpdateDialog.java
new file mode 100644
index 0000000..bd8c2f1
--- /dev/null
+++ b/src/com/google/gct/idea/appengine/deploy/AppEngineUpdateDialog.java
@@ -0,0 +1,275 @@
+/*
+ * 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.dom.AppEngineWebFileDescription;
+import com.google.gct.idea.appengine.gradle.facet.AppEngineConfigurationProperties;
+import com.google.gct.idea.appengine.gradle.facet.AppEngineGradleFacet;
+import com.google.gct.login.GoogleLogin;
+import com.google.gct.login.IGoogleLoginCompletedCallback;
+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.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.artifacts.ArtifactManager;
+import com.intellij.packaging.elements.PackagingElementResolvingContext;
+import com.intellij.packaging.impl.artifacts.ArtifactUtil;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.ui.SortedComboBoxModel;
+import com.intellij.util.xml.DomElement;
+import com.intellij.util.xml.DomFileElement;
+import com.intellij.util.xml.DomManager;
+import com.intellij.xml.util.XmlStringUtil;
+import org.eclipse.jgit.util.StringUtils;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+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 ModulesCombobox myModuleComboBox;
+ private JTextField myProjectId;
+ private JTextField myVersion;
+ private JPanel myPanel;
+ private List<Module> myDeployableModules;
+ private Project myProject;
+ private Module myInitiallySelectedModule;
+
+ private AppEngineUpdateDialog(Project project, List<Module> deployableModules, 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(285, 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;
+
+ // Login on demand and queue up the dialog to show after a successful login.
+ //if login fails, it already shows an error.
+ if (!GoogleLogin.getInstance().isLoggedIn()) {
+ // log in on demand...
+ GoogleLogin.getInstance().logIn(null, new IGoogleLoginCompletedCallback() {
+ @Override
+ public void onLoginCompleted() {
+ if (GoogleLogin.getInstance().isLoggedIn()) {
+ EventQueue.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ // Success!, lets run the deploy now.
+ AppEngineUpdateDialog dialog = new AppEngineUpdateDialog(project, modules, passedSelectedModule);
+ dialog.show();
+ }
+ });
+ }
+ }
+ });
+ }
+ else {
+ 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() {
+ myProjectId.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;
+ }
+
+ myProjectId.setText(appEngineWebApp.getApplication().getRawText());
+ myVersion.setText(appEngineWebApp.getVersion().getRawText());
+ }
+ }
+
+ @Override
+ protected void doOKAction() {
+ if (getOKAction().isEnabled()) {
+ GoogleLogin login = GoogleLogin.getInstance();
+ Module selectedModule = myModuleComboBox.getSelectedModule();
+ String sdk = "";
+ String war = "";
+ AppEngineGradleFacet facet = AppEngineGradleFacet.getAppEngineFacetByModule(selectedModule);
+ if (facet != null) {
+ AppEngineConfigurationProperties model = facet.getConfiguration().getState();
+ sdk = model.APPENGINE_SDKROOT;
+ war = model.WAR_DIR;
+ }
+
+ String client_secret = login.fetchOAuth2ClientSecret();
+ String client_id = login.fetchOAuth2ClientId();
+ String refresh_token = login.fetchOAuth2RefreshToken();
+
+ if (StringUtils.isEmptyOrNull(client_secret) ||
+ StringUtils.isEmptyOrNull(client_id) ||
+ StringUtils.isEmptyOrNull(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.");
+ Messages.showErrorDialog(this.getPeer().getOwner(), "Login credentials are not valid.", "Login");
+ return;
+ }
+
+ // These should not fail as they are a part of the dialog validation.
+ if (Strings.isNullOrEmpty(sdk) ||
+ Strings.isNullOrEmpty(war) ||
+ Strings.isNullOrEmpty(myProjectId.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, myProjectId.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(myProjectId.getText())) {
+ return new ValidationInfo("Please enter a Project ID.");
+ }
+
+ return null;
+ }
+
+}