blob: 016abb34d74a84b0cf3f1b9ee0ef0bbab636c7af [file] [log] [blame]
package org.eclipse.team.internal.ccvs.core.connection;
/*
* (c) Copyright IBM Corp. 2000, 2002.
* All Rights Reserved.
*/
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
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.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.core.runtime.Status;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ccvs.core.CVSException;
import org.eclipse.team.internal.ccvs.core.CVSProvider;
import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
import org.eclipse.team.internal.ccvs.core.CVSStatus;
import org.eclipse.team.internal.ccvs.core.CVSTag;
import org.eclipse.team.internal.ccvs.core.ICVSFolder;
import org.eclipse.team.internal.ccvs.core.ICVSRemoteFolder;
import org.eclipse.team.internal.ccvs.core.ICVSRemoteResource;
import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation;
import org.eclipse.team.internal.ccvs.core.ICVSRunnable;
import org.eclipse.team.internal.ccvs.core.IConnectionMethod;
import org.eclipse.team.internal.ccvs.core.IUserAuthenticator;
import org.eclipse.team.internal.ccvs.core.IUserInfo;
import org.eclipse.team.internal.ccvs.core.Policy;
import org.eclipse.team.internal.ccvs.core.client.Command;
import org.eclipse.team.internal.ccvs.core.client.Session;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.resources.RemoteFolder;
import org.eclipse.team.internal.ccvs.core.resources.RemoteModule;
/**
* This class manages a CVS repository location.
*
* It provides the mapping between connection method name and the
* plugged in ICunnectionMethod.
*
* It parses location strings into instances.
*
* It provides a method to open a connection to the server along
* with a method to validate that connections can be made.
*
* It manages its user info using the plugged in IUserAuthenticator
* (unless a username and password are provided as part of the creation
* string, in which case, no authenticator is used).
*
* Instances must be disposed of when no longer needed in order to
* notify the authenticator so cached properties can be cleared
*
*/
public class CVSRepositoryLocation extends PlatformObject implements ICVSRepositoryLocation, IUserInfo {
// server platform constants
public static final int UNDETERMINED_PLATFORM = 0;
public static final int CVS_SERVER = 1;
public static final int CVSNT_SERVER = 2;
public static final int UNSUPPORTED_SERVER = 3;
public static final int UNKNOWN_SERVER = 4;
// static variables for extension points
private static IUserAuthenticator authenticator;
private static IConnectionMethod[] pluggedInConnectionMethods = null;
private IConnectionMethod method;
private String user;
private String password;
private String host;
private int port;
private String root;
private boolean userFixed;
private boolean passwordFixed;
private int serverPlatform = UNDETERMINED_PLATFORM;
public static final char COLON = ':';
public static final char HOST_SEPARATOR = '@';
public static final char PORT_SEPARATOR = '#';
public static final boolean STANDALONE_MODE = (System.getProperty("eclipse.cvs.standalone")==null) ? //$NON-NLS-1$
false :(new Boolean(System.getProperty("eclipse.cvs.standalone")).booleanValue()); //$NON-NLS-1$
// fields needed for caching the password
public static final String INFO_PASSWORD = "org.eclipse.team.cvs.core.password";//$NON-NLS-1$
public static final String INFO_USERNAME = "org.eclipse.team.cvs.core.username";//$NON-NLS-1$
public static final String AUTH_SCHEME = "";//$NON-NLS-1$
public static final URL FAKE_URL;
static {
URL temp = null;
try {
temp = new URL("http://org.eclipse.team.cvs.core");//$NON-NLS-1$
} catch (MalformedURLException e) {
}
FAKE_URL = temp;
}
/*
* Create a CVSRepositoryLocation from its composite parts.
*/
private CVSRepositoryLocation(IConnectionMethod method, String user, String password, String host, int port, String root, boolean userFixed, boolean passwordFixed) {
this.method = method;
this.user = user;
this.password = password;
this.host = host;
this.port = port;
this.root = root;
// The username can be fixed only if one is provided
if (userFixed && (user != null))
this.userFixed = true;
// The password can only be fixed if the username is and a password is provided
if (userFixed && passwordFixed && (password != null))
this.passwordFixed = true;
}
/*
* Create the connection to the remote server.
* If anything fails, an exception will be thrown and must
* be handled by the caller.
*/
private Connection createConnection(String password, IProgressMonitor monitor) throws CVSException {
// FIXME Should the open() of Connection be done in the constructor?
// The only reason it should is if connections can be reused (they aren't reused now).
// FIXME! monitor is unused
Connection connection = new Connection(this, method.createConnection(this, password));
connection.open(monitor);
return connection;
}
/*
* Dispose of the receiver by clearing any cached authorization information.
* This method shold only be invoked when the corresponding adapter is shut
* down or a connection is being validated.
*/
public void dispose() throws CVSException {
flushCache();
}
/*
* Flush the keyring entry associated with the receiver
*/
private void flushCache() throws CVSException {
try {
Platform.flushAuthorizationInfo(FAKE_URL, getLocation(), AUTH_SCHEME);
} catch (CoreException e) {
// We should probably wrap the CoreException here!
CVSProviderPlugin.log(e.getStatus());
throw new CVSException(IStatus.ERROR, IStatus.ERROR, Policy.bind("CVSRepositoryLocation.errorFlushing", getLocation()), e);//$NON-NLS-1$
}
}
/*
* @see ICVSRepositoryLocation#getHost()
*/
public String getHost() {
return host;
}
/*
* @see IRepositoryLocation#getLocation()
*
* The username is included if it is fixed.
* The password is never included even if it is fixed.
* The port is included if it is not the default port.
*/
public String getLocation() {
return COLON + method.getName() + COLON +
(userFixed?(user +
(passwordFixed?(COLON + password):"")//$NON-NLS-1$
+ HOST_SEPARATOR):"") +//$NON-NLS-1$
host +
((port == USE_DEFAULT_PORT)?"":(PORT_SEPARATOR + new Integer(port).toString())) +//$NON-NLS-1$
COLON + root;
}
/*
* @see ICVSRepositoryLocation#getMethod()
*/
public IConnectionMethod getMethod() {
return method;
}
public boolean setMethod(String methodName) {
IConnectionMethod newMethod = getPluggedInConnectionMethod(methodName);
if (newMethod == null)
return false;
method = newMethod;
return true;
}
/*
* @see ICVSRepositoryLocation#getPort()
*/
public int getPort() {
return port;
}
/*
* @see ICVSRepositoryLocation#members(CVSTag, boolean, IProgressMonitor)
*/
public ICVSRemoteResource[] members(CVSTag tag, boolean modules, IProgressMonitor progress) throws CVSException {
try {
if (modules) {
return RemoteModule.getRemoteModules(this, tag, progress);
} else {
RemoteFolder root = new RemoteFolder(null, this, Path.EMPTY, tag);
ICVSRemoteResource[] resources = (ICVSRemoteResource[])root.members(progress);
// There is the off chance that there is a file in the root of the repository.
// This is not supported by cvs so we need to make sure there are no files
List folders = new ArrayList(resources.length);
for (int i = 0; i < resources.length; i++) {
ICVSRemoteResource remoteResource = resources[i];
if (remoteResource.isContainer()) {
folders.add(remoteResource);
}
}
return (ICVSRemoteResource[]) folders.toArray(new ICVSRemoteResource[folders.size()]);
}
} catch(TeamException e) {
throw new CVSException(e.getStatus());
}
}
/*
* @see ICVSRepositoryLocation#getRemoteFolder(String, CVSTag)
*/
public ICVSRemoteFolder getRemoteFolder(String remotePath, CVSTag tag) {
return new RemoteFolder(null, this, new Path(remotePath), tag);
}
/*
* @see ICVSRepositoryLocation#getRootDirectory()
*/
public String getRootDirectory() {
return root;
}
/*
* @see ICVSRepositoryLocation#getTimeout()
*
* For the time being, the timeout value is a system wide value
* associated with the CVSPlugin singleton.
*/
public int getTimeout() {
return CVSProviderPlugin.getPlugin().getTimeout();
}
/*
* @see ICVSRepositoryLocation#getUserInfo()
*/
public IUserInfo getUserInfo(boolean makeUsernameMutable) {
return new UserInfo(user, password, makeUsernameMutable ? true : isUsernameMutable());
}
/*
* @see ICVSRepositoryLocation#getUsername()
* @see IUserInfo#getUsername()
*/
public String getUsername() {
// If the username is mutable, get it from the cache if it's there
if (user == null && isUsernameMutable()) {
try {
retrievePassword();
} catch (CVSException e) {
}
}
return user == null ? "" : user;
}
/*
* @see IUserInfo#isUsernameMutable()
*/
public boolean isUsernameMutable() {
return !userFixed;
}
/*
* Open a connection to the repository represented by the receiver.
* If the username or password are not fixed, openConnection will
* use the plugged-in authenticator to prompt for the username and/or
* password if one has not previously been provided or if the previously
* supplied username and password are invalid.
*/
public Connection openConnection(IProgressMonitor monitor) throws CVSException {
try {
// Allow two ticks in case of a retry
monitor.beginTask(Policy.bind("CVSRepositoryLocation.openingConnection", getLocation()), 2);//$NON-NLS-1$
// If we have a username and password, use them to attempt a connection
if ((user != null) && (password != null)) {
return createConnection(password, monitor);
}
// Get the repository in order to ensure that the location is known by CVS.
// (The get will record the location if it's not already recorded.
CVSProvider.getInstance().getRepository(getLocation());
while (true) {
try {
// The following will throw an exception if authentication fails
String password = retrievePassword();
if (user == null) {
// This is possible if the cache was cleared somehow for a location with a mutable username
throw new CVSAuthenticationException(new CVSStatus(CVSStatus.ERROR, Policy.bind("CVSRepositoryLocation.usernameRequired"))); //$NON-NLS-1$
}
if (password == null)
password = "";//$NON-NLS-1$
return createConnection(password, monitor);
} catch (CVSAuthenticationException ex) {
String message = ex.getMessage();
try {
IUserAuthenticator authenticator = getAuthenticator();
if (authenticator == null) {
throw new CVSAuthenticationException(getLocation(), Policy.bind("Client.noAuthenticator"));//$NON-NLS-1$
}
authenticator.promptForUserInfo(this, this, message);
updateCache();
} catch (OperationCanceledException e) {
throw new CVSAuthenticationException(new CVSStatus(CVSStatus.ERROR, message));
}
}
}
} finally {
monitor.done();
}
}
/*
* Implementation of inherited toString()
*/
public String toString() {
return getLocation();
}
public boolean equals(Object o) {
if (!(o instanceof CVSRepositoryLocation)) return false;
return getLocation().equals(((CVSRepositoryLocation)o).getLocation());
}
public int hashCode() {
return getLocation().hashCode();
}
/*
* Return the cached password from the keyring.
* Also, set the username of the receiver if the username is mutable
*/
private String retrievePassword() throws CVSException {
Map map = Platform.getAuthorizationInfo(FAKE_URL, getLocation(), AUTH_SCHEME);
if (map != null) {
String username = (String) map.get(INFO_USERNAME);
if (username != null && isUsernameMutable())
setUsername(username);
String password = (String) map.get(INFO_PASSWORD);
if (password != null) {
return password;
}
}
return null;
}
/*
* @see IUserInfo#setPassword(String)
*/
public void setPassword(String password) {
if (passwordFixed)
throw new UnsupportedOperationException();
this.password = password;
// XXX The cache needs to get the new password somehow but not before we are validated!
}
public void setUserInfo(IUserInfo userinfo) {
user = userinfo.getUsername();
password = ((UserInfo)userinfo).getPassword();
}
/*
* @see IUserInfo#setUsername(String)
*/
public void setUsername(String user) {
if (userFixed)
throw new UnsupportedOperationException();
this.user = user;
// XXX The cache needs to get the new username somehow but not before we are validated!
}
public void setUserMuteable(boolean muteable) {
userFixed = !muteable;
}
public void updateCache() throws CVSException {
if (passwordFixed)
return;
updateCache(user, password, true);
password = null;
// Ensure that the receiver is known by the CVS provider
CVSProvider.getInstance().getRepository(getLocation());
}
/*
* Cache the user info in the keyring
*/
private void updateCache(String username, String password, boolean createIfAbsent) throws CVSException {
// put the password into the Platform map
Map map = Platform.getAuthorizationInfo(FAKE_URL, getLocation(), AUTH_SCHEME);
if (map == null) {
if ( ! createIfAbsent) return;
map = new java.util.HashMap(10);
}
if (username != null)
map.put(INFO_USERNAME, username);
if (password != null)
map.put(INFO_PASSWORD, password);
try {
Platform.addAuthorizationInfo(FAKE_URL, getLocation(), AUTH_SCHEME, map);
} catch (CoreException e) {
// We should probably wrap the CoreException here!
CVSProviderPlugin.log(e.getStatus());
throw new CVSException(IStatus.ERROR, IStatus.ERROR, Policy.bind("CVSRepositoryLocation.errorCaching", getLocation()), e);//$NON-NLS-1$
}
}
/*
* Validate that the receiver contains valid information for
* making a connection. If the receiver contains valid
* information, the method returns. Otherwise, an exception
* indicating the problem is throw.
*/
public void validateConnection(IProgressMonitor monitor) throws CVSException {
try {
ICVSFolder root = CVSWorkspaceRoot.getCVSFolderFor(ResourcesPlugin.getWorkspace().getRoot());
Session.run(this, root, false, new ICVSRunnable() {
public void run(IProgressMonitor monitor) throws CVSException {
IStatus status = Command.VERSION.execute(null, CVSRepositoryLocation.this, monitor);
// Log any non-ok status
if (! status.isOK()) {
if (status.isMultiStatus()) {
IStatus[] children = status.getChildren();
for (int i = 0; i < children.length; i++) {
CVSProviderPlugin.log(children[i]);
}
} else {
CVSProviderPlugin.log(status);
}
}
}
}, monitor);
} catch (CVSException e) {
// If the validation failed, dispose of any cached info
dispose();
throw e;
}
}
/**
* Return the server platform type. It will be one of the following:
* UNDETERMINED_PLATFORM: The platform has not been determined
* CVS_SERVER: The platform is regular CVS server
* CVSNT_SERVER: The platform in CVSNT
* If UNDETERMINED_PLATFORM is returned, the platform can be determined
* using the Command.VERSION command.
*/
public int getServerPlatform() {
return serverPlatform;
}
/**
* This method is called from Command.VERSION to set the platform type.
*/
public void setServerPlaform(IStatus status) {
// OK means that its a regular cvs server
if (status.isOK()) {
serverPlatform = CVS_SERVER;
return;
}
// Find the status that reports the CVS platform
if (status.isMultiStatus()) {
IStatus[] children = status.getChildren();
for (int i = 0; i < children.length; i++) {
IStatus iStatus = children[i];
if (iStatus.getCode() == CVSStatus.SERVER_IS_CVSNT
|| iStatus.getCode() == CVSStatus.UNSUPPORTED_SERVER_VERSION
|| iStatus.getCode() == CVSStatus.SERVER_IS_UNKNOWN) {
status = iStatus;
break;
}
}
}
// Second, check the code of the status itself to see if it is NT
switch (status.getCode()) {
case CVSStatus.SERVER_IS_CVSNT:
serverPlatform = CVSNT_SERVER;
break;
case CVSStatus.UNSUPPORTED_SERVER_VERSION:
serverPlatform = UNSUPPORTED_SERVER;
break;
case CVSStatus.SERVER_IS_UNKNOWN:
serverPlatform = UNKNOWN_SERVER;
break;
default:
// We had an error status with no info about the server.
// Mark it as undetermined.
serverPlatform = UNDETERMINED_PLATFORM;
}
}
public static boolean validateConnectionMethod(String methodName) {
String[] methods = CVSProviderPlugin.getProvider().getSupportedConnectionMethods();
for (int i=0;i<methods.length;i++) {
if (methodName.equals(methods[i]))
return true;
}
return false;
}
/*
* Create a repository location instance from the given properties.
* The supported properties are:
*
* connection The connection method to be used
* user The username for the connection (optional)
* password The password used for the connection (optional)
* host The host where the repository resides
* port The port to connect to (optional)
* root The server directory where the repository is located
*/
public static CVSRepositoryLocation fromProperties(Properties configuration) throws CVSException {
// We build a string to allow validation of the components that are provided to us
String connection = configuration.getProperty("connection");//$NON-NLS-1$
if (connection == null)
connection = "pserver";//$NON-NLS-1$
IConnectionMethod method = getPluggedInConnectionMethod(connection);
if (method == null)
throw new CVSException(new Status(IStatus.ERROR, CVSProviderPlugin.ID, TeamException.UNABLE, Policy.bind("CVSRepositoryLocation.methods", new Object[] {getPluggedInConnectionMethodNames()}), null));//$NON-NLS-1$
String user = configuration.getProperty("user");//$NON-NLS-1$
if (user.length() == 0)
user = null;
String password = configuration.getProperty("password");//$NON-NLS-1$
if (user == null)
password = null;
String host = configuration.getProperty("host");//$NON-NLS-1$
if (host == null)
throw new CVSException(new Status(IStatus.ERROR, CVSProviderPlugin.ID, TeamException.UNABLE, Policy.bind("CVSRepositoryLocation.hostRequired"), null));//$NON-NLS-1$
String portString = configuration.getProperty("port");//$NON-NLS-1$
int port;
if (portString == null)
port = ICVSRepositoryLocation.USE_DEFAULT_PORT;
else
port = Integer.parseInt(portString);
String root = configuration.getProperty("root");//$NON-NLS-1$
if (root == null)
throw new CVSException(new Status(IStatus.ERROR, CVSProviderPlugin.ID, TeamException.UNABLE, Policy.bind("CVSRepositoryLocation.rootRequired"), null));//$NON-NLS-1$
root = root.replace('\\', '/');
return new CVSRepositoryLocation(method, user, password, host, port, root, user != null, false);
}
/*
* Parse a location string and return a CVSRepositoryLocation.
*
* On failure, the status of the exception will be a MultiStatus
* that includes the original parsing error and a general status
* displaying the passed location and proper form. This form is
* better for logging, etc.
*/
public static CVSRepositoryLocation fromString(String location) throws CVSException {
try {
return fromString(location, false);
} catch (CVSException e) {
// Parsing failed. Include a status that
// shows the passed location and the proper form
MultiStatus error = new MultiStatus(CVSProviderPlugin.ID, CVSStatus.ERROR, Policy.bind("CVSRepositoryLocation.invalidFormat", new Object[] {location}), null);//$NON-NLS-1$
error.merge(new CVSStatus(CVSStatus.ERROR, Policy.bind("CVSRepositoryLocation.locationForm")));//$NON-NLS-1$
error.merge(e.getStatus());
throw new CVSException(error);
}
}
/*
* Parse a location string and return a CVSRepositoryLocation.
*
* The valid format (from the cederqvist) is:
*
* :method:[[user][:password]@]hostname[:[port]]/path/to/repository
*
* However, this does not work with CVS on NT so we use the format
*
* :method:[user[:password]@]hostname[#port]:/path/to/repository
*
* Some differences to note:
* The : after the host/port is not optional because of NT naming including device
* e.g. :pserver:username:password@hostname#port:D:\cvsroot
*
* If validateOnly is true, this method will always throw an exception.
* The status of the exception indicates success or failure. The status
* of the exception contains a specific message suitable for displaying
* to a user who has knowledge of the provided location string.
* @see CVSRepositoryLocation.fromString(String)
*/
public static CVSRepositoryLocation fromString(String location, boolean validateOnly) throws CVSException {
String partId = null;
try {
// Get the connection method
partId = "CVSRepositoryLocation.parsingMethod";//$NON-NLS-1$
int start = location.indexOf(COLON);
if (start != 0)
throw new CVSException(Policy.bind("CVSRepositoryLocation.startOfLocation"));//$NON-NLS-1$
int end = location.indexOf(COLON, start + 1);
String methodName = location.substring(start + 1, end);
IConnectionMethod method = getPluggedInConnectionMethod(methodName);
if (method == null)
throw new CVSException(new CVSStatus(CVSStatus.ERROR, Policy.bind("CVSRepositoryLocation.methods", new Object[] {getPluggedInConnectionMethodNames()})));//$NON-NLS-1$
// Get the user name and password (if provided)
partId = "CVSRepositoryLocation.parsingUser";//$NON-NLS-1$
start = end + 1;
end = location.indexOf(HOST_SEPARATOR, start);
String user = null;;
String password = null;
// if end is -1 then there is no host separator meaning that the username is not present
if (end != -1) {
// Get the optional user and password
user = location.substring(start, end);
// Separate the user and password (if there is a password)
start = user.indexOf(COLON);
if (start != -1) {
partId = "CVSRepositoryLocation.parsingPassword";//$NON-NLS-1$
password = user.substring(start+1);
user = user.substring(0, start);
}
// Set start to point after the host separator
start = end + 1;
}
// Get the host (and port)
partId = "CVSRepositoryLocation.parsingHost";//$NON-NLS-1$
end= location.indexOf(COLON, start);
String host = location.substring(start, end);
int port = USE_DEFAULT_PORT;
// Separate the port and host if there is a port
start = host.indexOf(PORT_SEPARATOR);
if (start != -1) {
partId = "CVSRepositoryLocation.parsingPort";//$NON-NLS-1$
port = Integer.parseInt(host.substring(start+1));
host = host.substring(0, start);
}
// Get the repository path (translating backslashes to slashes)
partId = "CVSRepositoryLocation.parsingRoot";//$NON-NLS-1$
start = end + 1;
String root = location.substring(start).replace('\\', '/');
if (validateOnly)
throw new CVSException(new CVSStatus(CVSStatus.OK, Policy.bind("ok")));//$NON-NLS-1$
return new CVSRepositoryLocation(method, user, password, host, port, root, (user != null), (password != null));
}
catch (IndexOutOfBoundsException e) {
// We'll get here if anything funny happened while extracting substrings
throw new CVSException(Policy.bind(partId));
}
catch (NumberFormatException e) {
// We'll get here if we couldn't parse a number
throw new CVSException(Policy.bind(partId));
}
}
public static IUserAuthenticator getAuthenticator() {
if (authenticator == null) {
authenticator = getPluggedInAuthenticator();
}
return authenticator;
}
/*
* Return the connection method registered for the given name or null if none
* are registered
*/
private static IConnectionMethod getPluggedInConnectionMethod(String methodName) {
IConnectionMethod[] methods = getPluggedInConnectionMethods();
for(int i=0; i<methods.length; i++) {
if(methodName.equals(methods[i].getName()))
return methods[i];
}
return null;
}
/*
* Return a string containing a list of all connection methods
*/
private static String getPluggedInConnectionMethodNames() {
IConnectionMethod[] methods = getPluggedInConnectionMethods();
StringBuffer methodNames = new StringBuffer();
for(int i=0; i<methods.length; i++) {
String name = methods[i].getName();
if (i>0)
methodNames.append(", ");//$NON-NLS-1$
methodNames.append(name);
}
return methodNames.toString();
}
public static IConnectionMethod[] getPluggedInConnectionMethods() {
if(pluggedInConnectionMethods==null) {
List connectionMethods = new ArrayList();
if (STANDALONE_MODE) {
connectionMethods.add(new PServerConnectionMethod());
} else {
IExtension[] extensions = Platform.getPluginRegistry().getExtensionPoint(CVSProviderPlugin.ID, CVSProviderPlugin.PT_CONNECTIONMETHODS).getExtensions();
for(int i=0; i<extensions.length; i++) {
IExtension extension = extensions[i];
IConfigurationElement[] configs = extension.getConfigurationElements();
if (configs.length == 0) {
CVSProviderPlugin.log(new Status(IStatus.ERROR, CVSProviderPlugin.ID, 0, Policy.bind("CVSProviderPlugin.execProblem"), null));//$NON-NLS-1$
continue;
}
try {
IConfigurationElement config = configs[0];
connectionMethods.add(config.createExecutableExtension("run"));//$NON-NLS-1$
} catch (CoreException ex) {
CVSProviderPlugin.log(new Status(IStatus.ERROR, CVSProviderPlugin.ID, 0, Policy.bind("CVSProviderPlugin.execProblem"), ex));//$NON-NLS-1$
}
}
}
pluggedInConnectionMethods = (IConnectionMethod[])connectionMethods.toArray(new IConnectionMethod[0]);
}
return pluggedInConnectionMethods;
}
private static IUserAuthenticator getPluggedInAuthenticator() {
IExtension[] extensions = Platform.getPluginRegistry().getExtensionPoint(CVSProviderPlugin.ID, CVSProviderPlugin.PT_AUTHENTICATOR).getExtensions();
if (extensions.length == 0)
return null;
IExtension extension = extensions[0];
IConfigurationElement[] configs = extension.getConfigurationElements();
if (configs.length == 0) {
CVSProviderPlugin.log(new Status(IStatus.ERROR, CVSProviderPlugin.ID, 0, Policy.bind("CVSAdapter.noConfigurationElement", new Object[] {extension.getUniqueIdentifier()}), null));//$NON-NLS-1$
return null;
}
try {
IConfigurationElement config = configs[0];
return (IUserAuthenticator) config.createExecutableExtension("run");//$NON-NLS-1$
} catch (CoreException ex) {
CVSProviderPlugin.log(new Status(IStatus.ERROR, CVSProviderPlugin.ID, 0, Policy.bind("CVSAdapter.unableToInstantiate", new Object[] {extension.getUniqueIdentifier()}), ex));//$NON-NLS-1$
return null;
}
}
/*
* Validate that the given string could ne used to succesfully create
* an instance of the receiver.
*
* This method performs some initial checks to provide displayable
* feedback and also tries a more in-depth parse using fromString(String, boolean).
*/
public static IStatus validate(String location) {
// Check some simple things that are not checked in creation
if (location == null)
return new CVSStatus(CVSStatus.ERROR, Policy.bind("CVSRepositoryLocation.nullLocation"));//$NON-NLS-1$
if (location.equals(""))//$NON-NLS-1$
return new CVSStatus(CVSStatus.ERROR, Policy.bind("CVSRepositoryLocation.emptyLocation"));//$NON-NLS-1$
if (location.endsWith(" ") || location.endsWith("\t"))//$NON-NLS-1$ //$NON-NLS-2$
return new CVSStatus(CVSStatus.ERROR, Policy.bind("CVSRepositoryLocation.endWhitespace"));//$NON-NLS-1$
if (!location.startsWith(":") || location.indexOf(COLON, 1) == -1)//$NON-NLS-1$
return new CVSStatus(CVSStatus.ERROR, Policy.bind("CVSRepositoryLocation.startOfLocation"));//$NON-NLS-1$
// Do some quick checks to provide geberal feedback
String formatError = Policy.bind("CVSRepositoryLocation.locationForm");//$NON-NLS-1$
int secondColon = location.indexOf(COLON, 1);
int at = location.indexOf(HOST_SEPARATOR);
if (at != -1) {
String user = location.substring(secondColon + 1, at);
if (user.equals(""))//$NON-NLS-1$
return new CVSStatus(CVSStatus.ERROR, formatError);
} else
at = secondColon;
int colon = location.indexOf(COLON, at + 1);
if (colon == -1)
return new CVSStatus(CVSStatus.ERROR, formatError);
String host = location.substring(at + 1, colon);
if (host.equals(""))//$NON-NLS-1$
return new CVSStatus(CVSStatus.ERROR, formatError);
String path = location.substring(colon + 1, location.length());
if (path.equals(""))//$NON-NLS-1$
return new CVSStatus(CVSStatus.ERROR, formatError);
// Do a full parse and see if it passes
try {
fromString(location, true);
} catch (CVSException e) {
// An exception is always throw. Return the status
return e.getStatus();
}
// Looks ok (we'll actually never get here because above
// fromString(String, boolean) will always throw an exception).
return new CVSStatus(IStatus.OK, Policy.bind("ok"));//$NON-NLS-1$
}
/**
* @see ICVSRepositoryLocation#flushUserInfo()
*/
public void flushUserInfo() throws CVSException {
flushCache();
}
}