summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--google-cloud-tools.iml1
-rw-r--r--login/src/com/google/gct/login/ui/GoogleLoginUsersPanel.java25
-rw-r--r--src/META-INF/plugin.xml4
-rw-r--r--src/com/google/gct/idea/appengine/gradle/action/GenerateEndpointAction.java1
-rw-r--r--src/com/google/gct/idea/appengine/gradle/action/InstallClientLibrariesAction.java50
-rw-r--r--src/com/google/gct/idea/settings/ExportSettings.java115
-rw-r--r--src/com/google/gct/idea/settings/ImportSettings.java137
7 files changed, 278 insertions, 55 deletions
diff --git a/google-cloud-tools.iml b/google-cloud-tools.iml
index 9126f4b..6d1ab7c 100644
--- a/google-cloud-tools.iml
+++ b/google-cloud-tools.iml
@@ -54,6 +54,7 @@
</library>
</orderEntry>
<orderEntry type="module" module-name="google-login" />
+ <orderEntry type="module" module-name="bootstrap" />
</component>
</module>
diff --git a/login/src/com/google/gct/login/ui/GoogleLoginUsersPanel.java b/login/src/com/google/gct/login/ui/GoogleLoginUsersPanel.java
index 6536283..a98ce85 100644
--- a/login/src/com/google/gct/login/ui/GoogleLoginUsersPanel.java
+++ b/login/src/com/google/gct/login/ui/GoogleLoginUsersPanel.java
@@ -59,6 +59,7 @@ public class GoogleLoginUsersPanel extends JPanel implements ListSelectionListen
private JButton signOutButton;
private JButton addAccountButton;
private boolean valueChanged = false;
+ private boolean ignoreSelection = false;
public GoogleLoginUsersPanel() {
super(new BorderLayout());
@@ -150,7 +151,7 @@ public class GoogleLoginUsersPanel extends JPanel implements ListSelectionListen
// Active user
boolean inPlayUrl = usersListCellRenderer.inPlayConsoleUrl(mouseEvent.getPoint(), index);
boolean inCloudUrl = usersListCellRenderer.inCloudConsoleUrl(mouseEvent.getPoint(), index);
- if(inPlayUrl || inCloudUrl){
+ if (inPlayUrl || inCloudUrl) {
list.setCursor(new Cursor(Cursor.HAND_CURSOR));
} else {
list.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
@@ -223,6 +224,9 @@ public class GoogleLoginUsersPanel extends JPanel implements ListSelectionListen
//This method is required by ListSelectionListener.
@Override
public void valueChanged(ListSelectionEvent e) {
+ if(ignoreSelection) {
+ return;
+ }
valueChanged = true;
if (e.getValueIsAdjusting() == false) {
if (list.getSelectedIndex() == -1) {
@@ -235,6 +239,19 @@ public class GoogleLoginUsersPanel extends JPanel implements ListSelectionListen
if(!selectedUser.isActiveUser()) {
GoogleLogin.getInstance().setActiveUser(selectedUser.getUserEmail());
}
+
+ // Change order of elements in the list so that the
+ // active user becomes the first element in the list
+ ignoreSelection = true;
+ try {
+ listModel.remove(list.getSelectedIndex());
+ listModel.add(0, selectedUser);
+
+ // Re-select the active user
+ list.setSelectedIndex(0);
+ } finally {
+ ignoreSelection = false;
+ }
}
}
}
@@ -258,6 +275,12 @@ public class GoogleLoginUsersPanel extends JPanel implements ListSelectionListen
if(listModel.getSize() == 0) {
// Add no user panel
listModel.addElement(NoUsersListItem.INSTANCE);
+ } else if ((activeUserIndex != 0) && (activeUserIndex < listModel.getSize())) {
+ // Change order of elements in the list so that the
+ // active user becomes the first element in the list
+ UsersListItem activeUser = (UsersListItem)listModel.remove(activeUserIndex);
+ listModel.add(0, activeUser);
+ activeUserIndex = 0;
}
return activeUserIndex;
diff --git a/src/META-INF/plugin.xml b/src/META-INF/plugin.xml
index c6bc850..ecba450 100644
--- a/src/META-INF/plugin.xml
+++ b/src/META-INF/plugin.xml
@@ -110,10 +110,6 @@
</extensions>
<actions>
- <action id="GoogleCloudTools.InstallClientLibraries"
- class="com.google.gct.idea.appengine.gradle.action.InstallClientLibrariesAction"
- text="Install Client Libraries"
- icon="/icons/cloudEndpoints.png"/>
<action id="GoogleCloudTools.GenerateEndpoint"
class="com.google.gct.idea.appengine.gradle.action.GenerateEndpointAction"
text="Generate Endpoint"
diff --git a/src/com/google/gct/idea/appengine/gradle/action/GenerateEndpointAction.java b/src/com/google/gct/idea/appengine/gradle/action/GenerateEndpointAction.java
index f442f43..7e236b2 100644
--- a/src/com/google/gct/idea/appengine/gradle/action/GenerateEndpointAction.java
+++ b/src/com/google/gct/idea/appengine/gradle/action/GenerateEndpointAction.java
@@ -83,6 +83,7 @@ public class GenerateEndpointAction extends AnAction {
try {
if (!AppEngineUtils.isAppEngineModule(project, module)) {
Messages.showErrorDialog(project, "Endpoints can only be generated for App Engine projects.", ERROR_MESSAGE_TITLE);
+ return;
}
}
catch (FileNotFoundException error) {
diff --git a/src/com/google/gct/idea/appengine/gradle/action/InstallClientLibrariesAction.java b/src/com/google/gct/idea/appengine/gradle/action/InstallClientLibrariesAction.java
deleted file mode 100644
index c90e040..0000000
--- a/src/com/google/gct/idea/appengine/gradle/action/InstallClientLibrariesAction.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.gradle.action;
-
-import com.android.tools.idea.gradle.invoker.GradleInvoker;
-
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
-
-import java.util.Arrays;
-
-/**
- * Action to generate client libraries for an AppEngine endpoints project and copy them to an associated android project
- */
-public class InstallClientLibrariesAction extends AnAction {
-
- private static final String ERROR_MSG_TITLE = "Install Client Libraries";
-
- @Override
- public void actionPerformed(AnActionEvent e) {
- final Project project = e.getProject();
- final Module appEngineModule = e.getData(LangDataKeys.MODULE);
-
- if (project == null || appEngineModule == null) {
- Messages.showErrorDialog(project, "Please select an App Engine module.", ERROR_MSG_TITLE);
- return;
- }
- // TODO : check if module is App Engine Module or not
-
- GradleInvoker.getInstance(project).executeTasks(Arrays.asList(appEngineModule.getName() + ":appengineEndpointsInstallClientLibs"));
- }
-}
diff --git a/src/com/google/gct/idea/settings/ExportSettings.java b/src/com/google/gct/idea/settings/ExportSettings.java
new file mode 100644
index 0000000..6228f25
--- /dev/null
+++ b/src/com/google/gct/idea/settings/ExportSettings.java
@@ -0,0 +1,115 @@
+/*
+ * 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.settings;
+
+import com.intellij.ide.IdeBundle;
+import com.intellij.ide.plugins.IdeaPluginDescriptor;
+import com.intellij.ide.plugins.PluginManager;
+import com.intellij.ide.plugins.PluginManagerCore;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.components.ExportableApplicationComponent;
+import com.intellij.openapi.components.ExportableComponent;
+import com.intellij.openapi.components.ServiceBean;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.io.ZipUtil;
+
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.*;
+import java.util.jar.JarOutputStream;
+
+/**
+ * Provides functionality to export the IDEA settings into a specified jar
+ */
+public class ExportSettings {
+ // TODO: use ImportSettings.SETTINGS_JAR_MARKER after merge
+ public static final String SETTINGS_JAR_MARKER = "IntelliJ IDEA Global Settings";
+
+ public static void doExport(String path) {
+ final Set<ExportableComponent> exportableComponents =
+ new HashSet<ExportableComponent>(Arrays.asList(ApplicationManager.getApplication().getComponents(ExportableApplicationComponent.class)));
+ exportableComponents.addAll(ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent.class));
+
+ if (exportableComponents.isEmpty()) {
+ return;
+ }
+
+ Set<File> exportFiles = new HashSet<File>();
+ for (final ExportableComponent markedComponent : exportableComponents) {
+ ContainerUtil.addAll(exportFiles, markedComponent.getExportFiles());
+ }
+
+ ApplicationManager.getApplication().saveSettings();
+
+ final File saveFile = new File(path);
+ try {
+ if (saveFile.exists()) {
+ final int ret = Messages
+ .showOkCancelDialog(IdeBundle.message("prompt.overwrite.settings.file", FileUtil.toSystemDependentName(saveFile.getPath())),
+ IdeBundle.message("title.file.already.exists"), Messages.getWarningIcon());
+ if (ret != Messages.OK) return;
+ }
+
+ final JarOutputStream output = new JarOutputStream(new FileOutputStream(saveFile));
+ try {
+ final File configPath = new File(PathManager.getConfigPath());
+ final HashSet<String> writtenItemRelativePaths = new HashSet<String>();
+ for (File file : exportFiles) {
+ final String rPath = FileUtil.getRelativePath(configPath, file);
+ assert rPath != null;
+ final String relativePath = FileUtil.toSystemIndependentName(rPath);
+ if (file.exists()) {
+ ZipUtil.addFileOrDirRecursively(output, saveFile, file, relativePath, null, writtenItemRelativePaths);
+ }
+ }
+
+ exportInstalledPlugins(saveFile, output, writtenItemRelativePaths);
+
+ final File magicFile = new File(FileUtil.getTempDirectory(), SETTINGS_JAR_MARKER);
+ FileUtil.createIfDoesntExist(magicFile);
+ magicFile.deleteOnExit();
+ ZipUtil.addFileToZip(output, magicFile, SETTINGS_JAR_MARKER, writtenItemRelativePaths, null);
+ }
+ finally {
+ output.close();
+ }
+ }
+ catch (IOException e1) {
+ Messages.showErrorDialog(IdeBundle.message("error.writing.settings", e1.toString()),IdeBundle.message("title.error.writing.file"));
+ }
+
+ }
+
+ private static void exportInstalledPlugins(File saveFile, JarOutputStream output, HashSet<String> writtenItemRelativePaths) throws IOException {
+ final List<String> oldPlugins = new ArrayList<String>();
+ for (IdeaPluginDescriptor descriptor : PluginManagerCore.getPlugins()) {
+ if (!descriptor.isBundled() && descriptor.isEnabled()) {
+ oldPlugins.add(descriptor.getPluginId().getIdString());
+ }
+ }
+ if (!oldPlugins.isEmpty()) {
+ final File tempFile = File.createTempFile("installed", "plugins");
+ tempFile.deleteOnExit();
+ PluginManagerCore.savePluginsList(oldPlugins, false, tempFile);
+ ZipUtil.addDirToZipRecursively(output, saveFile, tempFile, "/" + PluginManager.INSTALLED_TXT, null, writtenItemRelativePaths);
+ }
+ }
+}
diff --git a/src/com/google/gct/idea/settings/ImportSettings.java b/src/com/google/gct/idea/settings/ImportSettings.java
new file mode 100644
index 0000000..a509fc6
--- /dev/null
+++ b/src/com/google/gct/idea/settings/ImportSettings.java
@@ -0,0 +1,137 @@
+package com.google.gct.idea.settings;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.intellij.ide.IdeBundle;
+import com.intellij.ide.actions.ImportSettingsFilenameFilter;
+import com.intellij.ide.plugins.PluginManager;
+import com.intellij.ide.startup.StartupActionScriptManager;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.application.ex.ApplicationEx;
+import com.intellij.openapi.components.ExportableApplicationComponent;
+import com.intellij.openapi.components.ExportableComponent;
+import com.intellij.openapi.components.ServiceBean;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.updateSettings.impl.UpdateSettings;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.io.ZipUtil;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+
+/**
+ * Provides functionality to update IDEA setting from a jar containing new settings
+ */
+public class ImportSettings {
+ private static final String DIALOG_TITLE = "Setting Synchronization";
+ public static final String SETTINGS_JAR_MARKER = "IntelliJ IDEA Global Settings";
+
+ /**
+ * Parse and update the IDEA settings in the jar at <code>path</code>.
+ * Note: This function might require a restart of the application.
+ * @param path The location of the jar with the new IDEA settings.
+ */
+ public static void doImport(String path) {
+ final File saveFile = new File(path);
+ try {
+ if (!saveFile.exists()) {
+ Messages.showErrorDialog(IdeBundle.message("error.cannot.find.file", presentableFileName(saveFile)), DIALOG_TITLE);
+ return;
+ }
+
+ // What is this file used for?
+ final ZipEntry magicEntry = new ZipFile(saveFile).getEntry(SETTINGS_JAR_MARKER);
+ if (magicEntry == null) {
+ Messages.showErrorDialog("The file " + presentableFileName(saveFile) + " contains no settings to import",
+ DIALOG_TITLE);
+ return;
+ }
+
+ final ArrayList<ExportableComponent> registeredComponents = new ArrayList<ExportableComponent>(
+ Arrays.asList(ApplicationManager.getApplication().getComponents(ExportableApplicationComponent.class)));
+ registeredComponents.addAll(ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent.class));
+
+ List<ExportableComponent> storedComponents = getComponentsStored(saveFile, registeredComponents);
+
+ Set<String> relativeNamesToExtract = new HashSet<String>();
+ for (final ExportableComponent aComponent : storedComponents) {
+ final File[] exportFiles = aComponent.getExportFiles();
+ for (File exportFile : exportFiles) {
+ final File configPath = new File(PathManager.getConfigPath());
+ final String rPath = FileUtil.getRelativePath(configPath, exportFile);
+ assert rPath != null;
+ final String relativePath = FileUtil.toSystemIndependentName(rPath);
+ relativeNamesToExtract.add(relativePath);
+ }
+ }
+
+ relativeNamesToExtract.add(PluginManager.INSTALLED_TXT);
+
+ final File tempFile = new File(PathManager.getPluginTempPath() + "/" + saveFile.getName());
+ FileUtil.copy(saveFile, tempFile);
+ File outDir = new File(PathManager.getConfigPath());
+ final ImportSettingsFilenameFilter filenameFilter = new ImportSettingsFilenameFilter(relativeNamesToExtract);
+ StartupActionScriptManager.ActionCommand unzip = new StartupActionScriptManager.UnzipCommand(tempFile, outDir, filenameFilter);
+ StartupActionScriptManager.addActionCommand(unzip);
+
+ // remove temp file
+ StartupActionScriptManager.ActionCommand deleteTemp = new StartupActionScriptManager.DeleteCommand(tempFile);
+ StartupActionScriptManager.addActionCommand(deleteTemp);
+
+ UpdateSettings.getInstance().forceCheckForUpdateAfterRestart();
+
+ String key = ApplicationManager.getApplication().isRestartCapable()
+ ? "message.settings.imported.successfully.restart"
+ : "message.settings.imported.successfully";
+ final int ret = Messages.showOkCancelDialog(IdeBundle.message(key,
+ ApplicationNamesInfo.getInstance().getProductName(),
+ ApplicationNamesInfo.getInstance().getFullProductName()),
+ IdeBundle.message("title.restart.needed"), Messages.getQuestionIcon());
+ if (ret == Messages.OK) {
+ ((ApplicationEx)ApplicationManager.getApplication()).restart(true);
+ }
+ }
+ catch (ZipException e1) {
+ Messages.showErrorDialog(
+ "Error reading file " + presentableFileName(saveFile) + ".\\nThere was " + e1.getMessage(),
+ DIALOG_TITLE);
+ }
+ catch (IOException e1) {
+ Messages.showErrorDialog(IdeBundle.message("error.reading.settings.file.2", presentableFileName(saveFile), e1.getMessage()),
+ DIALOG_TITLE);
+ }
+ }
+
+ private static String presentableFileName(final File file) {
+ return "'" + FileUtil.toSystemDependentName(file.getPath()) + "'";
+ }
+
+ private static List<ExportableComponent> getComponentsStored(File zipFile,
+ ArrayList<ExportableComponent> registeredComponents)
+ throws IOException {
+ final File configPath = new File(PathManager.getConfigPath());
+
+ final ArrayList<ExportableComponent> components = new ArrayList<ExportableComponent>();
+ for (ExportableComponent component : registeredComponents) {
+ final File[] exportFiles = component.getExportFiles();
+ for (File exportFile : exportFiles) {
+ final String rPath = FileUtil.getRelativePath(configPath, exportFile);
+ assert rPath != null;
+ String relativePath = FileUtil.toSystemIndependentName(rPath);
+ if (exportFile.isDirectory()) relativePath += "/";
+ if (ZipUtil.isZipContainsEntry(zipFile, relativePath)) {
+ components.add(component);
+ break;
+ }
+ }
+ }
+ return components;
+ }
+}