diff options
Diffstat (limited to 'org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core')
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 { + +} |