1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 01:15:29 +02:00

Bug 428658 - Add a default Authenticator

Change-Id: I9e2e3ced3c1d3a0b9fb97e685d3836b586cc98a0
Signed-off-by: Greg Watson <g.watson@computer.org>
This commit is contained in:
Greg Watson 2014-06-07 00:07:26 -04:00
parent 79bf8fb436
commit dad71b863b
12 changed files with 328 additions and 126 deletions

View file

@ -4,6 +4,7 @@
<extension-point id="remoteServices" name="Remote Services" schema="schema/remoteServices.exsd"/>
<extension-point id="remoteResources" name="Remote Resources" schema="schema/remoteResources.exsd"/>
<extension-point id="processFactory" name="Process Factory" schema="schema/processFactory.exsd"/>
<extension-point id="authenticator" name="User Authenticator" schema="schema/authenticator.exsd"/>
<extension
point="org.eclipse.remote.core.remoteServices">
<remoteServices

View file

@ -0,0 +1,99 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.eclipse.remote.core" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appInfo>
<meta.schema plugin="org.eclipse.remote.core" id="authenticator" name="Authenticator"/>
</appInfo>
<documentation>
[Enter description of this extension point.]
</documentation>
</annotation>
<element name="extension">
<annotation>
<appInfo>
<meta.element />
</appInfo>
</annotation>
<complexType>
<sequence>
<element ref="authenticator"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
</complexType>
</element>
<element name="authenticator">
<complexType>
<attribute name="id" type="string" use="required">
<annotation>
<documentation>
The ID of the remote services that this authenticator should be used for.
</documentation>
</annotation>
</attribute>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>
An implementation of the IUserAuthenticator interface.
</documentation>
<appInfo>
<meta.attribute kind="java" basedOn=":org.eclipse.remote.core.IUserAuthenticator"/>
</appInfo>
</annotation>
</attribute>
<attribute name="priority" type="string">
<annotation>
<documentation>
The numerical value of the priority of the authenticator. The highest priority authenticator will be preferred over lower priority authenticators.
</documentation>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
[Enter the first release in which this extension point appears.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="examples"/>
</appInfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="apiInfo"/>
</appInfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="implementation"/>
</appInfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>
</schema>

View file

@ -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;
}
}

View file

@ -279,20 +279,6 @@ public interface IRemoteConnection extends Comparable<IRemoteConnection> {
*/
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.
*

View file

@ -53,6 +53,16 @@ public interface IRemoteConnectionManager {
*/
public List<IRemoteConnection> 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.

View file

@ -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)
*

View file

@ -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);
}

View file

@ -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));

View file

@ -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<String, JSchConnection> 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<IRemoteConnection> getConnections() {
loadConnections();
List<IRemoteConnection> conns = new ArrayList<IRemoteConnection>();
@ -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);

View file

@ -34,5 +34,13 @@
</description>
</transfer>
</extension>
<extension
point="org.eclipse.remote.core.authenticator">
<authenticator
class="org.eclipse.remote.internal.jsch.ui.JSchUserAuthenticator"
id="org.eclipse.remote.JSch"
priority="0">
</authenticator>
</extension>
</plugin>

View file

@ -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);
}

View file

@ -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;
}
}