diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/actions/Bundle.properties
--- a/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/actions/Bundle.properties Fri Jul 04 17:07:19 2008 +0200
+++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/actions/Bundle.properties Tue Jul 08 16:11:03 2008 +0200
@@ -1,6 +1,9 @@
CTL_CreateViewAction=Create view
LBL_process_problem=There was a problem creating the grails process:
CTL_GenerateAllAction=Generate all
+CTL_ManagePluginsAction=Grails Plugins
+CTL_Close=Close
+CTL_PluginTitle=Grails Plugins
MSG_Runtime_Not_Configured=The Grails Home has not been set.
\
Use menu Tools/Options/Groovy to set the environment.
\ No newline at end of file
diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/actions/ManagePluginsAction.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/actions/ManagePluginsAction.java Tue Jul 08 16:11:03 2008 +0200
@@ -0,0 +1,94 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2008 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.modules.groovy.grailsproject.actions;
+
+import java.awt.Dialog;
+import java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.groovy.grailsproject.GrailsProject;
+import org.netbeans.modules.groovy.grailsproject.ui.GrailsPluginsPanel;
+import org.openide.DialogDescriptor;
+import org.openide.DialogDisplayer;
+import org.openide.nodes.Node;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author David Calavera
+ */
+public class ManagePluginsAction extends AbstractAction {
+
+ GrailsProject project;
+
+ public ManagePluginsAction(Project project) {
+ super(NbBundle.getMessage(ManagePluginsAction.class, "CTL_ManagePluginsAction"));
+ this.project = (GrailsProject) project;
+ }
+
+ public boolean isEnabled() {
+ return true;
+ }
+
+ public void actionPerformed(ActionEvent arg0) {
+ GrailsPluginsPanel panel = new GrailsPluginsPanel(project);
+ javax.swing.JButton close =
+ new javax.swing.JButton(NbBundle.getMessage(ManagePluginsAction.class, "CTL_Close"));
+ close.getAccessibleContext()
+ .setAccessibleDescription(NbBundle.getMessage(ManagePluginsAction.class, "CTL_Close"));
+
+ DialogDescriptor descriptor =
+ new DialogDescriptor(panel, NbBundle.getMessage(ManagePluginsAction.class, "CTL_PluginTitle"),
+ true, new Object[] { close }, close, DialogDescriptor.DEFAULT_ALIGN,
+ new HelpCtx(GrailsPluginsPanel.class), null); // NOI18N
+ Dialog dlg = null;
+
+ try {
+ dlg = DialogDisplayer.getDefault().createDialog(descriptor);
+ dlg.setVisible(true);
+ } finally {
+ if (dlg != null) {
+ dlg.dispose();
+ }
+ }
+ }
+
+}
diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/Bundle.properties
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/Bundle.properties Tue Jul 08 16:11:03 2008 +0200
@@ -0,0 +1,4 @@
+PluginPleaseWait=Installing {0} plugin
+Installation=Installing plugins
+CTL_Close=Close
+CTL_Cancel=Cancel
\ No newline at end of file
diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/GrailsPlugin.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/GrailsPlugin.java Tue Jul 08 16:11:03 2008 +0200
@@ -0,0 +1,109 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2008 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.modules.groovy.grailsproject.plugins;
+
+/**
+ * plugin pojo class
+ *
+ * @author David Calavera
+ */
+public class GrailsPlugin implements Comparable {
+ private final String name;
+ private final String version;
+ private final String description;
+
+ public GrailsPlugin(String name, String version, String description) {
+ this.name = name;
+ this.version = version;
+ this.description = description;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String toString() {
+ String toS = getName();
+ if (getVersion() != null && getVersion().trim().length() > 0) {
+ toS += "(" + getVersion().trim() + ")";
+ }
+ if (getDescription() != null && getDescription().trim().length() > 0
+ && !getDescription().trim().equals("No description available")) {
+ toS += " -- " + getDescription().trim();
+ }
+ return toS;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final GrailsPlugin other = (GrailsPlugin) obj;
+ if (this.name != other.name && (this.name == null || !this.name.equalsIgnoreCase(other.name))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 97 * hash + (this.name != null ? this.name.toUpperCase().hashCode() : 0);
+ return hash;
+ }
+
+ public int compareTo(GrailsPlugin o) {
+ return name.compareToIgnoreCase(o.name);
+ }
+
+}
diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/GrailsPluginsManager.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/GrailsPluginsManager.java Tue Jul 08 16:11:03 2008 +0200
@@ -0,0 +1,304 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2008 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.modules.groovy.grailsproject.plugins;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.Dialog;
+import java.lang.String;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.swing.JButton;
+import javax.swing.SwingUtilities;
+import org.netbeans.api.project.ProjectInformation;
+import org.netbeans.modules.extexecution.api.ExecutionDescriptor;
+import org.netbeans.modules.extexecution.api.ExecutionService;
+import org.netbeans.modules.extexecution.api.input.InputProcessor;
+import org.netbeans.modules.extexecution.api.input.InputProcessors;
+import org.netbeans.modules.extexecution.api.input.LineProcessor;
+import org.netbeans.modules.groovy.grails.api.ExecutionSupport;
+import org.netbeans.modules.groovy.grails.api.GrailsProjectConfig;
+import org.netbeans.modules.groovy.grailsproject.GrailsProject;
+import org.netbeans.modules.groovy.grailsproject.actions.RefreshProjectRunnable;
+import org.openide.DialogDescriptor;
+import org.openide.DialogDisplayer;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Exceptions;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+import org.openide.util.RequestProcessor;
+import org.openide.xml.XMLUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
+
+/**
+ *
+ * @author David Calavera
+ */
+public class GrailsPluginsManager {
+
+ private final GrailsProject project;
+
+ private GrailsPluginsManager(GrailsProject project) {
+ this.project = project;
+ }
+
+ public static GrailsPluginsManager getInstance(GrailsProject project) {
+ return new GrailsPluginsManager(project);
+ }
+
+ public List refreshAvailablePlugins() {
+ String command = "list-plugins"; // NOI18N
+
+ ProjectInformation inf = project.getLookup().lookup(ProjectInformation.class);
+ String displayName = inf.getDisplayName() + " (" + command + ")"; // NOI18N
+
+ Callable callable = ExecutionSupport.getInstance().createSimpleCommand(
+ command, GrailsProjectConfig.forProject(project));
+
+ final PluginProcessor processor = new PluginProcessor();
+ ExecutionDescriptor.Builder builder = new ExecutionDescriptor.Builder();
+ builder.frontWindow(true);
+ builder.outProcessorFactory(new ExecutionDescriptor.InputProcessorFactory() {
+ public InputProcessor newInputProcessor() {
+ return InputProcessors.bridge(processor);
+ }
+ });
+
+ ExecutionService service = ExecutionService.newService(callable, builder.create(), displayName);
+ try {
+ service.run().get();
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ } catch (ExecutionException ex) {
+ Exceptions.printStackTrace(ex.getCause());
+ }
+
+ return processor.getPlugins();
+ }
+
+ public List refreshInstalledPlugins() {
+ List plugins = new ArrayList();
+ try {
+ FileObject pluginsDir = project.getProjectDirectory().getFileObject("plugins"); //NOI18N
+ if (pluginsDir != null && pluginsDir.isFolder()) {
+ pluginsDir.refresh();
+ for (FileObject child : pluginsDir.getChildren()) {
+ if (child.isFolder()) {
+ FileObject descriptor = child.getFileObject("plugin.xml"); //NOI18N
+ if (descriptor != null && descriptor.canRead()) {
+ Document doc = XMLUtil.parse(new InputSource(descriptor.getInputStream()),
+ false, false, null, null);
+ Node root = doc.getFirstChild();
+ String name = root.getAttributes().getNamedItem("name").getTextContent(); //NOI18N
+ String version = null;
+ String description = null;
+ if (root.getAttributes().getNamedItem("version") != null) { //NOI18N
+ version = root.getAttributes().getNamedItem("version").getTextContent(); //NOI18N
+ }
+ if (doc.getElementsByTagName("title") != null
+ && doc.getElementsByTagName("title").getLength() > 0) { //NOI18N
+ description = doc.getElementsByTagName("title")
+ .item(0).getTextContent(); //NOI18N
+ }
+
+ plugins.add(new GrailsPlugin(name, version, description));
+ }
+ }
+ }
+ }
+ } catch (Exception ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ Collections.sort(plugins);
+ return plugins;
+ }
+
+ public boolean uninstallPlugins(Object[] selectedPlugins) {
+ if (selectedPlugins != null && selectedPlugins.length > 0) {
+ FileObject pluginsDir = project.getProjectDirectory().getFileObject("plugins"); //NO I18N
+ if (pluginsDir != null && pluginsDir.isFolder() && pluginsDir.canWrite()) {
+ pluginsDir.refresh();
+ try {
+ for (Object obj : selectedPlugins) {
+ GrailsPlugin plugin = (GrailsPlugin) obj;
+ String pluginName = plugin.getName() + "-" + plugin.getVersion();
+ FileObject pluginDir = pluginsDir.getFileObject(pluginName);
+ if (pluginDir != null && pluginDir.isValid()) {
+ pluginDir.delete();
+ }
+ FileObject pluginZipFile = pluginsDir.getFileObject("grails-" + pluginName + ".zip");
+ if (pluginZipFile != null && pluginZipFile.isValid()) {
+ pluginZipFile.delete();
+ }
+ }
+ } catch (Exception ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ }
+ return true;
+ }
+
+ public boolean installPlugins(final Object[] selectedPlugins) {
+ boolean installed = true;
+ if (selectedPlugins != null && selectedPlugins.length > 0) {
+ final JButton closeButton = new JButton(NbBundle.getMessage(GrailsPluginsManager.class, "CTL_Close"));
+ final JButton cancelButton =
+ new JButton(NbBundle.getMessage(GrailsPluginsManager.class, "CTL_Cancel"));
+ closeButton.getAccessibleContext()
+ .setAccessibleDescription(NbBundle.getMessage(GrailsPluginsManager.class, "CTL_Close"));
+
+ Object[] options = new Object[] { closeButton, cancelButton };
+ closeButton.setEnabled(false);
+
+ String title = NbBundle.getMessage(GrailsPluginsManager.class, "Installation");
+
+ for (Object obj : selectedPlugins) {
+ final GrailsPlugin plugin = (GrailsPlugin) obj;
+
+ final InstallingPluginPanel progress = new InstallingPluginPanel(NbBundle.getMessage(GrailsPluginsManager.class, "PluginPleaseWait", plugin.getName()));
+ DialogDescriptor descriptor = new DialogDescriptor(progress, title, true, options, closeButton,
+ DialogDescriptor.DEFAULT_ALIGN, new HelpCtx(InstallingPluginPanel.class), null); // NOI18N
+ descriptor.setModal(true);
+ final Dialog dlg = DialogDisplayer.getDefault().createDialog(descriptor);
+
+ closeButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent ev) {
+ dlg.setVisible(false);
+ dlg.dispose();
+ }
+ });
+
+ final String command = "install-plugin"; // NOI18N
+
+ Runnable runner = new Runnable() {
+ public void run() {
+ ProjectInformation inf = project.getLookup().lookup(ProjectInformation.class);
+ String displayName = inf.getDisplayName() + " (" + command + ")"; // NOI18N
+
+ Callable callable = ExecutionSupport.getInstance().createSimpleCommand(
+ command, GrailsProjectConfig.forProject(project), plugin.getName(), plugin.getVersion());
+
+ ExecutionDescriptor.Builder builder = new ExecutionDescriptor.Builder();
+ builder.frontWindow(true);
+ builder.postExecution(new RefreshProjectRunnable(project));
+
+ ExecutionService service = ExecutionService.newService(callable, builder.create(), displayName);
+ final Future future = service.run();
+ cancelButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent ev) {
+ future.cancel(true);
+ }
+ });
+
+ try {
+ future.get();
+ } catch (InterruptedException ex) {
+ //do nothing
+ } catch (ExecutionException ex) {
+ Exceptions.printStackTrace(ex);
+ } catch (CancellationException ex) {
+ //do nothing
+ }
+
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ dlg.setVisible(false);
+ dlg.dispose();
+ }
+ });
+ }
+ };
+ RequestProcessor.getDefault().post(runner, 10);
+ dlg.setVisible(true);
+
+ if (descriptor.getValue() == cancelButton) {
+ cleanUninstalledPlugin(dlg, plugin);
+ installed = false;
+ }
+ }
+ }
+ return installed;
+ }
+
+ private void cleanUninstalledPlugin(Dialog dlg, GrailsPlugin plugin) {
+ uninstallPlugins(new Object[]{plugin});
+ dlg.setVisible(false);
+ dlg.dispose();
+ }
+
+ private static class PluginProcessor implements LineProcessor {
+
+ private final List plugins = Collections.synchronizedList(new ArrayList());
+
+ private static final Pattern PLUGIN_PATTERN = Pattern.compile("(.+)[\\s]+<([\\w\\s.-]+)>[\\s]+--(.+)");
+ public void processLine(String line) {
+ GrailsPlugin plugin = null;
+ Matcher matcher = PLUGIN_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ if (!"no releases".equals(matcher.group(2))) { //NO I18N
+ plugin = new GrailsPlugin(matcher.group(1).trim(), matcher.group(2), matcher.group(3));
+ }
+ }
+ if (plugin != null) {
+ plugins.add(plugin);
+ }
+ }
+
+ public void reset() {
+ // noop
+ }
+
+ public List getPlugins() {
+ return plugins;
+ }
+
+ }
+}
diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/InstallingPluginPanel.form
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/InstallingPluginPanel.form Tue Jul 08 16:11:03 2008 +0200
@@ -0,0 +1,55 @@
+
+
+
diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/InstallingPluginPanel.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/plugins/InstallingPluginPanel.java Tue Jul 08 16:11:03 2008 +0200
@@ -0,0 +1,66 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.netbeans.modules.groovy.grailsproject.plugins;
+
+/**
+ * @author David Calavera
+ */
+public class InstallingPluginPanel extends javax.swing.JPanel {
+
+ public InstallingPluginPanel(String message) {
+ initComponents();
+ jLabel1.setText(message);
+ }
+
+ public void done(String message) {
+ progressBar.setIndeterminate(false);
+ progressBar.getModel().setValue(progressBar.getModel().getMaximum());
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the FormEditor.
+ */
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ progressBar = new javax.swing.JProgressBar();
+ jLabel1 = new javax.swing.JLabel();
+
+ progressBar.setIndeterminate(true);
+
+ jLabel1.setText("Plugin");
+
+ org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+ .add(layout.createSequentialGroup()
+ .addContainerGap()
+ .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+ .add(progressBar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 372, Short.MAX_VALUE)
+ .add(jLabel1))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+ .add(layout.createSequentialGroup()
+ .add(12, 12, 12)
+ .add(jLabel1)
+ .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+ .add(progressBar, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(36, Short.MAX_VALUE))
+ );
+ }// //GEN-END:initComponents
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JProgressBar progressBar;
+ // End of variables declaration//GEN-END:variables
+
+}
diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/Bundle.properties
--- a/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/Bundle.properties Fri Jul 04 17:07:19 2008 +0200
+++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/Bundle.properties Tue Jul 08 16:11:03 2008 +0200
@@ -1,3 +1,4 @@
+FetchingPlugins=Please Wait... Fetching list of plugins from server
GeneralCustomizerPanel.projectFolderLabel.text=Project Directory:
GeneralCustomizerPanel.projectFolderTextField.text=
GeneralCustomizerPanel.activeGrailsEnvironmentLabel.text=Active Grails Enviroment:
diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/GrailsLogicalViewProvider.java
--- a/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/GrailsLogicalViewProvider.java Fri Jul 04 17:07:19 2008 +0200
+++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/GrailsLogicalViewProvider.java Tue Jul 08 16:11:03 2008 +0200
@@ -51,6 +51,7 @@
import org.netbeans.modules.groovy.grailsproject.GrailsActionProvider;
import org.netbeans.modules.groovy.grailsproject.GrailsProject;
import org.netbeans.modules.groovy.grailsproject.actions.GrailsCommandAction;
+import org.netbeans.modules.groovy.grailsproject.actions.ManagePluginsAction;
import org.netbeans.spi.project.ActionProvider;
import org.netbeans.spi.project.ui.LogicalViewProvider;
import org.netbeans.spi.project.ui.support.CommonProjectActions;
@@ -130,6 +131,8 @@
actions.add(null);
actions.add(ProjectSensitiveActions.projectCommandAction(GrailsActionProvider.COMMAND_GRAILS_SHELL,
NbBundle.getMessage(GrailsLogicalViewProvider.class, "LBL_ShellAction_Name"), null));
+ actions.add(null);
+ actions.add(new ManagePluginsAction(project));
actions.add(null);
actions.add(ProjectSensitiveActions.projectCommandAction(ActionProvider.COMMAND_RUN,
NbBundle.getMessage(GrailsLogicalViewProvider.class, "LBL_RunAction_Name"), null));
diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/GrailsPluginsPanel.form
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/GrailsPluginsPanel.form Tue Jul 08 16:11:03 2008 +0200
@@ -0,0 +1,207 @@
+
+
+
diff -r 3be9e9f80edf groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/GrailsPluginsPanel.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/groovy.grailsproject/src/org/netbeans/modules/groovy/grailsproject/ui/GrailsPluginsPanel.java Tue Jul 08 16:11:03 2008 +0200
@@ -0,0 +1,353 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.netbeans.modules.groovy.grailsproject.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.DefaultListModel;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingUtilities;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.groovy.grailsproject.GrailsProject;
+import org.netbeans.modules.groovy.grailsproject.plugins.GrailsPlugin;
+import org.netbeans.modules.groovy.grailsproject.plugins.GrailsPluginsManager;
+import org.openide.util.NbBundle;
+import org.openide.util.RequestProcessor;
+
+/**
+ * @author David Calavera
+ */
+public class GrailsPluginsPanel extends javax.swing.JPanel {
+
+ private GrailsProject project;
+ private GrailsPluginsManager pluginsManager;
+
+ private boolean installedInitialized;
+ private boolean installedModified;
+ private boolean availablePluginsInitialized;
+ private boolean availableModified;
+ private List installedPluginsList = new ArrayList();
+ private List availablePluginsList = new ArrayList();
+
+ /** Creates new customizer GrailsPluginsPanel */
+ public GrailsPluginsPanel(Project project) {
+ initComponents();
+ this.project = (GrailsProject) project;
+ this.pluginsManager = GrailsPluginsManager.getInstance(this.project);
+ }
+
+ /** Refresh the installed plugin list */
+ private void refreshInstalled() {
+ assert SwingUtilities.isEventDispatchThread();
+ final DefaultListModel model = new DefaultListModel();
+ reloadInstalledButton.setEnabled(false);
+ installedPluginsList = pluginsManager.refreshInstalledPlugins();
+ for (GrailsPlugin plugin : installedPluginsList) {
+ model.addElement(plugin);
+ }
+
+ installedPlugins.clearSelection();
+ installedPlugins.setModel(model);
+ installedPlugins.invalidate();
+ installedPlugins.repaint();
+ reloadInstalledButton.setEnabled(true);
+ }
+
+ private void refreshAvailable() {
+ assert SwingUtilities.isEventDispatchThread();
+
+ Runnable runner = new Runnable() {
+
+ public void run() {
+ synchronized(GrailsPluginsPanel.this) {
+ final DefaultListModel model = new DefaultListModel();
+ availablePluginsList = pluginsManager.refreshAvailablePlugins();
+
+ for (GrailsPlugin plugin : availablePluginsList) {
+ if (!installedPluginsList.contains(plugin)) {
+ model.addElement(plugin);
+ }
+ }
+
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ availablePlugins.clearSelection();
+ availablePlugins.setModel(model);
+ availablePlugins.invalidate();
+ availablePlugins.repaint();
+ reloadAvailableButton.setEnabled(true);
+ }
+ });
+ }
+ }
+ };
+
+ reloadAvailableButton.setEnabled(false);
+ DefaultListModel model = new DefaultListModel();
+ model.addElement(NbBundle.getMessage(GrailsPluginsPanel.class, "FetchingPlugins"));
+ availablePlugins.setModel(model);
+
+ RequestProcessor.getDefault().post(runner);
+ }
+
+ private void uninstallPlugins() {
+ Object[] selected = installedPlugins.getSelectedValues();
+ pluginsManager.uninstallPlugins(selected);
+
+ refreshInstalled();
+ availableModified = true;
+ }
+
+ private void installPlugins() {
+ installButton.setEnabled(false);
+
+ Object[] selected = availablePlugins.getSelectedValues();
+ availableModified = pluginsManager.installPlugins(selected);
+
+ refreshInstalled();
+
+ pluginsPanel.setSelectedComponent(installedPanel);
+ pluginsPanel.invalidate();
+ pluginsPanel.repaint();
+
+ installButton.setEnabled(true);
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the FormEditor.
+ */
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ pluginsPanel = new javax.swing.JTabbedPane();
+ installedPanel = new javax.swing.JPanel();
+ reloadInstalledButton = new javax.swing.JButton();
+ jScrollPane1 = new javax.swing.JScrollPane();
+ installedPlugins = new javax.swing.JList();
+ uninstallButton = new javax.swing.JButton();
+ newPluginPanel = new javax.swing.JPanel();
+ jScrollPane2 = new javax.swing.JScrollPane();
+ availablePlugins = new javax.swing.JList();
+ installButton = new javax.swing.JButton();
+ reloadAvailableButton = new javax.swing.JButton();
+
+ installedPanel.addComponentListener(new java.awt.event.ComponentAdapter() {
+ public void componentShown(java.awt.event.ComponentEvent evt) {
+ installedPanelComponentShown(evt);
+ }
+ });
+
+ reloadInstalledButton.setText("Reload Plugins");
+ reloadInstalledButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ reloadInstalledButtonActionPerformed(evt);
+ }
+ });
+
+ installedPlugins.setModel(new javax.swing.AbstractListModel() {
+ public int getSize() { return installedPluginsList.size(); }
+ public Object getElementAt(int arg0) { return installedPluginsList.get(arg0); }
+ });
+ installedPlugins.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
+ public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
+ installedPluginsValueChanged(evt);
+ }
+ });
+ jScrollPane1.setViewportView(installedPlugins);
+
+ uninstallButton.setText("Uninstall");
+ uninstallButton.setEnabled(false);
+ uninstallButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ uninstallButtonActionPerformed(evt);
+ }
+ });
+
+ org.jdesktop.layout.GroupLayout installedPanelLayout = new org.jdesktop.layout.GroupLayout(installedPanel);
+ installedPanel.setLayout(installedPanelLayout);
+ installedPanelLayout.setHorizontalGroup(
+ installedPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+ .add(installedPanelLayout.createSequentialGroup()
+ .addContainerGap()
+ .add(installedPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+ .add(uninstallButton)
+ .add(reloadInstalledButton)
+ .add(org.jdesktop.layout.GroupLayout.TRAILING, installedPanelLayout.createSequentialGroup()
+ .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
+ .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 728, Short.MAX_VALUE)))
+ .addContainerGap())
+ );
+ installedPanelLayout.setVerticalGroup(
+ installedPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+ .add(installedPanelLayout.createSequentialGroup()
+ .addContainerGap()
+ .add(reloadInstalledButton)
+ .add(17, 17, 17)
+ .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 355, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 35, Short.MAX_VALUE)
+ .add(uninstallButton)
+ .addContainerGap())
+ );
+
+ pluginsPanel.addTab("Installed", installedPanel);
+
+ newPluginPanel.addComponentListener(new java.awt.event.ComponentAdapter() {
+ public void componentShown(java.awt.event.ComponentEvent evt) {
+ newPluginPanelComponentShown(evt);
+ }
+ });
+
+ availablePlugins.setModel(new javax.swing.AbstractListModel() {
+ public int getSize() { return availablePluginsList.size(); }
+ public Object getElementAt(int arg0) { return availablePluginsList.get(arg0); }
+ });
+ availablePlugins.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
+ public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
+ availablePluginsValueChanged(evt);
+ }
+ });
+ jScrollPane2.setViewportView(availablePlugins);
+
+ installButton.setText("Install");
+ installButton.setEnabled(false);
+ installButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ installButtonActionPerformed(evt);
+ }
+ });
+
+ reloadAvailableButton.setText("Reload Plugins");
+ reloadAvailableButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ reloadAvailableButtonActionPerformed(evt);
+ }
+ });
+
+ org.jdesktop.layout.GroupLayout newPluginPanelLayout = new org.jdesktop.layout.GroupLayout(newPluginPanel);
+ newPluginPanel.setLayout(newPluginPanelLayout);
+ newPluginPanelLayout.setHorizontalGroup(
+ newPluginPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+ .add(newPluginPanelLayout.createSequentialGroup()
+ .addContainerGap()
+ .add(newPluginPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+ .add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 728, Short.MAX_VALUE)
+ .add(installButton)
+ .add(reloadAvailableButton))
+ .addContainerGap())
+ );
+ newPluginPanelLayout.setVerticalGroup(
+ newPluginPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+ .add(org.jdesktop.layout.GroupLayout.TRAILING, newPluginPanelLayout.createSequentialGroup()
+ .addContainerGap()
+ .add(reloadAvailableButton)
+ .add(17, 17, 17)
+ .add(jScrollPane2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 355, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 35, Short.MAX_VALUE)
+ .add(installButton)
+ .addContainerGap())
+ );
+
+ pluginsPanel.addTab("New plugins", newPluginPanel);
+
+ org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+ .add(layout.createSequentialGroup()
+ .addContainerGap()
+ .add(pluginsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 757, Short.MAX_VALUE)
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
+ .add(layout.createSequentialGroup()
+ .addContainerGap()
+ .add(pluginsPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 508, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+ }// //GEN-END:initComponents
+
+private void uninstallButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_uninstallButtonActionPerformed
+ uninstallPlugins();
+}//GEN-LAST:event_uninstallButtonActionPerformed
+
+private void reloadAvailableButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_reloadAvailableButtonActionPerformed
+ refreshAvailable();
+}//GEN-LAST:event_reloadAvailableButtonActionPerformed
+
+private void reloadInstalledButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_reloadInstalledButtonActionPerformed
+ refreshInstalled();
+}//GEN-LAST:event_reloadInstalledButtonActionPerformed
+
+private void installButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_installButtonActionPerformed
+ installPlugins();
+}//GEN-LAST:event_installButtonActionPerformed
+
+private void installedPluginsValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_installedPluginsValueChanged
+ uninstallButton.setEnabled(installedPlugins.getSelectedIndices() != null
+ && installedPlugins.getSelectedIndices().length > 0);
+}//GEN-LAST:event_installedPluginsValueChanged
+
+private void availablePluginsValueChanged(javax.swing.event.ListSelectionEvent evt) {//GEN-FIRST:event_availablePluginsValueChanged
+ installButton.setEnabled(availablePlugins.getSelectedIndices() != null
+ && availablePlugins.getSelectedIndices().length > 0);
+ //waiting the plugin list from the server
+ if (availablePlugins.getSelectedIndices().length == 1 &&
+ availablePlugins.getSelectedValue().equals(
+ NbBundle.getMessage(GrailsPluginsPanel.class, "FetchingPlugins"))) {
+ installButton.setEnabled(false);
+ }
+}//GEN-LAST:event_availablePluginsValueChanged
+
+private void installedPanelComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_installedPanelComponentShown
+ assert SwingUtilities.isEventDispatchThread();
+
+ if (!installedInitialized) {
+ installedInitialized = true;
+ installedPlugins.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+
+ installedModified = true;
+ } else installedModified = false;
+
+ if (installedModified) {
+ refreshInstalled();
+ }
+}//GEN-LAST:event_installedPanelComponentShown
+
+private void newPluginPanelComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_newPluginPanelComponentShown
+ assert SwingUtilities.isEventDispatchThread();
+
+ if (!availablePluginsInitialized) {
+ availablePluginsInitialized = true;
+ availablePlugins.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+
+ availableModified = true;
+ }
+
+ if (availableModified) {
+ refreshAvailable();
+ availableModified = false;
+ }
+}//GEN-LAST:event_newPluginPanelComponentShown
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JList availablePlugins;
+ private javax.swing.JButton installButton;
+ private javax.swing.JPanel installedPanel;
+ private javax.swing.JList installedPlugins;
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JScrollPane jScrollPane2;
+ private javax.swing.JPanel newPluginPanel;
+ private javax.swing.JTabbedPane pluginsPanel;
+ private javax.swing.JButton reloadAvailableButton;
+ private javax.swing.JButton reloadInstalledButton;
+ private javax.swing.JButton uninstallButton;
+ // End of variables declaration//GEN-END:variables
+
+}