From dad71b863bf5569d406030b8165a4399d23d7d00 Mon Sep 17 00:00:00 2001 From: Greg Watson Date: Sat, 7 Jun 2014 00:07:26 -0400 Subject: [PATCH] Bug 428658 - Add a default Authenticator Change-Id: I9e2e3ced3c1d3a0b9fb97e685d3836b586cc98a0 Signed-off-by: Greg Watson --- bundles/org.eclipse.remote.core/plugin.xml | 1 + .../schema/authenticator.exsd | 99 +++++++++++++++++ .../core/AbstractRemoteConnectionManager.java | 101 ++++++++++++++++++ .../remote/core/IRemoteConnection.java | 14 --- .../remote/core/IRemoteConnectionManager.java | 10 ++ .../core/services/local/LocalConnection.java | 12 --- .../local/LocalConnectionManager.java | 5 +- .../internal/jsch/core/JSchConnection.java | 15 +-- .../jsch/core/JSchConnectionManager.java | 16 +-- bundles/org.eclipse.remote.jsch.ui/plugin.xml | 8 ++ .../jsch/ui/JSchUIConnectionManager.java | 80 +------------- .../jsch/ui/JSchUserAuthenticator.java | 93 ++++++++++++++++ 12 files changed, 328 insertions(+), 126 deletions(-) create mode 100644 bundles/org.eclipse.remote.core/schema/authenticator.exsd create mode 100644 bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/AbstractRemoteConnectionManager.java create mode 100644 bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/JSchUserAuthenticator.java diff --git a/bundles/org.eclipse.remote.core/plugin.xml b/bundles/org.eclipse.remote.core/plugin.xml index 4434d889a90..649790aaebd 100644 --- a/bundles/org.eclipse.remote.core/plugin.xml +++ b/bundles/org.eclipse.remote.core/plugin.xml @@ -4,6 +4,7 @@ + + + + + + + + + [Enter description of this extension point.] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The ID of the remote services that this authenticator should be used for. + + + + + + + An implementation of the IUserAuthenticator interface. + + + + + + + + + + The numerical value of the priority of the authenticator. The highest priority authenticator will be preferred over lower priority authenticators. + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + diff --git a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/AbstractRemoteConnectionManager.java b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/AbstractRemoteConnectionManager.java new file mode 100644 index 00000000000..e3f9a63f6c2 --- /dev/null +++ b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/AbstractRemoteConnectionManager.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corporation and others. + * 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: + * IBM Corporation - Initial API and implementation + *******************************************************************************/ +package org.eclipse.remote.core; + +import java.lang.reflect.Constructor; + +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.Platform; +import org.eclipse.remote.internal.core.RemoteCorePlugin; + +/** + * Abstract base class for remote connection managers. + * + * @since 8.0 + */ +public abstract class AbstractRemoteConnectionManager implements IRemoteConnectionManager { + private static final String AUTHENTICATOR_EXTENSION_POINT_ID = "authenticator"; //$NON-NLS-1$ + private static final String ID_ATTR = "id"; //$NON-NLS-1$ + private static final String CLASS_ATTR = "class"; //$NON-NLS-1$ + private static final String PRIORITY_ATTR = "priority"; //$NON-NLS-1$ + + private final IRemoteServices fRemoteServices; + private boolean fLoaded; + private Constructor fUserAuthenticatorConstructor; + + public AbstractRemoteConnectionManager(IRemoteServices services) { + fRemoteServices = services; + } + + protected IRemoteServices getRemoteServices() { + return fRemoteServices; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.remote.core.IRemoteConnectionManager#getUserAuthenticator() + */ + @Override + public IUserAuthenticator getUserAuthenticator(IRemoteConnection connection) { + if (!fLoaded) { + int currPriority = -1; + IExtensionRegistry registry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = registry.getExtensionPoint(RemoteCorePlugin.getUniqueIdentifier(), + AUTHENTICATOR_EXTENSION_POINT_ID); + final IExtension[] extensions = extensionPoint.getExtensions(); + + for (IExtension ext : extensions) { + final IConfigurationElement[] elements = ext.getConfigurationElements(); + + for (IConfigurationElement ce : elements) { + String id = ce.getAttribute(ID_ATTR); + if (id.equals(getRemoteServices().getId())) { + int priority = 0; + String priorityAttr = ce.getAttribute(PRIORITY_ATTR); + if (priorityAttr != null) { + try { + priority = Integer.parseInt(priorityAttr); + } catch (NumberFormatException e) { + // Assume default + } + } + if (priority > currPriority) { + try { + String widgetClass = ce.getAttribute(CLASS_ATTR); + Class cls = Platform.getBundle(ce.getDeclaringExtension().getContributor().getName()).loadClass( + widgetClass); + if (cls != null) { + fUserAuthenticatorConstructor = cls.getConstructor(IRemoteConnection.class); + currPriority = priority; + } + } catch (ClassNotFoundException | NoSuchMethodException e) { + RemoteCorePlugin.log(e); + } + } + } + } + } + fLoaded = true; + } + if (fUserAuthenticatorConstructor != null) { + try { + return (IUserAuthenticator) fUserAuthenticatorConstructor.newInstance(connection); + } catch (Exception e) { + RemoteCorePlugin.log(e); + } + } + return null; + } +} \ No newline at end of file diff --git a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/IRemoteConnection.java b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/IRemoteConnection.java index aabb544a98b..5a86677268c 100644 --- a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/IRemoteConnection.java +++ b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/IRemoteConnection.java @@ -279,20 +279,6 @@ public interface IRemoteConnection extends Comparable { */ public void open(IProgressMonitor monitor) throws RemoteConnectionException; - /** - * Open the connection. Must be called before the connection can be used. - * - * @param authenticator - * authenticator to allow the caller to manage interaction with the user - * @param monitor - * the progress monitor to use for reporting progress to the user. It is the caller's responsibility to call done() - * on the given monitor. Accepts null, indicating that no progress should be reported and that the operation cannot - * be cancelled. - * @throws RemoteConnectionException - * @since 7.0 - */ - public void open(IUserAuthenticator authenticator, IProgressMonitor monitor) throws RemoteConnectionException; - /** * Remove a listener that will be notified when this connection's status changes. * diff --git a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/IRemoteConnectionManager.java b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/IRemoteConnectionManager.java index 7cdf0f10b0c..8eeb68a4b86 100644 --- a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/IRemoteConnectionManager.java +++ b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/core/IRemoteConnectionManager.java @@ -53,6 +53,16 @@ public interface IRemoteConnectionManager { */ public List getConnections(); + /** + * Get the user authenticator that will be used when opening connections. The user authenticator is specified using the + * org.eclipse.remote.core.authenticator extension point. + * + * @param connection + * connection that will use this authenticator + * @return user authenticator + */ + public IUserAuthenticator getUserAuthenticator(IRemoteConnection connection); + /** * Creates a new remote connection named with supplied name. The connection attributes will be the default for the * implementation. diff --git a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/services/local/LocalConnection.java b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/services/local/LocalConnection.java index 8138744c610..18b112be9c7 100644 --- a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/services/local/LocalConnection.java +++ b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/services/local/LocalConnection.java @@ -28,7 +28,6 @@ import org.eclipse.remote.core.IRemoteFileManager; import org.eclipse.remote.core.IRemoteProcess; import org.eclipse.remote.core.IRemoteProcessBuilder; import org.eclipse.remote.core.IRemoteServices; -import org.eclipse.remote.core.IUserAuthenticator; import org.eclipse.remote.core.exception.RemoteConnectionException; import org.eclipse.remote.core.exception.UnableToForwardPortException; import org.eclipse.remote.internal.core.RemoteCorePlugin; @@ -352,17 +351,6 @@ public class LocalConnection implements IRemoteConnection { } } - /* - * (non-Javadoc) - * - * @see org.eclipse.remote.core.IRemoteConnection#open(org.eclipse.remote.core.IUserAuthenticator, - * org.eclipse.core.runtime.IProgressMonitor) - */ - @Override - public void open(IUserAuthenticator authenticator, IProgressMonitor monitor) throws RemoteConnectionException { - open(monitor); - } - /* * (non-Javadoc) * diff --git a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/services/local/LocalConnectionManager.java b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/services/local/LocalConnectionManager.java index 76461dd528d..23468927c16 100644 --- a/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/services/local/LocalConnectionManager.java +++ b/bundles/org.eclipse.remote.core/src/org/eclipse/remote/internal/core/services/local/LocalConnectionManager.java @@ -15,17 +15,18 @@ import java.util.ArrayList; import java.util.List; import org.eclipse.core.filesystem.EFS; +import org.eclipse.remote.core.AbstractRemoteConnectionManager; import org.eclipse.remote.core.IRemoteConnection; -import org.eclipse.remote.core.IRemoteConnectionManager; import org.eclipse.remote.core.IRemoteConnectionWorkingCopy; import org.eclipse.remote.core.IRemoteServices; import org.eclipse.remote.core.exception.RemoteConnectionException; import org.eclipse.remote.internal.core.messages.Messages; -public class LocalConnectionManager implements IRemoteConnectionManager { +public class LocalConnectionManager extends AbstractRemoteConnectionManager { private final IRemoteConnection fLocalConnection; public LocalConnectionManager(IRemoteServices services) { + super(services); fLocalConnection = new LocalConnection(services); } diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java index 86bdeeb6a4f..e42e41c12da 100644 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnection.java @@ -809,26 +809,15 @@ public class JSchConnection implements IRemoteConnection { */ @Override public void open(IProgressMonitor monitor) throws RemoteConnectionException { - open(null, monitor); - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.remote.core.IRemoteConnection#open(org.eclipse.remote.core.IUserAuthenticator, - * org.eclipse.core.runtime.IProgressMonitor) - */ - @Override - public void open(final IUserAuthenticator authenticator, IProgressMonitor monitor) throws RemoteConnectionException { if (!isOpen()) { checkIsConfigured(); SubMonitor subMon = SubMonitor.convert(monitor, 70); - Session session = newSession(authenticator, subMon.newChild(10)); + Session session = newSession(fManager.getUserAuthenticator(this), subMon.newChild(10)); if (subMon.isCanceled()) { throw new RemoteConnectionException(Messages.JSchConnection_Connection_was_cancelled); } if (!checkConfiguration(session, subMon.newChild(20))) { - newSession(authenticator, subMon.newChild(10)); + newSession(fManager.getUserAuthenticator(this), subMon.newChild(10)); loadEnv(subMon.newChild(10)); } fWorkingDir = getCwd(subMon.newChild(10)); diff --git a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnectionManager.java b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnectionManager.java index 2371454b3d4..a93f29ed79a 100644 --- a/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnectionManager.java +++ b/bundles/org.eclipse.remote.jsch.core/src/org/eclipse/remote/internal/jsch/core/JSchConnectionManager.java @@ -20,8 +20,8 @@ import java.util.Map; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.osgi.util.NLS; +import org.eclipse.remote.core.AbstractRemoteConnectionManager; import org.eclipse.remote.core.IRemoteConnection; -import org.eclipse.remote.core.IRemoteConnectionManager; import org.eclipse.remote.core.IRemoteConnectionWorkingCopy; import org.eclipse.remote.core.IRemoteServices; import org.eclipse.remote.core.exception.RemoteConnectionException; @@ -29,15 +29,14 @@ import org.eclipse.remote.internal.jsch.core.messages.Messages; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; -public class JSchConnectionManager implements IRemoteConnectionManager { - private final IRemoteServices fRemoteServices; +public class JSchConnectionManager extends AbstractRemoteConnectionManager { private Map fConnections; /** * @since 4.0 */ public JSchConnectionManager(IRemoteServices services) { - fRemoteServices = services; + super(services); } /* @@ -47,6 +46,7 @@ public class JSchConnectionManager implements IRemoteConnectionManager { * org.eclipse.remote.core.IRemoteConnectionManager#getConnection(java * .lang.String) */ + @Override public IRemoteConnection getConnection(String name) { loadConnections(); return fConnections.get(name); @@ -62,6 +62,7 @@ public class JSchConnectionManager implements IRemoteConnectionManager { /** * @since 4.0 */ + @Override public IRemoteConnection getConnection(URI uri) { String connName = JSchFileSystem.getConnectionNameFor(uri); if (connName != null) { @@ -71,7 +72,7 @@ public class JSchConnectionManager implements IRemoteConnectionManager { } public JSchConnection createConnection(String name) { - return new JSchConnection(name, fRemoteServices); + return new JSchConnection(name, getRemoteServices()); } /* @@ -80,6 +81,7 @@ public class JSchConnectionManager implements IRemoteConnectionManager { * @see * org.eclipse.remote.core.IRemoteConnectionManager#getConnections() */ + @Override public List getConnections() { loadConnections(); List conns = new ArrayList(); @@ -94,7 +96,7 @@ public class JSchConnectionManager implements IRemoteConnectionManager { Preferences connections = root.node(JSchConnectionAttributes.CONNECTIONS_KEY); try { for (String name : connections.childrenNames()) { - JSchConnection connection = new JSchConnection(name, fRemoteServices); + JSchConnection connection = new JSchConnection(name, getRemoteServices()); fConnections.put(name, connection); } } catch (BackingStoreException e) { @@ -113,6 +115,7 @@ public class JSchConnectionManager implements IRemoteConnectionManager { /** * @since 5.0 */ + @Override public IRemoteConnectionWorkingCopy newConnection(String name) throws RemoteConnectionException { if (getConnection(name) != null) { throw new RemoteConnectionException(NLS.bind(Messages.JSchConnectionManager_connection_with_name_exists, name)); @@ -139,6 +142,7 @@ public class JSchConnectionManager implements IRemoteConnectionManager { * org.eclipse.remote.core.IRemoteConnectionManager#removeConnection * (org.eclipse.remote.core.IRemoteConnection) */ + @Override public void removeConnection(IRemoteConnection conn) throws RemoteConnectionException { if (!(conn instanceof JSchConnection)) { throw new RemoteConnectionException(Messages.JSchConnectionManager_invalidConnectionType); diff --git a/bundles/org.eclipse.remote.jsch.ui/plugin.xml b/bundles/org.eclipse.remote.jsch.ui/plugin.xml index 79ce742cbf9..f84b7e90cb5 100644 --- a/bundles/org.eclipse.remote.jsch.ui/plugin.xml +++ b/bundles/org.eclipse.remote.jsch.ui/plugin.xml @@ -34,5 +34,13 @@ + + + + diff --git a/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/JSchUIConnectionManager.java b/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/JSchUIConnectionManager.java index d4811eec2aa..9c108403141 100644 --- a/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/JSchUIConnectionManager.java +++ b/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/JSchUIConnectionManager.java @@ -11,103 +11,25 @@ package org.eclipse.remote.internal.jsch.ui; import java.lang.reflect.InvocationTargetException; -import java.net.PasswordAuthentication; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.ErrorDialog; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.operation.IRunnableWithProgress; -import org.eclipse.jsch.ui.UserInfoPrompter; import org.eclipse.remote.core.IRemoteConnection; import org.eclipse.remote.core.IRemoteServices; -import org.eclipse.remote.core.IUserAuthenticator; import org.eclipse.remote.core.exception.RemoteConnectionException; import org.eclipse.remote.internal.jsch.core.JSchConnectionManager; import org.eclipse.remote.internal.jsch.ui.messages.Messages; import org.eclipse.remote.internal.jsch.ui.wizards.JSchConnectionWizard; import org.eclipse.remote.ui.AbstractRemoteUIConnectionManager; import org.eclipse.remote.ui.IRemoteUIConnectionWizard; -import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; -import com.jcraft.jsch.JSch; -import com.jcraft.jsch.JSchException; - public class JSchUIConnectionManager extends AbstractRemoteUIConnectionManager { - private class RemoteAuthenticator implements IUserAuthenticator { - UserInfoPrompter prompter; - - public RemoteAuthenticator(IRemoteConnection conn) { - try { - prompter = new UserInfoPrompter(new JSch().getSession(conn.getUsername(), conn.getAddress())); - } catch (JSchException e) { - // Not allowed - } - } - - @Override - public PasswordAuthentication prompt(String username, String message) { - if (prompter.promptPassword(message)) { - PasswordAuthentication auth = new PasswordAuthentication(username, prompter.getPassword().toCharArray()); - return auth; - } - return null; - } - - @Override - public String[] prompt(String destination, String name, String message, String[] prompt, boolean[] echo) { - return prompter.promptKeyboardInteractive(destination, name, message, prompt, echo); - } - - @Override - public int prompt(final int promptType, final String title, final String message, final int[] promptResponses, - final int defaultResponseIndex) { - final Display display = getDisplay(); - final int[] retval = new int[1]; - final String[] buttons = new String[promptResponses.length]; - for (int i = 0; i < promptResponses.length; i++) { - int prompt = promptResponses[i]; - switch (prompt) { - case IDialogConstants.OK_ID: - buttons[i] = IDialogConstants.OK_LABEL; - break; - case IDialogConstants.CANCEL_ID: - buttons[i] = IDialogConstants.CANCEL_LABEL; - break; - case IDialogConstants.NO_ID: - buttons[i] = IDialogConstants.NO_LABEL; - break; - case IDialogConstants.YES_ID: - buttons[i] = IDialogConstants.YES_LABEL; - break; - } - } - - display.syncExec(new Runnable() { - @Override - public void run() { - final MessageDialog dialog = new MessageDialog(new Shell(display), title, null /* title image */, message, - promptType, buttons, defaultResponseIndex); - retval[0] = dialog.open(); - } - }); - return promptResponses[retval[0]]; - } - } - - private Display getDisplay() { - Display display = Display.getCurrent(); - if (display == null) { - display = Display.getDefault(); - } - return display; - } - private final JSchConnectionManager fConnMgr; public JSchUIConnectionManager(IRemoteServices services) { @@ -131,7 +53,7 @@ public class JSchUIConnectionManager extends AbstractRemoteUIConnectionManager { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { - connection.open(new RemoteAuthenticator(connection), monitor); + connection.open(monitor); } catch (RemoteConnectionException e) { throw new InvocationTargetException(e); } diff --git a/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/JSchUserAuthenticator.java b/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/JSchUserAuthenticator.java new file mode 100644 index 00000000000..e073fa74017 --- /dev/null +++ b/bundles/org.eclipse.remote.jsch.ui/src/org/eclipse/remote/internal/jsch/ui/JSchUserAuthenticator.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corporation and others. + * 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: + * IBM Corporation - Initial API and implementation + *******************************************************************************/ +package org.eclipse.remote.internal.jsch.ui; + +import java.net.PasswordAuthentication; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jsch.ui.UserInfoPrompter; +import org.eclipse.remote.core.IRemoteConnection; +import org.eclipse.remote.core.IUserAuthenticator; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; + +public class JSchUserAuthenticator implements IUserAuthenticator { + private UserInfoPrompter prompter; + + public JSchUserAuthenticator(IRemoteConnection conn) { + try { + prompter = new UserInfoPrompter(new JSch().getSession(conn.getUsername(), conn.getAddress())); + } catch (JSchException e) { + // Not allowed + } + } + + @Override + public PasswordAuthentication prompt(String username, String message) { + if (prompter.promptPassword(message)) { + PasswordAuthentication auth = new PasswordAuthentication(username, prompter.getPassword().toCharArray()); + return auth; + } + return null; + } + + @Override + public String[] prompt(String destination, String name, String message, String[] prompt, boolean[] echo) { + return prompter.promptKeyboardInteractive(destination, name, message, prompt, echo); + } + + @Override + public int prompt(final int promptType, final String title, final String message, final int[] promptResponses, + final int defaultResponseIndex) { + final Display display = getDisplay(); + final int[] retval = new int[1]; + final String[] buttons = new String[promptResponses.length]; + for (int i = 0; i < promptResponses.length; i++) { + int prompt = promptResponses[i]; + switch (prompt) { + case IDialogConstants.OK_ID: + buttons[i] = IDialogConstants.OK_LABEL; + break; + case IDialogConstants.CANCEL_ID: + buttons[i] = IDialogConstants.CANCEL_LABEL; + break; + case IDialogConstants.NO_ID: + buttons[i] = IDialogConstants.NO_LABEL; + break; + case IDialogConstants.YES_ID: + buttons[i] = IDialogConstants.YES_LABEL; + break; + } + } + + display.syncExec(new Runnable() { + @Override + public void run() { + final MessageDialog dialog = new MessageDialog(new Shell(display), title, null /* title image */, message, + promptType, buttons, defaultResponseIndex); + retval[0] = dialog.open(); + } + }); + return promptResponses[retval[0]]; + } + + private Display getDisplay() { + Display display = Display.getCurrent(); + if (display == null) { + display = Display.getDefault(); + } + return display; + } +}