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