Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core')
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/ConsoleDocument.java95
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/IMavenConsoleListener.java27
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsoleFactory.java31
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsoleImpl.java395
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsolePageParticipant.java107
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsoleService.java18
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenShowConsoleAction.java82
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/M2EUIPluginActivator.java69
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenAdapterFactory.java67
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenImages.java223
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenVersionDecorator.java111
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/UpdateConfigurationJob.java126
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/AddDependencyAction.java85
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/AddPluginAction.java74
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/ChangeNatureAction.java181
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/CheckoutAsMavenAction.java90
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/DisableNatureAction.java80
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/EnableNatureAction.java141
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MaterializeAction.java56
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenActionSupport.java138
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenConsoleRemoveAction.java31
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenDebugOutputAction.java62
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenPropertyTester.java95
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/ModuleProjectWizardAction.java60
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/OpenMavenConsoleAction.java28
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/OpenPomAction.java405
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/OpenUrlAction.java228
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/RefreshMavenModelsAction.java113
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/SelectionUtil.java357
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/UpdateConfigurationAction.java99
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/components/TextComboBoxCellEditor.java103
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/AbstractMavenDialog.java123
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/AddDependencyDialog.java690
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/EditDependencyDialog.java221
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/InputHistory.java231
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenGoalSelectionDialog.java358
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenMessageDialog.java105
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenPropertyDialog.java191
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenRepositorySearchDialog.java441
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/AbstractLifecyclePropertyPage.java57
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/AbstractPropertyPageExtensionPoint.java67
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ILifecyclePropertyPage.java60
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ILifecyclePropertyPageExtensionPoint.java55
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/LifecycleMappingPropertyPageFactory.java142
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ProjectConfiguratorsTable.java108
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ProjectConfiguratorsTableContentProvider.java60
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ProjectConfiguratorsTableLabelProvider.java95
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/CustomizableLifecycleMappingPropertyPage.java57
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/EmptyLifecycleMappingPropertyPage.java27
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/GoalsFieldEditor.java196
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/LocalArchetypeCatalogDialog.java228
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenArchetypesPreferencePage.java319
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenGoalSelectionAdapter.java72
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenInstallationsPreferencePage.java672
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenPreferencePage.java104
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenProjectLifecycleMappingPage.java96
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenProjectPreferencePage.java166
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenSettingsPreferencePage.java411
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MissingLifecycleMappingPropertyPage.java36
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/RemoteArchetypeCatalogDialog.java282
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/SimpleLifecycleMappingPropertyPage.java61
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/MavenSearchPage.java140
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/MavenSearchResult.java76
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/MavenSearchResultPage.java80
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/ArtifactInfo.java78
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/CComboContentAdapter.java96
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/ControlDecoration.java1088
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/IndexSearchEngine.java183
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/MenuDetectEvent.java77
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/MenuDetectListener.java43
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/Packaging.java47
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/SearchEngine.java49
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/SearchException.java29
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/M2EErrorDialog.java218
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/M2EUIUtils.java88
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/ProposalUtil.java178
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/Util.java57
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/MavenRepositoryView.java595
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/RepositoryViewContentProvider.java85
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/RepositoryViewLabelProvider.java96
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/AbstractIndexedRepositoryNode.java85
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/AbstractRepositoriesNode.java76
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/CustomRepositoriesNode.java35
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/GlobalRepositoriesNode.java36
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IArtifactNode.java22
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IMavenRepositoryNode.java28
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IndexedArtifactFileNode.java90
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IndexedArtifactGroupNode.java100
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IndexedArtifactNode.java91
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/LocalRepositoryNode.java38
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/LocalRepositoryRootNode.java54
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/ProjectRepositoriesNode.java65
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/RepositoryNode.java56
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/WorkspaceRepositoryNode.java32
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/AbstactCreateMavenProjectJob.java80
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/AbstractMavenProjectWizard.java40
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/AbstractMavenWizardPage.java218
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/CustomArchetypeDialog.java251
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenArtifactComponent.java267
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenCheckoutLocationPage.java422
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenCheckoutWizard.java171
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenDependenciesWizardPage.java285
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenImportWizard.java99
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenImportWizardPage.java525
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenInstallFileArtifactWizardPage.java388
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenInstallFileRepositoryWizardPage.java148
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenInstallFileWizard.java149
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenLocationComponent.java192
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenMaterializePomWizard.java151
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenModuleWizard.java296
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenModuleWizardParentPage.java314
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenParentComponent.java221
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomSelectionComponent.java560
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomWizard.java172
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomWizardPage.java221
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectCheckoutJob.java257
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectSelectionDialog.java191
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizard.java325
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardArchetypePage.java951
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardArchetypeParametersPage.java615
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardArtifactPage.java359
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardLocationPage.java316
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/ProjectsImportPage.java626
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/ProjectsImportWizard.java47
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/ResolverConfigurationComponent.java155
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/WidthGroup.java53
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/WorkingSetGroup.java269
-rw-r--r--org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/WorkingSetHelper.java8
128 files changed, 22961 insertions, 0 deletions
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/ConsoleDocument.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/ConsoleDocument.java
new file mode 100644
index 00000000..77ccfa1b
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/ConsoleDocument.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.internal.console;
+
+/**
+ * Simple circular buffer that stores a fix number of lines.
+ */
+// TODO consider use standard ConsoleDocument
+public class ConsoleDocument {
+ public static final int COMMAND = 0; // command text
+ public static final int MESSAGE = 1; // message received
+ public static final int ERROR = 2; // error received
+ public static final int STATUS = 3; // status text
+ public static final int DELIMITER = 4; // delimiter text between runs
+
+ private int[] lineTypes;
+ private String[] lines;
+
+ private int writeIndex = 0;
+ private int readIndex = 0;
+
+ private static final int BUFFER_SIZE = 200;
+
+ protected static class ConsoleLine {
+ public String line;
+ public int type;
+ ConsoleLine(String line, int type) {
+ this.line = line;
+ this.type = type;
+ }
+ }
+
+ /**
+ * Creates an empty console document.
+ */
+ public ConsoleDocument() {
+ }
+
+ /**
+ * Clears the console document.
+ */
+ public void clear() {
+ lineTypes = null;
+ lines = null;
+ writeIndex = 0;
+ readIndex = 0;
+ }
+
+ /**
+ * Appends a line of the specified type to the end of the console.
+ */
+ public void appendConsoleLine(int type, String line) {
+ if(lines == null) {
+ lines = new String[BUFFER_SIZE];
+ lineTypes = new int[BUFFER_SIZE];
+ }
+ lines[writeIndex] = line;
+ lineTypes[writeIndex] = type;
+
+ if(++writeIndex >= BUFFER_SIZE) {
+ writeIndex = 0;
+ }
+ if(writeIndex == readIndex) {
+ if(++readIndex >= BUFFER_SIZE) {
+ readIndex = 0;
+ }
+ }
+ }
+
+ public ConsoleLine[] getLines() {
+ if(isEmpty()) return new ConsoleLine[0];
+ ConsoleLine[] docLines = new ConsoleLine[readIndex > writeIndex ? BUFFER_SIZE : writeIndex];
+ int index = readIndex;
+ for (int i = 0; i < docLines.length; i++) {
+ docLines[i] = new ConsoleLine(lines[index], lineTypes[index]);
+ if (++index >= BUFFER_SIZE) {
+ index = 0;
+ }
+ }
+ return docLines;
+ }
+
+ public boolean isEmpty() {
+ return writeIndex == readIndex;
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/IMavenConsoleListener.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/IMavenConsoleListener.java
new file mode 100644
index 00000000..a1817882
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/IMavenConsoleListener.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.internal.console;
+
+import java.util.EventListener;
+
+/**
+ * A console listener is notified of output to the Maven console.
+ *
+ * @author Benjamin Bentmann
+ */
+public interface IMavenConsoleListener extends EventListener {
+
+ void loggingMessage(String msg);
+
+ void loggingError(String msg);
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsoleFactory.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsoleFactory.java
new file mode 100644
index 00000000..1a491e99
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsoleFactory.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.internal.console;
+
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.ui.console.IConsoleFactory;
+
+/**
+ * Maven Console factory is used to show the console from the "Open Console"
+ * drop-down action in Console view.
+ *
+ * @see org.eclipse.ui.console.consoleFactory extension point.
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenConsoleFactory implements IConsoleFactory {
+
+ public void openConsole() {
+ M2EUIPluginActivator.getDefault().getMavenConsoleImpl().showConsole();
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsoleImpl.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsoleImpl.java
new file mode 100644
index 00000000..ef200552
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsoleImpl.java
@@ -0,0 +1,395 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.internal.console;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.internal.preferences.MavenPreferenceConstants;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.console.ConsolePlugin;
+import org.eclipse.ui.console.IConsole;
+import org.eclipse.ui.console.IConsoleListener;
+import org.eclipse.ui.console.IConsoleManager;
+import org.eclipse.ui.console.IOConsole;
+import org.eclipse.ui.console.IOConsoleOutputStream;
+
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.util.ULocale;
+
+
+/**
+ * Maven Console implementation
+ *
+ * @author Dmitri Maximovich
+ */
+public class MavenConsoleImpl extends IOConsole implements IPropertyChangeListener {
+
+ private boolean initialized = false;
+
+ // console is visible in the Console view
+ private boolean visible = false;
+
+ private ConsoleDocument consoleDocument;
+
+ // created colors for each line type - must be disposed at shutdown
+ private Color commandColor;
+
+ private Color messageColor;
+
+ private Color errorColor;
+
+ // streams for each command type - each stream has its own color
+ private IOConsoleOutputStream commandStream;
+
+ private IOConsoleOutputStream messageStream;
+
+ private IOConsoleOutputStream errorStream;
+ private static final String TITLE = Messages.MavenConsoleImpl_title;
+
+ private List<IMavenConsoleListener> listeners = new CopyOnWriteArrayList<IMavenConsoleListener>();
+
+ public MavenConsoleImpl(ImageDescriptor imageDescriptor) {
+ super(TITLE, imageDescriptor);
+ this.setConsoleDocument(new ConsoleDocument());
+ }
+
+ protected void init() {
+ super.init();
+
+ // Ensure that initialization occurs in the UI thread
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ JFaceResources.getFontRegistry().addListener(MavenConsoleImpl.this);
+ initializeConsoleStreams(Display.getDefault());
+ dumpConsole();
+ }
+ });
+ }
+
+ /*
+ * Initialize three streams of the console. Must be called from the UI thread, so synchronization is unnecessary.
+ */
+ protected void initializeConsoleStreams(Display display) {
+ if(!initialized) {
+ setCommandStream(newOutputStream());
+ setErrorStream(newOutputStream());
+ setMessageStream(newOutputStream());
+
+ // TODO convert this to use themes
+ // install colors
+ commandColor = new Color(display, new RGB(0, 0, 0));
+ messageColor = new Color(display, new RGB(0, 0, 255));
+ errorColor = new Color(display, new RGB(255, 0, 0));
+
+ getCommandStream().setColor(commandColor);
+ getMessageStream().setColor(messageColor);
+ getErrorStream().setColor(errorColor);
+
+ // install font
+ setFont(JFaceResources.getFontRegistry().get("pref_console_font")); //$NON-NLS-1$
+
+ initialized = true;
+ }
+ }
+
+ /**
+ * Is always called from main thread, so synchronization not necessary
+ */
+ protected void dumpConsole() {
+ setVisible(true);
+ ConsoleDocument.ConsoleLine[] lines = getConsoleDocument().getLines();
+ for(int i = 0; i < lines.length; i++ ) {
+ ConsoleDocument.ConsoleLine line = lines[i];
+ appendLine(line.type, line.line);
+ }
+ getConsoleDocument().clear();
+ }
+
+ private void appendLine(final int type, final String line) {
+ show(false);
+ //the synchronization here caused a deadlock. since the writes are simply appending to the output stream
+ //or the document, just doing it on the main thread to avoid deadlocks and or corruption of the
+ //document or output stream
+ Display.getDefault().asyncExec(new Runnable(){
+ public void run(){
+ if(isVisible()) {
+ try {
+ switch(type) {
+ case ConsoleDocument.COMMAND:
+ getCommandStream().write(line);
+ getCommandStream().write('\n');
+ break;
+ case ConsoleDocument.MESSAGE:
+ getMessageStream().write(line);
+ getMessageStream().write('\n');
+ break;
+ case ConsoleDocument.ERROR:
+ getErrorStream().write(line);
+ getErrorStream().write('\n');
+ break;
+ }
+ } catch(IOException ex) {
+ MavenLogger.log("Console error", ex);
+ }
+ } else {
+ getConsoleDocument().appendConsoleLine(type, line);
+ }
+ }
+ });
+ }
+
+ /**
+ * Show the console.
+ *
+ * @param showNoMatterWhat ignore preferences if <code>true</code>
+ */
+ public void show(boolean showNoMatterWhat) {
+ if(showNoMatterWhat) {
+ if(!isVisible()) {
+ showConsole();
+ } else {
+ ConsolePlugin.getDefault().getConsoleManager().showConsoleView(this);
+ }
+ }
+ }
+
+ public void showConsole() {
+ boolean exists = false;
+ IConsoleManager manager = ConsolePlugin.getDefault().getConsoleManager();
+ for(IConsole element : manager.getConsoles()) {
+ if(this == element) {
+ exists = true;
+ }
+ }
+ if(!exists) {
+ manager.addConsoles(new IConsole[] {this});
+ }
+ manager.showConsoleView(this);
+ }
+
+ public void closeConsole() {
+ IConsoleManager manager = ConsolePlugin.getDefault().getConsoleManager();
+ manager.removeConsoles(new IConsole[] {this});
+ ConsolePlugin.getDefault().getConsoleManager().addConsoleListener(this.newLifecycle());
+ }
+
+
+ public void propertyChange(PropertyChangeEvent event) {
+ // font changed
+ setFont(JFaceResources.getFontRegistry().get("pref_console_font")); //$NON-NLS-1$
+ }
+
+ private void bringConsoleToFront() {
+ if(PlatformUI.isWorkbenchRunning()) {
+ IConsoleManager manager = ConsolePlugin.getDefault().getConsoleManager();
+ if(!isVisible()) {
+ manager.addConsoles(new IConsole[] {this});
+ }
+ manager.showConsoleView(this);
+ }
+ }
+
+ // Called when console is removed from the console view
+ protected void dispose() {
+ // Here we can't call super.dispose() because we actually want the partitioner to remain
+ // connected, but we won't show lines until the console is added to the console manager
+ // again.
+ Display.getDefault().asyncExec(new Runnable(){
+ public void run(){
+ setVisible(false);
+ JFaceResources.getFontRegistry().removeListener(MavenConsoleImpl.this);
+ }
+ });
+ }
+
+ public void shutdown() {
+ // Call super dispose because we want the partitioner to be
+ // disconnected.
+ super.dispose();
+ if(commandColor != null) {
+ commandColor.dispose();
+ }
+ if(messageColor != null) {
+ messageColor.dispose();
+ }
+ if(errorColor != null) {
+ errorColor.dispose();
+ }
+ }
+
+ private DateFormat getDateFormat() {
+ return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, ULocale.getDefault());
+ }
+
+ // MavenConsole
+
+ public void logMessage(String message) {
+ if(showConsoleOnOutput()){
+ bringConsoleToFront();
+ }
+ appendLine(ConsoleDocument.MESSAGE, getDateFormat().format(new Date()) + ": " + message);
+
+ for(IMavenConsoleListener listener : listeners) {
+ try {
+ listener.loggingMessage(message);
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void logError(String message) {
+ if(showConsoleOnError()){
+ bringConsoleToFront();
+ }
+ appendLine(ConsoleDocument.ERROR, getDateFormat().format(new Date()) + ": " + message); //$NON-NLS-1$
+
+ for(IMavenConsoleListener listener : listeners) {
+ try {
+ listener.loggingError(message);
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public boolean showConsoleOnError(){
+ return M2EUIPluginActivator.getDefault().getPreferenceStore().getBoolean(MavenPreferenceConstants.P_SHOW_CONSOLE_ON_ERR);
+ }
+
+ public boolean showConsoleOnOutput(){
+ return M2EUIPluginActivator.getDefault().getPreferenceStore().getBoolean(MavenPreferenceConstants.P_SHOW_CONSOLE_ON_OUTPUT);
+ }
+ public IConsoleListener newLifecycle() {
+ return new MavenConsoleLifecycle();
+ }
+
+ /**
+ * @param commandStream The commandStream to set.
+ */
+ protected void setCommandStream(IOConsoleOutputStream commandStream) {
+ this.commandStream = commandStream;
+ }
+
+ /**
+ * @return Returns the commandStream.
+ */
+ protected IOConsoleOutputStream getCommandStream() {
+ return commandStream;
+ }
+
+ /**
+ * @param messageStream The messageStream to set.
+ */
+ protected void setMessageStream(IOConsoleOutputStream messageStream) {
+ this.messageStream = messageStream;
+ }
+
+ /**
+ * @return Returns the messageStream.
+ */
+ protected IOConsoleOutputStream getMessageStream() {
+ return messageStream;
+ }
+
+ /**
+ * @param errorStream The errorStream to set.
+ */
+ protected void setErrorStream(IOConsoleOutputStream errorStream) {
+ this.errorStream = errorStream;
+ }
+
+ /**
+ * @return Returns the errorStream.
+ */
+ protected IOConsoleOutputStream getErrorStream() {
+ return errorStream;
+ }
+
+ /**
+ * @param visible The visible to set.
+ */
+ protected void setVisible(boolean visible) {
+ this.visible = visible;
+ }
+
+ /**
+ * @return Returns the visible.
+ */
+ protected boolean isVisible() {
+ return visible;
+ }
+
+ /**
+ * @param consoleDocument The consoleDocument to set.
+ */
+ private void setConsoleDocument(ConsoleDocument consoleDocument) {
+ this.consoleDocument = consoleDocument;
+ }
+
+ /**
+ * @return Returns the consoleDocument.
+ */
+ protected ConsoleDocument getConsoleDocument() {
+ return consoleDocument;
+ }
+
+ /**
+ * Used to notify this console of lifecycle methods <code>init()</code> and <code>dispose()</code>.
+ */
+ public class MavenConsoleLifecycle implements org.eclipse.ui.console.IConsoleListener {
+
+ public void consolesAdded(IConsole[] consoles) {
+ for(int i = 0; i < consoles.length; i++ ) {
+ IConsole console = consoles[i];
+ if(console == MavenConsoleImpl.this) {
+ init();
+ }
+ }
+
+ }
+
+ public void consolesRemoved(IConsole[] consoles) {
+ for(int i = 0; i < consoles.length; i++ ) {
+ IConsole console = consoles[i];
+ if(console == MavenConsoleImpl.this) {
+ ConsolePlugin.getDefault().getConsoleManager().removeConsoleListener(this);
+ dispose();
+ }
+ }
+ }
+
+ }
+
+ public void addMavenConsoleListener(IMavenConsoleListener listener) {
+ listeners.remove(listener);
+ listeners.add(listener);
+ }
+
+ public void removeMavenConsoleListener(IMavenConsoleListener listener) {
+ listeners.remove(listener);
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsolePageParticipant.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsolePageParticipant.java
new file mode 100644
index 00000000..b6925116
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsolePageParticipant.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.internal.console;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.internal.preferences.MavenPreferenceConstants;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+import org.eclipse.m2e.core.ui.internal.actions.MavenConsoleRemoveAction;
+import org.eclipse.m2e.core.ui.internal.actions.MavenDebugOutputAction;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.console.IConsole;
+import org.eclipse.ui.console.IConsoleConstants;
+import org.eclipse.ui.console.IConsolePageParticipant;
+import org.eclipse.ui.part.IPageBookViewPage;
+
+
+
+public class MavenConsolePageParticipant implements IConsolePageParticipant {
+
+ private IAction consoleRemoveAction;
+ private IAction debugAction;
+ private IAction showOnErrorAction;
+ private IAction showOnOutputAction;
+
+ private static final String SHOW_ON_OUTPUT_LBL = Messages.MavenConsolePageParticipant_any;
+ private static final String SHOW_ON_ERR_LBL = Messages.MavenConsolePageParticipant_error;
+
+ public void init(IPageBookViewPage page, IConsole console) {
+ this.consoleRemoveAction = new MavenConsoleRemoveAction();
+ this.debugAction = new MavenDebugOutputAction();
+
+
+ showOnOutputAction = new ShowOnOutputAction(console, SHOW_ON_OUTPUT_LBL);
+ showOnErrorAction = new ShowOnErrorAction(console, SHOW_ON_ERR_LBL);
+
+ IActionBars actionBars = page.getSite().getActionBars();
+ configureToolBar(actionBars.getToolBarManager());
+ }
+
+ private void configureToolBar(IToolBarManager mgr){
+ mgr.appendToGroup(IConsoleConstants.LAUNCH_GROUP, consoleRemoveAction);
+ mgr.prependToGroup(IConsoleConstants.OUTPUT_GROUP, debugAction);
+ mgr.appendToGroup(IConsoleConstants.OUTPUT_GROUP, showOnOutputAction);
+ mgr.appendToGroup(IConsoleConstants.OUTPUT_GROUP, showOnErrorAction);
+ }
+ public void dispose() {
+ this.consoleRemoveAction = null;
+ this.debugAction = null;
+ }
+
+ public void activated() {
+ }
+
+ public void deactivated() {
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ return null;
+ }
+
+
+
+ class ShowOnErrorAction extends MavenShowConsoleAction{
+ public ShowOnErrorAction(IConsole console, String name){
+ super(name);
+ setImageDescriptor(MavenImages.SHOW_CONSOLE_ERR);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.MavenShowConsoleAction#getKey()
+ */
+ protected String getKey() {
+ return MavenPreferenceConstants.P_SHOW_CONSOLE_ON_ERR;
+ }
+ }
+
+ class ShowOnOutputAction extends MavenShowConsoleAction{
+
+ /**
+ * @param console
+ */
+ public ShowOnOutputAction(IConsole console, String name) {
+ super(name);
+ setImageDescriptor(MavenImages.SHOW_CONSOLE_OUT);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.MavenShowConsoleAction#getKey()
+ */
+ protected String getKey() {
+ return MavenPreferenceConstants.P_SHOW_CONSOLE_ON_OUTPUT;
+ }
+
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsoleService.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsoleService.java
new file mode 100644
index 00000000..86f6840b
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenConsoleService.java
@@ -0,0 +1,18 @@
+
+package org.eclipse.m2e.core.internal.console;
+
+import org.eclipse.m2e.core.core.MavenConsole;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+
+
+public class MavenConsoleService implements MavenConsole {
+
+ public void logMessage(String msg) {
+ M2EUIPluginActivator.getDefault().getMavenConsoleImpl().logMessage(msg);
+ }
+
+ public void logError(String msg) {
+ M2EUIPluginActivator.getDefault().getMavenConsoleImpl().logError(msg);
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenShowConsoleAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenShowConsoleAction.java
new file mode 100644
index 00000000..52f9e2d0
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/internal/console/MavenShowConsoleAction.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.internal.console;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+
+/**
+ * MavenShowConsoleAction
+ *
+ * @author dyocum
+ */
+public abstract class MavenShowConsoleAction extends Action implements IPropertyChangeListener{
+
+ public MavenShowConsoleAction(String name){
+ super(name, IAction.AS_CHECK_BOX);
+ setToolTipText(name);
+ getPreferenceStore().addPropertyChangeListener(this);
+ update();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ if (property.equals(getKey())) {
+ update();
+ }
+ }
+
+ protected abstract String getKey();
+
+ private void update() {
+ IPreferenceStore store = getPreferenceStore();
+ if (store.getBoolean(getKey())) {
+ // on
+ setChecked(true);
+ } else {
+ // off
+ setChecked(false);
+ }
+ }
+
+ /**
+ * @return
+ */
+ private IPreferenceStore getPreferenceStore() {
+ return M2EUIPluginActivator.getDefault().getPreferenceStore();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.action.Action#run()
+ */
+ public void run() {
+ IPreferenceStore store = getPreferenceStore();
+ boolean show = isChecked();
+ store.removePropertyChangeListener(this);
+ store.setValue(getKey(), show);
+ store.addPropertyChangeListener(this);
+ }
+
+ /**
+ * Must be called to dispose this action.
+ */
+ public void dispose() {
+ getPreferenceStore().removePropertyChangeListener(this);
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/M2EUIPluginActivator.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/M2EUIPluginActivator.java
new file mode 100644
index 00000000..e0b2e371
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/M2EUIPluginActivator.java
@@ -0,0 +1,69 @@
+
+package org.eclipse.m2e.core.ui.internal;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.internal.console.MavenConsoleImpl;
+import org.eclipse.m2e.core.ui.internal.search.util.IndexSearchEngine;
+import org.eclipse.m2e.core.ui.internal.search.util.SearchEngine;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+
+public class M2EUIPluginActivator extends AbstractUIPlugin {
+
+ private static M2EUIPluginActivator instance;
+
+ public M2EUIPluginActivator() {
+ M2EUIPluginActivator.instance = this;
+ }
+
+ private MavenConsoleImpl console;
+
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ }
+
+ public static M2EUIPluginActivator getDefault() {
+ return instance;
+ }
+
+ /**
+ * Returns an Image for the file at the given relative path.
+ */
+ public static Image getImage(String path) {
+ ImageRegistry registry = getDefault().getImageRegistry();
+ Image image = registry.get(path);
+ if(image == null) {
+ registry.put(path, imageDescriptorFromPlugin(IMavenConstants.PLUGIN_ID, path));
+ image = registry.get(path);
+ }
+ return image;
+ }
+
+ public static ImageDescriptor getImageDescriptor(String path) {
+ return imageDescriptorFromPlugin(IMavenConstants.PLUGIN_ID, path);
+ }
+
+ public synchronized MavenConsoleImpl getMavenConsoleImpl() {
+ if(console == null) {
+ console = new MavenConsoleImpl(MavenImages.M2);
+ }
+ return console;
+ }
+
+ public SearchEngine getSearchEngine(IProject project) throws CoreException {
+ return new IndexSearchEngine(MavenPlugin.getDefault().getIndexManager().getIndex(project));
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenAdapterFactory.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenAdapterFactory.java
new file mode 100644
index 00000000..b09ccb05
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenAdapterFactory.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.ui.IActionFilter;
+
+/**
+ * @author Eugene Kuleshov
+ */
+@SuppressWarnings("unchecked")
+public class MavenAdapterFactory implements IAdapterFactory {
+
+ private static final Class[] ADAPTER_TYPES = new Class[] { IActionFilter.class };
+
+ public Class[] getAdapterList() {
+ return ADAPTER_TYPES;
+ }
+
+ public Object getAdapter(final Object adaptable, Class adapterType) {
+ return new IActionFilter() {
+ public boolean testAttribute(Object target, String name, String value) {
+ return "label".equals(name) // //$NON-NLS-1$
+ && value.equals(getStub(adaptable, LabelProviderStub.class).getLabel());
+ }
+
+ private <T> T getStub(final Object o, Class<T> type) {
+ // can't use IWorkbenchAdapter here because it can cause recursion
+ return (T) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] {type}, //
+ new InvocationHandler() {
+ public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
+ try {
+ Method method = o.getClass().getDeclaredMethod(m.getName(), m.getParameterTypes());
+ return method.invoke(o, args);
+ } catch(RuntimeException ex) {
+ return null;
+ } catch(Exception ex) {
+ return null;
+ }
+ }
+ });
+ }
+ };
+ }
+
+ /**
+ * A stub interface to access org.eclipse.jdt.internal.ui.packageview.ClassPathContainer#getLabel()
+ */
+ public interface LabelProviderStub {
+ public String getLabel();
+ }
+
+}
+
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenImages.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenImages.java
new file mode 100644
index 00000000..cd6b5570
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenImages.java
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.viewers.DecorationOverlayIcon;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+
+/**
+ * @author Eugene Kuleshov
+ */
+public class MavenImages {
+
+ // object images
+
+ public static final Image IMG_CLEAR = createImage("clear.gif"); //$NON-NLS-1$
+
+ public static final Image IMG_CLEAR_DISABLED = createImage("clear_disabled.gif"); //$NON-NLS-1$
+
+ public static final String PATH_JAR = "jar_obj.gif"; //$NON-NLS-1$
+
+ public static final String PATH_PROJECT = "project_obj.gif"; //$NON-NLS-1$
+
+ public static final Image IMG_JAR = createImage(PATH_JAR);
+
+ public static final String PATH_LOCK = "lock_ovr.gif"; //$NON-NLS-1$
+
+ public static final String PATH_VERSION = "jar_version.gif"; //$NON-NLS-1$
+
+ public static final Image IMG_VERSION = createImage(PATH_VERSION);
+
+ public static final String PATH_VERSION_SRC = "jar_src_version.gif"; //$NON-NLS-1$
+
+ public static final Image IMG_VERSION_SRC = createImage(PATH_VERSION_SRC);
+
+ public static final Image IMG_JAVA = createImage("java_obj.gif"); //$NON-NLS-1$
+
+ public static final Image IMG_JAVA_SRC = createImage("java_src_obj.gif"); //$NON-NLS-1$
+
+ // public static final Image IMG_M2 = createImage("m2.gif");
+
+ public static final Image IMG_LAUNCH_MAIN = createImage("main_tab.gif"); //$NON-NLS-1$
+
+ public static final Image IMG_INDEX = createImage("maven_index.gif"); //$NON-NLS-1$
+
+ public static final Image IMG_INDEXES = createImage("maven_indexes.gif"); //$NON-NLS-1$
+
+ public static final Image IMG_MAVEN_JAR = createImage("mjar.gif"); //$NON-NLS-1$
+
+ // public static final Image IMG_JAR = createImage("mlabel.gif");
+
+ public static final Image IMG_NEW_POM = createImage("new_m2_pom.gif"); //$NON-NLS-1$
+
+ public static final Image IMG_NEW_PROJECT = createImage("new_m2_project.gif"); //$NON-NLS-1$
+
+ public static final Image IMG_OPEN_POM = createImage("open_pom.gif"); //$NON-NLS-1$
+
+ // public static final Image IMG_POM = createImage("pom_obj.gif");
+
+ public static final Image IMG_UPD_DEPENDENCIES = createImage("update_dependencies.gif"); //$NON-NLS-1$
+
+ public static final Image IMG_UPD_SOURCES = createImage("update_source_folders.gif"); //$NON-NLS-1$
+
+ public static final Image IMG_WEB = createImage("web.gif"); //$NON-NLS-1$
+
+ // wizard images
+
+ public static final ImageDescriptor WIZ_IMPORT_WIZ = createDescriptor("import_project.png"); //$NON-NLS-1$
+
+ public static final ImageDescriptor WIZ_NEW_PROJECT = createDescriptor("new_m2_project_wizard.gif"); //$NON-NLS-1$
+
+ // descriptors
+
+ public static final ImageDescriptor M2 = createDescriptor("m2.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor DEBUG = createDescriptor("debug.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor ADD_INDEX = createDescriptor("add_index.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor CLOSE = createDescriptor("close.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor COPY = createDescriptor("copy.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor COLLAPSE_ALL = createDescriptor("collapseall.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor EXPAND_ALL = createDescriptor("expandall.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor NEW_POM = createDescriptor("new_m2_pom.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor REFRESH = createDescriptor("refresh.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor UPD_INDEX = createDescriptor("update_index.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor REBUILD_INDEX = createDescriptor("rebuild_index.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor POM = createDescriptor("pom_obj.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor IMPORT_PROJECT = createDescriptor("import_m2_project.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor SHOW_CONSOLE_ERR = createDescriptor("stderr.gif"); //$NON-NLS-1$
+
+ public static final ImageDescriptor SHOW_CONSOLE_OUT = createDescriptor("stdout.gif"); //$NON-NLS-1$
+
+ private static ImageDescriptor createDescriptor(String key) {
+ try {
+ ImageRegistry imageRegistry = getImageRegistry();
+ if(imageRegistry != null) {
+ ImageDescriptor imageDescriptor = imageRegistry.getDescriptor(key);
+ if(imageDescriptor==null) {
+ imageDescriptor = doCreateDescriptor(key);
+ imageRegistry.put(key, imageDescriptor);
+ }
+ return imageDescriptor;
+ }
+ } catch(Exception ex) {
+ MavenLogger.log(key, ex);
+ }
+ return null;
+ }
+
+ private static Image createImage(String key) {
+ createDescriptor(key);
+ ImageRegistry imageRegistry = getImageRegistry();
+ return imageRegistry == null ? null : imageRegistry.get(key);
+ }
+
+ private static ImageRegistry getImageRegistry() {
+ M2EUIPluginActivator plugin = M2EUIPluginActivator.getDefault();
+ return plugin == null ? null : plugin.getImageRegistry();
+ }
+
+ private static ImageDescriptor doCreateDescriptor(String image) {
+ return AbstractUIPlugin.imageDescriptorFromPlugin(IMavenConstants.PLUGIN_ID, "icons/" + image); //$NON-NLS-1$
+ }
+
+
+
+ private static ImageDescriptor createImageDescriptor( String key, ImageData imageData )
+ {
+ try
+ {
+ ImageRegistry imageRegistry = getImageRegistry();
+ if ( imageRegistry != null )
+ {
+ ImageDescriptor imageDescriptor = imageRegistry.getDescriptor( key );
+ if ( imageDescriptor != null )
+ {
+ imageRegistry.remove( key );
+ }
+ {
+ imageDescriptor = ImageDescriptor.createFromImageData( imageData );
+ imageRegistry.put( key, imageDescriptor );
+ }
+ return imageDescriptor;
+ }
+ }
+ catch ( Exception ex )
+ {
+ MavenLogger.log(key, ex);
+ }
+ return null;
+ }
+
+ private static ImageDescriptor getOverlayImageDescriptor( String basekey, String overlaykey, int quadrant )
+ {
+ String key = basekey + overlaykey;
+ try
+ {
+ ImageRegistry imageRegistry = getImageRegistry();
+ if ( imageRegistry != null )
+ {
+ ImageDescriptor imageDescriptor = imageRegistry.getDescriptor( key );
+ if ( imageDescriptor == null )
+ {
+ ImageDescriptor base = createDescriptor( basekey );
+ ImageDescriptor overlay = createDescriptor( overlaykey );
+ if ( base == null || overlay == null )
+ {
+ MavenLogger.log( "cannot construct overlay image descriptor for " + basekey + " " + overlaykey );
+ return null;
+ }
+ imageDescriptor = createOverlayDescriptor( base, overlay, quadrant );
+ imageRegistry.put( key, imageDescriptor );
+ }
+ return imageDescriptor;
+ }
+ }
+ catch ( Exception ex )
+ {
+ MavenLogger.log(key, ex);
+ }
+ return null;
+ }
+
+ public static Image getOverlayImage( String base, String overlay, int quadrant )
+ {
+ getOverlayImageDescriptor( base, overlay, quadrant );
+ ImageRegistry imageRegistry = getImageRegistry();
+ return imageRegistry == null ? null : imageRegistry.get( base + overlay );
+ }
+
+
+ private static ImageDescriptor createOverlayDescriptor( ImageDescriptor base, ImageDescriptor overlay, int quadrant )
+ {
+ return new DecorationOverlayIcon( base.createImage(), overlay, quadrant );
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenVersionDecorator.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenVersionDecorator.java
new file mode 100644
index 00000000..9b462c54
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/MavenVersionDecorator.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.project.IMavenProjectChangedListener;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.MavenProjectChangedEvent;
+import org.eclipse.m2e.core.project.MavenProjectManager;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * @author Eugene Kuleshov
+ */
+public class MavenVersionDecorator implements ILabelDecorator {
+
+ private Map<ILabelProviderListener, IMavenProjectChangedListener> listeners = new HashMap<ILabelProviderListener, IMavenProjectChangedListener>();
+
+ public Image decorateImage(Image image, Object element) {
+ return null;
+ }
+
+ public String decorateText(String text, Object element) {
+ if(element instanceof IResource) {
+ IResource resource = (IResource) element;
+ IProject project = resource.getProject();
+ if(project!=null) {
+ MavenProjectManager projectManager = MavenPlugin.getDefault().getMavenProjectManager();
+ IMavenProjectFacade facade = projectManager.create(project, new NullProgressMonitor());
+ if(facade!=null) {
+ ArtifactKey mavenProject = facade.getArtifactKey();
+ if(mavenProject!=null) {
+ String name = resource.getName();
+ int start = text.indexOf(name);
+ if(start>-1) {
+ int n = text.indexOf(' ', start + name.length());
+ if(n>-1) {
+ return text.substring(0, n) + " " + mavenProject.getVersion() + text.substring(n); //$NON-NLS-1$
+ }
+ }
+ return text + " " + mavenProject.getVersion(); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ public void addListener(final ILabelProviderListener listener) {
+ IMavenProjectChangedListener projectChangeListener = new IMavenProjectChangedListener() {
+ public void mavenProjectChanged(MavenProjectChangedEvent[] events, IProgressMonitor monitor) {
+ ArrayList<IResource> pomList = new ArrayList<IResource>();
+ for(int i = 0; i < events.length; i++ ) {
+ // pomList.add(events[i].getSource());
+ if(events[i]!=null && events[i].getMavenProject()!=null) {
+ IFile pom = events[i].getMavenProject().getPom();
+ pomList.add(pom);
+ if(pom.getParent().getType()==IResource.PROJECT) {
+ pomList.add(pom.getParent());
+ }
+ }
+ }
+ listener.labelProviderChanged(new LabelProviderChangedEvent(MavenVersionDecorator.this, pomList.toArray()));
+ }
+ };
+
+ listeners.put(listener, projectChangeListener);
+
+ MavenProjectManager projectManager = MavenPlugin.getDefault().getMavenProjectManager();
+ projectManager.addMavenProjectChangedListener(projectChangeListener);
+ }
+
+ public void removeListener(ILabelProviderListener listener) {
+ IMavenProjectChangedListener projectChangeListener = listeners.get(listener);
+ if(projectChangeListener!=null) {
+ MavenProjectManager projectManager = MavenPlugin.getDefault().getMavenProjectManager();
+ projectManager.removeMavenProjectChangedListener(projectChangeListener);
+ }
+ }
+
+ public void dispose() {
+ // TODO remove all listeners
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/UpdateConfigurationJob.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/UpdateConfigurationJob.java
new file mode 100644
index 00000000..3fa93c07
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/UpdateConfigurationJob.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.WorkspaceJob;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.progress.IProgressConstants;
+
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenConsole;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.ui.internal.actions.OpenMavenConsoleAction;
+import org.eclipse.m2e.core.ui.internal.util.M2EUIUtils;
+
+
+public class UpdateConfigurationJob extends WorkspaceJob {
+
+ private IProject[] projects;
+
+ private MavenPlugin plugin;
+
+ private Shell shell;
+
+ public UpdateConfigurationJob(MavenPlugin plugin, IProject[] projects) {
+ this(plugin, projects, null);
+ }
+
+ public UpdateConfigurationJob(MavenPlugin plugin, IProject[] projects, Shell shell) {
+ this(plugin, shell);
+ this.projects = projects;
+ }
+
+ private UpdateConfigurationJob(MavenPlugin plugin, Shell shell) {
+ super(Messages.UpdateSourcesAction_job_update_conf);
+ this.plugin = plugin;
+ this.shell = shell;
+ setRule(this.plugin.getProjectConfigurationManager().getRule());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.resources.WorkspaceJob#runInWorkspace(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public IStatus runInWorkspace(IProgressMonitor monitor) {
+ setProperty(IProgressConstants.ACTION_PROPERTY, new OpenMavenConsoleAction());
+ monitor.beginTask(getName(), projects.length);
+
+ MavenConsole console = plugin.getConsole();
+
+ long l1 = System.currentTimeMillis();
+ console.logMessage("Update started");
+
+ MultiStatus status = null;
+ //project names to the errors encountered when updating them
+ Map<String, Throwable> updateErrors = new HashMap<String, Throwable>();
+
+ for(IProject project : projects) {
+ if(monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+
+ monitor.subTask(project.getName());
+ IMavenProjectFacade projectFacade = plugin.getMavenProjectManager().create(project, monitor);
+ if(projectFacade != null) {
+ try {
+ plugin.getProjectConfigurationManager().updateProjectConfiguration(project, //
+ new SubProgressMonitor(monitor, 1));
+ } catch(CoreException ex) {
+ if(status == null) {
+ status = new MultiStatus(IMavenConstants.PLUGIN_ID, IStatus.ERROR, //
+ Messages.UpdateSourcesAction_error_cannot_update, null);
+ }
+ status.add(ex.getStatus());
+ updateErrors.put(project.getName(), ex);
+ } catch(IllegalArgumentException e) {
+ status = new MultiStatus(IMavenConstants.PLUGIN_ID, IStatus.ERROR, //
+ Messages.UpdateSourcesAction_error_cannot_update, null);
+ updateErrors.put(project.getName(), e);
+ }
+ }
+ }
+ if(updateErrors.size() > 0) {
+ handleErrors(updateErrors);
+ }
+ long l2 = System.currentTimeMillis();
+ console.logMessage(NLS.bind("Update completed: {0} sec", ((l2 - l1) / 1000)));
+
+ return status != null ? status : Status.OK_STATUS;
+ }
+
+ private void handleErrors(final Map<String, Throwable> updateErrors) {
+ final Display display = Display.getDefault();
+ if(display != null) {
+ display.asyncExec(new Runnable() {
+
+ public void run() {
+ M2EUIUtils.showErrorsForProjectsDialog(shell != null ? shell : display.getActiveShell(),
+ Messages.UpdateSourcesAction_error_title, Messages.UpdateSourcesAction_error_message, updateErrors);
+ }
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/AddDependencyAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/AddDependencyAction.java
new file mode 100644
index 00000000..fdc8390d
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/AddDependencyAction.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import org.apache.maven.model.Dependency;
+import org.apache.maven.project.MavenProject;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.embedder.MavenModelManager;
+import org.eclipse.m2e.core.index.IndexedArtifactFile;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.ui.internal.dialogs.MavenRepositorySearchDialog;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+
+public class AddDependencyAction extends MavenActionSupport implements IWorkbenchWindowActionDelegate {
+
+ public static final String ID = "org.eclipse.m2e.addDependencyAction"; //$NON-NLS-1$
+
+ public void run(IAction action) {
+ IFile file = getPomFileFromPomEditorOrViewSelection();
+
+ if(file == null) {
+ return;
+ }
+
+ MavenPlugin plugin = MavenPlugin.getDefault();
+ MavenProject mp = null;
+ IProject prj = file.getProject();
+ if (prj != null && IMavenConstants.POM_FILE_NAME.equals(file.getProjectRelativePath().toString())) {
+ IMavenProjectFacade facade = MavenPlugin.getDefault().getMavenProjectManager().getProject(prj);
+ if (facade != null) {
+ mp = facade.getMavenProject();
+ }
+ }
+
+ MavenRepositorySearchDialog dialog = MavenRepositorySearchDialog.createSearchDependencyDialog(getShell(), Messages.AddDependencyAction_searchDialog_title, mp, prj, false);
+ if(dialog.open() == Window.OK) {
+ IndexedArtifactFile indexedArtifactFile = (IndexedArtifactFile) dialog.getFirstResult();
+ if(indexedArtifactFile != null) {
+ try {
+ MavenModelManager modelManager = plugin.getMavenModelManager();
+ Dependency dependency = indexedArtifactFile.getDependency();
+ String selectedScope = dialog.getSelectedScope();
+ dependency.setScope(selectedScope);
+
+ if (indexedArtifactFile.version == null) {
+ dependency.setVersion(null);
+ }
+
+ modelManager.addDependency(file, dependency);
+ } catch(Exception ex) {
+ String msg = NLS.bind(Messages.AddDependencyAction_error_msg, file);
+ MavenLogger.log(msg, ex);
+ MessageDialog.openError(Display.getCurrent().getActiveShell(), Messages.AddDependencyAction_error_title, msg);
+ }
+ }
+ }
+ }
+
+ public void dispose() {
+ }
+
+ public void init(IWorkbenchWindow window) {
+ }
+ }
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/AddPluginAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/AddPluginAction.java
new file mode 100644
index 00000000..aa08b1fb
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/AddPluginAction.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import org.apache.maven.project.MavenProject;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.window.Window;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.embedder.MavenModelManager;
+import org.eclipse.m2e.core.index.IndexedArtifactFile;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.ui.internal.dialogs.MavenRepositorySearchDialog;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+
+public class AddPluginAction extends MavenActionSupport implements IWorkbenchWindowActionDelegate {
+
+ public static final String ID = "org.eclipse.m2e.addPluginAction"; //$NON-NLS-1$
+
+ public void run(IAction action) {
+ IFile file = getPomFileFromPomEditorOrViewSelection();
+
+ if(file == null) {
+ return;
+ }
+ MavenProject mp = null;
+ IProject prj = file.getProject();
+ if (prj != null && IMavenConstants.POM_FILE_NAME.equals(file.getProjectRelativePath().toString())) {
+ IMavenProjectFacade facade = MavenPlugin.getDefault().getMavenProjectManager().getProject(prj);
+ if (facade != null) {
+ mp = facade.getMavenProject();
+ }
+ }
+
+
+ MavenRepositorySearchDialog dialog = MavenRepositorySearchDialog.createSearchPluginDialog(getShell(), Messages.AddPluginAction_searchDialog_title,
+ mp, prj, false);
+ if(dialog.open() == Window.OK) {
+ final IndexedArtifactFile indexedArtifactFile = (IndexedArtifactFile) dialog.getFirstResult();
+ if(indexedArtifactFile != null) {
+ try {
+ MavenModelManager modelManager = MavenPlugin.getDefault().getMavenModelManager();
+ modelManager.updateProject(file, new MavenModelManager.PluginAdder( //
+ indexedArtifactFile.group, //
+ indexedArtifactFile.artifact, //
+ indexedArtifactFile.version));
+ } catch(Exception ex) {
+ MavenLogger.log("Can't add plugin to " + file, ex);
+ }
+ }
+ }
+ }
+
+ public void dispose() {
+ }
+
+ public void init(IWorkbenchWindow window) {
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/ChangeNatureAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/ChangeNatureAction.java
new file mode 100644
index 00000000..027ca97e
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/ChangeNatureAction.java
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.WorkspaceJob;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.embedder.IMavenConfiguration;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.IProjectConfigurationManager;
+import org.eclipse.m2e.core.project.MavenProjectManager;
+import org.eclipse.m2e.core.project.MavenUpdateRequest;
+import org.eclipse.m2e.core.project.ResolverConfiguration;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+
+
+public class ChangeNatureAction implements IObjectActionDelegate, IExecutableExtension {
+
+ public static final String ID_ENABLE_WORKSPACE = "org.eclipse.m2e.enableWorkspaceResolutionAction"; //$NON-NLS-1$
+
+ public static final String ID_DISABLE_WORKSPACE = "org.eclipse.m2e.disableWorkspaceResolutionAction"; //$NON-NLS-1$
+
+ public static final int ENABLE_WORKSPACE = 1;
+
+ public static final int DISABLE_WORKSPACE = 2;
+
+ private ISelection selection;
+
+ private int option;
+
+ public ChangeNatureAction() {
+ this(ENABLE_WORKSPACE);
+ }
+
+ public ChangeNatureAction(int option) {
+ this.option = option;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
+ */
+ public void setInitializationData(IConfigurationElement config, String propertyName, Object data) {
+ if (data != null) {
+ if ("enableWorkspaceResolution".equals(data)) {//$NON-NLS-1$
+ option = ENABLE_WORKSPACE;
+ }
+ if ("disableWorkspaceResolution".equals(data)) {//$NON-NLS-1$
+ option = DISABLE_WORKSPACE;
+ }
+ }
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ this.selection = selection;
+ }
+
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ }
+
+ public void run(IAction action) {
+ if(selection instanceof IStructuredSelection) {
+ IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+ Set<IProject> projects = new LinkedHashSet<IProject>();
+ for(Iterator<?> it = structuredSelection.iterator(); it.hasNext();) {
+ Object element = it.next();
+ IProject project = null;
+ if(element instanceof IProject) {
+ project = (IProject) element;
+ } else if(element instanceof IAdaptable) {
+ project = (IProject) ((IAdaptable) element).getAdapter(IProject.class);
+ }
+ if(project != null) {
+ projects.add(project);
+ }
+ }
+
+ new UpdateJob(projects, option).schedule();
+ }
+ }
+
+ static class UpdateJob extends WorkspaceJob {
+ private final Set<IProject> projects;
+ private final int option;
+
+ private final IProjectConfigurationManager importManager;
+ private final MavenProjectManager projectManager;
+ private final IMavenConfiguration mavenConfiguration;
+
+ public UpdateJob(Set<IProject> projects, int option) {
+ super(Messages.ChangeNatureAction_job_changing);
+ this.projects = projects;
+ this.option = option;
+
+ MavenPlugin plugin = MavenPlugin.getDefault();
+ this.importManager = plugin.getProjectConfigurationManager();
+ this.projectManager = plugin.getMavenProjectManager();
+
+ this.mavenConfiguration = MavenPlugin.getDefault().getMavenConfiguration();
+ }
+
+ public IStatus runInWorkspace(IProgressMonitor monitor) {
+ MultiStatus status = null;
+ for(IProject project : projects) {
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+
+ monitor.subTask(project.getName());
+
+ try {
+ changeNature(project, monitor);
+ } catch (CoreException ex) {
+ if (status == null) {
+ status = new MultiStatus(IMavenConstants.PLUGIN_ID, IStatus.ERROR, Messages.ChangeNatureAction_status_error, null);
+ }
+ status.add(ex.getStatus());
+ }
+ }
+
+ boolean offline = mavenConfiguration.isOffline();
+ boolean updateSnapshots = false;
+ projectManager.refresh(new MavenUpdateRequest(projects.toArray(new IProject[projects.size()]), //
+ offline, updateSnapshots));
+
+ return status != null? status: Status.OK_STATUS;
+ }
+
+ private void changeNature(final IProject project, IProgressMonitor monitor) throws CoreException {
+ MavenPlugin plugin = MavenPlugin.getDefault();
+ MavenProjectManager projectManager = plugin.getMavenProjectManager();
+
+ final ResolverConfiguration configuration = projectManager.getResolverConfiguration(project);
+
+ boolean updateSourceFolders = false;
+
+ switch(option) {
+ case ENABLE_WORKSPACE:
+ configuration.setResolveWorkspaceProjects(true);
+ break;
+ case DISABLE_WORKSPACE:
+ configuration.setResolveWorkspaceProjects(false);
+ break;
+ }
+
+ projectManager.setResolverConfiguration(project, configuration);
+
+ if (updateSourceFolders) {
+ importManager.updateProjectConfiguration(project, monitor);
+ }
+ }
+ }
+
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/CheckoutAsMavenAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/CheckoutAsMavenAction.java
new file mode 100644
index 00000000..f6bf95d2
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/CheckoutAsMavenAction.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import java.util.Iterator;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.m2e.core.ui.internal.wizards.MavenCheckoutWizard;
+import org.eclipse.m2e.scm.ScmUrl;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+
+
+/**
+ * Checkout as Maven project action
+ *
+ * @author @author Eugene Kuleshov
+ */
+public class CheckoutAsMavenAction implements IObjectActionDelegate {
+
+ private IStructuredSelection selection;
+ private IWorkbenchPart targetPart;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.actions.ActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ if (selection instanceof IStructuredSelection) {
+ this.selection = (IStructuredSelection) selection;
+ }
+ }
+
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ this.targetPart = targetPart;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.actions.ActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ public void run(IAction action) {
+ ScmUrl[] urls = null;
+ if(selection != null) {
+ urls = new ScmUrl[selection.size()];
+ int i = 0;
+ for(Iterator<?> it = selection.iterator(); it.hasNext();) {
+ urls[i++] = (ScmUrl) it.next();
+ }
+ }
+
+ MavenCheckoutWizard wizard = new MavenCheckoutWizard(urls);
+ WizardDialog dialog = new WizardDialog(getShell(), wizard);
+ dialog.open();
+ }
+
+ protected Shell getShell() {
+ Shell shell = null;
+ if(targetPart != null) {
+ shell = targetPart.getSite().getShell();
+ }
+ if(shell != null) {
+ return shell;
+ }
+
+ IWorkbench workbench = M2EUIPluginActivator.getDefault().getWorkbench();
+ if(workbench == null) {
+ return null;
+ }
+
+ IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
+ return window == null ? null : window.getShell();
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/DisableNatureAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/DisableNatureAction.java
new file mode 100644
index 00000000..f3d01f2e
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/DisableNatureAction.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+
+
+public class DisableNatureAction implements IObjectActionDelegate {
+ public static final String ID = "org.eclipse.m2e.disableAction"; //$NON-NLS-1$
+
+ private ISelection selection;
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ public void run(IAction action) {
+ if(selection instanceof IStructuredSelection) {
+ IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+ for(Iterator<?> it = structuredSelection.iterator(); it.hasNext();) {
+ Object element = it.next();
+ IProject project = null;
+ if(element instanceof IProject) {
+ project = (IProject) element;
+ } else if(element instanceof IAdaptable) {
+ project = (IProject) ((IAdaptable) element).getAdapter(IProject.class);
+ }
+ if(project != null) {
+ MavenPlugin plugin = MavenPlugin.getDefault();
+
+ try {
+ plugin.getProjectConfigurationManager().disableMavenNature(project, new NullProgressMonitor());
+
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ this.selection = selection;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction,
+ * org.eclipse.ui.IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/EnableNatureAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/EnableNatureAction.java
new file mode 100644
index 00000000..ec97c63b
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/EnableNatureAction.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.IProjectConfigurationManager;
+import org.eclipse.m2e.core.project.ResolverConfiguration;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.m2e.core.ui.internal.wizards.MavenPomWizard;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPart;
+
+
+public class EnableNatureAction implements IObjectActionDelegate, IExecutableExtension {
+
+ public static final String ID = "org.eclipse.m2e.enableNatureAction"; //$NON-NLS-1$
+
+ static final String ID_WORKSPACE = "org.eclipse.m2e.enableWorkspaceResolutionAction"; //$NON-NLS-1$
+
+ static final String ID_MODULES = "org.eclipse.m2e.enableModulesAction"; //$NON-NLS-1$
+
+ private boolean workspaceProjects = true;
+
+ private ISelection selection;
+
+ public EnableNatureAction() {
+ }
+
+ public EnableNatureAction(String option) {
+ setInitializationData(null, null, option);
+ }
+
+ public void setInitializationData(IConfigurationElement config, String propertyName, Object data) {
+ if(IMavenConstants.NO_WORKSPACE_PROJECTS.equals(data)) {
+ this.workspaceProjects = false;
+ }
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ this.selection = selection;
+ }
+
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ }
+
+ public void run(IAction action) {
+ if(selection instanceof IStructuredSelection) {
+ IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+ for(Iterator<?> it = structuredSelection.iterator(); it.hasNext();) {
+ Object element = it.next();
+ IProject project = null;
+ if(element instanceof IProject) {
+ project = (IProject) element;
+ } else if(element instanceof IAdaptable) {
+ project = (IProject) ((IAdaptable) element).getAdapter(IProject.class);
+ }
+ if(project != null) {
+ enableNature(project, structuredSelection.size() == 1);
+ }
+ }
+ }
+ }
+
+ private void enableNature(final IProject project, boolean isSingle) {
+ final M2EUIPluginActivator plugin = M2EUIPluginActivator.getDefault();
+ IFile pom = project.getFile(IMavenConstants.POM_FILE_NAME);
+ if(isSingle && !pom.exists()) {
+ // XXX move into AbstractProjectConfigurator and use Eclipse project settings
+ IWorkbench workbench = plugin.getWorkbench();
+
+ MavenPomWizard wizard = new MavenPomWizard();
+ wizard.init(workbench, (IStructuredSelection) selection);
+
+ Shell shell = workbench.getActiveWorkbenchWindow().getShell();
+ WizardDialog wizardDialog = new WizardDialog(shell, wizard);
+ wizardDialog.create();
+ wizardDialog.getShell().setText(Messages.EnableNatureAction_wizard_shell);
+ if(wizardDialog.open() == Window.CANCEL) {
+ return;
+ }
+ }
+ Job job = new Job(Messages.EnableNatureAction_job_enable) {
+
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ ResolverConfiguration configuration = new ResolverConfiguration();
+ configuration.setResolveWorkspaceProjects(workspaceProjects);
+ configuration.setActiveProfiles(""); //$NON-NLS-1$
+
+ boolean hasMavenNature = project.hasNature(IMavenConstants.NATURE_ID);
+
+ IProjectConfigurationManager configurationManager = MavenPlugin.getDefault().getProjectConfigurationManager();
+
+ configurationManager.enableMavenNature(project, configuration, new NullProgressMonitor());
+
+ if(!hasMavenNature) {
+ configurationManager.updateProjectConfiguration(project, monitor);
+ }
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ job.schedule();
+
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MaterializeAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MaterializeAction.java
new file mode 100644
index 00000000..5f11bb52
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MaterializeAction.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import org.apache.maven.model.Dependency;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.m2e.core.ui.internal.wizards.MavenMaterializePomWizard;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.PlatformUI;
+
+
+public class MaterializeAction implements IObjectActionDelegate {
+
+ public static final String ID = "org.eclipse.m2e.materializeAction"; //$NON-NLS-1$
+
+ private IStructuredSelection selection;
+
+ public void run(IAction action) {
+ MavenMaterializePomWizard wizard = new MavenMaterializePomWizard();
+ wizard.init(PlatformUI.getWorkbench(), selection);
+
+ Dependency[] dependencies = wizard.getDependencies();
+ if(dependencies!=null && dependencies.length>0) {
+ WizardDialog dialog = new WizardDialog(Display.getCurrent().getActiveShell(), wizard);
+ dialog.open();
+ } else {
+ // TODO show info dialog
+ }
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ if(selection instanceof IStructuredSelection) {
+ this.selection = (IStructuredSelection) selection;
+ } else {
+ this.selection = null;
+ }
+ }
+
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenActionSupport.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenActionSupport.java
new file mode 100644
index 00000000..b7fc256e
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenActionSupport.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.embedder.ArtifactRef;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.MavenProjectManager;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ *
+ * MavenActionSupport
+ *
+ * @author Jason van Zyl
+ */
+public abstract class MavenActionSupport implements IObjectActionDelegate {
+ protected IStructuredSelection selection;
+
+ protected IWorkbenchPart targetPart;
+
+ protected Set<ArtifactKey> getArtifacts(IFile file, MavenPlugin plugin) {
+ try {
+ MavenProjectManager projectManager = plugin.getMavenProjectManager();
+ //TODO: mkleint: this is a bit troubling as it can take considerate amount of time
+ // and it's being called in action's run() before the search dialog appearing.
+ IMavenProjectFacade projectFacade = projectManager.create(file, true, new NullProgressMonitor());
+ if(projectFacade != null) {
+ return ArtifactRef.toArtifactKey(projectFacade.getMavenProjectArtifacts());
+ }
+ } catch(Exception ex) {
+ String msg = "Can't read Maven project";
+ MavenLogger.log(msg, ex);
+ plugin.getConsole().logError(msg + "; " + ex.toString());
+ }
+ return Collections.emptySet();
+ }
+
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ this.targetPart = targetPart;
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ if(selection instanceof IStructuredSelection) {
+ this.selection = (IStructuredSelection) selection;
+ }
+ }
+
+ protected Shell getShell() {
+ Shell shell = null;
+ if(targetPart != null) {
+ shell = targetPart.getSite().getShell();
+ }
+ if(shell != null) {
+ return shell;
+ }
+
+ IWorkbench workbench = M2EUIPluginActivator.getDefault().getWorkbench();
+ if(workbench == null) {
+ return null;
+ }
+
+ IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
+ return window == null ? null : window.getShell();
+ }
+
+ protected IFile getPomFileFromPomEditorOrViewSelection() {
+ IFile file = null;
+ //
+ // If I am in the POM editor I want to get hold of the IFile that is currently in the buffer
+ //
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+
+ if(window != null) {
+ IWorkbenchPage page = window.getActivePage();
+ if(page != null) {
+ IEditorPart editor = page.getActiveEditor();
+ if(editor != null) {
+ IEditorInput input = editor.getEditorInput();
+ if(input instanceof IFileEditorInput) {
+ IFileEditorInput fileInput = (IFileEditorInput) input;
+ file = fileInput.getFile();
+ if(file.getName().equals(IMavenConstants.POM_FILE_NAME)) {
+ return file;
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Otherwise we will assume a pom.xml file or IProject is being selected in the
+ // package explorer and we'll get the IFile from that. Otherwise we'll bail.
+ //
+ Object o = selection.iterator().next();
+
+ if(o instanceof IProject) {
+ file = ((IProject) o).getFile(IMavenConstants.POM_FILE_NAME);
+ } else if(o instanceof IFile) {
+ file = (IFile) o;
+ } else {
+ file = null;
+ }
+
+ return file;
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenConsoleRemoveAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenConsoleRemoveAction.java
new file mode 100644
index 00000000..6cea8f2a
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenConsoleRemoveAction.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+
+
+public class MavenConsoleRemoveAction extends Action {
+
+ public MavenConsoleRemoveAction() {
+ setToolTipText(Messages.MavenConsoleRemoveAction_tooltip);
+ setImageDescriptor(MavenImages.CLOSE);
+ }
+
+ public void run() {
+ M2EUIPluginActivator.getDefault().getMavenConsoleImpl().closeConsole();
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenDebugOutputAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenDebugOutputAction.java
new file mode 100644
index 00000000..ca71dffb
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenDebugOutputAction.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.internal.preferences.MavenPreferenceConstants;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+
+
+/**
+ * @author Eugene Kuleshov
+ */
+public class MavenDebugOutputAction extends Action {
+
+ private IPropertyChangeListener listener = new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ if(MavenPreferenceConstants.P_DEBUG_OUTPUT.equals(event.getProperty())) {
+ setChecked(isDebug());
+ }
+ }
+ };
+
+ public MavenDebugOutputAction() {
+ setToolTipText(Messages.MavenDebugOutputAction_0);
+ setImageDescriptor(MavenImages.DEBUG);
+
+ getPreferenceStore().addPropertyChangeListener(listener);
+ setChecked(isDebug());
+ }
+
+ public void run() {
+ getPreferenceStore().setValue(MavenPreferenceConstants.P_DEBUG_OUTPUT, isChecked());
+ }
+
+ public void dispose() {
+ getPreferenceStore().removePropertyChangeListener(listener);
+ }
+
+ IPreferenceStore getPreferenceStore() {
+ return M2EUIPluginActivator.getDefault().getPreferenceStore();
+ }
+
+ boolean isDebug() {
+ return getPreferenceStore().getBoolean(MavenPreferenceConstants.P_DEBUG_OUTPUT);
+ }
+
+}
+
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenPropertyTester.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenPropertyTester.java
new file mode 100644
index 00000000..7631b089
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/MavenPropertyTester.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.MavenProjectManager;
+import org.eclipse.m2e.core.project.ResolverConfiguration;
+
+/**
+ * Helper IPropertyTester implementation to check if receiver can be launched with Maven.
+ * E.g. it is pom.xml file of folder or project that has pom.xml.
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenPropertyTester extends PropertyTester {
+
+
+ private static final String WORKSPACE_RESULUTION_ENABLE = "workspaceResulutionEnable";
+ private static final String LAUNCHABLE = "launchable";
+
+ public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
+ if (LAUNCHABLE.equals(property)) {
+ IAdaptable adaptable = (IAdaptable) receiver;
+
+ IProject projectAdapter = (IProject) adaptable.getAdapter(IProject.class);
+ if(projectAdapter!=null) {
+ return projectAdapter.getFile(IMavenConstants.POM_FILE_NAME).exists();
+ }
+
+ IFolder folderAdapter = (IFolder) adaptable.getAdapter(IFolder.class);
+ if(folderAdapter!=null) {
+ return folderAdapter.getFile(IMavenConstants.POM_FILE_NAME).exists();
+ }
+
+ IFile fileAdapter = (IFile) adaptable.getAdapter(IFile.class);
+ if(fileAdapter!=null) {
+ return fileAdapter.exists() && IMavenConstants.POM_FILE_NAME.equals(fileAdapter.getName());
+ }
+ return false;
+ }
+ if (WORKSPACE_RESULUTION_ENABLE.equals(property)) {
+ boolean enableWorkspaceResolution = true;
+ IAdaptable adaptable = (IAdaptable) receiver;
+
+ IProject projectAdapter = (IProject) adaptable.getAdapter(IProject.class);
+ if(projectAdapter!=null) {
+ MavenProjectManager projectManager = MavenPlugin.getDefault().getMavenProjectManager();
+ IMavenProjectFacade projectFacade = projectManager.create(projectAdapter, new NullProgressMonitor());
+ if(projectFacade != null) {
+ ResolverConfiguration configuration = projectFacade.getResolverConfiguration();
+ return !configuration.shouldResolveWorkspaceProjects();
+ }
+ }
+ return enableWorkspaceResolution;
+ }
+
+ if ("hasArtifactKey".equals(property)) {
+ ArtifactKey ak = SelectionUtil.getType(receiver, ArtifactKey.class);
+ return ak != null;
+ }
+ if ("hasProjectArtifactKey".equals(property)) {
+ ArtifactKey key = SelectionUtil.getType(receiver, ArtifactKey.class);
+ if(key != null) {
+ MavenProjectManager projectManager = MavenPlugin.getDefault().getMavenProjectManager();
+ IMavenProjectFacade mavenProject = null;
+ mavenProject = projectManager.getMavenProject( //
+ key.getGroupId(), key.getArtifactId(), key.getVersion());
+ return mavenProject != null;
+ }
+ }
+
+ return false;
+
+ }
+
+}
+
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/ModuleProjectWizardAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/ModuleProjectWizardAction.java
new file mode 100644
index 00000000..396fc450
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/ModuleProjectWizardAction.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.m2e.core.ui.internal.wizards.MavenModuleWizard;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * A module project wizard action.
+ */
+public class ModuleProjectWizardAction implements IObjectActionDelegate {
+
+ /** action id */
+ public static final String ID =
+ "org.eclipse.m2e.actions.moduleProjectWizardAction"; //$NON-NLS-1$
+
+ /** the current selection */
+ private IStructuredSelection selection;
+
+ /** parent shell */
+ private Shell parent;
+
+ /** Runs the action. */
+ public void run( IAction action ) {
+ MavenModuleWizard wizard = new MavenModuleWizard();
+ wizard.init( PlatformUI.getWorkbench(), selection );
+ WizardDialog dialog = new WizardDialog( parent, wizard );
+ dialog.open();
+ }
+
+
+ /** Sets the active workbench part. */
+ public void setActivePart( IAction action, IWorkbenchPart part ) {
+ parent = part.getSite().getShell();
+ }
+
+
+ /** Handles the selection change */
+ public void selectionChanged( IAction action, ISelection selection ) {
+ if( selection instanceof IStructuredSelection ) {
+ this.selection = ( IStructuredSelection ) selection;
+ }
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/OpenMavenConsoleAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/OpenMavenConsoleAction.java
new file mode 100644
index 00000000..52fc283b
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/OpenMavenConsoleAction.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+
+/**
+ * Open Maven Console Action
+ *
+ * @author Eugene Kuleshov
+ */
+public class OpenMavenConsoleAction extends Action {
+
+ public void run() {
+ M2EUIPluginActivator.getDefault().getMavenConsoleImpl().showConsole();
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/OpenPomAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/OpenPomAction.java
new file mode 100644
index 00000000..da3520e9
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/OpenPomAction.java
@@ -0,0 +1,405 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.content.IContentTypeManager;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.index.IIndex;
+import org.eclipse.m2e.core.index.IndexedArtifact;
+import org.eclipse.m2e.core.index.IndexedArtifactFile;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.MavenProjectManager;
+import org.eclipse.m2e.core.ui.internal.dialogs.MavenRepositorySearchDialog;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorRegistry;
+import org.eclipse.ui.IPathEditorInput;
+import org.eclipse.ui.IPersistableElement;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionDelegate;
+import org.eclipse.ui.part.FileEditorInput;
+
+
+/**
+ * Open POM Action
+ *
+ * @author Eugene Kuleshov
+ */
+public class OpenPomAction extends ActionDelegate implements IWorkbenchWindowActionDelegate {
+
+ private static final String ID = "org.eclipse.m2e.openPomAction"; //$NON-NLS-1$
+
+ String type = IIndex.SEARCH_ARTIFACT;
+
+ private IStructuredSelection selection;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow)
+ */
+ public void init(IWorkbenchWindow window) {
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ if(selection instanceof IStructuredSelection) {
+ this.selection = (IStructuredSelection) selection;
+ } else {
+ this.selection = null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.actions.ActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ public void run(IAction action) {
+ //TODO mkleint: this asks for rewrite.. having one action that does 2 quite different things based
+ // on something as vague as selection passed in is unreadable..
+ if(selection != null) {
+ Object element = this.selection.getFirstElement();
+ if(IIndex.SEARCH_ARTIFACT.equals(type) && element != null) {
+ try {
+ final ArtifactKey ak = SelectionUtil.getArtifactKey(element);
+ if(ak != null) {
+ new Job(Messages.OpenPomAction_job_opening) {
+ protected IStatus run(IProgressMonitor monitor) {
+ openEditor(ak.getGroupId(), ak.getArtifactId(), ak.getVersion(), monitor);
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ return;
+ }
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ MessageDialog.openInformation(Display.getDefault().getActiveShell(), //
+ Messages.OpenPomAction_open_error_title, Messages.OpenPomAction_open_error_message);
+ }
+ });
+ }
+ }
+ }
+
+ String title = Messages.OpenPomAction_title_pom;
+
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ MavenRepositorySearchDialog dialog = MavenRepositorySearchDialog.createOpenPomDialog(shell, title);
+ if(dialog.open() == Window.OK) {
+ final IndexedArtifactFile iaf = (IndexedArtifactFile) dialog.getFirstResult();
+ new Job(Messages.OpenPomAction_job_opening) {
+ protected IStatus run(IProgressMonitor monitor) {
+ if(iaf != null) {
+ openEditor(iaf.group, iaf.artifact, iaf.version, monitor);
+ }
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ }
+ }
+
+ public static void openEditor(IndexedArtifact ia, IndexedArtifactFile f, IProgressMonitor monitor) {
+ if(f == null || ia.getClassname() == null || ia.getPackageName() == null) {
+ return;
+ }
+
+ String groupId = f.getDependency().getGroupId();
+ String artifactId = f.getDependency().getArtifactId();
+ String version = f.getDependency().getVersion();
+
+ String name = ia.getClassname();
+ String fileName = ia.getPackageName().replace('.', '/') + "/" + ia.getClassname() + ".java"; //$NON-NLS-1$ //$NON-NLS-2$
+ String tooltip = groupId + ":" + artifactId + ":" + version + "/" + fileName; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ try {
+ IMaven maven = MavenPlugin.getDefault().getMaven();
+
+ List<ArtifactRepository> artifactRepositories = maven.getArtifactRepositories();
+
+ Artifact artifact = maven.resolve(groupId, artifactId, version, "java-source", "sources", artifactRepositories, //$NON-NLS-1$ //$NON-NLS-2$
+ monitor);
+
+ final File file = artifact.getFile();
+ if(file == null) {
+ openDialog(NLS.bind(Messages.OpenPomAction_error_download_source, tooltip));
+ return;
+ }
+
+ // that won't work if source archive have subfolders before actual source tree
+ String url = "jar:" + file.toURL().toString() + "!/" + fileName; //$NON-NLS-1$ //$NON-NLS-2$
+ InputStream is = new URL(url).openStream();
+ byte[] buff = readStream(is);
+
+ openEditor(new MavenPathStorageEditorInput(name + ".java", tooltip, url, buff), name + ".java"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ } catch(IOException ex) {
+ String msg = NLS.bind(Messages.OpenPomAction_error_open_editor, name);
+ MavenLogger.log(msg, ex);
+ openDialog(msg + "\n" + ex.toString()); //$NON-NLS-1$
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ openDialog(ex.getMessage() + "\n" + ex.toString()); //$NON-NLS-1$
+ }
+ }
+
+ public static IEditorPart openEditor(String groupId, String artifactId, String version, IProgressMonitor monitor) {
+ if(groupId.length() > 0 && artifactId.length() > 0) {
+ final String name = groupId + ":" + artifactId + ":" + version + ".pom"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ try {
+ MavenPlugin plugin = MavenPlugin.getDefault();
+
+ MavenProjectManager projectManager = plugin.getMavenProjectManager();
+ IMavenProjectFacade projectFacade = projectManager.getMavenProject(groupId, artifactId, version);
+ if(projectFacade != null) {
+ final IFile pomFile = projectFacade.getPom();
+ return openEditor(new FileEditorInput(pomFile), name);
+ }
+
+ IMaven maven = MavenPlugin.getDefault().getMaven();
+
+ List<ArtifactRepository> artifactRepositories = maven.getArtifactRepositories();
+
+ Artifact artifact = maven.resolve(groupId, artifactId, version, "pom", null, artifactRepositories, monitor); //$NON-NLS-1$
+
+ File file = artifact.getFile();
+ if(file != null) {
+ return openEditor(new MavenPathStorageEditorInput(name, name, file.getAbsolutePath(),
+ readStream(new FileInputStream(file))), name);
+ }
+
+ openDialog(NLS.bind(Messages.OpenPomAction_error_download, name));
+
+ } catch(IOException ex) {
+ String msg = NLS.bind(Messages.OpenPomAction_error_open_pom, name);
+ MavenLogger.log(msg, ex);
+ openDialog(msg + "\n" + ex.toString()); //$NON-NLS-1$
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ openDialog(ex.getMessage() + "\n" + ex.toString()); //$NON-NLS-1$
+ }
+ }
+
+ return null;
+ }
+
+ public static IEditorPart openEditor(final IEditorInput editorInput, final String name) {
+ final IEditorPart[] part = new IEditorPart[1];
+ PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
+ public void run() {
+ IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
+ IContentType contentType = contentTypeManager.findContentTypeFor(name);
+ IEditorRegistry editorRegistry = PlatformUI.getWorkbench().getEditorRegistry();
+ IEditorDescriptor editor = editorRegistry.getDefaultEditor(name, contentType);
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if(window != null) {
+ IWorkbenchPage page = window.getActivePage();
+ if(page != null) {
+ try {
+ part[0] = page.openEditor(editorInput, editor.getId());
+ } catch(PartInitException ex) {
+ MessageDialog.openInformation(Display.getDefault().getActiveShell(), //
+ Messages.OpenPomAction_open_title, NLS.bind(Messages.OpenPomAction_33, editorInput.getName(), ex.toString())); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ });
+ return part[0];
+ }
+
+ private static void openDialog(final String msg) {
+ PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ MessageDialog.openInformation(Display.getDefault().getActiveShell(), //
+ Messages.OpenPomAction_open_title, msg);
+ }
+ });
+ }
+
+ private static byte[] readStream(InputStream is) throws IOException {
+ byte[] b = new byte[is.available()];
+ int len = 0;
+ while(true) {
+ int n = is.read(b, len, b.length - len);
+ if(n == -1) {
+ if(len < b.length) {
+ byte[] c = new byte[len];
+ System.arraycopy(b, 0, c, 0, len);
+ b = c;
+ }
+ return b;
+ }
+ len += n;
+ if(len == b.length) {
+ byte[] c = new byte[b.length + 1000];
+ System.arraycopy(b, 0, c, 0, len);
+ b = c;
+ }
+ }
+ }
+
+ /**
+ * Storage editor input implementation for Maven poms
+ */
+ public static class MavenStorageEditorInput implements IStorageEditorInput {
+
+ private final String name;
+
+ private final String path;
+
+ private final String tooltip;
+
+ private final byte[] content;
+
+ public MavenStorageEditorInput(String name, String tooltip, String path, byte[] content) {
+ this.name = name;
+ this.path = path;
+ this.tooltip = tooltip;
+ this.content = content;
+ }
+
+ // IStorageEditorInput
+
+ public boolean exists() {
+ return true;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getToolTipText() {
+ return this.tooltip;
+ }
+
+ public IStorage getStorage() {
+ return new MavenStorage(name, path, content);
+ }
+
+ public ImageDescriptor getImageDescriptor() {
+ return null;
+ }
+
+ public IPersistableElement getPersistable() {
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ return null;
+ }
+
+ // IPathEditorInput
+
+ public IPath getPath() {
+ return path == null ? null : new Path(path);
+ }
+
+ }
+
+ public static class MavenPathStorageEditorInput extends MavenStorageEditorInput implements IPathEditorInput {
+ public MavenPathStorageEditorInput(String name, String tooltip, String path, byte[] content) {
+ super(name, tooltip, path, content);
+ }
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ //implemented as hinted by IPathEditorInput javadoc.
+ public boolean equals(Object obj) {
+ IPath path = getPath();
+ if (path != null && obj instanceof MavenPathStorageEditorInput) {
+ return path.equals(((MavenPathStorageEditorInput)obj).getPath());
+ }
+ return super.equals(obj);
+ }
+ }
+
+ private static class MavenStorage implements IStorage {
+ private String name;
+
+ private final String path;
+
+ private final byte[] content;
+
+ public MavenStorage(String name, String path, byte[] content) {
+ this.name = name;
+ this.path = path;
+ this.content = content;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public IPath getFullPath() {
+ return path == null ? null : new Path(path);
+ }
+
+ public InputStream getContents() {
+ return new ByteArrayInputStream(content);
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ return null;
+ }
+
+
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/OpenUrlAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/OpenUrlAction.java
new file mode 100644
index 00000000..245563a3
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/OpenUrlAction.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.model.CiManagement;
+import org.apache.maven.model.IssueManagement;
+import org.apache.maven.model.Scm;
+import org.apache.maven.project.MavenProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionDelegate;
+import org.eclipse.ui.browser.IWebBrowser;
+import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
+
+
+/**
+ * Open Url Action
+ *
+ * @author Eugene Kuleshov
+ */
+public class OpenUrlAction extends ActionDelegate implements IWorkbenchWindowActionDelegate, IExecutableExtension {
+
+ public static final String ID_PROJECT = "org.eclipse.m2e.openProjectPage"; //$NON-NLS-1$
+
+ public static final String ID_ISSUES = "org.eclipse.m2e.openIssuesPage"; //$NON-NLS-1$
+
+ public static final String ID_SCM = "org.eclipse.m2e.openScmPage"; //$NON-NLS-1$
+
+ public static final String ID_CI = "org.eclipse.m2e.openCiPage"; //$NON-NLS-1$
+
+ String actionId;
+
+ private IStructuredSelection selection;
+
+ public OpenUrlAction() {
+ }
+
+ public OpenUrlAction(String id) {
+ this.actionId = id;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ if(selection instanceof IStructuredSelection) {
+ this.selection = (IStructuredSelection) selection;
+ } else {
+ this.selection = null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ public void run(IAction action) {
+ if(selection != null) {
+ try {
+ Object element = this.selection.getFirstElement();
+ final ArtifactKey a = SelectionUtil.getArtifactKey(element);
+ if(a != null) {
+ new Job(Messages.OpenUrlAction_job_browser) {
+ protected IStatus run(IProgressMonitor monitor) {
+ openBrowser(actionId, a.getGroupId(), a.getArtifactId(), a.getVersion(), monitor);
+ return Status.OK_STATUS;
+ }
+
+ }.schedule();
+ return;
+ }
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ MessageDialog.openInformation(Display.getDefault().getActiveShell(), //
+ Messages.OpenUrlAction_open_url_title, Messages.OpenUrlAction_open_url_message);
+ }
+ });
+ }
+ }
+ }
+
+ public static void openBrowser(String actionId, String groupId, String artifactId, String version, IProgressMonitor monitor) {
+ try {
+ MavenProject mavenProject = getMavenProject(groupId, artifactId, version, monitor);
+ final String url = getUrl(actionId, mavenProject);
+ if(url!=null) {
+ PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ try {
+ IWorkbenchBrowserSupport browserSupport = PlatformUI.getWorkbench().getBrowserSupport();
+ IWebBrowser browser = browserSupport.createBrowser(IWorkbenchBrowserSupport.NAVIGATION_BAR
+ | IWorkbenchBrowserSupport.LOCATION_BAR, url, url, url);
+ browser.openURL(new URL(url));
+ } catch(PartInitException ex) {
+ MavenLogger.log(ex);
+ } catch(MalformedURLException ex) {
+ MavenLogger.log("Malformed url " + url, ex);
+ }
+ }
+ });
+ }
+ } catch(Exception ex) {
+ MavenLogger.log("Can't open URL", ex);
+ }
+ }
+
+ private static String getUrl(String actionId, MavenProject mavenProject) {
+ String url = null;
+ if(ID_PROJECT.equals(actionId)) {
+ url = mavenProject.getUrl();
+ if(url == null) {
+ openDialog(Messages.OpenUrlAction_error_no_url);
+ }
+ } else if(ID_ISSUES.equals(actionId)) {
+ IssueManagement issueManagement = mavenProject.getIssueManagement();
+ if(issueManagement != null) {
+ url = issueManagement.getUrl();
+ }
+ if(url == null) {
+ openDialog(Messages.OpenUrlAction_error_no_issues);
+ }
+ } else if(ID_SCM.equals(actionId)) {
+ Scm scm = mavenProject.getScm();
+ if(scm != null) {
+ url = scm.getUrl();
+ }
+ if(url == null) {
+ openDialog(Messages.OpenUrlAction_error_no_scm);
+ }
+ } else if(ID_CI.equals(actionId)) {
+ CiManagement ciManagement = mavenProject.getCiManagement();
+ if(ciManagement != null) {
+ url = ciManagement.getUrl();
+ }
+ if(url == null) {
+ openDialog(Messages.OpenUrlAction_error_no_ci);
+ }
+ }
+ return url;
+ }
+
+ private static MavenProject getMavenProject(String groupId, String artifactId, String version, IProgressMonitor monitor) throws Exception {
+ String name = groupId + ":" + artifactId + ":" + version;
+
+ MavenPlugin plugin = MavenPlugin.getDefault();
+ IMaven maven = MavenPlugin.getDefault().getMaven();
+
+ IMavenProjectFacade projectFacade = plugin.getMavenProjectManager().getMavenProject(groupId, artifactId, version);
+ if(projectFacade != null) {
+ return projectFacade.getMavenProject(monitor);
+ }
+
+ List<ArtifactRepository> artifactRepositories = maven.getArtifactRepositories();
+
+ Artifact a = maven.resolve(groupId, artifactId, version, "pom", null, artifactRepositories, monitor); //$NON-NLS-1$
+
+ File pomFile = a.getFile();
+ if(pomFile == null) {
+ openDialog(NLS.bind(Messages.OpenUrlAction_error_open, name));
+ return null;
+ }
+
+ return maven.readProject(pomFile, monitor);
+ }
+
+ private static void openDialog(final String msg) {
+ PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ MessageDialog.openInformation(Display.getDefault().getActiveShell(), //
+ Messages.OpenUrlAction_browser_title, msg);
+ }
+ });
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow)
+ */
+ public void init(IWorkbenchWindow window) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
+ */
+ public void setInitializationData(IConfigurationElement config, String propertyName, Object data) {
+ if(data != null) {
+ actionId = (String) data;
+ }
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/RefreshMavenModelsAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/RefreshMavenModelsAction.java
new file mode 100644
index 00000000..1c2d0cc1
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/RefreshMavenModelsAction.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.project.MavenProjectManager;
+import org.eclipse.m2e.core.project.MavenUpdateRequest;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+import org.eclipse.ui.IWorkingSet;
+
+
+public class RefreshMavenModelsAction implements IWorkbenchWindowActionDelegate, IExecutableExtension {
+
+ public static final String ID = "org.eclipse.m2e.refreshMavenModelsAction"; //$NON-NLS-1$
+
+ public static final String ID_SNAPSHOTS = "org.eclipse.m2e.refreshMavenSnapshotsAction"; //$NON-NLS-1$
+
+ private boolean updateSnapshots = false;
+
+ private boolean offline = false; // should respect global settings
+
+ private IStructuredSelection selection;
+
+ public RefreshMavenModelsAction() {
+ }
+
+ public RefreshMavenModelsAction(boolean updateSnapshots) {
+ this.updateSnapshots = updateSnapshots;
+ }
+
+ // IExecutableExtension
+
+ public void setInitializationData(IConfigurationElement config, String propertyName, Object data) {
+ if("snapshots".equals(data)) { //$NON-NLS-1$
+ this.updateSnapshots = true;
+ }
+ }
+
+ // IWorkbenchWindowActionDelegate
+
+ public void run(IAction action) {
+ MavenProjectManager projectManager = MavenPlugin.getDefault().getMavenProjectManager();
+ projectManager.refresh(new MavenUpdateRequest(getProjects(), offline, updateSnapshots));
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ if(selection instanceof IStructuredSelection) {
+ this.selection = (IStructuredSelection) selection;
+ } else {
+ this.selection = null;
+ }
+ }
+
+ public void dispose() {
+ }
+
+ public void init(IWorkbenchWindow window) {
+ }
+
+ private IProject[] getProjects() {
+ ArrayList<IProject> projectList = new ArrayList<IProject>();
+ if(selection != null) {
+ for(Iterator<?> it = selection.iterator(); it.hasNext();) {
+ Object o = it.next();
+ if(o instanceof IProject) {
+ projectList.add((IProject) o);
+ } else if(o instanceof IWorkingSet) {
+ IWorkingSet workingSet = (IWorkingSet) o;
+ for(IAdaptable adaptable : workingSet.getElements()) {
+ IProject project = (IProject) adaptable.getAdapter(IProject.class);
+ try {
+ if(project != null && project.isAccessible() && project.hasNature(IMavenConstants.NATURE_ID)) {
+ projectList.add(project);
+ }
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ }
+ }
+ }
+ }
+ }
+ if(projectList.isEmpty()) {
+ return ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ }
+ return projectList.toArray(new IProject[projectList.size()]);
+ }
+
+}
+
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/SelectionUtil.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/SelectionUtil.java
new file mode 100644
index 00000000..385dc645
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/SelectionUtil.java
@@ -0,0 +1,357 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.execution.MavenExecutionResult;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.util.IOUtil;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.MavenProjectManager;
+import org.eclipse.m2e.core.ui.internal.util.Util;
+import org.eclipse.m2e.core.ui.internal.util.Util.FileStoreEditorInputStub;
+import org.eclipse.m2e.model.edit.pom.Dependency;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkingSet;
+import org.eclipse.ui.IWorkingSetManager;
+import org.eclipse.ui.PlatformUI;
+
+
+/**
+ * Helper methods to deal with workspace resources passed as navigator selection to actions and wizards.
+ */
+public class SelectionUtil {
+
+ public static final int UNSUPPORTED = 0;
+
+ public static final int PROJECT_WITH_NATURE = 1;
+
+ public static final int PROJECT_WITHOUT_NATURE = 2;
+
+ public static final int POM_FILE = 4;
+
+ public static final int JAR_FILE = 8;
+
+ public static final int WORKING_SET = 16;
+
+ /** Checks which type the given selection belongs to. */
+ public static int getSelectionType(IStructuredSelection selection) {
+ int type = UNSUPPORTED;
+ if(selection != null) {
+ for(Iterator<?> it = selection.iterator(); it.hasNext();) {
+ int elementType = getElementType(it.next());
+ if(elementType == UNSUPPORTED) {
+ return UNSUPPORTED;
+ }
+ type |= elementType;
+ }
+ }
+ return type;
+ }
+
+ /** Checks which type the given element belongs to. */
+ public static int getElementType(Object element) {
+ IProject project = getType(element, IProject.class);
+ if(project != null) {
+ try {
+ if(project.hasNature(IMavenConstants.NATURE_ID)) {
+ return PROJECT_WITH_NATURE;
+ }
+ return PROJECT_WITHOUT_NATURE;
+ } catch(CoreException e) {
+ // ignored
+ }
+ }
+
+ IFile file = getType(element, IFile.class);
+ if(file != null) {
+ if(IMavenConstants.POM_FILE_NAME.equals(file.getFullPath().lastSegment())) {
+ return POM_FILE;
+ }
+ }
+
+ ArtifactKey artifactKey = getType(element, ArtifactKey.class);
+ if(artifactKey != null) {
+ return JAR_FILE;
+ }
+
+ IWorkingSet workingSet = getType(element, IWorkingSet.class);
+ if(workingSet!=null) {
+ return WORKING_SET;
+ }
+
+ return UNSUPPORTED;
+ }
+
+ /**
+ * Checks if the object belongs to a given type and returns it or a suitable adapter.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T getType(Object element, Class<T> type) {
+ if(element==null) {
+ return null;
+ }
+ if(type.isInstance(element)) {
+ return (T) element;
+ }
+ if(element instanceof IAdaptable) {
+ T adapter = (T) ((IAdaptable) element).getAdapter(type);
+ if(adapter != null) {
+ return adapter;
+ }
+ }
+ return (T) Platform.getAdapterManager().getAdapter(element, type);
+ }
+
+ public static IPath getSelectedLocation(IStructuredSelection selection) {
+ Object element = selection == null ? null : selection.getFirstElement();
+
+ IPath path = getType(element, IPath.class);
+ if(path != null) {
+ return path;
+ }
+
+ IResource resource = getType(element, IResource.class);
+ if(resource != null) {
+ return resource.getLocation();
+ }
+
+// IPackageFragmentRoot fragment = getType(element, IResource.class);
+// if(fragment != null) {
+// IJavaProject javaProject = fragment.getJavaProject();
+// if(javaProject != null) {
+// IResource resource = getType(javaProject, IResource.class);
+// if(resource != null) {
+// return resource.getProject().getProject().getLocation();
+// }
+// }
+// }
+
+ return null;
+ }
+
+ public static IWorkingSet getSelectedWorkingSet(IStructuredSelection selection) {
+ Object element = selection == null ? null : selection.getFirstElement();
+ {
+ IWorkingSet workingSet = getType(element, IWorkingSet.class);
+ if(workingSet != null) {
+ return workingSet;
+ }
+ }
+ {
+ IResource resource = getType(element, IResource.class);
+ if(resource != null) {
+ return getWorkingSet(resource.getProject());
+ }
+ }
+
+// IResource resource = getType(element, IResource.class);
+// if(resource != null) {
+// return getWorkingSet(resource);
+// }
+
+// IPackageFragmentRoot fragment = getType(element, IPackageFragmentRoot.class);
+// if(fragment != null) {
+// IJavaProject javaProject = fragment.getJavaProject();
+// if(javaProject != null) {
+// IResource resource = getType(javaProject, IResource.class);
+// if(resource != null) {
+// return getWorkingSet(resource.getProject());
+// }
+// }
+// }
+
+ return null;
+ }
+
+ public static IWorkingSet getWorkingSet(Object element) {
+ IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager();
+ for(IWorkingSet workingSet : workingSetManager.getWorkingSets()) {
+ for(IAdaptable adaptable : workingSet.getElements()) {
+ if(adaptable.getAdapter(IResource.class) == element) {
+ return workingSet;
+ }
+ }
+ }
+ return null;
+ }
+
+ public static List<IWorkingSet> getAssignedWorkingSets(Object element) {
+ List<IWorkingSet> list = new ArrayList<IWorkingSet>();
+ IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager();
+ for(IWorkingSet workingSet : workingSetManager.getWorkingSets()) {
+ for(IAdaptable adaptable : workingSet.getElements()) {
+ if(adaptable.getAdapter(IResource.class) == element) {
+ list.add(workingSet);
+ }
+ }
+ }
+ return list;
+ }
+
+ public static ArtifactKey getArtifactKey(Object element) throws CoreException {
+ if(element instanceof Artifact) {
+ return new ArtifactKey(((Artifact) element));
+
+ } else if(element instanceof org.sonatype.aether.graph.DependencyNode) {
+ org.sonatype.aether.artifact.Artifact artifact = ((org.sonatype.aether.graph.DependencyNode) element)
+ .getDependency().getArtifact();
+ return new ArtifactKey(artifact);
+
+ } else if(element instanceof Dependency) {
+ Dependency dependency = (Dependency) element;
+ String groupId = dependency.getGroupId();
+ String artifactId = dependency.getArtifactId();
+ String version = dependency.getVersion();
+
+ if(version == null) {
+ //mkleint: this looks scary
+ IEditorPart editor = getActiveEditor();
+ if(editor!=null) {
+ MavenProject mavenProject = getMavenProject(editor.getEditorInput(), null);
+ if(mavenProject!=null) {
+ Artifact a = mavenProject.getArtifactMap().get(groupId + ":" + artifactId); //$NON-NLS-1$
+ version = a.getBaseVersion();
+ }
+ }
+ }
+ return new ArtifactKey(dependency.getGroupId(), dependency.getArtifactId(), version, null);
+ }
+
+ return SelectionUtil.getType(element, ArtifactKey.class);
+ }
+
+ public static MavenProject getMavenProject(IEditorInput editorInput, IProgressMonitor monitor) throws CoreException {
+ if(editorInput instanceof IFileEditorInput) {
+ IFile pomFile = ((IFileEditorInput) editorInput).getFile();
+ MavenProjectManager projectManager = MavenPlugin.getDefault().getMavenProjectManager();
+ IMavenProjectFacade facade = projectManager.create(pomFile, true, monitor);
+ if(facade!=null) {
+ return facade.getMavenProject(monitor);
+ }
+
+ } else if(editorInput instanceof IStorageEditorInput) {
+ IStorageEditorInput storageInput = (IStorageEditorInput) editorInput;
+ IStorage storage = storageInput.getStorage();
+ IPath path = storage.getFullPath();
+ if(path == null || !new File(path.toOSString()).exists()) {
+ File tempPomFile = null;
+ InputStream is = null;
+ OutputStream os = null;
+ try {
+ tempPomFile = File.createTempFile("maven-pom", ".pom"); //$NON-NLS-1$ //$NON-NLS-2$
+ os = new FileOutputStream(tempPomFile);
+ is = storage.getContents();
+ IOUtil.copy(is, os);
+ return readMavenProject(tempPomFile, monitor);
+ } catch(IOException ex) {
+ MavenLogger.log("Can't close stream", ex);
+ } finally {
+ IOUtil.close(is);
+ IOUtil.close(os);
+ if(tempPomFile != null) {
+ tempPomFile.delete();
+ }
+ }
+ } else {
+ return readMavenProject(path.toFile(), monitor);
+ }
+
+ } else if(editorInput.getClass().getName().endsWith("FileStoreEditorInput")) { //$NON-NLS-1$
+ return readMavenProject(new File(Util.proxy(editorInput, FileStoreEditorInputStub.class).getURI().getPath()), monitor);
+ }
+
+ return null;
+ }
+
+ private static MavenProject readMavenProject(File pomFile, IProgressMonitor monitor) throws CoreException {
+ if(monitor==null) {
+ monitor = new NullProgressMonitor();
+ }
+
+ IMaven maven = MavenPlugin.getDefault().getMaven();
+
+ MavenExecutionRequest request = maven.createExecutionRequest(monitor);
+ request.setOffline(false);
+ request.setUpdateSnapshots(false);
+ request.setRecursive(false);
+ request.setPom(pomFile);
+
+ MavenExecutionResult result = maven.execute(request, monitor);
+
+ MavenProject project = result.getProject();
+ if(project!=null) {
+ return project;
+ }
+
+ if(result.hasExceptions()) {
+ List<IStatus> statuses = new ArrayList<IStatus>();
+ List<Throwable> exceptions = result.getExceptions();
+ for(Throwable e : exceptions) {
+ statuses.add(new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, -1, e.getMessage(), e));
+ }
+
+ throw new CoreException(new MultiStatus(IMavenConstants.PLUGIN_ID, IStatus.ERROR, //
+ statuses.toArray(new IStatus[statuses.size()]), Messages.SelectionUtil_error_cannot_read, null));
+ }
+
+ throw new CoreException(new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, -1, //
+ Messages.SelectionUtil_error_cannot_read, null));
+ }
+
+ private static IEditorPart getActiveEditor() {
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if(window != null) {
+ IWorkbenchPage page = window.getActivePage();
+ if(page != null) {
+ return page.getActiveEditor();
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/UpdateConfigurationAction.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/UpdateConfigurationAction.java
new file mode 100644
index 00000000..99d33112
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/actions/UpdateConfigurationAction.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.actions;
+
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.ui.internal.UpdateConfigurationJob;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkingSet;
+
+
+public class UpdateConfigurationAction implements IObjectActionDelegate {
+
+ public static final String ID = "org.eclipse.m2e.updateConfigurationAction"; //$NON-NLS-1$
+
+ private IStructuredSelection selection;
+
+ private Shell shell;
+
+ public UpdateConfigurationAction() {
+ }
+
+ public UpdateConfigurationAction(Shell shell) {
+ this.shell = shell;
+ }
+
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ if (targetPart != null) {
+ shell = targetPart.getSite().getShell();
+ }
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ if(selection instanceof IStructuredSelection) {
+ this.selection = (IStructuredSelection) selection;
+ } else {
+ this.selection = null;
+ }
+ }
+
+ public void run(IAction action) {
+ final Set<IProject> projects = getProjects();
+ final MavenPlugin plugin = MavenPlugin.getDefault();
+ new UpdateConfigurationJob(plugin, projects.toArray(new IProject[projects.size()])).schedule();
+ }
+
+ private Set<IProject> getProjects() {
+ Set<IProject> projects = new LinkedHashSet<IProject>();
+ if(selection != null) {
+ for(Iterator<?> it = selection.iterator(); it.hasNext();) {
+ Object element = it.next();
+ if(element instanceof IProject) {
+ projects.add((IProject) element);
+ } else if(element instanceof IWorkingSet) {
+ IWorkingSet workingSet = (IWorkingSet) element;
+ for(IAdaptable adaptable : workingSet.getElements()) {
+ IProject project = (IProject) adaptable.getAdapter(IProject.class);
+ try {
+ if(project != null && project.isAccessible() && project.hasNature(IMavenConstants.NATURE_ID)) {
+ projects.add(project);
+ }
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ }
+ }
+ } else if(element instanceof IAdaptable) {
+ IProject project = (IProject) ((IAdaptable) element).getAdapter(IProject.class);
+ if(project != null) {
+ projects.add(project);
+ }
+ }
+ }
+ }
+ return projects;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/components/TextComboBoxCellEditor.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/components/TextComboBoxCellEditor.java
new file mode 100644
index 00000000..45c0e957
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/components/TextComboBoxCellEditor.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.components;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CCombo;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.events.TraverseListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+
+/**
+ * A TextComboBoxCellEditor to overcome the limitation of the standard ComboBoxCellEditor, which does not allow to edit
+ * plain text values.
+ *
+ * @author Dmitry Platonoff
+ */
+public class TextComboBoxCellEditor extends CellEditor {
+
+ protected String[] items;
+
+
+ protected CCombo combo;
+
+ public TextComboBoxCellEditor(Composite parent, int style) {
+ super(parent, style);
+ }
+
+ protected Control createControl(Composite parent) {
+ combo = new CCombo(parent, getStyle());
+ combo.setFont(parent.getFont());
+
+ combo.addKeyListener(new KeyAdapter() {
+ public void keyPressed(KeyEvent e) {
+ keyReleaseOccured(e);
+ }
+ });
+ combo.addTraverseListener(new TraverseListener() {
+ public void keyTraversed(TraverseEvent e) {
+ if (e.detail == SWT.TRAVERSE_ESCAPE
+ || e.detail == SWT.TRAVERSE_RETURN) {
+ e.doit = false;
+ }
+ }
+ });
+
+ loadItems();
+
+ return combo;
+ }
+
+ protected Object doGetValue() {
+ Assert.isNotNull(combo);
+ return combo.getText();
+ }
+
+ protected void doSetFocus() {
+ Assert.isNotNull(combo);
+ combo.setFocus();
+ }
+
+ protected void doSetValue(Object value) {
+ Assert.isNotNull(combo);
+ combo.setText(String.valueOf(value));
+ }
+
+ public String[] getItems() {
+ return items;
+ }
+
+ public void setItems(String[] items) {
+ this.items = items;
+ loadItems();
+ }
+
+ protected void loadItems() {
+ if(combo != null && items != null) {
+ combo.setItems(items);
+ }
+ }
+
+ protected void keyReleaseOccured(KeyEvent keyEvent) {
+ if(keyEvent.character == SWT.ESC) {
+ fireCancelEditor();
+ } else if(keyEvent.character == SWT.TAB || keyEvent.character == SWT.CR) {
+ focusLost();
+ }
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/AbstractMavenDialog.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/AbstractMavenDialog.java
new file mode 100644
index 00000000..e72d3849
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/AbstractMavenDialog.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.dialogs;
+
+import org.eclipse.jface.dialogs.DialogSettings;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.SelectionStatusDialog;
+
+
+/**
+ * A dialog superclass, featuring position and size settings.
+ */
+public abstract class AbstractMavenDialog extends SelectionStatusDialog {
+
+ protected static final String KEY_WIDTH = "width"; //$NON-NLS-1$
+ protected static final String KEY_HEIGHT = "height"; //$NON-NLS-1$
+ private static final String KEY_X = "x"; //$NON-NLS-1$
+ private static final String KEY_Y = "y"; //$NON-NLS-1$
+ protected IDialogSettings settings;
+ private Point location;
+ private Point size;
+
+ /**
+ * @param parent
+ */
+ protected AbstractMavenDialog(Shell parent, String settingsSection) {
+ super(parent);
+
+ IDialogSettings pluginSettings = M2EUIPluginActivator.getDefault().getDialogSettings();
+ IDialogSettings settings = pluginSettings.getSection(settingsSection);
+ if(settings == null) {
+ settings = new DialogSettings(settingsSection);
+ settings.put(KEY_WIDTH, 480);
+ settings.put(KEY_HEIGHT, 450);
+ pluginSettings.addSection(settings);
+ }
+ this.settings = settings;
+ }
+
+ protected Point getInitialSize() {
+ Point result = super.getInitialSize();
+ if(size != null) {
+ result.x = Math.max(result.x, size.x);
+ result.y = Math.max(result.y, size.y);
+ Rectangle display = getShell().getDisplay().getClientArea();
+ result.x = Math.min(result.x, display.width);
+ result.y = Math.min(result.y, display.height);
+ }
+ return result;
+ }
+
+ protected Point getInitialLocation(Point initialSize) {
+ Point result = super.getInitialLocation(initialSize);
+ if(location != null) {
+ result.x = location.x;
+ result.y = location.y;
+ Rectangle display = getShell().getDisplay().getClientArea();
+ int xe = result.x + initialSize.x;
+ if(xe > display.width) {
+ result.x -= xe - display.width;
+ }
+ int ye = result.y + initialSize.y;
+ if(ye > display.height) {
+ result.y -= ye - display.height;
+ }
+ }
+ return result;
+ }
+
+ public boolean close() {
+ writeSettings();
+ return super.close();
+ }
+
+ /**
+ * Initializes itself from the dialog settings with the same state as at the
+ * previous invocation.
+ */
+ protected void readSettings() {
+ try {
+ int x = settings.getInt(KEY_X); //$NON-NLS-1$
+ int y = settings.getInt(KEY_Y); //$NON-NLS-1$
+ location = new Point(x, y);
+ } catch(NumberFormatException e) {
+ location = null;
+ }
+ try {
+ int width = settings.getInt(KEY_WIDTH); //$NON-NLS-1$
+ int height = settings.getInt(KEY_HEIGHT); //$NON-NLS-1$
+ size = new Point(width, height);
+
+ } catch(NumberFormatException e) {
+ size = null;
+ }
+ }
+
+ /**
+ * Stores it current configuration in the dialog store.
+ */
+ private void writeSettings() {
+ Point location = getShell().getLocation();
+ settings.put(KEY_X, location.x); //$NON-NLS-1$
+ settings.put(KEY_Y, location.y); //$NON-NLS-1$
+
+ Point size = getShell().getSize();
+ settings.put(KEY_WIDTH, size.x); //$NON-NLS-1$
+ settings.put(KEY_HEIGHT, size.y); //$NON-NLS-1$
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/AddDependencyDialog.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/AddDependencyDialog.java
new file mode 100644
index 00000000..268f7407
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/AddDependencyDialog.java
@@ -0,0 +1,690 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.dialogs;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.maven.project.MavenProject;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.index.IIndex;
+import org.eclipse.m2e.core.index.IndexManager;
+import org.eclipse.m2e.core.index.IndexedArtifact;
+import org.eclipse.m2e.core.index.IndexedArtifactFile;
+import org.eclipse.m2e.core.index.UserInputSearchExpression;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.ui.internal.search.util.Packaging;
+import org.eclipse.m2e.core.ui.internal.util.M2EUIUtils;
+import org.eclipse.m2e.core.ui.internal.util.ProposalUtil;
+import org.eclipse.m2e.core.ui.internal.wizards.MavenPomSelectionComponent;
+import org.eclipse.m2e.core.ui.internal.wizards.WidthGroup;
+import org.eclipse.m2e.model.edit.pom.Dependency;
+import org.eclipse.m2e.model.edit.pom.PomFactory;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+
+import com.ibm.icu.text.DateFormat;
+
+
+/**
+ * A Dialog whose primary goal is to allow the user to select a dependency, either by entering the GAV coordinates
+ * manually, or by search through a repository index.
+ *
+ * @author rgould
+ */
+public class AddDependencyDialog extends AbstractMavenDialog {
+
+ public static final String[] SCOPES = new String[] {"compile", "provided", "runtime", "test", "system"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
+ /*
+ * dependencies under dependencyManagement are permitted to use an the extra "import" scope
+ */
+ public static final String[] DEP_MANAGEMENT_SCOPES = new String[] {"compile", "provided", "runtime", "test", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ "system", "import"}; //$NON-NLS-1$ //$NON-NLS-2$
+
+ protected static final String DIALOG_SETTINGS = AddDependencyDialog.class.getName();
+
+ protected static final long SEARCH_DELAY = 500L; //in milliseconds
+
+ protected String[] scopes;
+
+ protected TreeViewer resultsViewer;
+
+ protected Text queryText;
+
+ protected Text groupIDtext;
+
+ protected Text artifactIDtext;
+
+ protected Text versionText;
+
+ protected Text infoTextarea;
+
+ protected Combo scopeCombo;
+
+ protected java.util.List<Dependency> dependencies;
+
+ protected WidthGroup widthGroup;
+
+ /*
+ * Stores selected files from the results viewer. These are later
+ * converted into the above dependencies when OK is pressed.
+ */
+ protected java.util.List<IndexedArtifactFile> artifactFiles;
+
+ protected SearchJob currentSearch;
+
+ protected IProject project;
+
+ protected IStatus lastStatus;
+
+ protected SelectionListener resultsListener;
+
+ protected boolean updating;
+
+ private final MavenProject mavenProject;
+
+ private final boolean isForDependencyManagement;
+
+ private Set<String> managedKeys;
+
+ private Set<String> existingKeys;
+
+ /**
+ * The AddDependencyDialog differs slightly in behaviour depending on context. If it is being used to apply a
+ * dependency under the "dependencyManagement" context, the extra "import" scope is available. Set @param
+ * isForDependencyManagement to true if this is case.
+ *
+ * @param parent
+ * @param isForDependencyManagement
+ * @param project the project which contains this POM. Used for looking up indices
+ */
+ public AddDependencyDialog(Shell parent, boolean isForDependencyManagement, IProject project, MavenProject mavenProject) {
+ super(parent, DIALOG_SETTINGS);
+ this.project = project;
+ this.mavenProject = mavenProject;
+
+ this.isForDependencyManagement = isForDependencyManagement;
+
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ setTitle(Messages.AddDependencyDialog_title);
+// setStatusLineAboveButtons(true);
+
+ if(!isForDependencyManagement) {
+ this.scopes = SCOPES;
+ } else {
+ this.scopes = DEP_MANAGEMENT_SCOPES;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.Dialog#createDialogArea()
+ */
+ protected Control createDialogArea(Composite parent) {
+ readSettings();
+
+ Composite composite = (Composite) super.createDialogArea(parent);
+
+ widthGroup = new WidthGroup();
+ composite.addControlListener(widthGroup);
+
+ Composite gavControls = createGAVControls(composite);
+ gavControls.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+
+ Composite searchControls = createSearchControls(composite);
+ searchControls.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ updateStatus();
+ return composite;
+ }
+
+ /**
+ * Sets the up group-artifact-version controls
+ */
+ private Composite createGAVControls(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+
+ GridLayout gridLayout = new GridLayout(4, false);
+ gridLayout.marginWidth = 0;
+ gridLayout.horizontalSpacing = 10;
+ composite.setLayout(gridLayout);
+
+ Label groupIDlabel = new Label(composite, SWT.NONE);
+ groupIDlabel.setText(Messages.AddDependencyDialog_groupId_label);
+ widthGroup.addControl(groupIDlabel);
+
+ groupIDtext = new Text(composite, SWT.BORDER);
+ groupIDtext.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ M2EUIUtils.addRequiredDecoration(groupIDtext);
+
+ new Label(composite, SWT.NONE);
+ new Label(composite, SWT.NONE);
+
+
+ Label artifactIDlabel = new Label(composite, SWT.NONE);
+ artifactIDlabel.setText(Messages.AddDependencyDialog_artifactId_label);
+ widthGroup.addControl(artifactIDlabel);
+
+ artifactIDtext = new Text(composite, SWT.BORDER);
+ artifactIDtext.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ M2EUIUtils.addRequiredDecoration(artifactIDtext);
+
+ new Label(composite, SWT.NONE);
+ new Label(composite, SWT.NONE);
+
+ Label versionLabel = new Label(composite, SWT.NONE);
+ versionLabel.setText(Messages.AddDependencyDialog_version_label);
+ widthGroup.addControl(versionLabel);
+
+ versionText = new Text(composite, SWT.BORDER);
+ versionText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+
+ Label scopeLabel = new Label(composite, SWT.NONE);
+ scopeLabel.setText(Messages.AddDependencyDialog_scope_label);
+
+ scopeCombo = new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY);
+ scopeCombo.setItems(scopes);
+ GridData scopeListData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
+ scopeCombo.setLayoutData(scopeListData);
+ scopeCombo.setText(scopes[0]);
+
+ /*
+ * Fix the tab order (group -> artifact -> version -> scope)
+ */
+ composite.setTabList(new Control[] {groupIDtext, artifactIDtext, versionText, scopeCombo});
+
+ ProposalUtil.addGroupIdProposal(project, groupIDtext, Packaging.ALL);
+ ProposalUtil.addArtifactIdProposal(project, groupIDtext, artifactIDtext, Packaging.ALL);
+ ProposalUtil.addVersionProposal(project, mavenProject, groupIDtext, artifactIDtext, versionText, Packaging.ALL);
+
+ artifactIDtext.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent e) {
+ updateInfo();
+ }
+ });
+
+ groupIDtext.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent e) {
+ updateInfo();
+ }
+ });
+
+ return composite;
+ }
+
+ void updateInfo() {
+// infoTextarea.setText(""); //$NON-NLS-1$
+ if(!updating) {
+ resultsViewer.setSelection(StructuredSelection.EMPTY);
+ updateStatus();
+ }
+ // TODO mkleint: for now just ignore..
+// this snippet is supposed to tell people that they selected dependency already in the
+// project
+
+// if(dependencyNode == null) {
+// return;
+// }
+// dependencyNode.accept(new DependencyVisitor() {
+//
+// public boolean visitLeave(DependencyNode node) {
+// if(node.getDependency() != null && node.getDependency().getArtifact() != null) {
+// Artifact artifact = node.getDependency().getArtifact();
+// if(artifact.getGroupId().equalsIgnoreCase(groupIDtext.getText().trim())
+// && artifact.getArtifactId().equalsIgnoreCase(artifactIDtext.getText().trim())) {
+// infoTextarea.setText(NLS.bind(Messages.AddDependencyDialog_info_transitive,
+// new String[] {artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion()}));
+// }
+// return false;
+// }
+// return true;
+// }
+//
+// public boolean visitEnter(DependencyNode node) {
+// return true;
+// }
+// });
+
+ }
+
+ private Composite createSearchControls(Composite parent) {
+ SashForm sashForm = new SashForm(parent, SWT.VERTICAL | SWT.SMOOTH);
+ sashForm.setLayout(new FillLayout());
+
+ Composite resultsComposite = new Composite(sashForm, SWT.NONE);
+ GridLayout resultsLayout = new GridLayout(1, false);
+ resultsLayout.marginWidth = 0;
+ resultsComposite.setLayout(resultsLayout);
+
+ Label queryLabel = new Label(resultsComposite, SWT.NONE);
+ queryLabel.setText(Messages.AddDependencyDialog_search_label);
+// widthGroup.addControl(queryLabel);
+
+ queryText = new Text(resultsComposite, SWT.BORDER | SWT.SEARCH);
+ queryText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ queryText.setFocus();
+
+// queryText.setMessage(Messages.AddDependencyDialog_search_message);
+
+ Label resultsLabel = new Label(resultsComposite, SWT.NONE);
+ resultsLabel.setText(Messages.AddDependencyDialog_results_label);
+ resultsLabel.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
+// widthGroup.addControl(resultsLabel);
+
+ Tree resultsTree = new Tree(resultsComposite, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION);
+ GridData treeData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ treeData.heightHint = 140;
+ treeData.widthHint = 100;
+ resultsTree.setLayoutData(treeData);
+
+ Composite infoComposite = new Composite(sashForm, SWT.NONE);
+ GridLayout infoLayout = new GridLayout(1, false);
+ infoLayout.marginWidth = 0;
+ infoComposite.setLayout(infoLayout);
+
+ Label infoLabel = new Label(infoComposite, SWT.NONE);
+ infoLabel.setText(Messages.AddDependencyDialog_info_label);
+ infoLabel.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
+// widthGroup.addControl(infoLabel);
+
+ infoTextarea = new Text(infoComposite, SWT.MULTI | SWT.READ_ONLY | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+ GridData infoData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ infoData.heightHint = 60;
+ infoData.widthHint = 100;
+ infoTextarea.setLayoutData(infoData);
+
+ sashForm.setWeights(new int[] {70, 30});
+
+ /*
+ * Set up TreeViewer for search results
+ */
+
+ resultsViewer = new TreeViewer(resultsTree);
+ resultsViewer.setContentProvider(new MavenPomSelectionComponent.SearchResultContentProvider());
+ //TODO we want to have the artifacts marked for presence and management..
+ managedKeys = new HashSet<String>();
+ existingKeys = new HashSet<String>();
+ if (mavenProject != null && mavenProject.getDependencyManagement() != null) {
+ for (org.apache.maven.model.Dependency d : mavenProject.getDependencyManagement().getDependencies()) {
+ managedKeys.add(d.getGroupId() + ":" + d.getArtifactId());
+ managedKeys.add(d.getGroupId() + ":" + d.getArtifactId() + ":" + d.getVersion());
+ }
+ }
+ if (isForDependencyManagement) {
+ existingKeys = managedKeys;
+ managedKeys = Collections.<String>emptySet();
+ }
+ resultsViewer.setLabelProvider(new DelegatingStyledCellLabelProvider(
+ new MavenPomSelectionComponent.SearchResultLabelProvider(existingKeys, managedKeys,
+ IIndex.SEARCH_ARTIFACT)));
+
+ /*
+ * Hook up events
+ */
+
+ resultsListener = new SelectionListener();
+ resultsViewer.addSelectionChangedListener(resultsListener);
+
+ queryText.addKeyListener(new KeyAdapter() {
+ public void keyPressed(KeyEvent e) {
+ if(e.keyCode == SWT.ARROW_DOWN) {
+ resultsViewer.getTree().setFocus();
+ }
+ }
+ });
+
+ queryText.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent e) {
+ search(queryText.getText());
+ }
+ });
+
+ return sashForm;
+ }
+
+ /**
+ * Just a short helper method to determine what to display in the text widgets when the user selects multiple objects
+ * in the tree viewer. If the objects have the same value, then we should show that to them, otherwise we show
+ * something like "(multiple selected)"
+ *
+ * @param current
+ * @param newValue
+ * @return
+ */
+ String chooseWidgetText(String current, String newValue) {
+ if(current == null) {
+ return newValue;
+ } else if(!current.equals(newValue)) {
+ return Messages.AddDependencyDialog_multipleValuesSelected;
+ }
+ return current;
+ }
+
+ void appendFileInfo(final StringBuffer buffer, final IndexedArtifactFile file) {
+ buffer.append(" * " + file.fname);
+ if(file.size != -1) {
+ buffer.append(", size: ");
+ if((file.size / 1024 / 1024) > 0) {
+ buffer.append((file.size / 1024 / 1024) + "MB");
+ } else {
+ buffer.append(Math.max(1, file.size / 1024) + "KB");
+ }
+ }
+ buffer.append(", date: " + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT).format(file.date));
+ buffer.append("\n");
+
+// TODO mkleint: for now just ignore..
+// this snippet is supposed to tell people that they selected dependency already in the
+// project
+
+// if(dependencyNode != null) {
+// dependencyNode.accept(new DependencyVisitor() {
+//
+// public boolean visitEnter(DependencyNode node) {
+// return true;
+// }
+//
+// public boolean visitLeave(DependencyNode node) {
+// if(node.getDependency() == null || node.getDependency().getArtifact() == null) {
+// return true;
+// }
+// Artifact artifact = node.getDependency().getArtifact();
+// if(artifact.getGroupId().equalsIgnoreCase(file.group)
+// && artifact.getArtifactId().equalsIgnoreCase(file.artifact)) {
+// buffer.append(NLS.bind(Messages.AddDependencyDialog_transitive_dependency,
+// new String[] {artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion()}));
+// /*
+// * DependencyNodes don't know their parents. Determining which transitive dependency
+// * is using the selected dependency is non trivial :(
+// */
+// return false;
+// }
+// return true;
+// }
+// });
+// }
+ }
+
+ protected void search(String query) {
+ if(query == null || query.length() <= 2) {
+ if(this.currentSearch != null) {
+ this.currentSearch.cancel();
+ }
+ } else {
+ IndexManager indexManager = MavenPlugin.getDefault().getIndexManager();
+
+ if(this.currentSearch != null) {
+ this.currentSearch.cancel();
+ }
+
+ this.currentSearch = new SearchJob(query.toLowerCase(), indexManager);
+ this.currentSearch.schedule(SEARCH_DELAY);
+ }
+ }
+
+ protected boolean isGroupAndArtifactPresent() {
+ return groupIDtext.getText().trim().length() > 0 && artifactIDtext.getText().trim().length() > 0;
+ }
+
+ protected void updateStatus() {
+ boolean enableOK = isGroupAndArtifactPresent() || (artifactFiles != null && artifactFiles.size() > 0);
+
+ int severity = enableOK ? IStatus.OK : IStatus.ERROR;
+ String message = enableOK ? "" : Messages.AddDependencyDialog_groupAndArtifactRequired; //$NON-NLS-1$
+
+ if(lastStatus == null || lastStatus.getSeverity() != severity) {
+ setInfo(severity, message);
+ }
+ }
+
+ protected void updateStatus(IStatus status) {
+ lastStatus = status;
+ super.updateStatus(status);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.dialogs.SelectionStatusDialog#computeResult()
+ * This is called when OK is pressed. There's no obligation to do anything.
+ */
+ protected void computeResult() {
+ String scope = scopeCombo.getText(); //$NON-NLS-1$
+
+ if(artifactFiles == null || artifactFiles.size() == 1) {
+ String type = "";
+ String classifier = "";
+ if (artifactFiles != null && artifactFiles.size() == 1) {
+ // use the selected artifact props if available..
+ IndexedArtifactFile file = artifactFiles.iterator().next();
+ classifier = file.classifier;
+ type = file.type;
+ }
+ Dependency dependency = createDependency(groupIDtext.getText().trim(), artifactIDtext.getText().trim(),
+ versionText.getText().trim(), scope, type, classifier); //$NON-NLS-1$
+ this.dependencies = Collections.singletonList(dependency);
+ } else {
+ this.dependencies = new LinkedList<Dependency>();
+ for(IndexedArtifactFile file : artifactFiles) {
+ Dependency dep = createDependency(file.group, file.artifact, managedKeys.contains(MavenPomSelectionComponent.getKey(file)) ? null : file.version, scope, file.type, file.classifier);
+ this.dependencies.add(dep);
+ }
+ }
+ }
+
+ private Dependency createDependency(String groupID, String artifactID, String version, String scope, String type, String classifier) {
+ Dependency dependency = PomFactory.eINSTANCE.createDependency();
+ dependency.setGroupId(groupID);
+ dependency.setArtifactId(artifactID);
+ if (version != null) {
+ dependency.setVersion(version);
+ }
+ dependency.setClassifier(classifier);
+
+ /*
+ * For scope and type, if the values are the default, don't save them.
+ * This reduces clutter in the XML file (although forces people who don't
+ * know what the defaults are to look them up).
+ */
+ dependency.setScope("compile".equals(scope) ? "" : scope); //$NON-NLS-1$ //$NON-NLS-2$
+ dependency.setType("jar".equals(type) ? "" : type); //$NON-NLS-1$ //$NON-NLS-2$
+
+ return dependency;
+ }
+
+ public java.util.List<Dependency> getDependencies() {
+ return this.dependencies;
+ }
+
+ void setInfo(int status, String message) {
+ updateStatus(new Status(status, IMavenConstants.PLUGIN_ID, message));
+ }
+
+ public final class SelectionListener implements ISelectionChangedListener {
+ public void selectionChanged(SelectionChangedEvent event) {
+ IStructuredSelection selection = (IStructuredSelection) event.getSelection();
+ if(selection.isEmpty()) {
+ infoTextarea.setText(""); //$NON-NLS-1$
+ artifactFiles = null;
+ updateStatus();
+ } else {
+ String artifact = null;
+ String group = null;
+ String version = null;
+
+ artifactFiles = new LinkedList<IndexedArtifactFile>();
+ StringBuffer buffer = new StringBuffer();
+ Iterator iter = selection.iterator();
+ while(iter.hasNext()) {
+ Object obj = iter.next();
+ IndexedArtifactFile file = null;
+ boolean managed = false;
+ if(obj instanceof IndexedArtifact) {
+ //the idea here is that if we have a managed version for something, then the IndexedArtifact shall
+ //represent that value..
+ IndexedArtifact ia = (IndexedArtifact)obj;
+ if (managedKeys.contains(MavenPomSelectionComponent.getKey(ia))) {
+ for (IndexedArtifactFile f : ia.getFiles()) {
+ if (managedKeys.contains(MavenPomSelectionComponent.getKey(f))) {
+ file = f;
+ managed = true;
+ break;
+ }
+ }
+ }
+ if (file == null) {
+ file = ((IndexedArtifact) obj).getFiles().iterator().next();
+ }
+ } else {
+ file = (IndexedArtifactFile) obj;
+ if (managedKeys.contains(MavenPomSelectionComponent.getKey(file))) {
+ managed = true;
+ }
+ }
+
+ appendFileInfo(buffer, file);
+ artifactFiles.add(file);
+
+ artifact = chooseWidgetText(artifact, file.artifact);
+ group = chooseWidgetText(group, file.group);
+ version = chooseWidgetText(version, managed ? "" : file.version);
+ }
+ setInfo(OK, NLS.bind(artifactFiles.size() == 1 ? Messages.AddDependencyDialog_itemSelected
+ : Messages.AddDependencyDialog_itemsSelected, artifactFiles.size()));
+ infoTextarea.setText(buffer.toString());
+
+ updating = true;
+ artifactIDtext.setText(artifact);
+ groupIDtext.setText(group);
+ versionText.setText(version);
+ updating = false;
+
+ boolean enabled = !(artifactFiles.size() > 1);
+ artifactIDtext.setEnabled(enabled);
+ groupIDtext.setEnabled(enabled);
+ versionText.setEnabled(enabled);
+ }
+ }
+ }
+
+ private class SearchJob extends Job {
+
+ private String query;
+
+ private IndexManager indexManager;
+
+ private boolean cancelled = false;
+
+ public SearchJob(String query, IndexManager indexManager) {
+ super(NLS.bind(Messages.AddDependencyDialog_searchingFor, query));
+ this.query = query;
+ this.indexManager = indexManager;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected IStatus run(IProgressMonitor monitor) {
+ if(this.cancelled || resultsViewer == null || resultsViewer.getControl() == null
+ || resultsViewer.getControl().isDisposed()) {
+ return Status.CANCEL_STATUS;
+ }
+
+ try {
+ setResults(IStatus.OK, Messages.AddDependencyDialog_searching, Collections.<String, IndexedArtifact> emptyMap());
+ // TODO: before it was searching all indexes, but it should current project? (cstamas)
+ // If not, the change getIndex(project) to getAllIndexes() and done
+ // TODO: cstamas identified this as "user input", true?
+ Map<String, IndexedArtifact> results = indexManager.getIndex(project).search(
+ new UserInputSearchExpression(query), IIndex.SEARCH_ARTIFACT, IIndex.SEARCH_JARS + IIndex.SEARCH_TESTS);
+ setResults(IStatus.OK, NLS.bind(Messages.AddDependencyDialog_searchDone, results.size()), results);
+ } catch(BooleanQuery.TooManyClauses exception) {
+ setResults(IStatus.ERROR, Messages.AddDependencyDialog_tooManyResults,
+ Collections.<String, IndexedArtifact> emptyMap());
+ } catch(RuntimeException exception) {
+ setResults(IStatus.ERROR, NLS.bind(Messages.AddDependencyDialog_searchError, exception.toString()),
+ Collections.<String, IndexedArtifact> emptyMap());
+ } catch(CoreException ex) {
+ setResults(IStatus.ERROR, NLS.bind(Messages.AddDependencyDialog_searchError, ex.getMessage()),
+ Collections.<String, IndexedArtifact> emptyMap());
+ MavenLogger.log(ex);
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.Job#canceling()
+ */
+ protected void canceling() {
+ this.cancelled = true;
+ super.canceling();
+ }
+
+ private void setResults(final int status, final String infoMessage, final Map<String, IndexedArtifact> results) {
+ if(cancelled) {
+ return;
+ }
+
+ Display.getDefault().syncExec(new Runnable() {
+
+ public void run() {
+ if(status == IStatus.OK) {
+ infoTextarea.setText(infoMessage);
+ } else {
+ setInfo(status, infoMessage);
+ }
+ if(results != null && resultsViewer != null && resultsViewer.getControl() != null
+ && !resultsViewer.getControl().isDisposed()) {
+ resultsViewer.setInput(results);
+ }
+ }
+ });
+ }
+
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/EditDependencyDialog.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/EditDependencyDialog.java
new file mode 100644
index 00000000..fe1a7848
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/EditDependencyDialog.java
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.dialogs;
+
+import static org.eclipse.m2e.core.ui.internal.util.Util.nvl;
+
+import org.apache.maven.project.MavenProject;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.edit.command.SetCommand;
+import org.eclipse.emf.edit.domain.EditingDomain;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.ui.internal.search.util.Packaging;
+import org.eclipse.m2e.core.ui.internal.util.M2EUIUtils;
+import org.eclipse.m2e.core.ui.internal.util.ProposalUtil;
+import org.eclipse.m2e.model.edit.pom.Dependency;
+import org.eclipse.m2e.model.edit.pom.PomPackage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+
+public class EditDependencyDialog extends AbstractMavenDialog {
+ protected static PomPackage POM_PACKAGE = PomPackage.eINSTANCE;
+
+ private static final String[] TYPES = new String[] {"jar", "war", "rar", "ear", "par", "ejb", "ejb-client", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
+ "test-jar", "java-source", "javadoc", "maven-plugin", "pom"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
+ private EditingDomain editingDomain;
+
+ private IProject project;
+
+ private String[] scopes;
+
+ protected Text groupIdText;
+
+ protected Text artifactIdText;
+
+ protected Text versionText;
+
+ protected Text classifierText;
+
+ protected Combo typeCombo;
+
+ protected Combo scopeCombo;
+
+ protected Text systemPathText;
+
+// protected Button selectSystemPathButton;
+
+ protected Button optionalButton;
+
+ private Dependency dependency;
+
+ private MavenProject mavenproject;
+
+ public EditDependencyDialog(Shell parent, boolean dependencyManagement, EditingDomain editingDomain, IProject project, MavenProject mavenProject) {
+ super(parent, EditDependencyDialog.class.getName());
+ this.editingDomain = editingDomain;
+ this.project = project;
+ this.mavenproject = mavenProject;
+
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ setTitle(Messages.EditDependencyDialog_title);
+
+ if(!dependencyManagement) {
+ scopes = MavenRepositorySearchDialog.SCOPES;
+ } else {
+ scopes = MavenRepositorySearchDialog.DEP_MANAGEMENT_SCOPES;
+ }
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ readSettings();
+ Composite superComposite = (Composite) super.createDialogArea(parent);
+
+ Composite composite = new Composite(superComposite, SWT.NONE);
+ composite.setLayout(new GridLayout(3, false));
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ Label groupIdLabel = new Label(composite, SWT.NONE);
+ groupIdLabel.setText(Messages.EditDependencyDialog_groupId_label);
+
+ groupIdText = new Text(composite, SWT.BORDER);
+ GridData gd_groupIdText = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1);
+ gd_groupIdText.horizontalIndent = 4;
+ groupIdText.setLayoutData(gd_groupIdText);
+ ProposalUtil.addGroupIdProposal(project, groupIdText, Packaging.ALL);
+ M2EUIUtils.addRequiredDecoration(groupIdText);
+
+ Label artifactIdLabel = new Label(composite, SWT.NONE);
+ artifactIdLabel.setText(Messages.EditDependencyDialog_artifactId_label);
+
+ artifactIdText = new Text(composite, SWT.BORDER);
+ GridData gd_artifactIdText = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1);
+ gd_artifactIdText.horizontalIndent = 4;
+ artifactIdText.setLayoutData(gd_artifactIdText);
+ ProposalUtil.addArtifactIdProposal(project, groupIdText, artifactIdText, Packaging.ALL);
+ M2EUIUtils.addRequiredDecoration(artifactIdText);
+
+ Label versionLabel = new Label(composite, SWT.NONE);
+ versionLabel.setText(Messages.EditDependencyDialog_version_label);
+
+ versionText = new Text(composite, SWT.BORDER);
+ GridData versionTextData = new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1);
+ versionTextData.horizontalIndent = 4;
+ versionTextData.widthHint = 200;
+ versionText.setLayoutData(versionTextData);
+ ProposalUtil.addVersionProposal(project, mavenproject, groupIdText, artifactIdText, versionText, Packaging.ALL);
+
+ Label classifierLabel = new Label(composite, SWT.NONE);
+ classifierLabel.setText(Messages.EditDependencyDialog_classifier_label);
+
+ classifierText = new Text(composite, SWT.BORDER);
+ GridData gd_classifierText = new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1);
+ gd_classifierText.horizontalIndent = 4;
+ gd_classifierText.widthHint = 200;
+ classifierText.setLayoutData(gd_classifierText);
+ ProposalUtil
+ .addClassifierProposal(project, groupIdText, artifactIdText, versionText, classifierText, Packaging.ALL);
+
+ Label typeLabel = new Label(composite, SWT.NONE);
+ typeLabel.setText(Messages.EditDependencyDialog_type_label);
+
+ typeCombo = new Combo(composite, SWT.NONE);
+ typeCombo.setItems(TYPES);
+ GridData gd_typeText = new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1);
+ gd_typeText.horizontalIndent = 4;
+ gd_typeText.widthHint = 120;
+ typeCombo.setLayoutData(gd_typeText);
+
+ Label scopeLabel = new Label(composite, SWT.NONE);
+ scopeLabel.setText(Messages.EditDependencyDialog_scope_label);
+
+ scopeCombo = new Combo(composite, SWT.NONE);
+ scopeCombo.setItems(scopes);
+ GridData gd_scopeText = new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1);
+ gd_scopeText.horizontalIndent = 4;
+ gd_scopeText.widthHint = 120;
+ scopeCombo.setLayoutData(gd_scopeText);
+
+ Label systemPathLabel = new Label(composite, SWT.NONE);
+ systemPathLabel.setText(Messages.EditDependencyDialog_systemPath_label);
+
+ systemPathText = new Text(composite, SWT.BORDER);
+ GridData gd_systemPathText = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1);
+ gd_systemPathText.horizontalIndent = 4;
+ gd_systemPathText.widthHint = 200;
+ systemPathText.setLayoutData(gd_systemPathText);
+
+// selectSystemPathButton = new Button(composite, SWT.NONE);
+// selectSystemPathButton.setText("Select...");
+
+ new Label(composite, SWT.NONE);
+
+ optionalButton = new Button(composite, SWT.CHECK);
+ optionalButton.setText(Messages.EditDependencyDialog_optional_checkbox);
+ GridData gd_optionalButton = new GridData(SWT.LEFT, SWT.TOP, false, false, 2, 1);
+ gd_optionalButton.horizontalIndent = 4;
+ optionalButton.setLayoutData(gd_optionalButton);
+
+ composite.setTabList(new Control[] {groupIdText, artifactIdText, versionText, classifierText, typeCombo,
+ scopeCombo, systemPathText, /*selectSystemPathButton,*/optionalButton});
+
+ setDependency(dependency);
+
+ return superComposite;
+ }
+
+ protected void computeResult() {
+ CompoundCommand compoundCommand = new CompoundCommand();
+ compoundCommand.append(createCommand(groupIdText.getText(), POM_PACKAGE.getDependency_GroupId(), "")); //$NON-NLS-1$
+ compoundCommand.append(createCommand(artifactIdText.getText(), POM_PACKAGE.getDependency_ArtifactId(), "")); //$NON-NLS-1$
+ compoundCommand.append(createCommand(versionText.getText(), POM_PACKAGE.getDependency_Version(), "")); //$NON-NLS-1$
+ compoundCommand.append(createCommand(classifierText.getText(), POM_PACKAGE.getDependency_Classifier(), "")); //$NON-NLS-1$
+ compoundCommand.append(createCommand(typeCombo.getText(), POM_PACKAGE.getDependency_Type(), "jar")); //$NON-NLS-1$
+ compoundCommand.append(createCommand(scopeCombo.getText(), POM_PACKAGE.getDependency_Scope(), "compile")); //$NON-NLS-1$
+ compoundCommand.append(createCommand(systemPathText.getText(), POM_PACKAGE.getDependency_SystemPath(), "")); //$NON-NLS-1$
+ compoundCommand.append(createCommand(String.valueOf(optionalButton.getSelection()),
+ POM_PACKAGE.getDependency_Optional(), "false")); //$NON-NLS-1$
+ editingDomain.getCommandStack().execute(compoundCommand);
+ }
+
+ public void setDependency(Dependency dependency) {
+ this.dependency = dependency;
+
+ if(dependency != null && groupIdText != null && !groupIdText.isDisposed()) {
+ groupIdText.setText(nvl(dependency.getGroupId()));
+ artifactIdText.setText(nvl(dependency.getArtifactId()));
+ versionText.setText(nvl(dependency.getVersion()));
+ classifierText.setText(nvl(dependency.getClassifier()));
+ typeCombo.setText("".equals(nvl(dependency.getType())) ? "jar" : dependency.getType()); //$NON-NLS-1$ //$NON-NLS-2$
+ scopeCombo.setText("".equals(nvl(dependency.getScope())) ? "compile" : dependency.getScope()); //$NON-NLS-1$ //$NON-NLS-2$
+ systemPathText.setText(nvl(dependency.getSystemPath()));
+
+ boolean optional = Boolean.parseBoolean(dependency.getOptional());
+ if(optionalButton.getSelection() != optional) {
+ optionalButton.setSelection(optional);
+ }
+ }
+ }
+
+ private Command createCommand(String value, Object feature, String defaultValue) {
+ return SetCommand.create(editingDomain, dependency, feature,
+ value.length() == 0 || value.equals(defaultValue) ? SetCommand.UNSET_VALUE : value);
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/InputHistory.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/InputHistory.java
new file mode 100644
index 00000000..c585956d
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/InputHistory.java
@@ -0,0 +1,231 @@
+
+package org.eclipse.m2e.core.ui.internal.dialogs;
+
+import java.beans.Beans;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.custom.CCombo;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Control;
+
+
+public class InputHistory {
+ /** the history limit */
+ protected static final int MAX_HISTORY = 10;
+
+ /** dialog settings to store input history */
+ protected IDialogSettings dialogSettings;
+
+ /** the Map of field ids to List of comboboxes that share the same history */
+ private Map<String, List<ControlWrapper>> comboMap;
+
+ private List<String> privileged;
+
+ public InputHistory(String sectionName) {
+ this(sectionName, new String[0]);
+ }
+
+ public InputHistory(String sectionName, String[] privileged) {
+ comboMap = new HashMap<String, List<ControlWrapper>>();
+
+ M2EUIPluginActivator plugin = M2EUIPluginActivator.getDefault();
+ if(plugin != null) {
+ IDialogSettings pluginSettings = plugin.getDialogSettings();
+ dialogSettings = pluginSettings.getSection(sectionName);
+ if(dialogSettings == null) {
+ dialogSettings = pluginSettings.addNewSection(sectionName);
+ pluginSettings.addSection(dialogSettings);
+ }
+ }
+ assert privileged != null;
+ this.privileged = Arrays.asList(privileged);
+ }
+
+ /** Loads the input history from the dialog settings. */
+ public void load() {
+ if(Beans.isDesignTime()) {
+ return;
+ }
+
+ for(Map.Entry<String, List<ControlWrapper>> e : comboMap.entrySet()) {
+ String id = e.getKey();
+ Set<String> items = new LinkedHashSet<String>();
+ String[] itemsArr = dialogSettings.getArray(id);
+ items.addAll(privileged);
+ if(itemsArr != null) {
+ items.addAll(Arrays.asList(itemsArr));
+ }
+ for(ControlWrapper wrapper : e.getValue()) {
+ if(!wrapper.isDisposed()) {
+ wrapper.setItems(items.toArray(new String[0]));
+ }
+ }
+ }
+ }
+
+ /** Saves the input history into the dialog settings. */
+ public void save() {
+ if(Beans.isDesignTime()) {
+ return;
+ }
+
+ for(Map.Entry<String, List<ControlWrapper>> e : comboMap.entrySet()) {
+ String id = e.getKey();
+
+ Set<String> history = new LinkedHashSet<String>(MAX_HISTORY);
+
+ for(ControlWrapper wrapper : e.getValue()) {
+ wrapper.collect();
+ String lastValue = wrapper.text;
+ if(lastValue != null && lastValue.trim().length() > 0) {
+ history.add(lastValue);
+ }
+ }
+
+ ControlWrapper wrapper = e.getValue().iterator().next();
+ String[] items = wrapper.items;
+ if(items != null) {
+ for(int j = 0; j < items.length && history.size() < MAX_HISTORY; j++ ) {
+ // do not store the privileged items if they are not selected.
+ // we eventually inject the same or different set next time
+ if(!privileged.contains(items[j])) {
+ history.add(items[j]);
+ }
+ }
+ }
+
+ dialogSettings.put(id, history.toArray(new String[history.size()]));
+ }
+ }
+
+ /** Adds an input control to the list of fields to save. */
+ public void add(Control combo) {
+ add(null, combo);
+ }
+
+ /** Adds an input control to the list of fields to save. */
+ public void add(String id, final Control combo) {
+ if(combo != null) {
+ if(id == null) {
+ id = String.valueOf(combo.getData("name"));
+ }
+ List<ControlWrapper> combos = comboMap.get(id);
+ if(combos == null) {
+ combos = new ArrayList<ControlWrapper>();
+ comboMap.put(id, combos);
+ }
+ if(combo instanceof Combo) {
+ combos.add(new ComboWrapper((Combo) combo));
+ } else if(combo instanceof CCombo) {
+ combos.add(new CComboWrapper((CCombo) combo));
+ }
+ }
+ }
+
+ abstract private class ControlWrapper {
+ protected Control control;
+
+ protected String text;
+
+ protected String[] items;
+
+ private boolean collected;
+
+ protected ControlWrapper(Control control) {
+ this.control = control;
+ control.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ collect();
+ }
+ });
+ }
+
+ protected void collect() {
+ if(!collected && !isDisposed()) {
+ text = getText();
+ items = getItems();
+ }
+ collected = true;
+ }
+
+ protected boolean isDisposed() {
+ return control.isDisposed();
+ }
+
+ abstract protected String getText();
+
+ abstract protected String[] getItems();
+
+ abstract protected void setItems(String[] items);
+ }
+
+ private class ComboWrapper extends ControlWrapper {
+ private Combo combo;
+
+ protected ComboWrapper(Combo combo) {
+ super(combo);
+ this.combo = combo;
+ }
+
+ protected String getText() {
+ return combo.getText();
+ }
+
+ protected String[] getItems() {
+ return combo.getItems();
+ }
+
+ protected void setItems(String[] items) {
+ String value = combo.getText();
+ combo.setItems(items);
+ if(value.length() > 0) {
+ // setItems() clears the text input, so we need to restore it
+ combo.setText(value);
+ } else if(items.length > 0) {
+ combo.setText(items[0]);
+ }
+ }
+ }
+
+ private class CComboWrapper extends ControlWrapper {
+ private CCombo combo;
+
+ protected CComboWrapper(CCombo combo) {
+ super(combo);
+ this.combo = combo;
+ }
+
+ protected String getText() {
+ return combo.getText();
+ }
+
+ protected String[] getItems() {
+ try {
+ return combo.getItems();
+ } catch(SWTException swtException) {
+ //CCombo throws this if the list is disposed, but the combo itself is not disposed yet
+ return new String[0];
+ }
+ }
+
+ protected void setItems(String[] items) {
+ String value = combo.getText();
+ combo.setItems(items);
+ if(value.length() > 0) {
+ // setItems() clears the text input, so we need to restore it
+ combo.setText(value);
+ }
+ }
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenGoalSelectionDialog.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenGoalSelectionDialog.java
new file mode 100644
index 00000000..f6ada911
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenGoalSelectionDialog.java
@@ -0,0 +1,358 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.dialogs;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.index.IIndex;
+import org.eclipse.m2e.core.index.IndexManager;
+import org.eclipse.m2e.core.index.IndexedArtifact;
+import org.eclipse.m2e.core.index.IndexedArtifactFile;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
+import org.eclipse.ui.dialogs.ISelectionStatusValidator;
+
+
+public class MavenGoalSelectionDialog extends ElementTreeSelectionDialog {
+
+ Button isQualifiedNameButton;
+
+ boolean isQualifiedName = true;
+
+ public MavenGoalSelectionDialog(Shell parent) {
+ super(parent, new GoalsLabelProvider(), new GoalsContentProvider());
+
+ setTitle(Messages.getString("launch.goalsDialog.title")); //$NON-NLS-1$
+ setMessage(org.eclipse.m2e.core.internal.Messages.MavenGoalSelectionDialog_message);
+ setValidator(new GoalsSelectionValidator());
+ setInput(new Object());
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+ layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+ layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+ layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Label selectGoalLabel = new Label(composite, SWT.NONE);
+ selectGoalLabel.setText(org.eclipse.m2e.core.internal.Messages.MavenGoalSelectionDialog_lblSelect);
+
+ final GoalsFilter filter = new GoalsFilter();
+
+ final Text filterText = new Text(composite, SWT.BORDER);
+ GridData gd_filterText = new GridData(SWT.FILL, SWT.CENTER, true, false);
+ gd_filterText.widthHint = 200;
+ filterText.setLayoutData(gd_filterText);
+ filterText.setFocus();
+
+ final TreeViewer treeViewer = createTreeViewer(composite);
+ treeViewer.addFilter(filter);
+
+ GridData data = new GridData(GridData.FILL_BOTH);
+ data.widthHint = 500;
+ data.heightHint = 400;
+ // data.widthHint = convertWidthInCharsToPixels(fWidth);
+ // data.heightHint = convertHeightInCharsToPixels(fHeight);
+
+ final Tree tree = treeViewer.getTree();
+ tree.setLayoutData(data);
+ tree.setFont(parent.getFont());
+
+ filterText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ String text = filterText.getText();
+ filter.setFilter(text);
+ treeViewer.refresh();
+ if(text.trim().length() == 0) {
+ treeViewer.collapseAll();
+ } else {
+ treeViewer.expandAll();
+ }
+ }
+ });
+
+ filterText.addKeyListener(new KeyAdapter() {
+ public void keyPressed(KeyEvent e) {
+ if(e.keyCode == SWT.ARROW_DOWN) {
+ tree.setFocus();
+ tree.setSelection(tree.getTopItem().getItem(0));
+
+ Object[] elements = ((ITreeContentProvider) treeViewer.getContentProvider()).getElements(null);
+ treeViewer.setSelection(new StructuredSelection(elements[0]));
+ }
+
+ }
+ });
+
+ isQualifiedNameButton = new Button(composite, SWT.CHECK);
+ isQualifiedNameButton.setText(org.eclipse.m2e.core.internal.Messages.MavenGoalSelectionDialog_btnQualified);
+ isQualifiedNameButton.setSelection(true);
+ isQualifiedNameButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ isQualifiedName = isQualifiedNameButton.getSelection();
+ }
+ });
+
+// if (fIsEmpty) {
+// messageLabel.setEnabled(false);
+// treeWidget.setEnabled(false);
+// }
+
+ return composite;
+ }
+
+ public boolean isQualifiedName() {
+ return isQualifiedName;
+ }
+
+ /**
+ * GoalsContentProvider
+ */
+ static class GoalsContentProvider implements ITreeContentProvider {
+ private static Object[] EMPTY = new Object[0];
+
+ private final List<Group> groups = new ArrayList<Group>();
+
+ public GoalsContentProvider() {
+// MavenEmbedderManager embedderManager = MavenPlugin.getDefault().getMavenEmbedderManager();
+// try {
+// MavenEmbedder embedder = embedderManager.getWorkspaceEmbedder();
+// groups.add(new Group(Messages.getString("launch.goalsDialog.lifecycleBuild"), //$NON-NLS-1$
+// null, null, getLifecyclePhases(embedder.getBuildLifecyclePhases())));
+// groups.add(new Group(Messages.getString("launch.goalsDialog.lifecycleSite"), //$NON-NLS-1$
+// null, null, getLifecyclePhases(embedder.getSiteLifecyclePhases())));
+// groups.add(new Group(Messages.getString("launch.goalsDialog.lifecycleClean"), //$NON-NLS-1$
+// null, null, getLifecyclePhases(embedder.getCleanLifecyclePhases())));
+// } catch(Exception e) {
+// MavenLogger.log("Unable to get lifecycle phases", e);
+// }
+
+ IndexManager indexManager = MavenPlugin.getDefault().getIndexManager();
+ try {
+ // TODO: this will search ALL indexes, isn't the right to search _this_ project reposes only?
+ // I did not find (at first glance, maybe was hasty) a way to get IProject
+ Map<String, IndexedArtifact> result = indexManager.getAllIndexes().search(null, IIndex.SEARCH_PLUGIN); //$NON-NLS-1$
+ TreeMap<String, Group> map = new TreeMap<String, Group>();
+ for(IndexedArtifact a : result.values()) {
+ IndexedArtifactFile f = a.getFiles().iterator().next();
+ if(f.prefix != null && f.prefix.length() > 0 && f.goals != null) {
+ List<Entry> goals = new ArrayList<Entry>();
+ for(String goal : f.goals) {
+ if(goal.length() > 0) {
+ goals.add(new Entry(goal, f.prefix, f));
+ }
+ }
+ if(goals.size() > 0) {
+ map.put(f.prefix + ":" + f.group, new Group(f.prefix, f.group, f.artifact, goals)); //$NON-NLS-1$
+ }
+ }
+ }
+ groups.addAll(map.values());
+ } catch(CoreException e) {
+ MavenLogger.log(e);
+ }
+ }
+
+ private List<Entry> getLifecyclePhases(List<?> phases) {
+ List<Entry> entries = new ArrayList<Entry>();
+ for(int i = 0; i < phases.size(); i++ ) {
+ entries.add(new Entry((String) phases.get(i), null, null));
+ }
+ return entries;
+ }
+
+ public Object[] getElements(Object inputElement) {
+ return groups.toArray();
+ }
+
+ public Object[] getChildren(Object parent) {
+ if(parent instanceof Group) {
+ return ((Group) parent).entries.toArray();
+ }
+ return EMPTY;
+ }
+
+ public boolean hasChildren(Object element) {
+ return element instanceof Group;
+ }
+
+ public Object getParent(Object element) {
+ return null;
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ public void dispose() {
+ }
+
+ }
+
+ /**
+ * GoalsLabelProvider
+ */
+ static class GoalsLabelProvider extends LabelProvider {
+ public String getText(Object element) {
+ if(element instanceof Group) {
+ Group g = (Group) element;
+ if(g.groupId == null) {
+ return g.name;
+ }
+ return g.name + " - " + g.groupId + ":" + g.artifactId; //$NON-NLS-1$ //$NON-NLS-2$
+
+ } else if(element instanceof Entry) {
+ return ((Entry) element).name;
+
+ }
+ return super.getText(element);
+ }
+ }
+
+ /**
+ * GoalsFilter
+ */
+ static class GoalsFilter extends ViewerFilter {
+ private String filter;
+
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ if(filter == null || filter.trim().length() == 0) {
+ return true;
+ }
+ if(element instanceof Group) {
+ Group g = (Group) element;
+ if(g.name.indexOf(filter) > -1) {
+ return true;
+ }
+ for(Iterator<Entry> it = g.entries.iterator(); it.hasNext();) {
+ Entry e = it.next();
+ if(e.name.indexOf(filter) > -1) {
+ return true;
+ }
+ }
+
+ } else if(element instanceof Entry) {
+ Entry e = (Entry) element;
+ return e.name.indexOf(filter) > -1 || (e.prefix != null && e.prefix.indexOf(filter) > -1);
+
+ }
+ return false;
+ }
+
+ public void setFilter(String filter) {
+ this.filter = filter;
+ }
+ }
+
+ /**
+ * GoalsSelectionValidator
+ */
+ static class GoalsSelectionValidator implements ISelectionStatusValidator {
+ public IStatus validate(Object[] selection) {
+ if(selection.length == 0) {
+ return new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, -1,
+ org.eclipse.m2e.core.internal.Messages.MavenGoalSelectionDialog_error, null);
+ }
+ for(int j = 0; j < selection.length; j++ ) {
+ if(selection[j] instanceof Entry) {
+ continue;
+ }
+ return new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, -1, "", null); //$NON-NLS-1$
+ }
+ return Status.OK_STATUS;
+ }
+ }
+
+ /**
+ * Group
+ */
+ static class Group {
+ public final String name;
+
+ public final String groupId;
+
+ public final String artifactId;
+
+ public final List<Entry> entries;
+
+ public Group(String name, String groupId, String artifactId, List<Entry> entries) {
+ this.name = name;
+ this.groupId = groupId;
+ this.artifactId = artifactId;
+ this.entries = entries;
+ }
+ }
+
+ /**
+ * Entry
+ */
+ public static class Entry {
+ public final String prefix;
+
+ public final String name;
+
+ private final IndexedArtifactFile f;
+
+ public Entry(String name, String prefix, IndexedArtifactFile f) {
+ this.prefix = prefix;
+ this.name = name;
+ this.f = f;
+ }
+
+ public String getName() {
+ return prefix == null ? name : prefix + ":" + name; //$NON-NLS-1$
+ }
+
+ public String getQualifiedName() {
+ // return prefix == null ? name : prefix + ":" + name;
+ return prefix == null ? name : f.group + ":" + f.artifact + ":" + f.version + ":" + name; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenMessageDialog.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenMessageDialog.java
new file mode 100644
index 00000000..8dd4c980
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenMessageDialog.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.dialogs;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * MavenMessageDialog
+ *
+ * @author dyocum
+ */
+public class MavenMessageDialog extends MessageDialog {
+
+ private StyledText messageArea;
+ /**
+ * @param parentShell
+ * @param dialogTitle
+ * @param dialogTitleImage
+ * @param dialogMessage
+ * @param dialogImageType
+ * @param dialogButtonLabels
+ * @param defaultIndex
+ */
+ public MavenMessageDialog(Shell parentShell, String dialogTitle, Image dialogTitleImage, String dialogMessage,
+ int dialogImageType, String[] dialogButtonLabels, int defaultIndex) {
+ super(parentShell, dialogTitle, dialogTitleImage, dialogMessage, dialogImageType, dialogButtonLabels, defaultIndex);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.MessageDialog#createCustomArea(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createCustomArea(Composite parent) {
+ // TODO Auto-generated method createCustomArea
+ this.messageArea = new StyledText(parent, SWT.WRAP|SWT.READ_ONLY|SWT.H_SCROLL|SWT.V_SCROLL|SWT.BORDER);
+ this.messageArea.setLayout(new GridLayout());
+ GridData gd = new GridData(SWT.LEFT, SWT.TOP, true, true);
+ //size hints
+ gd.widthHint = 600;
+ gd.heightHint = 300;
+ messageArea.setLayoutData(gd);
+ return messageArea;
+ }
+
+ /**
+ *
+ * @param parent Parent shell
+ * @param title Title of the dialog
+ * @param label The label shown above the msg.
+ * @param message The actual message to show in the text area.
+ */
+ public static void openInfo(Shell parent, String title, String label, String message) {
+ MavenMessageDialog dialog = new MavenMessageDialog(parent, title, Display.getDefault().getSystemImage(SWT.ICON_INFORMATION), // accept
+ label, INFORMATION, new String[] { IDialogConstants.OK_LABEL }, 0); // ok
+ dialog.create();
+ dialog.getMessageArea().setText(message);
+ dialog.getDialogArea().pack(true);
+ dialog.open();
+ return;
+ }
+
+ /**
+ *
+ * @param parent
+ * @param title
+ * @param label
+ * @param message
+ * @param severity constants from MessageDialog
+ */
+ public static void openWithSeverity(Shell parent, String title, String label, String message, int severity) {
+ Image icon = severity == IMessageProvider.ERROR ? Display.getDefault().getSystemImage(SWT.ICON_ERROR) : Display.getDefault().getSystemImage(SWT.ICON_INFORMATION);
+ MavenMessageDialog dialog = new MavenMessageDialog(parent, title, icon, // accept
+ label, severity, new String[] { IDialogConstants.OK_LABEL }, 0); // ok
+ dialog.create();
+ dialog.getMessageArea().setText(message);
+ dialog.getDialogArea().pack(true);
+ dialog.open();
+ return;
+ }
+ /**
+ * @return Returns the messageArea.
+ */
+ private StyledText getMessageArea() {
+ return messageArea;
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenPropertyDialog.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenPropertyDialog.java
new file mode 100644
index 00000000..0e5cc359
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenPropertyDialog.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.dialogs;
+
+// import org.eclipse.debug.ui.StringVariableSelectionDialog;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+
+public class MavenPropertyDialog extends Dialog {
+
+ private final String title;
+
+ private final String initialName;
+
+ private final String initialValue;
+
+ private final VerifyListener verifyListener;
+
+ protected Text nameText;
+
+ protected Text valueText;
+
+ private String name;
+
+ private String value;
+
+ public MavenPropertyDialog(Shell shell, String title, String initialName, String initialValue, VerifyListener verifyListener) {
+ super(shell);
+ this.title = title;
+ this.initialName = initialName;
+ this.initialValue = initialValue;
+ this.verifyListener = verifyListener;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createDialogArea(Composite parent) {
+ Composite comp = new Composite(parent, SWT.NONE);
+ GridLayout gridLayout = new GridLayout(2, false);
+ gridLayout.marginTop = 7;
+ gridLayout.marginWidth = 12;
+ comp.setLayout(gridLayout);
+
+ Label nameLabel = new Label(comp, SWT.NONE);
+ nameLabel.setText(Messages.getString("launch.propertyDialog.name")); //$NON-NLS-1$;
+ nameLabel.setFont(comp.getFont());
+
+ nameText = new Text(comp, SWT.BORDER | SWT.SINGLE);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 300;
+ nameText.setLayoutData(gd);
+ nameText.setFont(comp.getFont());
+ nameText.setText(initialName==null ? "" : initialName); //$NON-NLS-1$
+ nameText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ updateButtons();
+ }
+ });
+
+ Label valueLabel = new Label(comp, SWT.NONE);
+ valueLabel.setText(Messages.getString("launch.propertyDialog.value")); //$NON-NLS-1$;
+ valueLabel.setFont(comp.getFont());
+
+ valueText = new Text(comp, SWT.BORDER | SWT.SINGLE);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 300;
+ valueText.setLayoutData(gd);
+ valueText.setFont(comp.getFont());
+ valueText.setText(initialValue==null ? "" : initialValue); //$NON-NLS-1$
+ valueText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ updateButtons();
+ }
+ });
+
+// if(variables) {
+// Button variablesButton = new Button(comp, SWT.PUSH);
+// variablesButton.setText(Messages.getString("launch.propertyDialog.browseVariables")); //$NON-NLS-1$;
+// gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
+// gd.horizontalSpan = 2;
+// int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
+// gd.widthHint = Math.max(widthHint, variablesButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
+// variablesButton.setLayoutData(gd);
+// variablesButton.setFont(comp.getFont());
+//
+// variablesButton.addSelectionListener(new SelectionAdapter() {
+// public void widgetSelected(SelectionEvent se) {
+// StringVariableSelectionDialog variablesDialog = new StringVariableSelectionDialog(getShell());
+// if(variablesDialog.open() == IDialogConstants.OK_ID) {
+// String variable = variablesDialog.getVariableExpression();
+// if(variable != null) {
+// valueText.insert(variable.trim());
+// }
+// }
+// }
+// });
+// }
+
+ return comp;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int)
+ */
+ protected void buttonPressed(int buttonId) {
+ if(buttonId == IDialogConstants.OK_ID) {
+ name = nameText.getText();
+ value = valueText.getText();
+ } else {
+ name = null;
+ value = null;
+ }
+ super.buttonPressed(buttonId);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
+ */
+ protected void configureShell(Shell shell) {
+ super.configureShell(shell);
+ if(title != null) {
+ shell.setText(title);
+ }
+// if (fInitialValues[0].length() == 0) {
+// PlatformUI.getWorkbench().getHelpSystem().setHelp(shell, IAntUIHelpContextIds.ADD_PROPERTY_DIALOG);
+// } else {
+// PlatformUI.getWorkbench().getHelpSystem().setHelp(shell, IAntUIHelpContextIds.EDIT_PROPERTY_DIALOG);
+// }
+ }
+
+ /**
+ * Enable the OK button if valid input
+ */
+ protected void updateButtons() {
+ String name = nameText.getText().trim();
+ String value = valueText.getText().trim();
+ // verify name
+ Event e = new Event();
+ e.widget = nameText;
+ VerifyEvent ev = new VerifyEvent(e);
+ ev.doit = true;
+ if (verifyListener != null) {
+ ev.text = name;
+ verifyListener.verifyText(ev);
+ }
+ getButton(IDialogConstants.OK_ID).setEnabled((name.length() > 0) && (value.length() > 0) && ev.doit);
+ }
+
+ /**
+ * Enable the buttons on creation.
+ *
+ * @see org.eclipse.jface.window.Window#create()
+ */
+ public void create() {
+ super.create();
+ updateButtons();
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenRepositorySearchDialog.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenRepositorySearchDialog.java
new file mode 100644
index 00000000..9e05f623
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/dialogs/MavenRepositorySearchDialog.java
@@ -0,0 +1,441 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.dialogs;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.DependencyManagement;
+import org.apache.maven.model.Parent;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.PluginManagement;
+import org.apache.maven.project.MavenProject;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.index.IIndex;
+import org.eclipse.m2e.core.index.IndexedArtifact;
+import org.eclipse.m2e.core.index.IndexedArtifactFile;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.ui.internal.search.util.Packaging;
+import org.eclipse.m2e.core.ui.internal.util.M2EUIUtils;
+import org.eclipse.m2e.core.ui.internal.util.ProposalUtil;
+import org.eclipse.m2e.core.ui.internal.wizards.MavenPomSelectionComponent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Maven POM Search dialog
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenRepositorySearchDialog extends AbstractMavenDialog {
+ private static final String DIALOG_SETTINGS = MavenRepositorySearchDialog.class.getName();
+
+ public static final String[] SCOPES = new String[] {"compile", "provided", "runtime", "test", "system"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
+ /*
+ * dependencies under dependencyManagement are permitted to use an the extra "import" scope
+ */
+ public static final String[] DEP_MANAGEMENT_SCOPES = new String[] {"compile", "provided", "runtime", "test", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ "system", "import"}; //$NON-NLS-1$ //$NON-NLS-2$
+
+
+ /**
+ *
+ * @param parent
+ * @param title
+ * @return
+ */
+ public static MavenRepositorySearchDialog createOpenPomDialog(Shell parent, String title) {
+ return new MavenRepositorySearchDialog(parent, title, IIndex.SEARCH_ARTIFACT, Collections.<ArtifactKey>emptySet(), Collections.<ArtifactKey>emptySet(), false, null, null, false);
+ }
+
+ /**
+ *
+ * @param parent
+ * @param title
+ * @param mp
+ * @param p
+ * @param inManagedSection true when the result will be added to the dependencyManagement section of the pom.
+ * @return
+ */
+ public static MavenRepositorySearchDialog createSearchDependencyDialog(Shell parent, String title, MavenProject mp, IProject p, boolean inManagedSection) {
+ Set<ArtifactKey> artifacts = new HashSet<ArtifactKey>();
+ Set<ArtifactKey> managed = new HashSet<ArtifactKey>();
+ if (mp != null) {
+ Set<ArtifactKey> keys = inManagedSection ? artifacts : managed;
+ DependencyManagement dm = mp.getDependencyManagement();
+ if (dm != null && dm.getDependencies() != null) {
+ for (Dependency dep : dm.getDependencies()) {
+ keys.add(new ArtifactKey(dep.getGroupId(), dep.getArtifactId(), dep.getVersion(), dep.getClassifier()));
+ }
+ }
+ if (!inManagedSection) {
+ for (Dependency dep : mp.getModel().getDependencies()) {
+ artifacts.add(new ArtifactKey(dep.getGroupId(), dep.getArtifactId(), dep.getVersion(), dep.getClassifier()));
+ }
+ }
+ }
+ return new MavenRepositorySearchDialog(parent, title, IIndex.SEARCH_ARTIFACT, artifacts, managed, true, mp, p, true);
+ }
+ /**
+ *
+ * @param parent
+ * @param title
+ * @param mp
+ * @param p
+ * @return
+ */
+ public static MavenRepositorySearchDialog createSearchParentDialog(Shell parent, String title, MavenProject mp, IProject p) {
+ Set<ArtifactKey> artifacts = new HashSet<ArtifactKey>();
+ Set<ArtifactKey> managed = new HashSet<ArtifactKey>();
+ if (mp != null && mp.getModel().getParent() != null) {
+ Parent par = mp.getModel().getParent();
+ artifacts.add(new ArtifactKey(par.getGroupId(), par.getArtifactId(), par.getVersion(), null));
+ }
+ return new MavenRepositorySearchDialog(parent, title, IIndex.SEARCH_PARENTS, artifacts, managed, false, mp, p, true);
+ }
+
+ /**
+ *
+ * @param parent
+ * @param title
+ * @param mp
+ * @param p
+ * @param inManagedSection true when the result will be added to the dependencyManagement section of the pom.
+ * @return
+ */
+ public static MavenRepositorySearchDialog createSearchPluginDialog(Shell parent, String title, MavenProject mp, IProject p, boolean inManagedSection) {
+ Set<ArtifactKey> artifacts = new HashSet<ArtifactKey>();
+ Set<ArtifactKey> managed = new HashSet<ArtifactKey>();
+ Set<ArtifactKey> keys = inManagedSection ? artifacts : managed;
+ if (mp != null && mp.getBuild() != null) {
+ PluginManagement pm = mp.getBuild().getPluginManagement();
+ if (pm != null && pm.getPlugins() != null) {
+ for (Plugin plug : pm.getPlugins()) {
+ keys.add(new ArtifactKey(plug.getGroupId(), plug.getArtifactId(), plug.getVersion(), null));
+ }
+ }
+ if (!inManagedSection && mp.getModel().getBuild() != null) {
+ for (Plugin plug : mp.getModel().getBuild().getPlugins()) {
+ artifacts.add(new ArtifactKey(plug.getGroupId(), plug.getArtifactId(), plug.getVersion(), null));
+ }
+ }
+
+ }
+ return new MavenRepositorySearchDialog(parent, title, IIndex.SEARCH_PLUGIN, artifacts, managed, false, mp, p, true);
+ }
+ private final boolean showScope;
+
+ private final Set<ArtifactKey> artifacts;
+
+ private final Set<ArtifactKey> managed;
+
+ /**
+ * One of
+ * {@link IIndex#SEARCH_ARTIFACT},
+ * {@link IIndex#SEARCH_CLASS_NAME},
+ */
+ private final String queryType;
+
+ private String queryText;
+
+ MavenPomSelectionComponent pomSelectionComponent;
+
+ private IndexedArtifact selectedIndexedArtifact;
+
+ private IndexedArtifactFile selectedIndexedArtifactFile;
+
+ private String selectedScope;
+
+ private Combo comScope;
+
+ private Text txtGroupId;
+
+ private Text txtArtifactId;
+
+ private Text txtVersion;
+
+ private boolean ignoreTextChange = false;
+
+ private IProject project;
+
+ private MavenProject mavenproject;
+
+ private final boolean showCoords;
+
+ private MavenRepositorySearchDialog(Shell parent, String title, String queryType,
+ Set<ArtifactKey> artifacts, Set<ArtifactKey> managed, boolean showScope, MavenProject mp, IProject p, boolean showCoordinates) {
+ super(parent, DIALOG_SETTINGS);
+ this.artifacts = artifacts;
+ this.managed = managed;
+ this.queryType = queryType;
+ this.showScope = showScope;
+ this.project = p;
+ this.mavenproject = mp;
+ this.showCoords = showCoordinates;
+
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ setStatusLineAboveButtons(true);
+ setTitle(title);
+ }
+
+ public void setQuery(String query) {
+ this.queryText = query;
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ readSettings();
+
+ Composite composite = (Composite) super.createDialogArea(parent);
+ if (showCoords) {
+ createGAVControls(composite);
+ Label separator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
+ separator.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ }
+
+ pomSelectionComponent = new MavenPomSelectionComponent(composite, SWT.NONE);
+ pomSelectionComponent.init(queryText, queryType, artifacts, managed);
+
+ pomSelectionComponent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ pomSelectionComponent.addDoubleClickListener(new IDoubleClickListener() {
+ public void doubleClick(DoubleClickEvent event) {
+ if (!pomSelectionComponent.getStatus().matches(IStatus.ERROR)) {
+ okPressedDelegate();
+ }
+ }
+ });
+ pomSelectionComponent.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ updateStatusDelegate(pomSelectionComponent.getStatus());
+ computeResultFromTree();
+ }
+ });
+ pomSelectionComponent.setFocus();
+
+ return composite;
+ }
+
+ /**
+ * Sets the up group-artifact-version controls
+ */
+ private Composite createGAVControls(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ GridLayout gridLayout = new GridLayout(showScope ? 4 : 2, false);
+ gridLayout.marginWidth = 0;
+ gridLayout.horizontalSpacing = 10;
+ composite.setLayout(gridLayout);
+
+ Label groupIDlabel = new Label(composite, SWT.NONE);
+ groupIDlabel.setText(Messages.AddDependencyDialog_groupId_label);
+
+ txtGroupId = new Text(composite, SWT.BORDER);
+ txtGroupId.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ M2EUIUtils.addRequiredDecoration(txtGroupId);
+
+ if (showScope) {
+ new Label(composite, SWT.NONE);
+ new Label(composite, SWT.NONE);
+ }
+
+ Label artifactIDlabel = new Label(composite, SWT.NONE);
+ artifactIDlabel.setText(Messages.AddDependencyDialog_artifactId_label);
+
+ txtArtifactId = new Text(composite, SWT.BORDER);
+ txtArtifactId.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ M2EUIUtils.addRequiredDecoration(txtArtifactId);
+
+ if (showScope) {
+ new Label(composite, SWT.NONE);
+ new Label(composite, SWT.NONE);
+ }
+
+ Label versionLabel = new Label(composite, SWT.NONE);
+ versionLabel.setText(Messages.AddDependencyDialog_version_label);
+
+ txtVersion = new Text(composite, SWT.BORDER);
+ txtVersion.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+
+ if (showScope) {
+ Label scopeLabel = new Label(composite, SWT.NONE);
+ scopeLabel.setText(Messages.AddDependencyDialog_scope_label);
+
+ comScope = new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY);
+ comScope.setItems(SCOPES);
+ GridData scopeListData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
+ comScope.setLayoutData(scopeListData);
+ comScope.setText(SCOPES[0]);
+ }
+
+ if (showScope) {
+ /*
+ * Fix the tab order (group -> artifact -> version -> scope)
+ */
+ composite.setTabList(new Control[] {txtGroupId, txtArtifactId, txtVersion, comScope});
+ } else {
+ composite.setTabList(new Control[] {txtGroupId, txtArtifactId, txtVersion});
+ }
+
+ Packaging pack;
+ if (queryType.equals(IIndex.SEARCH_PARENTS)) {
+ pack = Packaging.POM;
+ } else if (queryType.equals(IIndex.SEARCH_PLUGIN)) {
+ pack = Packaging.PLUGIN;
+ } else {
+ pack = Packaging.ALL;
+ }
+ ProposalUtil.addGroupIdProposal(project, txtGroupId, pack);
+ ProposalUtil.addArtifactIdProposal(project, txtGroupId, txtArtifactId, pack);
+ ProposalUtil.addVersionProposal(project, mavenproject, txtGroupId, txtArtifactId, txtVersion, pack);
+
+ txtArtifactId.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent e) {
+ if (!ignoreTextChange) {
+ computeResultFromField(valueOrNull(txtGroupId.getText()), valueOrNull(txtArtifactId.getText()), valueOrNull(txtVersion.getText()));
+ }
+ }
+ });
+
+ txtGroupId.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent e) {
+ if (!ignoreTextChange) {
+ computeResultFromField(valueOrNull(txtGroupId.getText()), valueOrNull(txtArtifactId.getText()), valueOrNull(txtVersion.getText()));
+ }
+ }
+ });
+ txtVersion.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent e) {
+ if (!ignoreTextChange) {
+ computeResultFromField(valueOrNull(txtGroupId.getText()), valueOrNull(txtArtifactId.getText()), valueOrNull(txtVersion.getText()));
+ }
+ }
+ });
+
+ return composite;
+ }
+
+ void okPressedDelegate() {
+ okPressed();
+ }
+
+ void updateStatusDelegate(IStatus status) {
+ updateStatus(status);
+ }
+
+ private String valueOrNull(String text) {
+ return text.trim().length() == 0 ? null : text;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.dialogs.SelectionStatusDialog#computeResult()
+ */
+ protected void computeResult() {
+ if (showCoords) {
+ computeResultFromField(valueOrNull(txtGroupId.getText()), valueOrNull(txtArtifactId.getText()), valueOrNull(txtVersion.getText()));
+ } else {
+ computeResultFromTree();
+ }
+ }
+
+ private void computeResultFromField(String groupId, String artifactId, String version) {
+ selectedIndexedArtifact = cloneIndexedArtifact(selectedIndexedArtifact, groupId, artifactId);
+ selectedIndexedArtifactFile = cloneIndexedArtifactFile(selectedIndexedArtifactFile, groupId, artifactId, version);
+ selectedScope = comScope == null ? null : comScope.getText();
+ setResult(Collections.singletonList(selectedIndexedArtifactFile));
+ }
+
+ private void computeResultFromTree() {
+ selectedIndexedArtifact = pomSelectionComponent.getIndexedArtifact();
+ selectedIndexedArtifactFile = pomSelectionComponent.getIndexedArtifactFile();
+ selectedScope = comScope == null ? null : comScope.getText();
+ setResult(Collections.singletonList(selectedIndexedArtifactFile));
+ if (selectedIndexedArtifactFile != null && showCoords) {
+ ignoreTextChange = true;
+ try {
+ txtGroupId.setText(selectedIndexedArtifactFile.group);
+ txtArtifactId.setText(selectedIndexedArtifactFile.artifact);
+ if (!managed.contains(new ArtifactKey(selectedIndexedArtifactFile.group, selectedIndexedArtifactFile.artifact, selectedIndexedArtifactFile.version, selectedIndexedArtifactFile.classifier))) {
+ txtVersion.setText(selectedIndexedArtifactFile.version);
+ } else {
+ txtVersion.setText("");
+ }
+ } finally {
+ ignoreTextChange = false;
+ }
+ }
+ }
+
+ public IndexedArtifact getSelectedIndexedArtifact() {
+ return this.selectedIndexedArtifact;
+ }
+
+ public IndexedArtifactFile getSelectedIndexedArtifactFile() {
+ return this.selectedIndexedArtifactFile;
+ }
+
+ public String getSelectedScope() {
+ return this.selectedScope;
+ }
+
+ private IndexedArtifact cloneIndexedArtifact(IndexedArtifact old, String groupId, String artifactId) {
+ if (old == null) {
+ return new IndexedArtifact(groupId, artifactId, null, null, null);
+ }
+ return new IndexedArtifact(groupId != null ? groupId : old.getGroupId(),
+ artifactId != null ? artifactId : old.getArtifactId(),
+ old.getPackageName(), old.getClassname(), old.getPackaging());
+ }
+
+ private IndexedArtifactFile cloneIndexedArtifactFile(IndexedArtifactFile old, String groupId, String artifactId, String version) {
+ if (old == null) {
+ return new IndexedArtifactFile(null, groupId, artifactId, version, null, null, null, 0L, null, 0, 0, null, null);
+ }
+ return new IndexedArtifactFile(old.repository,
+ groupId,
+ artifactId,
+ version,
+ old.type,
+ old.classifier,
+ old.fname,
+ old.size,
+ old.date,
+ old.sourcesExists,
+ old.javadocExists,
+ old.prefix,
+ old.goals);
+ }
+
+
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/AbstractLifecyclePropertyPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/AbstractLifecyclePropertyPage.java
new file mode 100644
index 00000000..3ce330f1
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/AbstractLifecyclePropertyPage.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.lifecycle;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * AbstractLifecyclePropertyPage
+ * Holds the pieces used in the common lifecycle mapping properties pages.
+ *
+ * @author dyocum
+ */
+public abstract class AbstractLifecyclePropertyPage extends AbstractPropertyPageExtensionPoint implements ILifecyclePropertyPage{
+ private IProject project;
+ private Shell shell;
+
+ public AbstractLifecyclePropertyPage(){
+ }
+
+ public void setupPage(IProject project, Shell shell){
+ this.project = project;
+ this.setShell(shell);
+ }
+
+ public void setProject(IProject project){
+ this.project = project;
+ }
+
+ public IProject getProject(){
+ return project;
+ }
+
+ /**
+ * @param shell The shell to set.
+ */
+ public void setShell(Shell shell) {
+ this.shell = shell;
+ }
+
+ /**
+ * @return Returns the shell.
+ */
+ public Shell getShell() {
+ return shell;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/AbstractPropertyPageExtensionPoint.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/AbstractPropertyPageExtensionPoint.java
new file mode 100644
index 00000000..ace3c250
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/AbstractPropertyPageExtensionPoint.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.lifecycle;
+
+/**
+ * AbstractPropertyPageExtensionPoint
+ *
+ * @author dyocum
+ */
+public class AbstractPropertyPageExtensionPoint implements ILifecyclePropertyPageExtensionPoint {
+
+ private String name;
+ private String id;
+ private String lifecycleMappingId;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.lifecycle.ILifecyclePropertyPageExtensionPoint#getLifecycleMappingId()
+ */
+ public String getLifecycleMappingId() {
+ return lifecycleMappingId;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.lifecycle.ILifecyclePropertyPageExtensionPoint#getName()
+ */
+ public String getName() {
+ return name;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.lifecycle.ILifecyclePropertyPageExtensionPoint#getPageId()
+ */
+ public String getPageId() {
+ return id;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.lifecycle.ILifecyclePropertyPageExtensionPoint#setLifecycleMappingId(java.lang.String)
+ */
+ public void setLifecycleMappingId(String lifecycleMappingId) {
+ this.lifecycleMappingId = lifecycleMappingId;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.lifecycle.ILifecyclePropertyPageExtensionPoint#setName()
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.lifecycle.ILifecyclePropertyPageExtensionPoint#setPageId()
+ */
+ public void setPageId(String id) {
+ this.id = id;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ILifecyclePropertyPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ILifecyclePropertyPage.java
new file mode 100644
index 00000000..bbc88239
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ILifecyclePropertyPage.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.lifecycle;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * ILifecyclePropertyPage
+ *
+ * @author dyocum
+ */
+public interface ILifecyclePropertyPage extends ILifecyclePropertyPageExtensionPoint{
+ /**
+ * Create and return the composite which will be shown in the parent properties page.
+ * @param parent
+ * @return
+ */
+ public Control createContents(Composite parent);
+
+ /**
+ * Called when the 'Restore Defaults' button is pressed in the properties page.
+ */
+ public void performDefaults();
+
+ /**
+ * Called when the 'OK' or 'Apply' buttons are pressed in the properties dialog.
+ * @return
+ */
+ public boolean performOk();
+
+ /**
+ * The project that these lifecycle mapping properties apply to
+ * @param project
+ */
+ public void setProject(IProject project);
+
+ public IProject getProject();
+
+ /**
+ * The parent shell used for showing error messages.
+ * @param shell
+ */
+ public void setShell(Shell shell);
+
+ public Shell getShell();
+
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ILifecyclePropertyPageExtensionPoint.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ILifecyclePropertyPageExtensionPoint.java
new file mode 100644
index 00000000..a81284da
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ILifecyclePropertyPageExtensionPoint.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.lifecycle;
+
+/**
+ * ILifecyclePropertyPageExtensionPoint
+ *
+ * @author dyocum
+ */
+public interface ILifecyclePropertyPageExtensionPoint {
+ /**
+ * The name of the page. This will be displayed in the title of the properties page.
+ * @return
+ */
+ public String getName();
+
+ /**
+ * Name of the page, called when the extension point is read in
+ */
+ public void setName(String name);
+
+ /**
+ * Get the id of the property page as defined in the extension point
+ * @return
+ */
+ public String getPageId();
+
+ /**
+ * Set the id of the property page, called when extension point is read
+ */
+ public void setPageId(String id);
+
+ /**
+ * Sets the id of the lifecycle mapping strategy that this property page is
+ * associated with
+ * @param lifecycleMappingId
+ */
+ public void setLifecycleMappingId(String lifecycleMappingId);
+
+ /**
+ * Gets the id of the lifecycle mapping strategy
+ * @return
+ */
+ public String getLifecycleMappingId();
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/LifecycleMappingPropertyPageFactory.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/LifecycleMappingPropertyPageFactory.java
new file mode 100644
index 00000000..45d49092
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/LifecycleMappingPropertyPageFactory.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.lifecycle;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.IProjectConfigurationManager;
+import org.eclipse.m2e.core.project.MavenProjectManager;
+import org.eclipse.m2e.core.project.ResolverConfiguration;
+import org.eclipse.m2e.core.project.configurator.ILifecycleMapping;
+import org.eclipse.swt.widgets.Shell;
+
+
+/**
+ * LifecycleMappingPropertyPageFactory
+ *
+ * @author dyocum
+ */
+public class LifecycleMappingPropertyPageFactory {
+
+ public static final String EXTENSION_LIFECYCLE_MAPPING_PROPERTY_PAGE = IMavenConstants.PLUGIN_ID + ".lifecycleMappingPropertyPage"; //$NON-NLS-1$
+
+ private static final String ATTR_LIFECYCLE_MAPPING_ID = "lifecycleMappingId"; //$NON-NLS-1$
+
+ private static final String ATTR_LIFECYCLE_PROP_NAME = "name"; //$NON-NLS-1$
+
+ private static final String ATTR_LIFECYCLE_PROP_ID = "id"; //$NON-NLS-1$
+
+ private static final String ELEMENT_LIFECYCLE_MAPPING_PROPERTY_PAGE = "lifecycleMappingPropertyPage"; //$NON-NLS-1$
+
+ private static LifecycleMappingPropertyPageFactory factory;
+
+ private Map<String, ILifecyclePropertyPage> pageMap;
+
+ public static LifecycleMappingPropertyPageFactory getFactory() {
+ if(factory == null) {
+ factory = new LifecycleMappingPropertyPageFactory();
+ factory.buildFactory();
+ }
+ return factory;
+ }
+
+ /**
+ * Get a particular lifecycle property page, set in the project to use for the lifecycle mapping, set the Shell for
+ * displaying dialogs.
+ *
+ * @param id
+ * @param project
+ * @param shell
+ * @return
+ */
+ public ILifecyclePropertyPage getPageForId(String id, IProject project, Shell shell) {
+ if(id == null){
+ //for the no-op (empty) lifecycle mapping, use that page
+ id = "NULL"; //$NON-NLS-1$
+ }
+ ILifecyclePropertyPage page = getFactory().pageMap.get(id);
+ if(page == null){
+ return null;
+ }
+ page.setProject(project);
+ page.setShell(shell);
+ return page;
+ }
+
+ public ILifecyclePropertyPage getPage(String id){
+ return getFactory().pageMap.get(id);
+ }
+
+ public void buildFactory() {
+ pageMap = new HashMap<String, ILifecyclePropertyPage>();
+ IExtensionRegistry registry = Platform.getExtensionRegistry();
+ IExtensionPoint configuratorsExtensionPoint = registry.getExtensionPoint(EXTENSION_LIFECYCLE_MAPPING_PROPERTY_PAGE);
+ if(configuratorsExtensionPoint != null) {
+ IExtension[] configuratorExtensions = configuratorsExtensionPoint.getExtensions();
+ for(IExtension extension : configuratorExtensions) {
+ IConfigurationElement[] elements = extension.getConfigurationElements();
+ for(IConfigurationElement element : elements) {
+ if(element.getName().equals(ELEMENT_LIFECYCLE_MAPPING_PROPERTY_PAGE)) {
+ try {
+ Object o = element.createExecutableExtension("class"); //$NON-NLS-1$
+ ILifecyclePropertyPage propPage = (ILifecyclePropertyPage) o;
+ String id = element.getAttribute(ATTR_LIFECYCLE_MAPPING_ID);
+
+ propPage.setLifecycleMappingId(id);
+ String name = element.getAttribute(ATTR_LIFECYCLE_PROP_NAME);
+ propPage.setName(name);
+
+ String pageId = element.getAttribute(ATTR_LIFECYCLE_PROP_ID);
+ if(pageId != null) {
+ propPage.setPageId(pageId);
+ }
+ pageMap.put(id, propPage);
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public static IMavenProjectFacade getProjectFacade(IProject project) {
+ MavenProjectManager projectManager = MavenPlugin.getDefault().getMavenProjectManager();
+ return projectManager.create(project, new NullProgressMonitor());
+ }
+
+ public static ResolverConfiguration getResolverConfiguration(IProject project) {
+ MavenProjectManager projectManager = MavenPlugin.getDefault().getMavenProjectManager();
+ return projectManager.getResolverConfiguration(project);
+ }
+
+ public static ILifecycleMapping getLifecycleMapping(IProject project) throws CoreException {
+ IMavenProjectFacade facade = getProjectFacade(project);
+ ILifecycleMapping lifecycleMapping = null;
+ IProjectConfigurationManager configurationManager = MavenPlugin.getDefault().getProjectConfigurationManager();
+ lifecycleMapping = configurationManager.getLifecycleMapping(facade);
+ return lifecycleMapping;
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ProjectConfiguratorsTable.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ProjectConfiguratorsTable.java
new file mode 100644
index 00000000..2e3e3020
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ProjectConfiguratorsTable.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.lifecycle;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator;
+import org.eclipse.m2e.core.project.configurator.ILifecycleMapping;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+
+/**
+ * ProjectConfiguratorsTable
+ * Composite that holds a read only table of project configurators for a given lifecycle mapping strategy.
+ *
+ * @author dyocum
+ */
+public class ProjectConfiguratorsTable {
+
+ private TableViewer configuratorsTable;
+ private ProjectConfiguratorsTableContentProvider configuratorsContentProvider;
+ private ProjectConfiguratorsTableLabelProvider configuratorsLabelProvider;
+ public static final String[] CONFIG_TABLE_COLUMN_PROPERTIES = new String[]{ "name", "id"}; //$NON-NLS-1$ //$NON-NLS-2$
+ public static final String[] CONFIG_TABLE_COLUMN_NAMES = new String[]{ Messages.ProjectConfiguratorsTable_column_name, Messages.ProjectConfiguratorsTable_column_id};
+ private static final int TABLE_WIDTH = 500;
+
+ public ProjectConfiguratorsTable(Composite parent, IProject project){
+ createTable(parent);
+ updateTable(project);
+ }
+
+ protected void updateTable(IProject project){
+ if(project != null){
+ try{
+ ILifecycleMapping lifecycleMapping = LifecycleMappingPropertyPageFactory.getLifecycleMapping(project);
+ if(lifecycleMapping != null) {
+// List<AbstractProjectConfigurator> projectConfigurators = lifecycleMapping
+// .getProjectConfigurators(new NullProgressMonitor());
+// setProjectConfigurators(projectConfigurators.toArray(new AbstractProjectConfigurator[] {}));
+ } else {
+ setProjectConfigurators(new AbstractProjectConfigurator[] {});
+ }
+ } catch(CoreException e){
+ setProjectConfigurators(new AbstractProjectConfigurator[]{});
+ }
+ }
+ }
+ private void createTable(Composite parent){
+ configuratorsTable = new TableViewer(parent, SWT.BORDER|SWT.H_SCROLL|SWT.V_SCROLL);
+ TableViewerColumn nameColumn = new TableViewerColumn(configuratorsTable, SWT.LEFT);
+ nameColumn.getColumn().setText(CONFIG_TABLE_COLUMN_NAMES[0]);
+ nameColumn.getColumn().setWidth((int)(TABLE_WIDTH*.50));
+
+ TableViewerColumn idColumn = new TableViewerColumn(configuratorsTable, SWT.LEFT);
+ idColumn.getColumn().setText(CONFIG_TABLE_COLUMN_NAMES[1]);
+ idColumn.getColumn().setWidth((int)(TABLE_WIDTH*.50));
+
+ configuratorsTable.getTable().setHeaderVisible(true);
+ configuratorsTable.getTable().setLinesVisible(true);
+ configuratorsContentProvider = new ProjectConfiguratorsTableContentProvider();
+ configuratorsLabelProvider = new ProjectConfiguratorsTableLabelProvider();
+ configuratorsTable.setContentProvider(configuratorsContentProvider);
+ configuratorsTable.setLabelProvider(configuratorsLabelProvider);
+ configuratorsTable.setColumnProperties(CONFIG_TABLE_COLUMN_PROPERTIES);
+ configuratorsTable.getTable().setData("name", "projectConfiguratorsTable"); //$NON-NLS-1$ //$NON-NLS-2$
+ GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);
+ gd.horizontalIndent=6;
+ gd.grabExcessHorizontalSpace = true;
+ gd.grabExcessVerticalSpace = true;
+ configuratorsTable.getControl().setLayoutData(gd);
+
+ final TableColumn nCol = nameColumn.getColumn();
+ final TableColumn iCol = idColumn.getColumn();
+ final Table tab = configuratorsTable.getTable();
+ configuratorsTable.getTable().addControlListener(new ControlAdapter() {
+ public void controlResized(ControlEvent e) {
+ nCol.setWidth((int)(tab.getClientArea().width*0.50));
+ iCol.setWidth((int)(tab.getClientArea().width*0.50));
+ }
+ });
+ }
+
+ public TableViewer getTableViewer(){
+ return configuratorsTable;
+ }
+
+ public void setProjectConfigurators(AbstractProjectConfigurator[] configurators){
+ configuratorsTable.setInput(configurators);
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ProjectConfiguratorsTableContentProvider.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ProjectConfiguratorsTableContentProvider.java
new file mode 100644
index 00000000..0c8bd3d1
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ProjectConfiguratorsTableContentProvider.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.lifecycle;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator;
+
+/**
+ * ConfiguratorsTableContentProvider
+ *
+ * @author dyocum
+ */
+public class ProjectConfiguratorsTableContentProvider implements IStructuredContentProvider {
+
+ public ProjectConfiguratorsTableContentProvider(){
+ }
+
+ protected String[] getNoConfigMsg(){
+ return new String[]{Messages.ProjectConfiguratorsTableContentProvider_no_configs};
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
+ */
+ public Object[] getElements(Object inputElement) {
+
+ if(inputElement == null || !(inputElement instanceof AbstractProjectConfigurator[]) || ((AbstractProjectConfigurator[])inputElement).length == 0){
+ return getNoConfigMsg();
+ }
+ return (AbstractProjectConfigurator[])inputElement;
+
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ public void dispose() {
+ // TODO Auto-generated method dispose
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+ */
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // TODO Auto-generated method inputChanged
+
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ProjectConfiguratorsTableLabelProvider.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ProjectConfiguratorsTableLabelProvider.java
new file mode 100644
index 00000000..cde6669d
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/lifecycle/ProjectConfiguratorsTableLabelProvider.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.lifecycle;
+
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * ConfiguratorsTableLabelProvider
+ *
+ * @author dyocum
+ */
+public class ProjectConfiguratorsTableLabelProvider implements ITableLabelProvider, IColorProvider{
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
+ */
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
+ */
+ public String getColumnText(Object element, int columnIndex) {
+ if(element == null){
+ return ""; //$NON-NLS-1$
+ } else if(element instanceof AbstractProjectConfigurator){
+ return columnIndex == 0 ? ((AbstractProjectConfigurator)element).getName() : ((AbstractProjectConfigurator)element).getId();
+ }
+ return columnIndex == 0 ? element.toString() : ""; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
+ */
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
+ */
+ public void dispose() {
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String)
+ */
+ public boolean isLabelProperty(Object element, String property) {
+ // TODO Auto-generated method isLabelProperty
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
+ */
+ public void removeListener(ILabelProviderListener listener) {
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IColorProvider#getBackground(java.lang.Object)
+ */
+ public Color getBackground(Object element) {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IColorProvider#getForeground(java.lang.Object)
+ */
+ public Color getForeground(Object element) {
+ if(element instanceof AbstractProjectConfigurator){
+ return Display.getDefault().getSystemColor(SWT.COLOR_BLACK);
+ }
+ return Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY);
+
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/CustomizableLifecycleMappingPropertyPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/CustomizableLifecycleMappingPropertyPage.java
new file mode 100644
index 00000000..e06c6e1b
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/CustomizableLifecycleMappingPropertyPage.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.preferences;
+
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.ui.internal.lifecycle.AbstractLifecyclePropertyPage;
+import org.eclipse.m2e.core.ui.internal.lifecycle.ProjectConfiguratorsTable;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * CustomizableLifecycleMappingPropertyPage
+ *
+ * @author dyocum
+ */
+public class CustomizableLifecycleMappingPropertyPage extends AbstractLifecyclePropertyPage{
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
+ */
+ public Control createContents(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout(2, false));
+ composite.setLayoutData(new GridData(GridData.FILL));
+ new ProjectConfiguratorsTable(composite, getProject());
+ return composite;
+ }
+
+ public void performDefaults(){
+ //do nothing
+ }
+
+ public boolean performOk() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.lifecycle.AbstractLifecyclePropertyPage#getMessage()
+ */
+ public String getMessage() {
+ // TODO Auto-generated method getMessage
+ return Messages.CustomizableLifecycleMappingPropertyPage_message;
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/EmptyLifecycleMappingPropertyPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/EmptyLifecycleMappingPropertyPage.java
new file mode 100644
index 00000000..92c98101
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/EmptyLifecycleMappingPropertyPage.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.preferences;
+
+import org.eclipse.m2e.core.internal.Messages;
+
+/**
+ * EmptyLifecycleMappingPropertyPage
+ *
+ * @author dyocum
+ */
+public class EmptyLifecycleMappingPropertyPage extends SimpleLifecycleMappingPropertyPage {
+
+ public EmptyLifecycleMappingPropertyPage() {
+ super(Messages.EmptyLifecycleMappingPropertyPage_title);
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/GoalsFieldEditor.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/GoalsFieldEditor.java
new file mode 100644
index 00000000..480f0dad
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/GoalsFieldEditor.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.preferences;
+
+import org.eclipse.jface.preference.FieldEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+
+
+/**
+ * A field editor for a combo box that allows the drop-down selection of one of
+ * a list of items.
+ *
+ * Adapted from org.eclipse.jface.preference.ComboFieldEditor
+ */
+public class GoalsFieldEditor extends FieldEditor {
+
+ /**
+ * The <code>Combo</code> widget.
+ */
+ Text goalsText;
+
+ /**
+ * The value (not the name) of the currently selected item in the Combo widget.
+ */
+ String value;
+
+ private Button goialsSelectButton;
+
+ private final String buttonText;
+
+ /**
+ * Create the combo box field editor.
+ *
+ * @param name the name of the preference this field editor works on
+ * @param labelText the label text of the field editor
+ * @param buttonText
+ * @param entryValues the entry values
+ * @param parent the parent composite
+ */
+ public GoalsFieldEditor(String name, String labelText, String buttonText, Composite parent) {
+ init(name, labelText);
+ this.buttonText = buttonText;
+ createControl(parent);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.preference.FieldEditor#adjustForNumColumns(int)
+ */
+ protected void adjustForNumColumns(int numColumns) {
+ if(numColumns > 1) {
+ Control control = getLabelControl();
+ ((GridData) control.getLayoutData()).horizontalSpan = numColumns;
+ ((GridData) goalsText.getLayoutData()).horizontalSpan = numColumns - 1;
+ } else {
+ Control control = getLabelControl();
+ ((GridData) control.getLayoutData()).horizontalSpan = 2;
+ ((GridData) goalsText.getLayoutData()).horizontalSpan = 1;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.preference.FieldEditor#doFillIntoGrid(org.eclipse.swt.widgets.Composite, int)
+ */
+ protected void doFillIntoGrid(Composite parent, int numColumns) {
+ Control labelControl = getLabelControl(parent);
+ GridData gd = new GridData();
+ gd.horizontalSpan = numColumns;
+ gd.horizontalAlignment = GridData.FILL;
+ gd.grabExcessHorizontalSpace = true;
+ labelControl.setLayoutData(gd);
+
+ Text goalsText = getTextControl(parent);
+ gd = new GridData();
+ gd.horizontalSpan = numColumns - 1;
+ gd.horizontalAlignment = GridData.FILL;
+ gd.grabExcessHorizontalSpace = true;
+ goalsText.setLayoutData(gd);
+ goalsText.setFont(parent.getFont());
+
+ goialsSelectButton = new Button(parent, SWT.NONE);
+ goialsSelectButton.setText(buttonText);
+ goialsSelectButton.addSelectionListener(new MavenGoalSelectionAdapter(goalsText, parent.getShell()));
+ gd = new GridData();
+ gd.horizontalSpan = 1;
+ gd.horizontalAlignment = GridData.FILL;
+ gd.grabExcessHorizontalSpace = true;
+ goalsText.setLayoutData(gd);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.preference.FieldEditor#doLoad()
+ */
+ protected void doLoad() {
+ updateComboForValue(getPreferenceStore().getString(getPreferenceName()));
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.preference.FieldEditor#doLoadDefault()
+ */
+ protected void doLoadDefault() {
+ updateComboForValue(getPreferenceStore().getDefaultString(getPreferenceName()));
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.preference.FieldEditor#doStore()
+ */
+ protected void doStore() {
+ if (value == null) {
+ getPreferenceStore().setToDefault(getPreferenceName());
+ } else {
+ getPreferenceStore().setValue(getPreferenceName(), value);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.preference.FieldEditor#getNumberOfControls()
+ */
+ public int getNumberOfControls() {
+ return 2;
+ }
+
+ /*
+ * Lazily create and return the Combo control.
+ */
+ private Text getTextControl(Composite parent) {
+ if (goalsText == null) {
+ goalsText = new Text(parent, SWT.BORDER);
+ goalsText.setFont(parent.getFont());
+// for (int i = 0; i < entryValues.length; i++) {
+// goalsCombo.add(entryValues[i], i);
+// }
+// goalsCombo.addSelectionListener(new SelectionAdapter() {
+// public void widgetSelected(SelectionEvent evt) {
+// String oldValue = value;
+// value = goalsCombo.getText();
+// setPresentsDefaultValue(false);
+// fireValueChanged(VALUE, oldValue, value);
+// }
+// });
+ goalsText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent modifyevent) {
+ String oldValue = value;
+ value = goalsText.getText();
+ setPresentsDefaultValue(false);
+ fireValueChanged(VALUE, oldValue, value);
+ }
+ });
+ }
+ return goalsText;
+ }
+
+ protected void setPresentsDefaultValue(boolean booleanValue) {
+ super.setPresentsDefaultValue(booleanValue);
+ }
+
+ protected void fireValueChanged(String property, Object oldValue, Object newValue) {
+ super.fireValueChanged(property, oldValue, newValue);
+ }
+
+// /*
+// * Given the name (label) of an entry, return the corresponding value.
+// */
+// String getValueForName(String name) {
+// for (int i = 0; i < fEntryValues.length; i++) {
+// String[] entry = fEntryValues[i];
+// if (name.equals(entry[0])) {
+// return entry[1];
+// }
+// }
+// return fEntryValues[0][0];
+// }
+
+ /*
+ * Set the name in the combo widget to match the specified value.
+ */
+ private void updateComboForValue(String value) {
+ this.value = value;
+ goalsText.setText(value);
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/LocalArchetypeCatalogDialog.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/LocalArchetypeCatalogDialog.java
new file mode 100644
index 00000000..2b69eaea
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/LocalArchetypeCatalogDialog.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.preferences;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.maven.archetype.catalog.Archetype;
+import org.apache.maven.archetype.catalog.ArchetypeCatalog;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.DialogSettings;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.m2e.core.archetype.ArchetypeCatalogFactory;
+import org.eclipse.m2e.core.archetype.ArchetypeCatalogFactory.LocalCatalogFactory;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Local Archetype catalog dialog
+ *
+ * @author Eugene Kuleshov
+ */
+public class LocalArchetypeCatalogDialog extends TitleAreaDialog {
+
+ private static final String DIALOG_SETTINGS = LocalArchetypeCatalogDialog.class.getName();
+
+ private static final String KEY_LOCATIONS = "catalogLocation"; //$NON-NLS-1$
+
+ private static final int MAX_HISTORY = 15;
+
+ private String title;
+
+ private String message;
+
+ Combo catalogLocationCombo;
+
+ private Text catalogDescriptionText;
+
+ private IDialogSettings dialogSettings;
+
+ private ArchetypeCatalogFactory archetypeCatalogFactory;
+
+
+ protected LocalArchetypeCatalogDialog(Shell shell, ArchetypeCatalogFactory factory) {
+ super(shell);
+ this.archetypeCatalogFactory = factory;
+ this.title = Messages.LocalArchetypeCatalogDialog_title;
+ this.message = Messages.LocalArchetypeCatalogDialog_message;
+ setShellStyle(SWT.DIALOG_TRIM);
+
+ IDialogSettings pluginSettings = M2EUIPluginActivator.getDefault().getDialogSettings();
+ dialogSettings = pluginSettings.getSection(DIALOG_SETTINGS);
+ if(dialogSettings == null) {
+ dialogSettings = new DialogSettings(DIALOG_SETTINGS);
+ pluginSettings.addSection(dialogSettings);
+ }
+ }
+
+ protected Control createContents(Composite parent) {
+ Control control = super.createContents(parent);
+ setTitle(title);
+ setMessage(message);
+ return control;
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite composite1 = (Composite) super.createDialogArea(parent);
+
+ Composite composite = new Composite(composite1, SWT.NONE);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.marginTop = 7;
+ gridLayout.marginWidth = 12;
+ gridLayout.numColumns = 3;
+ composite.setLayout(gridLayout);
+
+ Label catalogLocationLabel = new Label(composite, SWT.NONE);
+ catalogLocationLabel.setText(Messages.LocalArchetypeCatalogDialog_lblCatalog);
+
+ catalogLocationCombo = new Combo(composite, SWT.NONE);
+ GridData gd_catalogLocationCombo = new GridData(SWT.FILL, SWT.CENTER, true, false);
+ gd_catalogLocationCombo.widthHint = 250;
+ catalogLocationCombo.setLayoutData(gd_catalogLocationCombo);
+ catalogLocationCombo.setItems(getSavedValues(KEY_LOCATIONS));
+
+ Button browseButton = new Button(composite, SWT.NONE);
+ browseButton.setText(Messages.LocalArchetypeCatalogDialog_btnBrowse);
+ browseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ FileDialog dialog = new FileDialog(getShell());
+ dialog.setText(Messages.LocalArchetypeCatalogDialog_dialog_title);
+ String location = dialog.open();
+ if(location!=null) {
+ catalogLocationCombo.setText(location);
+ update();
+ }
+ }
+ });
+ setButtonLayoutData(browseButton);
+
+ Label catalogDescriptionLabel = new Label(composite, SWT.NONE);
+ catalogDescriptionLabel.setText(Messages.LocalArchetypeCatalogDialog_lblDesc);
+
+ catalogDescriptionText = new Text(composite, SWT.BORDER);
+ catalogDescriptionText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+
+
+ if(archetypeCatalogFactory!=null) {
+ catalogLocationCombo.setText(archetypeCatalogFactory.getId());
+ catalogDescriptionText.setText(archetypeCatalogFactory.getDescription());
+ }
+
+ ModifyListener modifyListener = new ModifyListener() {
+ public void modifyText(final ModifyEvent e) {
+ update();
+ }
+ };
+ catalogLocationCombo.addModifyListener(modifyListener);
+ catalogDescriptionText.addModifyListener(modifyListener);
+
+ return composite;
+ }
+
+ private String[] getSavedValues(String key) {
+ String[] array = dialogSettings.getArray(key);
+ return array == null ? new String[0] : array;
+ }
+
+ protected void configureShell(Shell shell) {
+ super.configureShell(shell);
+ shell.setText(title);
+ }
+
+ public void create() {
+ super.create();
+ getButton(IDialogConstants.OK_ID).setEnabled(false);
+ }
+
+ protected void okPressed() {
+ String description = catalogDescriptionText.getText().trim();
+ String location = catalogLocationCombo.getText().trim();
+
+ archetypeCatalogFactory = new LocalCatalogFactory(location, description, true);
+
+ saveValue(KEY_LOCATIONS, location);
+
+ super.okPressed();
+ }
+
+ public ArchetypeCatalogFactory getArchetypeCatalogFactory() {
+ return archetypeCatalogFactory;
+ }
+
+ private void saveValue(String key, String value) {
+ List<String> dirs = new ArrayList<String>();
+ dirs.addAll(Arrays.asList(getSavedValues(key)));
+
+ dirs.remove(value);
+ dirs.add(0, value);
+
+ if(dirs.size() > MAX_HISTORY) {
+ dirs = dirs.subList(0, MAX_HISTORY);
+ }
+
+ dialogSettings.put(key, dirs.toArray(new String[dirs.size()]));
+ }
+
+ void update() {
+ boolean isValid = isValid();
+ // verifyButton.setEnabled(isValid);
+ getButton(IDialogConstants.OK_ID).setEnabled(isValid);
+ }
+
+ private boolean isValid() {
+ setErrorMessage(null);
+ setMessage(null, IStatus.WARNING);
+
+ String location = catalogLocationCombo.getText().trim();
+ if(location.length()==0) {
+ setErrorMessage(Messages.LocalArchetypeCatalogDialog_error_no_location);
+ return false;
+ }
+
+ if(!new File(location).exists()) {
+ setErrorMessage(Messages.LocalArchetypeCatalogDialog_error_exist);
+ return false;
+ }
+
+ LocalCatalogFactory factory = new LocalCatalogFactory(location, null, true);
+ ArchetypeCatalog archetypeCatalog = factory.getArchetypeCatalog();
+ @SuppressWarnings("unchecked")
+ List<Archetype> archetypes = archetypeCatalog.getArchetypes();
+ if(archetypes==null || archetypes.size()==0) {
+ setMessage(Messages.LocalArchetypeCatalogDialog_error_empty, IStatus.WARNING);
+ }
+
+ return true;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenArchetypesPreferencePage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenArchetypesPreferencePage.java
new file mode 100644
index 00000000..d4af3594
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenArchetypesPreferencePage.java
@@ -0,0 +1,319 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.preferences;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.window.Window;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.archetype.ArchetypeCatalogFactory;
+import org.eclipse.m2e.core.archetype.ArchetypeCatalogFactory.LocalCatalogFactory;
+import org.eclipse.m2e.core.archetype.ArchetypeCatalogFactory.RemoteCatalogFactory;
+import org.eclipse.m2e.core.archetype.ArchetypeManager;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.browser.IWebBrowser;
+
+
+/**
+ * Maven Archetype catalogs preference page
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenArchetypesPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+
+ ArchetypeManager archetypeManager;
+ TableViewer archetypesViewer;
+
+ List<ArchetypeCatalogFactory> archetypeCatalogs;
+
+ public MavenArchetypesPreferencePage() {
+ setTitle(Messages.MavenArchetypesPreferencePage_title);
+
+ this.archetypeManager = MavenPlugin.getDefault().getArchetypeManager();
+ }
+
+ protected void performDefaults() {
+ for(Iterator<ArchetypeCatalogFactory> it = archetypeCatalogs.iterator(); it.hasNext();) {
+ ArchetypeCatalogFactory factory = it.next();
+ if(factory.isEditable()) {
+ it.remove();
+ }
+ }
+
+ archetypesViewer.setInput(archetypeCatalogs);
+ archetypesViewer.setSelection(null, true);
+
+ super.performDefaults();
+ }
+
+ public boolean performOk() {
+ Collection<ArchetypeCatalogFactory> catalogs = archetypeManager.getArchetypeCatalogs();
+ for(ArchetypeCatalogFactory factory : catalogs) {
+ if(factory.isEditable()) {
+ archetypeManager.removeArchetypeCatalogFactory(factory.getId());
+ }
+ }
+ for(ArchetypeCatalogFactory factory : archetypeCatalogs) {
+ if(factory.isEditable()) {
+ archetypeManager.addArchetypeCatalogFactory(factory);
+ }
+ }
+
+ try {
+ archetypeManager.saveCatalogs();
+ } catch(IOException ex) {
+ setErrorMessage(NLS.bind(Messages.MavenArchetypesPreferencePage_error, ex.getMessage()));
+ return false;
+ }
+
+ return super.performOk();
+ }
+
+ public void init(IWorkbench workbench) {
+ }
+
+ protected Control createContents(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout gridLayout = new GridLayout(2, false);
+ gridLayout.marginWidth = 0;
+ gridLayout.marginHeight = 0;
+ composite.setLayout(gridLayout);
+
+ Link addRemoveOrLink = new Link(composite, SWT.NONE);
+ GridData gd_addRemoveOrLink = new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1);
+ addRemoveOrLink.setLayoutData(gd_addRemoveOrLink);
+ addRemoveOrLink.setText(Messages.MavenArchetypesPreferencePage_link);
+ addRemoveOrLink.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ try {
+ URL url = new URL("http://maven.apache.org/plugins/maven-archetype-plugin/specification/archetype-catalog.html"); //$NON-NLS-1$
+ IWebBrowser browser = PlatformUI.getWorkbench().getBrowserSupport().getExternalBrowser();
+ browser.openURL(url);
+ } catch(MalformedURLException ex) {
+ MavenLogger.log("Malformed URL", ex);
+ } catch(PartInitException ex) {
+ MavenLogger.log(ex);
+ }
+ }
+ });
+
+ // archetypesViewer = CheckboxTableViewer.newCheckList(composite, SWT.BORDER | SWT.FULL_SELECTION);
+ archetypesViewer = new TableViewer(composite, SWT.BORDER | SWT.FULL_SELECTION);
+
+ archetypesViewer.setLabelProvider(new CatalogsLabelProvider());
+
+ archetypesViewer.setContentProvider(new IStructuredContentProvider() {
+
+ public Object[] getElements(Object input) {
+ if(input instanceof Collection) {
+ return ((Collection<?>) input).toArray();
+ }
+ return new Object[0];
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ public void dispose() {
+ }
+
+ });
+
+ Table table = archetypesViewer.getTable();
+ table.setLinesVisible(false);
+ table.setHeaderVisible(false);
+ table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 4));
+
+ TableColumn typeColumn = new TableColumn(table, SWT.NONE);
+ typeColumn.setWidth(250);
+ typeColumn.setText(""); //$NON-NLS-1$
+
+ Button addLocalButton = new Button(composite, SWT.NONE);
+ addLocalButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ addLocalButton.setText(Messages.MavenArchetypesPreferencePage_btnAddLocal);
+ addLocalButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ LocalArchetypeCatalogDialog dialog = new LocalArchetypeCatalogDialog(getShell(), null);
+ if (dialog.open()==Window.OK) {
+ ArchetypeCatalogFactory factory = dialog.getArchetypeCatalogFactory();
+ archetypeCatalogs.add(factory);
+ archetypesViewer.setInput(archetypeCatalogs);
+ archetypesViewer.setSelection(new StructuredSelection(factory), true);
+ }
+ }
+ });
+
+ Button addRemoteButton = new Button(composite, SWT.NONE);
+ addRemoteButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ addRemoteButton.setText(Messages.MavenArchetypesPreferencePage_btnAddRemote);
+ addRemoteButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ RemoteArchetypeCatalogDialog dialog = new RemoteArchetypeCatalogDialog(getShell(), null);
+ if (dialog.open()==Window.OK) {
+ ArchetypeCatalogFactory factory = dialog.getArchetypeCatalogFactory();
+ archetypeCatalogs.add(factory);
+ archetypesViewer.setInput(archetypeCatalogs);
+ archetypesViewer.setSelection(new StructuredSelection(factory), true);
+ }
+ }
+ });
+
+ final Button editButton = new Button(composite, SWT.NONE);
+ editButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ editButton.setEnabled(false);
+ editButton.setText(Messages.MavenArchetypesPreferencePage_btnEdit);
+ editButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ ArchetypeCatalogFactory factory = getSelectedArchetypeCatalogFactory();
+ ArchetypeCatalogFactory newFactory = null;
+ if(factory instanceof LocalCatalogFactory) {
+ LocalArchetypeCatalogDialog dialog = new LocalArchetypeCatalogDialog(getShell(), factory);
+ if (dialog.open()==Window.OK) {
+ newFactory = dialog.getArchetypeCatalogFactory();
+ }
+ } else if(factory instanceof RemoteCatalogFactory) {
+ RemoteArchetypeCatalogDialog dialog = new RemoteArchetypeCatalogDialog(getShell(), factory);
+ if (dialog.open()==Window.OK) {
+ newFactory = dialog.getArchetypeCatalogFactory();
+ }
+ }
+ if(newFactory!=null) {
+ int n = archetypeCatalogs.indexOf(factory);
+ if(n>-1) {
+ archetypeCatalogs.set(n, newFactory);
+ archetypesViewer.setInput(archetypeCatalogs);
+ archetypesViewer.setSelection(new StructuredSelection(newFactory), true);
+ }
+ }
+ }
+ });
+
+ final Button removeButton = new Button(composite, SWT.NONE);
+ removeButton.setEnabled(false);
+ removeButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, true));
+ removeButton.setText(Messages.MavenArchetypesPreferencePage_btnRemove);
+ removeButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ ArchetypeCatalogFactory factory = getSelectedArchetypeCatalogFactory();
+ archetypeCatalogs.remove(factory);
+ archetypesViewer.setInput(archetypeCatalogs);
+ archetypesViewer.setSelection(null, true);
+ }
+ });
+
+ archetypesViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ if(archetypesViewer.getSelection() instanceof IStructuredSelection) {
+ ArchetypeCatalogFactory factory = getSelectedArchetypeCatalogFactory();
+ boolean isEnabled = factory != null && factory.isEditable();
+ removeButton.setEnabled(isEnabled);
+ editButton.setEnabled(isEnabled);
+ }
+ }
+ });
+
+ archetypeCatalogs = new ArrayList<ArchetypeCatalogFactory>(archetypeManager.getArchetypeCatalogs());
+ archetypesViewer.setInput(archetypeCatalogs);
+ archetypesViewer.refresh(); // should listen on property changes instead?
+
+ return composite;
+ }
+
+ protected ArchetypeCatalogFactory getSelectedArchetypeCatalogFactory() {
+ IStructuredSelection selection = (IStructuredSelection) archetypesViewer.getSelection();
+ return (ArchetypeCatalogFactory) selection.getFirstElement();
+ }
+
+
+ static class CatalogsLabelProvider implements ITableLabelProvider, IColorProvider {
+
+ private Color disabledColor = Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GRAY);
+
+ public String getColumnText(Object element, int columnIndex) {
+ ArchetypeCatalogFactory factory = (ArchetypeCatalogFactory) element;
+ if(factory instanceof LocalCatalogFactory) {
+ return NLS.bind(Messages.MavenArchetypesPreferencePage_local, factory.getDescription());
+ } else if(factory instanceof RemoteCatalogFactory) {
+ if(factory.isEditable()) {
+ return NLS.bind(Messages.MavenArchetypesPreferencePage_remote,factory.getDescription());
+ }
+ return NLS.bind(Messages.MavenArchetypesPreferencePage_packaged, factory.getDescription());
+ }
+ return factory.getDescription();
+ }
+
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+
+ public Color getBackground(Object element) {
+ return null;
+ }
+
+ public Color getForeground(Object element) {
+ ArchetypeCatalogFactory factory = (ArchetypeCatalogFactory) element;
+ return !factory.isEditable() ? disabledColor : null;
+ }
+
+ public void dispose() {
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+ public void removeListener(ILabelProviderListener listener) {
+ }
+
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenGoalSelectionAdapter.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenGoalSelectionAdapter.java
new file mode 100644
index 00000000..10f316b9
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenGoalSelectionAdapter.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.preferences;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.m2e.core.ui.internal.dialogs.MavenGoalSelectionDialog;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+public class MavenGoalSelectionAdapter extends SelectionAdapter {
+ private Shell shell;
+ private Text text;
+
+ public MavenGoalSelectionAdapter(Text text, Shell shell) {
+ this.text = text;
+ this.shell = shell;
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+// String fileName = Util.substituteVar(fPomDirName.getText());
+// if(!isDirectoryExist(fileName)) {
+// MessageDialog.openError(getShell(), Messages.getString("launch.errorPomMissing"),
+// Messages.getString("launch.errorSelectPom")); //$NON-NLS-1$ //$NON-NLS-2$
+// return;
+// }
+ MavenGoalSelectionDialog dialog = new MavenGoalSelectionDialog(shell);
+ int rc = dialog.open();
+ if(rc == IDialogConstants.OK_ID) {
+ text.insert(""); // clear selected text //$NON-NLS-1$
+
+ String txt = text.getText();
+ int len = txt.length();
+ int pos = text.getCaretPosition();
+
+ StringBuffer sb = new StringBuffer();
+ if((pos > 0 && txt.charAt(pos - 1) != ' ')) {
+ sb.append(' ');
+ }
+
+ String sep = ""; //$NON-NLS-1$
+ Object[] o = dialog.getResult();
+ for(int i = 0; i < o.length; i++ ) {
+ if(o[i] instanceof MavenGoalSelectionDialog.Entry) {
+ if(dialog.isQualifiedName()) {
+ sb.append(sep).append(((MavenGoalSelectionDialog.Entry) o[i]).getQualifiedName());
+ } else {
+ sb.append(sep).append(((MavenGoalSelectionDialog.Entry) o[i]).getName());
+ }
+ }
+ sep = " "; //$NON-NLS-1$
+ }
+
+ if(pos < len && txt.charAt(pos) != ' ') {
+ sb.append(' ');
+ }
+
+ text.insert(sb.toString());
+ text.setFocus();
+ }
+ }
+ } \ No newline at end of file
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenInstallationsPreferencePage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenInstallationsPreferencePage.java
new file mode 100644
index 00000000..07315548
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenInstallationsPreferencePage.java
@@ -0,0 +1,672 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.preferences;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.maven.settings.building.SettingsProblem;
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.embedder.IMavenConfiguration;
+import org.eclipse.m2e.core.embedder.MavenRuntime;
+import org.eclipse.m2e.core.embedder.MavenRuntimeManager;
+import org.eclipse.m2e.core.index.IndexManager;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.internal.embedder.MavenEmbeddedRuntime;
+import org.eclipse.m2e.core.internal.preferences.MavenPreferenceConstants;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IPropertyListener;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.browser.IWebBrowser;
+import org.eclipse.ui.ide.IDE;
+
+
+/**
+ * Maven installations preference page
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenInstallationsPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+
+ final MavenPlugin mavenPlugin;
+
+ final MavenRuntimeManager runtimeManager;
+
+ final IMavenConfiguration mavenConfiguration;
+
+ final IMaven maven;
+
+ MavenRuntime defaultRuntime;
+
+ List<MavenRuntime> runtimes;
+
+ CheckboxTableViewer runtimesViewer;
+
+ Text globalSettingsText;
+
+ private String globalSettings;
+
+ boolean dirty = false;
+
+ public MavenInstallationsPreferencePage() {
+ setTitle(Messages.MavenInstallationsPreferencePage_title);
+
+ this.mavenPlugin = MavenPlugin.getDefault();
+ this.runtimeManager = mavenPlugin.getMavenRuntimeManager();
+ this.mavenConfiguration = MavenPlugin.getDefault().getMavenConfiguration();
+ this.maven = MavenPlugin.getDefault().getMaven();
+
+ }
+
+ public void init(IWorkbench workbench) {
+ }
+
+ protected void performDefaults() {
+ runtimeManager.reset();
+ defaultRuntime = runtimeManager.getDefaultRuntime();
+ runtimes = runtimeManager.getMavenRuntimes();
+
+ runtimesViewer.setInput(runtimes);
+ runtimesViewer.setChecked(defaultRuntime, true);
+ runtimesViewer.refresh();
+
+ storeCustom(""); //$NON-NLS-1$
+ globalSettingsText.setText(""); //$NON-NLS-1$
+ mavenConfiguration.setGlobalSettingsFile(""); //$NON-NLS-1$
+
+ updateGlobals(true);
+ super.performDefaults();
+ setDirty(true);
+ }
+
+
+ protected void storeCustom(String dir){
+ M2EUIPluginActivator.getDefault().getPreferenceStore().setValue(P_MAVEN_CUSTOM_GLOBAL, dir == null ? "" : dir); //$NON-NLS-1$
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.preference.PreferencePage#performApply()
+ */
+ protected void performApply() {
+ updateSettings();
+ }
+
+ public void updateSettings(){
+ new Job(Messages.MavenInstallationsPreferencePage_job_updating) {
+ protected IStatus run(IProgressMonitor monitor) {
+ String dir = getGlobalSettingsText();
+
+ runtimeManager.setRuntimes(runtimes);
+ runtimeManager.setDefaultRuntime(defaultRuntime);
+ String oldSettings = mavenConfiguration.getGlobalSettingsFile();
+
+ mavenConfiguration.setGlobalSettingsFile(dir);
+ if(defaultRuntime == null || defaultRuntime instanceof MavenEmbeddedRuntime){
+ storeCustom(dir);
+ }
+ IndexManager indexManager = mavenPlugin.getIndexManager();
+ try {
+ indexManager.getWorkspaceIndex().updateIndex(true, monitor);
+ } catch(CoreException ex) {
+ return ex.getStatus();
+ }
+ if((dir == null && oldSettings != null) || (dir != null && !(dir.equals(oldSettings)))){
+ //mavenPlugin.getIndexManager().scheduleIndexUpdate(IndexManager.LOCAL_INDEX, true, 0L);
+ }
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ }
+
+ public boolean performOk() {
+ if (dirty) {
+ updateSettings();
+ }
+ return true;
+ }
+
+ public void setDirty(boolean dirty){
+ this.dirty = dirty;
+ }
+
+ public boolean isDirty(){
+ return this.dirty;
+ }
+
+ protected boolean validateMavenInstall(String dir){
+ if(dir == null || dir.length() == 0){
+ return false;
+ }
+ File selectedDir = new File(dir);
+ if(!selectedDir.isDirectory()){
+ MessageDialog.openError(getShell(), Messages.MavenInstallationsPreferencePage_error_title, Messages.MavenInstallationsPreferencePage_error_message);
+ return false;
+ }
+ File binDir = new File(dir, "bin"); //$NON-NLS-1$
+ File confDir = new File(dir, "conf"); //$NON-NLS-1$
+ File libDir = new File(dir, "lib"); //$NON-NLS-1$
+ if(!binDir.exists() || !confDir.exists() || !libDir.exists()){
+ MessageDialog.openError(getShell(), Messages.MavenInstallationsPreferencePage_error_title, Messages.MavenInstallationsPreferencePage_error2_message);
+ return false;
+ }
+ return true;
+ }
+ protected Control createContents(Composite parent) {
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout gridLayout = new GridLayout(3, false);
+ gridLayout.marginBottom = 5;
+ gridLayout.marginRight = 5;
+ gridLayout.marginHeight = 0;
+ gridLayout.marginWidth = 0;
+ composite.setLayout(gridLayout);
+
+ Label link = new Label(composite, SWT.NONE);
+ link.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 3, 1));
+ link.setText(Messages.MavenInstallationsPreferencePage_link);
+
+
+ createTable(composite);
+ createGlobalSettings(composite);
+
+
+ defaultRuntime = runtimeManager.getDefaultRuntime();
+ runtimes = runtimeManager.getMavenRuntimes();
+
+ runtimesViewer.setInput(runtimes);
+ runtimesViewer.setChecked(defaultRuntime, true);
+ runtimesViewer.refresh(); // should listen on property changes instead?
+
+ checkSettings();
+ updateGlobals(false);
+ globalSettingsText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent modifyevent) {
+ setGlobalSettingsText(globalSettingsText.getText());
+ updateGlobalSettingsLink();
+ checkSettings();
+ setDirty(true);
+ }
+ });
+
+ return composite;
+ }
+
+ /**
+ *
+ */
+ private void updateGlobalSettingsText(boolean useLastCustomGlobal) {
+ String globalSettings = getGlobalSettingsFile(useLastCustomGlobal);
+ globalSettingsText.setText(globalSettings == null ? "" : globalSettings); //$NON-NLS-1$
+ }
+
+ /**
+ * Use this to retrieve the global settings file which has not been applied yet
+ * @return
+ */
+ public String getGlobalSettingsFile(boolean useLastCustomGlobal) {
+ if(defaultRuntime == null || defaultRuntime instanceof MavenEmbeddedRuntime){
+ String globalSettings = null;
+ if(useLastCustomGlobal){
+ globalSettings = M2EUIPluginActivator.getDefault().getPreferenceStore().getString(P_MAVEN_CUSTOM_GLOBAL);
+ } else {
+ globalSettings = M2EUIPluginActivator.getDefault().getPreferenceStore().getString(MavenPreferenceConstants.P_GLOBAL_SETTINGS_FILE);
+ }
+ return globalSettings.trim().length()==0 ? null : globalSettings;
+ }
+ return defaultRuntime == null ? null : defaultRuntime.getSettings();
+ }
+
+ public void setGlobalSettingsText(String settings){
+ this.globalSettings = settings;
+ }
+ public String getGlobalSettingsText(){
+ return this.globalSettings;
+ }
+ /**
+ *
+ */
+ private void updateGlobals(boolean useLastCustomGlobal) {
+ updateGlobalSettingsText(useLastCustomGlobal);
+ updateGlobalSettingsLink();
+ updateGlobalSettingsBrowseButton();
+ }
+
+ private Link globalSettingsLink;
+
+ private Button globalSettingsBrowseButton;
+
+ private MavenRuntime getCheckedRuntime(){
+ Object[] runtimes = runtimesViewer.getCheckedElements();
+ if(runtimes != null && runtimes.length > 0){
+ return (MavenRuntime)runtimes[0];
+ }
+ return null;
+ }
+
+ protected MavenRuntime getSelectedMavenRuntime(){
+ IStructuredSelection sel = (IStructuredSelection)runtimesViewer.getSelection();
+ return (MavenRuntime) sel.getFirstElement();
+ }
+
+ private void updateGlobalSettingsLink(){
+ MavenRuntime runtime = getCheckedRuntime();
+ String text = ""; //$NON-NLS-1$
+ String currText = globalSettingsText.getText();
+ boolean showURL = false;
+
+ File f = new File(currText);
+ if(f.exists()){
+ showURL = true;
+ }
+ String openFile = showURL ? Messages.MavenInstallationsPreferencePage_link_open : ""; //$NON-NLS-2$
+ if(runtime instanceof MavenEmbeddedRuntime){
+ text = NLS.bind(Messages.MavenInstallationsPreferencePage_settings, openFile);
+ } else {
+ text = NLS.bind(Messages.MavenInstallationsPreferencePage_settings_install, openFile);
+ }
+ globalSettingsLink.setText(text);
+ }
+
+ private void updateGlobalSettingsBrowseButton(){
+ MavenRuntime runtime = getCheckedRuntime();
+ boolean enabled = (runtime != null && (runtime instanceof MavenEmbeddedRuntime));
+ globalSettingsBrowseButton.setEnabled(enabled);
+ globalSettingsText.setEditable(enabled);
+ }
+
+ private void createGlobalSettings(Composite composite) {
+ globalSettingsLink = new Link(composite, SWT.NONE);
+ globalSettingsLink.setData("name", "globalSettingsLink"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ globalSettingsLink.setToolTipText(Messages.MavenInstallationsPreferencePage_link_global);
+ GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1);
+ gd.verticalIndent = 25;
+ globalSettingsLink.setLayoutData(gd);
+
+ globalSettingsLink.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ String globalSettings = getGlobalSettings();
+ if(globalSettings.length() == 0) {
+ globalSettings = defaultRuntime.getSettings();
+ }
+ if(globalSettings != null && globalSettings.length() > 0) {
+ openEditor(globalSettings);
+ }
+ }
+ });
+
+ globalSettingsText = new Text(composite, SWT.BORDER);
+ globalSettingsText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+ globalSettingsText.setData("name", "globalSettingsText"); //$NON-NLS-1$ //$NON-NLS-2$
+ globalSettingsBrowseButton = new Button(composite, SWT.NONE);
+ GridData gd_globalSettingsBrowseButton = new GridData(SWT.FILL, SWT.CENTER, false, false);
+ globalSettingsBrowseButton.setLayoutData(gd_globalSettingsBrowseButton);
+ globalSettingsBrowseButton.setText(Messages.MavenInstallationsPreferencePage_btnGlobalBrowse);
+ globalSettingsBrowseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ FileDialog dialog = new FileDialog(getShell(), SWT.OPEN);
+ if(getGlobalSettings().length() > 0) {
+ dialog.setFileName(getGlobalSettings());
+ }
+ String file = dialog.open();
+ if(file != null) {
+ file = file.trim();
+ if(file.length() > 0) {
+ globalSettingsText.setText(file);
+ }
+ }
+ }
+ });
+ }
+
+
+ private void createTable(Composite composite){
+ runtimesViewer = CheckboxTableViewer.newCheckList(composite, SWT.BORDER | SWT.FULL_SELECTION);
+
+ runtimesViewer.setLabelProvider(new RuntimesLabelProvider());
+
+ runtimesViewer.setContentProvider(new IStructuredContentProvider() {
+
+ @SuppressWarnings("unchecked")
+ public Object[] getElements(Object input) {
+ if(input instanceof List) {
+ List list = (List) input;
+ if(list.size() > 0) {
+ return list.toArray(new MavenRuntime[list.size()]);
+ }
+ }
+ return new Object[0];
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ public void dispose() {
+ }
+
+ });
+
+ Table table = runtimesViewer.getTable();
+ table.setLinesVisible(false);
+ table.setHeaderVisible(false);
+ GridData gd_table = new GridData(SWT.FILL, SWT.FILL, true, false, 2, 3);
+ gd_table.heightHint = 151;
+ gd_table.widthHint = 333;
+ table.setLayoutData(gd_table);
+
+ Button addButton = new Button(composite, SWT.NONE);
+ addButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ addButton.setText(Messages.MavenInstallationsPreferencePage_btnAdd);
+ addButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ DirectoryDialog dlg = new DirectoryDialog(getShell());
+ dlg.setText(Messages.MavenInstallationsPreferencePage_dialog_install_title);
+ dlg.setMessage(Messages.MavenInstallationsPreferencePage_dialog_install_message);
+ String dir = dlg.open();
+ if(dir == null){
+ return;
+ }
+ boolean ok = validateMavenInstall(dir);
+ if(ok){
+ MavenRuntime runtime = MavenRuntimeManager.createExternalRuntime(dir);
+ if(runtimes.contains(runtime)) {
+ MessageDialog.openError(getShell(), Messages.MavenInstallationsPreferencePage_error_title, Messages.MavenInstallationsPreferencePage_error3_message);
+ } else {
+ runtimes.add(runtime);
+ runtimesViewer.refresh();
+ runtimesViewer.setAllChecked(false);
+ runtimesViewer.setChecked(runtime, true);
+ if(runtime != null){
+ setCheckedRuntime(runtime);
+ }
+ }
+ }
+ }
+ });
+
+ final Button editButton = new Button(composite, SWT.NONE);
+ editButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ editButton.setEnabled(false);
+ editButton.setText(Messages.MavenInstallationsPreferencePage_btnEdit);
+ editButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ MavenRuntime runtime = getSelectedMavenRuntime();
+ DirectoryDialog dlg = new DirectoryDialog(Display.getCurrent().getActiveShell());
+ dlg.setText(Messages.MavenInstallationsPreferencePage_dialog_title);
+ dlg.setMessage(Messages.MavenInstallationsPreferencePage_dialog_message);
+ dlg.setFilterPath(runtime.getLocation());
+ String dir = dlg.open();
+ boolean ok = validateMavenInstall(dir);
+ if(ok && !dir.equals(runtime.getLocation())) {
+ MavenRuntime newRuntime = MavenRuntimeManager.createExternalRuntime(dir);
+ if(runtimes.contains(newRuntime)) {
+ MessageDialog.openError(getShell(), Messages.MavenInstallationsPreferencePage_error_title, Messages.MavenInstallationsPreferencePage_error4_message);
+ } else {
+ runtimes.set(runtimes.indexOf(runtime), newRuntime);
+ runtimesViewer.refresh();
+ setDirty(true);
+ if(newRuntime != null){
+ setCheckedRuntime(newRuntime);
+ }
+ }
+ }
+ }
+ });
+
+ final Button removeButton = new Button(composite, SWT.NONE);
+ removeButton.setEnabled(false);
+ removeButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ removeButton.setText(Messages.MavenInstallationsPreferencePage_btnRemove);
+ removeButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ MavenRuntime runtime = getSelectedMavenRuntime();
+ runtimes.remove(runtime);
+ runtimesViewer.refresh();
+ Object[] checkedElements = runtimesViewer.getCheckedElements();
+ if(checkedElements == null || checkedElements.length == 0) {
+ defaultRuntime = runtimeManager.getRuntime(MavenRuntimeManager.EMBEDDED);
+ runtimesViewer.setChecked(defaultRuntime, true);
+ setCheckedRuntime(defaultRuntime);
+ }
+ setDirty(true);
+ }
+ });
+
+ runtimesViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ if(runtimesViewer.getSelection() instanceof IStructuredSelection) {
+ MavenRuntime runtime = getSelectedMavenRuntime();
+ boolean isEnabled = runtime != null && runtime.isEditable();
+ removeButton.setEnabled(isEnabled);
+ editButton.setEnabled(isEnabled);
+ }
+ }
+ });
+
+ runtimesViewer.addCheckStateListener(new ICheckStateListener() {
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ if(event.getElement() != null && event.getChecked()){
+
+ setCheckedRuntime((MavenRuntime)event.getElement());
+ }
+ }
+ });
+ Link noteLabel = new Link(composite, SWT.WRAP | SWT.READ_ONLY);
+ GridData noteLabelData = new GridData(SWT.FILL, SWT.TOP, false, false, 2, 1);
+ noteLabelData.horizontalIndent = 15;
+ noteLabelData.widthHint = 100;
+
+ noteLabel.setLayoutData(noteLabelData);
+ noteLabel.setText(Messages.MavenInstallationsPreferencePage_lblNote1 +
+ Messages.MavenInstallationsPreferencePage_lblNote2);
+ noteLabel.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ try {
+ URL url = new URL(e.text);
+ IWebBrowser browser = PlatformUI.getWorkbench().getBrowserSupport().getExternalBrowser();
+ browser.openURL(url);
+ } catch(MalformedURLException ex) {
+ MavenLogger.log("Malformed URL", ex);
+ } catch(PartInitException ex) {
+ MavenLogger.log(ex);
+ }
+ }
+ });
+ }
+
+ private static final String P_MAVEN_CUSTOM_GLOBAL = "customGlobalSettingsFile"; //$NON-NLS-1$
+
+ protected void setCheckedRuntime(MavenRuntime runtime){
+ runtimesViewer.setAllChecked(false);
+ runtimesViewer.setChecked(runtime, true);
+ defaultRuntime = runtime;
+ boolean useDefault = (defaultRuntime == null || defaultRuntime instanceof MavenEmbeddedRuntime);
+ updateGlobals(useDefault);
+ setDirty(true);
+ }
+
+ void checkSettings() {
+ setErrorMessage(null);
+ setMessage(null);
+
+ String globalSettings = getGlobalSettings();
+ if(globalSettings != null && globalSettings.length() > 0) {
+ File globalSettingsFile = new File(globalSettings);
+ if(!globalSettingsFile.exists()) {
+ setMessage(Messages.MavenInstallationsPreferencePage_error_global_missing, IMessageProvider.WARNING);
+ globalSettings = null;
+ }
+ } else {
+ globalSettings = null;
+ }
+
+ List<SettingsProblem> result = maven.validateSettings(globalSettings);
+ if(result.size() > 0) {
+ setMessage(Messages.MavenInstallationsPreferencePage_error_global_parse + result.get(0).getMessage(), IMessageProvider.WARNING);
+ }
+
+ }
+
+
+
+ @SuppressWarnings("unchecked")
+ void openEditor(final String fileName) {
+ // XXX create new settings.xml if does not exist
+
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+
+ IEditorDescriptor desc = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor("settings.xml"); //$NON-NLS-1$
+
+ File file = new File(fileName);
+ IEditorInput input = null;
+ try {
+ //class implementing editor input for external file has been renamed in eclipse 3.3, hence reflection
+ Class javaInput = null;
+ try {
+ javaInput = Class.forName("org.eclipse.ui.internal.editors.text.JavaFileEditorInput"); //$NON-NLS-1$
+ Constructor cons = javaInput.getConstructor(new Class[] {File.class});
+ input = (IEditorInput) cons.newInstance(new Object[] {file});
+ } catch(Exception e) {
+ try {
+ IFileStore fileStore = EFS.getLocalFileSystem().fromLocalFile(file);
+ Class storeInput = Class.forName("org.eclipse.ui.ide.FileStoreEditorInput"); //$NON-NLS-1$
+ Constructor cons = storeInput.getConstructor(new Class[] {IFileStore.class});
+ input = (IEditorInput) cons.newInstance(new Object[] {fileStore});
+ } catch(Exception ex) {
+ //ignore...
+ }
+ }
+ final IEditorPart editor = IDE.openEditor(page, input, desc.getId());
+ editor.addPropertyListener(new IPropertyListener() {
+ public void propertyChanged(Object source, int propId) {
+ if(!editor.isDirty()) {
+ mavenPlugin.getConsole().logMessage("Refreshing settings " + fileName);
+ invalidateMavenSettings(false);
+ }
+ }
+ });
+
+ } catch(PartInitException ex) {
+ MavenLogger.log(ex);
+ }
+ }
+
+
+ void invalidateMavenSettings(final boolean reindex) {
+// new Job("Invalidating Maven settings") {
+// protected IStatus run(IProgressMonitor monitor) {
+// mavenPlugin.getMavenEmbedderManager().invalidateMavenSettings();
+// if(reindex) {
+// mavenPlugin.getIndexManager().scheduleIndexUpdate(IndexManager.LOCAL_INDEX, true, 0L);
+// }
+// return Status.OK_STATUS;
+// }
+// }.schedule();
+ }
+ String getGlobalSettings() {
+ return globalSettingsText.getText().trim();
+ }
+
+ static class RuntimesLabelProvider implements ITableLabelProvider, IColorProvider {
+
+ public String getColumnText(Object element, int columnIndex) {
+ MavenRuntime runtime = (MavenRuntime) element;
+ return runtime.toString();
+ }
+
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+
+ public Color getBackground(Object element) {
+ return null;
+ }
+
+ public Color getForeground(Object element) {
+ MavenRuntime runtime = (MavenRuntime) element;
+ if(!runtime.isEditable()) {
+ return Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GRAY);
+ }
+ return null;
+ }
+
+ public void dispose() {
+ }
+
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ public void addListener(ILabelProviderListener listener) {
+ }
+
+ public void removeListener(ILabelProviderListener listener) {
+ }
+
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenPreferencePage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenPreferencePage.java
new file mode 100644
index 00000000..42aecfc8
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenPreferencePage.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.preferences;
+
+import org.eclipse.jface.preference.BooleanFieldEditor;
+import org.eclipse.jface.preference.FieldEditorPreferencePage;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.internal.preferences.MavenPreferenceConstants;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+
+public class MavenPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
+
+ final MavenPlugin plugin;
+
+ public MavenPreferencePage() {
+ super(GRID);
+ setPreferenceStore(M2EUIPluginActivator.getDefault().getPreferenceStore());
+
+ plugin = MavenPlugin.getDefault();
+ }
+
+ public void init(IWorkbench workbench) {
+ }
+
+ /*
+ * Creates the field editors. Field editors are abstractions of the common GUI
+ * blocks needed to manipulate various types of preferences. Each field editor
+ * knows how to save and restore itself.
+ */
+ public void createFieldEditors() {
+
+ addField(new BooleanFieldEditor(MavenPreferenceConstants.P_OFFLINE, Messages.getString("preferences.offline"), //$NON-NLS-1$
+ getFieldEditorParent()));
+
+ addField(new BooleanFieldEditor(MavenPreferenceConstants.P_DEBUG_OUTPUT, //
+ Messages.getString("preferences.debugOutput"), //$NON-NLS-1$
+ getFieldEditorParent()));
+
+ // addField( new BooleanFieldEditor( MavenPreferenceConstants.P_UPDATE_SNAPSHOTS,
+ // Messages.getString( "preferences.updateSnapshots" ), //$NON-NLS-1$
+ // getFieldEditorParent() ) );
+
+ addField(new BooleanFieldEditor(MavenPreferenceConstants.P_DOWNLOAD_SOURCES, //
+ Messages.getString("preferences.downloadSources"), //$NON-NLS-1$
+ getFieldEditorParent()));
+
+ addField(new BooleanFieldEditor(MavenPreferenceConstants.P_DOWNLOAD_JAVADOC, //
+ Messages.getString("preferences.downloadJavadoc"), //$NON-NLS-1$
+ getFieldEditorParent()));
+
+ addField(new BooleanFieldEditor(MavenPreferenceConstants.P_UPDATE_INDEXES, //
+ org.eclipse.m2e.core.internal.Messages.MavenPreferencePage_download, //
+ getFieldEditorParent()));
+
+ addField(new BooleanFieldEditor(MavenPreferenceConstants.P_UPDATE_PROJECTS, //
+ org.eclipse.m2e.core.internal.Messages.MavenPreferencePage_update, //
+ getFieldEditorParent()));
+
+ addField(new BooleanFieldEditor(MavenPreferenceConstants.P_HIDE_FOLDERS_OF_NESTED_PROJECTS, //
+ org.eclipse.m2e.core.internal.Messages.MavenPreferencePage_hide, getFieldEditorParent()));
+
+ GridData comboCompositeGridData = new GridData();
+ comboCompositeGridData.verticalIndent = 25;
+ comboCompositeGridData.horizontalSpan = 3;
+ comboCompositeGridData.grabExcessHorizontalSpace = true;
+ comboCompositeGridData.horizontalAlignment = GridData.FILL;
+
+ Composite comboComposite = new Composite(getFieldEditorParent(), SWT.NONE);
+ comboComposite.setLayoutData(comboCompositeGridData);
+ comboComposite.setLayout(new GridLayout(2, false));
+
+ // addSeparator();
+ }
+
+ private void addSeparator() {
+ Label separator = new Label(getFieldEditorParent(), SWT.HORIZONTAL | SWT.SEPARATOR);
+ // separator.setVisible(false);
+ GridData separatorGridData = new GridData();
+ separatorGridData.horizontalSpan = 4;
+ separatorGridData.grabExcessHorizontalSpace = true;
+ separatorGridData.horizontalAlignment = GridData.FILL;
+ separatorGridData.verticalIndent = 10;
+ separator.setLayoutData(separatorGridData);
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenProjectLifecycleMappingPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenProjectLifecycleMappingPage.java
new file mode 100644
index 00000000..119b8d22
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenProjectLifecycleMappingPage.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.preferences;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.configurator.ILifecycleMapping;
+import org.eclipse.m2e.core.ui.internal.lifecycle.ILifecyclePropertyPage;
+import org.eclipse.m2e.core.ui.internal.lifecycle.LifecycleMappingPropertyPageFactory;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+/**
+ * Maven project preference page
+ *
+ * @author Dan Yocum
+ */
+public class MavenProjectLifecycleMappingPage extends PropertyPage{
+
+ private ILifecyclePropertyPage currentPage;
+
+ public MavenProjectLifecycleMappingPage() {
+
+ setTitle(""); //$NON-NLS-1$
+ }
+
+ protected Control createContents(Composite parent) {
+ currentPage = loadCurrentPage((IProject)getElement());
+ setMessage(currentPage.getName());
+ return currentPage.createContents(parent);
+ }
+
+ private ILifecyclePropertyPage getErrorPage(String msg){
+ SimpleLifecycleMappingPropertyPage p = new SimpleLifecycleMappingPropertyPage(msg);
+ return p;
+ }
+
+ private ILifecyclePropertyPage getPage(ILifecycleMapping lifecycleMapping){
+ ILifecyclePropertyPage page = LifecycleMappingPropertyPageFactory.getFactory().getPageForId(lifecycleMapping.getId(), getProject(), this.getShell());
+ if(page == null){
+ page = getErrorPage(Messages.MavenProjectLifecycleMappingPage_error_no_page);
+ page.setName(lifecycleMapping.getName());
+ }
+ return page;
+ }
+
+ private ILifecyclePropertyPage loadCurrentPage(IProject project){
+ ILifecyclePropertyPage page = null;
+ try{
+ ILifecycleMapping lifecycleMapping = LifecycleMappingPropertyPageFactory.getLifecycleMapping(project);
+ if(lifecycleMapping == null){
+ return getErrorPage(Messages.MavenProjectLifecycleMappingPage_error_no_strategy);
+ }
+ page = getPage(lifecycleMapping);
+ return page;
+ } catch(CoreException ce){
+ MavenLogger.log(ce);
+ SimpleLifecycleMappingPropertyPage p = new SimpleLifecycleMappingPropertyPage(Messages.MavenProjectLifecycleMappingPage_error_page_error);
+ return p;
+ }
+ }
+
+ protected void performDefaults() {
+ currentPage.performDefaults();
+ }
+
+ protected IProject getProject() {
+ return (IProject) getElement();
+ }
+
+ public boolean performOk() {
+ return currentPage.performOk();
+ }
+
+ public void setElement(IAdaptable element){
+ if(currentPage != null && element instanceof IProject){
+ currentPage.setProject((IProject)element);
+ }
+ super.setElement(element);
+ }
+
+}
+
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenProjectPreferencePage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenProjectPreferencePage.java
new file mode 100644
index 00000000..5803311b
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenProjectPreferencePage.java
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.preferences;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.WorkspaceJob;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.MavenProjectManager;
+import org.eclipse.m2e.core.project.ResolverConfiguration;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+/**
+ * Maven project preference page
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenProjectPreferencePage extends PropertyPage {
+
+ private Button resolveWorspaceProjectsButton;
+// private Button includeModulesButton;
+
+ private Text activeProfilesText;
+
+ public MavenProjectPreferencePage() {
+ setTitle(Messages.MavenProjectPreferencePage_title);
+ }
+
+ protected Control createContents(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout(2, false));
+ composite.setLayoutData(new GridData(GridData.FILL));
+
+ Label profilesLabel = new Label(composite, SWT.NONE);
+ profilesLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
+ profilesLabel.setText(Messages.MavenProjectPreferencePage_lblProfiles);
+
+ activeProfilesText = new Text(composite, SWT.BORDER);
+ activeProfilesText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+
+ resolveWorspaceProjectsButton = new Button(composite, SWT.CHECK);
+ GridData resolveWorspaceProjectsButtonData = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1);
+ resolveWorspaceProjectsButton.setLayoutData(resolveWorspaceProjectsButtonData);
+ resolveWorspaceProjectsButton.setText(Messages.MavenProjectPreferencePage_btnResolve);
+
+// includeModulesButton = new Button(composite, SWT.CHECK);
+// GridData gd = new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1);
+// gd.verticalIndent = 15;
+// includeModulesButton.setLayoutData(gd);
+// includeModulesButton.setText("Include &Modules");
+//
+// Text includeModulesText = new Text(composite, SWT.WRAP | SWT.READ_ONLY | SWT.MULTI);
+// includeModulesText.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_BLUE));
+// GridData gd_includeModulesText = new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1);
+// gd_includeModulesText.horizontalIndent = 15;
+// gd_includeModulesText.verticalIndent = 0;
+// gd_includeModulesText.widthHint = 300;
+// gd_includeModulesText.heightHint = 120;
+// includeModulesText.setLayoutData(gd_includeModulesText);
+// includeModulesText.setBackground(composite.getBackground());
+// includeModulesText.setText("When enabled, dependencies from all nested modules "
+// + "are added to the \"Maven Dependencies\" container and "
+// + "source folders from nested modules are added to the current "
+// + "project build path (use \"Update Sources\" action)");
+
+ init(getResolverConfiguration());
+
+ return composite;
+ }
+
+ protected void performDefaults() {
+ init(new ResolverConfiguration());
+ }
+
+ private void init(ResolverConfiguration configuration) {
+
+ resolveWorspaceProjectsButton.setSelection(configuration.shouldResolveWorkspaceProjects());
+// includeModulesButton.setSelection(configuration.shouldIncludeModules());
+ activeProfilesText.setText(configuration.getActiveProfiles());
+ }
+
+ public boolean performOk() {
+ final IProject project = getProject();
+ try {
+ if(!project.isAccessible() || !project.hasNature(IMavenConstants.NATURE_ID)) {
+ return true;
+ }
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ return false;
+ }
+
+ final ResolverConfiguration configuration = getResolverConfiguration();
+ if(configuration.getActiveProfiles().equals(activeProfilesText.getText()) &&
+// configuration.shouldIncludeModules()==includeModulesButton.getSelection() &&
+ configuration.shouldResolveWorkspaceProjects()==resolveWorspaceProjectsButton.getSelection()) {
+ return true;
+ }
+
+ configuration.setResolveWorkspaceProjects(resolveWorspaceProjectsButton.getSelection());
+// configuration.setIncludeModules(includeModulesButton.getSelection());
+ configuration.setActiveProfiles(activeProfilesText.getText());
+
+ MavenProjectManager projectManager = MavenPlugin.getDefault().getMavenProjectManager();
+ boolean isSet = projectManager.setResolverConfiguration(getProject(), configuration);
+ if(isSet) {
+
+ boolean res = MessageDialog.openQuestion(getShell(), Messages.MavenProjectPreferencePage_dialog_title, //
+ Messages.MavenProjectPreferencePage_dialog_message);
+ if(res) {
+ final MavenPlugin plugin = MavenPlugin.getDefault();
+ WorkspaceJob job = new WorkspaceJob(NLS.bind(Messages.MavenProjectPreferencePage_job, project.getName() )) {
+ public IStatus runInWorkspace(IProgressMonitor monitor) {
+ try {
+ plugin.getProjectConfigurationManager().updateProjectConfiguration(project, monitor);
+ } catch(CoreException ex) {
+ return ex.getStatus();
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ job.setRule(plugin.getProjectConfigurationManager().getRule());
+ job.schedule();
+ }
+
+ }
+
+ return isSet;
+ }
+
+ private ResolverConfiguration getResolverConfiguration() {
+ MavenProjectManager projectManager = MavenPlugin.getDefault().getMavenProjectManager();
+ return projectManager.getResolverConfiguration(getProject());
+ }
+
+ private IProject getProject() {
+ return (IProject) getElement();
+ }
+
+}
+
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenSettingsPreferencePage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenSettingsPreferencePage.java
new file mode 100644
index 00000000..b96c844a
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MavenSettingsPreferencePage.java
@@ -0,0 +1,411 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.preferences;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.maven.cli.MavenCli;
+import org.apache.maven.repository.RepositorySystem;
+import org.apache.maven.settings.Settings;
+import org.apache.maven.settings.building.SettingsProblem;
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.WorkspaceJob;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.embedder.IMavenConfiguration;
+import org.eclipse.m2e.core.embedder.MavenRuntime;
+import org.eclipse.m2e.core.embedder.MavenRuntimeManager;
+import org.eclipse.m2e.core.index.IndexManager;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.MavenUpdateRequest;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IPropertyListener;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+
+
+/**
+ * Maven installations preference page
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenSettingsPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+
+ final MavenPlugin mavenPlugin;
+
+ final MavenRuntimeManager runtimeManager;
+
+ final IMavenConfiguration mavenConfiguration;
+
+ final IMaven maven;
+
+ MavenRuntime defaultRuntime;
+
+
+ Text userSettingsText;
+
+ Text localRepositoryText;
+
+ boolean dirty = false;
+
+ private Link userSettingsLink;
+
+ public MavenSettingsPreferencePage() {
+ setTitle(org.eclipse.m2e.core.internal.Messages.MavenSettingsPreferencePage_title);
+
+ this.mavenPlugin = MavenPlugin.getDefault();
+ this.runtimeManager = mavenPlugin.getMavenRuntimeManager();
+ this.mavenConfiguration = MavenPlugin.getDefault().getMavenConfiguration();
+ this.maven = MavenPlugin.getDefault().getMaven();
+ }
+
+ public void init(IWorkbench workbench) {
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.DialogPage#setVisible(boolean)
+ */
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ if(visible){
+ updateLocalRepository();
+ }
+ }
+
+ protected void performDefaults() {
+ userSettingsText.setText(MavenCli.DEFAULT_USER_SETTINGS_FILE.getAbsolutePath());
+ setDirty(true);
+ updateLocalRepository();
+ super.performDefaults();
+ }
+
+ protected void updateSettings(final boolean updateMavenDependencies){
+ final String userSettings = getUserSettings();
+
+ new Job(org.eclipse.m2e.core.internal.Messages.MavenSettingsPreferencePage_job_updating) {
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ final File localRepositoryDir = new File(maven.getLocalRepository().getBasedir());
+ if(userSettings.length() > 0) {
+ mavenConfiguration.setUserSettingsFile(userSettings);
+ } else {
+ mavenConfiguration.setUserSettingsFile(null);
+ }
+
+ File newRepositoryDir = new File(maven.getLocalRepository().getBasedir());
+ if(!newRepositoryDir.equals(localRepositoryDir)) {
+ IndexManager indexManager = mavenPlugin.getIndexManager();
+ indexManager.getWorkspaceIndex().updateIndex(true, monitor);
+ }
+ if(updateMavenDependencies){
+ IMavenProjectFacade[] projects = MavenPlugin.getDefault().getMavenProjectManager().getProjects();
+ ArrayList<IProject> allProjects = new ArrayList<IProject>();
+ if(projects != null){
+ MavenPlugin.getDefault().getMaven().reloadSettings();
+ SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, projects.length);
+ for(int i=0;i<projects.length;i++){
+ subMonitor.beginTask(NLS.bind(org.eclipse.m2e.core.internal.Messages.MavenSettingsPreferencePage_task_updating, projects[i].getProject().getName()), 1);
+ allProjects.add(projects[i].getProject());
+ }
+ IMavenConfiguration configuration = MavenPlugin.getDefault().getMavenConfiguration();
+ MavenPlugin.getDefault().getMavenProjectManager().refresh(new MavenUpdateRequest(allProjects.toArray(new IProject[]{}), configuration.isOffline(), true));
+ subMonitor.done();
+ }
+ }
+ return Status.OK_STATUS;
+ } catch (CoreException e) {
+ return e.getStatus();
+ }
+ }
+ }.schedule();
+ }
+
+ protected void performApply() {
+ if(dirty){
+ updateSettings(false);
+ }
+ }
+
+ public boolean performOk() {
+ if (dirty) {
+ updateSettings(false);
+ }
+ return true;
+ }
+
+ public void setDirty(boolean dirty){
+ this.dirty = dirty;
+ }
+
+ public boolean isDirty(){
+ return this.dirty;
+ }
+
+ protected Control createContents(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout gridLayout = new GridLayout(4, false);
+ gridLayout.marginBottom = 5;
+ gridLayout.marginRight = 5;
+ gridLayout.marginHeight = 0;
+ gridLayout.marginWidth = 0;
+ composite.setLayout(gridLayout);
+
+ createUserSettings(composite);
+ Label localRepositoryLabel = new Label(composite, SWT.NONE);
+ GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1);
+ gd.verticalIndent=25;
+ localRepositoryLabel.setLayoutData(gd);
+ localRepositoryLabel.setText(org.eclipse.m2e.core.internal.Messages.MavenSettingsPreferencePage_lblLocal);
+
+ localRepositoryText = new Text(composite, SWT.READ_ONLY|SWT.BORDER);
+ localRepositoryText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
+ localRepositoryText.setData("name", "localRepositoryText"); //$NON-NLS-1$ //$NON-NLS-2$
+ localRepositoryText.setEditable(false);
+ Button reindexButton = new Button(composite, SWT.NONE);
+ reindexButton.setLayoutData(new GridData(SWT.FILL, SWT.RIGHT, false, false, 1, 1));
+ reindexButton.setText(Messages.getString("preferences.reindexButton")); //$NON-NLS-1$
+ reindexButton.addSelectionListener(new SelectionAdapter(){
+
+ /* (non-Javadoc)
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ public void widgetSelected(SelectionEvent e) {
+ new WorkspaceJob(org.eclipse.m2e.core.internal.Messages.MavenSettingsPreferencePage_job_indexing) {
+ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
+ IndexManager indexManager = mavenPlugin.getIndexManager();
+ indexManager.getWorkspaceIndex().updateIndex(true, monitor);
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ }
+ });
+ defaultRuntime = runtimeManager.getDefaultRuntime();
+
+ String userSettings = mavenConfiguration.getUserSettingsFile();
+ if(userSettings == null || userSettings.length() == 0) {
+ userSettingsText.setText(MavenCli.DEFAULT_USER_SETTINGS_FILE.getAbsolutePath());
+ } else {
+ userSettingsText.setText(userSettings);
+ }
+
+ checkSettings();
+ updateLocalRepository();
+
+ userSettingsText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent modifyevent) {
+ updateLocalRepository();
+ checkSettings();
+ setDirty(true);
+ }
+ });
+
+ return composite;
+ }
+
+ public void updateSettingsLink(boolean active){
+ String text = org.eclipse.m2e.core.internal.Messages.MavenSettingsPreferencePage_link1;
+ if(active){
+ text = org.eclipse.m2e.core.internal.Messages.MavenSettingsPreferencePage_link2;
+ }
+ userSettingsLink.setText(text);
+ }
+ /**
+ * @param composite
+ */
+ private void createUserSettings(Composite composite) {
+
+ userSettingsLink = new Link(composite, SWT.NONE);
+ userSettingsLink.setData("name", "userSettingsLink"); //$NON-NLS-1$ //$NON-NLS-2$
+ userSettingsLink.setText(org.eclipse.m2e.core.internal.Messages.MavenSettingsPreferencePage_link2);
+ userSettingsLink.setToolTipText(org.eclipse.m2e.core.internal.Messages.MavenSettingsPreferencePage_link_tooltip);
+ GridData gd_userSettingsLabel = new GridData(SWT.FILL, SWT.CENTER, true, false, 4, 1);
+
+ gd_userSettingsLabel.verticalIndent = 15;
+ userSettingsLink.setLayoutData(gd_userSettingsLabel);
+ userSettingsLink.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ String userSettings = getUserSettings();
+ if(userSettings.length() == 0) {
+ userSettings = MavenCli.DEFAULT_USER_SETTINGS_FILE.getAbsolutePath();
+ }
+ openEditor(userSettings);
+ }
+ });
+ userSettingsText = new Text(composite, SWT.BORDER);
+ userSettingsText.setData("name", "userSettingsText"); //$NON-NLS-1$ //$NON-NLS-2$
+ GridData gd_userSettingsText = new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1);
+ gd_userSettingsText.verticalIndent = 5;
+ gd_userSettingsText.widthHint = 100;
+ userSettingsText.setLayoutData(gd_userSettingsText);
+
+ Button userSettingsBrowseButton = new Button(composite, SWT.NONE);
+ GridData gd_userSettingsBrowseButton = new GridData(SWT.FILL, SWT.RIGHT, false, false, 1, 1);
+
+ userSettingsBrowseButton.setLayoutData(gd_userSettingsBrowseButton);
+ userSettingsBrowseButton.setText(org.eclipse.m2e.core.internal.Messages.MavenSettingsPreferencePage_btnBrowse);
+ userSettingsBrowseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ FileDialog dialog = new FileDialog(getShell(), SWT.OPEN);
+ if(getUserSettings().length() > 0) {
+ dialog.setFileName(getUserSettings());
+ }
+ String file = dialog.open();
+ if(file != null) {
+ file = file.trim();
+ if(file.length() > 0) {
+ userSettingsText.setText(file);
+ updateLocalRepository();
+ checkSettings();
+ }
+ }
+ }
+ });
+
+ Button updateSettings = new Button(composite, SWT.NONE);
+ GridData gd = new GridData(SWT.FILL, SWT.LEFT, false, false, 1, 1);
+ updateSettings.setText(org.eclipse.m2e.core.internal.Messages.MavenSettingsPreferencePage_btnUpdate);
+ updateSettings.addSelectionListener(new SelectionAdapter(){
+ public void widgetSelected(SelectionEvent e){
+ updateSettings(true);
+ }
+ });
+ }
+
+ protected void updateLocalRepository() {
+ final String userSettings = getUserSettings();
+ String globalSettings = runtimeManager.getGlobalSettingsFile();
+ try {
+ Settings settings = maven.buildSettings(globalSettings, userSettings);
+ String localRepository = settings.getLocalRepository();
+ if(localRepository == null){
+ localRepository = RepositorySystem.defaultUserLocalRepository.getAbsolutePath();
+ }
+ if(!localRepositoryText.isDisposed()) {
+ localRepositoryText.setText(localRepository == null ? "" : localRepository); //$NON-NLS-1$
+ }
+ } catch (CoreException e) {
+ setMessage(e.getMessage(), IMessageProvider.ERROR);
+ }
+ }
+
+ protected void checkSettings() {
+ setErrorMessage(null);
+ setMessage(null);
+ boolean fileExists = false;
+ String userSettings = getUserSettings();
+ if(userSettings != null && userSettings.length() > 0) {
+ File userSettingsFile = new File(userSettings);
+ if(!userSettingsFile.exists()) {
+ setMessage(org.eclipse.m2e.core.internal.Messages.MavenSettingsPreferencePage_error_missing, IMessageProvider.WARNING);
+ userSettings = null;
+
+ } else {
+ fileExists = true;
+ }
+
+ } else {
+ userSettings = null;
+ }
+ updateSettingsLink(fileExists);
+ List<SettingsProblem> result = maven.validateSettings(userSettings);
+ if(result.size() > 0) {
+ setMessage(NLS.bind(org.eclipse.m2e.core.internal.Messages.MavenSettingsPreferencePage_error_parse, result.get(0).getMessage()), IMessageProvider.WARNING);
+ }
+ }
+
+
+
+ @SuppressWarnings("unchecked")
+ void openEditor(final String fileName) {
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
+ IWorkbenchPage page = window.getActivePage();
+
+ IEditorDescriptor desc = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor("settings.xml"); //$NON-NLS-1$
+
+ File file = new File(fileName);
+ IEditorInput input = null;
+ try {
+ //class implementing editor input for external file has been renamed in eclipse 3.3, hence reflection
+ Class javaInput = null;
+ try {
+ javaInput = Class.forName("org.eclipse.ui.internal.editors.text.JavaFileEditorInput"); //$NON-NLS-1$
+ Constructor cons = javaInput.getConstructor(new Class[] {File.class});
+ input = (IEditorInput) cons.newInstance(new Object[] {file});
+ } catch(Exception e) {
+ try {
+ IFileStore fileStore = EFS.getLocalFileSystem().fromLocalFile(file);
+ Class storeInput = Class.forName("org.eclipse.ui.ide.FileStoreEditorInput"); //$NON-NLS-1$
+ Constructor cons = storeInput.getConstructor(new Class[] {IFileStore.class});
+ input = (IEditorInput) cons.newInstance(new Object[] {fileStore});
+ } catch(Exception ex) {
+ //ignore...
+ }
+ }
+ final IEditorPart editor = IDE.openEditor(page, input, desc.getId());
+ editor.addPropertyListener(new IPropertyListener() {
+ public void propertyChanged(Object source, int propId) {
+ if(!editor.isDirty()) {
+ mavenPlugin.getConsole().logMessage("Refreshing settings " + fileName);
+ }
+ }
+ });
+
+ } catch(PartInitException ex) {
+ MavenLogger.log(ex);
+ }
+ }
+
+ String getUserSettings() {
+ return userSettingsText.getText().trim();
+ }
+
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MissingLifecycleMappingPropertyPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MissingLifecycleMappingPropertyPage.java
new file mode 100644
index 00000000..f9b0d893
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/MissingLifecycleMappingPropertyPage.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.preferences;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.configurator.ILifecycleMapping;
+import org.eclipse.m2e.core.ui.internal.lifecycle.LifecycleMappingPropertyPageFactory;
+
+public class MissingLifecycleMappingPropertyPage extends SimpleLifecycleMappingPropertyPage {
+
+ public MissingLifecycleMappingPropertyPage() {
+ super(Messages.MissingLifecycleMappingPropertyPage_title);
+ }
+
+ protected String getMessage() {
+ try {
+ ILifecycleMapping lifecycleMapping = LifecycleMappingPropertyPageFactory.getLifecycleMapping(getProject());
+ if(lifecycleMapping == null) {
+ return Messages.MissingLifecycleMappingPropertyPage_error;
+ }
+ } catch(CoreException ex) {
+ // this is odd, but lets ignore it anyways
+ }
+ return super.getMessage();
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/RemoteArchetypeCatalogDialog.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/RemoteArchetypeCatalogDialog.java
new file mode 100644
index 00000000..fa194908
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/RemoteArchetypeCatalogDialog.java
@@ -0,0 +1,282 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.preferences;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.maven.archetype.catalog.Archetype;
+import org.apache.maven.archetype.catalog.ArchetypeCatalog;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.dialogs.DialogSettings;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.m2e.core.archetype.ArchetypeCatalogFactory;
+import org.eclipse.m2e.core.archetype.ArchetypeCatalogFactory.RemoteCatalogFactory;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Remote Archetype catalog dialog
+ *
+ * @author Eugene Kuleshov
+ */
+public class RemoteArchetypeCatalogDialog extends TitleAreaDialog {
+
+ /**
+ *
+ */
+ private static final int VERIFY_ID = IDialogConstants.CLIENT_ID + 1;
+
+ private static final String DIALOG_SETTINGS = RemoteArchetypeCatalogDialog.class.getName();
+
+ private static final String KEY_LOCATIONS = "catalogUrl"; //$NON-NLS-1$
+
+ private static final int MAX_HISTORY = 15;
+
+ private String title;
+
+ private String message;
+
+ Combo catalogUrlCombo;
+
+ private Text catalogDescriptionText;
+
+ private IDialogSettings dialogSettings;
+
+ private ArchetypeCatalogFactory archetypeCatalogFactory;
+
+ Button verifyButton;
+
+
+ protected RemoteArchetypeCatalogDialog(Shell shell, ArchetypeCatalogFactory factory) {
+ super(shell);
+ this.archetypeCatalogFactory = factory;
+ this.title = Messages.RemoteArchetypeCatalogDialog_title;
+ this.message = Messages.RemoteArchetypeCatalogDialog_message;
+ setShellStyle(SWT.DIALOG_TRIM);
+
+ IDialogSettings pluginSettings = M2EUIPluginActivator.getDefault().getDialogSettings();
+ dialogSettings = pluginSettings.getSection(DIALOG_SETTINGS);
+ if(dialogSettings == null) {
+ dialogSettings = new DialogSettings(DIALOG_SETTINGS);
+ pluginSettings.addSection(dialogSettings);
+ }
+ }
+
+ protected Control createContents(Composite parent) {
+ Control control = super.createContents(parent);
+ setTitle(title);
+ setMessage(message);
+ return control;
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite composite1 = (Composite) super.createDialogArea(parent);
+
+ Composite composite = new Composite(composite1, SWT.NONE);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.marginTop = 7;
+ gridLayout.marginWidth = 12;
+ gridLayout.numColumns = 2;
+ composite.setLayout(gridLayout);
+
+ Label catalogLocationLabel = new Label(composite, SWT.NONE);
+ catalogLocationLabel.setText(Messages.RemoteArchetypeCatalogDialog_lblCatalog);
+
+ catalogUrlCombo = new Combo(composite, SWT.NONE);
+ GridData gd_catalogLocationCombo = new GridData(SWT.FILL, SWT.CENTER, true, false);
+ gd_catalogLocationCombo.widthHint = 250;
+ catalogUrlCombo.setLayoutData(gd_catalogLocationCombo);
+ catalogUrlCombo.setItems(getSavedValues(KEY_LOCATIONS));
+
+ Label catalogDescriptionLabel = new Label(composite, SWT.NONE);
+ catalogDescriptionLabel.setText(Messages.RemoteArchetypeCatalogDialog_lblDesc);
+
+ catalogDescriptionText = new Text(composite, SWT.BORDER);
+ catalogDescriptionText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+
+ if(archetypeCatalogFactory!=null) {
+ catalogUrlCombo.setText(archetypeCatalogFactory.getId());
+ catalogDescriptionText.setText(archetypeCatalogFactory.getDescription());
+ }
+
+ ModifyListener modifyListener = new ModifyListener() {
+ public void modifyText(final ModifyEvent e) {
+ update();
+ }
+ };
+ catalogUrlCombo.addModifyListener(modifyListener);
+ catalogDescriptionText.addModifyListener(modifyListener);
+
+ return composite;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.TrayDialog#createButtonBar(org.eclipse.swt.widgets.Composite)
+ */
+ protected Control createButtonBar(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+ layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+ layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+ layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ composite.setFont(parent.getFont());
+
+ // create help control if needed
+ if(isHelpAvailable()) {
+ createHelpControl(composite);
+ }
+
+ verifyButton = createButton(composite, VERIFY_ID, Messages.RemoteArchetypeCatalogDialog_btnVerify, false);
+ verifyButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ verifyButton.setEnabled(false);
+ String url = catalogUrlCombo.getText();
+ final RemoteCatalogFactory factory = new RemoteCatalogFactory(url, null, true);
+
+ new Job(Messages.RemoteArchetypeCatalogDialog_job_download) {
+ protected IStatus run(IProgressMonitor monitor) {
+ IStatus status = Status.OK_STATUS;
+ ArchetypeCatalog catalog = null;
+ try {
+ catalog = factory.getArchetypeCatalog();
+ } finally {
+ final IStatus s = status;
+ @SuppressWarnings("unchecked")
+ final List<Archetype> archetypes = catalog==null ? Collections.emptyList() : catalog.getArchetypes();
+ getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ verifyButton.setEnabled(true);
+ if(!s.isOK()) {
+ setErrorMessage(NLS.bind(Messages.RemoteArchetypeCatalogDialog_error_read,s.getMessage()));
+ getButton(IDialogConstants.OK_ID).setEnabled(false);
+ } else if(archetypes.size()==0) {
+ setMessage(Messages.RemoteArchetypeCatalogDialog_error_empty, IStatus.WARNING);
+ } else {
+ setMessage(NLS.bind(Messages.RemoteArchetypeCatalogDialog_message_found, archetypes.size()), IStatus.INFO);
+ }
+ }
+ });
+ }
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ }
+ });
+
+ Label filler= new Label(composite, SWT.NONE);
+ filler.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
+ layout.numColumns++;
+
+ super.createButtonsForButtonBar(composite); // cancel button
+
+ return composite;
+ }
+
+ protected Button getButton(int id) {
+ return super.getButton(id);
+ }
+
+ private String[] getSavedValues(String key) {
+ String[] array = dialogSettings.getArray(key);
+ return array == null ? new String[0] : array;
+ }
+
+ protected void configureShell(Shell shell) {
+ super.configureShell(shell);
+ shell.setText(title);
+ }
+
+ public void create() {
+ super.create();
+ getButton(IDialogConstants.OK_ID).setEnabled(false);
+ getButton(VERIFY_ID).setEnabled(false);
+ }
+
+ protected void okPressed() {
+ String description = catalogDescriptionText.getText().trim();
+ String location = catalogUrlCombo.getText().trim();
+
+ archetypeCatalogFactory = new RemoteCatalogFactory(location, description, true);
+
+ saveValue(KEY_LOCATIONS, location);
+
+ super.okPressed();
+ }
+
+ public ArchetypeCatalogFactory getArchetypeCatalogFactory() {
+ return archetypeCatalogFactory;
+ }
+
+ private void saveValue(String key, String value) {
+ List<String> dirs = new ArrayList<String>();
+ dirs.addAll(Arrays.asList(getSavedValues(key)));
+
+ dirs.remove(value);
+ dirs.add(0, value);
+
+ if(dirs.size() > MAX_HISTORY) {
+ dirs = dirs.subList(0, MAX_HISTORY);
+ }
+
+ dialogSettings.put(key, dirs.toArray(new String[dirs.size()]));
+ }
+
+ void update() {
+ boolean isValid = isValid();
+ getButton(IDialogConstants.OK_ID).setEnabled(isValid);
+ getButton(VERIFY_ID).setEnabled(isValid);
+ }
+
+ private boolean isValid() {
+ setErrorMessage(null);
+ setMessage(null, IStatus.WARNING);
+
+
+ String url = catalogUrlCombo.getText().trim();
+ if(url.length()==0) {
+ setErrorMessage(Messages.RemoteArchetypeCatalogDialog_error_required);
+ verifyButton.setEnabled(false);
+ return false;
+ }
+
+ verifyButton.setEnabled(true);
+ return true;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/SimpleLifecycleMappingPropertyPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/SimpleLifecycleMappingPropertyPage.java
new file mode 100644
index 00000000..9044e069
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/SimpleLifecycleMappingPropertyPage.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.preferences;
+
+import org.eclipse.m2e.core.ui.internal.lifecycle.AbstractLifecyclePropertyPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+
+
+/**
+ * Simple lifecycle mapping properties page that displays static text.
+ *
+ * @author igor
+ */
+public class SimpleLifecycleMappingPropertyPage extends AbstractLifecyclePropertyPage {
+
+ private String message;
+
+ public SimpleLifecycleMappingPropertyPage(String message) {
+ this.message = message;
+ }
+
+ public Control createContents(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout(2, false));
+ composite.setLayoutData(new GridData(GridData.FILL));
+ Label noInfoLabel = new Label(composite, SWT.NONE);
+ noInfoLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 2, 1));
+ noInfoLabel.setAlignment(SWT.CENTER);
+ noInfoLabel.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY));
+ noInfoLabel.setData("name", "noInfoLabel"); //$NON-NLS-1$ //$NON-NLS-2$
+ noInfoLabel.setText(getMessage());
+ return composite;
+ }
+
+ protected String getMessage() {
+ return message;
+ }
+
+ public void performDefaults() {
+ }
+
+ public boolean performOk() {
+ return true;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/MavenSearchPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/MavenSearchPage.java
new file mode 100644
index 00000000..b58dddd9
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/MavenSearchPage.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.search;
+
+import org.eclipse.jface.dialogs.DialogPage;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.search.ui.ISearchPage;
+import org.eclipse.search.ui.ISearchPageContainer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+
+/**
+ * Maven Search Page
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenSearchPage extends DialogPage implements ISearchPage {
+
+ private Table table;
+ private Combo classNameText;
+ private Combo sha1Text;
+ private Combo versionText;
+ private Combo packagingIdText;
+ private Combo artifactIdText;
+ private Combo groupIdText;
+
+ // private ISearchPageContainer container;
+
+ public MavenSearchPage() {
+ }
+
+ public MavenSearchPage(String title) {
+ super(title);
+ }
+
+ public MavenSearchPage(String title, ImageDescriptor image) {
+ super(title, image);
+ }
+
+ public void setContainer(ISearchPageContainer container) {
+ // this.container = container;
+ }
+
+ public boolean performAction() {
+ // TODO Auto-generated method performAction
+ return false;
+ }
+
+ public void createControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout(3, false));
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ setControl(parent);
+
+ Label groupIdLabel = new Label(composite, SWT.NONE);
+ groupIdLabel.setText(Messages.MavenSearchPage_lblGroupid);
+
+ groupIdText = new Combo(composite, SWT.NONE);
+ groupIdText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+
+ Label artifactIdLabel = new Label(composite, SWT.NONE);
+ artifactIdLabel.setText(Messages.MavenSearchPage_lblArtifactid);
+
+ artifactIdText = new Combo(composite, SWT.NONE);
+ artifactIdText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+
+ Label versionLabel = new Label(composite, SWT.NONE);
+ versionLabel.setText(Messages.MavenSearchPage_lblVersion);
+
+ versionText = new Combo(composite, SWT.NONE);
+ versionText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+
+ Label packagingIdLabel = new Label(composite, SWT.NONE);
+ packagingIdLabel.setText(Messages.MavenSearchPage_lblPackaging);
+
+ packagingIdText = new Combo(composite, SWT.NONE);
+ GridData packagingIdTextData = new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1);
+ packagingIdTextData.widthHint = 208;
+ packagingIdText.setLayoutData(packagingIdTextData);
+
+ Label sha1Label = new Label(composite, SWT.NONE);
+ sha1Label.setText(Messages.MavenSearchPage_lblSha);
+
+ sha1Text = new Combo(composite, SWT.NONE);
+ sha1Text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+
+ Button browseButton = new Button(composite, SWT.NONE);
+ browseButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ browseButton.setText(Messages.MavenSearchPage_btnBrowse);
+
+ Label classNameLabel = new Label(composite, SWT.NONE);
+ classNameLabel.setText(Messages.MavenSearchPage_lblClass);
+
+ classNameText = new Combo(composite, SWT.NONE);
+ classNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+
+ Label separator = new Label(composite, SWT.HORIZONTAL | SWT.SEPARATOR);
+ GridData separatorData = new GridData(SWT.FILL, SWT.TOP, false, false, 3, 1);
+ separatorData.heightHint = 15;
+ separatorData.minimumHeight = 15;
+ separator.setLayoutData(separatorData);
+ separator.setText(Messages.MavenSearchPage_separator);
+
+ Label repositoriesLabel = new Label(composite, SWT.NONE);
+ repositoriesLabel.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
+ repositoriesLabel.setText(Messages.MavenSearchPage_lblRepos);
+
+ CheckboxTableViewer tableViewer = CheckboxTableViewer.newCheckList(composite, SWT.BORDER);
+ table = tableViewer.getTable();
+ table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 2));
+
+ Button selectAllButton = new Button(composite, SWT.NONE);
+ selectAllButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ selectAllButton.setText(Messages.MavenSearchPage_btnSelect);
+ new Label(composite, SWT.NONE);
+
+ Button deselectAllButton = new Button(composite, SWT.NONE);
+ deselectAllButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ deselectAllButton.setText(Messages.MavenSearchPage_btnUnselect);
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/MavenSearchResult.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/MavenSearchResult.java
new file mode 100644
index 00000000..a464aeea
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/MavenSearchResult.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.search;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.search.ui.ISearchQuery;
+import org.eclipse.search.ui.text.AbstractTextSearchResult;
+import org.eclipse.search.ui.text.IEditorMatchAdapter;
+import org.eclipse.search.ui.text.IFileMatchAdapter;
+
+/**
+ * Maven search result
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenSearchResult extends AbstractTextSearchResult {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.search.ui.ISearchResult#getQuery()
+ */
+ public ISearchQuery getQuery() {
+ // TODO Auto-generated method getQuery
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.search.ui.ISearchResult#getLabel()
+ */
+ public String getLabel() {
+ // TODO Auto-generated method getLabel
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.search.ui.ISearchResult#getImageDescriptor()
+ */
+ public ImageDescriptor getImageDescriptor() {
+ // TODO Auto-generated method getImageDescriptor
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.search.ui.ISearchResult#getTooltip()
+ */
+ public String getTooltip() {
+ // TODO Auto-generated method getTooltip
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.search.ui.text.AbstractTextSearchResult#getEditorMatchAdapter()
+ */
+ public IEditorMatchAdapter getEditorMatchAdapter() {
+ // TODO Auto-generated method getEditorMatchAdapter
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.search.ui.text.AbstractTextSearchResult#getFileMatchAdapter()
+ */
+ public IFileMatchAdapter getFileMatchAdapter() {
+ // TODO Auto-generated method getFileMatchAdapter
+ return null;
+ }
+
+}
+
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/MavenSearchResultPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/MavenSearchResultPage.java
new file mode 100644
index 00000000..d0c28aae
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/MavenSearchResultPage.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.search;
+
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.search.ui.text.AbstractTextSearchViewPage;
+import org.eclipse.ui.IMemento;
+
+/**
+ * Maven search result page
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenSearchResultPage extends AbstractTextSearchViewPage {
+
+ public MavenSearchResultPage() {
+ super(FLAG_LAYOUT_TREE | FLAG_LAYOUT_FLAT);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#configureTableViewer(org.eclipse.jface.viewers.TableViewer)
+ */
+ protected void configureTableViewer(TableViewer viewer) {
+ // TODO Auto-generated method configureTableViewer
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#configureTreeViewer(org.eclipse.jface.viewers.TreeViewer)
+ */
+ protected void configureTreeViewer(TreeViewer viewer) {
+ // TODO Auto-generated method configureTreeViewer
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#clear()
+ */
+ protected void clear() {
+ // TODO Auto-generated method clear
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#elementsChanged(java.lang.Object[])
+ */
+ protected void elementsChanged(Object[] objects) {
+ // TODO Auto-generated method elementsChanged
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#restoreState(org.eclipse.ui.IMemento)
+ */
+ public void restoreState(IMemento memento) {
+ super.restoreState(memento);
+
+ // TODO Auto-generated method restoreState
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.search.ui.text.AbstractTextSearchViewPage#saveState(org.eclipse.ui.IMemento)
+ */
+ public void saveState(IMemento memento) {
+ super.saveState(memento);
+ // TODO Auto-generated method saveState
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/ArtifactInfo.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/ArtifactInfo.java
new file mode 100644
index 00000000..ea5b18ee
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/ArtifactInfo.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.search.util;
+
+
+/**
+ * Information about the artifact.
+ *
+ * @author Lukas Krecan
+ */
+public class ArtifactInfo {
+ private final String groupId;
+ private final String artifactId;
+ private final String version;
+ private final String classfier;
+ private final String type;
+
+ public ArtifactInfo(String groupId, String artifactId, String version, String classfier, String type) {
+ this.groupId = groupId;
+ this.artifactId = artifactId;
+ this.version = version;
+ this.classfier = classfier;
+ this.type = type;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public String getArtifactId() {
+ return artifactId;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getClassfier() {
+ return classfier;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Constructs a <code>String</code> with all attributes
+ * in name = value format.
+ *
+ * @return a <code>String</code> representation
+ * of this object.
+ */
+ public String toString()
+ {
+ final String TAB = " "; //$NON-NLS-1$
+
+ String retValue = ""; //$NON-NLS-1$
+
+ retValue = "ArtifactInfo ( " //$NON-NLS-1$
+ + "groupId = " + this.groupId + TAB //$NON-NLS-1$
+ + "artifactId = " + this.artifactId + TAB //$NON-NLS-1$
+ + "version = " + this.version + TAB //$NON-NLS-1$
+ + "classfier = " + this.classfier + TAB //$NON-NLS-1$
+ + "type = " + this.type + TAB //$NON-NLS-1$
+ + " )"; //$NON-NLS-1$
+
+ return retValue;
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/CComboContentAdapter.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/CComboContentAdapter.java
new file mode 100644
index 00000000..aa465fc1
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/CComboContentAdapter.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.search.util;
+
+import org.eclipse.jface.fieldassist.ContentProposalAdapter;
+import org.eclipse.jface.fieldassist.IControlContentAdapter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CCombo;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Control;
+
+
+/**
+ * An {@link IControlContentAdapter} for SWT CCombo controls. This is a convenience class for easily creating a
+ * {@link ContentProposalAdapter} for combo fields.
+ */
+public class CComboContentAdapter implements IControlContentAdapter /*, IControlContentAdapter2 */ {
+
+ /*
+ * Set to <code>true</code> if we should compute the text
+ * vertical bounds rather than just use the field size.
+ * Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=164748
+ * The corresponding SWT bug is
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=44072
+ */
+ private static final boolean COMPUTE_TEXT_USING_CLIENTAREA = !"carbon".equals(SWT.getPlatform()); //$NON-NLS-1$
+
+ public String getControlContents(Control control) {
+ return ((CCombo) control).getText();
+ }
+
+ public void setControlContents(Control control, String text, int cursorPosition) {
+ ((CCombo) control).setText(text);
+ ((CCombo) control).setSelection(new Point(cursorPosition, cursorPosition));
+ }
+
+ public void insertControlContents(Control control, String text, int cursorPosition) {
+ CCombo combo = (CCombo) control;
+ String contents = combo.getText();
+ Point selection = combo.getSelection();
+ StringBuffer sb = new StringBuffer();
+ sb.append(contents.substring(0, selection.x));
+ sb.append(text);
+ if(selection.y < contents.length()) {
+ sb.append(contents.substring(selection.y, contents.length()));
+ }
+ combo.setText(sb.toString());
+ selection.x = selection.x + cursorPosition;
+ selection.y = selection.x;
+ combo.setSelection(selection);
+ }
+
+ public int getCursorPosition(Control control) {
+ return ((CCombo) control).getSelection().x;
+ }
+
+ public Rectangle getInsertionBounds(Control control) {
+ // This doesn't take horizontal scrolling into affect.
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=204599
+ CCombo combo = (CCombo) control;
+ int position = combo.getSelection().y;
+ String contents = combo.getText();
+ GC gc = new GC(combo);
+ gc.setFont(combo.getFont());
+ Point extent = gc.textExtent(contents.substring(0, Math.min(position, contents.length())));
+ gc.dispose();
+ if(COMPUTE_TEXT_USING_CLIENTAREA) {
+ return new Rectangle(combo.getClientArea().x + extent.x, combo.getClientArea().y, 1, combo.getClientArea().height);
+ }
+ return new Rectangle(extent.x, 0, 1, combo.getSize().y);
+ }
+
+ public void setCursorPosition(Control control, int index) {
+ ((CCombo) control).setSelection(new Point(index, index));
+ }
+
+ public Point getSelection(Control control) {
+ return ((CCombo) control).getSelection();
+ }
+
+ public void setSelection(Control control, Point range) {
+ ((CCombo) control).setSelection(range);
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/ControlDecoration.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/ControlDecoration.java
new file mode 100644
index 00000000..8c90a57d
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/ControlDecoration.java
@@ -0,0 +1,1088 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+
+package org.eclipse.m2e.core.ui.internal.search.util;
+
+import org.eclipse.core.runtime.ListenerList;
+import org.eclipse.jface.fieldassist.FieldDecoration;
+import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.MouseTrackListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.graphics.Region;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Widget;
+
+
+/**
+ * ControlDecoration renders an image decoration near a control. It allows clients to specify an image and a position
+ * for the image relative to the control. A ControlDecoration may be assigned description text, which can optionally be
+ * shown when the user hovers over the image. Clients can decorate any kind of control.
+ * <p>
+ * Decoration images always appear on the left or right side of the field, never above or below it. Decorations can be
+ * positioned at the top, center, or bottom of either side of the control. Future implementations may provide additional
+ * positioning options for decorations.
+ * <p>
+ * ControlDecoration renders the image adjacent to the specified (already created) control, with no guarantee that it
+ * won't be clipped or otherwise obscured or overlapped by adjacent controls, including another ControlDecoration placed
+ * in the same location. Clients should ensure that there is adequate space adjacent to the control to show the
+ * decoration properly.
+ * <p>
+ * Clients using ControlDecoration should typically ensure that enough margin space is reserved for a decoration by
+ * altering the layout data margins, although this is not assumed or required by the ControlDecoration implementation.
+ * <p>
+ * This class is intended to be instantiated and used by clients. It is not intended to be subclassed by clients.
+ *
+ * @since 3.3
+ * @see FieldDecoration
+ * @see FieldDecorationRegistry
+ */
+public class ControlDecoration {
+ /**
+ * Debug flag for tracing
+ */
+ private static boolean DEBUG = false;
+
+ /**
+ * Cached platform flags for dealing with platform-specific issues.
+ */
+ static boolean CARBON = "carbon".equals(SWT.getPlatform()); //$NON-NLS-1$
+
+ /**
+ * The associated control
+ */
+ Control control;
+
+ /**
+ * The composite on which to render the decoration and hook mouse events, or null if we are hooking all parent
+ * composites.
+ */
+ private Composite composite;
+
+ /**
+ * The associated image.
+ */
+ private Image image;
+
+ /**
+ * The associated description text.
+ */
+ private String descriptionText;
+
+ /**
+ * The position of the decoration.
+ */
+ private int position;
+
+ /**
+ * The decoration's visibility flag
+ */
+ boolean visible = true;
+
+ /**
+ * Boolean indicating whether the decoration should only be shown when the control has focus
+ */
+ boolean showOnlyOnFocus = false;
+
+ /**
+ * Boolean indicating whether the decoration should show its description text in a hover when the user hovers over the
+ * decoration.
+ */
+ boolean showHover = true;
+
+ /**
+ * Margin width used between the decorator and the control.
+ */
+ private int marginWidth = 0;
+
+ /**
+ * Registered selection listeners.
+ */
+ ListenerList selectionListeners = new ListenerList();
+
+ /**
+ * Registered menu detect listeners.
+ */
+ ListenerList menuDetectListeners = new ListenerList();
+
+ /**
+ * The focus listener
+ */
+ private FocusListener focusListener;
+
+ /**
+ * The dispose listener
+ */
+ private DisposeListener disposeListener;
+
+ /**
+ * The paint listener installed for drawing the decoration
+ */
+ private PaintListener paintListener;
+
+ /**
+ * The mouse listener installed for tracking the hover
+ */
+ private MouseTrackListener mouseTrackListener;
+
+ /**
+ * The mouse move listener installed for tracking the hover
+ */
+ MouseMoveListener mouseMoveListener;
+
+ /**
+ * The untyped listener installed for notifying external listeners
+ */
+ private Listener compositeListener;
+
+ /**
+ * Control that we last installed a move listener on. We only want one at a time.
+ */
+ Control moveListeningTarget = null;
+
+ /**
+ * Debug counter used to match add and remove listeners
+ */
+ private int listenerInstalls = 0;
+
+ /**
+ * The current rectangle used for tracking mouse moves
+ */
+ Rectangle decorationRectangle;
+
+ /**
+ * An internal flag tracking whether we have focus. We use this rather than isFocusControl() so that we can set the
+ * flag as soon as we get the focus callback, rather than having to do an asyncExec in the middle of a focus callback
+ * to ensure that isFocusControl() represents the outcome of the event.
+ */
+ boolean hasFocus = false;
+
+ /**
+ * The hover used for showing description text
+ */
+ private Hover hover;
+
+ /**
+ * The hover used to show a decoration image's description.
+ */
+ class Hover {
+ private static final String EMPTY = ""; //$NON-NLS-1$
+
+ /**
+ * Offset of info hover arrow from the left or right side.
+ */
+ private int hao = 10;
+
+ /**
+ * Width of info hover arrow.
+ */
+ private int haw = 8;
+
+ /**
+ * Height of info hover arrow.
+ */
+ private int hah = 10;
+
+ /**
+ * Margin around info hover text.
+ */
+ int hm = 2;
+
+ /**
+ * This info hover's shell.
+ */
+ Shell hoverShell;
+
+ /**
+ * The info hover text.
+ */
+ String text = EMPTY;
+
+ /**
+ * The region used to manage the shell shape
+ */
+ Region region;
+
+ /**
+ * Boolean indicating whether the last computed polygon location had an arrow on left. (true if left, false if
+ * right).
+ */
+ boolean arrowOnLeft = true;
+
+ /*
+ * Create a hover parented by the specified shell.
+ */
+ Hover(Shell parent) {
+ final Display display = parent.getDisplay();
+ hoverShell = new Shell(parent, SWT.NO_TRIM | SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL);
+ hoverShell.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ hoverShell.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+ hoverShell.addPaintListener(new PaintListener() {
+ public void paintControl(PaintEvent pe) {
+ pe.gc.drawText(text, hm, hm);
+ if(!CARBON) {
+ pe.gc.drawPolygon(getPolygon(true));
+ }
+ }
+ });
+ hoverShell.addMouseListener(new MouseAdapter() {
+ public void mouseDown(MouseEvent e) {
+ hideHover();
+ }
+ });
+ }
+
+ /*
+ * Compute a polygon that represents a hover with an arrow pointer. If
+ * border is true, compute the polygon inset by 1-pixel border. Consult
+ * the arrowOnLeft flag to determine which side the arrow is on.
+ */
+ int[] getPolygon(boolean border) {
+ Point e = getExtent();
+ int b = border ? 1 : 0;
+ if(arrowOnLeft) {
+ return new int[] {0, 0, e.x - b, 0, e.x - b, e.y - b, hao + haw, e.y - b, hao + haw / 2, e.y + hah - b, hao,
+ e.y - b, 0, e.y - b, 0, 0};
+ }
+ return new int[] {0, 0, e.x - b, 0, e.x - b, e.y - b, e.x - hao - b, e.y - b, e.x - hao - haw / 2, e.y + hah - b,
+ e.x - hao - haw, e.y - b, 0, e.y - b, 0, 0};
+ }
+
+ /*
+ * Dispose the hover, it is no longer needed. Dispose any resources
+ * allocated by the hover.
+ */
+ void dispose() {
+ if(!hoverShell.isDisposed()) {
+ hoverShell.dispose();
+ }
+ if(region != null) {
+ region.dispose();
+ }
+ }
+
+ /*
+ * Set the visibility of the hover.
+ */
+ void setVisible(boolean visible) {
+ if(visible) {
+ if(!hoverShell.isVisible()) {
+ hoverShell.setVisible(true);
+ }
+ } else {
+ if(hoverShell.isVisible()) {
+ hoverShell.setVisible(false);
+ }
+ }
+ }
+
+ /*
+ * Set the text of the hover to the specified text. Recompute the size
+ * and location of the hover to hover near the decoration rectangle,
+ * pointing the arrow toward the target control.
+ */
+ void setText(String t, Rectangle decorationRectangle, Control targetControl) {
+ if(t == null) {
+ t = EMPTY;
+ }
+ if(!t.equals(text)) {
+ Point oldSize = getExtent();
+ text = t;
+ hoverShell.redraw();
+ Point newSize = getExtent();
+ if(!oldSize.equals(newSize)) {
+ // set a flag that indicates the direction of arrow
+ arrowOnLeft = decorationRectangle.x <= targetControl.getLocation().x;
+ setNewShape();
+ }
+ }
+
+ Point extent = getExtent();
+ int y = -extent.y - hah + 1;
+ int x = arrowOnLeft ? -hao + haw / 2 : -extent.x + hao + haw / 2;
+
+ hoverShell.setLocation(control.getParent().toDisplay(decorationRectangle.x + x, decorationRectangle.y + y));
+ }
+
+ /*
+ * Return whether or not the hover (shell) is visible.
+ */
+ boolean isVisible() {
+ return hoverShell.isVisible();
+ }
+
+ /*
+ * Compute the extent of the hover for the current text.
+ */
+ Point getExtent() {
+ GC gc = new GC(hoverShell);
+ Point e = gc.textExtent(text);
+ gc.dispose();
+ e.x += hm * 2;
+ e.y += hm * 2;
+ return e;
+ }
+
+ /*
+ * Compute a new shape for the hover shell.
+ */
+ void setNewShape() {
+ Region oldRegion = region;
+ region = new Region();
+ region.add(getPolygon(false));
+ hoverShell.setRegion(region);
+ if(oldRegion != null) {
+ oldRegion.dispose();
+ }
+
+ }
+ }
+
+ /**
+ * Construct a ControlDecoration for decorating the specified control at the specified position relative to the
+ * control. Render the decoration on top of any Control that happens to appear at the specified location.
+ * <p>
+ * SWT constants are used to specify the position of the decoration relative to the control. The position should
+ * include style bits describing both the vertical and horizontal orientation. <code>SWT.LEFT</code> and
+ * <code>SWT.RIGHT</code> describe the horizontal placement of the decoration relative to the control, and the
+ * constants <code>SWT.TOP</code>, <code>SWT.CENTER</code>, and <code>SWT.BOTTOM</code> describe the vertical
+ * alignment of the decoration relative to the control. Decorations always appear on either the left or right side of
+ * the control, never above or below it. For example, a decoration appearing on the left side of the field, at the
+ * top, is specified as SWT.LEFT | SWT.TOP. If no position style bits are specified, the control decoration will be
+ * positioned to the left and center of the control (<code>SWT.LEFT | SWT.CENTER</code>).
+ * </p>
+ *
+ * @param control the control to be decorated
+ * @param position bit-wise or of position constants (<code>SWT.TOP</code>, <code>SWT.BOTTOM</code>,
+ * <code>SWT.LEFT</code>, <code>SWT.RIGHT</code>, and <code>SWT.CENTER</code>).
+ */
+ public ControlDecoration(Control control, int position) {
+ this(control, position, null);
+
+ }
+
+ /**
+ * Construct a ControlDecoration for decorating the specified control at the specified position relative to the
+ * control. Render the decoration only on the specified Composite or its children. The decoration will be clipped if
+ * it does not appear within the visible bounds of the composite or its child composites.
+ * <p>
+ * SWT constants are used to specify the position of the decoration relative to the control. The position should
+ * include style bits describing both the vertical and horizontal orientation. <code>SWT.LEFT</code> and
+ * <code>SWT.RIGHT</code> describe the horizontal placement of the decoration relative to the control, and the
+ * constants <code>SWT.TOP</code>, <code>SWT.CENTER</code>, and <code>SWT.BOTTOM</code> describe the vertical
+ * alignment of the decoration relative to the control. Decorations always appear on either the left or right side of
+ * the control, never above or below it. For example, a decoration appearing on the left side of the field, at the
+ * top, is specified as SWT.LEFT | SWT.TOP. If no position style bits are specified, the control decoration will be
+ * positioned to the left and center of the control (<code>SWT.LEFT | SWT.CENTER</code>).
+ * </p>
+ *
+ * @param control the control to be decorated
+ * @param position bit-wise or of position constants (<code>SWT.TOP</code>, <code>SWT.BOTTOM</code>,
+ * <code>SWT.LEFT</code>, <code>SWT.RIGHT</code>, and <code>SWT.CENTER</code>).
+ * @param composite The SWT composite within which the decoration should be rendered. The decoration will be clipped
+ * to this composite, but it may be rendered on a child of the composite. The decoration will not be visible
+ * if the specified composite or its child composites are not visible in the space relative to the control,
+ * where the decoration is to be rendered. If this value is <code>null</code>, then the decoration will be
+ * rendered on whichever composite (or composites) are located in the specified position.
+ */
+ public ControlDecoration(Control control, int position, Composite composite) {
+ this.position = position;
+ this.control = control;
+ this.composite = composite;
+
+ addControlListeners();
+
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notified when the platform-specific context menu
+ * trigger has occurred, by sending it one of the messages defined in the <code>MenuDetectListener</code> interface.
+ * <p>
+ * The <code>widget</code> field in the SelectionEvent will contain the Composite on which the decoration is rendered
+ * that received the click. The <code>x</code> and <code>y</code> fields will be in coordinates relative to the
+ * display. The <code>data</code> field will contain the decoration that received the event.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ * @see org.eclipse.swt.events.MenuDetectListener
+ * @see org.eclipse.swt.events.MenuDetectEvent
+ * @see #removeMenuDetectListener
+ */
+ public void addMenuDetectListener(MenuDetectListener listener) {
+ menuDetectListeners.add(listener);
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will be notified when the platform-specific context menu
+ * trigger has occurred.
+ *
+ * @param listener the listener which should no longer be notified. This message has no effect if the listener was not
+ * previously added to the receiver.
+ * @see org.eclipse.swt.events.MenuDetectListener
+ * @see #addMenuDetectListener
+ */
+ public void removeMenuDetectListener(MenuDetectListener listener) {
+ menuDetectListeners.remove(listener);
+ }
+
+ /**
+ * Adds the listener to the collection of listeners who will be notified when the decoration is selected, by sending
+ * it one of the messages defined in the <code>SelectionListener</code> interface.
+ * <p>
+ * <code>widgetSelected</code> is called when the decoration is selected (by mouse click).
+ * <code>widgetDefaultSelected</code> is called when the decoration is double-clicked.
+ * </p>
+ * <p>
+ * The <code>widget</code> field in the SelectionEvent will contain the Composite on which the decoration is rendered
+ * that received the click. The <code>x</code> and <code>y</code> fields will be in coordinates relative to that
+ * widget. The <code>data</code> field will contain the decoration that received the event.
+ * </p>
+ *
+ * @param listener the listener which should be notified
+ * @see org.eclipse.swt.events.SelectionListener
+ * @see org.eclipse.swt.events.SelectionEvent
+ * @see #removeSelectionListener
+ */
+ public void addSelectionListener(SelectionListener listener) {
+ selectionListeners.add(listener);
+ }
+
+ /**
+ * Removes the listener from the collection of listeners who will be notified when the decoration is selected.
+ *
+ * @param listener the listener which should no longer be notified. This message has no effect if the listener was not
+ * previously added to the receiver.
+ * @see org.eclipse.swt.events.SelectionListener
+ * @see #addSelectionListener
+ */
+ public void removeSelectionListener(SelectionListener listener) {
+ selectionListeners.remove(listener);
+ }
+
+ /**
+ * Dispose this ControlDecoration. Unhook any listeners that have been installed on the target control. This method
+ * has no effect if the receiver is already disposed.
+ */
+ public void dispose() {
+ if(control == null) {
+ return;
+ }
+ if(hover != null) {
+ hover.dispose();
+ hover = null;
+ }
+ removeControlListeners();
+ control = null;
+ }
+
+ /**
+ * Get the control that is decorated by the receiver.
+ *
+ * @return the Control decorated by the receiver. May be <code>null</code> if the control has been uninstalled.
+ */
+ public Control getControl() {
+ return control;
+ }
+
+ /**
+ * Add any listeners needed on the target control and on the composite where the decoration is to be rendered.
+ */
+ private void addControlListeners() {
+ disposeListener = new DisposeListener() {
+ public void widgetDisposed(DisposeEvent event) {
+ dispose();
+ }
+ };
+ printAddListener(control, "DISPOSE"); //$NON-NLS-1$
+ control.addDisposeListener(disposeListener);
+
+ focusListener = new FocusListener() {
+ public void focusGained(FocusEvent event) {
+ hasFocus = true;
+ if(showOnlyOnFocus) {
+ update();
+ }
+ }
+
+ public void focusLost(FocusEvent event) {
+ hasFocus = false;
+ if(showOnlyOnFocus) {
+ update();
+ }
+ }
+ };
+ printAddListener(control, "FOCUS"); //$NON-NLS-1$
+ control.addFocusListener(focusListener);
+
+ // Listener for painting the decoration
+ paintListener = new PaintListener() {
+ public void paintControl(PaintEvent event) {
+ Control control = (Control) event.widget;
+ Rectangle rect = getDecorationRectangle(control);
+ if(shouldShowDecoration()) {
+ event.gc.drawImage(getImage(), rect.x, rect.y);
+ }
+ }
+ };
+
+ // Listener for tracking the end of a hover. Only installed
+ // after a hover begins.
+ mouseMoveListener = new MouseMoveListener() {
+ public void mouseMove(MouseEvent event) {
+ if(showHover) {
+ if(!decorationRectangle.contains(event.x, event.y)) {
+ hideHover();
+ // No need to listen any longer
+ printRemoveListener(event.widget, "MOUSEMOVE"); //$NON-NLS-1$
+ ((Control) event.widget).removeMouseMoveListener(mouseMoveListener);
+ moveListeningTarget = null;
+ }
+ }
+ }
+ };
+
+ // Listener for tracking the beginning of a hover. Always installed.
+ mouseTrackListener = new MouseTrackListener() {
+ public void mouseExit(MouseEvent event) {
+ // Just in case we didn't catch it before.
+ Control target = (Control) event.widget;
+ if(target == moveListeningTarget) {
+ printRemoveListener(target, "MOUSEMOVE"); //$NON-NLS-1$
+ target.removeMouseMoveListener(mouseMoveListener);
+ moveListeningTarget = null;
+ }
+ hideHover();
+ }
+
+ public void mouseHover(MouseEvent event) {
+ if(showHover) {
+ decorationRectangle = getDecorationRectangle((Control) event.widget);
+ if(decorationRectangle.contains(event.x, event.y)) {
+ showHoverText(getDescriptionText());
+ Control target = (Control) event.widget;
+ if(moveListeningTarget == null) {
+ printAddListener(target, "MOUSEMOVE"); //$NON-NLS-1$
+ target.addMouseMoveListener(mouseMoveListener);
+ moveListeningTarget = target;
+ } else if(target != moveListeningTarget) {
+ printRemoveListener(moveListeningTarget, "MOUSEMOVE"); //$NON-NLS-1$
+ moveListeningTarget.removeMouseMoveListener(mouseMoveListener);
+ printAddListener(target, "MOUSEMOVE"); //$NON-NLS-1$
+ target.addMouseMoveListener(mouseMoveListener);
+ moveListeningTarget = target;
+ } else {
+ // It is already installed on this control.
+ }
+ }
+ }
+ }
+
+ public void mouseEnter(MouseEvent event) {
+ // Nothing to do until a hover occurs.
+ }
+ };
+
+ compositeListener = new Listener() {
+ public void handleEvent(Event event) {
+ // Don't forward events if decoration is not showing
+ if(!visible) {
+ return;
+ }
+ // Notify listeners if any are registered.
+ switch(event.type) {
+ case SWT.MouseDown:
+ if(!selectionListeners.isEmpty())
+ notifySelectionListeners(event);
+ break;
+ case SWT.MouseDoubleClick:
+ if(!selectionListeners.isEmpty())
+ notifySelectionListeners(event);
+ break;
+ case SWT.MenuDetect:
+ if(!menuDetectListeners.isEmpty())
+ notifyMenuDetectListeners(event);
+ break;
+ }
+ }
+ };
+
+ // We do not know which parent in the control hierarchy
+ // is providing the decoration space, so hook all the way up, until
+ // the shell or the specified parent composite is reached.
+ Composite c = control.getParent();
+ while(c != null) {
+ installCompositeListeners(c);
+ if(composite != null && composite == c) {
+ // We just installed on the specified composite, so stop.
+ c = null;
+ } else if(c instanceof Shell) {
+ // We just installed on a shell, so don't go further
+ c = null;
+ } else {
+ c = c.getParent();
+ }
+ }
+ // force a redraw of the decoration area so our paint listener
+ // is notified.
+ update();
+ }
+
+ /*
+ * Install the listeners used to paint and track mouse events on the
+ * composite.
+ */
+ private void installCompositeListeners(Composite c) {
+ if(!c.isDisposed()) {
+ printAddListener(c, "PAINT"); //$NON-NLS-1$
+ c.addPaintListener(paintListener);
+ printAddListener(c, "MOUSETRACK"); //$NON-NLS-1$
+ c.addMouseTrackListener(mouseTrackListener);
+ printAddListener(c, "SWT.MenuDetect"); //$NON-NLS-1$
+ c.addListener(SWT.MenuDetect, compositeListener);
+ printAddListener(c, "SWT.MouseDown"); //$NON-NLS-1$
+ c.addListener(SWT.MouseDown, compositeListener);
+ printAddListener(c, "SWT.MouseDoubleClick"); //$NON-NLS-1$
+ c.addListener(SWT.MouseDoubleClick, compositeListener);
+ }
+ }
+
+ /*
+ * Remove the listeners used to paint and track mouse events on the
+ * composite.
+ */
+ private void removeCompositeListeners(Composite c) {
+ if(!c.isDisposed()) {
+ printRemoveListener(c, "PAINT"); //$NON-NLS-1$
+ c.removePaintListener(paintListener);
+ printRemoveListener(c, "MOUSETRACK"); //$NON-NLS-1$
+ c.removeMouseTrackListener(mouseTrackListener);
+ printRemoveListener(c, "SWT.MenuDetect"); //$NON-NLS-1$
+ c.removeListener(SWT.MenuDetect, compositeListener);
+ printRemoveListener(c, "SWT.MouseDown"); //$NON-NLS-1$
+ c.removeListener(SWT.MouseDown, compositeListener);
+ printRemoveListener(c, "SWT.MouseDoubleClick"); //$NON-NLS-1$
+ c.removeListener(SWT.MouseDoubleClick, compositeListener);
+ }
+ }
+
+ void notifySelectionListeners(Event event) {
+ if(!(event.widget instanceof Control)) {
+ return;
+ }
+ if(getDecorationRectangle((Control) event.widget).contains(event.x, event.y)) {
+ SelectionEvent clientEvent = new SelectionEvent(event);
+ clientEvent.data = this;
+ if(getImage() != null) {
+ clientEvent.height = getImage().getBounds().height;
+ clientEvent.width = getImage().getBounds().width;
+ }
+ Object[] listeners;
+ switch(event.type) {
+ case SWT.MouseDoubleClick:
+ if(event.button == 1) {
+ listeners = selectionListeners.getListeners();
+ for(int i = 0; i < listeners.length; i++ ) {
+ ((SelectionListener) listeners[i]).widgetDefaultSelected(clientEvent);
+ }
+ }
+ break;
+ case SWT.MouseDown:
+ if(event.button == 1) {
+ listeners = selectionListeners.getListeners();
+ for(int i = 0; i < listeners.length; i++ ) {
+ ((SelectionListener) listeners[i]).widgetSelected(clientEvent);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ void notifyMenuDetectListeners(Event event) {
+ if(getDecorationRectangle(null).contains(event.x, event.y)) {
+ MenuDetectEvent clientEvent = new MenuDetectEvent(event);
+ clientEvent.data = this;
+ Object[] listeners = menuDetectListeners.getListeners();
+ for(int i = 0; i < listeners.length; i++ ) {
+ ((MenuDetectListener) listeners[i]).menuDetected(clientEvent);
+
+ }
+ }
+ }
+
+ /**
+ * Show the specified text using the same hover dialog as is used to show decorator descriptions. When
+ * {@link #setShowHover(boolean)} has been set to <code>true</code>, a decoration's description text will be shown in
+ * an info hover over the field's control whenever the mouse hovers over the decoration. This method can be used to
+ * show a decoration's description text at other times (such as when the control receives focus), or to show other
+ * text associated with the field. The hover will not be shown if the decoration is hidden.
+ *
+ * @param text the text to be shown in the info hover, or <code>null</code> if no text should be shown.
+ */
+ public void showHoverText(String text) {
+ if(control == null) {
+ return;
+ }
+ showHoverText(text, control);
+ }
+
+ /**
+ * Hide any hover popups that are currently showing on the control. When {@link #setShowHover(boolean)} has been set
+ * to <code>true</code>, a decoration's description text will be shown in an info hover over the field's control as
+ * long as the mouse hovers over the decoration, and will be hidden when the mouse exits the decoration. This method
+ * can be used to hide a hover, whether it was shown explicitly using {@link #showHoverText(String)}, or was showing
+ * because the user was hovering in the decoration.
+ * <p>
+ * This message has no effect if there is no current hover.
+ */
+ public void hideHover() {
+ if(hover != null) {
+ hover.setVisible(false);
+ }
+ }
+
+ /**
+ * Show the control decoration. This message has no effect if the decoration is already showing. If
+ * {@link #setShowOnlyOnFocus(boolean)} is set to <code>true</code>, the decoration will only be shown if the control
+ * has focus.
+ */
+ public void show() {
+ if(!visible) {
+ visible = true;
+ update();
+ }
+ }
+
+ /**
+ * Hide the control decoration and any associated hovers. This message has no effect if the decoration is already
+ * hidden.
+ */
+ public void hide() {
+ if(visible) {
+ visible = false;
+ hideHover();
+ update();
+ }
+ }
+
+ /**
+ * Get the description text that may be shown in a hover for this decoration.
+ *
+ * @return the text to be shown as a description for the decoration, or <code>null</code> if none has been set.
+ */
+ public String getDescriptionText() {
+ return descriptionText;
+ }
+
+ /**
+ * Set the image shown in this control decoration. Update the rendered decoration.
+ *
+ * @param text the text to be shown as a description for the decoration, or <code>null</code> if none has been set.
+ */
+ public void setDescriptionText(String text) {
+ this.descriptionText = text;
+ update();
+ }
+
+ /**
+ * Get the image shown in this control decoration.
+ *
+ * @return the image to be shown adjacent to the control, or <code>null</code> if one has not been set.
+ */
+ public Image getImage() {
+ return image;
+ }
+
+ /**
+ * Set the image shown in this control decoration. Update the rendered decoration.
+ *
+ * @param image the image to be shown adjacent to the control. Should never be <code>null</code>.
+ */
+ public void setImage(Image image) {
+ this.image = image;
+ update();
+ }
+
+ /**
+ * Get the boolean that controls whether the decoration is shown only when the control has focus. The default value of
+ * this setting is <code>false</code>.
+ *
+ * @return <code>true</code> if the decoration should only be shown when the control has focus, and <code>false</code>
+ * if it should always be shown. Note that if the control is not capable of receiving focus (
+ * <code>SWT.NO_FOCUS</code>), then the decoration will never show when this value is <code>true</code>.
+ */
+ public boolean getShowOnlyOnFocus() {
+ return showOnlyOnFocus;
+ }
+
+ /**
+ * Set the boolean that controls whether the decoration is shown only when the control has focus. The default value of
+ * this setting is <code>false</code>.
+ *
+ * @param showOnlyOnFocus <code>true</code> if the decoration should only be shown when the control has focus, and
+ * <code>false</code> if it should always be shown. Note that if the control is not capable of receiving
+ * focus (<code>SWT.NO_FOCUS</code>), then the decoration will never show when this value is
+ * <code>true</code>.
+ */
+ public void setShowOnlyOnFocus(boolean showOnlyOnFocus) {
+ this.showOnlyOnFocus = showOnlyOnFocus;
+ update();
+ }
+
+ /**
+ * Get the boolean that controls whether the decoration's description text should be shown in a hover when the user
+ * hovers over the decoration. The default value of this setting is <code>true</code>.
+ *
+ * @return <code>true</code> if a hover popup containing the decoration's description text should be shown when the
+ * user hovers over the decoration, and <code>false</code> if a hover should not be shown.
+ */
+ public boolean getShowHover() {
+ return showHover;
+ }
+
+ /**
+ * Set the boolean that controls whether the decoration's description text should be shown in a hover when the user
+ * hovers over the decoration. The default value of this setting is <code>true</code>.
+ *
+ * @param showHover <code>true</code> if a hover popup containing the decoration's description text should be shown
+ * when the user hovers over the decoration, and <code>false</code> if a hover should not be shown.
+ */
+ public void setShowHover(boolean showHover) {
+ this.showHover = showHover;
+ update();
+ }
+
+ /**
+ * Get the margin width in pixels that should be used between the decorator and the horizontal edge of the control.
+ * The default value of this setting is <code>0</code>.
+ *
+ * @return the number of pixels that should be reserved between the horizontal edge of the control and the adjacent
+ * edge of the decoration.
+ */
+ public int getMarginWidth() {
+ return marginWidth;
+ }
+
+ /**
+ * Set the margin width in pixels that should be used between the decorator and the horizontal edge of the control.
+ * The default value of this setting is <code>0</code>.
+ *
+ * @param marginWidth the number of pixels that should be reserved between the horizontal edge of the control and the
+ * adjacent edge of the decoration.
+ */
+ public void setMarginWidth(int marginWidth) {
+ this.marginWidth = marginWidth;
+ update();
+ }
+
+ /**
+ * Something has changed, requiring redraw. Redraw the decoration and update the hover text if appropriate.
+ */
+ protected void update() {
+ if(control == null || control.isDisposed()) {
+ return;
+ }
+ Rectangle rect = getDecorationRectangle(control.getShell());
+ // Redraw this rectangle in all children
+ control.getShell().redraw(rect.x, rect.y, rect.width, rect.height, true);
+ control.getShell().update();
+ if(hover != null && getDescriptionText() != null) {
+ hover.setText(getDescriptionText(), getDecorationRectangle(control.getParent()), control);
+ }
+ }
+
+ /*
+ * Show the specified text in the hover, positioning the hover near the
+ * specified control.
+ */
+ private void showHoverText(String text, Control hoverNear) {
+ // If we aren't to show a hover, don't do anything.
+ if(!showHover) {
+ return;
+ }
+
+ // If we are not visible, don't show the hover.
+ if(!visible) {
+ return;
+ }
+ // If there is no text, don't do anything.
+ if(text == null) {
+ hideHover();
+ return;
+ }
+
+ // If there is no control, nothing to do
+ if(control == null) {
+ return;
+ }
+ // Create the hover if it's not showing
+ if(hover == null) {
+ hover = new Hover(hoverNear.getShell());
+ }
+ hover.setText(text, getDecorationRectangle(control.getParent()), control);
+ hover.setVisible(true);
+ }
+
+ /*
+ * Remove any listeners installed on the controls.
+ */
+ private void removeControlListeners() {
+ if(control == null) {
+ return;
+ }
+ printRemoveListener(control, "FOCUS"); //$NON-NLS-1$
+ control.removeFocusListener(focusListener);
+ focusListener = null;
+
+ printRemoveListener(control, "DISPOSE"); //$NON-NLS-1$
+ control.removeDisposeListener(disposeListener);
+ disposeListener = null;
+
+ Composite c = control.getParent();
+ while(c != null) {
+ removeCompositeListeners(c);
+ if(composite != null && composite == c) {
+ // We previously installed listeners only to the specified
+ // composite, so stop.
+ c = null;
+ } else if(c instanceof Shell) {
+ // We previously installed listeners only up to the first Shell
+ // encountered, so stop.
+ c = null;
+ } else {
+ c = c.getParent();
+ }
+ }
+ paintListener = null;
+ mouseTrackListener = null;
+ compositeListener = null;
+
+ // We may have a remaining mouse move listener installed
+ if(moveListeningTarget != null) {
+ printRemoveListener(moveListeningTarget, "MOUSEMOVE"); //$NON-NLS-1$
+ moveListeningTarget.removeMouseMoveListener(mouseMoveListener);
+ moveListeningTarget = null;
+ mouseMoveListener = null;
+ }
+ if(DEBUG) {
+ if(listenerInstalls > 0) {
+ System.out.println("LISTENER LEAK>>>CHECK TRACE ABOVE"); //$NON-NLS-1$
+ } else if(listenerInstalls < 0) {
+ System.out.println("REMOVED UNREGISTERED LISTENERS>>>CHECK TRACE ABOVE"); //$NON-NLS-1$
+ } else {
+ System.out.println("ALL INSTALLED LISTENERS WERE REMOVED."); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /**
+ * Return the rectangle in which the decoration should be rendered, in coordinates relative to the specified control.
+ * If the specified control is null, return the rectangle in display coordinates.
+ *
+ * @param targetControl the control whose coordinates should be used
+ * @return the rectangle in which the decoration should be rendered
+ */
+ protected Rectangle getDecorationRectangle(Control targetControl) {
+ if(getImage() == null || control == null) {
+ return new Rectangle(0, 0, 0, 0);
+ }
+ // Compute the bounds first relative to the control's parent.
+ Rectangle imageBounds = getImage().getBounds();
+ Rectangle controlBounds = control.getBounds();
+ int x, y;
+ // Compute x
+ if((position & SWT.RIGHT) == SWT.RIGHT) {
+ x = controlBounds.x + controlBounds.width + marginWidth;
+ } else {
+ // default is left
+ x = controlBounds.x - imageBounds.width - marginWidth;
+ }
+ // Compute y
+ if((position & SWT.TOP) == SWT.TOP) {
+ y = controlBounds.y;
+ } else if((position & SWT.BOTTOM) == SWT.BOTTOM) {
+ y = controlBounds.y + control.getBounds().height - imageBounds.height;
+ } else {
+ // default is center
+ y = controlBounds.y + (control.getBounds().height - imageBounds.height) / 2;
+ }
+
+ // Now convert to coordinates relative to the target control.
+ Point globalPoint = control.getParent().toDisplay(x, y);
+ Point targetPoint;
+ if(targetControl == null) {
+ targetPoint = globalPoint;
+ } else {
+ targetPoint = targetControl.toControl(globalPoint);
+ }
+ return new Rectangle(targetPoint.x, targetPoint.y, imageBounds.width, imageBounds.height);
+ }
+
+ /*
+ * Return true if the decoration should be shown, false if it should not.
+ */
+ boolean shouldShowDecoration() {
+ if(!visible) {
+ return false;
+ }
+ if(control == null || control.isDisposed() || getImage() == null) {
+ return false;
+ }
+
+ if(!control.isVisible()) {
+ return false;
+ }
+ if(showOnlyOnFocus) {
+ return hasFocus;
+ }
+ return true;
+ }
+
+ /*
+ * If in debug mode, print info about adding the specified listener.
+ */
+ void printAddListener(Widget widget, String listenerType) {
+ listenerInstalls++ ;
+ if(DEBUG) {
+ System.out.println("Added listener>>>" + listenerType + " to>>>" + widget); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ }
+
+ /*
+ * If in debug mode, print info about adding the specified listener.
+ */
+ void printRemoveListener(Widget widget, String listenerType) {
+ listenerInstalls-- ;
+ if(DEBUG) {
+ System.out.println("Removed listener>>>" + listenerType + " from>>>" + widget); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/IndexSearchEngine.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/IndexSearchEngine.java
new file mode 100644
index 00000000..6bab025d
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/IndexSearchEngine.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.search.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.apache.maven.artifact.versioning.ComparableVersion;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.m2e.core.index.IIndex;
+import org.eclipse.m2e.core.index.IndexManager;
+import org.eclipse.m2e.core.index.IndexedArtifact;
+import org.eclipse.m2e.core.index.IndexedArtifactFile;
+import org.eclipse.m2e.core.index.MatchTyped.MatchType;
+import org.eclipse.m2e.core.index.MatchTypedStringSearchExpression;
+import org.eclipse.m2e.core.index.SearchExpression;
+
+
+/**
+ * Search engine integrating {@link IndexManager} with POM XML editor.
+ *
+ * @author Lukas Krecan
+ * @author Eugene Kuleshov
+ */
+public class IndexSearchEngine implements SearchEngine {
+
+ private final IIndex index;
+
+ public IndexSearchEngine(IIndex index) {
+ this.index = index;
+ }
+
+ protected boolean isBlank(String str) {
+ return str == null || str.trim().length() == 0;
+ }
+
+ public Collection<String> findArtifactIds(String groupId, String searchExpression, Packaging packaging,
+ ArtifactInfo containingArtifact) {
+ // TODO add support for implicit groupIds in plugin dependencies "org.apache.maven.plugins", ...
+ // Someone, give me here access to settings.xml, to be able to pick up "real" predefined groupIds added by user
+ // Currently, I am just simulating the "factory defaults" of maven, but user changes to settings.xml
+ // will not be picked up this way!
+ ArrayList<SearchExpression> groupIdSearchExpressions = new ArrayList<SearchExpression>();
+ if(isBlank(groupId)) {
+ // values from effective settings
+ // we are wiring in the defaults only, but user changes are lost!
+ // org.apache.maven.plugins
+ // org.codehaus.mojo
+ groupIdSearchExpressions.add(new MatchTypedStringSearchExpression("org.apache.maven.plugins", MatchType.EXACT));
+ groupIdSearchExpressions.add(new MatchTypedStringSearchExpression("org.codehaus.mojo", MatchType.EXACT));
+ } else {
+ groupIdSearchExpressions.add(new MatchTypedStringSearchExpression(groupId, MatchType.EXACT));
+ }
+
+ try {
+ TreeSet<String> ids = new TreeSet<String>();
+ for(IndexedArtifact artifact : index.find(groupIdSearchExpressions, null, null, packaging.toSearchExpression() == null ? null :
+ Collections.singleton(packaging.toSearchExpression()))) {
+ ids.add(artifact.getArtifactId());
+ }
+ return subSet(ids, searchExpression);
+ } catch(CoreException ex) {
+ throw new SearchException(ex.getMessage(), ex.getStatus().getException());
+ }
+ }
+
+ public Collection<String> findClassifiers(String groupId, String artifactId, String version, String prefix,
+ Packaging packaging) {
+ try {
+ Collection<IndexedArtifact> values = index.find(new MatchTypedStringSearchExpression(groupId, MatchType.EXACT),
+ new MatchTypedStringSearchExpression(artifactId, MatchType.EXACT), null, packaging.toSearchExpression());
+ if(values.isEmpty()) {
+ return Collections.emptySet();
+ }
+
+ TreeSet<String> ids = new TreeSet<String>();
+ Set<IndexedArtifactFile> files = values.iterator().next().getFiles();
+ for(IndexedArtifactFile artifactFile : files) {
+ if(artifactFile.classifier != null) {
+ ids.add(artifactFile.classifier);
+ }
+ }
+ return subSet(ids, prefix);
+ } catch(CoreException ex) {
+ throw new SearchException(ex.getMessage(), ex.getStatus().getException());
+ }
+ }
+
+ public Collection<String> findGroupIds(String searchExpression, Packaging packaging, ArtifactInfo containingArtifact) {
+ try {
+ TreeSet<String> ids = new TreeSet<String>();
+
+ SearchExpression groupSearchExpression = isBlank(searchExpression) ? null : new MatchTypedStringSearchExpression(
+ searchExpression, MatchType.PARTIAL);
+
+ for(IndexedArtifact artifact : index.find(groupSearchExpression, null, null, packaging.toSearchExpression())) {
+ ids.add(artifact.getGroupId());
+ }
+ return subSet(ids, searchExpression);
+ } catch(CoreException ex) {
+ throw new SearchException(ex.getMessage(), ex.getStatus().getException());
+ }
+ }
+
+ public Collection<String> findTypes(String groupId, String artifactId, String version, String prefix,
+ Packaging packaging) {
+ try {
+ Collection<IndexedArtifact> values = index.find(new MatchTypedStringSearchExpression(groupId, MatchType.EXACT),
+ new MatchTypedStringSearchExpression(artifactId, MatchType.EXACT), null, packaging.toSearchExpression());
+ if(values.isEmpty()) {
+ return Collections.emptySet();
+ }
+
+ TreeSet<String> ids = new TreeSet<String>();
+ Set<IndexedArtifactFile> files = values.iterator().next().getFiles();
+ for(IndexedArtifactFile artifactFile : files) {
+ if(artifactFile.type != null) {
+ ids.add(artifactFile.type);
+ }
+ }
+ return subSet(ids, prefix);
+ } catch(CoreException ex) {
+ throw new SearchException(ex.getMessage(), ex.getStatus().getException());
+ }
+ }
+
+ public Collection<String> findVersions(String groupId, String artifactId, String searchExpression, Packaging packaging) {
+ try {
+ Collection<IndexedArtifact> values = index.find(new MatchTypedStringSearchExpression(groupId, MatchType.EXACT),
+ new MatchTypedStringSearchExpression(artifactId, MatchType.EXACT), null, packaging.toSearchExpression());
+ if(values.isEmpty()) {
+ return Collections.emptySet();
+ }
+
+ TreeSet<String> ids = new TreeSet<String>();
+ Set<IndexedArtifactFile> files = values.iterator().next().getFiles();
+ for(IndexedArtifactFile artifactFile : files) {
+ ids.add(artifactFile.version);
+ }
+ Collection<String> result = subSet(ids, searchExpression);
+
+ // sort results according to o.a.m.artifact.versioning.ComparableVersion
+ SortedSet<ComparableVersion> versions = new TreeSet<ComparableVersion>();
+ for(String version : result) {
+ versions.add(new ComparableVersion(version));
+ }
+ result = null; // not used any more
+ List<String> sorted = new ArrayList<String>(versions.size());
+ for(ComparableVersion version : versions) {
+ sorted.add(version.toString());
+ }
+ versions = null; // not used any more
+ Collections.reverse(sorted);
+ return sorted;
+ } catch(CoreException ex) {
+ throw new SearchException(ex.getMessage(), ex.getStatus().getException());
+ }
+ }
+
+ private Collection<String> subSet(TreeSet<String> ids, String searchExpression) {
+ if(searchExpression == null || searchExpression.length() == 0) {
+ return ids;
+ }
+ int n = searchExpression.length();
+ return ids.subSet(searchExpression, //
+ searchExpression.substring(0, n - 1) + ((char) (searchExpression.charAt(n - 1) + 1)));
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/MenuDetectEvent.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/MenuDetectEvent.java
new file mode 100644
index 00000000..15745da3
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/MenuDetectEvent.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.search.util;
+
+
+import org.eclipse.swt.events.TypedEvent;
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * Instances of this class are sent whenever the platform-
+ * specific trigger for showing a context menu is detected.
+ *
+ * @see MenuDetectListener
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
+ *
+ * @since 3.3
+ */
+
+public final class MenuDetectEvent extends TypedEvent {
+
+ /**
+ * the display-relative x coordinate of the pointer
+ * at the time the context menu trigger occurred
+ */
+ public int x;
+
+ /**
+ * the display-relative y coordinate of the pointer
+ * at the time the context menu trigger occurred
+ */
+ public int y;
+
+ /**
+ * A flag indicating whether the operation should be allowed.
+ * Setting this field to <code>false</code> will cancel the operation.
+ */
+ public boolean doit;
+
+ private static final long serialVersionUID = -3061660596590828941L;
+
+/**
+ * Constructs a new instance of this class based on the
+ * information in the given untyped event.
+ *
+ * @param e the untyped event containing the information
+ */
+public MenuDetectEvent(Event e) {
+ super(e);
+ this.x = e.x;
+ this.y = e.y;
+ this.doit = e.doit;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the event
+ */
+public String toString() {
+ String string = super.toString ();
+ return string.substring (0, string.length() - 1) // remove trailing '}'
+ + " x=" + x //$NON-NLS-1$
+ + " y=" + y //$NON-NLS-1$
+ + " doit=" + doit //$NON-NLS-1$
+ + "}"; //$NON-NLS-1$
+}
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/MenuDetectListener.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/MenuDetectListener.java
new file mode 100644
index 00000000..26cb1421
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/MenuDetectListener.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.search.util;
+
+
+import java.util.EventListener;
+
+/**
+ * Classes which implement this interface provide methods
+ * that deal with the events that are generated when the
+ * platform-specific trigger for showing a context menu is
+ * detected.
+ * <p>
+ * After creating an instance of a class that implements
+ * this interface it can be added to a control or TrayItem
+ * using the <code>addMenuDetectListener</code> method and
+ * removed using the <code>removeMenuDetectListener</code> method.
+ * When the context menu trigger occurs, the
+ * <code>menuDetected</code> method will be invoked.
+ * </p>
+ *
+ * @see MenuDetectEvent
+ *
+ * @since 3.3
+ */
+public interface MenuDetectListener extends EventListener {
+
+/**
+ * Sent when the platform-dependent trigger for showing a menu item is detected.
+ *
+ * @param e an event containing information about the menu detect
+ */
+public void menuDetected (MenuDetectEvent e);
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/Packaging.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/Packaging.java
new file mode 100644
index 00000000..cf98ea6b
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/Packaging.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.search.util;
+
+import org.eclipse.m2e.core.index.SearchExpression;
+import org.eclipse.m2e.core.index.SourcedSearchExpression;
+
+
+/**
+ * Packaging representation.
+ *
+ * @author Lukas Krecan
+ */
+public enum Packaging {
+ ALL(null), PLUGIN("maven-plugin"), // //$NON-NLS-1$
+ POM("pom"); //$NON-NLS-1$
+
+ private final String text;
+
+ private Packaging(String text) {
+ this.text = text;
+ }
+
+ /**
+ * Text representation of the packaging.
+ */
+ public String getText() {
+ return text;
+ }
+
+ public SearchExpression toSearchExpression() {
+ if(ALL.equals(this)) {
+ return null;
+ }
+
+ return new SourcedSearchExpression(getText());
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/SearchEngine.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/SearchEngine.java
new file mode 100644
index 00000000..c6f8634a
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/SearchEngine.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.search.util;
+
+import java.util.Collection;
+
+
+/**
+ * Interface to be implemented by a SearchEngine.
+ *
+ * @author Lukas Krecan
+ */
+public interface SearchEngine {
+
+ /**
+ * Finds groupIds for given expression.
+ * @param searchExpression
+ * @param packaging
+ * @param containingArtifact When looking for exclusion, contains information about artifact we are excluding from.
+ * @return
+ */
+ public Collection<String> findGroupIds(String searchExpression, Packaging packaging, ArtifactInfo containingArtifact);
+
+ /**
+ * Finds artifactIds for given expression
+ * @param groupId
+ * @param searchExpression
+ * @param packaging
+ * @param containingArtifact When looking for exclusion, contains information about artifact we are excluding from.
+ * @return
+ */
+ public Collection<String> findArtifactIds(String groupId, String searchExpression, Packaging packaging, ArtifactInfo containingArtifact);
+
+ public Collection<String> findVersions(String groupId, String artifactId, String searchExpression, Packaging packaging);
+
+ public Collection<String> findClassifiers(String groupId, String artifactId, String version, String prefix, Packaging packaging);
+
+ public Collection<String> findTypes(String groupId, String artifactId, String version, String prefix, Packaging packaging);
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/SearchException.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/SearchException.java
new file mode 100644
index 00000000..2cb0c06b
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/search/util/SearchException.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.search.util;
+
+/**
+ * @author Lukas Krecan
+ */
+public class SearchException extends RuntimeException {
+
+ private static final long serialVersionUID = 6909305234190388928L;
+
+ public SearchException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public SearchException(String message) {
+ super(message);
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/M2EErrorDialog.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/M2EErrorDialog.java
new file mode 100644
index 00000000..e4d2dd12
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/M2EErrorDialog.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.util;
+
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.m2e.core.internal.M2EUtils;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TableColumn;
+
+/**
+ * M2EErrorDialog
+ * Error dialog for displaying a list/table of error values.
+ *
+ * @author dyocum
+ */
+public class M2EErrorDialog extends MessageDialog {
+
+
+ private TableViewer errorTable;
+ private static final int PROJECT_COL = 0;
+ protected static final int TABLE_WIDTH = 700;
+ protected String[] COL_NAMES = {Messages.M2EErrorDialog_column_name, Messages.M2EErrorDialog_column_error};
+ protected int[] COL_STYLES = {SWT.LEFT, SWT.LEFT};
+ protected Map<String, Throwable> errorMap;
+
+ /**
+ * @param parentShell
+ * @param dialogTitle
+ * @param dialogTitleImage
+ * @param dialogMessage
+ * @param dialogImageType
+ * @param dialogButtonLabels
+ * @param defaultIndex
+ */
+ public M2EErrorDialog(Shell parentShell, String dialogTitle, Image dialogTitleImage, String dialogMessage,
+ int dialogImageType, String[] dialogButtonLabels, int defaultIndex, Map<String, Throwable> errorMap) {
+ super(parentShell, dialogTitle, dialogTitleImage, dialogMessage, dialogImageType, dialogButtonLabels, defaultIndex);
+ this.errorMap = errorMap;
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ }
+
+ protected Control createCustomArea(Composite parent) {
+ Composite comp = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout(1, true);
+ comp.setLayout(layout);
+
+ GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
+ gd.widthHint = TABLE_WIDTH+50;
+ gd.grabExcessHorizontalSpace=true;
+ gd.grabExcessVerticalSpace=true;
+ comp.setLayoutData(gd);
+
+ gd = new GridData(SWT.FILL, SWT.FILL, true, true);
+ gd.widthHint = TABLE_WIDTH;
+ gd.heightHint = 200;
+ errorTable = new TableViewer(comp, SWT.BORDER|SWT.H_SCROLL|SWT.V_SCROLL|SWT.FULL_SELECTION);
+ errorTable.getTable().setHeaderVisible(true);
+ errorTable.getTable().setLinesVisible(true);
+
+ errorTable.setContentProvider(new ErrorTableContentProvider());
+ errorTable.setLabelProvider(new ErrorTableLabelProvider());
+ errorTable.getControl().setLayoutData(gd);
+
+ setupTableColumns();
+ errorTable.setInput(errorMap);
+ return comp;
+ }
+
+ /**
+ * Create the table columns and set up their widths
+ */
+ protected void setupTableColumns() {
+ GC gc = new GC(errorTable.getControl());
+ gc.setFont(errorTable.getControl().getFont());
+ for(int i=0;i<COL_NAMES.length;i++){
+ TableColumn col = new TableColumn(errorTable.getTable(), COL_STYLES[i]);
+ col.setText(COL_NAMES[i]);
+ int width = calcStringWidth(gc, i);
+ col.setWidth(width);
+ }
+ gc.dispose();
+ }
+
+ /**
+ * Find out how wide the strings are so the columns can be set correctly.
+ * @param gc
+ * @param column
+ * @return
+ */
+ private int calcStringWidth(GC gc, int column){
+ int maxWidth = 100;
+ if(column == PROJECT_COL){
+ Set<String> keySet = errorMap.keySet();
+ for(String projectName : keySet){
+ int width = gc.stringExtent(projectName).x+10;
+ maxWidth = Math.max(maxWidth, width);
+ }
+ return maxWidth;
+ }
+ Collection<Throwable> values = errorMap.values();
+ for(Throwable t : values){
+ String msg = M2EUtils.getRootCauseMessage(t);
+ if(msg == null){
+ msg = ""; //$NON-NLS-1$
+ }
+ int width = gc.stringExtent(msg).x+10;
+ maxWidth = Math.max(maxWidth, width);
+ }
+ return maxWidth;
+ }
+
+ /**
+ * ErrorTableContentProvider
+ *
+ * @author dyocum
+ */
+ class ErrorTableContentProvider implements IStructuredContentProvider {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
+ */
+ public Object[] getElements(Object inputElement) {
+ if(inputElement instanceof Map){
+ return ((Map)inputElement).keySet().toArray();
+ }
+ return new Object[0];
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ public void dispose() {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+ */
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+ }
+
+ class ErrorTableLabelProvider implements ITableLabelProvider{
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
+ */
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
+ */
+ public String getColumnText(Object element, int columnIndex) {
+ if(columnIndex == PROJECT_COL){
+ return element.toString();
+ }
+ String msg = M2EUtils.getRootCauseMessage(errorMap.get(element));
+ return msg == null ? "" : msg; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
+ */
+ public void addListener(ILabelProviderListener listener) {
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
+ */
+ public void dispose() {
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String)
+ */
+ public boolean isLabelProperty(Object element, String property) {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
+ */
+ public void removeListener(ILabelProviderListener listener) {
+ }
+ }
+
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/M2EUIUtils.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/M2EUIUtils.java
new file mode 100644
index 00000000..0b9aa536
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/M2EUIUtils.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.util;
+
+import java.util.Map;
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.fieldassist.ControlDecoration;
+import org.eclipse.jface.fieldassist.FieldDecoration;
+import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
+import org.eclipse.m2e.core.internal.M2EUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * M2EUtils
+ *
+ * @author dyocum
+ */
+public class M2EUIUtils {
+
+ public static Font deriveFont(Font f, int style, int height){
+ FontData[] fd = f.getFontData();
+ FontData[] newFD = new FontData[fd.length];
+ for(int i=0;i<fd.length;i++){
+ newFD[i] = new FontData(fd[i].getName(), height, style);
+ }
+ return new Font(Display.getCurrent(), newFD);
+ }
+
+ public static void showErrorDialog(Shell shell, String title, String msg, Exception e){
+ StringBuffer buff = new StringBuffer(msg);
+ Throwable t = M2EUtils.getRootCause(e);
+ if(t != null && !nullOrEmpty(t.getMessage())){
+ buff.append(t.getMessage());
+ }
+ MessageDialog.openError(shell, title, buff.toString());
+ }
+
+ public static boolean nullOrEmpty(String s){
+ return s == null || s.length() == 0;
+ }
+
+ /**
+ * @param shell
+ * @param string
+ * @param string2
+ * @param updateErrors
+ */
+ public static void showErrorsForProjectsDialog(final Shell shell, final String title, final String message,
+ final Map<String, Throwable> errorMap) {
+ // TODO Auto-generated method showErrorsForProjectsDialog
+ Display.getDefault().asyncExec(new Runnable(){
+ public void run(){
+ String[] buttons = {IDialogConstants.OK_LABEL};
+ int ok_button = 0;
+ M2EErrorDialog errDialog = new M2EErrorDialog(shell, title, Dialog.getImage(Dialog.DLG_IMG_MESSAGE_ERROR), message, MessageDialog.ERROR, buttons, ok_button,
+ errorMap);
+ errDialog.create();
+ errDialog.open();
+ }
+ });
+
+ }
+
+ public static void addRequiredDecoration(Control control) {
+ FieldDecoration fieldDecoration = FieldDecorationRegistry.getDefault().getFieldDecoration(
+ FieldDecorationRegistry.DEC_REQUIRED);
+ ControlDecoration controlDecoration = new ControlDecoration(control, SWT.LEFT | SWT.CENTER);
+ controlDecoration.setDescriptionText(fieldDecoration.getDescription());
+ controlDecoration.setImage(fieldDecoration.getImage());
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/ProposalUtil.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/ProposalUtil.java
new file mode 100644
index 00000000..d082d161
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/ProposalUtil.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Properties;
+
+import org.apache.maven.project.MavenProject;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.fieldassist.ContentProposalAdapter;
+import org.eclipse.jface.fieldassist.FieldDecoration;
+import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
+import org.eclipse.jface.fieldassist.IContentProposal;
+import org.eclipse.jface.fieldassist.IContentProposalProvider;
+import org.eclipse.jface.fieldassist.IControlContentAdapter;
+import org.eclipse.jface.fieldassist.TextContentAdapter;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.m2e.core.ui.internal.search.util.CComboContentAdapter;
+import org.eclipse.m2e.core.ui.internal.search.util.ControlDecoration;
+import org.eclipse.m2e.core.ui.internal.search.util.Packaging;
+import org.eclipse.m2e.core.ui.internal.search.util.SearchEngine;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter;
+
+
+/**
+ * Holds the proposal utility code, previously in the editor.xml plug-in. Provides proposal suggestions for text and
+ * combo widgets for various metadata (group, artifact, etc.)
+ *
+ * @author rgould
+ */
+public class ProposalUtil {
+
+ public static abstract class Searcher {
+ public abstract Collection<String> search() throws CoreException;
+ }
+
+ public static final class TextProposal implements IContentProposal {
+ private final String text;
+
+ public TextProposal(String text) {
+ this.text = text;
+ }
+
+ public int getCursorPosition() {
+ return text.length();
+ }
+
+ public String getContent() {
+ return text;
+ }
+
+ public String getLabel() {
+ return text;
+ }
+
+ public String getDescription() {
+ return null;
+ }
+ }
+
+ public static void addCompletionProposal(final Control control, final Searcher searcher) {
+ FieldDecoration fieldDecoration = FieldDecorationRegistry.getDefault().getFieldDecoration(
+ FieldDecorationRegistry.DEC_CONTENT_PROPOSAL);
+ ControlDecoration decoration = new ControlDecoration(control, SWT.LEFT | SWT.TOP);
+ decoration.setShowOnlyOnFocus(true);
+ decoration.setDescriptionText(fieldDecoration.getDescription());
+ decoration.setImage(fieldDecoration.getImage());
+
+ IContentProposalProvider proposalProvider = new IContentProposalProvider() {
+ public IContentProposal[] getProposals(String contents, int position) {
+ final String start = contents.length() > position ? contents.substring(0, position) : contents;
+ ArrayList<IContentProposal> proposals = new ArrayList<IContentProposal>();
+ try {
+ for(final String text : searcher.search()) {
+ if (text.startsWith(start)) {
+ proposals.add(new TextProposal(text));
+ }
+ }
+ } catch(CoreException e) {
+ MavenLogger.log(e);
+ }
+ return proposals.toArray(new IContentProposal[proposals.size()]);
+ }
+ };
+
+ IControlContentAdapter contentAdapter;
+ if(control instanceof Text) {
+ contentAdapter = new TextContentAdapter();
+ } else {
+ contentAdapter = new CComboContentAdapter();
+ }
+
+ ContentAssistCommandAdapter adapter = new ContentAssistCommandAdapter( //
+ control, contentAdapter, proposalProvider, //
+ ContentAssistCommandAdapter.CONTENT_PROPOSAL_COMMAND, null);
+ // ContentProposalAdapter adapter = new ContentProposalAdapter(control, contentAdapter, //
+ // proposalProvider, KeyStroke.getInstance(SWT.MOD1, ' '), null);
+ adapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);
+ adapter.setPopupSize(new Point(250, 120));
+ adapter.setPopupSize(new Point(250, 120));
+ }
+
+ public static void addClassifierProposal(final IProject project, final Text groupIdText, final Text artifactIdText,
+ final Text versionText, final Text classifierText, final Packaging packaging) {
+ addCompletionProposal(classifierText, new Searcher() {
+ public Collection<String> search() throws CoreException {
+ return getSearchEngine(project).findClassifiers(groupIdText.getText(), //
+ artifactIdText.getText(), versionText.getText(), "", packaging);
+ }
+ });
+ }
+
+ public static void addVersionProposal(final IProject project, final MavenProject mp, final Text groupIdText, final Text artifactIdText,
+ final Text versionText, final Packaging packaging) {
+ addCompletionProposal(versionText, new Searcher() {
+ public Collection<String> search() throws CoreException {
+ Collection<String> toRet = new ArrayList<String>();
+ toRet.addAll(getSearchEngine(project).findVersions(groupIdText.getText(), //
+ artifactIdText.getText(), "", packaging));
+ if (mp != null) {
+ //add version props now..
+ Properties props = mp.getProperties();
+ ArrayList<String> list = new ArrayList<String>();
+ if (props != null) {
+ for (Object prop : props.keySet()) {
+ String propString = prop.toString();
+ if (propString.endsWith("Version") || propString.endsWith(".version")) {
+ list.add("${" + propString + "}");
+ }
+ }
+ }
+ Collections.sort(list);
+ toRet.addAll(list);
+ }
+ return toRet;
+ }
+ });
+ }
+
+ public static void addArtifactIdProposal(final IProject project, final Text groupIdText, final Text artifactIdText,
+ final Packaging packaging) {
+ addCompletionProposal(artifactIdText, new Searcher() {
+ public Collection<String> search() throws CoreException {
+ // TODO handle artifact info
+ return getSearchEngine(project).findArtifactIds(groupIdText.getText(), "", packaging,
+ null);
+ }
+ });
+ }
+
+ public static void addGroupIdProposal(final IProject project, final Text groupIdText, final Packaging packaging) {
+ addCompletionProposal(groupIdText, new Searcher() {
+ public Collection<String> search() throws CoreException {
+ // TODO handle artifact info
+ return getSearchEngine(project).findGroupIds(groupIdText.getText(), packaging, null);
+ }
+ });
+ }
+
+ public static SearchEngine getSearchEngine(final IProject project) throws CoreException {
+ return M2EUIPluginActivator.getDefault().getSearchEngine(project);
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/Util.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/Util.java
new file mode 100644
index 00000000..e3beb7d2
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/util/Util.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.util;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+
+/**
+ * Utility methods
+ *
+ * @author Eugene Kuleshov
+ */
+public class Util {
+
+ /**
+ * Proxy factory for compatibility stubs
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T proxy(final Object o, Class<T> type) {
+ return (T) Proxy.newProxyInstance(type.getClassLoader(), //
+ new Class[] {type}, //
+ new InvocationHandler() {
+ public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
+ try {
+ Method mm = o.getClass().getMethod(m.getName(), m.getParameterTypes());
+ return mm.invoke(o, args);
+ } catch(final NoSuchMethodException e) {
+ return null;
+ }
+ }
+ });
+ }
+
+ /**
+ * Stub interface for FileStoreEditorInput
+ *
+ * @see Util#proxy(Object, Class)
+ */
+ public static interface FileStoreEditorInputStub {
+ public java.net.URI getURI();
+ }
+
+ public static String nvl(String s) {
+ return s == null ? "" : s; //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/MavenRepositoryView.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/MavenRepositoryView.java
new file mode 100644
index 00000000..95e37be3
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/MavenRepositoryView.java
@@ -0,0 +1,595 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.WorkspaceJob;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.index.IndexListener;
+import org.eclipse.m2e.core.index.IndexManager;
+import org.eclipse.m2e.core.index.IndexedArtifact;
+import org.eclipse.m2e.core.index.IndexedArtifactFile;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.internal.index.IndexedArtifactGroup;
+import org.eclipse.m2e.core.internal.index.NexusIndex;
+import org.eclipse.m2e.core.repository.IRepository;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+import org.eclipse.m2e.core.ui.internal.actions.MaterializeAction;
+import org.eclipse.m2e.core.ui.internal.actions.OpenPomAction;
+import org.eclipse.m2e.core.ui.internal.util.M2EUIUtils;
+import org.eclipse.m2e.core.ui.internal.views.nodes.AbstractIndexedRepositoryNode;
+import org.eclipse.m2e.core.ui.internal.views.nodes.IArtifactNode;
+import org.eclipse.m2e.core.ui.internal.views.nodes.IndexedArtifactFileNode;
+import org.eclipse.m2e.core.ui.internal.views.nodes.LocalRepositoryNode;
+import org.eclipse.m2e.core.ui.internal.views.nodes.RepositoryNode;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.actions.BaseSelectionListenerAction;
+import org.eclipse.ui.part.DrillDownAdapter;
+import org.eclipse.ui.part.ViewPart;
+
+
+/**
+ * Maven repository view
+ *
+ * @author dyocum
+ */
+public class MavenRepositoryView extends ViewPart {
+ private static final String ENABLE_FULL = Messages.MavenRepositoryView_enable_full;
+ private static final String ENABLED_FULL = Messages.MavenRepositoryView_enabled_full;
+ private static final String DISABLE_DETAILS = Messages.MavenRepositoryView_disable_details;
+ private static final String DISABLED_DETAILS = Messages.MavenRepositoryView_details_disabled;
+ private static final String ENABLE_MIN = Messages.MavenRepositoryView_enable_minimum;
+ private static final String ENABLED_MIN = Messages.MavenRepositoryView_minimum_enabled;
+
+ private IndexManager indexManager = MavenPlugin.getDefault().getIndexManager();
+
+ private IAction collapseAllAction;
+
+ private IAction reloadSettings;
+
+ BaseSelectionListenerAction openPomAction;
+
+ private BaseSelectionListenerAction updateAction;
+
+ private BaseSelectionListenerAction rebuildAction;
+
+ private DisableIndexAction disableAction;
+ private EnableMinIndexAction enableMinAction;
+ private EnableFullIndexAction enableFullAction;
+
+ private BaseSelectionListenerAction copyUrlAction;
+
+ private BaseSelectionListenerAction materializeProjectAction;
+
+ TreeViewer viewer;
+ private RepositoryViewContentProvider contentProvider;
+
+ private DrillDownAdapter drillDownAdapter;
+
+ private IndexListener indexListener;
+
+ public void setFocus() {
+ viewer.getControl().setFocus();
+ }
+
+ public void createPartControl(Composite parent) {
+ viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+ contentProvider = new RepositoryViewContentProvider();
+ viewer.setContentProvider(contentProvider);
+ viewer.setLabelProvider(new RepositoryViewLabelProvider(viewer.getTree().getFont()));
+
+ viewer.addDoubleClickListener(new IDoubleClickListener() {
+ public void doubleClick(DoubleClickEvent event) {
+
+ }
+ });
+ viewer.setInput(getViewSite());
+ drillDownAdapter = new DrillDownAdapter(viewer);
+
+ makeActions();
+ hookContextMenu();
+
+ viewer.addDoubleClickListener(new IDoubleClickListener() {
+ public void doubleClick(DoubleClickEvent event) {
+ openPomAction.run();
+ }
+ });
+
+ contributeToActionBars();
+ this.indexListener = new IndexListener() {
+
+ public void indexAdded(IRepository repository) {
+ refreshView();
+ }
+
+ public void indexChanged(IRepository repository) {
+ refreshView();
+ }
+
+ public void indexRemoved(IRepository repository) {
+ refreshView();
+ }
+
+ public void indexUpdating(IRepository repository){
+ Display.getDefault().asyncExec(new Runnable(){
+ public void run(){
+ viewer.refresh(true);
+ }
+ });
+ }
+ };
+
+ indexManager.addIndexListener(this.indexListener);
+ }
+
+ private void hookContextMenu() {
+ MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
+ menuMgr.setRemoveAllWhenShown(true);
+ menuMgr.addMenuListener(new IMenuListener() {
+ public void menuAboutToShow(IMenuManager manager) {
+ MavenRepositoryView.this.fillContextMenu(manager);
+ }
+ });
+
+ Menu menu = menuMgr.createContextMenu(viewer.getControl());
+ viewer.getControl().setMenu(menu);
+ getSite().registerContextMenu(menuMgr, viewer);
+ }
+
+ private void contributeToActionBars() {
+ IActionBars bars = getViewSite().getActionBars();
+ fillLocalPullDown(bars.getMenuManager());
+ fillLocalToolBar(bars.getToolBarManager());
+ }
+
+ private void fillLocalPullDown(IMenuManager manager) {
+ manager.add(new Separator());
+ manager.add(collapseAllAction);
+ manager.add(reloadSettings);
+ }
+
+ protected List<AbstractIndexedRepositoryNode> getSelectedRepositoryNodes(List elements){
+ ArrayList<AbstractIndexedRepositoryNode> list = new ArrayList<AbstractIndexedRepositoryNode>();
+ if (elements != null) {
+ for(int i=0;i<elements.size();i++){
+ Object elem = elements.get(i);
+ if(elem instanceof AbstractIndexedRepositoryNode) {
+ list.add((AbstractIndexedRepositoryNode)elem);
+ }
+ }
+ }
+ return list;
+ }
+ protected List<IArtifactNode> getArtifactNodes(List elements){
+ if(elements == null || elements.size() == 0){
+ return null;
+ }
+ ArrayList<IArtifactNode> list = new ArrayList<IArtifactNode>();
+ for(int i=0;i<elements.size();i++){
+ Object elem = elements.get(i);
+ if(elem instanceof IArtifactNode){
+ IArtifactNode node = (IArtifactNode)elem;
+ list.add(node);
+ }
+ }
+ return list;
+ }
+ void fillContextMenu(IMenuManager manager) {
+ manager.add(openPomAction);
+ manager.add(copyUrlAction);
+ manager.add(materializeProjectAction);
+ manager.add(new Separator());
+ manager.add(updateAction);
+ manager.add(rebuildAction);
+ manager.add(new Separator());
+ manager.add(disableAction);
+ manager.add(enableMinAction);
+ manager.add(enableFullAction);
+// manager.add(deleteFromLocalAction);
+ manager.add(new Separator());
+ manager.add(collapseAllAction);
+ manager.add(new Separator());
+ drillDownAdapter.addNavigationActions(manager);
+ manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+ }
+
+ private void fillLocalToolBar(IToolBarManager manager) {
+ manager.add(new Separator());
+ manager.add(collapseAllAction);
+ manager.add(reloadSettings);
+ manager.add(new Separator());
+ drillDownAdapter.addNavigationActions(manager);
+ }
+
+ private void makeActions() {
+ collapseAllAction = new Action(Messages.MavenRepositoryView_btnCollapse) {
+ public void run() {
+ viewer.collapseAll();
+ }
+ };
+ collapseAllAction.setToolTipText(Messages.MavenRepositoryView_btnCollapse_tooltip);
+ collapseAllAction.setImageDescriptor(MavenImages.COLLAPSE_ALL);
+ reloadSettings = new Action(Messages.MavenRepositoryView_action_reload){
+ public void run(){
+ String msg = Messages.MavenRepositoryView_reload_msg;
+ boolean res = MessageDialog.openConfirm(getViewSite().getShell(), //
+ Messages.MavenRepositoryView_reload_title, msg);
+ if(res){
+ Job job = new WorkspaceJob(Messages.MavenRepositoryView_job_reloading) {
+ public IStatus runInWorkspace(IProgressMonitor monitor) {
+ try {
+ MavenPlugin.getDefault().getMaven().reloadSettings();
+ } catch(CoreException ex) {
+ return ex.getStatus();
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ job.schedule();
+ }
+ }
+ };
+
+ reloadSettings.setImageDescriptor(MavenImages.REFRESH);
+// deleteFromLocalAction = new BaseSelectionListenerAction("Delete from Repository") {
+// public void run() {
+// List<IArtifactNode> nodes = getArtifactNodes(getStructuredSelection().toList());
+// if(nodes != null){
+// for(IArtifactNode node : nodes){
+// String key = node.getDocumentKey();
+// System.out.println("key: "+key);
+// ((NexusIndexManager)MavenPlugin.getDefault().getIndexManager()).removeDocument("local", null, key);
+// }
+// }
+// }
+//
+// protected boolean updateSelection(IStructuredSelection selection) {
+// List<IArtifactNode> nodes = getArtifactNodes(getStructuredSelection().toList());
+// return (nodes != null && nodes.size() > 0);
+// }
+// };
+// deleteFromLocalAction.setToolTipText("Delete the selected GAV from the local repository");
+ //updateAction.setImageDescriptor(MavenImages.UPD_INDEX);
+
+
+ updateAction = new BaseSelectionListenerAction(Messages.MavenRepositoryView_action_update) {
+ public void run() {
+ List<AbstractIndexedRepositoryNode> nodes = getSelectedRepositoryNodes(getStructuredSelection().toList());
+ for(AbstractIndexedRepositoryNode node : nodes) {
+ if (node instanceof RepositoryNode) {
+ ((RepositoryNode) node).getIndex().scheduleIndexUpdate(false);
+ }
+ }
+ }
+
+ protected boolean updateSelection(IStructuredSelection selection) {
+ int indexCount = 0;
+ for (AbstractIndexedRepositoryNode node : getSelectedRepositoryNodes(selection.toList())) {
+ if (node instanceof RepositoryNode && node.isEnabledIndex()) {
+ indexCount ++;
+ }
+ }
+ if(indexCount > 1){
+ setText(Messages.MavenRepositoryView_update_more);
+ } else {
+ setText(Messages.MavenRepositoryView_update_one);
+ }
+ return indexCount > 0;
+ }
+ };
+ updateAction.setToolTipText(Messages.MavenRepositoryView_btnUpdate_tooltip);
+ updateAction.setImageDescriptor(MavenImages.UPD_INDEX);
+
+ rebuildAction = new BaseSelectionListenerAction(Messages.MavenRepositoryView_action_rebuild) {
+ public void run() {
+ List<AbstractIndexedRepositoryNode> nodes = getSelectedRepositoryNodes(getStructuredSelection().toList());
+ if(nodes.size() > 0){
+ if(nodes.size() == 1){
+ NexusIndex index = nodes.get(0).getIndex();
+ if (index != null) {
+ String repositoryUrl = index.getRepositoryUrl();
+ String msg = NLS.bind(Messages.MavenRepositoryView_rebuild_msg, repositoryUrl);
+ boolean res = MessageDialog.openConfirm(getViewSite().getShell(), //
+ Messages.MavenRepositoryView_rebuild_title, msg);
+ if(res) {
+ index.scheduleIndexUpdate(true);
+ }
+ }
+ } else {
+ String msg = Messages.MavenRepositoryView_rebuild_msg2;
+ boolean res = MessageDialog.openConfirm(getViewSite().getShell(), //
+ Messages.MavenRepositoryView_rebuild_title2, msg);
+ if(res) {
+ for(AbstractIndexedRepositoryNode node : nodes){
+ NexusIndex index = node.getIndex();
+ if (index != null) {
+ index.scheduleIndexUpdate(true);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ protected boolean updateSelection(IStructuredSelection selection) {
+ int indexCount = 0;
+ for (AbstractIndexedRepositoryNode node : getSelectedRepositoryNodes(selection.toList())) {
+ if ((node instanceof LocalRepositoryNode) || node.isEnabledIndex()) {
+ indexCount ++;
+ }
+ }
+ if(indexCount > 1){
+ setText(Messages.MavenRepositoryView_rebuild_many);
+ } else {
+ setText(Messages.MavenRepositoryView_rebuild_one);
+ }
+ return indexCount > 0;
+ }
+ };
+
+ rebuildAction.setToolTipText(Messages.MavenRepositoryView_action_rebuild_tooltip);
+ rebuildAction.setImageDescriptor(MavenImages.REBUILD_INDEX);
+
+ disableAction = new DisableIndexAction();
+
+ disableAction.setToolTipText(Messages.MavenRepositoryView_action_disable_tooltip);
+ disableAction.setImageDescriptor(MavenImages.REBUILD_INDEX);
+
+ enableMinAction = new EnableMinIndexAction();
+ enableMinAction.setToolTipText(Messages.MavenRepositoryView_action_enable_tooltip);
+ enableMinAction.setImageDescriptor(MavenImages.REBUILD_INDEX);
+
+ enableFullAction = new EnableFullIndexAction();
+ enableFullAction.setToolTipText(Messages.MavenRepositoryView_action_enableFull_tooltip);
+ enableFullAction.setImageDescriptor(MavenImages.REBUILD_INDEX);
+
+ openPomAction = new BaseSelectionListenerAction(Messages.MavenRepositoryView_action_open) {
+ public void run() {
+ ISelection selection = viewer.getSelection();
+ Object element = ((IStructuredSelection) selection).getFirstElement();
+ if(element instanceof IndexedArtifactFileNode) {
+ IndexedArtifactFile f = ((IndexedArtifactFileNode) element).getIndexedArtifactFile();
+ OpenPomAction.openEditor(f.group, f.artifact, f.version, null);
+ }
+ }
+
+ protected boolean updateSelection(IStructuredSelection selection) {
+ return selection.getFirstElement() instanceof IndexedArtifactFile;
+ }
+ };
+ openPomAction.setToolTipText(Messages.MavenRepositoryView_action_open_tooltip);
+ openPomAction.setImageDescriptor(MavenImages.POM);
+
+ copyUrlAction = new BaseSelectionListenerAction(Messages.MavenRepositoryView_action_copy) {
+ public void run() {
+ Object element = getStructuredSelection().getFirstElement();
+ String url = null;
+ if(element instanceof RepositoryNode) {
+ url = ((RepositoryNode) element).getRepositoryUrl();
+ } else if(element instanceof IndexedArtifactGroup) {
+ IndexedArtifactGroup group = (IndexedArtifactGroup) element;
+ String repositoryUrl = group.getRepository().getUrl();
+ if(!repositoryUrl.endsWith("/")) { //$NON-NLS-1$
+ repositoryUrl += "/"; //$NON-NLS-1$
+ }
+ url = repositoryUrl + group.getPrefix().replace('.', '/');
+ } else if(element instanceof IndexedArtifact) {
+ //
+ } else if(element instanceof IndexedArtifactFile) {
+ //
+ }
+ if(url != null) {
+ Clipboard clipboard = new Clipboard(Display.getCurrent());
+ clipboard.setContents(new String[] {url}, new Transfer[] {TextTransfer.getInstance()});
+ clipboard.dispose();
+ }
+ }
+
+ protected boolean updateSelection(IStructuredSelection selection) {
+ Object element = selection.getFirstElement();
+ return element instanceof RepositoryNode;
+ }
+ };
+ copyUrlAction.setToolTipText(Messages.MavenRepositoryView_action_copy_tooltip);
+ copyUrlAction.setImageDescriptor(MavenImages.COPY);
+
+ materializeProjectAction = new BaseSelectionListenerAction(Messages.MavenRepositoryView_action_materialize) {
+ public void run() {
+ Object element = getStructuredSelection().getFirstElement();
+ if(element instanceof IndexedArtifactFileNode){
+ MaterializeAction action = new MaterializeAction();
+ StructuredSelection sel = new StructuredSelection(new Object[]{((IndexedArtifactFileNode) element).getIndexedArtifactFile()});
+ action.selectionChanged(this, sel);
+ action.run(this);
+ }
+ }
+
+ protected boolean updateSelection(IStructuredSelection selection) {
+ return selection.getFirstElement() instanceof IndexedArtifactFileNode;
+ }
+ };
+ materializeProjectAction.setImageDescriptor(MavenImages.IMPORT_PROJECT);
+
+ viewer.addSelectionChangedListener(openPomAction);
+ viewer.addSelectionChangedListener(updateAction);
+ viewer.addSelectionChangedListener(disableAction);
+ viewer.addSelectionChangedListener(enableMinAction);
+ viewer.addSelectionChangedListener(enableFullAction);
+ viewer.addSelectionChangedListener(rebuildAction);
+ viewer.addSelectionChangedListener(copyUrlAction);
+ viewer.addSelectionChangedListener(materializeProjectAction);
+ }
+
+ protected void setIndexDetails(AbstractIndexedRepositoryNode node, String details) {
+ if (node != null && node.getIndex() != null) {
+ try {
+ node.getIndex().setIndexDetails(details);
+ } catch(CoreException ex) {
+ M2EUIUtils.showErrorDialog(this.getViewSite().getShell(), Messages.MavenRepositoryView_error_title, Messages.MavenRepositoryView_error_message, ex);
+ }
+ }
+ }
+
+ protected AbstractIndexedRepositoryNode getSelectedRepositoryNode(IStructuredSelection selection) {
+ List elements = selection.toList();
+ if (elements.size() != 1) {
+ return null;
+ }
+ Object element = elements.get(0);
+ return element instanceof AbstractIndexedRepositoryNode? (AbstractIndexedRepositoryNode) element: null;
+ }
+
+ public void dispose() {
+ viewer.removeSelectionChangedListener(materializeProjectAction);
+ viewer.removeSelectionChangedListener(copyUrlAction);
+ viewer.removeSelectionChangedListener(rebuildAction);
+ viewer.removeSelectionChangedListener(disableAction);
+ viewer.removeSelectionChangedListener(enableMinAction);
+ viewer.removeSelectionChangedListener(enableFullAction);
+ viewer.removeSelectionChangedListener(updateAction);
+ viewer.removeSelectionChangedListener(openPomAction);
+ indexManager.removeIndexListener(this.indexListener);
+ super.dispose();
+ }
+
+ void refreshView() {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ Object[] expandedElems = viewer.getExpandedElements();
+ if (!viewer.getControl().isDisposed()) {
+ viewer.setInput(getViewSite());
+ if(expandedElems != null && expandedElems.length > 0){
+ viewer.setExpandedElements(expandedElems);
+ }
+ }
+ }
+ });
+ };
+
+ /**
+ * Base Selection Listener does not allow the style (radio button/check) to be set.
+ * This base class listens to selections and sets the appropriate index value
+ * depending on its value
+ * AbstractIndexAction
+ *
+ * @author dyocum
+ */
+ abstract class AbstractIndexAction extends Action implements ISelectionChangedListener{
+
+ protected abstract String getDetailsValue();
+ protected abstract String getActionText();
+
+ public AbstractIndexAction(String text, int style){
+ super(text, style);
+ }
+
+ public void run() {
+ IStructuredSelection sel = (IStructuredSelection)viewer.getSelection();
+ setIndexDetails(getSelectedRepositoryNode(sel), getDetailsValue());
+ }
+
+ /*
+ */
+ public void selectionChanged(SelectionChangedEvent event) {
+ IStructuredSelection sel = (IStructuredSelection)event.getSelection();
+ updateSelection(sel);
+ }
+
+ protected void updateSelection(IStructuredSelection selection) {
+ AbstractIndexedRepositoryNode node = getSelectedRepositoryNode(selection);
+ updateIndexDetails(node);
+ setText(getActionText());
+ boolean enabled = (node != null && node instanceof RepositoryNode);
+ this.setEnabled(enabled);
+ }
+
+ protected void updateIndexDetails(AbstractIndexedRepositoryNode node){
+ if(node == null || node.getIndex() == null){
+ return;
+ }
+ NexusIndex index = node.getIndex();
+ setChecked(getDetailsValue().equals(index.getIndexDetails()));
+ }
+
+ }
+
+ class DisableIndexAction extends AbstractIndexAction {
+ public DisableIndexAction(){
+ super(DISABLE_DETAILS, IAction.AS_CHECK_BOX);
+ }
+
+ protected String getDetailsValue(){
+ return NexusIndex.DETAILS_DISABLED;
+ }
+ protected String getActionText(){
+ return isChecked() ? DISABLED_DETAILS : DISABLE_DETAILS;
+ }
+ }
+
+ class EnableMinIndexAction extends AbstractIndexAction {
+ public EnableMinIndexAction(){
+ super(ENABLE_MIN, IAction.AS_CHECK_BOX);
+ }
+
+ protected String getDetailsValue(){
+ return NexusIndex.DETAILS_MIN;
+ }
+ protected String getActionText(){
+ return isChecked() ? ENABLED_MIN : ENABLE_MIN;
+ }
+ }
+
+ class EnableFullIndexAction extends AbstractIndexAction {
+ public EnableFullIndexAction(){
+ super(ENABLE_FULL, IAction.AS_CHECK_BOX);
+ }
+
+ protected String getDetailsValue(){
+ return NexusIndex.DETAILS_FULL;
+ }
+ protected String getActionText(){
+ return isChecked() ? ENABLED_FULL : ENABLE_FULL;
+ }
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/RepositoryViewContentProvider.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/RepositoryViewContentProvider.java
new file mode 100644
index 00000000..a084fc52
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/RepositoryViewContentProvider.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.m2e.core.ui.internal.views.nodes.CustomRepositoriesNode;
+import org.eclipse.m2e.core.ui.internal.views.nodes.GlobalRepositoriesNode;
+import org.eclipse.m2e.core.ui.internal.views.nodes.IMavenRepositoryNode;
+import org.eclipse.m2e.core.ui.internal.views.nodes.LocalRepositoryRootNode;
+import org.eclipse.m2e.core.ui.internal.views.nodes.ProjectRepositoriesNode;
+import org.eclipse.ui.IViewSite;
+
+/**
+ * RepositoryViewContentProvider
+ *
+ * @author dyocum
+ */
+public class RepositoryViewContentProvider implements IStructuredContentProvider, ITreeContentProvider {
+
+ private LocalRepositoryRootNode localNode;
+ private GlobalRepositoriesNode globalNode;
+ private ProjectRepositoriesNode projectNode;
+ private CustomRepositoriesNode customNode;
+
+ public RepositoryViewContentProvider() {
+ }
+
+ public void inputChanged(Viewer v, Object oldInput, Object newInput) {
+ }
+
+ public void dispose() {
+ }
+
+ public Object[] getElements(Object parent) {
+ return getChildren(parent);
+ }
+
+ public Object getParent(Object child) {
+ return null;
+ }
+
+ public boolean hasChildren(Object parent) {
+ if(parent instanceof IMavenRepositoryNode){
+ return ((IMavenRepositoryNode)parent).hasChildren();
+ }
+ return false;
+ }
+
+ public Object[] getRootNodes(){
+ if(localNode == null){
+ localNode = new LocalRepositoryRootNode();
+
+ }
+ if(globalNode == null){
+ globalNode = new GlobalRepositoriesNode();
+ }
+ if(projectNode == null) {
+ projectNode = new ProjectRepositoriesNode();
+ }
+ if(customNode == null) {
+ customNode = new CustomRepositoriesNode();
+ }
+ return new Object[]{localNode, globalNode, projectNode, customNode};
+ }
+
+ public Object[] getChildren(Object parent) {
+ if(parent instanceof IViewSite){
+ return getRootNodes();
+ } else if(parent instanceof IMavenRepositoryNode){
+ return ((IMavenRepositoryNode)parent).getChildren();
+ }
+ return new Object[0];
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/RepositoryViewLabelProvider.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/RepositoryViewLabelProvider.java
new file mode 100644
index 00000000..f65adaf6
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/RepositoryViewLabelProvider.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views;
+
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.IFontProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.m2e.core.ui.internal.util.M2EUIUtils;
+import org.eclipse.m2e.core.ui.internal.views.nodes.IMavenRepositoryNode;
+import org.eclipse.m2e.core.ui.internal.views.nodes.RepositoryNode;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * RepositoryViewLabelProvider
+ *
+ * @author dyocum
+ */
+public class RepositoryViewLabelProvider extends LabelProvider implements IColorProvider, IFontProvider {
+
+ private Font italicFont;
+ public RepositoryViewLabelProvider(Font treeFont){
+ int size = 0;
+ FontData[] data = treeFont.getFontData();
+ if(data == null){
+ size = 12;
+ } else {
+ for(int i=0;i<data.length;i++){
+ size = Math.max(size, data[i].getHeight());
+ }
+ }
+ italicFont = M2EUIUtils.deriveFont(treeFont, SWT.ITALIC, size);
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.BaseLabelProvider#dispose()
+ */
+ public void dispose() {
+ italicFont.dispose();
+ super.dispose();
+ }
+
+
+ public String getText(Object obj) {
+ if(obj instanceof IMavenRepositoryNode){
+ return ((IMavenRepositoryNode)obj).getName();
+ }
+ return obj.toString();
+ }
+
+ public Image getImage(Object obj) {
+ if(obj instanceof IMavenRepositoryNode){
+ return ((IMavenRepositoryNode)obj).getImage();
+ }
+ return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT);
+ }
+
+ public Color getBackground(Object element) {
+ return null;
+ }
+
+ public Color getForeground(Object element) {
+ if(element instanceof RepositoryNode){
+ if(((RepositoryNode)element).isEnabledIndex()){
+ return Display.getDefault().getSystemColor(SWT.COLOR_BLACK);
+ }
+ return Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY);
+ }
+ return Display.getDefault().getSystemColor(SWT.COLOR_BLACK);
+ }
+
+ public Font getFont(Object element) {
+ if(element instanceof IMavenRepositoryNode){
+ boolean updating = ((IMavenRepositoryNode)element).isUpdating();
+ return updating ? italicFont : null;
+ }
+ return null;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/AbstractIndexedRepositoryNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/AbstractIndexedRepositoryNode.java
new file mode 100644
index 00000000..2d1755b6
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/AbstractIndexedRepositoryNode.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.nodes;
+
+import java.util.Arrays;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.internal.index.IndexedArtifactGroup;
+import org.eclipse.m2e.core.internal.index.NexusIndex;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+import org.eclipse.swt.graphics.Image;
+
+
+/**
+ * AbstractIndexedRepository
+ *
+ * @author igor
+ */
+public abstract class AbstractIndexedRepositoryNode implements IMavenRepositoryNode {
+
+ protected static final Object[] NO_CHILDREN = new Object[0];
+
+ protected final NexusIndex index;
+
+ protected AbstractIndexedRepositoryNode(NexusIndex index) {
+ this.index = index;
+ }
+
+ public Object[] getChildren() {
+
+ if(index == null) {
+ return NO_CHILDREN;
+ }
+
+ try {
+ IndexedArtifactGroup[] rootGroups = index.getRootIndexedArtifactGroups();
+ if(rootGroups == null) {
+ return NO_CHILDREN;
+ }
+ IndexedArtifactGroupNode[] children = new IndexedArtifactGroupNode[rootGroups.length];
+ Arrays.sort(rootGroups);
+ for(int i = 0; i < rootGroups.length; i++ ) {
+ children[i] = new IndexedArtifactGroupNode(rootGroups[i]);
+ }
+ return children;
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ return NO_CHILDREN;
+ }
+ }
+
+ public Image getImage() {
+ return MavenImages.IMG_INDEX;
+ }
+
+ public boolean hasChildren() {
+ return index != null;
+ }
+
+ public boolean isUpdating() {
+ return index != null && index.isUpdating();
+ }
+
+ public NexusIndex getIndex() {
+ return index;
+ }
+
+ public String getRepositoryUrl() {
+ return index.getRepositoryUrl();
+ }
+
+ public boolean isEnabledIndex() {
+ return index != null && index.isEnabled();
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/AbstractRepositoriesNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/AbstractRepositoriesNode.java
new file mode 100644
index 00000000..c1b24b70
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/AbstractRepositoriesNode.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.nodes;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.internal.index.NexusIndex;
+import org.eclipse.m2e.core.internal.index.NexusIndexManager;
+import org.eclipse.m2e.core.repository.IRepository;
+import org.eclipse.m2e.core.repository.IRepositoryRegistry;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * AbstractRepositoriesNode
+ *
+ * @author igor
+ */
+public abstract class AbstractRepositoriesNode implements IMavenRepositoryNode {
+
+ protected final NexusIndexManager indexManager = (NexusIndexManager) MavenPlugin.getDefault().getIndexManager();
+ protected final IRepositoryRegistry repositoryRegistry = MavenPlugin.getDefault().getRepositoryRegistry();
+
+ public Object[] getChildren() {
+
+ ArrayList<Object> mirrorNodes = new ArrayList<Object>();
+ ArrayList<Object> globalRepoNodes = new ArrayList<Object>();
+
+ for (IRepository repo : getRepositories()) {
+ NexusIndex index = indexManager.getIndex(repo);
+ RepositoryNode node = new RepositoryNode(index);
+ if (repo.getMirrorOf() != null) {
+ mirrorNodes.add(node);
+ } else {
+ globalRepoNodes.add(node);
+ }
+ }
+
+ ArrayList<Object> nodes = new ArrayList<Object>();
+ nodes.addAll(mirrorNodes);
+ nodes.addAll(globalRepoNodes);
+
+ return nodes.toArray(new Object[nodes.size()]);
+ }
+
+ protected abstract List<IRepository> getRepositories();
+
+ public String toString() {
+ return getName();
+ }
+
+ public boolean hasChildren() {
+ Object[] kids = getChildren();
+ return kids != null && kids.length > 0;
+ }
+
+ public Image getImage() {
+ return MavenImages.IMG_INDEXES;
+ }
+
+ public boolean isUpdating() {
+ return false;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/CustomRepositoriesNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/CustomRepositoriesNode.java
new file mode 100644
index 00000000..678dcbdd
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/CustomRepositoriesNode.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.nodes;
+
+import java.util.List;
+
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.repository.IRepository;
+import org.eclipse.m2e.core.repository.IRepositoryRegistry;
+
+/**
+ * CustomRepositoriesNode
+ *
+ * @author igor
+ */
+public class CustomRepositoriesNode extends AbstractRepositoriesNode {
+
+ protected List<IRepository> getRepositories() {
+ return repositoryRegistry.getRepositories(IRepositoryRegistry.SCOPE_UNKNOWN);
+ }
+
+ public String getName() {
+ return Messages.CustomRepositoriesNode_name;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/GlobalRepositoriesNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/GlobalRepositoriesNode.java
new file mode 100644
index 00000000..7eef0deb
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/GlobalRepositoriesNode.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.nodes;
+
+import java.util.List;
+
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.repository.IRepository;
+import org.eclipse.m2e.core.repository.IRepositoryRegistry;
+
+
+/**
+ * Parent node for all artifact repositories and mirrors defined in settings.xml.
+ *
+ * @author dyocum
+ */
+public class GlobalRepositoriesNode extends AbstractRepositoriesNode {
+
+ public String getName() {
+ return Messages.GlobalRepositoriesNode_name;
+ }
+
+ protected List<IRepository> getRepositories() {
+ return repositoryRegistry.getRepositories(IRepositoryRegistry.SCOPE_SETTINGS);
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IArtifactNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IArtifactNode.java
new file mode 100644
index 00000000..54c908fb
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IArtifactNode.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.nodes;
+
+
+/**
+ * AbstractArtifactNode
+ *
+ * @author dyocum
+ */
+public interface IArtifactNode {
+ public String getDocumentKey();
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IMavenRepositoryNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IMavenRepositoryNode.java
new file mode 100644
index 00000000..b296ca7f
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IMavenRepositoryNode.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.nodes;
+
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * MavenRepositoryRootNode
+ *
+ * @author dyocum
+ */
+public interface IMavenRepositoryNode {
+
+ public Object[] getChildren();
+ public String getName();
+ public Image getImage();
+ public boolean hasChildren();
+ public boolean isUpdating();
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IndexedArtifactFileNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IndexedArtifactFileNode.java
new file mode 100644
index 00000000..91b140c0
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IndexedArtifactFileNode.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.nodes;
+
+import org.eclipse.m2e.core.index.IIndex;
+import org.eclipse.m2e.core.index.IndexedArtifactFile;
+import org.eclipse.m2e.core.internal.index.NexusIndexManager;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * IndexedArtifactFileNode
+ *
+ * @author dyocum
+ */
+public class IndexedArtifactFileNode implements IMavenRepositoryNode, IArtifactNode {
+
+ private IndexedArtifactFile artifactFile;
+
+ public IndexedArtifactFileNode(IndexedArtifactFile artifactFile){
+ this.artifactFile = artifactFile;
+ }
+
+ public IndexedArtifactFile getIndexedArtifactFile(){
+ return this.artifactFile;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.IMavenRepositoryNode#getChildren()
+ */
+ public Object[] getChildren() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.IMavenRepositoryNode#getName()
+ */
+ public String getName() {
+ String label = artifactFile.artifact;
+ if(artifactFile.classifier != null) {
+ label += " : " + artifactFile.classifier; //$NON-NLS-1$
+ }
+ if(artifactFile.version != null) {
+ label += " : " + artifactFile.version; //$NON-NLS-1$
+ }
+ return label;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.IMavenRepositoryNode#hasChildren()
+ */
+ public boolean hasChildren() {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.nodes.IMavenRepositoryNode#getImage()
+ */
+ public Image getImage() {
+ if(artifactFile.sourcesExists == IIndex.PRESENT) {
+ return MavenImages.IMG_VERSION_SRC;
+ }
+ return MavenImages.IMG_VERSION;
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.nodes.IArtifactNode#getDocumentKey()
+ */
+ public String getDocumentKey() {
+ return NexusIndexManager.getDocumentKey(artifactFile.getArtifactKey());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.nodes.IMavenRepositoryNode#isUpdating()
+ */
+ public boolean isUpdating() {
+ return false;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IndexedArtifactGroupNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IndexedArtifactGroupNode.java
new file mode 100644
index 00000000..6c411fa3
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IndexedArtifactGroupNode.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.nodes;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.index.IndexedArtifact;
+import org.eclipse.m2e.core.internal.index.IndexedArtifactGroup;
+import org.eclipse.m2e.core.internal.index.NexusIndexManager;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * IndexedArtifactGroupNode
+ *
+ * @author dyocum
+ */
+public class IndexedArtifactGroupNode implements IMavenRepositoryNode, IArtifactNode {
+
+ private IndexedArtifactGroup indexedArtifactGroup;
+ private Object[] kids = null;
+ public IndexedArtifactGroupNode(IndexedArtifactGroup group){
+ this.indexedArtifactGroup = group;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.IMavenRepositoryNode#getChildren()
+ */
+ public Object[] getChildren() {
+ NexusIndexManager indexManager = (NexusIndexManager) MavenPlugin.getDefault().getIndexManager();
+
+ IndexedArtifactGroup resolvedGroup = indexManager.resolveGroup(indexedArtifactGroup);
+ //IndexedArtifactGroup resolvedGroup = indexedArtifactGroup;
+ ArrayList<Object> results = new ArrayList<Object>();
+ Collection<IndexedArtifactGroup> groups = resolvedGroup.getNodes().values();
+ for(IndexedArtifactGroup group : groups){
+ IndexedArtifactGroupNode node = new IndexedArtifactGroupNode(group);
+ results.add(node);
+ }
+
+ Collection<IndexedArtifact> artifacts = resolvedGroup.getFiles().values(); // IndexedArtifact
+ for(IndexedArtifact artifact : artifacts){
+ IndexedArtifactNode artifactNode = new IndexedArtifactNode(artifact);
+ results.add(artifactNode);
+ }
+ kids = results.toArray(new Object[results.size()]);
+ return kids;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.IMavenRepositoryNode#getName()
+ */
+ public String getName() {
+ String prefix = indexedArtifactGroup.getPrefix();
+ int n = prefix.lastIndexOf('.');
+ return n < 0 ? prefix : prefix.substring(n + 1);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.IMavenRepositoryNode#hasChildren()
+ */
+ public boolean hasChildren() {
+// if(kids == null){
+// kids = getChildren();
+// }
+// return kids != null && kids.length > 0;
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.nodes.IMavenRepositoryNode#getImage()
+ */
+ public Image getImage() {
+ return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER);
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.nodes.IArtifactNode#getDocumentKey()
+ */
+ public String getDocumentKey() {
+ return indexedArtifactGroup.getPrefix();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.nodes.IMavenRepositoryNode#isUpdating()
+ */
+ public boolean isUpdating() {
+ // TODO Auto-generated method isUpdating
+ return false;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IndexedArtifactNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IndexedArtifactNode.java
new file mode 100644
index 00000000..7e295320
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/IndexedArtifactNode.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.nodes;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+import org.eclipse.m2e.core.index.IndexedArtifact;
+import org.eclipse.m2e.core.index.IndexedArtifactFile;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * IndexedArtifactNode
+ *
+ * @author dyocum
+ */
+public class IndexedArtifactNode implements IMavenRepositoryNode, IArtifactNode {
+
+ private IndexedArtifact artifact;
+ private Object[] kids = null;
+ public IndexedArtifactNode(IndexedArtifact artifact){
+ this.artifact = artifact;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.IMavenRepositoryNode#getChildren()
+ */
+ public Object[] getChildren() {
+ Set<IndexedArtifactFile> files = artifact.getFiles();
+ if(files == null){
+ return new Object[0];
+ }
+ ArrayList<Object> fileList = new ArrayList<Object>();
+ for(IndexedArtifactFile iaf : files){
+ fileList.add(new IndexedArtifactFileNode(iaf));
+ }
+ kids = fileList.toArray(new IndexedArtifactFileNode[fileList.size()]);
+ return kids;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.IMavenRepositoryNode#getName()
+ */
+ public String getName() {
+ // return a.group + ":" + a.artifact;
+ String pkg = artifact.getPackaging();
+ if(pkg == null){
+ pkg = Messages.IndexedArtifactNode_no_pack;
+ }
+ return artifact.getArtifactId() + " - " + pkg; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.IMavenRepositoryNode#hasChildren()
+ */
+ public boolean hasChildren() {
+ //return kids != null && kids.length > 0;
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.nodes.IMavenRepositoryNode#getImage()
+ */
+ public Image getImage() {
+ return MavenImages.IMG_JAR;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.nodes.IArtifactNode#getDocumentKey()
+ */
+ public String getDocumentKey() {
+ return artifact.getArtifactId();
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.ui.internal.views.nodes.IMavenRepositoryNode#isUpdating()
+ */
+ public boolean isUpdating() {
+ // TODO Auto-generated method isUpdating
+ return false;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/LocalRepositoryNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/LocalRepositoryNode.java
new file mode 100644
index 00000000..e46218be
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/LocalRepositoryNode.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.nodes;
+
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.internal.index.NexusIndex;
+import org.eclipse.m2e.core.repository.IRepository;
+
+/**
+ * LocalRepositoryNode
+ *
+ * @author igor
+ */
+public class LocalRepositoryNode extends AbstractIndexedRepositoryNode {
+
+ public LocalRepositoryNode(NexusIndex index) {
+ super(index);
+ }
+
+ public String getName() {
+ IRepository repository = index.getRepository();
+ StringBuilder sb = new StringBuilder();
+ sb.append(Messages.LocalRepositoryNode_local);
+ if (repository.getBasedir() != null) {
+ sb.append(" (").append(repository.getBasedir().getAbsolutePath()).append(')'); //$NON-NLS-1$
+ }
+ return sb.toString();
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/LocalRepositoryRootNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/LocalRepositoryRootNode.java
new file mode 100644
index 00000000..4ed2d2c3
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/LocalRepositoryRootNode.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.nodes;
+
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.internal.index.NexusIndex;
+import org.eclipse.m2e.core.internal.index.NexusIndexManager;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * LocalRepositoryNode
+ *
+ * @author dyocum
+ */
+public class LocalRepositoryRootNode implements IMavenRepositoryNode{
+
+ public Object[] getChildren() {
+ NexusIndexManager indexManager = (NexusIndexManager) MavenPlugin.getDefault().getIndexManager();
+ NexusIndex localIndex = indexManager.getLocalIndex();
+ NexusIndex workspaceIndex = indexManager.getWorkspaceIndex();
+ return new Object[]{
+ new LocalRepositoryNode(localIndex),
+ new WorkspaceRepositoryNode(workspaceIndex)
+ };
+ }
+
+ public String getName() {
+ return Messages.LocalRepositoryRootNode_name;
+ }
+
+ public boolean hasChildren() {
+ return true;
+ }
+
+ public Image getImage() {
+ return MavenImages.IMG_INDEXES;
+ }
+
+ public boolean isUpdating() {
+ return false;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/ProjectRepositoriesNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/ProjectRepositoriesNode.java
new file mode 100644
index 00000000..69ab7d64
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/ProjectRepositoriesNode.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.nodes;
+
+import java.util.ArrayList;
+
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.internal.index.NexusIndex;
+import org.eclipse.m2e.core.internal.index.NexusIndexManager;
+import org.eclipse.m2e.core.repository.IRepository;
+import org.eclipse.m2e.core.repository.IRepositoryRegistry;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+import org.eclipse.swt.graphics.Image;
+
+
+/**
+ * Parent node for all artifact repositories configured in pom.xml files.
+ */
+public class ProjectRepositoriesNode implements IMavenRepositoryNode {
+
+ private NexusIndexManager indexManager = (NexusIndexManager) MavenPlugin.getDefault().getIndexManager();
+ private IRepositoryRegistry repositoryRegistry = MavenPlugin.getDefault().getRepositoryRegistry();
+
+ public Object[] getChildren() {
+ ArrayList<Object> nodes = new ArrayList<Object>();
+ for(IRepository repo : repositoryRegistry.getRepositories(IRepositoryRegistry.SCOPE_PROJECT)) {
+ NexusIndex index = indexManager.getIndex(repo);
+ RepositoryNode node = new RepositoryNode(index);
+ nodes.add(node);
+ }
+ return nodes.toArray(new Object[nodes.size()]);
+ }
+
+ public Image getImage() {
+ return MavenImages.IMG_INDEXES;
+ }
+
+ public String getName() {
+ return Messages.ProjectRepositoriesNode_name;
+ }
+
+ public String toString() {
+ return getName();
+ }
+
+ public boolean hasChildren() {
+ Object[] kids = getChildren();
+ return kids != null && kids.length > 0;
+ }
+
+ public boolean isUpdating() {
+ return false;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/RepositoryNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/RepositoryNode.java
new file mode 100644
index 00000000..849df8bf
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/RepositoryNode.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.nodes;
+
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.internal.index.NexusIndex;
+import org.eclipse.m2e.core.repository.IRepository;
+
+/**
+ * LocalRepsoitoryNode
+ *
+ * @author dyocum
+ */
+public class RepositoryNode extends AbstractIndexedRepositoryNode {
+
+ private final IRepository repository;
+
+ public RepositoryNode(NexusIndex index){
+ super(index);
+ this.repository = index.getRepository();
+ }
+
+ public String getName() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(repository.getId());
+ sb.append(" (").append(repository.getUrl()).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
+ if (repository.getMirrorOf() != null) {
+ sb.append(" [mirrorOf=").append(repository.getMirrorOf()).append("]"); //$NON-NLS-2$
+ }
+ if (repository.getMirrorId() != null) {
+ sb.append(" [mirrored by ").append(repository.getMirrorId()).append("]"); //$NON-NLS-2$
+ }
+ if (isUpdating()) {
+ sb.append(Messages.RepositoryNode_updating);
+ }
+ return sb.toString();
+ }
+
+ public String getRepositoryUrl() {
+ return repository.getUrl();
+ }
+
+ public String getRepoName() {
+ return repository.toString();
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/WorkspaceRepositoryNode.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/WorkspaceRepositoryNode.java
new file mode 100644
index 00000000..4cbb19fe
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/views/nodes/WorkspaceRepositoryNode.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.views.nodes;
+
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.internal.index.NexusIndex;
+
+/**
+ * WorkspaceRepositoryNode
+ *
+ * @author igor
+ */
+public class WorkspaceRepositoryNode extends AbstractIndexedRepositoryNode {
+
+ public WorkspaceRepositoryNode(NexusIndex index) {
+ super(index);
+ }
+
+ public String getName() {
+ return Messages.WorkspaceRepositoryNode_name;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/AbstactCreateMavenProjectJob.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/AbstactCreateMavenProjectJob.java
new file mode 100644
index 00000000..38639f93
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/AbstactCreateMavenProjectJob.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.WorkspaceJob;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.m2e.core.project.IMavenProjectImportResult;
+import org.eclipse.m2e.core.ui.internal.actions.OpenMavenConsoleAction;
+import org.eclipse.ui.IWorkingSet;
+import org.eclipse.ui.progress.IProgressConstants;
+
+
+public abstract class AbstactCreateMavenProjectJob extends WorkspaceJob {
+
+ private final List<IWorkingSet> workingSets;
+
+ public AbstactCreateMavenProjectJob(String name, List<IWorkingSet> workingSets) {
+ super(name);
+ this.workingSets = workingSets;
+ }
+
+ @Override
+ public final IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
+ setProperty(IProgressConstants.ACTION_PROPERTY, new OpenMavenConsoleAction());
+ List<IProject> projects = doCreateMavenProjects(monitor);
+ if(projects != null) {
+ for(IProject project : projects) {
+ addToWorkingSets(project, workingSets);
+ }
+ }
+ return Status.OK_STATUS;
+ }
+
+ protected abstract List<IProject> doCreateMavenProjects(IProgressMonitor monitor) throws CoreException;
+
+ // PlatformUI.getWorkbench().getWorkingSetManager().addToWorkingSets(project, new IWorkingSet[] {workingSet});
+ public static void addToWorkingSets(IProject project, List<IWorkingSet> workingSets) {
+ if(workingSets != null && workingSets.size() > 0) {
+ // IAdaptable[] elements = workingSet.adaptElements(new IAdaptable[] {project});
+ // if(elements.length == 1) {
+ for(IWorkingSet workingSet : workingSets) {
+ if (workingSet!=null) {
+ IAdaptable[] oldElements = workingSet.getElements();
+ IAdaptable[] newElements = new IAdaptable[oldElements.length + 1];
+ System.arraycopy(oldElements, 0, newElements, 0, oldElements.length);
+ newElements[oldElements.length] = project;
+ workingSet.setElements(newElements);
+ }
+ }
+ }
+ }
+
+ protected static ArrayList<IProject> toProjects(List<IMavenProjectImportResult> results) {
+ ArrayList<IProject> projects = new ArrayList<IProject>();
+ for (IMavenProjectImportResult result : results) {
+ if (result.getProject()!=null) {
+ projects.add(result.getProject());
+ }
+ }
+ return projects;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/AbstractMavenProjectWizard.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/AbstractMavenProjectWizard.java
new file mode 100644
index 00000000..74a272cb
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/AbstractMavenProjectWizard.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.core.ui.internal.actions.SelectionUtil;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkingSet;
+
+
+public abstract class AbstractMavenProjectWizard extends Wizard {
+
+ protected IStructuredSelection selection;
+
+ protected ProjectImportConfiguration importConfiguration;
+
+ protected List<IWorkingSet> workingSets = new ArrayList<IWorkingSet>();
+
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ this.selection = selection;
+ this.importConfiguration = new ProjectImportConfiguration();
+ this.workingSets.add(SelectionUtil.getSelectedWorkingSet(selection));
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/AbstractMavenWizardPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/AbstractMavenWizardPage.java
new file mode 100644
index 00000000..9b065a8b
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/AbstractMavenWizardPage.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.DialogSettings;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+
+
+/**
+ * AbstractMavenImportWizardPage
+ *
+ * @author Eugene Kuleshov
+ */
+public abstract class AbstractMavenWizardPage extends WizardPage {
+
+ /** the history limit */
+ protected static final int MAX_HISTORY = 15;
+
+ /**
+ * The project import configuration
+ */
+ private ProjectImportConfiguration importConfiguration;
+
+ /** The resolver configuration panel */
+ protected ResolverConfigurationComponent resolverConfigurationComponent;
+
+ /** dialog settings to store input history */
+ protected IDialogSettings dialogSettings;
+
+ /** the Map of field ids to List of comboboxes that share the same history */
+ private Map<String, List<Combo>> fieldsWithHistory;
+
+ private boolean isHistoryLoaded = false;
+
+ /** @wbp.parser.constructor */
+ protected AbstractMavenWizardPage(String pageName) {
+ this(pageName, null);
+ }
+
+ /**
+ * Creates a page. This constructor should be used for the wizards where you need to have the advanced settings box on
+ * each page. Pass the same bean to each page so they can share the data.
+ */
+ protected AbstractMavenWizardPage(String pageName, ProjectImportConfiguration importConfiguration) {
+ super(pageName);
+ this.importConfiguration = importConfiguration;
+
+ fieldsWithHistory = new HashMap<String, List<Combo>>();
+
+ initDialogSettings();
+ }
+
+ public ProjectImportConfiguration getImportConfiguration() {
+ return this.importConfiguration;
+ }
+
+ /** Creates an advanced settings panel. */
+ protected void createAdvancedSettings(Composite composite, GridData gridData) {
+ if(importConfiguration != null) {
+// Label separator = new Label(composite, SWT.HORIZONTAL | SWT.SEPARATOR);
+// GridData separatorData = new GridData(SWT.FILL, SWT.TOP, false, false, gridData.horizontalSpan, 1);
+// separatorData.verticalIndent = 7;
+// separator.setLayoutData(separatorData);
+ gridData.verticalIndent = 7;
+
+ resolverConfigurationComponent = new ResolverConfigurationComponent(composite, importConfiguration, true);
+ resolverConfigurationComponent.setLayoutData(gridData);
+ addFieldWithHistory("projectNameTemplate", resolverConfigurationComponent.template); //$NON-NLS-1$
+ }
+ }
+
+ /** Loads the advanced settings data when the page is displayed. */
+ public void setVisible(boolean visible) {
+ if(visible) {
+ if(!isHistoryLoaded) {
+ // load data before history kicks in
+ if(resolverConfigurationComponent != null) {
+ resolverConfigurationComponent.loadData();
+ }
+ loadInputHistory();
+ isHistoryLoaded = true;
+ } else {
+ saveInputHistory();
+ }
+ if(resolverConfigurationComponent != null) {
+ resolverConfigurationComponent.loadData();
+ }
+ }
+ super.setVisible(visible);
+ }
+
+ /** Saves the history when the page is disposed. */
+ public void dispose() {
+ saveInputHistory();
+ super.dispose();
+ }
+
+ /** Loads the dialog settings using the page name as a section name. */
+ private void initDialogSettings() {
+ IDialogSettings pluginSettings;
+
+ // This is strictly to get SWT Designer working locally without blowing up.
+ if( MavenPlugin.getDefault() == null ) {
+ pluginSettings = new DialogSettings("Workbench");
+ }
+ else {
+ pluginSettings = M2EUIPluginActivator.getDefault().getDialogSettings();
+ }
+
+ dialogSettings = pluginSettings.getSection(getName());
+ if(dialogSettings == null) {
+ dialogSettings = pluginSettings.addNewSection(getName());
+ pluginSettings.addSection(dialogSettings);
+ }
+ }
+
+ /** Loads the input history from the dialog settings. */
+ private void loadInputHistory() {
+ for(Map.Entry<String, List<Combo>> e : fieldsWithHistory.entrySet()) {
+ String id = e.getKey();
+ String[] items = dialogSettings.getArray(id);
+ if(items != null) {
+ for(Combo combo : e.getValue()) {
+ String text = combo.getText();
+ combo.setItems(items);
+ if(text.length() > 0) {
+ // setItems() clears the text input, so we need to restore it
+ combo.setText(text);
+ }
+ }
+ }
+ }
+ }
+
+ /** Saves the input history into the dialog settings. */
+ private void saveInputHistory() {
+ for(Map.Entry<String, List<Combo>> e : fieldsWithHistory.entrySet()) {
+ String id = e.getKey();
+
+ Set<String> history = new LinkedHashSet<String>(MAX_HISTORY);
+
+ for(Combo combo : e.getValue()) {
+ String lastValue = combo.getText();
+ if(lastValue != null && lastValue.trim().length() > 0) {
+ history.add(lastValue);
+ }
+ }
+
+ Combo combo = e.getValue().iterator().next();
+ String[] items = combo.getItems();
+ for(int j = 0; j < items.length && history.size() < MAX_HISTORY; j++ ) {
+ history.add(items[j]);
+ }
+
+ dialogSettings.put(id, history.toArray(new String[history.size()]));
+ }
+ }
+
+ /** Adds an input control to the list of fields to save. */
+ protected void addFieldWithHistory(String id, Combo combo) {
+ if(combo != null) {
+ List<Combo> combos = fieldsWithHistory.get(id);
+ if(combos == null) {
+ combos = new ArrayList<Combo>();
+ fieldsWithHistory.put(id, combos);
+ }
+ combos.add(combo);
+ }
+ }
+
+ protected String validateIdInput(String text, String id) {
+ if(text == null || text.length() == 0) {
+ return Messages.getString("wizard.project.page.maven2.validator." + id + "ID"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if(text.contains(" ")) { //$NON-NLS-1$
+ return Messages.getString("wizard.project.page.maven2.validator." + id + "IDnospaces"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ IStatus nameStatus = ResourcesPlugin.getWorkspace().validateName(text, IResource.PROJECT);
+ if(!nameStatus.isOK()) {
+ return Messages.getString("wizard.project.page.maven2.validator." + id + "IDinvalid", nameStatus.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if(!text.matches("[A-Za-z0-9_\\-.]+")) { //$NON-NLS-1$
+ return Messages.getString("wizard.project.page.maven2.validator." + id + "IDinvalid", text); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ return null;
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/CustomArchetypeDialog.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/CustomArchetypeDialog.java
new file mode 100644
index 00000000..28c0ecb5
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/CustomArchetypeDialog.java
@@ -0,0 +1,251 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.DialogSettings;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Custom Archetype dialog
+ *
+ * @author Eugene Kuleshov
+ */
+public class CustomArchetypeDialog extends TitleAreaDialog {
+
+ private static final String DIALOG_SETTINGS = CustomArchetypeDialog.class.getName();
+
+ private static final String KEY_ARCHETYPE_GROUP_ID = "archetypeGroupId"; //$NON-NLS-1$
+
+ private static final String KEY_ARCHETYPE_ARTIFACT_ID = "archetypeArtifactId"; //$NON-NLS-1$
+
+ private static final String KEY_ARCHETYPE_VERSION = "archetypeVersion"; //$NON-NLS-1$
+
+ private static final String KEY_REPOSITORY_URL = "repositoryUrl"; //$NON-NLS-1$
+
+ private static final int MAX_HISTORY = 15;
+
+ private String title;
+
+ private String message;
+
+ private Combo archetypeGroupIdCombo;
+
+ private Combo archetypeArtifactIdCombo;
+
+ private Combo archetypeVersionCombo;
+
+ private Combo repositoryCombo;
+
+ private IDialogSettings dialogSettings;
+
+ private String archetypeArtifactId;
+
+ private String archetypeGroupId;
+
+ private String archetypeVersion;
+
+ private String repositoryUrl;
+
+ protected CustomArchetypeDialog(Shell shell, String title) {
+ super(shell);
+ this.title = title;
+ this.message = Messages.CustomArchetypeDialog_message;
+ setShellStyle(SWT.DIALOG_TRIM);
+
+ IDialogSettings pluginSettings = M2EUIPluginActivator.getDefault().getDialogSettings();
+ dialogSettings = pluginSettings.getSection(DIALOG_SETTINGS);
+ if(dialogSettings == null) {
+ dialogSettings = new DialogSettings(DIALOG_SETTINGS);
+ pluginSettings.addSection(dialogSettings);
+ }
+ }
+
+ protected Control createContents(Composite parent) {
+ Control control = super.createContents(parent);
+ setTitle(title);
+ setMessage(message);
+ return control;
+ }
+
+ protected Control createDialogArea(Composite parent) {
+ Composite composite1 = (Composite) super.createDialogArea(parent);
+
+ Composite composite = new Composite(composite1, SWT.NONE);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.marginTop = 7;
+ gridLayout.marginWidth = 12;
+ gridLayout.numColumns = 2;
+ composite.setLayout(gridLayout);
+
+ Label archetypeGroupIdLabel = new Label(composite, SWT.NONE);
+ archetypeGroupIdLabel.setText(Messages.CustomArchetypeDialog_lblArchetypegroupId);
+
+ archetypeGroupIdCombo = new Combo(composite, SWT.NONE);
+ GridData archetypeGroupIdComboData = new GridData(SWT.FILL, SWT.CENTER, true, false);
+ archetypeGroupIdComboData.widthHint = 350;
+ archetypeGroupIdCombo.setLayoutData(archetypeGroupIdComboData);
+ archetypeGroupIdCombo.setItems(getSavedValues(KEY_ARCHETYPE_GROUP_ID));
+ archetypeGroupIdCombo.setData("name", "archetypeGroupId"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ Label archetypeArtifactIdLabel = new Label(composite, SWT.NONE);
+ archetypeArtifactIdLabel.setText(Messages.CustomArchetypeDialog_lblArchetypeartifactid);
+
+ archetypeArtifactIdCombo = new Combo(composite, SWT.NONE);
+ archetypeArtifactIdCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ archetypeArtifactIdCombo.setItems(getSavedValues(KEY_ARCHETYPE_ARTIFACT_ID));
+ archetypeArtifactIdCombo.setData("name", "archetypeArtifactId"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ Label archetypeVersionLabel = new Label(composite, SWT.NONE);
+ archetypeVersionLabel.setText(Messages.CustomArchetypeDialog_lblArchetypeversion);
+
+ archetypeVersionCombo = new Combo(composite, SWT.NONE);
+ archetypeVersionCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ archetypeVersionCombo.setItems(getSavedValues(KEY_ARCHETYPE_VERSION));
+ archetypeVersionCombo.setData("name", "archetypeVersion"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ Label repositoryLabel = new Label(composite, SWT.NONE);
+ repositoryLabel.setText(Messages.CustomArchetypeDialog_lblRepo);
+
+ repositoryCombo = new Combo(composite, SWT.NONE);
+ repositoryCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ repositoryCombo.setItems(getSavedValues(KEY_REPOSITORY_URL));
+ repositoryCombo.setData("name", "repository"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ ModifyListener modifyListener = new ModifyListener() {
+ public void modifyText(final ModifyEvent e) {
+ update();
+ }
+ };
+
+ archetypeGroupIdCombo.addModifyListener(modifyListener);
+ archetypeArtifactIdCombo.addModifyListener(modifyListener);
+ archetypeVersionCombo.addModifyListener(modifyListener);
+ repositoryCombo.addModifyListener(modifyListener);
+
+// fullIndexButton = new Button(composite, SWT.CHECK);
+// fullIndexButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
+// fullIndexButton.setText("&Full Index");
+// fullIndexButton.setSelection(true);
+
+ return composite;
+ }
+
+ private String[] getSavedValues(String key) {
+ String[] array = dialogSettings.getArray(key);
+ return array == null ? new String[0] : array;
+ }
+
+ protected void configureShell(Shell shell) {
+ super.configureShell(shell);
+ shell.setText(title);
+ }
+
+ public void create() {
+ super.create();
+ getButton(IDialogConstants.OK_ID).setEnabled(false);
+ }
+
+ protected void okPressed() {
+ archetypeArtifactId = archetypeArtifactIdCombo.getText().trim();
+ archetypeGroupId = archetypeGroupIdCombo.getText().trim();
+ archetypeVersion = archetypeVersionCombo.getText().trim();
+ repositoryUrl = repositoryCombo.getText().trim();
+
+ saveValue(KEY_ARCHETYPE_GROUP_ID, archetypeGroupId);
+ saveValue(KEY_ARCHETYPE_ARTIFACT_ID, archetypeArtifactId);
+ saveValue(KEY_ARCHETYPE_VERSION, archetypeVersion);
+ saveValue(KEY_REPOSITORY_URL, repositoryUrl);
+
+ super.okPressed();
+ }
+
+ public String getArchetypeGroupId() {
+ return archetypeGroupId;
+ }
+
+ public String getArchetypeArtifactId() {
+ return archetypeArtifactId;
+ }
+
+ public String getArchetypeVersion() {
+ return archetypeVersion;
+ }
+
+ public String getRepositoryUrl() {
+ return repositoryUrl;
+ }
+
+ private void saveValue(String key, String value) {
+ List<String> dirs = new ArrayList<String>();
+ dirs.addAll(Arrays.asList(getSavedValues(key)));
+
+ dirs.remove(value);
+ dirs.add(0, value);
+
+ if(dirs.size() > MAX_HISTORY) {
+ dirs = dirs.subList(0, MAX_HISTORY);
+ }
+
+ dialogSettings.put(key, dirs.toArray(new String[dirs.size()]));
+ }
+
+ void update() {
+ boolean isValid = isValid();
+ // verifyButton.setEnabled(isValid);
+ getButton(IDialogConstants.OK_ID).setEnabled(isValid);
+ }
+
+ private boolean isValid() {
+ setErrorMessage(null);
+ setMessage(null, IStatus.WARNING);
+
+ if(archetypeGroupIdCombo.getText().trim().length()==0) {
+ setErrorMessage(Messages.CustomArchetypeDialog_error_grid);
+ return false;
+ }
+
+ if(archetypeArtifactIdCombo.getText().trim().length()==0) {
+ setErrorMessage(Messages.CustomArchetypeDialog_error_artid);
+ return false;
+ }
+
+ if(archetypeVersionCombo.getText().trim().length()==0) {
+ setErrorMessage(Messages.CustomArchetypeDialog_error_version);
+ return false;
+ }
+
+ // TODO check if archetype available locally
+
+ return true;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenArtifactComponent.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenArtifactComponent.java
new file mode 100644
index 00000000..5ebdb92f
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenArtifactComponent.java
@@ -0,0 +1,267 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import org.apache.maven.model.Model;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+
+public class MavenArtifactComponent extends Composite {
+
+ public static final String JAR = "jar"; //$NON-NLS-1$
+
+ public static final String WAR = "war"; //$NON-NLS-1$
+
+ public static final String EAR = "ear"; //$NON-NLS-1$
+
+ public static final String RAR = "rar"; //$NON-NLS-1$
+
+ public static final String POM = "pom"; //$NON-NLS-1$
+
+ // MNGECLIPSE-688 add EJB Support
+ public static final String EJB = "ejb"; //$NON-NLS-1$
+
+ public static final String[] PACKAGING_OPTIONS = {JAR, POM, WAR };
+
+ public static final String DEFAULT_PACKAGING = JAR;
+
+ public static final String DEFAULT_VERSION = "0.0.1-SNAPSHOT"; //$NON-NLS-1$
+
+ /** group id text field */
+ protected Combo groupIdCombo;
+
+ /** artifact id text field */
+ protected Combo artifactIdCombo;
+
+ /** version text field */
+ protected Combo versionCombo;
+
+ /** packaging options combobox */
+ protected Combo packagingCombo;
+
+ /** name text field */
+ protected Combo nameCombo;
+
+ /** description text field */
+ protected Text descriptionText;
+
+ private ModifyListener modifyingListener;
+
+ private Label groupIdlabel;
+
+ private Label artifactIdLabel;
+
+ private Label versionLabel;
+
+ private Label packagingLabel;
+
+ private Label nameLabel;
+
+ private Label descriptionLabel;
+
+ /** Creates a new component. */
+ public MavenArtifactComponent(Composite parent, int styles) {
+ super(parent, styles);
+
+ GridLayout layout = new GridLayout();
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ layout.numColumns = 2;
+ setLayout(layout);
+
+ Group artifactGroup = new Group(this, SWT.NONE);
+ artifactGroup.setText(Messages.getString("artifactComponent.artifact")); //$NON-NLS-1$
+ GridData gd_artifactGroup = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
+ artifactGroup.setLayoutData(gd_artifactGroup);
+ artifactGroup.setLayout(new GridLayout(2, false));
+
+ groupIdlabel = new Label(artifactGroup, SWT.NONE);
+ groupIdlabel.setText(Messages.getString("artifactComponent.groupId")); //$NON-NLS-1$
+
+ groupIdCombo = new Combo(artifactGroup, SWT.BORDER);
+ groupIdCombo.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false));
+ groupIdCombo.setData("name", "groupIdCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ artifactIdLabel = new Label(artifactGroup, SWT.NONE);
+ artifactIdLabel.setText(Messages.getString("artifactComponent.artifactId")); //$NON-NLS-1$
+
+ artifactIdCombo = new Combo(artifactGroup, SWT.BORDER);
+ artifactIdCombo.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false));
+ artifactIdCombo.setData("name", "artifactIdCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ versionLabel = new Label(artifactGroup, SWT.NONE);
+ versionLabel.setText(Messages.getString("artifactComponent.version")); //$NON-NLS-1$
+
+ versionCombo = new Combo(artifactGroup, SWT.BORDER);
+ versionCombo.setLayoutData(new GridData(150, SWT.DEFAULT));
+ versionCombo.setText(DEFAULT_VERSION);
+ versionCombo.setData("name", "versionCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ packagingLabel = new Label(artifactGroup, SWT.NONE);
+ packagingLabel.setText(Messages.getString("artifactComponent.packaging")); //$NON-NLS-1$
+
+ packagingCombo = new Combo(artifactGroup, SWT.NONE);
+ packagingCombo.setItems(PACKAGING_OPTIONS);
+ packagingCombo.setText(DEFAULT_PACKAGING);
+ packagingCombo.setLayoutData(new GridData(150, SWT.DEFAULT));
+ packagingCombo.setData("name", "packagingCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ nameLabel = new Label(artifactGroup, SWT.NONE);
+ nameLabel.setLayoutData(new GridData());
+ nameLabel.setText(Messages.getString("artifactComponent.name")); //$NON-NLS-1$
+
+ nameCombo = new Combo(artifactGroup, SWT.BORDER);
+ nameCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ nameCombo.setData("name", "nameCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ descriptionLabel = new Label(artifactGroup, SWT.NONE);
+ descriptionLabel.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false));
+ descriptionLabel.setText(Messages.getString("artifactComponent.description")); //$NON-NLS-1$
+
+ descriptionText = new Text(artifactGroup, SWT.V_SCROLL | SWT.BORDER | SWT.WRAP);
+ GridData gd_descriptionText = new GridData(SWT.FILL, SWT.FILL, false, true);
+ gd_descriptionText.minimumHeight = 20;
+ descriptionText.setLayoutData(gd_descriptionText);
+ descriptionText.setData("name", "descriptionText"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public void setModifyingListener(ModifyListener modifyingListener) {
+ this.modifyingListener = modifyingListener;
+
+ groupIdCombo.addModifyListener(modifyingListener);
+ artifactIdCombo.addModifyListener(modifyingListener);
+ versionCombo.addModifyListener(modifyingListener);
+ packagingCombo.addModifyListener(modifyingListener);
+ }
+
+ public void dispose() {
+ super.dispose();
+
+ if(modifyingListener != null) {
+ groupIdCombo.removeModifyListener(modifyingListener);
+ artifactIdCombo.removeModifyListener(modifyingListener);
+ versionCombo.removeModifyListener(modifyingListener);
+ packagingCombo.removeModifyListener(modifyingListener);
+ }
+ }
+
+ public String getModelName() {
+ return nameCombo.getText();
+ }
+
+ public String getArtifactId() {
+ return this.artifactIdCombo.getText();
+ }
+
+ public String getGroupId() {
+ return this.groupIdCombo.getText();
+ }
+
+ public String getVersion() {
+ return this.versionCombo.getText();
+ }
+
+ public String getPackaging() {
+ return packagingCombo.getText();
+ }
+
+ public String getDescription() {
+ return descriptionText.getText();
+ }
+
+ public void setModelName(String name) {
+ nameCombo.setText(name);
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupIdCombo.setText(groupId);
+ }
+
+ public void setArtifactId(String artifact) {
+ this.artifactIdCombo.setText(artifact);
+ }
+
+ public void setVersion(String version) {
+ versionCombo.setText(version);
+ }
+
+ public void setPackaging(String packaging) {
+ if(packagingCombo != null) {
+ packagingCombo.setText(packaging);
+ }
+ }
+
+ public void setDescription(String description) {
+ if(descriptionText != null) {
+ descriptionText.setText(description);
+ }
+ }
+
+ public Model getModel() {
+ Model model = new Model();
+ model.setModelVersion("4.0.0"); //$NON-NLS-1$
+
+ model.setGroupId(getGroupId());
+ model.setArtifactId(getArtifactId());
+ model.setVersion(getVersion());
+ model.setPackaging(getPackaging());
+
+ if(getModelName().length()>0) {
+ model.setName(getModelName());
+ }
+ if(getDescription().length()>0) {
+ model.setDescription(getDescription());
+ }
+
+ return model;
+ }
+
+ /** Enables or disables the artifact id text field. */
+ public void setArtifactIdEditable(boolean b) {
+ artifactIdCombo.setEnabled(b);
+ }
+
+ public Combo getGroupIdCombo() {
+ return groupIdCombo;
+ }
+
+ public Combo getArtifactIdCombo() {
+ return artifactIdCombo;
+ }
+
+ public Combo getVersionCombo() {
+ return versionCombo;
+ }
+
+ public Combo getNameCombo() {
+ return nameCombo;
+ }
+
+ public void setWidthGroup(WidthGroup widthGroup) {
+ widthGroup.addControl(this.groupIdlabel);
+ widthGroup.addControl(this.artifactIdLabel);
+ widthGroup.addControl(this.versionLabel);
+ widthGroup.addControl(this.packagingLabel);
+ widthGroup.addControl(this.nameLabel);
+ widthGroup.addControl(this.descriptionLabel);
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenCheckoutLocationPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenCheckoutLocationPage.java
new file mode 100644
index 00000000..33c26a4a
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenCheckoutLocationPage.java
@@ -0,0 +1,422 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.maven.model.Scm;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.wizard.IWizardContainer;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.scm.ScmHandlerFactory;
+import org.eclipse.m2e.scm.ScmHandlerUi;
+import org.eclipse.m2e.scm.ScmTag;
+import org.eclipse.m2e.scm.ScmUrl;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+
+/**
+ * @author Eugene Kuleshov
+ */
+public class MavenCheckoutLocationPage extends AbstractMavenWizardPage {
+
+ String scmType;
+ ScmUrl[] scmUrls;
+ String scmParentUrl;
+
+ Combo scmTypeCombo;
+
+ Combo scmUrlCombo;
+
+ Button scmUrlBrowseButton;
+
+ Button headRevisionButton;
+
+ Label revisionLabel;
+
+ Text revisionText;
+
+ Button revisionBrowseButton;
+
+ private Button checkoutAllProjectsButton;
+
+ protected MavenCheckoutLocationPage(ProjectImportConfiguration projectImportConfiguration) {
+ super("MavenCheckoutLocationPage", projectImportConfiguration);
+ setTitle(Messages.MavenCheckoutLocationPage_title);
+ setDescription(Messages.MavenCheckoutLocationPage_description);
+ }
+
+ public void createControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout gridLayout = new GridLayout(5, false);
+ gridLayout.verticalSpacing = 0;
+ composite.setLayout(gridLayout);
+ setControl(composite);
+
+ SelectionAdapter selectionAdapter = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ updatePage();
+ }
+ };
+
+ if(scmUrls == null || scmUrls.length < 2) {
+ Label urlLabel = new Label(composite, SWT.NONE);
+ urlLabel.setText(Messages.MavenCheckoutLocationPage_lblurl);
+
+ scmTypeCombo = new Combo(composite, SWT.READ_ONLY);
+ GridData gd_scmTypeCombo = new GridData(SWT.FILL, SWT.CENTER, false, false);
+ gd_scmTypeCombo.widthHint = 80;
+ scmTypeCombo.setLayoutData(gd_scmTypeCombo);
+ scmTypeCombo.setData("name", "mavenCheckoutLocation.typeCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+ String[] types = ScmHandlerFactory.getTypes();
+ for(int i = 0; i < types.length; i++ ) {
+ scmTypeCombo.add(types[i]);
+ }
+ scmTypeCombo.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ String newScmType = scmTypeCombo.getText();
+ if(!newScmType.equals(scmType)) {
+ scmType = newScmType;
+ scmUrlCombo.setText(""); //$NON-NLS-1$
+ updatePage();
+ }
+ }
+ });
+
+ if(scmUrls!=null && scmUrls.length == 1) {
+ try {
+ scmType = ScmUrl.getType(scmUrls[0].getUrl());
+ } catch(CoreException ex) {
+ }
+ }
+
+ scmUrlCombo = new Combo(composite, SWT.NONE);
+ scmUrlCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+ scmUrlCombo.setData("name", "mavenCheckoutLocation.urlCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ scmUrlBrowseButton = new Button(composite, SWT.NONE);
+ scmUrlBrowseButton.setText(Messages.MavenCheckoutLocationPage_btnBrowse);
+ }
+
+ headRevisionButton = new Button(composite, SWT.CHECK);
+ GridData headRevisionButtonData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 5, 1);
+ headRevisionButtonData.verticalIndent = 5;
+ headRevisionButton.setLayoutData(headRevisionButtonData);
+ headRevisionButton.setText(Messages.MavenCheckoutLocationPage_btnHead);
+ headRevisionButton.setSelection(true);
+ headRevisionButton.addSelectionListener(selectionAdapter);
+
+ revisionLabel = new Label(composite, SWT.RADIO);
+ GridData revisionButtonData = new GridData();
+ revisionButtonData.horizontalIndent = 10;
+ revisionLabel.setLayoutData(revisionButtonData);
+ revisionLabel.setText(Messages.MavenCheckoutLocationPage_lblRevision);
+ // revisionButton.addSelectionListener(selectionAdapter);
+
+ revisionText = new Text(composite, SWT.BORDER);
+ GridData revisionTextData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1);
+ revisionTextData.widthHint = 115;
+ revisionTextData.verticalIndent = 3;
+ revisionText.setLayoutData(revisionTextData);
+
+ if(scmUrls != null) {
+ ScmTag tag = scmUrls[0].getTag();
+ if(tag!=null) {
+ headRevisionButton.setSelection(false);
+ revisionText.setText(tag.getName());
+ }
+ }
+
+ revisionText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ updatePage();
+ }
+ });
+
+ revisionBrowseButton = new Button(composite, SWT.NONE);
+ GridData gd_revisionBrowseButton = new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1);
+ gd_revisionBrowseButton.verticalIndent = 3;
+ revisionBrowseButton.setLayoutData(gd_revisionBrowseButton);
+ revisionBrowseButton.setText(Messages.MavenCheckoutLocationPage_btnRevSelect);
+ revisionBrowseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ String url = scmParentUrl;
+ if(url==null) {
+ return;
+ }
+
+ String scmType = scmTypeCombo.getText();
+
+ ScmHandlerUi handlerUi = ScmHandlerFactory.getHandlerUiByType(scmType);
+ String revision = handlerUi.selectRevision(getShell(), scmUrls[0], revisionText.getText());
+ if(revision!=null) {
+ revisionText.setText(revision);
+ headRevisionButton.setSelection(false);
+ updatePage();
+ }
+ }
+ });
+
+ checkoutAllProjectsButton = new Button(composite, SWT.CHECK);
+ GridData checkoutAllProjectsData = new GridData(SWT.LEFT, SWT.TOP, true, false, 5, 1);
+ checkoutAllProjectsData.verticalIndent = 10;
+ checkoutAllProjectsButton.setLayoutData(checkoutAllProjectsData);
+ checkoutAllProjectsButton.setText(Messages.MavenCheckoutLocationPage_btnCheckout);
+ checkoutAllProjectsButton.setSelection(true);
+ checkoutAllProjectsButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ updatePage();
+ }
+ });
+
+ GridData advancedSettingsData = new GridData(SWT.FILL, SWT.TOP, true, false, 5, 1);
+ advancedSettingsData.verticalIndent = 10;
+ createAdvancedSettings(composite, advancedSettingsData);
+
+ if(scmUrls!=null && scmUrls.length == 1) {
+ scmTypeCombo.setText(scmType == null ? "" : scmType); //$NON-NLS-1$
+ scmUrlCombo.setText(scmUrls[0].getProviderUrl());
+ }
+
+ if(scmUrls == null || scmUrls.length < 2) {
+ scmUrlBrowseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ ScmHandlerUi handlerUi = ScmHandlerFactory.getHandlerUiByType(scmType);
+ // XXX should use null if there is no scmUrl selected
+ ScmUrl currentUrl = scmUrls==null || scmUrls.length==0 ? new ScmUrl("scm:" + scmType + ":") : scmUrls[0]; //$NON-NLS-1$ //$NON-NLS-2$
+ ScmUrl scmUrl = handlerUi.selectUrl(getShell(), currentUrl);
+ if(scmUrl!=null) {
+ scmUrlCombo.setText(scmUrl.getProviderUrl());
+ if(scmUrls==null) {
+ scmUrls = new ScmUrl[1];
+ }
+ scmUrls[0] = scmUrl;
+ scmParentUrl = scmUrl.getUrl();
+ updatePage();
+ }
+ }
+ });
+
+ scmUrlCombo.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ final String url = scmUrlCombo.getText();
+ if(url.startsWith("scm:")) { //$NON-NLS-1$
+ try {
+ final String type = ScmUrl.getType(url);
+ scmTypeCombo.setText(type);
+ scmType = type;
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ scmUrlCombo.setText(url.substring(type.length() + 5));
+ }
+ });
+ } catch(CoreException ex) {
+ }
+ return;
+ }
+
+ if(scmUrls==null) {
+ scmUrls = new ScmUrl[1];
+ }
+
+ ScmUrl scmUrl = new ScmUrl("scm:" + scmType + ":" + url); //$NON-NLS-1$ //$NON-NLS-2$
+ scmUrls[0] = scmUrl;
+ scmParentUrl = scmUrl.getUrl();
+ updatePage();
+ }
+ });
+ }
+
+ updatePage();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.wizards.AbstractMavenWizardPage#setVisible(boolean)
+ */
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+
+ if(dialogSettings!=null && scmUrlCombo!=null) {
+ String[] items = dialogSettings.getArray("scmUrl"); //$NON-NLS-1$
+ if(items != null) {
+ String text = scmUrlCombo.getText();
+ scmUrlCombo.setItems(items);
+ if (text.length() > 0) {
+ // setItems() clears the text input, so we need to restore it
+ scmUrlCombo.setText(text);
+ }
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.wizards.AbstractMavenWizardPage#dispose()
+ */
+ public void dispose() {
+ if(dialogSettings != null && scmUrlCombo!=null) {
+ Set<String> history = new LinkedHashSet<String>(MAX_HISTORY);
+
+ String lastValue = scmUrlCombo.getText();
+ if ( lastValue!=null && lastValue.trim().length() > 0 ) {
+ history.add("scm:" + scmType + ":" + lastValue); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ String[] items = scmUrlCombo.getItems();
+ for(int j = 0; j < items.length && history.size() < MAX_HISTORY; j++ ) {
+ history.add(items[j]);
+ }
+
+ dialogSettings.put("scmUrl", history.toArray(new String[history.size()])); //$NON-NLS-1$
+ }
+
+ super.dispose();
+ }
+
+ public IWizardContainer getContainer() {
+ return super.getContainer();
+ }
+
+ void updatePage() {
+ boolean canSelectUrl = false ;
+ boolean canSelectRevision = false;
+ ScmHandlerUi handlerUi = ScmHandlerFactory.getHandlerUiByType(scmType);
+ if(handlerUi!=null) {
+ canSelectUrl = handlerUi.canSelectUrl();
+ canSelectRevision = handlerUi.canSelectRevision();
+ }
+
+ if(scmUrlBrowseButton!=null) {
+ scmUrlBrowseButton.setEnabled(canSelectUrl);
+ }
+
+ revisionBrowseButton.setEnabled(canSelectRevision);
+
+ boolean isHeadRevision = isHeadRevision();
+ revisionLabel.setEnabled(!isHeadRevision);
+ revisionText.setEnabled(!isHeadRevision);
+
+ setPageComplete(isPageValid());
+ }
+
+ private boolean isPageValid() {
+ setErrorMessage(null);
+
+ if(scmUrls != null && scmUrls.length < 2) {
+ if(scmType == null) {
+ setErrorMessage(Messages.MavenCheckoutLocationPage_error_empty);
+ return false;
+ }
+ }
+
+ ScmHandlerUi handlerUi = ScmHandlerFactory.getHandlerUiByType(scmType);
+
+ if(scmUrls == null || scmUrls.length < 2) {
+ if(scmUrls == null || scmUrls.length == 0) {
+ setErrorMessage(Messages.MavenCheckoutLocationPage_error_empty_url);
+ return false;
+ }
+
+ if(handlerUi!=null && !handlerUi.isValidUrl(scmUrls[0].getUrl())) {
+ setErrorMessage(Messages.MavenCheckoutLocationPage_error_url_empty);
+ return false;
+ }
+ }
+
+ if(!isHeadRevision()) {
+ String revision = revisionText.getText().trim();
+ if(revision.length()==0) {
+ setErrorMessage(Messages.MavenCheckoutLocationPage_error_scm_empty);
+ return false;
+ }
+
+ if(handlerUi!=null && !handlerUi.isValidRevision(null, revision)) {
+ setErrorMessage(Messages.MavenCheckoutLocationPage_error_scm_invalid);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public void setParent(String parentUrl) {
+ this.scmParentUrl = parentUrl;
+ }
+
+ public void setUrls(ScmUrl[] urls) {
+ this.scmUrls = urls;
+ }
+
+ public ScmUrl[] getUrls() {
+ return scmUrls;
+ }
+
+ public Scm[] getScms() {
+ if(scmUrls==null) {
+ return new Scm[0];
+ }
+
+ String revision = getRevision();
+ Scm[] scms = new Scm[scmUrls.length];
+ for(int i = 0; i < scms.length; i++ ) {
+ Scm scm = new Scm();
+ scm.setConnection(scmUrls[i].getUrl());
+ scm.setTag(revision);
+ scms[i] = scm;
+ }
+ return scms;
+ }
+
+ public boolean isCheckoutAllProjects() {
+ return checkoutAllProjectsButton.getSelection();
+ }
+
+ public boolean isHeadRevision() {
+ return headRevisionButton.getSelection();
+ }
+
+ public String getRevision() {
+ if(isHeadRevision()) {
+ return "HEAD"; //$NON-NLS-1$
+ }
+ return revisionText.getText().trim();
+ }
+
+ public void addListener(final SelectionListener listener) {
+ ModifyListener listenerProxy = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ Event event = new Event();
+ event.widget = e.widget;
+ listener.widgetSelected(new SelectionEvent(event));
+ }
+ };
+ scmUrlCombo.addModifyListener(listenerProxy);
+ revisionText.addModifyListener(listenerProxy);
+ headRevisionButton.addSelectionListener(listener);
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenCheckoutWizard.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenCheckoutWizard.java
new file mode 100644
index 00000000..1705d282
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenCheckoutWizard.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.maven.model.Scm;
+import org.eclipse.core.runtime.IAdapterManager;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.MavenProjectScmInfo;
+import org.eclipse.m2e.core.ui.internal.actions.SelectionUtil;
+import org.eclipse.m2e.scm.ScmUrl;
+import org.eclipse.ui.IImportWizard;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+
+
+/**
+ * Maven checkout wizard
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenCheckoutWizard extends AbstractMavenProjectWizard implements IImportWizard, INewWizard {
+
+ private ScmUrl[] urls;
+
+ private String parentUrl;
+
+ private MavenCheckoutLocationPage scheckoutPage;
+
+ private MavenProjectWizardLocationPage locationPage;
+
+ public MavenCheckoutWizard() {
+ this(null);
+ setNeedsProgressMonitor(true);
+ }
+
+ public MavenCheckoutWizard(ScmUrl[] urls) {
+ setUrls(urls);
+ setNeedsProgressMonitor(true);
+ setWindowTitle(Messages.MavenCheckoutWizard_title);
+ }
+
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ super.init(workbench, selection);
+
+ this.selection = selection;
+
+ ArrayList<ScmUrl> urls = new ArrayList<ScmUrl>();
+ IAdapterManager adapterManager = Platform.getAdapterManager();
+ for(Iterator<?> it = selection.iterator(); it.hasNext();) {
+ ScmUrl url = (ScmUrl) adapterManager.getAdapter(it.next(), ScmUrl.class);
+ if(url != null) {
+ urls.add(url);
+ }
+ }
+ setUrls(urls.toArray(new ScmUrl[urls.size()]));
+ }
+
+ private void setUrls(ScmUrl[] urls) {
+ if(urls!=null && urls.length>0) {
+ this.urls = urls;
+ this.parentUrl = getParentUrl(urls);
+ }
+ }
+
+ private String getParentUrl(ScmUrl[] urls) {
+ if(urls.length==1) {
+ return urls[0].getUrl();
+ }
+
+ String parent = urls[0].getParentUrl();
+ for(int i = 1; parent!=null && i < urls.length; i++ ) {
+ String url = urls[i].getParentUrl();
+ if(!parent.equals(url)) {
+ parent = null;
+ }
+ }
+ return parent;
+ }
+
+ public void addPages() {
+ scheckoutPage = new MavenCheckoutLocationPage(importConfiguration);
+ scheckoutPage.setUrls(urls);
+ scheckoutPage.setParent(parentUrl);
+
+ locationPage = new MavenProjectWizardLocationPage(importConfiguration, //
+ Messages.MavenCheckoutWizard_location1,
+ Messages.MavenCheckoutWizard_location2, workingSets);
+ locationPage.setLocationPath(SelectionUtil.getSelectedLocation(selection));
+
+ addPage(scheckoutPage);
+ addPage(locationPage);
+ }
+
+// /** Adds the listeners after the page controls are created. */
+// public void createPageControls(Composite pageContainer) {
+// super.createPageControls(pageContainer);
+//
+// locationPage.addListener(new SelectionAdapter() {
+// public void widgetSelected(SelectionEvent e) {
+// projectsPage.setScms(locationPage.getScms(new NullProgressMonitor()));
+// }
+// });
+//
+// projectsPage.setScms(locationPage.getScms(new NullProgressMonitor()));
+// }
+
+ public boolean canFinish() {
+ if(scheckoutPage.isCheckoutAllProjects() && scheckoutPage.isPageComplete()) {
+ return true;
+ }
+ return super.canFinish();
+ }
+
+ public boolean performFinish() {
+ if(!canFinish()) {
+ return false;
+ }
+
+ final boolean checkoutAllProjects = scheckoutPage.isCheckoutAllProjects();
+
+ Scm[] scms = scheckoutPage.getScms();
+
+ final Collection<MavenProjectScmInfo> mavenProjects = new ArrayList<MavenProjectScmInfo>();
+ for(int i = 0; i < scms.length; i++ ) {
+ String url = scms[i].getConnection();
+ String revision = scms[i].getTag();
+
+ if(url.endsWith("/")) { //$NON-NLS-1$
+ url = url.substring(0, url.length()-1);
+ }
+
+ int n = url.lastIndexOf("/"); //$NON-NLS-1$
+ String label = (n == -1 ? url : url.substring(n)) + "/" + IMavenConstants.POM_FILE_NAME; //$NON-NLS-1$
+ MavenProjectScmInfo projectInfo = new MavenProjectScmInfo(label, null, //
+ null, revision, url, url);
+ mavenProjects.add(projectInfo);
+ }
+
+ MavenProjectCheckoutJob job = new MavenProjectCheckoutJob(importConfiguration, checkoutAllProjects, workingSets) {
+ protected Collection<MavenProjectScmInfo> getProjects(IProgressMonitor monitor) {
+ return mavenProjects;
+ }
+ };
+
+ if(!locationPage.isInWorkspace()) {
+ job.setLocation(locationPage.getLocationPath().toFile());
+ }
+
+ job.schedule();
+
+ return true;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenDependenciesWizardPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenDependenciesWizardPage.java
new file mode 100644
index 00000000..b5c4ba43
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenDependenciesWizardPage.java
@@ -0,0 +1,285 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.maven.model.Dependency;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.IWizardContainer;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.index.IndexedArtifact;
+import org.eclipse.m2e.core.index.IndexedArtifactFile;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+import org.eclipse.m2e.core.ui.internal.dialogs.MavenRepositorySearchDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * Wizard page for gathering information about Maven artifacts. Allows to select
+ * artifacts from the repository index.
+ */
+public class MavenDependenciesWizardPage extends AbstractMavenWizardPage {
+
+ /**
+ * Viewer containing dependencies
+ */
+ TableViewer dependencyViewer;
+
+ private Dependency[] dependencies;
+
+ /**
+ * Listeners notified about all changes
+ */
+ private List<ISelectionChangedListener> listeners = new ArrayList<ISelectionChangedListener>();
+
+ boolean showScope = false;
+
+ public MavenDependenciesWizardPage() {
+ this(null, Messages.getString("wizard.project.page.dependencies.title"), // //$NON-NLS-1$
+ Messages.getString("wizard.project.page.dependencies.description")); //$NON-NLS-1$
+ }
+
+ public MavenDependenciesWizardPage(ProjectImportConfiguration projectImportConfiguration, String title, String description) {
+ super("MavenDependenciesWizardPage", projectImportConfiguration); //$NON-NLS-1$
+ setTitle(title);
+ setDescription(description);
+ setPageComplete(true);
+ }
+
+ public void setShowScope(boolean showScope) {
+ this.showScope = showScope;
+ }
+
+ public void setDependencies(Dependency[] dependencies) {
+ this.dependencies = dependencies;
+ }
+
+ /**
+ * {@inheritDoc} This wizard page contains a <code>TableViewer</code> to display the currently included Maven2
+ * directories and a button area with buttons to add further dependencies or remove existing ones.
+ */
+ public void createControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NULL);
+ GridLayout layout = new GridLayout(3, false);
+ composite.setLayout(layout);
+
+ if(dependencies!=null) {
+ createArtifacts(composite);
+ }
+
+ createAdvancedSettings(composite, new GridData(SWT.FILL, SWT.TOP, false, false, 3, 1));
+
+ setControl(composite);
+
+ updatePage();
+ }
+
+ private void createArtifacts(Composite composite) {
+ Label mavenArtifactsLabel = new Label(composite, SWT.NONE);
+ mavenArtifactsLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
+ mavenArtifactsLabel.setText(org.eclipse.m2e.core.internal.Messages.MavenDependenciesWizardPage_lblArtifacts);
+
+ dependencyViewer = new TableViewer(composite, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
+ dependencyViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 2));
+ dependencyViewer.setUseHashlookup(true);
+ dependencyViewer.setLabelProvider(new ArtifactLabelProvider());
+ dependencyViewer.setComparator(new DependencySorter());
+ dependencyViewer.add(dependencies);
+
+ Button addDependencyButton = new Button(composite, SWT.PUSH);
+ GridData gd_addDependencyButton = new GridData(SWT.FILL, SWT.TOP, false, false);
+ addDependencyButton.setLayoutData(gd_addDependencyButton);
+ addDependencyButton.setText(Messages.getString("wizard.project.page.dependencies.add")); //$NON-NLS-1$
+
+ addDependencyButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ MavenRepositorySearchDialog dialog = MavenRepositorySearchDialog.createSearchDependencyDialog(getShell(), //
+ org.eclipse.m2e.core.internal.Messages.MavenDependenciesWizardPage_searchDialog_title, null, null, false);
+ if(dialog.open() == Window.OK) {
+ Object result = dialog.getFirstResult();
+ if(result instanceof IndexedArtifactFile) {
+ Dependency dependency = ((IndexedArtifactFile) result).getDependency();
+ dependency.setScope(dialog.getSelectedScope());
+ dependencyViewer.add(dependency);
+ notifyListeners();
+ } else if(result instanceof IndexedArtifact) {
+ // If we have an ArtifactInfo, we add the first FileInfo it contains
+ // which corresponds to the latest version of the artifact.
+ Set<IndexedArtifactFile> files = ((IndexedArtifact) result).getFiles();
+ if(files != null && !files.isEmpty()) {
+ dependencyViewer.add(files.iterator().next().getDependency());
+ notifyListeners();
+ }
+ }
+ }
+ }
+ });
+
+ final Button removeDependencyButton = new Button(composite, SWT.PUSH);
+ removeDependencyButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, true));
+ removeDependencyButton.setText(Messages.getString("wizard.project.page.dependencies.remove")); //$NON-NLS-1$
+ removeDependencyButton.setEnabled(false);
+
+ removeDependencyButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ IStructuredSelection selection = (IStructuredSelection) dependencyViewer.getSelection();
+ if(selection != null) {
+ dependencyViewer.remove(selection.toArray());
+ notifyListeners();
+ }
+ }
+ });
+
+ dependencyViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ IStructuredSelection selection = (IStructuredSelection) event.getSelection();
+ removeDependencyButton.setEnabled(selection.size() > 0);
+ }
+ });
+ }
+
+ public IWizardContainer getContainer() {
+ return super.getContainer();
+ }
+
+ void updatePage() {
+ setPageComplete(isPageValid());
+ }
+
+ private boolean isPageValid() {
+ setErrorMessage(null);
+ return true;
+ }
+
+ /**
+ * Notify listeners about changes
+ */
+ protected void notifyListeners() {
+ SelectionChangedEvent event = new SelectionChangedEvent(dependencyViewer, dependencyViewer.getSelection());
+ for(ISelectionChangedListener listener : listeners) {
+ listener.selectionChanged(event);
+ }
+ }
+
+ public void addListener(ISelectionChangedListener listener) {
+ listeners.add(listener);
+ }
+
+ /**
+ * Returns dependencies currently chosen by the user.
+ *
+ * @return dependencies currently chosen by the user. Neither the array nor any of its elements is
+ * <code>null</code>.
+ */
+ public Dependency[] getDependencies() {
+ List<Dependency> dependencies = new ArrayList<Dependency>();
+ for(int i = 0; i < dependencyViewer.getTable().getItemCount(); i++ ) {
+ Object element = dependencyViewer.getElementAt(i);
+ if(element instanceof Dependency) {
+ dependencies.add((Dependency) element);
+ }
+ }
+ return dependencies.toArray(new Dependency[dependencies.size()]);
+ }
+
+
+ /**
+ * Simple <code>LabelProvider</code> attached to the dependency viewer.
+ * <p>
+ * The information displayed for objects of type <code>Dependency</code> inside the dependency viewer is the
+ * following:
+ * </p>
+ * <p>
+ * {groupId} - {artifactId} - {version} - {type}
+ * </p>
+ */
+ public static class ArtifactLabelProvider extends LabelProvider {
+
+ /** The image to show for all objects of type <code>Dependency</code>. */
+ private static final Image DEPENDENCY_IMAGE = MavenImages.IMG_JAR;
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * The text returned for objects of type <code>Dependency</code> contains the following information about the
+ * dependency:
+ * </p>
+ * <p>
+ * {groupId} - {artifactId} - {version} - {type}
+ * </p>
+ */
+ public String getText(Object element) {
+ if(element instanceof Dependency) {
+ Dependency d = (Dependency) element;
+ return d.getGroupId() + ":" + d.getArtifactId() + ":" + d.getVersion() + (d.getClassifier() == null ? "" : ":" + d.getClassifier()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
+ return super.getText(element);
+ }
+
+ public Image getImage(Object element) {
+ if(element instanceof Dependency) {
+ return DEPENDENCY_IMAGE;
+ }
+ return super.getImage(element);
+ }
+ }
+
+ /**
+ * Simple <code>ViewerComparator</code> attached to the dependency viewer. Objects of type <code>Dependency</code> are
+ * sorted by (1) their groupId and (2) their artifactId.
+ */
+ public static class DependencySorter extends ViewerComparator {
+
+ /**
+ * Two objects of type <code>Dependency</code> are sorted by (1) their groupId and (2) their artifactId.
+ */
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ if(!(e1 instanceof Dependency) || !(e2 instanceof Dependency)) {
+ return super.compare(viewer, e1, e2);
+ }
+
+ // First of all, compare the group IDs of the two dependencies.
+ String group1 = ((Dependency) e1).getGroupId();
+ String group2 = ((Dependency) e2).getGroupId();
+
+ int result = (group1 == null) ? -1 : group1.compareToIgnoreCase(group2);
+
+ // If the group IDs match, we sort by the artifact IDs.
+ if(result == 0) {
+ String artifact1 = ((Dependency) e1).getArtifactId();
+ String artifact2 = ((Dependency) e2).getArtifactId();
+ result = artifact1 == null ? -1 : artifact1.compareToIgnoreCase(artifact2);
+ }
+
+ return result;
+ }
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenImportWizard.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenImportWizard.java
new file mode 100644
index 00000000..f23b2dfe
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenImportWizard.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.IMavenProjectImportResult;
+import org.eclipse.m2e.core.project.MavenProjectInfo;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.core.ui.internal.actions.SelectionUtil;
+import org.eclipse.ui.IImportWizard;
+import org.eclipse.ui.IWorkbench;
+
+
+/**
+ * Maven Import Wizard
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenImportWizard extends AbstractMavenProjectWizard implements IImportWizard {
+
+ private MavenImportWizardPage page;
+
+ private List<String> locations;
+
+ private boolean showLocation = true;
+
+ public MavenImportWizard() {
+ setNeedsProgressMonitor(true);
+ setWindowTitle(Messages.MavenImportWizard_title);
+ }
+
+ public MavenImportWizard(ProjectImportConfiguration importConfiguration, List<String> locations) {
+ this.locations = locations;
+ this.showLocation = false;
+ setNeedsProgressMonitor(true);
+ }
+
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ super.init(workbench, selection);
+
+ if(locations == null || locations.isEmpty()) {
+ IPath location = SelectionUtil.getSelectedLocation(selection);
+ if(location != null) {
+ locations = Collections.singletonList(location.toOSString());
+ }
+ }
+ }
+
+ public void addPages() {
+ page = new MavenImportWizardPage(importConfiguration, workingSets);
+ page.setLocations(locations);
+ page.setShowLocation(showLocation);
+ addPage(page);
+ }
+
+ public boolean performFinish() {
+ if(!page.isPageComplete()) {
+ return false;
+ }
+
+ final Collection<MavenProjectInfo> projects = page.getProjects();
+
+ final MavenPlugin plugin = MavenPlugin.getDefault();
+
+ Job job = new AbstactCreateMavenProjectJob(Messages.MavenImportWizard_job, workingSets) {
+ @Override
+ protected List<IProject> doCreateMavenProjects(IProgressMonitor monitor) throws CoreException {
+ List<IMavenProjectImportResult> results = plugin.getProjectConfigurationManager().importProjects(projects,
+ importConfiguration, monitor);
+ return toProjects(results);
+ }
+ };
+ job.setRule(plugin.getProjectConfigurationManager().getRule());
+ job.schedule();
+
+ return true;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenImportWizardPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenImportWizardPage.java
new file mode 100644
index 00000000..c1633138
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenImportWizardPage.java
@@ -0,0 +1,525 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.maven.model.Model;
+import org.apache.maven.model.Parent;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.embedder.MavenModelManager;
+import org.eclipse.m2e.core.project.AbstractProjectScanner;
+import org.eclipse.m2e.core.project.LocalProjectScanner;
+import org.eclipse.m2e.core.project.MavenProjectInfo;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.ui.IWorkingSet;
+
+
+/**
+ * Maven Import Wizard Page
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenImportWizardPage extends AbstractMavenWizardPage {
+
+ static final Object[] EMPTY = new Object[0];
+
+ protected Combo rootDirectoryCombo;
+
+ protected CheckboxTreeViewer projectTreeViewer;
+
+ private List<String> locations;
+
+ private IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+
+ private WorkingSetGroup workingSetGroup;
+
+ private boolean showLocation = true;
+
+ private final List<IWorkingSet> workingSets;
+
+ protected MavenImportWizardPage(ProjectImportConfiguration importConfiguration, List<IWorkingSet> workingSets) {
+ super("MavenProjectImportWizardPage", importConfiguration);
+ this.workingSets = workingSets;
+ setTitle(org.eclipse.m2e.core.internal.Messages.MavenImportWizardPage_title);
+ setDescription(org.eclipse.m2e.core.internal.Messages.MavenImportWizardPage_desc);
+ setPageComplete(false);
+ }
+
+ public void setShowLocation(boolean showLocation) {
+ this.showLocation = showLocation;
+ }
+
+ public void setLocations(List<String> locations) {
+ this.locations = locations;
+ }
+
+ public void createControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout(3, false));
+ setControl(composite);
+
+ if(showLocation || locations==null || locations.isEmpty()) {
+ final Label selectRootDirectoryLabel = new Label(composite, SWT.NONE);
+ selectRootDirectoryLabel.setLayoutData(new GridData());
+ selectRootDirectoryLabel.setText(Messages.getString("wizard.import.page.root")); //$NON-NLS-1$
+
+ rootDirectoryCombo = new Combo(composite, SWT.NONE);
+ rootDirectoryCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ rootDirectoryCombo.addSelectionListener(new SelectionAdapter() {
+ public void widgetDefaultSelected(SelectionEvent e) {
+ if(rootDirectoryCombo.getText().trim().length() > 0) {
+ scanProjects();
+ }
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ if(rootDirectoryCombo.getText().trim().length() > 0) {
+ scanProjects();
+ }
+ }
+ });
+ rootDirectoryCombo.setFocus();
+ addFieldWithHistory("rootDirectory", rootDirectoryCombo); //$NON-NLS-1$
+
+ if(locations!=null && locations.size()==1) {
+ rootDirectoryCombo.setText(locations.get(0));
+ }
+
+ final Button browseButton = new Button(composite, SWT.NONE);
+ browseButton.setText(Messages.getString("wizard.import.page.browse")); //$NON-NLS-1$
+ browseButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ browseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.NONE);
+ dialog.setText(Messages.getString("wizard.import.page.selectRootFolder")); //$NON-NLS-1$
+ String path = rootDirectoryCombo.getText();
+ if(path.length()==0) {
+ path = ResourcesPlugin.getWorkspace().getRoot().getLocation().toPortableString();
+ }
+ dialog.setFilterPath(path);
+
+ String result = dialog.open();
+ if(result != null) {
+ rootDirectoryCombo.setText(result);
+ scanProjects();
+ }
+ }
+ });
+ }
+
+ final Label projectsLabel = new Label(composite, SWT.NONE);
+ projectsLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
+ projectsLabel.setText(Messages.getString("wizard.import.page.projects")); //$NON-NLS-1$
+
+ projectTreeViewer = new CheckboxTreeViewer(composite, SWT.BORDER);
+
+ projectTreeViewer.addCheckStateListener(new ICheckStateListener() {
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ projectTreeViewer.setSubtreeChecked(event.getElement(), event.getChecked());
+ updateCheckedState();
+ Object[] checkedElements = projectTreeViewer.getCheckedElements();
+ setPageComplete(checkedElements != null && checkedElements.length > 0);
+ }
+ });
+
+ projectTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+
+ public void selectionChanged(SelectionChangedEvent event) {
+ IStructuredSelection selection = (IStructuredSelection) event.getSelection();
+ validateProjectInfo((MavenProjectInfo) selection.getFirstElement());
+ }});
+
+ projectTreeViewer.setContentProvider(new ITreeContentProvider() {
+
+ public Object[] getElements(Object element) {
+ if(element instanceof List) {
+ @SuppressWarnings("unchecked")
+ List<MavenProjectInfo> projects = (List<MavenProjectInfo>) element;
+ return projects.toArray(new MavenProjectInfo[projects.size()]);
+ }
+ return EMPTY;
+ }
+
+ public Object[] getChildren(Object parentElement) {
+ if(parentElement instanceof List) {
+ @SuppressWarnings("unchecked")
+ List<MavenProjectInfo> projects = (List<MavenProjectInfo>) parentElement;
+ return projects.toArray(new MavenProjectInfo[projects.size()]);
+ } else if(parentElement instanceof MavenProjectInfo) {
+ MavenProjectInfo mavenProjectInfo = (MavenProjectInfo) parentElement;
+ Collection<MavenProjectInfo> projects = mavenProjectInfo.getProjects();
+ return projects.toArray(new MavenProjectInfo[projects.size()]);
+ }
+ return EMPTY;
+ }
+
+ public Object getParent(Object element) {
+ return null;
+ }
+
+ public boolean hasChildren(Object parentElement) {
+ if(parentElement instanceof List) {
+ List<?> projects = (List<?>) parentElement;
+ return !projects.isEmpty();
+ } else if(parentElement instanceof MavenProjectInfo) {
+ MavenProjectInfo mavenProjectInfo = (MavenProjectInfo) parentElement;
+ return !mavenProjectInfo.getProjects().isEmpty();
+ }
+ return false;
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+ });
+
+ projectTreeViewer.setLabelProvider(new ProjectLabelProvider());
+
+ final Tree projectTree = projectTreeViewer.getTree();
+ GridData projectTreeData = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 3);
+ projectTreeData.heightHint = 250;
+ projectTreeData.widthHint = 500;
+ projectTree.setLayoutData(projectTreeData);
+
+ final Button selectAllButton = new Button(composite, SWT.NONE);
+ selectAllButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ selectAllButton.setText(Messages.getString("wizard.import.page.selectAll")); //$NON-NLS-1$
+ selectAllButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ projectTreeViewer.expandAll();
+ setAllChecked(true);
+ // projectTreeViewer.setSubtreeChecked(projectTreeViewer.getInput(), true);
+ validate();
+ }
+ });
+
+ final Button deselectAllButton = new Button(composite, SWT.NONE);
+ deselectAllButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ deselectAllButton.setText(Messages.getString("wizard.import.page.deselectAll")); //$NON-NLS-1$
+ deselectAllButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ setAllChecked(false);
+ // projectTreeViewer.setSubtreeChecked(projectTreeViewer.getInput(), false);
+ setPageComplete(false);
+ }
+ });
+
+ final Button refreshButton = new Button(composite, SWT.NONE);
+ refreshButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, true));
+ refreshButton.setText(Messages.getString("wizard.import.page.refresh")); //$NON-NLS-1$
+ refreshButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ scanProjects();
+ }
+ });
+
+ this.workingSetGroup = new WorkingSetGroup(composite, workingSets, getShell());
+
+ createAdvancedSettings(composite, new GridData(SWT.FILL, SWT.TOP, false, false, 3, 1));
+ resolverConfigurationComponent.template.addModifyListener(new ModifyListener(){
+ public void modifyText(ModifyEvent arg0) {
+ validate();
+ }
+ });
+
+ if(locations!=null && !locations.isEmpty()) {
+ scanProjects();
+ }
+ }
+
+ public void dispose() {
+ super.dispose();
+ workingSetGroup.dispose();
+ }
+
+ protected void scanProjects() {
+ final AbstractProjectScanner<MavenProjectInfo> projectScanner = getProjectScanner();
+ try {
+ getWizard().getContainer().run(true, true, new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ projectScanner.run(monitor);
+ }
+ });
+
+ projectTreeViewer.setInput(projectScanner.getProjects());
+ projectTreeViewer.expandAll();
+ // projectTreeViewer.setAllChecked(true);
+ setAllChecked(true);
+ Object[] checkedElements = projectTreeViewer.getCheckedElements();
+ setPageComplete(checkedElements != null && checkedElements.length > 0);
+ setErrorMessage(null);
+ setMessage(null);
+
+ List<Throwable> errors = projectScanner.getErrors();
+ if(!errors.isEmpty()) {
+ StringBuffer sb = new StringBuffer(Messages.getString("wizard.import.page.scanningErrors", errors.size())); //$NON-NLS-1$
+ int n = 1;
+ for(Throwable ex : errors) {
+ if(ex instanceof CoreException) {
+ String msg = ((CoreException) ex).getStatus().getMessage();
+ sb.append("\n ").append(n).append(" ").append(msg.trim()); //$NON-NLS-1$ //$NON-NLS-2$
+
+ } else {
+ String msg = ex.getMessage()==null ? ex.toString() : ex.getMessage();
+ sb.append("\n ").append(n).append(" ").append(msg.trim()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ n++;
+ }
+
+ setMessage(sb.toString(), IMessageProvider.WARNING);
+ }
+
+ } catch(InterruptedException ex) {
+ // canceled
+
+ } catch(InvocationTargetException ex) {
+ Throwable e = ex.getTargetException() == null ? ex : ex.getTargetException();
+ String msg;
+ if(e instanceof CoreException) {
+ msg = e.getMessage();
+ MavenLogger.log(msg, e);
+ } else {
+ msg = "Scanning error " + projectScanner.getDescription() + "; " + e.toString(); //$NON-NLS-2$
+ MavenPlugin.getDefault().getConsole().logError(msg);
+ MavenLogger.log(msg, e);
+ }
+ projectTreeViewer.setInput(null);
+ setPageComplete(false);
+ setErrorMessage(msg);
+
+ }
+ }
+
+ void setAllChecked(boolean state) {
+ @SuppressWarnings("unchecked")
+ List<MavenProjectInfo> input = (List<MavenProjectInfo>) projectTreeViewer.getInput();
+ if(input!=null) {
+ for(MavenProjectInfo mavenProjectInfo : input) {
+ projectTreeViewer.setSubtreeChecked(mavenProjectInfo, state);
+ }
+ updateCheckedState();
+ }
+ }
+
+ void updateCheckedState() {
+ Object[] elements = projectTreeViewer.getCheckedElements();
+ for(int i = 0; i < elements.length; i++ ) {
+ Object element = elements[i];
+ if(element instanceof MavenProjectInfo) {
+ MavenProjectInfo info = (MavenProjectInfo) element;
+ if(isWorkspaceFolder(info) || isAlreadyExists(info)) {
+ projectTreeViewer.setChecked(info, false);
+ }
+ }
+ }
+ }
+
+ boolean isWorkspaceFolder(MavenProjectInfo info) {
+ if(info!=null) {
+ File pomFile = info.getPomFile();
+ if(pomFile != null) {
+ File parentFile = pomFile.getParentFile();
+ if(parentFile.getAbsolutePath().equals(workspaceRoot.getLocation().toFile().getAbsolutePath())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ boolean isAlreadyExists(MavenProjectInfo info) {
+ if(info!=null) {
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ IProject project = getImportConfiguration().getProject(workspace.getRoot(), info.getModel());
+ return project.exists();
+ }
+ return false;
+ }
+
+ protected AbstractProjectScanner<MavenProjectInfo> getProjectScanner() {
+ File root = workspaceRoot.getLocation().toFile();
+ MavenPlugin mavenPlugin = MavenPlugin.getDefault();
+ MavenModelManager modelManager = mavenPlugin.getMavenModelManager();
+ if(showLocation || locations == null || locations.isEmpty()) {
+ return new LocalProjectScanner(root, rootDirectoryCombo.getText(), false, modelManager);
+ }
+ return new LocalProjectScanner(root, locations, true, modelManager);
+ }
+
+ /**
+ * @return collection of <code>MavenProjectInfo</code>
+ */
+ public Collection<MavenProjectInfo> getProjects() {
+ Collection<MavenProjectInfo> checkedProjects = new ArrayList<MavenProjectInfo>();
+ for(Object o : projectTreeViewer.getCheckedElements()) {
+ checkedProjects.add((MavenProjectInfo) o);
+ }
+
+ return checkedProjects;
+ }
+
+ private void collectProjects(List<MavenProjectInfo> mavenProjects, Set<MavenProjectInfo> checkedProjects,
+ Collection<MavenProjectInfo> childProjects) {
+ for(MavenProjectInfo projectInfo : childProjects) {
+ if(checkedProjects.contains(projectInfo)) {
+ mavenProjects.add(projectInfo);
+ } else {
+ collectProjects(mavenProjects, checkedProjects, projectInfo.getProjects());
+ }
+ }
+ }
+
+ protected boolean validateProjectInfo(MavenProjectInfo info) {
+ if(info!=null) {
+ String projectName = getImportConfiguration().getProjectName(info.getModel());
+ if(isWorkspaceFolder(info)) {
+ setMessage(Messages.getString("wizard.import.validator.workspaceFolder", projectName), IMessageProvider.WARNING); //$NON-NLS-1$
+ } else if(isAlreadyExists(info)) {
+ setMessage(Messages.getString("wizard.import.validator.projectExists", projectName), IMessageProvider.WARNING); //$NON-NLS-1$
+ } else {
+ setMessage(null, IMessageProvider.WARNING);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ protected void validate() {
+ Object[] elements = projectTreeViewer.getCheckedElements();
+ for(int i = 0; i < elements.length; i++ ) {
+ Object element = elements[i];
+ if(element instanceof MavenProjectInfo) {
+ if (validateProjectInfo((MavenProjectInfo) element)) {
+ setPageComplete(false);
+ return;
+ }
+ }
+ }
+
+ setMessage(null);
+ setPageComplete(projectTreeViewer.getCheckedElements().length > 0);
+ projectTreeViewer.refresh();
+ }
+
+ /**
+ * ProjectLabelProvider
+ */
+ class ProjectLabelProvider extends LabelProvider implements IColorProvider {
+
+ public String getText(Object element) {
+ if(element instanceof MavenProjectInfo) {
+ MavenProjectInfo info = (MavenProjectInfo) element;
+
+ if(info.getProfiles().isEmpty()) {
+ return info.getLabel() + " - " + getId(info); //$NON-NLS-1$
+ }
+
+ return info.getLabel() + " - " + getId(info) + " " + info.getProfiles(); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return super.getText(element);
+ }
+
+ private String getId(MavenProjectInfo info) {
+ Model model = info.getModel();
+
+ String groupId = model.getGroupId();
+ String artifactId = model.getArtifactId();
+ String version = model.getVersion();
+ String packaging = model.getPackaging();
+
+ Parent parent = model.getParent();
+
+ if(groupId==null && parent!=null) {
+ groupId = parent.getGroupId();
+ }
+ if(groupId==null) {
+ groupId = org.eclipse.m2e.core.internal.Messages.MavenImportWizardPage_inherited;
+ }
+
+ if(version==null && parent!=null) {
+ version = parent.getVersion();
+ }
+ if(version==null) {
+ version = org.eclipse.m2e.core.internal.Messages.MavenImportWizardPage_inherited;
+ }
+
+ return groupId + ":" + artifactId + ":" + version + ":" + packaging; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IColorProvider#getBackground(java.lang.Object)
+ */
+ public Color getForeground(Object element) {
+ if(element instanceof MavenProjectInfo) {
+ MavenProjectInfo info = (MavenProjectInfo) element;
+ if(isWorkspaceFolder(info)) {
+ return Display.getDefault().getSystemColor(SWT.COLOR_RED);
+ } else if(isAlreadyExists(info)) {
+ return Display.getDefault().getSystemColor(SWT.COLOR_GRAY);
+ }
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.IColorProvider#getForeground(java.lang.Object)
+ */
+ public Color getBackground(Object element) {
+ return null;
+ }
+
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenInstallFileArtifactWizardPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenInstallFileArtifactWizardPage.java
new file mode 100644
index 00000000..02e2dbc5
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenInstallFileArtifactWizardPage.java
@@ -0,0 +1,388 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.io.File;
+
+import org.apache.maven.project.MavenProject;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.index.IndexedArtifactFile;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.ui.internal.actions.SelectionUtil;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+
+/**
+ * Wizard page to enter parameters required for artifact installation.
+ *
+ * @author Guillaume Sauthier
+ * @author Mike Haller
+ * @author Eugene Kuleshov
+ */
+public class MavenInstallFileArtifactWizardPage extends WizardPage {
+
+ Text artifactFileNameText;
+ Text pomFileNameText;
+
+ private Combo groupIdCombo;
+ private Combo artifactIdCombo;
+ private Combo versionCombo;
+ private Combo packagingCombo;
+ private Combo classifierCombo;
+
+ Button createChecksumButton;
+ Button generatePomButton;
+
+ private final IFile file;
+
+ public MavenInstallFileArtifactWizardPage(IFile file) {
+ super("mavenInstallFileWizardPage");
+ this.file = file;
+ this.setTitle(Messages.MavenInstallFileArtifactWizardPage_title);
+ this.setDescription(Messages.MavenInstallFileArtifactWizardPage_desc);
+ }
+
+ public void createControl(Composite parent) {
+ Composite container = new Composite(parent, SWT.NONE);
+ container.setLayout(new GridLayout(3, false));
+ container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ ModifyListener modifyingListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ pageChanged();
+ }
+ };
+
+ Label artifactFileNameLabel = new Label(container, SWT.NONE);
+ artifactFileNameLabel.setText(Messages.MavenInstallFileArtifactWizardPage_lblFileName);
+
+ artifactFileNameText = new Text(container, SWT.BORDER);
+ artifactFileNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ artifactFileNameText.setData("name", "artifactFileNametext"); //$NON-NLS-1$ //$NON-NLS-2$
+ artifactFileNameText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ updateFileName(getArtifactFileName());
+ pageChanged();
+ }
+ });
+
+ final Button artifactFileNameButton = new Button(container, SWT.NONE);
+ artifactFileNameButton.setLayoutData(new GridData());
+ artifactFileNameButton.setData("name", "externalPomFileButton"); //$NON-NLS-1$ //$NON-NLS-2$
+ artifactFileNameButton.setText(Messages.MavenInstallFileArtifactWizardPage_btnFilename);
+ artifactFileNameButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ FileDialog fileDialog = new FileDialog(artifactFileNameButton.getShell());
+ fileDialog.setText(Messages.MavenInstallFileArtifactWizardPage_file_title);
+ fileDialog.setFileName(artifactFileNameText.getText());
+ String name = fileDialog.open();
+ if(name!=null) {
+ updateFileName(name);
+ }
+ }
+ });
+
+ Label pomFileNameLabel = new Label(container, SWT.NONE);
+ pomFileNameLabel.setText(Messages.MavenInstallFileArtifactWizardPage_lblPom);
+
+ pomFileNameText = new Text(container, SWT.BORDER);
+ pomFileNameText.setData("name", "pomFileNameText"); //$NON-NLS-1$ //$NON-NLS-2$
+ pomFileNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ pomFileNameText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ generatePomButton.setSelection(getPomFileName().length()==0);
+ pageChanged();
+ }
+ });
+
+ final Button pomFileNameButton = new Button(container, SWT.NONE);
+ pomFileNameButton.setLayoutData(new GridData());
+ pomFileNameButton.setData("name", "externalPomFileButton"); //$NON-NLS-1$ //$NON-NLS-2$
+ pomFileNameButton.setText(Messages.MavenInstallFileArtifactWizardPage_btnPom);
+ pomFileNameButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ FileDialog fileDialog = new FileDialog(pomFileNameButton.getShell());
+ fileDialog.setText(Messages.MavenInstallFileArtifactWizardPage_file_title);
+ fileDialog.setFileName(pomFileNameText.getText());
+ String res = fileDialog.open();
+ if(res!=null) {
+ pomFileNameText.setText(res);
+ }
+ }
+ });
+
+ new Label(container, SWT.NONE);
+
+ generatePomButton = new Button(container, SWT.CHECK);
+ generatePomButton.setData("name", "generatePomButton"); //$NON-NLS-1$ //$NON-NLS-2$
+ generatePomButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
+ generatePomButton.setText(Messages.MavenInstallFileArtifactWizardPage_btnGenerate);
+ generatePomButton.setSelection(true);
+ new Label(container, SWT.NONE);
+
+ createChecksumButton = new Button(container, SWT.CHECK);
+ createChecksumButton.setData("name", "createChecksumButton"); //$NON-NLS-1$ //$NON-NLS-2$
+ createChecksumButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
+ createChecksumButton.setText(Messages.MavenInstallFileArtifactWizardPage_btnChecksum);
+ createChecksumButton.setSelection(true);
+
+ Label separator = new Label(container, SWT.HORIZONTAL | SWT.SEPARATOR);
+ GridData separatorData = new GridData(SWT.FILL, SWT.CENTER, false, false, 3, 1);
+ separatorData.verticalIndent = 5;
+ separator.setLayoutData(separatorData);
+
+ Label groupIdlabel = new Label(container, SWT.NONE);
+ groupIdlabel.setText(Messages.MavenInstallFileArtifactWizardPage_lblgroupid);
+
+ groupIdCombo = new Combo(container, SWT.NONE);
+ groupIdCombo.setData("name", "groupIdCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+ groupIdCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ groupIdCombo.addModifyListener(modifyingListener);
+ new Label(container, SWT.NONE);
+
+ Label artifactIdLabel = new Label(container, SWT.NONE);
+ artifactIdLabel.setText(Messages.MavenInstallFileArtifactWizardPage_lblArtifact);
+
+ artifactIdCombo = new Combo(container, SWT.NONE);
+ artifactIdCombo.setData("name", "artifactIdCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+ artifactIdCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ artifactIdCombo.addModifyListener(modifyingListener);
+ new Label(container, SWT.NONE);
+
+ Label versionLabel = new Label(container, SWT.NONE);
+ versionLabel.setText(Messages.MavenInstallFileArtifactWizardPage_lblVersion);
+
+ versionCombo = new Combo(container, SWT.NONE);
+ versionCombo.setData("name", "versionCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+ versionCombo.setText(MavenArtifactComponent.DEFAULT_VERSION);
+ GridData versionComboData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1);
+ versionComboData.widthHint = 150;
+ versionCombo.setLayoutData(versionComboData);
+ versionCombo.addModifyListener(modifyingListener);
+
+ Label packagingLabel = new Label(container, SWT.NONE);
+ packagingLabel.setText(Messages.MavenInstallFileArtifactWizardPage_lblPackaging);
+
+ packagingCombo = new Combo(container, SWT.NONE);
+ packagingCombo.setData("name", "packagingCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+ packagingCombo.setText(MavenArtifactComponent.DEFAULT_PACKAGING);
+ packagingCombo.setItems(MavenArtifactComponent.PACKAGING_OPTIONS);
+ GridData packagingComboData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1);
+ packagingComboData.widthHint = 150;
+ packagingCombo.setLayoutData(packagingComboData);
+ packagingCombo.addModifyListener(modifyingListener);
+
+ Label classifierLabel = new Label(container, SWT.NONE);
+ classifierLabel.setText(Messages.MavenInstallFileArtifactWizardPage_lblClassifier);
+
+ classifierCombo = new Combo(container, SWT.NONE);
+ classifierCombo.setData("name", "classifierText"); //$NON-NLS-1$ //$NON-NLS-2$
+ classifierCombo.setItems(new String[] {"sources", "javadoc"}); //$NON-NLS-1$ //$NON-NLS-2$
+ GridData classifierTextData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1);
+ classifierTextData.widthHint = 150;
+ classifierCombo.setLayoutData(classifierTextData);
+ classifierCombo.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ generatePomButton.setSelection(getClassifier().length()==0);
+ }
+ });
+
+ if(file != null) {
+ updateFileName(file.getLocation().toOSString());
+ }
+
+ setControl(container);
+ }
+
+ void updateFileName(String fileName) {
+ if(!getArtifactFileName().equals(fileName)) {
+ artifactFileNameText.setText(fileName);
+ }
+
+ File file = new File(fileName);
+ if(!file.exists() || !file.isFile()) {
+ return;
+ }
+
+ if(fileName.endsWith(".jar") || fileName.endsWith(".war") || fileName.endsWith(".ear")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ packagingCombo.setText(fileName.substring(fileName.length()-3));
+ }
+
+ int n = fileName.lastIndexOf('.');
+ if(n>-1) {
+ String pomFileName = fileName.substring(0, n) + ".pom"; //$NON-NLS-1$
+ if(new File(pomFileName).exists()) {
+ pomFileNameText.setText(pomFileName);
+ }
+ } else {
+ pomFileNameText.setText(""); //$NON-NLS-1$
+ }
+
+ MavenPlugin plugin = MavenPlugin.getDefault();
+ try {
+ IndexedArtifactFile iaf = plugin.getIndexManager().getAllIndexes().identify(file);
+ if(iaf!=null) {
+ groupIdCombo.setText(iaf.group);
+ artifactIdCombo.setText(iaf.artifact);
+ versionCombo.setText(iaf.version);
+ if(iaf.classifier!=null) {
+ classifierCombo.setText(iaf.classifier);
+ }
+
+ String name = iaf.group + ":" + iaf.artifact + "-" + iaf.version // //$NON-NLS-1$ //$NON-NLS-2$
+ + (iaf.classifier == null ? "" : iaf.classifier); //$NON-NLS-1$
+ setMessage(NLS.bind(Messages.MavenInstallFileArtifactWizardPage_message, name), WARNING);
+ return;
+ }
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ }
+
+ if(n>-1) {
+ String pomFileName = fileName.substring(0, n) + ".pom"; //$NON-NLS-1$
+ if(new File(pomFileName).exists()) {
+ pomFileNameText.setText(pomFileName);
+
+ // read pom file
+
+ try {
+ IMaven maven = MavenPlugin.getDefault().getMaven();
+ MavenProject mavenProject = maven.readProject(new File(pomFileName), null);
+
+ groupIdCombo.setText(mavenProject.getGroupId());
+ artifactIdCombo.setText(mavenProject.getArtifactId());
+ versionCombo.setText(mavenProject.getVersion());
+ packagingCombo.setText(mavenProject.getPackaging());
+ return;
+
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ }
+ }
+ }
+
+ ArtifactKey artifactKey = SelectionUtil.getType(file, ArtifactKey.class);
+ if(artifactKey!=null) {
+ groupIdCombo.setText(artifactKey.getGroupId());
+ artifactIdCombo.setText(artifactKey.getArtifactId());
+ versionCombo.setText(artifactKey.getVersion());
+ if(artifactKey.getClassifier()!=null) {
+ classifierCombo.setText(artifactKey.getClassifier());
+ }
+ }
+ }
+
+ void pageChanged() {
+ String artifactFileName = getArtifactFileName();
+ if(artifactFileName.length() == 0) {
+ updateStatus(Messages.MavenInstallFileArtifactWizardPage_error_no_name);
+ return;
+ }
+
+ File file = new File(artifactFileName);
+ if(!file.exists() || !file.isFile()) {
+ updateStatus(Messages.MavenInstallFileArtifactWizardPage_error_missing);
+ return;
+ }
+
+ String pomFileName = getPomFileName();
+ if(pomFileName.length()>0) {
+ if(!new File(pomFileName).exists()) {
+ updateStatus(Messages.MavenInstallFileArtifactWizardPage_error_missingpom);
+ return;
+ }
+ }
+
+ if(getGroupId().length() == 0) {
+ updateStatus(Messages.MavenInstallFileArtifactWizardPage_error_groupid);
+ return;
+ }
+
+ if(getArtifactId().length() == 0) {
+ updateStatus(Messages.MavenInstallFileArtifactWizardPage_error_artifactid);
+ return;
+ }
+
+ if(getVersion().length() == 0) {
+ updateStatus(Messages.MavenInstallFileArtifactWizardPage_error_version);
+ return;
+ }
+
+ if(getPackaging().length() == 0) {
+ updateStatus(Messages.MavenInstallFileArtifactWizardPage_error_packaging);
+ return;
+ }
+
+ updateStatus(null);
+ }
+
+ private void updateStatus(String message) {
+ setErrorMessage(message);
+ setPageComplete(message == null);
+ }
+
+ public String getArtifactFileName() {
+ return artifactFileNameText.getText().trim();
+ }
+
+ public String getPomFileName() {
+ return pomFileNameText.getText().trim();
+ }
+
+ public String getGroupId() {
+ return groupIdCombo.getText().trim();
+ }
+
+ public String getArtifactId() {
+ return artifactIdCombo.getText().trim();
+ }
+
+ public String getVersion() {
+ return versionCombo.getText().trim();
+ }
+
+ public String getPackaging() {
+ return packagingCombo.getText().trim();
+ }
+
+ public String getClassifier() {
+ return this.classifierCombo.getText().trim();
+ }
+
+ public boolean isGeneratePom() {
+ return generatePomButton.getSelection();
+ }
+
+ public boolean isCreateChecksum() {
+ return createChecksumButton.getSelection();
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenInstallFileRepositoryWizardPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenInstallFileRepositoryWizardPage.java
new file mode 100644
index 00000000..aaff216b
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenInstallFileRepositoryWizardPage.java
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.io.File;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.model.edit.pom.Model;
+import org.eclipse.m2e.model.edit.pom.PomFactory;
+import org.eclipse.m2e.model.edit.pom.Repository;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+
+/**
+ * MavenInstallFileRepositoryWizardPage used to chose to repositories for installing artifacts.
+ *
+ * @author Mike Haller
+ */
+public class MavenInstallFileRepositoryWizardPage extends WizardPage {
+
+ private final IFile pomFile;
+
+ public MavenInstallFileRepositoryWizardPage(IFile pomFile) {
+ super("mavenInstallFileRepositorySelectionPage");
+ setTitle("Repository Selection Page");
+ setDescription("Select the repositories where to deploy the artifact");
+ this.pomFile = pomFile;
+ }
+
+ public void createControl(Composite parent) {
+ Composite container = new Composite(parent, SWT.NONE);
+ container.setLayout(new GridLayout(1, false));
+ container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ Label repositoriesLabel = new Label(container, SWT.NONE);
+ repositoriesLabel.setData("name", "repositoriesLabel");
+ repositoriesLabel.setText("&Repositories:");
+
+ CheckboxTreeViewer repositoryViewer = new CheckboxTreeViewer(container, SWT.BORDER);
+ repositoryViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ // repositoryViewer.setInput(pomFile);
+ repositoryViewer.setLabelProvider(new RepositoryLabelProvider());
+ repositoryViewer.setContentProvider(new RepositoriesContentProvider());
+ repositoryViewer.setCheckedElements(new Object[] {RepositoriesContentProvider.LOCAL_REPOSITORY});
+
+ initRepositories();
+
+ setControl(container);
+ }
+
+ private void initRepositories() {
+ // TODO Auto-generated method initRepositories
+
+ }
+
+ /**
+ * RepositoryLabelProvider prints the name of a repository, and if available, its URL.
+ */
+ public class RepositoryLabelProvider extends LabelProvider {
+
+ public String getText(Object element) {
+ if(element instanceof Repository) {
+ Repository repository = (Repository) element;
+ if(repository.getUrl() != null && repository.getUrl().trim().length() > 0) {
+ return repository.getName() + "(" + repository.getUrl() + ")";
+ }
+ return repository.getName();
+ }
+ return super.getText(element);
+ }
+
+ }
+
+ /**
+ * LocalRepositoriesContentProvider provides a list of local and remote repositories.
+ * <p>
+ * If no repositories could be found in the POM Maven Model, a default local repository is shown.
+ */
+ public static class RepositoriesContentProvider implements ITreeContentProvider {
+
+ public static final Repository LOCAL_REPOSITORY = createLocalRepository();
+
+ private static Repository createLocalRepository() {
+ Repository repository = PomFactory.eINSTANCE.createRepository();
+ repository.setId("local");
+ repository.setName("Local Repository");
+ try {
+ File localRepositoryDir = new File(MavenPlugin.getDefault().getMaven().getLocalRepository().getBasedir());
+ repository.setUrl(localRepositoryDir.toURI().toString());
+ } catch(CoreException ex) {
+ MavenLogger.log("Unable to determine local repository URL, using default", ex);
+ }
+ return repository;
+ }
+
+ public Object[] getElements(Object arg0) {
+ return repositories.toArray();
+ }
+
+ private EList<Repository> repositories;
+
+ public Object[] getChildren(Object arg0) {
+ return null;
+ }
+
+ public Object getParent(Object arg0) {
+ return null;
+ }
+
+ public boolean hasChildren(Object arg0) {
+ return false;
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer arg0, Object arg1, Object newInput) {
+ if(newInput instanceof Model) {
+ Model model = (Model) newInput;
+ repositories = model.getRepositories();
+ }
+ }
+
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenInstallFileWizard.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenInstallFileWizard.java
new file mode 100644
index 00000000..00b88ea3
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenInstallFileWizard.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.execution.MavenExecutionResult;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.ui.internal.actions.OpenMavenConsoleAction;
+import org.eclipse.ui.IImportWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.progress.IProgressConstants;
+
+
+/**
+ * Wizard to install artifacts into the local Maven repository.
+ *
+ * @author Guillaume Sauthier
+ * @author Mike Haller
+ * @author Eugene Kuleshov
+ * @since 0.9.7
+ */
+public class MavenInstallFileWizard extends Wizard implements IImportWizard {
+
+ private IFile selectedFile;
+
+ private IFile pomFile;
+
+ private MavenInstallFileArtifactWizardPage artifactPage;
+
+ private MavenInstallFileRepositoryWizardPage repositoryPage;
+
+ public MavenInstallFileWizard() {
+ setNeedsProgressMonitor(true);
+ setWindowTitle(Messages.MavenInstallFileWizard_title);
+ }
+
+ public void addPages() {
+ artifactPage = new MavenInstallFileArtifactWizardPage(selectedFile);
+ addPage(artifactPage);
+
+ // repositoryPage = new MavenInstallFileRepositoryWizardPage(pomFile);
+ // addPage(repositoryPage);
+ }
+
+ public boolean performFinish() {
+ final Properties properties = new Properties();
+
+ // Mandatory Properties for install:install-file
+ properties.setProperty("file", artifactPage.getArtifactFileName()); //$NON-NLS-1$
+
+ properties.setProperty("groupId", artifactPage.getGroupId()); //$NON-NLS-1$
+ properties.setProperty("artifactId", artifactPage.getArtifactId()); //$NON-NLS-1$
+ properties.setProperty("version", artifactPage.getVersion()); //$NON-NLS-1$
+ properties.setProperty("packaging", artifactPage.getPackaging()); //$NON-NLS-1$
+
+ if(artifactPage.getClassifier().length()>0) {
+ properties.setProperty("classifier", artifactPage.getClassifier()); //$NON-NLS-1$
+ }
+
+ if(artifactPage.getPomFileName().length()>0) {
+ properties.setProperty("pomFile", artifactPage.getPomFileName()); //$NON-NLS-1$
+ }
+ if(artifactPage.isGeneratePom()) {
+ properties.setProperty("generatePom", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if(artifactPage.isCreateChecksum()) {
+ properties.setProperty("createChecksum", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ new Job(Messages.MavenInstallFileWizard_job) {
+ protected IStatus run(IProgressMonitor monitor) {
+ setProperty(IProgressConstants.ACTION_PROPERTY, new OpenMavenConsoleAction());
+ MavenPlugin plugin = MavenPlugin.getDefault();
+ try {
+ // Run the install:install-file goal
+ IMaven maven = MavenPlugin.getDefault().getMaven();
+ MavenExecutionRequest request = maven.createExecutionRequest(monitor);
+ request.setGoals(Arrays.asList("install:install-file")); //$NON-NLS-1$
+ request.setUserProperties(properties);
+ MavenExecutionResult executionResult = maven.execute(request, monitor);
+
+ List<Throwable> exceptions = executionResult.getExceptions();
+ if(!exceptions.isEmpty()) {
+ for(Throwable exception : exceptions) {
+ String msg = Messages.MavenInstallFileWizard_error;
+ plugin.getConsole().logError(msg + "; " + exception.toString()); //$NON-NLS-1$
+ MavenLogger.log(msg, exception);
+ }
+ }
+
+ // TODO update index for local maven repository
+
+ } catch (CoreException ex) {
+ MavenLogger.log(ex);
+ plugin.getConsole().logError("Failed to install artifact");
+ }
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+
+ return true;
+ }
+
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ Object element = selection.getFirstElement();
+ if(element instanceof IFile) {
+ selectedFile = (IFile) element;
+ setPomFile(selectedFile.getProject());
+ } else if(element instanceof IProject) {
+ setPomFile((IProject) element);
+ }
+ }
+
+ private void setPomFile(IProject project) {
+ if(project.isAccessible()) {
+ IFile pomFile = project.getFile(IMavenConstants.POM_FILE_NAME);
+ if(pomFile!=null && pomFile.isAccessible()) {
+ this.pomFile = pomFile;
+ }
+ }
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenLocationComponent.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenLocationComponent.java
new file mode 100644
index 00000000..f7bd98e2
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenLocationComponent.java
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+
+
+/**
+ * Simple GUI component which allows the user to choose between a workspace
+ * location and a user specified external location.
+ *
+ * This component is mainly used for choosing the location at which to create
+ * a new project.
+ */
+public class MavenLocationComponent extends Composite {
+
+ /** Radio button indicating whether the workspace location has been chosen. */
+ protected Button inWorkspaceButton;
+
+ /** Radio button indicating whether an external location has been chosen. */
+ protected Button inExternalLocationButton;
+
+ /** Text field for defining a user specified external location. */
+ protected Combo locationCombo;
+
+ /** Button allowing to choose a directory on the file system as the external location. */
+ protected Button locationBrowseButton;
+
+ protected ModifyListener modifyingListener;
+
+ protected Label locationLabel;
+
+ /**
+ * Constructor.
+ *
+ * Constructs all the GUI components contained in this <code>Composite</code>.
+ * These components allow the user to choose between a workspace location and
+ * a user specified external location.
+ *
+ * @param parent The widget which will be the parent of this component.
+ * @param styles The widget style for this component.
+ * @param modifyingListener Listener which is notified when the contents of
+ * this component change due to user input.
+ */
+ public MavenLocationComponent( final Composite parent, int styles ) {
+ super( parent, styles );
+
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.marginHeight = 0;
+ gridLayout.marginWidth = 0;
+ setLayout( gridLayout );
+
+ Group locationGroup = new Group( this, SWT.NONE );
+ locationGroup.setText( Messages.getString( "locationComponent.location" ) ); //$NON-NLS-1$
+ locationGroup.setLayoutData( new GridData( GridData.FILL, GridData.FILL, true, true, 3, 1 ) );
+ GridLayout groupLayout = new GridLayout();
+ groupLayout.numColumns = 3;
+ groupLayout.marginLeft = 0;
+ locationGroup.setLayout( groupLayout );
+
+ GridData gridData = new GridData();
+ gridData.horizontalSpan = 3;
+
+ // first radio button
+ inWorkspaceButton = new Button( locationGroup, SWT.RADIO );
+ inWorkspaceButton.setText( Messages.getString( "locationComponent.inWorkspace" ) ); //$NON-NLS-1$
+ inWorkspaceButton.setLayoutData( new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1) );
+ inWorkspaceButton.addSelectionListener( new SelectionAdapter() {
+ public void widgetSelected( SelectionEvent e ) {
+ boolean isEnabled = !inWorkspaceButton.getSelection();
+ locationLabel.setEnabled( isEnabled );
+ locationCombo.setEnabled( isEnabled );
+ locationBrowseButton.setEnabled( isEnabled );
+ if(modifyingListener!=null) {
+ modifyingListener.modifyText( null );
+ }
+ }
+ } );
+
+ // second radio button
+ inExternalLocationButton = new Button( locationGroup, SWT.RADIO );
+ inExternalLocationButton.setText( Messages.getString( "locationComponent.atExternal" ) ); //$NON-NLS-1$
+ inExternalLocationButton.setLayoutData( gridData );
+
+ // choose directory
+ locationLabel = new Label( locationGroup, SWT.NONE );
+ GridData gd_locationLabel = new GridData();
+ gd_locationLabel.horizontalIndent = 10;
+ locationLabel.setLayoutData(gd_locationLabel);
+ locationLabel.setText( Messages.getString( "locationComponent.directory" ) ); //$NON-NLS-1$
+
+ locationCombo = new Combo( locationGroup, SWT.BORDER );
+ locationCombo.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ) );
+
+ locationBrowseButton = new Button( locationGroup, SWT.PUSH );
+ locationBrowseButton.setText( Messages.getString( "locationComponent.browse" ) ); //$NON-NLS-1$
+
+ gridData = new GridData( SWT.FILL, SWT.DEFAULT, false, false );
+ locationBrowseButton.setLayoutData( gridData );
+
+ locationBrowseButton.addSelectionListener( new SelectionAdapter() {
+ public void widgetSelected( SelectionEvent e ) {
+ DirectoryDialog dialog = new DirectoryDialog(getShell());
+ dialog.setText(Messages.getString( "locationComponent.selectLocation" )); //$NON-NLS-1$
+
+ String path = locationCombo.getText();
+ if(path.length()==0) {
+ path = ResourcesPlugin.getWorkspace().getRoot().getLocation().toPortableString();
+ }
+ dialog.setFilterPath(path);
+
+ String selectedDir = dialog.open();
+ if(selectedDir != null) {
+ locationCombo.setText( selectedDir.trim() );
+ }
+ }
+ } );
+
+ inWorkspaceButton.setSelection( true );
+
+ locationLabel.setEnabled( false );
+ locationCombo.setEnabled( false );
+ locationBrowseButton.setEnabled( false );
+ }
+
+ /**
+ * Returns the path of the location chosen by the user.
+ *
+ * According to the user input, the path either points to the workspace or
+ * to a valid user specified location on the filesystem.
+ *
+ * @return The path of the location chosen by the user.
+ * Is never <code>null</code>.
+ */
+ public IPath getLocationPath() {
+ if ( isInWorkspace() ) {
+ return Platform.getLocation();
+ }
+ return Path.fromOSString( locationCombo.getText().trim() );
+ }
+
+ /**
+ * Returns whether the workspace has been chosen as the location to use.
+ *
+ * @return <code>true</code> if the workspace is chosen as the location to use,
+ * <code>false</code> if the specified external location is to be used.
+ */
+ public boolean isInWorkspace() {
+ return inWorkspaceButton.getSelection();
+ }
+
+ public void setModifyingListener( ModifyListener modifyingListener ) {
+ this.modifyingListener = modifyingListener;
+ locationCombo.addModifyListener( modifyingListener );
+ }
+
+ public Combo getLocationCombo() {
+ return locationCombo;
+ }
+
+ public void dispose() {
+ super.dispose();
+ if(modifyingListener!=null) {
+ locationCombo.removeModifyListener( modifyingListener );
+ }
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenMaterializePomWizard.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenMaterializePomWizard.java
new file mode 100644
index 00000000..90bbb2ae
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenMaterializePomWizard.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.maven.model.Dependency;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.MavenProjectPomScanner;
+import org.eclipse.m2e.core.project.MavenProjectScmInfo;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.core.ui.internal.actions.SelectionUtil;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IImportWizard;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+
+
+/**
+ * A wizard used to import projects for Maven artifacts
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenMaterializePomWizard extends AbstractMavenProjectWizard implements IImportWizard, INewWizard {
+
+ MavenDependenciesWizardPage selectionPage;
+
+ MavenProjectWizardLocationPage locationPage;
+
+ Button checkOutAllButton;
+
+ Button useDeveloperConnectionButton;
+
+ // TODO replace with ArtifactKey
+ private Dependency[] dependencies;
+
+ public MavenMaterializePomWizard() {
+ importConfiguration = new ProjectImportConfiguration();
+ setNeedsProgressMonitor(true);
+ setWindowTitle(Messages.MavenMaterializePomWizard_title);
+ }
+
+ public void setDependencies(Dependency[] dependencies) {
+ this.dependencies = dependencies;
+ }
+
+ public Dependency[] getDependencies() {
+ return dependencies;
+ }
+
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ ArrayList<Dependency> dependencies = new ArrayList<Dependency>();
+
+ for(Iterator<?> it = selection.iterator(); it.hasNext();) {
+ Object element = it.next();
+ ArtifactKey artifactKey = SelectionUtil.getType(element, ArtifactKey.class);
+ if(artifactKey!=null) {
+ Dependency d = new Dependency();
+ d.setGroupId(artifactKey.getGroupId());
+ d.setArtifactId(artifactKey.getArtifactId());
+ d.setVersion(artifactKey.getVersion());
+ d.setClassifier(artifactKey.getClassifier());
+ dependencies.add(d);
+ }
+ }
+
+ setDependencies(dependencies.toArray(new Dependency[dependencies.size()]));
+ }
+
+ public void addPages() {
+ selectionPage = new MavenDependenciesWizardPage(importConfiguration, //
+ Messages.MavenMaterializePomWizard_dialog_title, //
+ Messages.MavenMaterializePomWizard_dialog_message) {
+ protected void createAdvancedSettings(Composite composite, GridData gridData) {
+ checkOutAllButton = new Button(composite, SWT.CHECK);
+ checkOutAllButton.setText(Messages.MavenMaterializePomWizard_btnCheckout);
+ checkOutAllButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 3, 1));
+
+ useDeveloperConnectionButton = new Button(composite, SWT.CHECK);
+ useDeveloperConnectionButton.setText(Messages.MavenMaterializePomWizard_btnDev);
+ useDeveloperConnectionButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 3, 1));
+
+ super.createAdvancedSettings(composite, gridData);
+ }
+ };
+ selectionPage.setDependencies(dependencies);
+
+ locationPage = new MavenProjectWizardLocationPage(importConfiguration, //
+ Messages.MavenMaterializePomWizard_location_title,
+ Messages.MavenMaterializePomWizard_location_message, workingSets);
+ locationPage.setLocationPath(SelectionUtil.getSelectedLocation(selection));
+
+ addPage(selectionPage);
+ addPage(locationPage);
+ }
+
+ public boolean canFinish() {
+ return super.canFinish();
+ }
+
+ public boolean performFinish() {
+ if(!canFinish()) {
+ return false;
+ }
+
+ final Dependency[] dependencies = selectionPage.getDependencies();
+
+ final boolean checkoutAllProjects = checkOutAllButton.getSelection();
+ final boolean developer = useDeveloperConnectionButton.getSelection();
+
+ MavenProjectCheckoutJob job = new MavenProjectCheckoutJob(importConfiguration, checkoutAllProjects, workingSets) {
+ protected List<MavenProjectScmInfo> getProjects(IProgressMonitor monitor) throws InterruptedException {
+ MavenPlugin plugin = MavenPlugin.getDefault();
+ MavenProjectPomScanner<MavenProjectScmInfo> scanner = new MavenProjectPomScanner<MavenProjectScmInfo>(developer, dependencies, //
+ plugin.getMavenModelManager(), //
+ plugin.getConsole());
+ scanner.run(monitor);
+ // XXX handle errors/warnings
+
+ return scanner.getProjects();
+ }
+ };
+
+ if(!locationPage.isInWorkspace()) {
+ job.setLocation(locationPage.getLocationPath().toFile());
+ }
+
+ job.schedule();
+
+ return true;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenModuleWizard.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenModuleWizard.java
new file mode 100644
index 00000000..7a9e1988
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenModuleWizard.java
@@ -0,0 +1,296 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.maven.archetype.catalog.Archetype;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Model;
+import org.apache.maven.model.Parent;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+import org.eclipse.m2e.core.ui.internal.actions.OpenMavenConsoleAction;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.progress.IProgressConstants;
+
+
+/**
+ * A project wizard for creating a new Maven2 module project.
+ */
+public class MavenModuleWizard extends AbstractMavenProjectWizard implements INewWizard {
+
+ /** The name of the default wizard page image. */
+ // protected static final String DEFAULT_PAGE_IMAGE_NAME = "icons/new_m2_project_wizard.gif";
+
+ /** The default wizard page image. */
+ // protected static final ImageDescriptor DEFAULT_PAGE_IMAGE = MavenPlugin.getImageDescriptor(DEFAULT_PAGE_IMAGE_NAME);
+
+ /** the current selection */
+ private IStructuredSelection selection;
+
+ /** the parent page (#1) */
+ protected MavenModuleWizardParentPage parentPage;
+
+ /** The archetype selection page. */
+ protected MavenProjectWizardArchetypePage archetypePage;
+
+ /** The wizard page for gathering Maven2 project information. */
+ protected MavenProjectWizardArtifactPage artifactPage;
+
+ /** The wizard page for gathering archetype project information. */
+ protected MavenProjectWizardArchetypeParametersPage parametersPage;
+
+ /** The wizard page for choosing the Maven2 dependencies to use. */
+ private MavenDependenciesWizardPage dependenciesPage;
+
+ private String moduleName;
+
+ protected boolean isEditor = false;
+
+ /** Default constructor. Sets the title and image of the wizard. */
+ public MavenModuleWizard() {
+ setWindowTitle(Messages.getString("wizard.module.title")); //$NON-NLS-1$
+ setDefaultPageImageDescriptor(MavenImages.WIZ_NEW_PROJECT);
+ setNeedsProgressMonitor(true);
+ }
+
+ public MavenModuleWizard(boolean isEditor) {
+ this();
+ this.isEditor = isEditor;
+ }
+
+ /** Creates the pages. */
+ public void addPages() {
+ parentPage = new MavenModuleWizardParentPage(importConfiguration, workingSets);
+ archetypePage = new MavenProjectWizardArchetypePage(importConfiguration);
+ parametersPage = new MavenProjectWizardArchetypeParametersPage(importConfiguration);
+ artifactPage = new MavenProjectWizardArtifactPage(importConfiguration);
+ dependenciesPage = new MavenDependenciesWizardPage(importConfiguration, //
+ Messages.getString("wizard.project.page.dependencies.title"), // //$NON-NLS-1$
+ Messages.getString("wizard.project.page.dependencies.description")); //$NON-NLS-1$
+ dependenciesPage.setDependencies(new Dependency[0]);
+ dependenciesPage.setShowScope(true);
+
+ addPage(parentPage);
+ addPage(archetypePage);
+ addPage(parametersPage);
+ addPage(artifactPage);
+ addPage(dependenciesPage);
+ }
+
+ /** Adds the listeners after the page controls are created. */
+ public void createPageControls(Composite pageContainer) {
+ artifactPage.setParentReadonly(true);
+ artifactPage.setTitle(Messages.getString("wizard.module.page.artifact.title")); //$NON-NLS-1$
+ archetypePage.setTitle(Messages.getString("wizard.module.page.archetype.title")); //$NON-NLS-1$
+ parametersPage.setTitle(Messages.getString("wizard.module.page.parameters.title")); //$NON-NLS-1$
+
+ super.createPageControls(pageContainer);
+
+ parametersPage.setArtifactIdEnabled(false);
+
+ parentPage.addArchetypeSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ archetypePage.setUsed(!parentPage.isSimpleProject());
+ }
+ });
+
+ parentPage.addModuleNameListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ parametersPage.setProjectName(parentPage.getModuleName());
+ artifactPage.setProjectName(parentPage.getModuleName());
+ }
+ });
+
+ parentPage.addParentProjectListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ copyParentValues();
+ }
+ });
+
+ if(selection != null && selection.size() > 0) {
+ parentPage.setParent(selection.getFirstElement());
+ copyParentValues();
+ }
+ }
+
+ /** Copies the parent project parameters to the artifact page. */
+ protected void copyParentValues() {
+ Model model = parentPage.getParentModel();
+ if(model != null) {
+ String groupId = model.getGroupId();
+ String artifactId = model.getArtifactId();
+ String version = model.getVersion();
+
+ if(groupId == null) {
+ Parent parent = model.getParent();
+ if(parent != null) {
+ groupId = parent.getGroupId();
+ }
+ }
+ if(version == null) {
+ Parent parent = model.getParent();
+ if(parent != null) {
+ version = parent.getVersion();
+ }
+ }
+
+ artifactPage.setParentProject(groupId, artifactId, version);
+ parametersPage.setParentProject(groupId, artifactId, version);
+ }
+ }
+
+ /** Stores the current selection. */
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ this.selection = selection;
+ }
+
+ /** Performs the "finish" action. */
+ public boolean performFinish() {
+ // First of all, we extract all the information from the wizard pages.
+ // Note that this should not be done inside the operation we will run
+ // since many of the wizard pages' methods can only be invoked from within
+ // the SWT event dispatcher thread. However, the operation spawns a new
+ // separate thread to perform the actual work, i.e. accessing SWT elements
+ // from within that thread would lead to an exception.
+
+ final String moduleName = parentPage.getModuleName();
+
+ // Get the location where to create the project. For some reason, when using
+ // the default workspace location for a project, we have to pass null
+ // instead of the actual location.
+ final IPath location = parentPage.getParentContainer().getLocation();
+
+ final IFile parentPom = parentPage.getPom();
+
+ Job job;
+
+ final MavenPlugin plugin = MavenPlugin.getDefault();
+
+ if(parentPage.isSimpleProject()) {
+
+ final Model model = artifactPage.getModel();
+ @SuppressWarnings("unchecked")
+ List<Dependency> modelDependencies = model.getDependencies();
+ modelDependencies.addAll(Arrays.asList(dependenciesPage.getDependencies()));
+
+ final String[] folders = artifactPage.getFolders();
+
+ job = new AbstactCreateMavenProjectJob(Messages.getString("wizard.project.job.creatingProject", moduleName), workingSets) { //$NON-NLS-1$
+ @Override
+ protected List<IProject> doCreateMavenProjects(IProgressMonitor monitor) throws CoreException {
+ setProperty(IProgressConstants.ACTION_PROPERTY, new OpenMavenConsoleAction());
+ String projectName = importConfiguration.getProjectName(model);
+ IProject project = importConfiguration.getProject(ResourcesPlugin.getWorkspace().getRoot(), model);
+
+ // XXX respect parent's setting for separate projects for modules
+ // XXX should run update sources on parent instead of creating new module project
+
+ plugin.getProjectConfigurationManager().createSimpleProject(project, location.append(moduleName), model,
+ folders, importConfiguration, monitor);
+
+ setModule(projectName);
+
+ return Arrays.asList(project);
+ }
+ };
+
+ } else {
+ Model model = parametersPage.getModel();
+
+ final IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(moduleName);
+ final Archetype archetype = archetypePage.getArchetype();
+
+ final String groupId = model.getGroupId();
+ final String artifactId = model.getArtifactId();
+ final String version = model.getVersion();
+ final String javaPackage = parametersPage.getJavaPackage();
+ final Properties properties = parametersPage.getProperties();
+
+ job = new AbstactCreateMavenProjectJob(Messages.getString(
+ "wizard.project.job.creating", archetype.getArtifactId()), workingSets) { //$NON-NLS-1$
+ @Override
+ protected List<IProject> doCreateMavenProjects(IProgressMonitor monitor) throws CoreException {
+ MavenPlugin plugin = MavenPlugin.getDefault();
+ plugin.getProjectConfigurationManager().createArchetypeProject(project, location, archetype, //
+ groupId, artifactId, version, javaPackage, properties, importConfiguration, monitor);
+
+ setModule(moduleName);
+
+ return Arrays.asList(project);
+ }
+ };
+ }
+ job.addJobChangeListener(new JobChangeAdapter() {
+ public void done(IJobChangeEvent event) {
+ final IStatus result = event.getResult();
+ if(result.isOK()) {
+ if(!isEditor) {
+ plugin.getMavenModelManager().addModule(parentPom, moduleName);
+ }
+
+ } else {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ MessageDialog.openError(getShell(), //
+ Messages.getString("wizard.project.job.failed", moduleName), // //$NON-NLS-1$
+ result.getMessage());
+ }
+ });
+ }
+ }
+ });
+ job.setRule(plugin.getProjectConfigurationManager().getRule());
+ job.schedule();
+
+ if(isEditor) {
+ try {
+ job.join();
+ } catch(InterruptedException ex) {
+ // ignore
+ }
+ }
+
+ return true;
+ }
+
+ void setModule(String moduleName) {
+ this.moduleName = moduleName;
+ }
+
+ public String getModuleName() {
+ return this.moduleName;
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenModuleWizardParentPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenModuleWizardParentPage.java
new file mode 100644
index 00000000..8b88cae1
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenModuleWizardParentPage.java
@@ -0,0 +1,314 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.List;
+
+import org.apache.maven.model.Model;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.core.ui.internal.actions.SelectionUtil;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkingSet;
+
+
+/**
+ * Maven2ModuleParentPage
+ */
+public class MavenModuleWizardParentPage extends AbstractMavenWizardPage {
+
+ /** the module name input field */
+ private Combo moduleNameCombo;
+
+ /** the parent project input field */
+ protected Text parentProjectText;
+
+ /** the "create simple project" checkbox */
+ private Button simpleProject;
+
+ /** the parent object entity */
+ protected Object parentObject;
+
+ /** the parent container */
+ private IContainer parentContainer;
+
+ /** the parent POM file */
+ private IFile pom;
+
+ /** the parent model */
+ private Model parentModel;
+
+ /** working set selector widget */
+ private WorkingSetGroup workingSetGroup;
+
+ private final List<IWorkingSet> workingSets;
+
+
+ /** Creates a new page. */
+ public MavenModuleWizardParentPage(ProjectImportConfiguration projectImportConfiguration, List<IWorkingSet> workingSets) {
+ super("MavenModuleWizardParentPage", projectImportConfiguration);
+ this.workingSets = workingSets;
+ setTitle(Messages.getString("wizard.module.page.parent.title")); //$NON-NLS-1$
+ setDescription(Messages.getString("wizard.module.page.parent.description")); //$NON-NLS-1$
+ setPageComplete(false);
+ }
+
+ /** Creates the page controls. */
+ public void createControl(Composite parent) {
+ Composite container = new Composite(parent, SWT.NULL);
+ container.setLayout(new GridLayout(3, false));
+
+ simpleProject = new Button(container, SWT.CHECK);
+ simpleProject.setText(Messages.getString("wizard.project.page.project.simpleProject")); //$NON-NLS-1$
+ simpleProject.setData("name", "simpleProjectButton"); //$NON-NLS-1$ //$NON-NLS-2$
+ simpleProject.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 3, 1));
+ simpleProject.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ validate();
+ }
+ });
+
+ Label nameLabel = new Label(container, SWT.NONE);
+ GridData gd_nameLabel = new GridData();
+ gd_nameLabel.verticalIndent = 10;
+ nameLabel.setLayoutData(gd_nameLabel);
+ nameLabel.setText(Messages.getString("wizard.module.page.parent.moduleName")); //$NON-NLS-1$
+
+ moduleNameCombo = new Combo(container, SWT.BORDER);
+ GridData gd_moduleNameCombo = new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1);
+ gd_moduleNameCombo.verticalIndent = 10;
+ moduleNameCombo.setLayoutData(gd_moduleNameCombo);
+ moduleNameCombo.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ validate();
+ }
+ });
+ addFieldWithHistory("moduleName", moduleNameCombo); //$NON-NLS-1$
+
+ Label parentLabel = new Label(container, SWT.NONE);
+ parentLabel.setText(Messages.getString("wizard.module.page.parent.parentProject")); //$NON-NLS-1$
+
+ parentProjectText = new Text(container, SWT.BORDER);
+ parentProjectText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
+ parentProjectText.setEditable(false);
+
+ Button browseButton = new Button(container, SWT.NONE);
+ browseButton.setText(Messages.getString("wizard.module.page.parent.browse")); //$NON-NLS-1$
+ browseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ MavenProjectSelectionDialog dialog = new MavenProjectSelectionDialog(getShell());
+ if(dialog.open() == Window.OK) {
+ setParent(dialog.getFirstResult());
+ validate();
+ }
+ }
+ });
+
+ this.workingSetGroup = new WorkingSetGroup(container, workingSets, getShell());
+
+ createAdvancedSettings(container, new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1));
+
+ initialize();
+
+ setControl(container);
+ }
+
+ /** Initializes the GUI components and validates the page. */
+ private void initialize() {
+ loadParent();
+ validate();
+ }
+
+ /** Validates the data entered. */
+ void validate() {
+ String moduleName = moduleNameCombo.getText().trim();
+ if(moduleName.length() == 0) {
+ setErrorMessage(null);
+ setMessage(Messages.getString("wizard.module.page.parent.validator.moduleName")); //$NON-NLS-1$
+ setPageComplete(false);
+ return;
+ }
+
+ // check whether the project name is valid
+ IStatus nameStatus =
+ ResourcesPlugin.getWorkspace().validateName(moduleName, IResource.PROJECT);
+ if(!nameStatus.isOK()) {
+ setErrorMessage(nameStatus.getMessage());
+ setPageComplete(false);
+ return;
+ }
+
+ // check if the given folder already exists
+ if(parentContainer != null && parentContainer.exists(new Path(moduleName))) {
+ setErrorMessage(Messages.getString("wizard.module.page.parent.validator.nameExists")); //$NON-NLS-1$
+ setPageComplete(false);
+ return;
+ }
+
+ if(pom == null) {
+ setErrorMessage(null);
+ setMessage(Messages.getString("wizard.module.page.parent.validator.parentProject")); //$NON-NLS-1$
+ setPageComplete(false);
+ return;
+ }
+ if(!validateParent()){
+ return;
+ }
+ setErrorMessage(null);
+ setMessage(null);
+ setPageComplete(true);
+ }
+
+ /** Assigns a parent object. */
+ public void setParent(Object parent) {
+ parentObject = parent;
+ loadParent();
+ }
+
+ /** Loads the data from the parent object. */
+ protected void loadParent() {
+ if(parentObject == null) {
+ return;
+ }
+
+ int type = SelectionUtil.getElementType(parentObject);
+
+ if(SelectionUtil.POM_FILE == type) {
+ pom = SelectionUtil.getType(parentObject, IFile.class);
+ } else if(SelectionUtil.PROJECT_WITH_NATURE == type) {
+ IProject project = SelectionUtil.getType(parentObject, IProject.class);
+ pom = project.getFile(IMavenConstants.POM_FILE_NAME);
+
+ workingSetGroup.selectWorkingSets(SelectionUtil.getAssignedWorkingSets(project));
+ } else if(parentObject instanceof IContainer) {
+ pom = ((IContainer) parentObject).getFile(new Path(IMavenConstants.POM_FILE_NAME));
+ }
+
+ if(pom != null && pom.exists()) {
+ parentObject = pom;
+ parentContainer = pom.getParent();
+
+ MavenPlugin plugin = MavenPlugin.getDefault();
+ try {
+ parentModel = plugin.getMavenModelManager().readMavenModel(pom);
+ validateParent();
+ parentProjectText.setText(parentModel.getArtifactId());
+ } catch(CoreException e) {
+ MavenLogger.log("Error loading POM: " + e.getMessage(), e);
+ }
+ }
+ }
+
+ private boolean validateParent(){
+ if(parentModel != null){
+ if(!"pom".equals(parentModel.getPackaging())){ //$NON-NLS-1$
+ setMessage(null);
+ setErrorMessage(org.eclipse.m2e.core.internal.Messages.MavenModuleWizardParentPage_error);
+ setPageComplete(false);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /** Returns "true" if the user chose not to use archetypes. */
+ public boolean isSimpleProject() {
+ return simpleProject.getSelection();
+ }
+
+ /** Skips the archetype selection page if the user chooses a simple project. */
+ public IWizardPage getNextPage() {
+ return getWizard().getPage(
+ isSimpleProject() ? "MavenProjectWizardArtifactPage" : "MavenProjectWizardArchetypePage");
+ }
+
+ /** Returns the module name. */
+ public String getModuleName() {
+ return moduleNameCombo.getText();
+ }
+
+ /** Returns the parent model. */
+ public Model getParentModel() {
+ return parentModel;
+ }
+
+ /** Returns the parent POM file handle. */
+ public IFile getPom() {
+ return pom;
+ }
+
+ /** Returns the parent container. */
+ public IContainer getParentContainer() {
+ return parentContainer;
+ }
+
+ /** Offers a listener hookup to the pages watching the module name field. */
+ public void addModuleNameListener(ModifyListener modifyListener) {
+ moduleNameCombo.addModifyListener(modifyListener);
+ }
+
+ /** Unhooks the listener watching the module name field. */
+ public void removesModuleNameListener(ModifyListener modifyListener) {
+ moduleNameCombo.removeModifyListener(modifyListener);
+ }
+
+ /** Offers a listener hookup to the pages watching the parent name field. */
+ public void addParentProjectListener(ModifyListener modifyListener) {
+ parentProjectText.addModifyListener(modifyListener);
+ }
+
+ /** Unhooks the listener watching the parent name field. */
+ public void removesParentProjectListener(ModifyListener modifyListener) {
+ parentProjectText.removeModifyListener(modifyListener);
+ }
+
+ /** Offers a listener hookup to the pages watching the archetype switch. */
+ public void addArchetypeSelectionListener(SelectionListener selectionListener) {
+ simpleProject.addSelectionListener(selectionListener);
+ }
+
+ /** Removes the listener watching the project name field. */
+ public void removeArchetypeSelectionListener(SelectionListener selectionListener) {
+ simpleProject.removeSelectionListener(selectionListener);
+ }
+
+ /** Cleans up. */
+ public void dispose() {
+ super.dispose();
+ workingSetGroup.dispose();
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenParentComponent.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenParentComponent.java
new file mode 100644
index 00000000..cda33f4f
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenParentComponent.java
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import org.apache.maven.model.Model;
+import org.apache.maven.model.Parent;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+
+
+/**
+ * Wizard page component showing panel project properties.
+ */
+public class MavenParentComponent extends Composite {
+
+ /** parent artifact id input field */
+ private Combo parentArtifactIdCombo;
+
+ /** parent group id input field */
+ private Combo parentGroupIdCombo;
+
+ /** parent version input field */
+ private Combo parentVersionCombo;
+
+ /** the "clear parent section" button */
+ private Button parentClearButton;
+
+ /** the "browse..." button */
+ private Button parentBrowseButton;
+
+ private Label groupIdLabel;
+
+ private Label artifactIdLabel;
+
+ private Label versionLabel;
+
+ /** Creates a new panel with parent controls. */
+ public MavenParentComponent(Composite parent, int style) {
+ super(parent, SWT.NONE);
+
+ boolean readonly = (style & SWT.READ_ONLY) != 0;
+
+ GridLayout topLayout = new GridLayout();
+ topLayout.marginHeight = 0;
+ topLayout.marginWidth = 0;
+ setLayout(topLayout);
+
+ Group group = new Group(this, SWT.NONE);
+ group.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ group.setText(Messages.getString("wizard.project.page.artifact.parent.title")); //$NON-NLS-1$
+
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.numColumns = 3;
+ group.setLayout(gridLayout);
+
+ groupIdLabel = new Label(group, SWT.NONE);
+ groupIdLabel.setText(Messages.getString("wizard.project.page.artifact.parent.groupId")); //$NON-NLS-1$
+
+ parentGroupIdCombo = new Combo(group, SWT.NONE);
+ parentGroupIdCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+ parentGroupIdCombo.setData("name", "parentGroupIdCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+ parentGroupIdCombo.setEnabled(!readonly);
+
+ artifactIdLabel = new Label(group, SWT.NONE);
+ artifactIdLabel.setText(Messages.getString("wizard.project.page.artifact.parent.artifactId")); //$NON-NLS-1$
+
+ parentArtifactIdCombo = new Combo(group, SWT.NONE);
+ parentArtifactIdCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+ parentArtifactIdCombo.setData("name", "parentArtifactIdCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+ parentArtifactIdCombo.setEnabled(!readonly);
+
+ versionLabel = new Label(group, SWT.NONE);
+ versionLabel.setText(Messages.getString("wizard.project.page.artifact.parent.version")); //$NON-NLS-1$
+
+ parentVersionCombo = new Combo(group, SWT.NONE);
+ GridData gd_versionCombo = new GridData(SWT.LEFT, SWT.CENTER, true, false);
+ gd_versionCombo.widthHint = 150;
+ parentVersionCombo.setLayoutData(gd_versionCombo);
+ parentVersionCombo.setEnabled(!readonly);
+ parentVersionCombo.setData("name", "parentVersionCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ if(!readonly) {
+ Composite buttonPanel = new Composite(group, SWT.NONE);
+ RowLayout rowLayout = new RowLayout();
+ rowLayout.pack = false;
+ rowLayout.marginTop = 0;
+ rowLayout.marginRight = 0;
+ rowLayout.marginLeft = 0;
+ rowLayout.marginBottom = 0;
+ buttonPanel.setLayout(rowLayout);
+ buttonPanel.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ parentBrowseButton = new Button(buttonPanel, SWT.NONE);
+ parentBrowseButton.setText(Messages.getString("wizard.project.page.artifact.parent.browse")); //$NON-NLS-1$
+ parentBrowseButton.setData("name", "parentBrowseButton"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ parentClearButton = new Button(buttonPanel, SWT.NONE);
+ parentClearButton.setText(Messages.getString("wizard.project.page.artifact.parent.clear")); //$NON-NLS-1$
+ parentClearButton.setData("name", "parentClearButton"); //$NON-NLS-1$ //$NON-NLS-2$
+ parentClearButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ setValues("", "", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ });
+ }
+ }
+
+ public Combo getGroupIdCombo() {
+ return parentGroupIdCombo;
+ }
+
+ public Combo getArtifactIdCombo() {
+ return this.parentArtifactIdCombo;
+ }
+
+ public Combo getVersionCombo() {
+ return this.parentVersionCombo;
+ }
+
+ public void setWidthGroup(WidthGroup widthGroup) {
+ widthGroup.addControl(this.groupIdLabel);
+ widthGroup.addControl(this.artifactIdLabel);
+ widthGroup.addControl(this.versionLabel);
+ }
+
+ /** Adds modify listener to the input controls. */
+ public void addModifyListener(ModifyListener listener) {
+ parentArtifactIdCombo.addModifyListener(listener);
+ parentGroupIdCombo.addModifyListener(listener);
+ parentVersionCombo.addModifyListener(listener);
+ }
+
+ /** Removes the listener from the input controls. */
+ public void removeModifyListener(ModifyListener listener) {
+ parentArtifactIdCombo.removeModifyListener(listener);
+ parentGroupIdCombo.removeModifyListener(listener);
+ parentVersionCombo.removeModifyListener(listener);
+ }
+
+ /** Adds selection listener to the "browse" button. */
+ public void addBrowseButtonListener(SelectionListener listener) {
+ if(parentBrowseButton != null) {
+ parentBrowseButton.addSelectionListener(listener);
+ }
+ }
+
+ /** Removes the selection listener from the "browse" button. */
+ public void removeBrowseButtonListener(SelectionListener listener) {
+ if(parentBrowseButton != null) {
+ parentBrowseButton.removeSelectionListener(listener);
+ }
+ }
+
+ /** Enables the "clear" button. */
+ public void setClearButtonEnabled(boolean enabled) {
+ if(parentClearButton != null) {
+ parentClearButton.setEnabled(enabled);
+ }
+ }
+
+ /** Sets the parent group values. */
+ public void setValues(String groupId, String artifactId, String version) {
+ parentGroupIdCombo.setText(groupId==null ? "" : groupId); //$NON-NLS-1$
+ parentArtifactIdCombo.setText(artifactId==null ? "" : artifactId); //$NON-NLS-1$
+ parentVersionCombo.setText(version==null ? "" : version); //$NON-NLS-1$
+ }
+
+ /** Updates a Maven model. */
+ public void updateModel(Model model) {
+ String groupId = parentGroupIdCombo.getText().trim();
+ if(groupId.length() > 0) {
+ Parent parent = new Parent();
+ parent.setGroupId(groupId);
+ parent.setArtifactId(parentArtifactIdCombo.getText().trim());
+ parent.setVersion(parentVersionCombo.getText().trim());
+ model.setParent(parent);
+ }
+ }
+
+ /**
+ * Validates the inputs to make sure all three fields are present in the same time, or none at all.
+ */
+ public boolean validate() {
+ int parentCheck = 0;
+ if(parentGroupIdCombo.getText().trim().length() > 0) {
+ parentCheck++ ;
+ }
+ if(parentArtifactIdCombo.getText().trim().length() > 0) {
+ parentCheck++ ;
+ }
+ if(parentVersionCombo.getText().trim().length() > 0) {
+ parentCheck++ ;
+ }
+
+ setClearButtonEnabled(parentCheck > 0);
+
+ return parentCheck == 0 || parentCheck == 3;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomSelectionComponent.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomSelectionComponent.java
new file mode 100644
index 00000000..8b98b1da
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomSelectionComponent.java
@@ -0,0 +1,560 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.lucene.search.BooleanQuery;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.IDecoration;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.StyledString;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.index.IIndex;
+import org.eclipse.m2e.core.index.IndexManager;
+import org.eclipse.m2e.core.index.IndexedArtifact;
+import org.eclipse.m2e.core.index.IndexedArtifactFile;
+import org.eclipse.m2e.core.index.UserInputSearchExpression;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+
+import com.ibm.icu.text.DateFormat;
+
+
+/**
+ * MavenPomSelectionComposite
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenPomSelectionComponent extends Composite {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.swt.widgets.Widget#dispose()
+ */
+ public void dispose() {
+ if(searchJob != null) {
+ searchJob.cancel();
+ }
+ super.dispose();
+ }
+
+ Text searchText = null;
+
+ TreeViewer searchResultViewer = null;
+
+ /**
+ * One of {@link IIndex#SEARCH_ARTIFACT}, {@link IIndex#SEARCH_CLASS_NAME},
+ */
+ String queryType;
+
+ SearchJob searchJob;
+
+ private IStatus status;
+
+ private ISelectionChangedListener selectionListener;
+
+ /**
+ * @deprecated
+ */
+ public static final String P_SEARCH_INCLUDE_JAVADOC = "searchIncludesJavadoc"; //$NON-NLS-1$
+
+ /**
+ * @deprecated
+ */
+ public static final String P_SEARCH_INCLUDE_SOURCES = "searchIncludesSources"; //$NON-NLS-1$
+
+ /**
+ * @deprecated
+ */
+ public static final String P_SEARCH_INCLUDE_TESTS = "searchIncludesTests"; //$NON-NLS-1$
+
+ private static final long SHORT_DELAY = 150L;
+
+ private static final long LONG_DELAY = 500L;
+
+ final HashSet<String> artifactKeys = new HashSet<String>();
+ final HashSet<String> managedKeys = new HashSet<String>();
+
+ public MavenPomSelectionComponent(Composite parent, int style) {
+ super(parent, style);
+ createSearchComposite();
+ }
+
+ private void createSearchComposite() {
+ GridLayout gridLayout = new GridLayout(2, false);
+ gridLayout.marginWidth = 0;
+ gridLayout.marginHeight = 0;
+ setLayout(gridLayout);
+
+ Label searchTextlabel = new Label(this, SWT.NONE);
+ searchTextlabel.setText(Messages.MavenPomSelectionComponent_search_title);
+ searchTextlabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));
+
+ searchText = new Text(this, SWT.BORDER | SWT.SEARCH);
+ searchText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1));
+ searchText.addKeyListener(new KeyAdapter() {
+ public void keyPressed(KeyEvent e) {
+ if(e.keyCode == SWT.ARROW_DOWN) {
+ searchResultViewer.getTree().setFocus();
+ selectFirstElementInTheArtifactTreeIfNoSelectionHasBeenMade();
+ }
+ }
+ });
+
+ searchText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ scheduleSearch(searchText.getText(), true);
+ }
+ });
+
+ Label searchResultsLabel = new Label(this, SWT.NONE);
+ searchResultsLabel.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1));
+ searchResultsLabel.setText(Messages.MavenPomSelectionComponent_lblResults);
+
+ Tree tree = new Tree(this, SWT.BORDER | SWT.SINGLE);
+ tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
+ tree.setData("name", "searchResultTree"); //$NON-NLS-1$ //$NON-NLS-2$
+ tree.addFocusListener(new FocusListener() {
+
+ public void focusGained(FocusEvent e) {
+ selectFirstElementInTheArtifactTreeIfNoSelectionHasBeenMade();
+ }
+
+ public void focusLost(FocusEvent e) {
+
+ }
+ });
+
+ searchResultViewer = new TreeViewer(tree);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.swt.widgets.Composite#setFocus()
+ */
+ public boolean setFocus() {
+ return searchText.setFocus();
+ }
+
+ void selectFirstElementInTheArtifactTreeIfNoSelectionHasBeenMade() {
+ //
+ // If we have started a new search when focus is passed to the tree viewer we will automatically select
+ // the first element if no element has been selected from a previous expedition into the tree viewer.
+ //
+ if(searchResultViewer.getTree().getItemCount() > 0 && searchResultViewer.getSelection().isEmpty()) {
+ Object artifact = searchResultViewer.getTree().getTopItem().getData();
+ searchResultViewer.setSelection(new StructuredSelection(artifact), true);
+ }
+ }
+
+ protected boolean showClassifiers() {
+ return (queryType != null && IIndex.SEARCH_ARTIFACT.equals(queryType));
+ }
+
+
+ public void init(String queryText, String queryType, Set<ArtifactKey> artifacts, Set<ArtifactKey> managed) {
+ this.queryType = queryType;
+
+ if(queryText != null) {
+ searchText.setText(queryText);
+ }
+
+ if(artifacts != null) {
+ for(ArtifactKey a : artifacts) {
+ artifactKeys.add(a.getGroupId() + ":" + a.getArtifactId()); //$NON-NLS-1$
+ artifactKeys.add(a.getGroupId() + ":" + a.getArtifactId() + ":" + a.getVersion()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ if (managed != null) {
+ for (ArtifactKey a : managed) {
+ managedKeys.add(a.getGroupId() + ":" + a.getArtifactId()); //$NON-NLS-1$
+ managedKeys.add(a.getGroupId() + ":" + a.getArtifactId() + ":" + a.getVersion()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ searchResultViewer.setContentProvider(new SearchResultContentProvider());
+ searchResultViewer.setLabelProvider(new DelegatingStyledCellLabelProvider(new SearchResultLabelProvider(artifactKeys, managedKeys, queryType)));
+ searchResultViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ IStructuredSelection selection = (IStructuredSelection) event.getSelection();
+ if(!selection.isEmpty()) {
+ if(selection.size() == 1) {
+ IndexedArtifactFile f = getSelectedIndexedArtifactFile(selection.getFirstElement());
+ // int severity = artifactKeys.contains(f.group + ":" + f.artifact) ? IStatus.ERROR : IStatus.OK;
+ int severity = IStatus.OK;
+ String date = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT).format(f.date);
+ setStatus(
+ severity,
+ NLS.bind(Messages.MavenPomSelectionComponent_detail1, f.fname,
+ (f.size != -1 ? NLS.bind(Messages.MavenPomSelectionComponent_details2, date, f.size) : date)));
+ } else {
+ setStatus(IStatus.OK, NLS.bind(Messages.MavenPomSelectionComponent_selected, selection.size()));
+ }
+ } else {
+ setStatus(IStatus.ERROR, Messages.MavenPomSelectionComponent_nosel);
+ }
+ }
+ });
+ setupClassifiers();
+ setStatus(IStatus.ERROR, ""); //$NON-NLS-1$
+ scheduleSearch(queryText, false);
+ }
+
+ protected void setupClassifiers() {
+ }
+
+ public IStatus getStatus() {
+ return this.status;
+ }
+
+ public void addDoubleClickListener(IDoubleClickListener listener) {
+ searchResultViewer.addDoubleClickListener(listener);
+ }
+
+ public void addSelectionChangedListener(ISelectionChangedListener listener) {
+ this.selectionListener = listener;
+ }
+
+ void setStatus(int severity, String message) {
+ this.status = new Status(severity, IMavenConstants.PLUGIN_ID, 0, message, null);
+ if(selectionListener != null) {
+ selectionListener.selectionChanged(new SelectionChangedEvent(searchResultViewer, searchResultViewer
+ .getSelection()));
+ }
+ }
+
+ public IndexedArtifact getIndexedArtifact() {
+ IStructuredSelection selection = (IStructuredSelection) searchResultViewer.getSelection();
+ Object element = selection.getFirstElement();
+ if(element instanceof IndexedArtifact) {
+ return (IndexedArtifact) element;
+ }
+ TreeItem[] treeItems = searchResultViewer.getTree().getSelection();
+ if(treeItems.length == 0) {
+ return null;
+ }
+ return (IndexedArtifact) treeItems[0].getParentItem().getData();
+ }
+
+ public IndexedArtifactFile getIndexedArtifactFile() {
+ IStructuredSelection selection = (IStructuredSelection) searchResultViewer.getSelection();
+ return getSelectedIndexedArtifactFile(selection.getFirstElement());
+ }
+
+ IndexedArtifactFile getSelectedIndexedArtifactFile(Object element) {
+ if(element instanceof IndexedArtifact) {
+ //the idea here is that if we have a managed version for something, then the IndexedArtifact shall
+ //represent that value..
+ IndexedArtifact ia = (IndexedArtifact)element;
+ if (managedKeys.contains(getKey(ia))) {
+ for (IndexedArtifactFile file : ia.getFiles()) {
+ if (managedKeys.contains(getKey(file))) {
+ return file;
+ }
+ }
+ }
+ return ia.getFiles().iterator().next();
+ }
+ return (IndexedArtifactFile) element;
+ }
+
+ void scheduleSearch(String query, boolean delay) {
+ if(query != null && query.length() > 2) {
+ if(searchJob == null) {
+ IndexManager indexManager = MavenPlugin.getDefault().getIndexManager();
+ searchJob = new SearchJob(queryType, indexManager);
+ } else {
+ if(!searchJob.cancel()) {
+ //for already running ones, just create new instance so that the previous one can piecefully die
+ //without preventing the new one from completing first
+ IndexManager indexManager = MavenPlugin.getDefault().getIndexManager();
+ searchJob = new SearchJob(queryType, indexManager);
+ }
+ }
+ searchJob.setQuery(query.toLowerCase());
+ searchJob.schedule(delay ? LONG_DELAY : SHORT_DELAY);
+ } else {
+ if(searchJob != null) {
+ searchJob.cancel();
+ }
+ }
+ }
+
+ public static String getKey(IndexedArtifactFile file) {
+ return file.group + ":" + file.artifact + ":" + file.version; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ public static String getKey(IndexedArtifact art) {
+ return art.getGroupId() + ":" + art.getArtifactId(); //$NON-NLS-1$
+ }
+
+
+ /**
+ * Search Job
+ */
+ private class SearchJob extends Job {
+
+ private IndexManager indexManager;
+
+ private String query;
+
+ private String field;
+
+ private volatile boolean stop = false;
+
+ public SearchJob(String field, IndexManager indexManager) {
+ super(Messages.MavenPomSelectionComponent_searchJob);
+ this.field = field;
+ this.indexManager = indexManager;
+ }
+
+ public void setQuery(String query) {
+ this.query = query;
+ }
+
+ public boolean shouldRun() {
+ stop = false;
+ return super.shouldRun();
+ }
+
+ public int getClassifier() {
+ // mkleint: no more allowing people to opt in/out displaying javadoc and sources..
+ // allow tests and every other classifier..
+ return IIndex.SEARCH_JARS + IIndex.SEARCH_TESTS;
+ }
+
+ protected IStatus run(IProgressMonitor monitor) {
+ int classifier = showClassifiers() ? getClassifier() : IIndex.SEARCH_ALL;
+ if(searchResultViewer == null || searchResultViewer.getControl() == null
+ || searchResultViewer.getControl().isDisposed()) {
+ return Status.CANCEL_STATUS;
+ }
+ if(query != null) {
+ String activeQuery = query;
+ try {
+ setResult(IStatus.OK, NLS.bind(Messages.MavenPomSelectionComponent_searching, activeQuery.toLowerCase()),
+ null);
+
+ Map<String, IndexedArtifact> res = indexManager.getAllIndexes().search( new UserInputSearchExpression(activeQuery), field, classifier);
+
+ //335139 have the managed entries always come up as first results
+ LinkedHashMap<String, IndexedArtifact> managed = new LinkedHashMap<String, IndexedArtifact>();
+ LinkedHashMap<String, IndexedArtifact> nonManaged = new LinkedHashMap<String, IndexedArtifact>();
+ for (Map.Entry<String, IndexedArtifact> art : res.entrySet()) {
+ String key = art.getValue().getGroupId() + ":" + art.getValue().getArtifactId();
+ if (managedKeys.contains(key)) {
+ managed.put(art.getKey(), art.getValue());
+ } else {
+ nonManaged.put(art.getKey(), art.getValue());
+ }
+ }
+ managed.putAll(nonManaged);
+ setResult(IStatus.OK, NLS.bind(Messages.MavenPomSelectionComponent_results, activeQuery, res.size()), managed);
+ } catch(BooleanQuery.TooManyClauses ex) {
+ setResult(IStatus.ERROR, Messages.MavenPomSelectionComponent_toomany,
+ Collections.<String, IndexedArtifact> emptyMap());
+ } catch(final RuntimeException ex) {
+ setResult(IStatus.ERROR, NLS.bind(Messages.MavenPomSelectionComponent_error, ex.toString()),
+ Collections.<String, IndexedArtifact> emptyMap());
+ } catch(final Exception ex) {
+ setResult(IStatus.ERROR, NLS.bind(Messages.MavenPomSelectionComponent_error, ex.getMessage()),
+ Collections.<String, IndexedArtifact> emptyMap());
+ }
+ }
+ return Status.OK_STATUS;
+ }
+
+ protected void canceling() {
+ stop = true;
+ }
+
+ private void setResult(final int severity, final String message, final Map<String, IndexedArtifact> result) {
+ if(stop)
+ return;
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ setStatus(severity, message);
+ if(result != null) {
+ if(!searchResultViewer.getControl().isDisposed()) {
+ searchResultViewer.setInput(result);
+ }
+ }
+ }
+ });
+ }
+ }
+
+ public static class SearchResultLabelProvider extends LabelProvider implements IColorProvider, DelegatingStyledCellLabelProvider.IStyledLabelProvider {
+ private final Set<String> artifactKeys;
+
+ private final String queryType;
+ private final Set<String> managedKeys;
+
+ /**
+ * both managedkeys and artifctkeys are supposed to hold both gr:art:ver combos and gr:art combos
+ * @param artifactKeys
+ * @param managedKeys
+ * @param queryType
+ */
+ public SearchResultLabelProvider(Set<String> artifactKeys, Set<String> managedKeys, String queryType) {
+ this.artifactKeys = artifactKeys;
+ this.queryType = queryType;
+ this.managedKeys = managedKeys;
+ }
+
+ public String getText(Object element) {
+ return super.getText(element);
+ }
+
+ protected String getRepoDisplayName(String repo) {
+ return repo;
+ }
+
+ public Color getForeground(Object element) {
+ if(element instanceof IndexedArtifactFile) {
+ IndexedArtifactFile f = (IndexedArtifactFile) element;
+ if(artifactKeys.contains(getKey(f))) {
+ return Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY);
+ }
+ } else if(element instanceof IndexedArtifact) {
+ IndexedArtifact i = (IndexedArtifact) element;
+ if(artifactKeys.contains(getKey(i))) {
+ return Display.getDefault().getSystemColor(SWT.COLOR_DARK_GRAY);
+ }
+ }
+ return null;
+ }
+
+ public Color getBackground(Object element) {
+ return null;
+ }
+
+ public Image getImage(Object element) {
+ if(element instanceof IndexedArtifactFile) {
+ IndexedArtifactFile f = (IndexedArtifactFile) element;
+ if (managedKeys.contains(getKey(f))) {
+ return MavenImages.getOverlayImage(f.sourcesExists==IIndex.PRESENT ? MavenImages.PATH_VERSION_SRC : MavenImages.PATH_VERSION,
+ MavenImages.PATH_LOCK, IDecoration.BOTTOM_LEFT);
+ }
+
+ if(f.sourcesExists==IIndex.PRESENT) {
+ return MavenImages.IMG_VERSION_SRC;
+ }
+ return MavenImages.IMG_VERSION;
+ } else if(element instanceof IndexedArtifact) {
+ IndexedArtifact i = (IndexedArtifact) element;
+ if (managedKeys.contains(getKey(i))) {
+ return MavenImages.getOverlayImage(MavenImages.PATH_JAR, MavenImages.PATH_LOCK, IDecoration.BOTTOM_LEFT);
+ }
+ return MavenImages.IMG_JAR;
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider#getStyledText(java.lang.Object)
+ */
+ public StyledString getStyledText(Object element) {
+ if(element instanceof IndexedArtifact) {
+ IndexedArtifact a = (IndexedArtifact) element;
+ String name = (a.getClassname() == null ? "" : a.getClassname() + " " + a.getPackageName() + " ") + a.getGroupId() + " " + a.getArtifactId(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ StyledString ss = new StyledString();
+ ss.append(name);
+ if (managedKeys.contains(getKey(a))) {
+ ss.append(Messages.MavenPomSelectionComponent_managed_decoration, StyledString.DECORATIONS_STYLER);
+ }
+ return ss;
+ } else if(element instanceof IndexedArtifactFile) {
+ IndexedArtifactFile f = (IndexedArtifactFile) element;
+ StyledString ss = new StyledString();
+ String name = f.version + " [" + (f.type == null ? "jar" : f.type) + (f.classifier != null ? ", " + f.classifier : "") + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+ ss.append(name);
+ if (managedKeys.contains(getKey(f))) {
+ ss.append(Messages.MavenPomSelectionComponent_managed_decoration, StyledString.DECORATIONS_STYLER);
+ }
+ return ss;
+ }
+ return new StyledString();
+ }
+
+ }
+
+ public static class SearchResultContentProvider implements ITreeContentProvider {
+ private static Object[] EMPTY = new Object[0];
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ public Object[] getElements(Object inputElement) {
+ if(inputElement instanceof Map) {
+ return ((Map<?, ?>) inputElement).values().toArray();
+ }
+ return EMPTY;
+ }
+
+ public Object[] getChildren(Object parentElement) {
+ if(parentElement instanceof IndexedArtifact) {
+ IndexedArtifact a = (IndexedArtifact) parentElement;
+ return a.getFiles().toArray();
+ }
+ return EMPTY;
+ }
+
+ public boolean hasChildren(Object element) {
+ return element instanceof IndexedArtifact;
+ }
+
+ public Object getParent(Object element) {
+ return null;
+ }
+
+ public void dispose() {
+
+ }
+
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomWizard.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomWizard.java
new file mode 100644
index 00000000..2b0eb6f6
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomWizard.java
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Model;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.embedder.MavenModelManager;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWizard;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+
+
+/**
+ * New POM wizard
+ */
+public class MavenPomWizard extends Wizard implements INewWizard {
+ private MavenPomWizardPage artifactPage;
+
+ private MavenDependenciesWizardPage dependenciesPage;
+
+ private ISelection selection;
+
+ /**
+ * Constructor for MavenPomWizard.
+ */
+ public MavenPomWizard() {
+ super();
+ setNeedsProgressMonitor(true);
+ setWindowTitle(Messages.MavenPomWizard_title);
+ }
+
+ /**
+ * Adding the page to the wizard.
+ */
+
+ public void addPages() {
+ artifactPage = new MavenPomWizardPage(selection);
+ dependenciesPage = new MavenDependenciesWizardPage();
+ dependenciesPage.setDependencies(new Dependency[0]);
+
+ addPage(artifactPage);
+ addPage(dependenciesPage);
+ }
+
+ /**
+ * This method is called when 'Finish' button is pressed in the wizard. We will create an operation and run it using
+ * wizard as execution context.
+ */
+ public boolean performFinish() {
+ final String projectName = artifactPage.getProject();
+ final Model model = artifactPage.getModel();
+ @SuppressWarnings("unchecked")
+ List<Dependency> modelDependencies = model.getDependencies();
+ modelDependencies.addAll(Arrays.asList(dependenciesPage.getDependencies()));
+
+ IRunnableWithProgress op = new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InvocationTargetException {
+ monitor.beginTask(Messages.MavenPomWizard_task, 1);
+ try {
+ doFinish(projectName, model, monitor);
+ monitor.worked(1);
+ } catch(CoreException e) {
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+ }
+ };
+
+ try {
+ getContainer().run(true, false, op);
+ } catch(InterruptedException e) {
+ return false;
+ } catch(InvocationTargetException e) {
+ Throwable realException = e.getTargetException();
+ MessageDialog.openError(getShell(), Messages.MavenPomWizard_error_title, realException.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * The worker method. It will find the container, create the file if missing or just replace its contents, and open
+ * the editor on the newly created file.
+ */
+ void doFinish(String projectName, final Model model, IProgressMonitor monitor) throws CoreException {
+ // monitor.beginTask("Creating " + fileName, 2);
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IResource resource = root.findMember(new Path(projectName));
+ if(!resource.exists() || (resource.getType() & IResource.FOLDER | IResource.PROJECT) == 0) {
+ // TODO show warning popup
+ throw new CoreException(new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, -1,
+ NLS.bind(Messages.MavenPomWizard_status_not_exists, projectName), null));
+ }
+
+ IContainer container = (IContainer) resource;
+ final IFile file = container.getFile(new Path(IMavenConstants.POM_FILE_NAME));
+ if(file.exists()) {
+ // TODO show warning popup
+ throw new CoreException(new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, -1, Messages.MavenPomWizard_error_exists, null));
+ }
+
+ final File pom = file.getLocation().toFile();
+
+ try {
+ MavenModelManager modelManager = MavenPlugin.getDefault().getMavenModelManager();
+ modelManager.createMavenModel(file, model);
+
+ getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ try {
+ IDE.openEditor(page, file, true);
+ } catch(PartInitException e) {
+ }
+ }
+ });
+
+ } catch(Exception ex) {
+ MavenLogger.log("Unable to create POM " + pom + "; " + ex.getMessage(), ex);
+
+ }
+ }
+
+ /**
+ * We will accept the selection in the workbench to see if we can initialize from it.
+ *
+ * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
+ */
+ public void init(IWorkbench workbench, IStructuredSelection selection) {
+ this.selection = selection;
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomWizardPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomWizardPage.java
new file mode 100644
index 00000000..f347e879
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomWizardPage.java
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import org.apache.maven.model.Model;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.ContainerSelectionDialog;
+
+
+/**
+ * Wizard page used to specify basic POM parameters
+ */
+public class MavenPomWizardPage extends AbstractMavenWizardPage {
+ private Text projectText;
+
+ private ISelection selection;
+
+ private MavenArtifactComponent pomComponent;
+
+ public MavenPomWizardPage(ISelection selection) {
+ super("wizardPage"); //$NON-NLS-1$
+ setTitle(Messages.MavenPomWizardPage_title);
+ setDescription(Messages.MavenPomWizardPage_desc);
+ this.selection = selection;
+ }
+
+ public void createControl(Composite parent) {
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ layout.makeColumnsEqualWidth = false;
+
+ Composite container = new Composite(parent, SWT.NULL);
+ container.setLayout(layout);
+
+ ModifyListener modifyingListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ dialogChanged();
+ }
+ };
+
+ Label label = new Label(container, SWT.NULL);
+ label.setText(Messages.MavenPomWizardPage_lblProject);
+
+ projectText = new Text(container, SWT.BORDER | SWT.SINGLE);
+ projectText.setEditable(false);
+ projectText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ projectText.addModifyListener(modifyingListener);
+
+ Button button = new Button(container, SWT.PUSH);
+ final GridData gridData_2 = new GridData();
+ button.setLayoutData(gridData_2);
+ button.setText(Messages.MavenPomWizardPage_btnBrowse);
+ button.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ handleBrowse();
+ }
+ });
+
+ pomComponent = new MavenArtifactComponent(container, SWT.NONE);
+ pomComponent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
+ pomComponent.setModifyingListener(modifyingListener);
+ addFieldWithHistory("groupId", pomComponent.getGroupIdCombo()); //$NON-NLS-1$
+ addFieldWithHistory("artifactId", pomComponent.getArtifactIdCombo()); //$NON-NLS-1$
+ addFieldWithHistory("version", pomComponent.getVersionCombo()); //$NON-NLS-1$
+ addFieldWithHistory("name", pomComponent.getNameCombo()); //$NON-NLS-1$
+
+ initialize();
+ dialogChanged();
+ setControl(container);
+ }
+
+ /**
+ * Tests if the current workbench selection is a suitable container to use.
+ */
+ private void initialize() {
+ if(selection != null && !selection.isEmpty() && selection instanceof IStructuredSelection) {
+ IStructuredSelection ssel = (IStructuredSelection) selection;
+ if(ssel.size() > 1) {
+ return;
+ }
+ Object obj = ssel.getFirstElement();
+ if(obj instanceof IResource) {
+ IContainer container;
+ if(obj instanceof IContainer) {
+ container = (IContainer) obj;
+ } else {
+ container = ((IResource) obj).getParent();
+ }
+ projectText.setText(container.getFullPath().toString());
+ pomComponent.setArtifactId(container.getName());
+ pomComponent.setGroupId(container.getName());
+ }
+ }
+
+ pomComponent.setVersion(MavenArtifactComponent.DEFAULT_VERSION);
+ pomComponent.setPackaging(MavenArtifactComponent.DEFAULT_PACKAGING);
+ }
+
+ /**
+ * Uses the standard container selection dialog to choose the new value for the container field.
+ */
+ void handleBrowse() {
+ ContainerSelectionDialog dialog = new ContainerSelectionDialog(getShell(),
+ ResourcesPlugin.getWorkspace().getRoot(), false, Messages.MavenPomWizardPage_dialog_title);
+ dialog.showClosedProjects(false);
+ if(dialog.open() == Window.OK) {
+ Object[] result = dialog.getResult();
+ if(result.length == 1) {
+ projectText.setText(((Path) result[0]).toString());
+ }
+ }
+
+// IJavaModel javaModel = JavaCore.create();
+//
+// IJavaProject[] projects;
+// try {
+// projects = javaModel.getJavaProjects();
+// } catch(JavaModelException e) {
+// MavenLogger.log(e);
+// projects = new IJavaProject[0];
+// }
+//
+// ILabelProvider labelProvider = new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT);
+// ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), labelProvider);
+// dialog.setTitle("Select Project");
+// dialog.setMessage("Choose project where POM will be created");
+// dialog.setElements(projects);
+//
+// String projectName = getProject();
+// if(projectName != null && projectName.length() > 0) {
+// IJavaProject javaProject = javaModel.getJavaProject(projectName);
+// if(javaProject != null) {
+// dialog.setInitialSelections(new Object[] {javaProject});
+// }
+// }
+//
+// if(dialog.open() == Window.OK) {
+// projectText.setText(((IJavaProject) dialog.getFirstResult()).getProject().getFullPath().toString());
+// }
+ }
+
+ /**
+ * Ensures that both text fields are set.
+ */
+ void dialogChanged() {
+ IResource container = ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(getProject()));
+
+ if(getProject().length() == 0) {
+ updateStatus(Messages.MavenPomWizardPage_error_folder);
+ return;
+ }
+ if(container == null || (container.getType() & IResource.FOLDER | IResource.PROJECT) == 0) {
+ updateStatus(Messages.MavenPomWizardPage_error_folder2);
+ return;
+ }
+ if(!container.isAccessible()) {
+ updateStatus(Messages.MavenPomWizardPage_error_folder_write);
+ return;
+ }
+
+ // TODO
+ if(pomComponent.getGroupId().length() == 0) {
+ updateStatus(Messages.MavenPomWizardPage_error_grid);
+ }
+
+ if(pomComponent.getArtifactId().length() == 0) {
+ updateStatus(Messages.MavenPomWizardPage_error_artid);
+ }
+
+ if(pomComponent.getVersion().length() == 0) {
+ updateStatus(Messages.MavenPomWizardPage_error_version);
+ }
+
+ if(pomComponent.getPackaging().length() == 0) {
+ updateStatus(Messages.MavenPomWizardPage_error_pack);
+ }
+
+ updateStatus(null);
+ }
+
+ private void updateStatus(String message) {
+ setErrorMessage(message);
+ setPageComplete(message == null);
+ }
+
+ public String getProject() {
+ return projectText.getText();
+ }
+
+ public Model getModel() {
+ return pomComponent.getModel();
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectCheckoutJob.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectCheckoutJob.java
new file mode 100644
index 00000000..e0bc6205
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectCheckoutJob.java
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.maven.model.Model;
+import org.codehaus.plexus.util.DirectoryScanner;
+import org.codehaus.plexus.util.FileUtils;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.resources.WorkspaceJob;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.IWizard;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.MavenConsole;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.embedder.MavenModelManager;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.IMavenProjectImportResult;
+import org.eclipse.m2e.core.project.LocalProjectScanner;
+import org.eclipse.m2e.core.project.MavenProjectInfo;
+import org.eclipse.m2e.core.project.MavenProjectScmInfo;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.core.ui.internal.actions.OpenMavenConsoleAction;
+import org.eclipse.m2e.scm.MavenCheckoutOperation;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IWorkingSet;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.NewProjectAction;
+import org.eclipse.ui.progress.IProgressConstants;
+
+
+/**
+ * Maven project checkout Job
+ *
+ * @author Eugene Kuleshov
+ */
+public abstract class MavenProjectCheckoutJob extends WorkspaceJob {
+
+ final ProjectImportConfiguration configuration;
+
+ boolean checkoutAllProjects;
+
+ Collection<MavenProjectInfo> projects;
+
+ File location;
+
+ List<String> collectedLocations = new ArrayList<String>();
+
+ final List<IWorkingSet> workingSets;
+
+ public MavenProjectCheckoutJob(ProjectImportConfiguration importConfiguration, boolean checkoutAllProjects,
+ List<IWorkingSet> workingSets) {
+ super(Messages.MavenProjectCheckoutJob_title);
+ this.configuration = importConfiguration;
+ this.checkoutAllProjects = checkoutAllProjects;
+ this.workingSets = workingSets;
+
+ setProperty(IProgressConstants.ACTION_PROPERTY, new OpenMavenConsoleAction());
+ addJobChangeListener(new CheckoutJobChangeListener());
+ }
+
+ public void setLocation(File location) {
+ this.location = location;
+ }
+
+ protected abstract Collection<MavenProjectScmInfo> getProjects(IProgressMonitor monitor) throws InterruptedException;
+
+
+ // WorkspaceJob
+
+ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
+ try {
+ MavenPlugin plugin = MavenPlugin.getDefault();
+ MavenConsole console = plugin.getConsole();
+
+ MavenCheckoutOperation operation = new MavenCheckoutOperation(location, getProjects(monitor), console);
+ operation.run(monitor);
+ collectedLocations.addAll(operation.getLocations());
+
+ IWorkspaceRoot workspace = ResourcesPlugin.getWorkspace().getRoot();
+
+ MavenModelManager modelManager = plugin.getMavenModelManager();
+
+ LocalProjectScanner scanner = new LocalProjectScanner(workspace.getLocation().toFile(), operation.getLocations(),
+ true, modelManager);
+ scanner.run(monitor);
+
+ this.projects = plugin.getProjectConfigurationManager().collectProjects(scanner.getProjects());
+
+ if(checkoutAllProjects) {
+ // check if there any project name conflicts
+ for(MavenProjectInfo projectInfo : projects) {
+ Model model = projectInfo.getModel();
+ if(model == null) {
+ model = modelManager.readMavenModel(projectInfo.getPomFile());
+ projectInfo.setModel(model);
+ }
+
+ String projectName = configuration.getProjectName(model);
+ IProject project = workspace.getProject(projectName);
+ if(project.exists()) {
+ checkoutAllProjects = false;
+ break;
+ }
+ }
+ }
+
+ return Status.OK_STATUS;
+
+ } catch(InterruptedException ex) {
+ return Status.CANCEL_STATUS;
+ }
+ }
+
+ /**
+ * Checkout job listener
+ */
+ final class CheckoutJobChangeListener extends JobChangeAdapter {
+
+ public void done(IJobChangeEvent event) {
+ IStatus result = event.getResult();
+ if(result.getSeverity() == IStatus.CANCEL) {
+ return;
+ } else if(!result.isOK()) {
+ // XXX report errors
+ return;
+ }
+
+ if(projects.isEmpty()) {
+ MavenPlugin.getDefault().getConsole().logMessage("No Maven projects to import");
+
+ if(collectedLocations.size()==1) {
+ final String location = collectedLocations.get(0);
+
+ DirectoryScanner projectScanner = new DirectoryScanner();
+ projectScanner.setBasedir(location);
+ projectScanner.setIncludes(new String[] {"**/.project"}); //$NON-NLS-1$
+ projectScanner.scan();
+
+ String[] projectFiles = projectScanner.getIncludedFiles();
+ if(projectFiles!=null && projectFiles.length>0) {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ boolean res = MessageDialog.openConfirm(Display.getDefault().getActiveShell(), //
+ Messages.MavenProjectCheckoutJob_confirm_title, //
+ Messages.MavenProjectCheckoutJob_confirm_message);
+ if(res) {
+ IWizard wizard = new ProjectsImportWizard(collectedLocations.get(0));
+ WizardDialog dialog = new WizardDialog(Display.getDefault().getActiveShell(), wizard);
+ dialog.open();
+ } else {
+ cleanup(collectedLocations);
+ }
+ }
+ });
+ return;
+ }
+
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ boolean res = MessageDialog.openConfirm(Display.getDefault().getActiveShell(), //
+ Messages.MavenProjectCheckoutJob_confirm2_title, //
+ Messages.MavenProjectCheckoutJob_confirm2_message);
+ if(res) {
+ Clipboard clipboard = new Clipboard(Display.getDefault());
+ clipboard.setContents(new Object[] { location }, new Transfer[] { TextTransfer.getInstance() });
+
+ NewProjectAction newProjectAction = new NewProjectAction(PlatformUI.getWorkbench().getActiveWorkbenchWindow());
+ newProjectAction.run();
+ } else {
+ cleanup(collectedLocations);
+ }
+ }
+ });
+ return;
+ }
+
+ cleanup(collectedLocations);
+ }
+
+ if(checkoutAllProjects) {
+ final MavenPlugin plugin = MavenPlugin.getDefault();
+ WorkspaceJob job = new AbstactCreateMavenProjectJob(Messages.MavenProjectCheckoutJob_job, workingSets) {
+ @Override
+ protected List<IProject> doCreateMavenProjects(IProgressMonitor monitor) throws CoreException {
+ Set<MavenProjectInfo> projectSet = plugin.getProjectConfigurationManager().collectProjects(projects);
+
+ List<IMavenProjectImportResult> results = plugin.getProjectConfigurationManager().importProjects(
+ projectSet, configuration, monitor);
+
+ return toProjects(results);
+ }
+ };
+ ISchedulingRule rule = ResourcesPlugin.getWorkspace().getRuleFactory()
+ .modifyRule(ResourcesPlugin.getWorkspace().getRoot());
+ job.setRule(rule);
+ job.schedule();
+
+ } else {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ MavenImportWizard wizard = new MavenImportWizard(configuration, collectedLocations);
+ WizardDialog dialog = new WizardDialog(Display.getDefault().getActiveShell(), wizard);
+ int res = dialog.open();
+ if(res == Window.CANCEL) {
+ cleanup(collectedLocations);
+ }
+ }
+ });
+ }
+ }
+
+ protected void cleanup(List<String> locations) {
+ MavenConsole console = MavenPlugin.getDefault().getConsole();
+ for(String location : locations) {
+ try {
+ FileUtils.deleteDirectory(location);
+ } catch(IOException ex) {
+ String msg = "Can't delete " + location;
+ console.logError(msg + "; " + (ex.getMessage()==null ? ex.toString() : ex.getMessage())); //$NON-NLS-1$
+ MavenLogger.log(msg, ex);
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectSelectionDialog.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectSelectionDialog.java
new file mode 100644
index 00000000..4ed6466c
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectSelectionDialog.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.ui.internal.dialogs.AbstractMavenDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.dialogs.FilteredTree;
+import org.eclipse.ui.dialogs.PatternFilter;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+
+/**
+ * A simple dialog allowing the selection of Maven projects and subfolders containing POMs.
+ */
+public class MavenProjectSelectionDialog extends AbstractMavenDialog {
+
+ protected static final String DIALOG_SETTINGS = MavenProjectSelectionDialog.class.getName();
+
+ protected static final long SEARCH_DELAY = 500L; //in milliseconds
+
+ private FilteredTree filteredTree;
+
+ private boolean useCheckboxTree;
+
+ /** Creates a dialog instance. */
+ public MavenProjectSelectionDialog(Shell parent, boolean useCheckboxTree) {
+ this(parent);
+ this.useCheckboxTree = useCheckboxTree;
+ }
+
+ /** Creates a dialog instance. */
+ public MavenProjectSelectionDialog(Shell parent) {
+ super(parent, DIALOG_SETTINGS);
+
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ setTitle(Messages.getString("projectSelectionDialog.title")); //$NON-NLS-1$
+ }
+
+ /** Produces the result of the selection. */
+ protected void computeResult() {
+ if(useCheckboxTree) {
+ List<Object> result = new ArrayList<Object>();
+ collectCheckedItems(getViewer().getTree().getItems(), result);
+ setResult(result);
+ } else {
+ setResult(((IStructuredSelection) getViewer().getSelection()).toList());
+ }
+ }
+
+ private void collectCheckedItems(TreeItem[] items, List<Object> list) {
+ for(TreeItem item : items) {
+ if(item.getChecked()) {
+ Object data = item.getData();
+ if(data != null) {
+ list.add(data);
+ }
+ }
+ collectCheckedItems(item.getItems(), list);
+ }
+ }
+
+ /** Creates the dialog controls. */
+ protected Control createDialogArea(Composite parent) {
+ readSettings();
+
+ Composite composite = (Composite) super.createDialogArea(parent);
+
+ filteredTree = new FilteredTree(composite, SWT.BORDER | (useCheckboxTree ? SWT.CHECK : 0), new PatternFilter(),
+ true);
+ filteredTree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ getViewer().setContentProvider(new MavenContainerContentProvider());
+ getViewer().setLabelProvider(WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider());
+ getViewer().setInput(ResourcesPlugin.getWorkspace());
+
+ getViewer().addDoubleClickListener(new IDoubleClickListener() {
+ public void doubleClick(DoubleClickEvent event) {
+ okPressed();
+ }
+ });
+
+ return composite;
+ }
+
+ protected void okPressed() {
+ super.okPressed();
+ }
+
+ protected TreeViewer getViewer() {
+ return filteredTree.getViewer();
+ }
+
+ /** The content provider class. */
+ protected static class MavenContainerContentProvider implements ITreeContentProvider {
+
+ /** Returns the children of the parent node. */
+ public Object[] getChildren(Object parent) {
+ if(parent instanceof IWorkspace) {
+ IProject[] projects = ((IWorkspace) parent).getRoot().getProjects();
+
+ List<IProject> children = new ArrayList<IProject>();
+ for(IProject project : projects) {
+ try {
+ if(project.isOpen() && project.hasNature(IMavenConstants.NATURE_ID)) {
+ children.add(project);
+ }
+ } catch(CoreException e) {
+ MavenLogger.log("Error checking project: " + e.getMessage(), e);
+ }
+ }
+ return children.toArray();
+ } else if(parent instanceof IContainer) {
+ IContainer container = (IContainer) parent;
+ if(container.isAccessible()) {
+ try {
+ List<IResource> children = new ArrayList<IResource>();
+ IResource[] members = container.members();
+ for(int i = 0; i < members.length; i++ ) {
+ if(members[i] instanceof IContainer
+ && ((IContainer) members[i]).exists(new Path(IMavenConstants.POM_FILE_NAME))) {
+ children.add(members[i]);
+ }
+ }
+ return children.toArray();
+ } catch(CoreException e) {
+ MavenLogger.log("Error checking container: " + e.getMessage(), e);
+ }
+ }
+ }
+ return new Object[0];
+ }
+
+ /** Returns the parent of the given element. */
+ public Object getParent(Object element) {
+ if(element instanceof IResource) {
+ return ((IResource) element).getParent();
+ }
+ return null;
+ }
+
+ /** Returns true if the element has any children. */
+ public boolean hasChildren(Object element) {
+ return getChildren(element).length > 0;
+ }
+
+ /** Disposes of any resources used. */
+ public void dispose() {
+ }
+
+ /** Handles the input change. */
+ public void inputChanged(Viewer viewer, Object arg1, Object arg2) {
+ }
+
+ /** Returns the elements of the given root. */
+ public Object[] getElements(Object element) {
+ return getChildren(element);
+ }
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizard.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizard.java
new file mode 100644
index 00000000..319cd34f
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizard.java
@@ -0,0 +1,325 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.maven.archetype.catalog.Archetype;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Model;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+import org.eclipse.m2e.core.ui.internal.actions.SelectionUtil;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.INewWizard;
+
+
+/**
+ * Simple project wizard for creating a new Maven2 project.
+ * <p>
+ * The wizard provides the following functionality to the user:
+ * <ul>
+ * <li>Create the project in the workspace or at some external location.</li>
+ * <li>Provide information about the Maven2 artifact to create.</li>
+ * <li>Choose directories of the default Maven2 directory structure to create.</li>
+ * <li>Choose a set of Maven2 dependencies for the project.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Once the wizard has finished, the following resources are created and configured:
+ * <ul>
+ * <li>A POM file containing the given artifact information and the chosen dependencies.</li>
+ * <li>The chosen Maven2 directories.</li>
+ * <li>The .classpath file is configured to hold appropriate entries for the Maven2 directories created as well as the
+ * Java and Maven2 classpath containers.</li>
+ * </ul>
+ * </p>
+ */
+public class MavenProjectWizard extends AbstractMavenProjectWizard implements INewWizard {
+
+ /** The wizard page for gathering general project information. */
+ protected MavenProjectWizardLocationPage locationPage;
+
+ /** The archetype selection page. */
+ protected MavenProjectWizardArchetypePage archetypePage;
+
+ /** The wizard page for gathering Maven2 project information. */
+ protected MavenProjectWizardArtifactPage artifactPage;
+
+ /** The wizard page for gathering archetype project information. */
+ protected MavenProjectWizardArchetypeParametersPage parametersPage;
+
+ /** The wizard page for choosing the Maven2 dependencies to use. */
+ protected MavenDependenciesWizardPage dependenciesPage;
+
+ protected Button simpleProject;
+
+ /**
+ * Default constructor. Sets the title and image of the wizard.
+ */
+ public MavenProjectWizard() {
+ super();
+ setWindowTitle(Messages.getString("wizard.project.title")); //$NON-NLS-1$
+ setDefaultPageImageDescriptor(MavenImages.WIZ_NEW_PROJECT);
+ setNeedsProgressMonitor(true);
+ }
+
+ public void addPages() {
+ locationPage = new MavenProjectWizardLocationPage(importConfiguration, //
+ Messages.getString("wizard.project.page.project.title"), // //$NON-NLS-1$
+ Messages.getString("wizard.project.page.project.description"), workingSets) { //$NON-NLS-1$
+
+ protected void createAdditionalControls(Composite container) {
+ simpleProject = new Button(container, SWT.CHECK);
+ simpleProject.setText(Messages.getString("wizard.project.page.project.simpleProject")); //$NON-NLS-1$
+ simpleProject.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 3, 1));
+ simpleProject.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ validate();
+ }
+ });
+
+ Label label = new Label(container, SWT.NONE);
+ GridData labelData = new GridData(SWT.FILL, SWT.TOP, false, false, 3, 1);
+ labelData.heightHint = 10;
+ label.setLayoutData(labelData);
+ }
+
+ /** Skips the archetype selection page if the user chooses a simple project. */
+ public IWizardPage getNextPage() {
+ return getPage(simpleProject.getSelection() ? "MavenProjectWizardArtifactPage" : "MavenProjectWizardArchetypePage"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ };
+ locationPage.setLocationPath(SelectionUtil.getSelectedLocation(selection));
+
+ archetypePage = new MavenProjectWizardArchetypePage(importConfiguration);
+ parametersPage = new MavenProjectWizardArchetypeParametersPage(importConfiguration);
+ artifactPage = new MavenProjectWizardArtifactPage(importConfiguration);
+ dependenciesPage = new MavenDependenciesWizardPage(importConfiguration, //
+ Messages.getString("wizard.project.page.dependencies.title"), // //$NON-NLS-1$
+ Messages.getString("wizard.project.page.dependencies.description")); //$NON-NLS-1$
+ dependenciesPage.setDependencies(new Dependency[0]);
+ dependenciesPage.setShowScope(true);
+
+ addPage(locationPage);
+ addPage(archetypePage);
+ addPage(parametersPage);
+ addPage(artifactPage);
+ addPage(dependenciesPage);
+ }
+
+ /** Adds the listeners after the page controls are created. */
+ public void createPageControls(Composite pageContainer) {
+ super.createPageControls(pageContainer);
+
+ simpleProject.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ boolean isSimpleproject = simpleProject.getSelection();
+ archetypePage.setUsed(!isSimpleproject);
+ parametersPage.setUsed(!isSimpleproject);
+ artifactPage.setUsed(isSimpleproject);
+ getContainer().updateButtons();
+ }
+ });
+
+ archetypePage.addArchetypeSelectionListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent selectionchangedevent) {
+ parametersPage.setArchetype(archetypePage.getArchetype());
+ getContainer().updateButtons();
+ }
+ });
+
+// locationPage.addProjectNameListener(new ModifyListener() {
+// public void modifyText(ModifyEvent e) {
+// parametersPage.setProjectName(locationPage.getProjectName());
+// artifactPage.setProjectName(locationPage.getProjectName());
+// }
+// });
+ }
+
+ /** Returns the model. */
+ public Model getModel() {
+ if(simpleProject.getSelection()) {
+ return artifactPage.getModel();
+ }
+ return parametersPage.getModel();
+ }
+
+ /**
+ * To perform the actual project creation, an operation is created and run using this wizard as execution context.
+ * That way, messages about the progress of the project creation are displayed inside the wizard.
+ */
+ public boolean performFinish() {
+ // First of all, we extract all the information from the wizard pages.
+ // Note that this should not be done inside the operation we will run
+ // since many of the wizard pages' methods can only be invoked from within
+ // the SWT event dispatcher thread. However, the operation spawns a new
+ // separate thread to perform the actual work, i.e. accessing SWT elements
+ // from within that thread would lead to an exception.
+
+// final IProject project = locationPage.getProjectHandle();
+// final String projectName = locationPage.getProjectName();
+
+ // Get the location where to create the project. For some reason, when using
+ // the default workspace location for a project, we have to pass null
+ // instead of the actual location.
+ final Model model = getModel();
+ final String projectName = importConfiguration.getProjectName(model);
+ IStatus nameStatus = importConfiguration.validateProjectName(model);
+ if(!nameStatus.isOK()) {
+ MessageDialog.openError(getShell(), Messages.getString("wizard.project.job.failed", projectName), nameStatus.getMessage()); //$NON-NLS-1$
+ return false;
+ }
+
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+
+ final IPath location = locationPage.isInWorkspace() ? null : locationPage.getLocationPath();
+ final IWorkspaceRoot root = workspace.getRoot();
+ final IProject project = importConfiguration.getProject(root, model);
+
+ boolean pomExists = ( locationPage.isInWorkspace() ?
+ root.getLocation().append(project.getName()) : location ).append(IMavenConstants.POM_FILE_NAME).toFile().exists();
+ if ( pomExists ) {
+ MessageDialog.openError(getShell(), Messages.getString("wizard.project.job.failed", projectName), Messages.getString("wizard.project.error.pomAlreadyExists")); //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+ }
+
+ final Job job;
+
+ final MavenPlugin plugin = MavenPlugin.getDefault();
+
+ if(simpleProject.getSelection()) {
+ List<Dependency> modelDependencies = model.getDependencies();
+ modelDependencies.addAll(Arrays.asList(dependenciesPage.getDependencies()));
+
+ final String[] folders = artifactPage.getFolders();
+
+ job = new AbstactCreateMavenProjectJob(Messages.getString("wizard.project.job.creatingProject", projectName), workingSets) { //$NON-NLS-1$
+ @Override
+ protected List<IProject> doCreateMavenProjects(IProgressMonitor monitor) throws CoreException {
+ plugin.getProjectConfigurationManager().createSimpleProject(project, location, model, folders, //
+ importConfiguration, monitor);
+ return Arrays.asList(project);
+ }
+ };
+
+ } else {
+ final Archetype archetype = archetypePage.getArchetype();
+
+ final String groupId = model.getGroupId();
+ final String artifactId = model.getArtifactId();
+ final String version = model.getVersion();
+ final String javaPackage = parametersPage.getJavaPackage();
+ final Properties properties = parametersPage.getProperties();
+
+ job = new AbstactCreateMavenProjectJob(Messages.getString(
+ "wizard.project.job.creating", archetype.getArtifactId()), workingSets) { //$NON-NLS-1$
+ @Override
+ protected List<IProject> doCreateMavenProjects(IProgressMonitor monitor) throws CoreException {
+ plugin.getProjectConfigurationManager().createArchetypeProject(project, location, archetype, //
+ groupId, artifactId, version, javaPackage, properties, importConfiguration, monitor);
+ return Arrays.asList(project);
+ }
+ };
+ }
+
+ job.addJobChangeListener(new JobChangeAdapter() {
+ public void done(IJobChangeEvent event) {
+ final IStatus result = event.getResult();
+ if(!result.isOK()) {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ MessageDialog.openError(getShell(), //
+ Messages.getString("wizard.project.job.failed", projectName), result.getMessage()); //$NON-NLS-1$
+ }
+ });
+ }
+ }
+ });
+
+
+ job.setRule(plugin.getProjectConfigurationManager().getRule());
+ job.schedule();
+
+// ProjectListener listener = new ProjectListener();
+// workspace.addResourceChangeListener(listener, IResourceChangeEvent.POST_CHANGE);
+// try {
+// job.setRule(plugin.getProjectConfigurationManager().getRule());
+// job.schedule();
+//
+// // MNGECLIPSE-766 wait until new project is created
+// while(listener.getNewProject() == null && (job.getState() & (Job.WAITING | Job.RUNNING)) > 0) {
+// try {
+// Thread.sleep(100L);
+// } catch (InterruptedException ex) {
+// // ignore
+// }
+// }
+//
+// } finally {
+// workspace.removeResourceChangeListener(listener);
+// }
+
+ return true;
+ }
+
+
+// static class ProjectListener implements IResourceChangeListener {
+// private IProject newProject = null;
+//
+// public void resourceChanged(IResourceChangeEvent event) {
+// IResourceDelta root = event.getDelta();
+// IResourceDelta[] projectDeltas = root.getAffectedChildren();
+// for (int i = 0; i < projectDeltas.length; i++) {
+// IResourceDelta delta = projectDeltas[i];
+// IResource resource = delta.getResource();
+// if (delta.getKind() == IResourceDelta.ADDED) {
+// newProject = (IProject)resource;
+// }
+// }
+// }
+// /**
+// * Gets the newProject.
+// * @return Returns a IProject
+// */
+// public IProject getNewProject() {
+// return newProject;
+// }
+// }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardArchetypePage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardArchetypePage.java
new file mode 100644
index 00000000..c7b888a1
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardArchetypePage.java
@@ -0,0 +1,951 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.maven.archetype.catalog.Archetype;
+import org.apache.maven.archetype.catalog.ArchetypeCatalog;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.repository.DefaultArtifactRepository;
+import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.ComboViewer;
+import org.eclipse.jface.viewers.IOpenListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.OpenEvent;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.IWizardContainer;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.archetype.ArchetypeCatalogFactory;
+import org.eclipse.m2e.core.archetype.ArchetypeCatalogFactory.NexusIndexerCatalogFactory;
+import org.eclipse.m2e.core.archetype.ArchetypeManager;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.index.IMutableIndex;
+import org.eclipse.m2e.core.index.IndexListener;
+import org.eclipse.m2e.core.index.IndexManager;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.core.repository.IRepository;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+import org.eclipse.m2e.core.ui.internal.util.M2EUIUtils;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+
+
+/**
+ * Maven Archetype selection wizard page presents the user with a list of available Maven Archetypes available for
+ * creating new project.
+ */
+public class MavenProjectWizardArchetypePage extends AbstractMavenWizardPage implements IndexListener {
+
+ private static final String KEY_CATALOG = "catalog"; //$NON-NLS-1$
+
+ private static final String ALL_CATALOGS = org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_all;
+
+ public static final Comparator<Archetype> ARCHETYPE_COMPARATOR = new Comparator<Archetype>() {
+
+ public int compare(Archetype a1, Archetype a2) {
+ String g1 = a1.getGroupId();
+ String g2 = a2.getGroupId();
+ int res = g1.compareTo(g2);
+ if(res != 0) {
+ return res;
+ }
+
+ String i1 = a1.getArtifactId();
+ String i2 = a2.getArtifactId();
+ res = i1.compareTo(i2);
+ if(res != 0) {
+ return res;
+ }
+
+ String v1 = a1.getVersion();
+ String v2 = a2.getVersion();
+ if(v1 == null) {
+ return v2 == null ? 0 : -1;
+ }
+ return v1.compareTo(v2);
+ }
+
+ };
+
+ ComboViewer catalogsComboViewer;
+
+ Text filterText;
+
+ /** the archetype table viewer */
+ TableViewer viewer;
+
+ /** the description value label */
+ Text descriptionText;
+
+ Button showLastVersionButton;
+
+ Button includeShapshotsButton;
+
+ Button addArchetypeButton;
+
+ /** the list of available archetypes */
+ volatile Collection<Archetype> archetypes;
+
+ Collection<Archetype> lastVersionArchetypes;
+
+ /** a flag indicating if the archetype selection is actually used in the wizard */
+ private boolean isUsed = true;
+
+ ArchetypeCatalogFactory catalogFactory = null;
+
+ /**
+ * Default constructor. Sets the title and description of this wizard page and marks it as not being complete as user
+ * input is required for continuing.
+ */
+ public MavenProjectWizardArchetypePage(ProjectImportConfiguration projectImportConfiguration) {
+ super("MavenProjectWizardArchetypePage", projectImportConfiguration); //$NON-NLS-1$
+ setTitle(Messages.getString("wizard.project.page.archetype.title")); //$NON-NLS-1$
+ setDescription(Messages.getString("wizard.project.page.archetype.description")); //$NON-NLS-1$
+ setPageComplete(false);
+ }
+
+ /** Creates the page controls. */
+ public void createControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout(3, false));
+
+ createViewer(composite);
+
+ createAdvancedSettings(composite, new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1));
+
+ MavenPlugin.getDefault().getIndexManager().addIndexListener(this);
+ setControl(composite);
+ }
+
+ /** Creates the archetype table viewer. */
+ private void createViewer(Composite parent) {
+ Label catalogsLabel = new Label(parent, SWT.NONE);
+ catalogsLabel.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_lblCatalog);
+
+ Composite catalogsComposite = new Composite(parent, SWT.NONE);
+ GridLayout catalogsCompositeLayout = new GridLayout();
+ catalogsCompositeLayout.marginWidth = 0;
+ catalogsCompositeLayout.marginHeight = 0;
+ catalogsCompositeLayout.numColumns = 2;
+ catalogsComposite.setLayout(catalogsCompositeLayout);
+ catalogsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 2, 1));
+
+ catalogsComboViewer = new ComboViewer(catalogsComposite);
+ catalogsComboViewer.getControl().setData("name", "catalogsCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+ catalogsComboViewer.getCombo().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ catalogsComboViewer.setContentProvider(new IStructuredContentProvider() {
+ public Object[] getElements(Object input) {
+
+ if(input instanceof Collection) {
+ return ((Collection<?>) input).toArray();
+ }
+ return new Object[0];
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ public void dispose() {
+ }
+ });
+
+ catalogsComboViewer.setLabelProvider(new LabelProvider() {
+ public String getText(Object element) {
+ if(element instanceof ArchetypeCatalogFactory) {
+ return ((ArchetypeCatalogFactory) element).getDescription();
+ } else if(element instanceof String) {
+ return element.toString();
+ }
+ return super.getText(element);
+ }
+ });
+
+ catalogsComboViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ ISelection selection = event.getSelection();
+ if(selection instanceof IStructuredSelection) {
+ Object factory = ((IStructuredSelection) selection).getFirstElement();
+ if(factory instanceof ArchetypeCatalogFactory) {
+ catalogFactory = (ArchetypeCatalogFactory) factory;
+ } else if(factory instanceof String) {
+ catalogFactory = null;
+ }
+ reloadViewer();
+ } else {
+ catalogFactory = null;
+ loadArchetypes(null, null, null);
+ }
+ //remember what was switched to here
+ if(dialogSettings != null && catalogFactory != null) {
+ dialogSettings.put(KEY_CATALOG, catalogFactory.getId());
+ }
+ }
+ });
+
+ final ArchetypeManager archetypeManager = MavenPlugin.getDefault().getArchetypeManager();
+ Collection<ArchetypeCatalogFactory> archetypeCatalogs = archetypeManager.getArchetypeCatalogs();
+ ArrayList allCatalogs = new ArrayList(archetypeManager.getArchetypeCatalogs());
+ allCatalogs.add(0, ALL_CATALOGS);
+ catalogsComboViewer.setInput(allCatalogs);
+
+ Button configureButton = new Button(catalogsComposite, SWT.NONE);
+ configureButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ configureButton.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_btnConfigure);
+ configureButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ PreferencesUtil.createPreferenceDialogOn(getShell(),
+ "org.eclipse.m2e.core.preferences.MavenArchetypesPreferencePage", null, null).open(); //$NON-NLS-1$
+
+ if(catalogFactory == null || archetypeManager.getArchetypeCatalogFactory(catalogFactory.getId()) == null) {
+ catalogFactory = archetypeManager.getArchetypeCatalogFactory(NexusIndexerCatalogFactory.ID);
+ }
+
+ catalogsComboViewer.setInput(archetypeManager.getArchetypeCatalogs());
+ catalogsComboViewer.setSelection(new StructuredSelection(catalogFactory));
+ }
+ });
+
+ Label filterLabel = new Label(parent, SWT.NONE);
+ filterLabel.setLayoutData(new GridData());
+ filterLabel.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_lblFilter);
+
+ QuickViewerFilter quickViewerFilter = new QuickViewerFilter();
+ LastVersionFilter versionFilter = new LastVersionFilter();
+ IncludeSnapshotsFilter snapshotsFilter = new IncludeSnapshotsFilter();
+
+ filterText = new Text(parent, SWT.BORDER);
+ filterText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ filterText.addModifyListener(quickViewerFilter);
+ filterText.addKeyListener(new KeyAdapter() {
+ public void keyPressed(KeyEvent e) {
+ if(e.keyCode == SWT.ARROW_DOWN) {
+ viewer.getTable().setFocus();
+ viewer.getTable().setSelection(0);
+
+ viewer.setSelection(new StructuredSelection(viewer.getElementAt(0)), true);
+ }
+ }
+ });
+
+ ToolBar toolBar = new ToolBar(parent, SWT.FLAT);
+ toolBar.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+
+ final ToolItem clearToolItem = new ToolItem(toolBar, SWT.PUSH);
+ clearToolItem.setEnabled(false);
+ clearToolItem.setImage(MavenImages.IMG_CLEAR);
+ clearToolItem.setDisabledImage(MavenImages.IMG_CLEAR_DISABLED);
+ clearToolItem.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ filterText.setText(""); //$NON-NLS-1$
+ }
+ });
+
+ filterText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ clearToolItem.setEnabled(filterText.getText().length() > 0);
+ }
+ });
+
+ SashForm sashForm = new SashForm(parent, SWT.VERTICAL);
+ GridData gd_sashForm = new GridData(SWT.FILL, SWT.FILL, false, true, 3, 1);
+ // gd_sashForm.widthHint = 500;
+ gd_sashForm.heightHint = 200;
+ sashForm.setLayoutData(gd_sashForm);
+ sashForm.setLayout(new GridLayout());
+
+ Composite composite1 = new Composite(sashForm, SWT.NONE);
+ GridLayout gridLayout1 = new GridLayout();
+ gridLayout1.horizontalSpacing = 0;
+ gridLayout1.marginWidth = 0;
+ gridLayout1.marginHeight = 0;
+ composite1.setLayout(gridLayout1);
+
+ viewer = new TableViewer(composite1, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION);
+ Table table = viewer.getTable();
+ table.setData("name", "archetypesTable"); //$NON-NLS-1$ //$NON-NLS-2$
+ table.setHeaderVisible(true);
+
+ TableColumn column1 = new TableColumn(table, SWT.LEFT);
+ column1.setWidth(150);
+ column1.setText(Messages.getString("wizard.project.page.archetype.column.groupId")); //$NON-NLS-1$
+
+ TableColumn column0 = new TableColumn(table, SWT.LEFT);
+ column0.setWidth(150);
+ column0.setText(Messages.getString("wizard.project.page.archetype.column.artifactId")); //$NON-NLS-1$
+
+ TableColumn column2 = new TableColumn(table, SWT.LEFT);
+ column2.setWidth(100);
+ column2.setText(Messages.getString("wizard.project.page.archetype.column.version")); //$NON-NLS-1$
+
+ GridData tableData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ tableData.widthHint = 400;
+ tableData.heightHint = 200;
+ table.setLayoutData(tableData);
+
+ viewer.setLabelProvider(new ArchetypeLabelProvider());
+
+ viewer.setComparator(new ViewerComparator() {
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ return ARCHETYPE_COMPARATOR.compare((Archetype) e1, (Archetype) e2);
+ }
+ });
+
+ viewer.addFilter(quickViewerFilter);
+ viewer.addFilter(versionFilter);
+ viewer.addFilter(snapshotsFilter);
+
+ viewer.setContentProvider(new IStructuredContentProvider() {
+ public Object[] getElements(Object inputElement) {
+ if(inputElement instanceof Collection) {
+ return ((Collection<?>) inputElement).toArray();
+ }
+ return new Object[0];
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+ });
+
+ viewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ Archetype archetype = getArchetype();
+ if(archetype != null) {
+ String repositoryUrl = archetype.getRepository();
+ String description = archetype.getDescription();
+
+ String text = description == null ? "" : description; //$NON-NLS-1$
+ text = text.replaceAll("\n", "").replaceAll("\\s{2,}", " "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+ if(repositoryUrl != null) {
+ text += text.length() > 0 ? "\n" + repositoryUrl : repositoryUrl; //$NON-NLS-1$
+ }
+
+ descriptionText.setText(text);
+ setPageComplete(true);
+ } else {
+ descriptionText.setText(""); //$NON-NLS-1$
+ setPageComplete(false);
+ }
+ }
+ });
+
+ viewer.addOpenListener(new IOpenListener() {
+ public void open(OpenEvent openevent) {
+ if(canFlipToNextPage()) {
+ getContainer().showPage(getNextPage());
+ }
+ }
+ });
+
+ Composite composite2 = new Composite(sashForm, SWT.NONE);
+ GridLayout gridLayout2 = new GridLayout();
+ gridLayout2.marginHeight = 0;
+ gridLayout2.marginWidth = 0;
+ gridLayout2.horizontalSpacing = 0;
+ composite2.setLayout(gridLayout2);
+
+ descriptionText = new Text(composite2, SWT.WRAP | SWT.V_SCROLL | SWT.READ_ONLY | SWT.MULTI | SWT.BORDER);
+
+ GridData descriptionTextData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ descriptionTextData.heightHint = 40;
+ descriptionText.setLayoutData(descriptionTextData);
+ //whole dialog resizes badly without the width hint to the desc text
+ descriptionTextData.widthHint = 250;
+ sashForm.setWeights(new int[] {80, 20});
+
+ Composite buttonComposite = new Composite(parent, SWT.NONE);
+ GridData gd_buttonComposite = new GridData(SWT.FILL, SWT.CENTER, false, false, 3, 1);
+ buttonComposite.setLayoutData(gd_buttonComposite);
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.marginHeight = 0;
+ gridLayout.marginWidth = 0;
+ gridLayout.numColumns = 3;
+ buttonComposite.setLayout(gridLayout);
+
+ showLastVersionButton = new Button(buttonComposite, SWT.CHECK);
+ showLastVersionButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false));
+ showLastVersionButton.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_btnLast);
+ showLastVersionButton.setSelection(true);
+ showLastVersionButton.addSelectionListener(versionFilter);
+
+ includeShapshotsButton = new Button(buttonComposite, SWT.CHECK);
+ GridData buttonData = new GridData(SWT.LEFT, SWT.CENTER, true, false);
+ buttonData.horizontalIndent = 25;
+ includeShapshotsButton.setLayoutData(buttonData);
+ includeShapshotsButton.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_btnSnapshots);
+ includeShapshotsButton.setSelection(false);
+ includeShapshotsButton.addSelectionListener(snapshotsFilter);
+
+ addArchetypeButton = new Button(buttonComposite, SWT.NONE);
+ addArchetypeButton.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_btnAdd);
+ addArchetypeButton.setData("name", "addArchetypeButton"); //$NON-NLS-1$ //$NON-NLS-2$
+ buttonData = new GridData(SWT.RIGHT, SWT.CENTER, true, false);
+ buttonData.horizontalIndent = 35;
+ addArchetypeButton.setLayoutData(buttonData);
+
+ addArchetypeButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ CustomArchetypeDialog dialog = new CustomArchetypeDialog(getShell(),
+ org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_add_title);
+ if(dialog.open() == Window.OK) {
+ String archetypeGroupId = dialog.getArchetypeGroupId();
+ String archetypeArtifactId = dialog.getArchetypeArtifactId();
+ String archetypeVersion = dialog.getArchetypeVersion();
+ String repositoryUrl = dialog.getRepositoryUrl();
+ downloadArchetype(archetypeGroupId, archetypeArtifactId, archetypeVersion, repositoryUrl);
+ }
+ }
+ });
+ }
+
+ protected IWizardContainer getContainer() {
+ return super.getContainer();
+ }
+
+ public void addArchetypeSelectionListener(ISelectionChangedListener listener) {
+ viewer.addSelectionChangedListener(listener);
+ }
+
+ public void dispose() {
+ MavenPlugin.getDefault().getIndexManager().removeIndexListener(this);
+ super.dispose();
+ }
+
+ public List<Archetype> getArchetypesForCatalog() {
+ if(catalogFactory == null) {
+ return getAllArchetypes();
+ }
+ try {
+ return catalogFactory.getArchetypeCatalog().getArchetypes();
+
+ } catch(CoreException ce) {
+ setErrorMessage(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_error_read);
+ return null;
+ }
+ }
+
+ private List<Archetype> getAllArchetypes() {
+ ArchetypeManager manager = MavenPlugin.getDefault().getArchetypeManager();
+ Collection<ArchetypeCatalogFactory> archetypeCatalogs = manager.getArchetypeCatalogs();
+ ArrayList<Archetype> list = new ArrayList<Archetype>();
+
+ for(ArchetypeCatalogFactory catalog : archetypeCatalogs) {
+ try {
+ //temporary hack to get around 'Test Remote Catalog' blowing up on download
+ //described in https://issues.sonatype.org/browse/MNGECLIPSE-1792
+ if(catalog.getDescription().startsWith("Test")) { //$NON-NLS-1$
+ continue;
+ }
+ @SuppressWarnings("unchecked")
+ List arcs = catalog.getArchetypeCatalog().getArchetypes();
+ if(arcs != null) {
+ list.addAll(arcs);
+ }
+ } catch(Exception ce) {
+ MavenLogger.log("Unable to read archetype catalog: " + catalog.getId(), ce);
+ }
+ }
+ return list;
+ }
+
+ /** Loads the available archetypes. */
+ void loadArchetypes(final String groupId, final String artifactId, final String version) {
+ Job job = new Job(Messages.getString("wizard.project.page.archetype.retrievingArchetypes")) { //$NON-NLS-1$
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ List<Archetype> catalogArchetypes = getArchetypesForCatalog();
+
+ if(catalogArchetypes == null || catalogArchetypes.size() == 0) {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ if(catalogFactory != null && "Nexus Indexer".equals(catalogFactory.getDescription())) { //$NON-NLS-1$
+ setErrorMessage(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_error_no);
+ }
+ }
+ });
+ } else {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ setErrorMessage(null);
+ }
+ });
+ }
+ if(catalogArchetypes == null) {
+ return Status.CANCEL_STATUS;
+ }
+ TreeSet<Archetype> archs = new TreeSet<Archetype>(ARCHETYPE_COMPARATOR);
+ archs.addAll(catalogArchetypes);
+ archetypes = archs;
+
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ updateViewer(groupId, artifactId, version);
+ }
+ });
+ } catch(Exception e) {
+ monitor.done();
+ return Status.CANCEL_STATUS;
+ }
+
+ return Status.OK_STATUS;
+ }
+ };
+ job.schedule();
+ }
+
+ public Set<Archetype> filterVersions(Collection<Archetype> archetypes) {
+ HashMap<String, Archetype> filteredArchetypes = new HashMap<String, Archetype>();
+
+ for(Archetype currentArchetype : archetypes) {
+ String key = getArchetypeKey(currentArchetype);
+ Archetype archetype = filteredArchetypes.get(key);
+ if(archetype == null) {
+ filteredArchetypes.put(key, currentArchetype);
+ } else {
+ DefaultArtifactVersion currentVersion = new DefaultArtifactVersion(currentArchetype.getVersion());
+ DefaultArtifactVersion version = new DefaultArtifactVersion(archetype.getVersion());
+ if(currentVersion.compareTo(version) > 0) {
+ filteredArchetypes.put(key, currentArchetype);
+ }
+ }
+ }
+
+ TreeSet<Archetype> result = new TreeSet<Archetype>(new Comparator<Archetype>() {
+ public int compare(Archetype a1, Archetype a2) {
+ String k1 = a1.getGroupId() + ":" + a1.getArtifactId() + ":" + a1.getVersion(); //$NON-NLS-1$ //$NON-NLS-2$
+ String k2 = a2.getGroupId() + ":" + a2.getArtifactId() + ":" + a2.getVersion(); //$NON-NLS-1$ //$NON-NLS-2$
+ return k1.compareTo(k2);
+ }
+ });
+ result.addAll(filteredArchetypes.values());
+ return result;
+ }
+
+ private String getArchetypeKey(Archetype archetype) {
+ return archetype.getGroupId() + ":" + archetype.getArtifactId(); //$NON-NLS-1$
+ }
+
+ ArchetypeCatalog getArchetypeCatalog() throws CoreException {
+ return catalogFactory == null ? null : catalogFactory.getArchetypeCatalog();
+ }
+
+ /** Sets the flag that the archetype selection is used in the wizard. */
+ public void setUsed(boolean isUsed) {
+ this.isUsed = isUsed;
+ }
+
+ /** Overrides the default to return "true" if the page is not used. */
+ public boolean isPageComplete() {
+ return !isUsed || super.isPageComplete();
+ }
+
+ /** Sets the focus to the table component. */
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+
+ if(visible) {
+ ArchetypeManager archetypeManager = MavenPlugin.getDefault().getArchetypeManager();
+ String catalogId = dialogSettings.get(KEY_CATALOG);
+ catalogFactory = null;
+ if(catalogId != null) {
+ catalogFactory = archetypeManager.getArchetypeCatalogFactory(catalogId);
+ }
+ catalogsComboViewer.setSelection(new StructuredSelection(catalogFactory == null ? ALL_CATALOGS : catalogFactory));
+
+ viewer.getTable().setFocus();
+ Archetype selected = getArchetype();
+ if(selected != null) {
+ viewer.reveal(selected);
+ }
+ }
+ }
+
+ /** Returns the selected archetype. */
+ public Archetype getArchetype() {
+ return (Archetype) ((IStructuredSelection) viewer.getSelection()).getFirstElement();
+ }
+
+ void updateViewer(String groupId, String artifactId, String version) {
+ lastVersionArchetypes = filterVersions(archetypes);
+
+ viewer.setInput(archetypes);
+
+ selectArchetype(groupId, artifactId, version);
+
+ Table table = viewer.getTable();
+ int columnCount = table.getColumnCount();
+ int width = 0;
+ for(int i = 0; i < columnCount; i++ ) {
+ TableColumn column = table.getColumn(i);
+ column.pack();
+ width += column.getWidth();
+ }
+ GridData tableData = (GridData) table.getLayoutData();
+ int oldHint = tableData.widthHint;
+ if(width > oldHint) {
+ tableData.widthHint = width;
+ }
+ getShell().pack(true);
+ tableData.widthHint = oldHint;
+ }
+
+ protected void selectArchetype(String groupId, String artifactId, String version) {
+ Archetype archetype = findArchetype(groupId, artifactId, version);
+
+ Table table = viewer.getTable();
+ if(archetype != null) {
+ viewer.setSelection(new StructuredSelection(archetype), true);
+
+ int n = table.getSelectionIndex();
+ table.setSelection(n);
+ }
+ }
+
+ /** Locates an archetype with given ids. */
+ protected Archetype findArchetype(String groupId, String artifactId, String version) {
+ for(Archetype archetype : archetypes) {
+ if(archetype.getGroupId().equals(groupId) && archetype.getArtifactId().equals(artifactId)) {
+ if(version == null || version.equals(archetype.getVersion())) {
+ return archetype;
+ }
+ }
+ }
+
+ return version == null ? null : findArchetype(groupId, artifactId, null);
+ }
+
+ protected void downloadArchetype(final String archetypeGroupId, final String archetypeArtifactId,
+ final String archetypeVersion, final String repositoryUrl) {
+ final String archetypeName = archetypeGroupId + ":" + archetypeArtifactId + ":" + archetypeVersion; //$NON-NLS-1$ //$NON-NLS-2$
+
+ try {
+ getContainer().run(true, true, new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InterruptedException {
+ monitor.beginTask(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_task_downloading
+ + archetypeName, IProgressMonitor.UNKNOWN);
+
+ try {
+ final IMaven maven = MavenPlugin.getDefault().getMaven();
+
+ final MavenPlugin plugin = MavenPlugin.getDefault();
+
+ final List<ArtifactRepository> remoteRepositories;
+ if(repositoryUrl.length() == 0) {
+ remoteRepositories = maven.getArtifactRepositories(); // XXX should use ArchetypeManager.getArhetypeRepositories()
+ } else {
+ ArtifactRepository repository = new DefaultArtifactRepository( //
+ "archetype", repositoryUrl, new DefaultRepositoryLayout(), null, null); //$NON-NLS-1$
+ remoteRepositories = Collections.singletonList(repository);
+ }
+
+ monitor.subTask(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_task_resolving);
+ Artifact pomArtifact = maven.resolve(archetypeGroupId, archetypeArtifactId, archetypeVersion,
+ "pom", null, remoteRepositories, monitor); //$NON-NLS-1$
+ monitor.worked(1);
+ if(monitor.isCanceled()) {
+ throw new InterruptedException();
+ }
+
+ File pomFile = pomArtifact.getFile();
+ if(pomFile.exists()) {
+ monitor.subTask(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_task_resolving2);
+ Artifact jarArtifact = maven.resolve(archetypeGroupId, archetypeArtifactId, archetypeVersion,
+ "jar", null, remoteRepositories, monitor); //$NON-NLS-1$
+ monitor.worked(1);
+ if(monitor.isCanceled()) {
+ throw new InterruptedException();
+ }
+
+ File jarFile = jarArtifact.getFile();
+
+ monitor.subTask(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_task_reading);
+ monitor.worked(1);
+ if(monitor.isCanceled()) {
+ throw new InterruptedException();
+ }
+
+ monitor.subTask(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_task_indexing);
+ IndexManager indexManager = plugin.getIndexManager();
+ IMutableIndex localIndex = indexManager.getLocalIndex();
+ localIndex.addArtifact(jarFile, new ArtifactKey(pomArtifact));
+
+ //save out the archetype
+ //TODO move this logig out of UI code!
+ Archetype archetype = new Archetype();
+ archetype.setGroupId(archetypeGroupId);
+ archetype.setArtifactId(archetypeArtifactId);
+ archetype.setVersion(archetypeVersion);
+ archetype.setRepository(repositoryUrl);
+ org.apache.maven.archetype.Archetype archetyper = MavenPlugin.getDefault().getArchetype();
+ archetyper.updateLocalCatalog(archetype);
+
+ loadArchetypes(archetypeGroupId, archetypeArtifactId, archetypeVersion);
+ } else {
+ final Artifact pom = pomArtifact;
+ //the user tried to add an archetype that couldn't be resolved on the server
+ getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ setErrorMessage(NLS.bind(
+ org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_error_resolve,
+ pom.toString()));
+ }
+ });
+ }
+
+ } catch(InterruptedException ex) {
+ throw ex;
+
+ } catch(final Exception ex) {
+ final String msg = NLS.bind(
+ org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_error_resolve2, archetypeName);
+ MavenLogger.log(msg, ex);
+ getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ setErrorMessage(msg + "\n" + ex.toString()); //$NON-NLS-1$
+ }
+ });
+
+ } finally {
+ monitor.done();
+
+ }
+ }
+ });
+
+ } catch(InterruptedException ex) {
+ // ignore
+
+ } catch(InvocationTargetException ex) {
+ String msg = NLS.bind(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypePage_error_resolve2,
+ archetypeName);
+ MavenLogger.log(msg, ex);
+ setErrorMessage(msg + "\n" + ex.toString()); //$NON-NLS-1$
+
+ }
+ }
+
+ /**
+ * ArchetypeLabelProvider
+ */
+ protected static class ArchetypeLabelProvider extends LabelProvider implements ITableLabelProvider {
+ /** Returns the element text */
+ public String getColumnText(Object element, int columnIndex) {
+ if(element instanceof Archetype) {
+ Archetype archetype = (Archetype) element;
+ switch(columnIndex) {
+ case 0:
+ return archetype.getGroupId();
+ case 1:
+ return archetype.getArtifactId();
+ case 2:
+ return archetype.getVersion();
+ }
+ }
+ return super.getText(element);
+ }
+
+ /** Returns the element text */
+ public Image getColumnImage(Object element, int columnIndex) {
+ return null;
+ }
+ }
+
+ /**
+ * QuickViewerFilter
+ */
+ protected class QuickViewerFilter extends ViewerFilter implements ModifyListener {
+
+ private String currentFilter;
+
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ if(currentFilter == null || currentFilter.length() == 0) {
+ return true;
+ }
+ Archetype archetype = (Archetype) element;
+ return archetype.getGroupId().indexOf(currentFilter) > -1
+ || archetype.getArtifactId().indexOf(currentFilter) > -1;
+ }
+
+ public void modifyText(ModifyEvent e) {
+ this.currentFilter = filterText.getText().trim();
+ viewer.refresh();
+ }
+ }
+
+ protected class IncludeSnapshotsFilter extends ViewerFilter implements SelectionListener {
+
+ /**
+ *
+ */
+ private static final String SNAPSHOT = "SNAPSHOT"; //$NON-NLS-1$
+
+ private boolean includeSnapshots = false;
+
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ if(element instanceof Archetype) {
+ String version = ((Archetype) element).getVersion();
+ boolean isSnap = false;
+ if(M2EUIUtils.nullOrEmpty(version)) {
+ isSnap = false;
+ } else if(version.lastIndexOf(SNAPSHOT) >= 0) {
+ isSnap = true;
+ }
+ return includeSnapshots ? true : !isSnap;
+ }
+ return false;
+
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ this.includeSnapshots = includeShapshotsButton.getSelection();
+ viewer.refresh();
+ Archetype archetype = getArchetype();
+ //can be null in some cases, don't try to reveal
+ if(archetype != null) {
+ viewer.reveal(archetype);
+ }
+ viewer.getTable().setSelection(viewer.getTable().getSelectionIndex());
+ viewer.getTable().setFocus();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ }
+
+ protected class LastVersionFilter extends ViewerFilter implements SelectionListener {
+
+ private boolean showLastVersion = true;
+
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ return showLastVersion ? lastVersionArchetypes.contains(element) : true;
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ this.showLastVersion = showLastVersionButton.getSelection();
+ viewer.refresh();
+ Archetype archetype = getArchetype();
+ //can be null in some cases, don't try to reveal
+ if(archetype != null) {
+ viewer.reveal(archetype);
+ }
+ viewer.getTable().setSelection(viewer.getTable().getSelectionIndex());
+ viewer.getTable().setFocus();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.index.IndexListener#indexAdded(org.eclipse.m2e.repository.IRepository)
+ */
+ public void indexAdded(IRepository repository) {
+
+ }
+
+ //reload the table when index updating finishes
+ //try to preserve selection in case this is a rebuild
+ protected void reloadViewer() {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ if(isCurrentPage()) {
+ StructuredSelection sel = (StructuredSelection) viewer.getSelection();
+ Archetype selArchetype = null;
+ if(sel != null && sel.getFirstElement() != null) {
+ selArchetype = (Archetype) sel.getFirstElement();
+ }
+ if(selArchetype != null) {
+ loadArchetypes(selArchetype.getGroupId(), selArchetype.getArtifactId(), selArchetype.getVersion());
+ } else {
+ loadArchetypes("org.apache.maven.archetypes", "maven-archetype-quickstart", "1.0"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ }
+ }
+ });
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.index.IndexListener#indexChanged(org.eclipse.m2e.repository.IRepository)
+ */
+ public void indexChanged(IRepository repository) {
+ reloadViewer();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.index.IndexListener#indexRemoved(org.eclipse.m2e.repository.IRepository)
+ */
+ public void indexRemoved(IRepository repository) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.m2e.index.IndexListener#indexUpdating(org.eclipse.m2e.repository.IRepository)
+ */
+ public void indexUpdating(IRepository repository) {
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardArchetypeParametersPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardArchetypeParametersPage.java
new file mode 100644
index 00000000..b272651e
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardArchetypeParametersPage.java
@@ -0,0 +1,615 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.apache.maven.archetype.catalog.Archetype;
+import org.apache.maven.archetype.common.ArchetypeArtifactManager;
+import org.apache.maven.archetype.exception.UnknownArchetype;
+import org.apache.maven.archetype.metadata.ArchetypeDescriptor;
+import org.apache.maven.archetype.metadata.RequiredProperty;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.model.Model;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.core.ui.internal.components.TextComboBoxCellEditor;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+
+import com.ibm.icu.lang.UCharacter;
+
+
+/**
+ * Wizard page responsible for gathering information about the Maven2 artifact when an archetype is being used to create
+ * a project (thus the class name pun).
+ */
+public class MavenProjectWizardArchetypeParametersPage extends AbstractMavenWizardPage {
+
+ public static final String DEFAULT_VERSION = "0.0.1-SNAPSHOT"; //$NON-NLS-1$
+
+ public static final String DEFAULT_PACKAGE = "foo"; //$NON-NLS-1$
+
+ Table propertiesTable;
+
+ TableViewer propertiesViewer;
+
+ final public static String KEY_PROPERTY = "key"; //$NON-NLS-1$
+
+ final public static int KEY_INDEX = 0;
+
+ final public static String VALUE_PROPERTY = "value"; //$NON-NLS-1$
+
+ final public static int VALUE_INDEX = 1;
+
+ /** group id text field */
+ protected Combo groupIdCombo;
+
+ /** artifact id text field */
+ protected Combo artifactIdCombo;
+
+ /** version text field */
+ protected Combo versionCombo;
+
+ /** package text field */
+ protected Combo packageCombo;
+
+ protected Button removeButton;
+
+ private boolean isUsed = true;
+
+ protected Set<String> requiredProperties;
+
+ protected Set<String> optionalProperties;
+
+ protected Archetype archetype;
+
+ protected boolean archetypeChanged = false;
+
+ /** shows if the package has been customized by the user */
+ protected boolean packageCustomized = false;
+
+ /** Creates a new page. */
+ public MavenProjectWizardArchetypeParametersPage(ProjectImportConfiguration projectImportConfiguration) {
+ super("Maven2ProjectWizardArchifactPage", projectImportConfiguration); //$NON-NLS-1$
+
+ setTitle(Messages.getString("wizard.project.page.maven2.title")); //$NON-NLS-1$
+ setDescription(Messages.getString("wizard.project.page.maven2.archetype.parameters.description")); //$NON-NLS-1$
+ setPageComplete(false);
+
+ requiredProperties = new HashSet<String>();
+ optionalProperties = new HashSet<String>();
+ }
+
+ /** Creates page controls. */
+ public void createControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NULL);
+ composite.setLayout(new GridLayout(3, false));
+
+ createArtifactGroup(composite);
+ createPropertiesGroup(composite);
+
+ validate();
+
+ createAdvancedSettings(composite, new GridData(SWT.FILL, SWT.TOP, false, false, 3, 1));
+ resolverConfigurationComponent.setModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ validate();
+ }
+ });
+
+ setControl(composite);
+
+ }
+
+ private void createArtifactGroup(Composite parent) {
+// Composite artifactGroup = new Composite(parent, SWT.NONE);
+// GridData gd_artifactGroup = new GridData( SWT.FILL, SWT.FILL, true, false );
+// artifactGroup.setLayoutData(gd_artifactGroup);
+// artifactGroup.setLayout(new GridLayout(2, false));
+
+ Label groupIdlabel = new Label(parent, SWT.NONE);
+ groupIdlabel.setText(Messages.getString("artifactComponent.groupId")); //$NON-NLS-1$
+
+ groupIdCombo = new Combo(parent, SWT.BORDER);
+ groupIdCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+ addFieldWithHistory("groupId", groupIdCombo); //$NON-NLS-1$
+ groupIdCombo.setData("name", "groupId"); //$NON-NLS-1$ //$NON-NLS-2$
+ groupIdCombo.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ updateJavaPackage();
+ validate();
+ }
+ });
+
+ Label artifactIdLabel = new Label(parent, SWT.NONE);
+ artifactIdLabel.setText(Messages.getString("artifactComponent.artifactId")); //$NON-NLS-1$
+
+ artifactIdCombo = new Combo(parent, SWT.BORDER);
+ artifactIdCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
+ addFieldWithHistory("artifactId", artifactIdCombo); //$NON-NLS-1$
+ artifactIdCombo.setData("name", "artifactId"); //$NON-NLS-1$ //$NON-NLS-2$
+ artifactIdCombo.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ updateJavaPackage();
+ validate();
+ }
+ });
+
+ Label versionLabel = new Label(parent, SWT.NONE);
+ versionLabel.setText(Messages.getString("artifactComponent.version")); //$NON-NLS-1$
+
+ versionCombo = new Combo(parent, SWT.BORDER);
+ GridData gd_versionCombo = new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1);
+ gd_versionCombo.widthHint = 150;
+ versionCombo.setLayoutData(gd_versionCombo);
+ versionCombo.setText(DEFAULT_VERSION);
+ addFieldWithHistory("version", versionCombo); //$NON-NLS-1$
+ versionCombo.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ validate();
+ }
+ });
+
+ Label packageLabel = new Label(parent, SWT.NONE);
+ packageLabel.setText(Messages.getString("artifactComponent.package")); //$NON-NLS-1$
+
+ packageCombo = new Combo(parent, SWT.BORDER);
+ packageCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
+ packageCombo.setData("name", "package"); //$NON-NLS-1$ //$NON-NLS-2$
+ addFieldWithHistory("package", packageCombo); //$NON-NLS-1$
+ packageCombo.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ if(!packageCustomized && !packageCombo.getText().equals(getDefaultJavaPackage())) {
+ packageCustomized = true;
+ }
+ validate();
+ }
+ });
+ }
+
+ private void createPropertiesGroup(Composite composite) {
+ Label propertiesLabel = new Label(composite, SWT.NONE);
+ propertiesLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1));
+ propertiesLabel.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypeParametersPage_lblProps);
+
+ propertiesViewer = new TableViewer(composite, SWT.BORDER | SWT.FULL_SELECTION);
+ propertiesTable = propertiesViewer.getTable();
+ propertiesTable.setLinesVisible(true);
+ propertiesTable.setHeaderVisible(true);
+ propertiesTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 2));
+
+ TableColumn propertiesTableNameColumn = new TableColumn(propertiesTable, SWT.NONE);
+ propertiesTableNameColumn.setWidth(130);
+ propertiesTableNameColumn.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypeParametersPage_columnName);
+
+ TableColumn propertiesTableValueColumn = new TableColumn(propertiesTable, SWT.NONE);
+ propertiesTableValueColumn.setWidth(230);
+ propertiesTableValueColumn.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypeParametersPage_columnValue);
+
+ propertiesViewer.setColumnProperties(new String[] {KEY_PROPERTY, VALUE_PROPERTY});
+
+ propertiesViewer.setCellEditors(new CellEditor[] {new TextCellEditor(propertiesTable, SWT.NONE),
+ new TextCellEditor(propertiesTable, SWT.NONE)});
+ propertiesViewer.setCellModifier(new ICellModifier() {
+ public boolean canModify(Object element, String property) {
+ return true;
+ }
+
+ public void modify(Object element, String property, Object value) {
+ if(element instanceof TableItem) {
+ ((TableItem) element).setText(getTextIndex(property), String.valueOf(value));
+ validate();
+ }
+ }
+
+ public Object getValue(Object element, String property) {
+ if(element instanceof TableItem) {
+ return ((TableItem) element).getText(getTextIndex(property));
+ }
+ return null;
+ }
+ });
+
+ Button addButton = new Button(composite, SWT.NONE);
+ addButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ addButton.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypeParametersPage_btnAdd);
+ addButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ propertiesViewer.editElement(addTableItem("?", "?"), KEY_INDEX); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ });
+
+ removeButton = new Button(composite, SWT.NONE);
+ removeButton.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
+ removeButton.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypeParametersPage_btnRemove);
+ removeButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ if(propertiesTable.getSelectionCount() > 0) {
+ propertiesTable.remove(propertiesTable.getSelectionIndices());
+ removeButton.setEnabled(propertiesTable.getItemCount() > 0);
+ validate();
+ }
+ }
+ });
+ }
+
+ /**
+ * Validates the contents of this wizard page.
+ * <p>
+ * Feedback about the validation is given to the user by displaying error messages or informative messages on the
+ * wizard page. Depending on the provided user input, the wizard page is marked as being complete or not.
+ * <p>
+ * If some error or missing input is detected in the user input, an error message or informative message,
+ * respectively, is displayed to the user. If the user input is complete and correct, the wizard page is marked as
+ * begin complete to allow the wizard to proceed. To that end, the following conditions must be met:
+ * <ul>
+ * <li>The user must have provided a valid group ID.</li>
+ * <li>The user must have provided a valid artifact ID.</li>
+ * <li>The user must have provided a version for the artifact.</li>
+ * </ul>
+ * </p>
+ *
+ * @see org.eclipse.jface.dialogs.DialogPage#setMessage(java.lang.String)
+ * @see org.eclipse.jface.wizard.WizardPage#setErrorMessage(java.lang.String)
+ * @see org.eclipse.jface.wizard.WizardPage#setPageComplete(boolean)
+ */
+ void validate() {
+ String error = validateInput();
+ setErrorMessage(error);
+ setPageComplete(error == null);
+ }
+
+ private String validateInput() {
+ String error = validateIdInput(groupIdCombo.getText().trim(), "group"); //$NON-NLS-1$
+ if(error != null) {
+ return error;
+ }
+
+ error = validateIdInput(artifactIdCombo.getText().trim(), "artifact"); //$NON-NLS-1$
+ if(error != null) {
+ return error;
+ }
+
+ String versionValue = versionCombo.getText().trim();
+ if(versionValue.length() == 0) {
+ return Messages.getString("wizard.project.page.maven2.validator.version"); //$NON-NLS-1$
+ }
+ //TODO: check validity of version?
+
+ String packageName = packageCombo.getText();
+ if(packageName.trim().length() != 0) {
+ if(!Pattern.matches("[A-Za-z_$][A-Za-z_$\\d]*(?:\\.[A-Za-z_$][A-Za-z_$\\d]*)*", packageName)) { //$NON-NLS-1$
+ return org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypeParametersPage_error_package;
+ }
+ }
+
+ // validate project name
+ IStatus nameStatus = getImportConfiguration().validateProjectName(getModel());
+ if(!nameStatus.isOK()) {
+ return Messages.getString("wizard.project.page.maven2.validator.projectNameInvalid", nameStatus.getMessage()); //$NON-NLS-1$
+ }
+
+ if(requiredProperties.size() > 0) {
+ Properties properties = getProperties();
+ for(String key : requiredProperties) {
+ String value = properties.getProperty(key);
+ if(value == null || value.length() == 0) {
+ return Messages.getString("wizard.project.page.maven2.validator.requiredProperty", key); //$NON-NLS-1$
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /** Ends the wizard flow chain. */
+ public IWizardPage getNextPage() {
+ return null;
+ }
+
+ public void setArchetype(Archetype archetype) {
+ if(archetype == null) {
+ propertiesTable.removeAll();
+ archetypeChanged = false;
+ } else if(!archetype.equals(this.archetype)) {
+ this.archetype = archetype;
+ propertiesTable.removeAll();
+ requiredProperties.clear();
+ optionalProperties.clear();
+ archetypeChanged = true;
+
+ Properties properties = archetype.getProperties();
+ if(properties != null) {
+ for(Iterator<Map.Entry<Object, Object>> it = properties.entrySet().iterator(); it.hasNext();) {
+ Map.Entry<?, ?> e = it.next();
+ String key = (String) e.getKey();
+ addTableItem(key, (String) e.getValue());
+ optionalProperties.add(key);
+ }
+ }
+ }
+ }
+
+ void loadArchetypeDescriptor() {
+ final String groupId = archetype.getGroupId();
+ final String artifactId = archetype.getArtifactId();
+ final String version = archetype.getVersion();
+ final String archetypeName = groupId + ":" + artifactId + ":" + version; //$NON-NLS-1$ //$NON-NLS-2$
+
+ try {
+ getContainer().run(false, true, new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) {
+ monitor.beginTask(NLS.bind(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypeParametersPage_task, archetypeName), IProgressMonitor.UNKNOWN);
+ try {
+ IMaven maven = MavenPlugin.getDefault().getMaven();
+
+ ArtifactRepository localRepository = maven.getLocalRepository();
+
+ List<ArtifactRepository> repositories = maven.getArtifactRepositories();
+
+ ArchetypeArtifactManager aaMgr = MavenPlugin.getDefault().getArchetypeArtifactManager();
+ if(aaMgr.isFileSetArchetype(groupId, artifactId, version, null, localRepository, repositories)) {
+ ArchetypeDescriptor descriptor = aaMgr.getFileSetArchetypeDescriptor(groupId, artifactId, version, null,
+ localRepository, repositories);
+ List<?> properties = descriptor.getRequiredProperties();
+ if(properties != null) {
+ for(Object o : properties) {
+ if(o instanceof RequiredProperty) {
+ RequiredProperty rp = (RequiredProperty) o;
+ requiredProperties.add(rp.getKey());
+ addTableItem(rp.getKey(), rp.getDefaultValue());
+ }
+ }
+ }
+ }
+ } catch(UnknownArchetype e) {
+ MavenLogger.log(NLS.bind("Error downloading archetype {0}",archetypeName), e);
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ } finally {
+ monitor.done();
+ }
+ }
+ });
+ } catch(InterruptedException ex) {
+ // ignore
+ } catch(InvocationTargetException ex) {
+ String msg = NLS.bind(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArchetypeParametersPage_error_download, archetypeName);
+ MavenLogger.log(msg, ex);
+ setErrorMessage(msg + "\n" + ex.toString()); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * @param key
+ * @param value
+ */
+ TableItem addTableItem(String key, String value) {
+ TableItem item = new TableItem(propertiesTable, SWT.NONE);
+ item.setData(item);
+ item.setText(KEY_INDEX, key);
+ item.setText(VALUE_INDEX, value == null ? "" : value); //$NON-NLS-1$
+ return item;
+ }
+
+ /**
+ * Updates the properties when a project name is set on the first page of the wizard.
+ */
+ public void setProjectName(String projectName) {
+ if(artifactIdCombo.getText().equals(groupIdCombo.getText())) {
+ groupIdCombo.setText(projectName);
+ }
+ artifactIdCombo.setText(projectName);
+ packageCombo.setText("org." + projectName.replace('-', '.')); //$NON-NLS-1$
+ validate();
+ }
+
+ /**
+ * Updates the properties when a project name is set on the first page of the wizard.
+ */
+ public void setParentProject(String groupId, String artifactId, String version) {
+ groupIdCombo.setText(groupId);
+ versionCombo.setText(version);
+ validate();
+ }
+
+ /** Enables or disables the artifact id text field. */
+ public void setArtifactIdEnabled(boolean b) {
+ artifactIdCombo.setEnabled(b);
+ }
+
+ /** Returns the package name. */
+ public String getJavaPackage() {
+ if(packageCombo.getText().length() > 0) {
+ return packageCombo.getText();
+ }
+ return getDefaultJavaPackage();
+ }
+
+ /** Updates the package name if the related fields changed. */
+ protected void updateJavaPackage() {
+ if(packageCustomized) {
+ return;
+ }
+
+ String defaultPackageName = getDefaultJavaPackage();
+ packageCombo.setText(defaultPackageName);
+ }
+
+ /** Returns the default package name. */
+ protected String getDefaultJavaPackage() {
+ return MavenProjectWizardArchetypeParametersPage.getDefaultJavaPackage(groupIdCombo.getText().trim(),
+ artifactIdCombo.getText().trim());
+ }
+
+ /** Creates the Model object. */
+ public Model getModel() {
+ Model model = new Model();
+
+ model.setModelVersion("4.0.0"); //$NON-NLS-1$
+ model.setGroupId(groupIdCombo.getText());
+ model.setArtifactId(artifactIdCombo.getText());
+ model.setVersion(versionCombo.getText());
+
+ return model;
+ }
+
+ public void setUsed(boolean isUsed) {
+ this.isUsed = isUsed;
+ }
+
+ public boolean isPageComplete() {
+ return !isUsed || super.isPageComplete();
+ }
+
+ /** Loads the group value when the page is displayed. */
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+
+ if(visible) {
+ if(groupIdCombo.getText().length() == 0 && groupIdCombo.getItemCount() > 0) {
+ groupIdCombo.setText(groupIdCombo.getItem(0));
+ packageCombo.setText(getDefaultJavaPackage());
+ packageCustomized = false;
+ }
+
+ if(archetypeChanged && archetype != null) {
+ archetypeChanged = false;
+ loadArchetypeDescriptor();
+ validate();
+ }
+
+ updatePropertyEditors();
+ }
+ }
+
+ public Properties getProperties() {
+ if(propertiesViewer.isCellEditorActive()) {
+ propertiesTable.setFocus();
+ }
+ Properties properties = new Properties();
+ for(int i = 0; i < propertiesTable.getItemCount(); i++ ) {
+ TableItem item = propertiesTable.getItem(i);
+ properties.put(item.getText(KEY_INDEX), item.getText(VALUE_INDEX));
+ }
+ return properties;
+ }
+
+ public int getTextIndex(String property) {
+ return KEY_PROPERTY.equals(property) ? KEY_INDEX : VALUE_INDEX;
+ }
+
+ public void updatePropertyEditors() {
+ CellEditor[] ce = propertiesViewer.getCellEditors();
+
+ int n = requiredProperties.size() + optionalProperties.size();
+ if(n == 0) {
+ if(ce[KEY_INDEX] instanceof TextComboBoxCellEditor) {
+ // if there was a combo editor previously defined, and the current
+ // archetype has no properties, replace it with a plain text editor
+ ce[KEY_INDEX].dispose();
+ ce[KEY_INDEX] = new TextCellEditor(propertiesTable, SWT.FLAT);
+ }
+ } else {
+ TextComboBoxCellEditor comboEditor = null;
+ // if there was a plain text editor previously defined, and the current
+ // archetype has properties, replace it with a combo editor
+ if(ce[KEY_INDEX] instanceof TextComboBoxCellEditor) {
+ comboEditor = (TextComboBoxCellEditor) ce[KEY_INDEX];
+ } else {
+ ce[KEY_INDEX].dispose();
+ comboEditor = new TextComboBoxCellEditor(propertiesTable, SWT.FLAT);
+ ce[KEY_INDEX] = comboEditor;
+ }
+
+ // populate the property name selection
+ List<String> propertyKeys = new ArrayList<String>(n);
+ propertyKeys.addAll(requiredProperties);
+ propertyKeys.addAll(optionalProperties);
+ comboEditor.setItems(propertyKeys.toArray(new String[n]));
+ }
+ }
+
+ public static String getDefaultJavaPackage(String groupId, String artifactId) {
+ StringBuffer sb = new StringBuffer(groupId);
+
+ if(sb.length() > 0 && artifactId.length() > 0) {
+ sb.append('.');
+ }
+
+ sb.append(artifactId);
+
+ if(sb.length() == 0) {
+ sb.append(DEFAULT_PACKAGE);
+ }
+
+ boolean isFirst = true;
+ StringBuffer pkg = new StringBuffer();
+ for(int i = 0; i < sb.length(); i++ ) {
+ char c = sb.charAt(i);
+ if(c == '-') {
+ pkg.append('_');
+ isFirst = false;
+ } else {
+ if(isFirst) {
+ if(UCharacter.isJavaIdentifierStart(c)) {
+ pkg.append(c);
+ isFirst = false;
+ }
+ } else {
+ if(c == '.') {
+ pkg.append('.');
+ isFirst = true;
+ } else if(UCharacter.isJavaIdentifierPart(c)) {
+ pkg.append(c);
+ }
+ }
+ }
+ }
+
+ return pkg.toString();
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardArtifactPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardArtifactPage.java
new file mode 100644
index 00000000..9afcce5e
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardArtifactPage.java
@@ -0,0 +1,359 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.maven.model.Model;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.window.Window;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.index.IndexedArtifactFile;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.core.ui.internal.dialogs.MavenRepositorySearchDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+
+
+/**
+ * Wizard page responsible for gathering information about the Maven2 artifact and the directories to create. This
+ * wizard page gathers Maven2 specific information. The user must specify the necessary information about the Maven2
+ * artifact and she can also decide which directories of the default Maven2 directory structure should be created. Input
+ * validation is performed in order to make sure that all the provided information is valid before letting the wizard
+ * continue.
+ */
+public class MavenProjectWizardArtifactPage extends AbstractMavenWizardPage {
+
+ private static final ProjectFolder JAVA = new ProjectFolder("src/main/java", "target/classes"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final ProjectFolder JAVA_TEST = new ProjectFolder("src/test/java", "target/test-classes"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final ProjectFolder RESOURCES = new ProjectFolder("src/main/resources", "target/classes"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ private static final ProjectFolder RESOURCES_TEST = new ProjectFolder("src/test/resources", "target/test-classes"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ // private static final ProjectFolder FILTERS = new ProjectFolder("src/main/filters", null, false);
+
+ // private static final ProjectFolder FILTERS_TEST = new ProjectFolder("src/test/filters", null, false);
+
+ // private static final ProjectFolder ASSEMBLY = new ProjectFolder("src/main/assembly", null, false);
+
+ // private static final ProjectFolder CONFIG = new ProjectFolder("src/main/config", null, false);
+
+ private static final ProjectFolder WEBAPP = new ProjectFolder("src/main/webapp", null); //$NON-NLS-1$
+
+ private static final ProjectFolder EAR = new ProjectFolder("src/main/application", null); //$NON-NLS-1$
+
+ private static final ProjectFolder SITE = new ProjectFolder("src/site", null); //$NON-NLS-1$
+
+ private static final ProjectFolder[] JAR_DIRS = {JAVA, JAVA_TEST, RESOURCES, RESOURCES_TEST};
+
+ private static final ProjectFolder[] WAR_DIRS = {JAVA, JAVA_TEST, RESOURCES, RESOURCES_TEST, WEBAPP};
+
+ private static final ProjectFolder[] EAR_DIRS = {EAR}; // MNGECLIPSE-688 add EAR Support
+
+ private static final ProjectFolder[] POM_DIRS = {SITE};
+
+ /** special directory sets, default is JAR_DIRS */
+ private static final Map<String, ProjectFolder[]> directorySets = new HashMap<String, ProjectFolder[]>();
+ static {
+ directorySets.put(MavenArtifactComponent.WAR, WAR_DIRS);
+ directorySets.put(MavenArtifactComponent.POM, POM_DIRS);
+ directorySets.put(MavenArtifactComponent.EAR, EAR_DIRS); // MNGECLIPSE-688 add EAR Support
+ }
+
+ /** parent property panel */
+ protected MavenParentComponent parentComponent;
+
+ /** artifact property panel */
+ protected MavenArtifactComponent artifactComponent;
+
+ /** the parent readonly state */
+ private boolean readonlyParent = false;
+
+ private boolean isUsed;
+
+ /**
+ * Sets the title and description of this wizard page and marks it as not being complete as user input is required for
+ * continuing.
+ * @wbp.parser.constructor
+ */
+ public MavenProjectWizardArtifactPage(ProjectImportConfiguration projectImportConfiguration) {
+ this("MavenProjectWizardArtifactPage", projectImportConfiguration); //$NON-NLS-1$
+ }
+
+ /**
+ * Sets the title and description of this wizard page and marks it as not being complete as user input is required for
+ * continuing.
+ */
+ protected MavenProjectWizardArtifactPage(String name, ProjectImportConfiguration projectImportConfiguration) {
+ super(name, projectImportConfiguration);
+
+ setTitle(Messages.getString("wizard.project.page.maven2.title")); //$NON-NLS-1$
+ setDescription(Messages.getString("wizard.project.page.maven2.description")); //$NON-NLS-1$
+ setPageComplete(false);
+ }
+
+ /**
+ * {@inheritDoc} This wizard page contains a <code>MavenArtifactComponent</code> to gather information about the Maven
+ * artifact and a <code>Maven2DirectoriesComponent</code> which allows to choose which directories of the default
+ * Maven directory structure to create.
+ */
+ public void createControl(Composite parent) {
+ GridLayout layout = new GridLayout();
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+
+ Composite container = new Composite(parent, SWT.NULL);
+ container.setLayout(layout);
+
+ WidthGroup widthGroup = new WidthGroup();
+ container.addControlListener(widthGroup);
+
+ ModifyListener modifyingListener = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ validate();
+ }
+ };
+
+ artifactComponent = new MavenArtifactComponent(container, SWT.NONE);
+ artifactComponent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ artifactComponent.setWidthGroup(widthGroup);
+ artifactComponent.setModifyingListener(modifyingListener);
+ artifactComponent.setArtifactIdEditable(!readonlyParent);
+
+ parentComponent = new MavenParentComponent(container, readonlyParent ? SWT.READ_ONLY : SWT.NONE);
+ parentComponent.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ parentComponent.setWidthGroup(widthGroup);
+
+ parentComponent.addModifyListener(modifyingListener);
+ parentComponent.addBrowseButtonListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ MavenRepositorySearchDialog dialog = MavenRepositorySearchDialog.createSearchParentDialog(getShell(),
+ org.eclipse.m2e.core.internal.Messages.MavenProjectWizardArtifactPage_searchDialog_title, null, null);
+
+ if(dialog.open() == Window.OK) {
+ IndexedArtifactFile indexedArtifactFile = (IndexedArtifactFile) dialog.getFirstResult();
+ if(indexedArtifactFile != null) {
+ parentComponent.setValues(indexedArtifactFile.group, indexedArtifactFile.artifact,
+ indexedArtifactFile.version);
+ }
+ }
+ }
+ });
+
+ createAdvancedSettings(container, new GridData(SWT.FILL, SWT.TOP, false, false, 2, 1));
+ resolverConfigurationComponent.setModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ validate();
+ }
+ });
+
+ addFieldWithHistory("groupId", artifactComponent.getGroupIdCombo()); //$NON-NLS-1$
+ addFieldWithHistory("artifactId", artifactComponent.getArtifactIdCombo()); //$NON-NLS-1$
+ addFieldWithHistory("version", artifactComponent.getVersionCombo()); //$NON-NLS-1$
+ addFieldWithHistory("name", artifactComponent.getNameCombo()); //$NON-NLS-1$
+
+ addFieldWithHistory("groupId", parentComponent.getGroupIdCombo()); //$NON-NLS-1$
+ addFieldWithHistory("artifactId", parentComponent.getArtifactIdCombo()); //$NON-NLS-1$
+ addFieldWithHistory("version", parentComponent.getVersionCombo()); //$NON-NLS-1$
+
+ container.layout();
+
+ validate();
+
+ setControl(container);
+ }
+
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ artifactComponent.getGroupIdCombo().setFocus();
+ }
+
+ /**
+ * Returns the Maven2 model containing the artifact information provided by the user.
+ *
+ * @return The Maven2 model containing the provided artifact information. Is never <code>null</code>.
+ */
+ public Model getModel() {
+ Model model = artifactComponent.getModel();
+
+ parentComponent.updateModel(model);
+
+ return model;
+ }
+
+ /** Returns the list of directories for the currently selected packaging. */
+ private ProjectFolder[] getProjectFolders() {
+ ProjectFolder[] folders = directorySets.get(artifactComponent.getPackaging());
+ return folders == null ? JAR_DIRS : folders;
+ }
+
+ /**
+ * Returns the directories of the default Maven2 directory structure selected by the user. These directories should be
+ * created along with the new project.
+ *
+ * @return The Maven2 directories selected by the user. Neither the array nor any of its elements is <code>null</code>
+ * .
+ */
+ public String[] getFolders() {
+ ProjectFolder[] mavenDirectories = getProjectFolders();
+
+ String[] directories = new String[mavenDirectories.length];
+ for(int i = 0; i < directories.length; i++ ) {
+ directories[i] = mavenDirectories[i].getPath();
+ }
+
+ return directories;
+ }
+
+ /**
+ * Validates the contents of this wizard page.
+ * <p>
+ * Feedback about the validation is given to the user by displaying error messages or informative messages on the
+ * wizard page. Depending on the provided user input, the wizard page is marked as being complete or not.
+ * <p>
+ * If some error or missing input is detected in the user input, an error message or informative message,
+ * respectively, is displayed to the user. If the user input is complete and correct, the wizard page is marked as
+ * begin complete to allow the wizard to proceed. To that end, the following conditions must be met:
+ * <ul>
+ * <li>The user must have provided a group ID.</li>
+ * <li>The user must have provided an artifact ID.</li>
+ * <li>The user must have provided a version for the artifact.</li>
+ * <li>The user must have provided the packaging type for the artifact.</li>
+ * </ul>
+ * </p>
+ *
+ * @see org.eclipse.jface.dialogs.DialogPage#setMessage(java.lang.String)
+ * @see org.eclipse.jface.wizard.WizardPage#setErrorMessage(java.lang.String)
+ * @see org.eclipse.jface.wizard.WizardPage#setPageComplete(boolean)
+ */
+ void validate() {
+ String error = validateInput();
+ setErrorMessage(error);
+ setPageComplete(error == null);
+ }
+
+ private String validateInput() {
+ String error = validateIdInput(artifactComponent.getGroupId().trim(), "group"); //$NON-NLS-1$
+ if(error != null) {
+ return error;
+ }
+
+ error = validateIdInput(artifactComponent.getArtifactId().trim(), "artifact"); //$NON-NLS-1$
+ if(error != null) {
+ return error;
+ }
+
+ if(artifactComponent.getVersion().trim().length() == 0) {
+ return Messages.getString("wizard.project.page.maven2.validator.version"); //$NON-NLS-1$
+ }
+
+ if(artifactComponent.getPackaging().trim().length() == 0) {
+ return Messages.getString("wizard.project.page.maven2.validator.packaging"); //$NON-NLS-1$
+ }
+
+ // if the parent project is specified, all three fields must be present
+ if(!parentComponent.validate()) {
+ return Messages.getString("wizard.project.page.maven2.validator.parent"); //$NON-NLS-1$
+ }
+
+ // validate project name
+ IStatus nameStatus = getImportConfiguration().validateProjectName(artifactComponent.getModel());
+ if(!nameStatus.isOK()) {
+ return nameStatus.getMessage();
+ }
+
+ return null;
+ }
+
+ /**
+ * Updates the properties when a project name is set on the first page of the wizard.
+ */
+ public void setProjectName(String projectName) {
+ if(artifactComponent.getArtifactId().equals(artifactComponent.getGroupId())) {
+ artifactComponent.setGroupId(projectName);
+ }
+ artifactComponent.setArtifactId(projectName);
+ validate();
+ }
+
+ /** Sets the readonly parent flag. */
+ public void setParentReadonly(boolean b) {
+ readonlyParent = b;
+ }
+
+ /**
+ * Updates the properties when a project name is set on the first page of the wizard.
+ */
+ public void setParentProject(String groupId, String artifactId, String version) {
+ parentComponent.setValues(groupId, artifactId, version);
+ artifactComponent.setGroupId(groupId);
+ artifactComponent.setVersion(version);
+ validate();
+ }
+
+ public void setUsed(boolean isUsed) {
+ this.isUsed = isUsed;
+ }
+
+ public boolean isPageComplete() {
+ return !isUsed || super.isPageComplete();
+ }
+
+ /**
+ * A placeholder representing a directory in the project structure.
+ */
+ final static class ProjectFolder {
+
+ /** Folder path */
+ private String path = null;
+
+ /** Output path */
+ private String outputPath = null;
+
+ ProjectFolder(String path, String outputPath) {
+ this.path = path;
+ this.outputPath = outputPath;
+ }
+
+ /**
+ * Returns folder path
+ */
+ String getPath() {
+ return path;
+ }
+
+ /**
+ * Returns folder output path
+ */
+ String getOutputPath() {
+ return outputPath;
+ }
+
+ /**
+ * Returns true for source folder
+ */
+ boolean isSourceEntry() {
+ return this.getOutputPath() != null;
+ }
+
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardLocationPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardLocationPage.java
new file mode 100644
index 00000000..6e582eb3
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenProjectWizardLocationPage.java
@@ -0,0 +1,316 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.IWorkingSet;
+
+
+/**
+ * Wizard page used to specify project location and working set.
+ */
+public class MavenProjectWizardLocationPage extends AbstractMavenWizardPage {
+
+ Button useDefaultWorkspaceLocationButton;
+ Label locationLabel;
+ Combo locationCombo;
+
+ boolean initialized = false;
+ private WorkingSetGroup workingSetGroup;
+
+ private IPath location;
+
+ private final List<IWorkingSet> workingSets;
+
+ /**
+ * Creates Maven project location page.
+ *
+ * @param title location page title text
+ * @param description location page description text
+ */
+ public MavenProjectWizardLocationPage(ProjectImportConfiguration configuration, String title, String description,
+ List<IWorkingSet> workingSets) {
+ super("MavenProjectWizardLocationPage", configuration); //$NON-NLS-1$
+ this.workingSets = workingSets;
+ setTitle(title);
+ setDescription(description);
+ setPageComplete(false);
+ }
+
+ /**
+ * {@inheritDoc} This wizard page contains a component to query the project name and a
+ * <code>MavenLocationComponent</code> which allows to specify whether the project should be created in the
+ * workspace or at some given external location.
+ */
+ public void createControl(Composite parent) {
+ Composite container = new Composite(parent, SWT.NULL);
+ container.setLayout(new GridLayout(3, false));
+
+ createAdditionalControls(container);
+
+// // project name
+// GridData gridData = new GridData();
+// Label label = new Label(container, SWT.NULL);
+// label.setLayoutData(gridData);
+// label.setText(Messages.getString("wizard.project.page.project.projectName"));
+// projectNameText = new Combo(container, SWT.BORDER | SWT.SINGLE);
+// projectNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+// projectNameText.addModifyListener(modifyingListener);
+// addFieldWithHistory("projectName", projectNameText);
+
+ // gridData.verticalIndent = 5;
+// locationComponent = new MavenLocationComponent(container, SWT.NONE);
+// locationComponent.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 3, 1));
+// locationComponent.setModifyingListener(modifyingListener);
+// addFieldWithHistory("location", locationComponent.getLocationCombo());
+
+ useDefaultWorkspaceLocationButton = new Button(container, SWT.CHECK);
+ GridData useDefaultWorkspaceLocationButtonData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1);
+ useDefaultWorkspaceLocationButton.setLayoutData(useDefaultWorkspaceLocationButtonData);
+ useDefaultWorkspaceLocationButton.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardLocationPage_btnUserDefault);
+ useDefaultWorkspaceLocationButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ boolean inWorkspace = isInWorkspace();
+ locationLabel.setEnabled(!inWorkspace);
+ locationCombo.setEnabled(!inWorkspace);
+ }
+ });
+ useDefaultWorkspaceLocationButton.setSelection(true);
+
+ locationLabel = new Label(container, SWT.NONE);
+ GridData locationLabelData = new GridData();
+ locationLabelData.horizontalIndent = 10;
+ locationLabel.setLayoutData(locationLabelData);
+ locationLabel.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardLocationPage_lblLocation);
+ locationLabel.setEnabled(false);
+
+ locationCombo = new Combo(container, SWT.NONE);
+ GridData locationComboData = new GridData(SWT.FILL, SWT.CENTER, true, false);
+ locationCombo.setLayoutData(locationComboData);
+ locationCombo.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ validate();
+ }
+ });
+ locationCombo.setEnabled(false);
+ addFieldWithHistory("location", locationCombo); //$NON-NLS-1$
+
+ Button locationBrowseButton = new Button(container, SWT.NONE);
+ GridData locationBrowseButtonData = new GridData(SWT.FILL, SWT.CENTER, false, false);
+ locationBrowseButton.setLayoutData(locationBrowseButtonData);
+ locationBrowseButton.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardLocationPage_btnLocation);
+ locationBrowseButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ DirectoryDialog dialog = new DirectoryDialog(getShell());
+ dialog.setText(org.eclipse.m2e.core.internal.Messages.MavenProjectWizardLocationPage_dialog_location);
+
+ String path = locationCombo.getText();
+ if(path.length()==0) {
+ path = ResourcesPlugin.getWorkspace().getRoot().getLocation().toPortableString();
+ }
+ dialog.setFilterPath(path);
+
+ String selectedDir = dialog.open();
+ if(selectedDir != null) {
+ locationCombo.setText(selectedDir);
+ useDefaultWorkspaceLocationButton.setSelection(false);
+ validate();
+ }
+ }
+ });
+
+ this.workingSetGroup = new WorkingSetGroup(container, workingSets, getShell());
+
+ if(location==null || Platform.getLocation().equals(location)) {
+// useDefaultWorkspaceLocationButton.setSelection(true);
+ } else {
+// useDefaultWorkspaceLocationButton.setSelection(false);
+// locationLabel.setEnabled(true);
+// locationCombo.setEnabled(true);
+ locationCombo.setText(location.toOSString());
+ }
+
+ createAdvancedSettings(container, new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1));
+
+ setControl(container);
+ }
+
+ /**
+ * Create additional controls
+ */
+ protected void createAdditionalControls(Composite container) {
+ }
+
+ public void dispose() {
+ super.dispose();
+ workingSetGroup.dispose();
+ }
+
+ /**
+ * Returns whether the user has chosen to create the project in the workspace or at an external location.
+ *
+ * @return <code>true</code> if the project is to be created in the workspace, <code>false</code> if it should be
+ * created at an external location.
+ */
+ public boolean isInWorkspace() {
+ return useDefaultWorkspaceLocationButton.getSelection();
+ }
+
+ /**
+ * Returns the path of the location where the project is to be created. According to the user input, the path either
+ * points to the workspace or to a valid user specified location on the filesystem.
+ *
+ * @return The path of the location where to create the project. Is never <code>null</code>.
+ */
+ public IPath getLocationPath() {
+ if(isInWorkspace()) {
+ return ResourcesPlugin.getWorkspace().getRoot().getLocation();
+ }
+ return Path.fromOSString(locationCombo.getText().trim());
+ }
+
+ public void setLocationPath(IPath location) {
+ this.location = location;
+ }
+
+ /** {@inheritDoc} */
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+
+ if(visible) {
+ initialized = true;
+ validate();
+// projectNameText.setFocus();
+ }
+ }
+
+ /**
+ * Validates the contents of this wizard page.
+ * <p>
+ * Feedback about the validation is given to the user by displaying error messages or informative messages on the
+ * wizard page. Depending on the provided user input, the wizard page is marked as being complete or not.
+ * <p>
+ * If some error or missing input is detected in the user input, an error message or informative message,
+ * respectively, is displayed to the user. If the user input is complete and correct, the wizard page is marked as
+ * begin complete to allow the wizard to proceed. To that end, the following conditions must be met:
+ * <ul>
+ * <li>The user must have provided a project name.</li>
+ * <li>The project name must be a valid project resource identifier.</li>
+ * <li>A project with the same name must not exist.</li>
+ * <li>A valid project location path must have been specified.</li>
+ * </ul>
+ * </p>
+ *
+ * @see org.eclipse.core.resources.IWorkspace#validateName(java.lang.String, int)
+ * @see org.eclipse.core.resources.IWorkspace#validateProjectLocation(org.eclipse.core.resources.IProject,
+ * org.eclipse.core.runtime.IPath)
+ * @see org.eclipse.jface.dialogs.DialogPage#setMessage(java.lang.String)
+ * @see org.eclipse.jface.wizard.WizardPage#setErrorMessage(java.lang.String)
+ * @see org.eclipse.jface.wizard.WizardPage#setPageComplete(boolean)
+ */
+ protected void validate() {
+ if (!initialized) {
+ return;
+ }
+
+ final IWorkspace workspace = ResourcesPlugin.getWorkspace();
+
+// final String name = getProjectName();
+//
+// // check whether the project name field is empty
+// if(name.trim().length() == 0) {
+// setErrorMessage(null);
+// setMessage(Messages.getString("wizard.project.page.project.validator.projectName"));
+// setPageComplete(false);
+// return;
+// }
+//
+// // check whether the project name is valid
+// final IStatus nameStatus = workspace.validateName(name, IResource.PROJECT);
+// if(!nameStatus.isOK()) {
+// setErrorMessage(nameStatus.getMessage());
+// setPageComplete(false);
+// return;
+// }
+//
+// // check whether project already exists
+// final IProject handle = getProjectHandle();
+// if(handle.exists()) {
+// setErrorMessage(Messages.getString("wizard.project.page.project.validator.projectExists"));
+// setPageComplete(false);
+// return;
+// }
+
+ IPath projectPath = getLocationPath();
+ String location = projectPath.toOSString();
+
+ // check whether location is empty
+ if(location.length() == 0) {
+ setErrorMessage(null);
+ setMessage(Messages.getString("wizard.project.page.project.validator.projectLocation")); //$NON-NLS-1$
+ setPageComplete(false);
+ return;
+ }
+
+ // check whether the location is a syntactically correct path
+ if(!Path.ROOT.isValidPath(location)) {
+ setErrorMessage(Messages.getString("wizard.project.page.project.validator.invalidLocation")); //$NON-NLS-1$
+ setPageComplete(false);
+ return;
+ }
+
+ // If we do not place the contents in the workspace validate the location.
+ if(!isInWorkspace()) {
+ //this wizardpage is used in multiple wizards, not only in MavenProjectWizard
+ // the other wizard don't seem to have any getModel() methods.
+ //see MNGECLIPSE-1252 for more.
+ if (getWizard() instanceof MavenProjectWizard)
+ {
+ String projectName = getImportConfiguration().getProjectName(((MavenProjectWizard)getWizard()).getModel());
+ if(projectName.length()>0){
+ final IStatus locationStatus = workspace.validateProjectLocation(workspace.getRoot().getProject(projectName), projectPath);
+ if(!locationStatus.isOK()) {
+ setErrorMessage(locationStatus.getMessage());
+ setPageComplete(false);
+ return;
+ }
+ }
+ }
+ }
+
+ setPageComplete(true);
+ setErrorMessage(null);
+ setMessage(null);
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/ProjectsImportPage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/ProjectsImportPage.java
new file mode 100644
index 00000000..6f82a08b
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/ProjectsImportPage.java
@@ -0,0 +1,626 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenConsole;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+import org.eclipse.ui.dialogs.IOverwriteQuery;
+
+
+/**
+ * The ProjectsImportPage is the page that allows the user to import projects from a particular location.
+ */
+public class ProjectsImportPage extends WizardPage implements IOverwriteQuery {
+
+ String location;
+
+ CheckboxTreeViewer projectsList;
+
+ IProject[] wsProjects;
+
+ ProjectRecord[] selectedProjects = new ProjectRecord[0];
+
+
+ public ProjectsImportPage(String location) {
+ super("wizardExternalProjectsPage"); //$NON-NLS-1$
+ this.location = location;
+
+ setTitle(Messages.ProjectsImportPage_title);
+ setDescription(Messages.ProjectsImportPage_desc);
+ setPageComplete(false);
+ }
+
+ public void createControl(Composite parent) {
+ initializeDialogUnits(parent);
+
+ Composite workArea = new Composite(parent, SWT.NONE);
+ setControl(workArea);
+
+ workArea.setLayout(new GridLayout());
+ workArea.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL));
+
+ createProjectsList(workArea);
+ createOptionsArea(workArea);
+ Dialog.applyDialogFont(workArea);
+
+ updateProjectsList(location);
+ }
+
+ /**
+ * Create the area with the extra options.
+ *
+ * @param workArea
+ */
+ private void createOptionsArea(Composite workArea) {
+ }
+
+ /**
+ * Create the checkbox list for the found projects.
+ *
+ * @param workArea
+ */
+ private void createProjectsList(Composite workArea) {
+ Label title = new Label(workArea, SWT.NONE);
+ title.setText(Messages.ProjectsImportPage_lstProjects);
+
+ Composite listComposite = new Composite(workArea, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.marginWidth = 0;
+ layout.makeColumnsEqualWidth = false;
+ listComposite.setLayout(layout);
+
+ listComposite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH));
+
+ projectsList = new CheckboxTreeViewer(listComposite, SWT.BORDER);
+ GridData listData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
+ projectsList.getControl().setLayoutData(listData);
+
+ projectsList.setContentProvider(new ITreeContentProvider() {
+
+ public Object[] getChildren(Object parentElement) {
+ return null;
+ }
+
+ public Object[] getElements(Object inputElement) {
+ return getValidProjects();
+ }
+
+ public boolean hasChildren(Object element) {
+ return false;
+ }
+
+ public Object getParent(Object element) {
+ return null;
+ }
+
+ public void dispose() {
+
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+ });
+
+ projectsList.setLabelProvider(new LabelProvider() {
+ public String getText(Object element) {
+ ProjectRecord projectRecord = (ProjectRecord) element;
+ return projectRecord.getProjectName() + " - " + projectRecord.projectFile.getParentFile().getAbsolutePath(); //$NON-NLS-1$
+ }
+ });
+
+ projectsList.addCheckStateListener(new ICheckStateListener() {
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ setPageComplete(projectsList.getCheckedElements().length > 0);
+ }
+ });
+
+ projectsList.setInput(this);
+ projectsList.setComparator(new ViewerComparator());
+ createSelectionButtons(listComposite);
+ }
+
+ /**
+ * Create the selection buttons in the listComposite.
+ *
+ * @param listComposite
+ */
+ private void createSelectionButtons(Composite listComposite) {
+ Composite buttonsComposite = new Composite(listComposite, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ buttonsComposite.setLayout(layout);
+
+ buttonsComposite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
+
+ Button selectAll = new Button(buttonsComposite, SWT.PUSH);
+ selectAll.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ selectAll.setText(Messages.ProjectsImportPage_btnSelect);
+ selectAll.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ projectsList.setCheckedElements(selectedProjects);
+ setPageComplete(projectsList.getCheckedElements().length > 0);
+ }
+ });
+ Dialog.applyDialogFont(selectAll);
+ setButtonLayoutData(selectAll);
+
+ Button deselectAll = new Button(buttonsComposite, SWT.PUSH);
+ deselectAll.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ deselectAll.setText(Messages.ProjectsImportPage_btnDeselect);
+ deselectAll.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ projectsList.setCheckedElements(new Object[0]);
+ setPageComplete(false);
+ }
+ });
+ Dialog.applyDialogFont(deselectAll);
+ setButtonLayoutData(deselectAll);
+
+ Button refresh = new Button(buttonsComposite, SWT.PUSH);
+ refresh.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ refresh.setText(Messages.ProjectsImportPage_btnRefresh);
+ refresh.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ updateProjectsList(location);
+ }
+ });
+ Dialog.applyDialogFont(refresh);
+ setButtonLayoutData(refresh);
+ }
+
+ /**
+ * Update the list of projects based on path. Method declared public only for test suite.
+ *
+ * @param path
+ */
+ void updateProjectsList(final String path) {
+ try {
+ getContainer().run(true, true, new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) {
+ monitor.beginTask(Messages.ProjectsImportPage_task_search, 100);
+ File directory = new File(path);
+ selectedProjects = new ProjectRecord[0];
+ Collection<File> files = new ArrayList<File>();
+ monitor.worked(10);
+
+ if(directory.isDirectory()) {
+ if(!collectProjectFilesFromDirectory(files, directory, null, monitor)) {
+ return;
+ }
+ selectedProjects = new ProjectRecord[files.size()];
+ int index = 0;
+ monitor.worked(50);
+ monitor.subTask(Messages.ProjectsImportPage_task_processing);
+ for(File file : files) {
+ selectedProjects[index] = new ProjectRecord(file);
+ index++ ;
+ }
+ } else {
+ monitor.worked(60);
+ }
+ monitor.done();
+ }
+
+ });
+ } catch(InvocationTargetException e) {
+ MavenLogger.log(e.getMessage(), e);
+ } catch(InterruptedException e) {
+ // Nothing to do if the user interrupts.
+ }
+
+ projectsList.refresh(true);
+ projectsList.setCheckedElements(getValidProjects());
+ if(getValidProjects().length < selectedProjects.length) {
+ setMessage(Messages.ProjectsImportPage_message, WARNING);
+ } else {
+ setMessage(null, WARNING);
+ }
+ setPageComplete(projectsList.getCheckedElements().length > 0);
+ }
+
+ /**
+ * Collect the list of .project files that are under directory into files.
+ *
+ * @param files
+ * @param directory
+ * @param directoriesVisited Set of canonical paths of directories, used as recursion guard
+ * @param monitor The monitor to report to
+ * @return boolean <code>true</code> if the operation was completed.
+ */
+ boolean collectProjectFilesFromDirectory(Collection<File> files, File directory, Set<String> directoriesVisited,
+ IProgressMonitor monitor) {
+ if(monitor.isCanceled()) {
+ return false;
+ }
+
+ monitor.subTask(NLS.bind(Messages.ProjectsImportPage_task_checking, directory.getPath()));
+ File[] contents = directory.listFiles();
+ if(contents == null)
+ return false;
+
+ // Initialize recursion guard for recursive symbolic links
+ if(directoriesVisited == null) {
+ directoriesVisited = new HashSet<String>();
+ try {
+ directoriesVisited.add(directory.getCanonicalPath());
+ } catch(IOException exception) {
+ MavenLogger.log(exception.toString(), exception);
+ }
+ }
+
+ // first look for project description files
+ final String dotProject = IProjectDescription.DESCRIPTION_FILE_NAME;
+ for(File file : contents) {
+ if(file.isFile() && file.getName().equals(dotProject)) {
+ files.add(file);
+ // don't search sub-directories since we can't have nested
+ // projects
+ return true;
+ }
+ }
+
+ // no project description found, so recurse into sub-directories
+ for(File file : contents) {
+ if(file.isDirectory() && !IMavenConstants.METADATA_FOLDER.equals(file.getName())) {
+ try {
+ String canonicalPath = file.getCanonicalPath();
+ if(!directoriesVisited.add(canonicalPath)) {
+ // already been here --> do not recurse
+ continue;
+ }
+ } catch(IOException exception) {
+ MavenLogger.log(exception.toString(), exception);
+ }
+ collectProjectFilesFromDirectory(files, file, directoriesVisited, monitor);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Create the selected projects
+ *
+ * @return boolean <code>true</code> if all project creations were successful.
+ */
+ public boolean createProjects() {
+ final Object[] selected = projectsList.getCheckedElements();
+
+ WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
+ protected void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ try {
+ monitor.beginTask("", selected.length); //$NON-NLS-1$
+ if(monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+
+ for(int i = 0; i < selected.length; i++ ) {
+ createExistingProject((ProjectRecord) selected[i], new SubProgressMonitor(monitor, 1));
+ }
+ } finally {
+ monitor.done();
+ }
+ }
+ };
+
+ // run the new project creation operation
+ try {
+ getContainer().run(true, true, op);
+ } catch(InterruptedException e) {
+ return false;
+ } catch(InvocationTargetException e) {
+ // one of the steps resulted in a core exception
+ Throwable t = e.getTargetException();
+ String message = Messages.ProjectsImportPage_error_creation;
+ IStatus status;
+ if(t instanceof CoreException) {
+ status = ((CoreException) t).getStatus();
+ } else {
+ status = new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, 1, message, t);
+ }
+ ErrorDialog.openError(getShell(), message, null, status);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Performs clean-up if the user cancels the wizard without doing anything
+ */
+ public void performCancel() {
+ }
+
+ /**
+ * Create the project described in record. If it is successful return true.
+ *
+ * @param record
+ * @return boolean <code>true</code> if successful
+ * @throws InterruptedException
+ */
+ boolean createExistingProject(final ProjectRecord record, IProgressMonitor monitor)
+ throws InvocationTargetException, InterruptedException {
+ String projectName = record.getProjectName();
+ final IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ final IProject project = workspace.getRoot().getProject(projectName);
+ if(record.description == null) {
+ // error case
+ record.description = workspace.newProjectDescription(projectName);
+ IPath locationPath = new Path(record.projectFile.getAbsolutePath());
+
+ // If it is under the root use the default location
+ if(Platform.getLocation().isPrefixOf(locationPath)) {
+ record.description.setLocation(null);
+ } else {
+ record.description.setLocation(locationPath);
+ }
+ } else {
+ record.description.setName(projectName);
+ }
+
+ try {
+ monitor.beginTask(Messages.ProjectsImportPage_task_creating, 100);
+
+ @SuppressWarnings("deprecation")
+ IPath projectPath = record.description.getLocation();
+ if(projectPath!=null) {
+ MavenConsole console = MavenPlugin.getDefault().getConsole();
+
+ IWorkspaceRoot root = workspace.getRoot();
+
+ if(projectPath.toFile().equals(root.getLocation().toFile())) {
+ console.logError("Can't create project " + projectName + " at Workspace folder");
+ return false;
+ }
+
+ if(projectPath.removeLastSegments(1).toFile().equals(root.getLocation().toFile())) {
+ // rename dir in workspace to match expected project name
+ if(!projectPath.equals(root.getLocation().append(projectName))) {
+ File projectDir = projectPath.toFile();
+ File newProject = new File(projectDir.getParent(), projectName);
+ if(!projectDir.renameTo(newProject)) {
+ MavenLogger.log("Can't rename " + projectDir + " to " + newProject, null);
+ }
+ record.description.setLocation(null);
+ }
+ }
+ }
+
+ project.create(record.description, new SubProgressMonitor(monitor, 30));
+ project.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(monitor, 70));
+
+ } catch(CoreException e) {
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+
+ return true;
+ }
+
+ /**
+ * The <code>WizardDataTransfer</code> implementation of this <code>IOverwriteQuery</code> method asks the user
+ * whether the existing resource at the given path should be overwritten.
+ *
+ * @param pathString
+ * @return the user's reply: one of <code>"YES"</code>, <code>"NO"</code>, <code>"ALL"</code>, or
+ * <code>"CANCEL"</code>
+ */
+ public String queryOverwrite(String pathString) {
+ Path path = new Path(pathString);
+
+ String messageString;
+ // Break the message up if there is a file name and a directory
+ // and there are at least 2 segments.
+ if(path.getFileExtension() == null || path.segmentCount() < 2) {
+ messageString = NLS.bind(Messages.ProjectsImportPage_overwrite, pathString);
+ } else {
+ messageString = NLS.bind(Messages.ProjectsImportPage_overwrite2,
+ path.lastSegment(), path.removeLastSegments(1).toOSString());
+ }
+
+ final MessageDialog dialog = new MessageDialog(getContainer().getShell(), Messages.ProjectsImportPage_dialog_title, null,
+ messageString, MessageDialog.QUESTION, new String[] {IDialogConstants.YES_LABEL,
+ IDialogConstants.YES_TO_ALL_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.NO_TO_ALL_LABEL,
+ IDialogConstants.CANCEL_LABEL}, 0);
+ String[] response = new String[] {YES, ALL, NO, NO_ALL, CANCEL};
+ // run in syncExec because callback is from an operation,
+ // which is probably not running in the UI thread.
+ getControl().getDisplay().syncExec(new Runnable() {
+ public void run() {
+ dialog.open();
+ }
+ });
+ return dialog.getReturnCode() < 0 ? CANCEL : response[dialog.getReturnCode()];
+ }
+
+ /**
+ * Retrieve all the projects in the current workspace.
+ *
+ * @return IProject[] array of IProject in the current workspace
+ */
+ private IProject[] getProjectsInWorkspace() {
+ if(wsProjects == null) {
+ wsProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ }
+ return wsProjects;
+ }
+
+ /**
+ * Method used for test suite.
+ *
+ * @return CheckboxTreeViewer the viewer containing all the projects found
+ */
+ public CheckboxTreeViewer getProjectsList() {
+ return projectsList;
+ }
+
+ /**
+ * Get the array of valid project records that can be imported from the source workspace or archive, selected by the
+ * user. If a project with the same name exists in both the source workspace and the current workspace, it will not
+ * appear in the list of projects to import and thus cannot be selected for import. Method declared public for test
+ * suite.
+ *
+ * @return ProjectRecord[] array of projects that can be imported into the workspace
+ */
+ public ProjectRecord[] getValidProjects() {
+ List<ProjectRecord> validProjects = new ArrayList<ProjectRecord>();
+ for(ProjectRecord projectRecord : selectedProjects) {
+ if(!isProjectInWorkspace(projectRecord.getProjectName())) {
+ validProjects.add(projectRecord);
+ }
+ }
+ return validProjects.toArray(new ProjectRecord[validProjects.size()]);
+ }
+
+ /**
+ * Determine if the project with the given name is in the current workspace.
+ *
+ * @param projectName String the project name to check
+ * @return boolean true if the project with the given name is in this workspace
+ */
+ private boolean isProjectInWorkspace(String projectName) {
+ if(projectName == null) {
+ return false;
+ }
+ IProject[] workspaceProjects = getProjectsInWorkspace();
+ for(int i = 0; i < workspaceProjects.length; i++ ) {
+ if(projectName.equals(workspaceProjects[i].getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+
+ /**
+ * Class declared public only for test suite.
+ */
+ public static class ProjectRecord {
+ File projectFile;
+
+ String projectName;
+
+ IProjectDescription description;
+
+ /**
+ * Create a record for a project based on the info in the file.
+ *
+ * @param file
+ */
+ ProjectRecord(File file) {
+ projectFile = file;
+ setProjectName();
+ }
+
+ /**
+ * Set the name of the project based on the projectFile.
+ */
+ private void setProjectName() {
+ IProjectDescription newDescription = null;
+ try {
+ IPath path = new Path(projectFile.getPath());
+ // if the file is in the default location, use the directory
+ // name as the project name
+ newDescription = ResourcesPlugin.getWorkspace().loadProjectDescription(path);
+
+ if(isDefaultLocation(path)) {
+ // projectName = path.segment(path.segmentCount() - 2);
+ // newDescription = ResourcesPlugin.getWorkspace().newProjectDescription(projectName);
+ }
+ } catch(CoreException e) {
+ // no good couldn't get the name
+ }
+
+ if(newDescription == null) {
+ this.description = null;
+ projectName = ""; //$NON-NLS-1$
+ } else {
+ this.description = newDescription;
+ projectName = this.description.getName();
+ }
+ }
+
+ /**
+ * Returns whether the given project description file path is in the default location for a project
+ *
+ * @param path The path to examine
+ * @return Whether the given path is the default location for a project
+ */
+ private boolean isDefaultLocation(IPath path) {
+ // The project description file must at least be within the project, which is within the workspace location
+ return path.segmentCount() > 1 && path.removeLastSegments(2).toFile().equals(Platform.getLocation().toFile());
+ }
+
+ /**
+ * Get the name of the project
+ *
+ * @return String
+ */
+ public String getProjectName() {
+ return projectName;
+ }
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/ProjectsImportWizard.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/ProjectsImportWizard.java
new file mode 100644
index 00000000..b6c3f0db
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/ProjectsImportWizard.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.ui.internal.MavenImages;
+
+/**
+ * WizardExtension
+ *
+ * @author Eugene Kuleshov
+ */
+public class ProjectsImportWizard extends Wizard {
+ private final String location;
+
+ private ProjectsImportPage mainPage;
+
+ public ProjectsImportWizard(String location) {
+ this.location = location;
+ setWindowTitle(Messages.ProjectsImportWizard_title);
+ setDefaultPageImageDescriptor(MavenImages.WIZ_IMPORT_WIZ);
+ }
+
+ public void addPages() {
+ mainPage = new ProjectsImportPage(this.location);
+ addPage(mainPage);
+ }
+
+ public boolean performCancel() {
+ mainPage.performCancel();
+ return true;
+ }
+
+ public boolean performFinish() {
+ return mainPage.createProjects();
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/ResolverConfigurationComponent.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/ResolverConfigurationComponent.java
new file mode 100644
index 00000000..cc183d04
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/ResolverConfigurationComponent.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import org.eclipse.m2e.core.core.Messages;
+import org.eclipse.m2e.core.project.ProjectImportConfiguration;
+import org.eclipse.m2e.core.project.ResolverConfiguration;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.events.ExpansionAdapter;
+import org.eclipse.ui.forms.events.ExpansionEvent;
+import org.eclipse.ui.forms.widgets.ExpandableComposite;
+
+
+/**
+ * A foldable resolver configuration panel
+ */
+public class ResolverConfigurationComponent extends ExpandableComposite {
+
+ private static final String[] DEFAULT_NAME_TEMPLATES = {"[artifactId]", // //$NON-NLS-1$
+ "[artifactId]-TRUNK", // //$NON-NLS-1$
+ "[artifactId]-[version]", // //$NON-NLS-1$
+ "[groupId].[artifactId]", "[groupId].[artifactId]-[version]"}; //$NON-NLS-1$ //$NON-NLS-2$
+
+ /** The resolver configuration */
+ protected final ResolverConfiguration resolverConfiguration;
+
+ /** project import configuration */
+ private final ProjectImportConfiguration projectImportConfiguration;
+
+ private ModifyListener modifyListener;
+
+ Button resolveWorkspaceProjects;
+
+ Text profiles;
+
+ Combo template;
+
+ /** Creates a new component. */
+ public ResolverConfigurationComponent(final Composite parent,
+ final ProjectImportConfiguration propectImportConfiguration, final boolean enableProjectNameTemplate) {
+ super(parent, ExpandableComposite.COMPACT | ExpandableComposite.TWISTIE | ExpandableComposite.EXPANDED);
+ this.projectImportConfiguration = propectImportConfiguration;
+ this.resolverConfiguration = propectImportConfiguration.getResolverConfiguration();
+
+ setText(Messages.getString("resolverConfiguration.advanced")); //$NON-NLS-1$
+
+ final Composite advancedComposite = new Composite(this, SWT.NONE);
+ setClient(advancedComposite);
+ addExpansionListener(new ExpansionAdapter() {
+ public void expansionStateChanged(ExpansionEvent e) {
+ Shell shell = parent.getShell();
+ Point minSize = shell.getMinimumSize();
+ shell.setMinimumSize(shell.getSize().x, minSize.y);
+ shell.pack();
+ parent.layout();
+ shell.setMinimumSize(minSize);
+ }
+ });
+
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.marginLeft = 11;
+ gridLayout.numColumns = 2;
+ advancedComposite.setLayout(gridLayout);
+
+ resolveWorkspaceProjects = new Button(advancedComposite, SWT.CHECK);
+ resolveWorkspaceProjects.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
+ resolveWorkspaceProjects.setText(Messages.getString("resolverConfiguration.resolveWorkspaceProjects")); //$NON-NLS-1$
+ resolveWorkspaceProjects.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ resolverConfiguration.setResolveWorkspaceProjects(resolveWorkspaceProjects.getSelection());
+ }
+ });
+
+ Label profilesLabel = new Label(advancedComposite, SWT.NONE);
+ profilesLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
+ profilesLabel.setText(Messages.getString("resolverConfiguration.profiles")); //$NON-NLS-1$
+
+ profiles = new Text(advancedComposite, SWT.BORDER);
+ profiles.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ profiles.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ resolverConfiguration.setActiveProfiles(profiles.getText());
+ }
+ });
+
+ if(enableProjectNameTemplate) {
+ Label templateLabel = new Label(advancedComposite, SWT.NONE);
+ templateLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
+ templateLabel.setText(Messages.getString("resolverConfiguration.template")); //$NON-NLS-1$
+
+ template = new Combo(advancedComposite, SWT.BORDER);
+ template.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ template.setToolTipText(Messages.getString("resolverConfiguration.templateDescription")); //$NON-NLS-1$
+ template.setItems(DEFAULT_NAME_TEMPLATES);
+ template.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ propectImportConfiguration.setProjectNameTemplate(template.getText());
+ }
+ });
+ }
+
+ loadData();
+ }
+
+ public void loadData() {
+ resolveWorkspaceProjects.setSelection(resolverConfiguration.shouldResolveWorkspaceProjects());
+ profiles.setText(resolverConfiguration.getActiveProfiles());
+ if(template != null) {
+ template.setText(projectImportConfiguration.getProjectNameTemplate());
+ }
+ }
+
+ public ResolverConfiguration getResolverConfiguration() {
+ return this.resolverConfiguration;
+ }
+
+ public void setModifyListener(ModifyListener modifyListener) {
+ this.modifyListener = modifyListener;
+
+ if(template != null) {
+ template.addModifyListener(modifyListener);
+ }
+ }
+
+ public void dispose() {
+ super.dispose();
+
+ if(modifyListener != null) {
+ template.removeModifyListener(modifyListener);
+ }
+ }
+
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/WidthGroup.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/WidthGroup.java
new file mode 100644
index 00000000..c5ef651f
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/WidthGroup.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.HashSet;
+
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * Group of controls with the same width
+ *
+ * @author Eugene Kuleshov
+ */
+public class WidthGroup extends ControlAdapter {
+
+ private final HashSet<Control> controls = new HashSet<Control>();
+
+ public void controlResized(ControlEvent e) {
+ int maxWidth = 0;
+ for(Control c : this.controls) {
+ int width = c.getSize().x;
+ if(width > maxWidth) {
+ maxWidth = width;
+ }
+ }
+ if(maxWidth > 0) {
+ for(Control c : this.controls) {
+ GridData gd = (GridData) c.getLayoutData();
+ gd.widthHint = maxWidth;
+ c.getParent().layout();
+ }
+ }
+ }
+
+ public void addControl(Control control) {
+ controls.add(control);
+ control.getParent().layout();
+ }
+
+}
+
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/WorkingSetGroup.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/WorkingSetGroup.java
new file mode 100644
index 00000000..3766579f
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/WorkingSetGroup.java
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.resource.DeviceResourceException;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.resource.LocalResourceManager;
+import org.eclipse.jface.resource.ResourceManager;
+import org.eclipse.jface.viewers.ComboViewer;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.jface.window.Window;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkingSet;
+import org.eclipse.ui.IWorkingSetManager;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.IWorkingSetSelectionDialog;
+
+
+/**
+ * Working set group
+ *
+ * @author Eugene Kuleshov
+ */
+public class WorkingSetGroup {
+
+ static final List<String> WORKING_SET_IDS = Arrays.asList( //
+ "org.eclipse.ui.resourceWorkingSetPage", "org.eclipse.jdt.ui.JavaWorkingSetPage"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ ComboViewer workingsetComboViewer;
+
+ Button addToWorkingSetButton;
+
+ final List<IWorkingSet> workingSets;
+
+ final Shell shell;
+
+ public WorkingSetGroup(Composite container, List<IWorkingSet> workingSets, Shell shell) {
+ this.workingSets = workingSets;
+ this.shell = shell;
+
+ createControl(container);
+ }
+
+ private void createControl(Composite container) {
+ addToWorkingSetButton = new Button(container, SWT.CHECK);
+ GridData gd_addToWorkingSetButton = new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1);
+ gd_addToWorkingSetButton.verticalIndent = 12;
+ addToWorkingSetButton.setLayoutData(gd_addToWorkingSetButton);
+ addToWorkingSetButton.setSelection(true);
+ addToWorkingSetButton.setData("name", "addToWorkingSetButton"); //$NON-NLS-1$ //$NON-NLS-2$
+ addToWorkingSetButton.setText(Messages.WorkingSetGroup_btnAddSet);
+ addToWorkingSetButton.setSelection(false);
+
+ final Label workingsetLabel = new Label(container, SWT.NONE);
+ GridData gd_workingsetLabel = new GridData();
+ gd_workingsetLabel.horizontalIndent = 10;
+ workingsetLabel.setLayoutData(gd_workingsetLabel);
+ workingsetLabel.setEnabled(false);
+ workingsetLabel.setData("name", "workingsetLabel"); //$NON-NLS-1$ //$NON-NLS-2$
+ workingsetLabel.setText(Messages.WorkingSetGroup_lblSet);
+
+ Combo workingsetCombo = new Combo(container, SWT.READ_ONLY);
+ workingsetCombo.setEnabled(false);
+ workingsetCombo.setData("name", "workingsetCombo"); //$NON-NLS-1$ //$NON-NLS-2$
+ workingsetCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+
+ workingsetComboViewer = new ComboViewer(workingsetCombo);
+ workingsetComboViewer.setContentProvider(new IStructuredContentProvider() {
+ public Object[] getElements(Object input) {
+ if(input instanceof IWorkingSet[]) {
+ return (IWorkingSet[]) input;
+ } else if(input instanceof List<?>) {
+ return new Object[] {input};
+ } else if(input instanceof Set<?>) {
+ return ((Set<?>) input).toArray();
+ }
+ return new IWorkingSet[0];
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+
+ public void dispose() {
+ }
+ });
+ workingsetComboViewer.setLabelProvider(new LabelProvider() {
+ private ResourceManager images = new LocalResourceManager(JFaceResources.getResources());
+
+ @SuppressWarnings("deprecation")
+ public Image getImage(Object element) {
+ if(element instanceof IWorkingSet) {
+ ImageDescriptor imageDescriptor = ((IWorkingSet) element).getImage();
+ if(imageDescriptor != null) {
+ try {
+ return (Image) images.create(imageDescriptor);
+ } catch(DeviceResourceException ex) {
+ return null;
+ }
+ }
+ }
+ return super.getImage(element);
+ }
+
+ public String getText(Object element) {
+ if(element instanceof IWorkingSet) {
+ return ((IWorkingSet) element).getLabel();
+ } else if(element instanceof List<?>) {
+ StringBuffer sb = new StringBuffer();
+ for(Object o : (List<?>) element) {
+ if(o instanceof IWorkingSet) {
+ if(sb.length() > 0) {
+ sb.append(", "); //$NON-NLS-1$
+ }
+ sb.append(((IWorkingSet) o).getLabel());
+ }
+ }
+ return sb.toString();
+ }
+ return super.getText(element);
+ }
+
+ public void dispose() {
+ images.dispose();
+ super.dispose();
+ }
+ });
+
+ workingsetComboViewer.setComparator(new ViewerComparator());
+
+ final Button newWorkingSetButton = new Button(container, SWT.NONE);
+ newWorkingSetButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
+ newWorkingSetButton.setData("name", "configureButton"); //$NON-NLS-1$ //$NON-NLS-2$
+ newWorkingSetButton.setText(Messages.WorkingSetGroup_btnMore);
+ newWorkingSetButton.setEnabled(false);
+ newWorkingSetButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(final SelectionEvent e) {
+ IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager();
+ IWorkingSetSelectionDialog dialog = workingSetManager.createWorkingSetSelectionDialog(shell, true,
+ WORKING_SET_IDS.toArray(new String[0]));
+ if(dialog.open() == Window.OK) {
+ IWorkingSet[] workingSets = dialog.getSelection();
+ selectWorkingSets(Arrays.asList(workingSets));
+ }
+ }
+ });
+
+ if(selectWorkingSets(workingSets)) {
+ addToWorkingSetButton.setSelection(true);
+ workingsetLabel.setEnabled(true);
+ workingsetComboViewer.getCombo().setEnabled(true);
+ newWorkingSetButton.setEnabled(true);
+ }
+
+ addToWorkingSetButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ boolean addToWorkingingSet = addToWorkingSetButton.getSelection();
+ workingsetLabel.setEnabled(addToWorkingingSet);
+ workingsetComboViewer.getCombo().setEnabled(addToWorkingingSet);
+ newWorkingSetButton.setEnabled(addToWorkingingSet);
+ if(addToWorkingingSet) {
+ updateConfiguration();
+ } else {
+ workingSets.clear();
+ }
+ }
+ });
+
+ workingsetComboViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ updateConfiguration();
+ }
+ });
+ }
+
+ protected void updateConfiguration() {
+ if(addToWorkingSetButton.getSelection()) {
+ IStructuredSelection selection = (IStructuredSelection) workingsetComboViewer.getSelection();
+ Object o = selection.getFirstElement();
+ if(o != null) {
+ workingSets.clear();
+ if(o instanceof IWorkingSet) {
+ workingSets.add((IWorkingSet) o);
+ } else if(o instanceof List<?>) {
+ @SuppressWarnings("unchecked")
+ List<IWorkingSet> l = (List<IWorkingSet>) o;
+ workingSets.addAll(l);
+ }
+ }
+ }
+ }
+
+ Set<IWorkingSet> getWorkingSets() {
+ Set<IWorkingSet> workingSets = new HashSet<IWorkingSet>();
+
+ IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager();
+ for(IWorkingSet workingSet : workingSetManager.getWorkingSets()) {
+ if(!workingSet.isEmpty()) {
+ IAdaptable[] elements = workingSet.getElements();
+ IResource resource = (IResource) elements[0].getAdapter(IResource.class);
+ if(resource != null) {
+ workingSets.add(workingSet);
+ }
+ } else {
+ if(WORKING_SET_IDS.contains(workingSet.getId())) {
+ workingSets.add(workingSet);
+ }
+ }
+ }
+
+ return workingSets;
+ }
+
+ public void dispose() {
+ workingsetComboViewer.getLabelProvider().dispose();
+ }
+
+ protected boolean selectWorkingSets(List<IWorkingSet> workingSets) {
+ Set<IWorkingSet> defaultSets = getWorkingSets();
+ workingsetComboViewer.setInput(defaultSets);
+
+ if(workingSets != null && workingSets.size() > 0) {
+ if(workingSets.size() == 1) {
+ IWorkingSet workingSet = workingSets.get(0);
+ if(defaultSets.contains(workingSet)) {
+ workingsetComboViewer.setSelection(new StructuredSelection(workingSet));
+ }
+ } else {
+ workingsetComboViewer.add(workingSets);
+ workingsetComboViewer.setSelection(new StructuredSelection((Object) workingSets));
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/WorkingSetHelper.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/WorkingSetHelper.java
new file mode 100644
index 00000000..171a95b9
--- /dev/null
+++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/WorkingSetHelper.java
@@ -0,0 +1,8 @@
+
+package org.eclipse.m2e.core.ui.internal.wizards;
+
+
+
+public class WorkingSetHelper {
+
+}

Back to the top