/*******************************************************************************
 * Copyright (c) 2000, 2011 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.core.connection;

import java.io.IOException;
import java.util.*;

import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ILock;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.equinox.security.storage.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.*;
import org.eclipse.team.internal.ccvs.core.resources.*;
import org.eclipse.team.internal.ccvs.core.util.KnownRepositories;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;

/**
 * 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 {
	/**
	 * Top secure preferences node to cache CVS information
	 */
	static final private String cvsNameSegment = "/CVS/"; //$NON-NLS-1$
	
	/**
	 * Keys determining connection information for a given server
	 */
	static final private String PASSWORD_KEY = "password"; //$NON-NLS-1$
	static final private String USERNAME_KEY = "login"; //$NON-NLS-1$
	
	/**
	 * The name of the preferences node in the CVS preferences that contains
	 * the known repositories as its children.
	 */
	public static final String PREF_REPOSITORIES_NODE = "repositories"; //$NON-NLS-1$
	
	/*
	 * The name of the node in the default scope that has the default settings
	 * for a repository.
	 */
	private static final String DEFAULT_REPOSITORY_SETTINGS_NODE = "default_repository_settings"; //$NON-NLS-1$

	// Preference keys used to persist the state of the location
	public static final String PREF_LOCATION = "location"; //$NON-NLS-1$
	public static final String PREF_SERVER_ENCODING = "encoding"; //$NON-NLS-1$
	
	// 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;
	
	// Locks for ensuring that authentication to a host is serialized
	// so that invalid passwords do not result in account lockout
	private static Map<String, ILock> hostLocks = new HashMap<>(); 

	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 boolean allowCaching;
	
	private int serverPlatform = UNDETERMINED_PLATFORM;
	
	public static final char COLON = ':';
	public static final char SEMICOLON = ';';
	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	:(Boolean.valueOf(System.getProperty("eclipse.cvs.standalone")).booleanValue()); //$NON-NLS-1$ 
	
	// command to start remote cvs in server mode
	private static final String INVOKE_SVR_CMD = "server"; //$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$ 

	/*
	 * Fields used to create the EXT command invocation
	 */
	public static final String USER_VARIABLE = "{user}"; //$NON-NLS-1$
	public static final String PASSWORD_VARIABLE = "{password}"; //$NON-NLS-1$
	public static final String HOST_VARIABLE = "{host}"; //$NON-NLS-1$
	public static final String PORT_VARIABLE = "{port}"; //$NON-NLS-1$

	/*
	 * Field that indicates which connection method is to be used for 
	 * locations that use the EXT connection method.
	 */
	private static String extProxy;
	
	/*
	 * Field that indicates that the last connection attempt made to 
	 * this repository location failed due to an authentication failure. 
	 * When this is set, subsequent attempts should prompt before attempting to connect
	 */
	private boolean previousAuthenticationFailed = false;
	
	/**
	 * Return the preferences node whose child nodes are the know repositories
	 * @return a preferences node
	 */
	public static Preferences getParentPreferences() {
		return CVSProviderPlugin.getPlugin().getInstancePreferences().node(PREF_REPOSITORIES_NODE);
	}
	
	/**
	 * Return a preferences node that contains suitable defaults for a
	 * repository location.
	 * @return  a preferences node
	 */
	public static Preferences getDefaultPreferences() {
		Preferences defaults = DefaultScope.INSTANCE.getNode(CVSProviderPlugin.ID).node(DEFAULT_REPOSITORY_SETTINGS_NODE);
		defaults.put(PREF_SERVER_ENCODING, getDefaultEncoding());
		return defaults;
	}
	
	private static String getDefaultEncoding() {
		return System.getProperty("file.encoding", "UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
	}
	
	/**
	 * Set the proxy connection method that is to be used when a 
	 * repository location has the ext connection method. This is
	 * usefull with the extssh connection method as it can be used to 
	 * keep the sandbox compatible with the command line client.
	 * @param string
	 */
	public static void setExtConnectionMethodProxy(String string) {
		extProxy = string;
	}
	
	/**
	 * 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
	 *   encoding The file system encoding of the server
	 */
	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, NLS.bind(CVSMessages.CVSRepositoryLocation_methods, (new Object[] {getPluggedInConnectionMethodNames()})), null));// 
		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, CVSMessages.CVSRepositoryLocation_hostRequired, null));// 
		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, CVSMessages.CVSRepositoryLocation_rootRequired, null));// 

		String encoding = configuration.getProperty("encoding"); //$NON-NLS-1$
		
		return new CVSRepositoryLocation(method, user, password, host, port, root, encoding, 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, IStatus.ERROR, NLS.bind(CVSMessages.CVSRepositoryLocation_invalidFormat, (new Object[] {location})), null);// 
			error.merge(new CVSStatus(IStatus.ERROR, CVSMessages.CVSRepositoryLocation_locationForm));// 
			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
	 * 
	 * Also parse alternative format from WinCVS, which stores connection
	 * parameters such as username and hostname in method options:
	 *
	 * :method[;option=arg...]:other_connection_data
	 * 
	 * e.g. :pserver;username=anonymous;hostname=localhost:/path/to/repository
	 * 
	 * 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 errorMessage = null;
		try {
			// Get the connection method
			errorMessage = CVSMessages.CVSRepositoryLocation_parsingMethod;
			int start = location.indexOf(COLON);
			String methodName;
			int end;
			// For parsing alternative location format
			int optionStart = location.indexOf(SEMICOLON);
			HashMap<String, String> hmOptions = new HashMap<>();

			if (start == 0) {
				end = location.indexOf(COLON, start + 1);
				
				// Check for alternative location syntax
				if (optionStart != -1) {
					// errorMessage = CVSMessages.CVSRepositoryLocation_parsingMethodOptions;
					methodName = location.substring(start + 1, optionStart);
					// Save options in hash table
					StringTokenizer stOpt = new StringTokenizer(
						location.substring(optionStart+1, end),
								"=;" //$NON-NLS-1$
					);
					while (stOpt.hasMoreTokens()) {
						hmOptions.put(stOpt.nextToken(), stOpt.nextToken());
					}
					start = end + 1;
				} else {
					methodName = location.substring(start + 1, end);
					start = end + 1;
				}
			} else {
				// this could be an alternate format for ext: username:password@host:path
				methodName = "ext"; //$NON-NLS-1$
				start = 0;
			}
			
			IConnectionMethod method = getPluggedInConnectionMethod(methodName);
			if (method == null)
				throw new CVSException(new CVSStatus(IStatus.ERROR, NLS.bind(CVSMessages.CVSRepositoryLocation_methods, (new Object[] {getPluggedInConnectionMethodNames()}))));// 
			
			// Get the user name and password (if provided)
			errorMessage = CVSMessages.CVSRepositoryLocation_parsingUser;
			//Since there is a @ sign in the user name so use lastIndexOf to get to the host separator @
			end = location.lastIndexOf(HOST_SEPARATOR, location.length());
			String user = null;
			String password = null;
			// if end is -1 then there is no host separator meaning that the username is not present
			// or set in options of alternative-style location string
			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) {
					errorMessage = CVSMessages.CVSRepositoryLocation_parsingPassword;
					password = user.substring(start+1);
					user = user.substring(0, start);	
				}
				// Set start to point after the host separator
				start = end + 1;
			} else if (optionStart != -1) {
				// alternative location string data
				// errorMessage = CVSMessages.CVSRepositoryLocation_parsingOptionsUsername;
				if (hmOptions.containsKey("username")) user = hmOptions.get("username").toString(); //$NON-NLS-1$ //$NON-NLS-2$
				// errorMessage = CVSMessages.CVSRepositoryLocation_parsingOptionsPassword;
				if (hmOptions.containsKey("password")) password = hmOptions.get("password").toString(); //$NON-NLS-1$ //$NON-NLS-2$
			}
			
			// Get the host (and port)
			errorMessage = CVSMessages.CVSRepositoryLocation_parsingHost;
			end= location.indexOf(COLON, start);
			int hostEnd = end;
			if (end == -1) {
				// The last colon is optional so look for the slash that starts the path
				end = location.indexOf('/', start);
				hostEnd = end;
				// Decrement the end since the slash is part of the path
				if (end != -1) end--;
			}
			String host = (hmOptions.containsKey("hostname")) ? hmOptions.get("hostname").toString() : location.substring(start, hostEnd); //$NON-NLS-1$ //$NON-NLS-2$
			int port = USE_DEFAULT_PORT;
			boolean havePort = false;
			if (hmOptions.containsKey("port")) { //$NON-NLS-1$
				port = Integer.parseInt(hmOptions.get("port").toString()); //$NON-NLS-1$
				havePort = true;
			}
			// Separate the port and host if there is a port
			start = host.indexOf(PORT_SEPARATOR);
			if (start != -1) {
				try {
					// Initially, we used a # between the host and port
					errorMessage = CVSMessages.CVSRepositoryLocation_parsingPort;
					port = Integer.parseInt(host.substring(start+1));
					host = host.substring(0, start);
					havePort = true;
				} catch (NumberFormatException e) {
					// Ignore this as the #1234 port could be part of a proxy host string
				}
			}
			if (!havePort) {
				// In the correct CVS format, the port follows the COLON
				errorMessage = CVSMessages.CVSRepositoryLocation_parsingPort;
				int index = end;
				char c = location.charAt(++index);
				String portString = new String();
				while (Character.isDigit(c)) {
					portString += c;
					c = location.charAt(++index);
				}
				if (portString.length() > 0) {
					end = index - 1;
					port = Integer.parseInt(portString);
				}
			}
			
			// Get the repository path (translating backslashes to slashes)
			errorMessage = CVSMessages.CVSRepositoryLocation_parsingRoot;
			start = end + 1;
			String root = location.substring(start);
			
			if (validateOnly)
				throw new CVSException(new CVSStatus(IStatus.OK, CVSMessages.ok));// 		
			return new CVSRepositoryLocation(method, user, password, host, port, root, null /* encoding */, (user != null), (password != null));
		} catch (IndexOutOfBoundsException e) {
			// We'll get here if anything funny happened while extracting substrings
			IStatus status = new CVSStatus(IStatus.ERROR, errorMessage);
			throw new CVSException(status);
		} catch (NumberFormatException e) {
			IStatus status = new CVSStatus(IStatus.ERROR, errorMessage);
			// We'll get here if we couldn't parse a number
			throw new CVSException(status);
		}
	}
	
	/**
	 * Get the plugged-in user authenticator if there is one.
	 * @return the plugged-in user authenticator or <code>null</code>
	 */
	public static IUserAuthenticator getAuthenticator() {
		if (authenticator == null) {
			authenticator = getPluggedInAuthenticator();
		}
		return authenticator;
	}
	
	/**
	 * Return the sorted array of plugged-in connection methods.
	 * @return the sorted array of plugged-in connection methods
	 */
	public static IConnectionMethod[] getPluggedInConnectionMethods() {
		if(pluggedInConnectionMethods==null) {
			List<Object> connectionMethods = new ArrayList<Object>();
			
			if (STANDALONE_MODE) {				
				connectionMethods.add(new PServerConnectionMethod());
			} else {
				IExtension[] extensions = Platform.getExtensionRegistry().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(IStatus.ERROR, NLS.bind("Connection method {0} is missing required fields", new Object[] {extension.getUniqueIdentifier()}), null);//$NON-NLS-1$ 
						continue;
					}
					try {
						IConfigurationElement config = configs[0];
						connectionMethods.add(config.createExecutableExtension("run"));//$NON-NLS-1$ 
					} catch (CoreException ex) {
						CVSProviderPlugin.log(IStatus.ERROR, NLS.bind("Could not instantiate connection method for  {0}", new Object[] {extension.getUniqueIdentifier()}), ex);//$NON-NLS-1$ 
					}
				}
			}
			IConnectionMethod[] methods = connectionMethods.toArray(new IConnectionMethod[0]);
			Arrays.sort(methods, (cm1, cm2) -> cm1.getName().compareTo(cm2.getName()));
			pluggedInConnectionMethods = methods;
		}
		return pluggedInConnectionMethods;
	}
	
	/*
	 * Return the connection method registered for the given name 
	 * or <code>null</code> if none is registered with the given name.
	 */
	private static IConnectionMethod getPluggedInConnectionMethod(String methodName) {
		Assert.isNotNull(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
	 * that is suitable for inclusion in an error message.
	 */
	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();
	}
	
	/*
	 * Get the pluged-in authenticator from the plugin manifest.
	 */
	private static IUserAuthenticator getPluggedInAuthenticator() {
		IExtension[] extensions = Platform.getExtensionRegistry().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(IStatus.ERROR, NLS.bind("User autheticator {0} is missing required fields", (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(IStatus.ERROR, NLS.bind("Unable to instantiate user authenticator {0}", (new Object[] {extension.getUniqueIdentifier()})), ex);//$NON-NLS-1$ 
			return null;
		}
	}
	
	/*
	 * Create a CVSRepositoryLocation from its composite parts.
	 */
	private CVSRepositoryLocation(IConnectionMethod method, String user, String password, String host, int port, String root, String encoding, 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;
		if (encoding != null) {
			setEncoding(encoding);
		}
	}
	
	/*
	 * 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 {
		IConnectionMethod methodToUse = method;
		if (method.getName().equals("ext") && extProxy != null && !extProxy.equals(method.getName())) { //$NON-NLS-1$
			methodToUse = getPluggedInConnectionMethod(extProxy); 
		}
		Connection connection = new Connection(this, methodToUse.createConnection(this, password));
		connection.open(monitor);
		return connection;
	}
	
	/*
	 * Dispose of the receiver by clearing any cached authorization information.
	 * This method should only be invoked when the corresponding adapter is shut
	 * down or a connection is being validated.
	 */
	public void dispose() {
		removeNode();
		try {
			if (hasPreferences()) {
				internalGetPreferences().removeNode();
				getParentPreferences().flush();
			}
		} catch (BackingStoreException e) {
			CVSProviderPlugin.log(IStatus.ERROR, NLS.bind(CVSMessages.CVSRepositoryLocation_73, new String[] { getLocation(true) }), e); 
		}
	}
	
	/*
	 * Clear and flush the keyring entry associated with the receiver
	 */
	private void removeNode() {
		ISecurePreferences node = getCVSNode();
		if (node == null)
			return;
		try {
			node.clear();
			node.flush(); // save immediately
		} catch (IllegalStateException e) {
			CVSProviderPlugin.log(IStatus.ERROR, e.getMessage(), e);
		} catch (IOException e) {
			CVSProviderPlugin.log(IStatus.ERROR, e.getMessage(), e);
		}
	}
	
	/*
	 * @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 getLocation(false);
	}
	
	public String getLocation(boolean forDisplay) {
		return COLON + method.getName() + COLON + 
			(userFixed?(user +
				((passwordFixed && !forDisplay)?(COLON + password):"")//$NON-NLS-1$ 
					+ HOST_SEPARATOR):"") +//$NON-NLS-1$ 
			host + COLON +
			((port == USE_DEFAULT_PORT)?"":(Integer.valueOf(port).toString())) + //$NON-NLS-1$ 
			root;
	}
	
	@Override
	public IConnectionMethod getMethod() {
		return method;
	}

	@Override
	public int getPort() {
		return port;
	}
	
	@Override
	public String getEncoding() {
		if (hasPreferences()) {
			return internalGetPreferences().get(PREF_SERVER_ENCODING, getDefaultEncoding());
		} else {
			return getDefaultEncoding();
		}
	}

	@Override
	public void setEncoding(String encoding) {
		if (encoding == null || encoding == getDefaultEncoding()) {
			if (hasPreferences()) {
				internalGetPreferences().remove(PREF_SERVER_ENCODING);
			}
		} else {
			ensurePreferencesStored();
			internalGetPreferences().put(PREF_SERVER_ENCODING, encoding);
			flushPreferences();
		}
	}	

	@Override
	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, ICVSRemoteFolder.REPOSITORY_ROOT_FOLDER_NAME, tag);
				ICVSRemoteResource[] resources = 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<ICVSRemoteResource> folders = new ArrayList<ICVSRemoteResource>(resources.length);
				for (int i = 0; i < resources.length; i++) {
					ICVSRemoteResource remoteResource = resources[i];
					if (remoteResource.isContainer()) {
						folders.add(remoteResource);
					}
				}
				return folders.toArray(new ICVSRemoteResource[folders.size()]);
			}
		} catch (CVSException e){
			// keep current CVSException
			throw e;
		} catch(TeamException e1) {
			throw new CVSException(e1.getStatus());
		}
	}
	
	@Override
	public ICVSRemoteFolder getRemoteFolder(String remotePath, CVSTag tag) {
		return new RemoteFolder(null, this, remotePath, tag);		
	}
	
	@Override
	public ICVSRemoteFile getRemoteFile(String remotePath, CVSTag tag) {
		IPath path = new Path(null, remotePath);
		RemoteFolderTree remoteFolder = new RemoteFolderTree(null, this, path.removeLastSegments(1).toString(), tag);
		RemoteFile remoteFile = new RemoteFile(remoteFolder, Update.STATE_ADDED_LOCAL, path.lastSegment(), null, null, tag);
		remoteFolder.setChildren(new ICVSRemoteResource[] { remoteFile });
		return remoteFile;
	}
	
	@Override
	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();
	}
	
	@Override
	public IUserInfo getUserInfo(boolean makeUsernameMutable) {
		return new UserInfo(getUsername(), password, makeUsernameMutable ? true : isUsernameMutable());
	}
	
	@Override
	public String getUsername() {
		// If the username is mutable, get it from the cache if it's there
		if (user == null && isUsernameMutable()) {
			retrieveUsername();
		}
		return user == null ? "" : user; //$NON-NLS-1$
	}
	
	@Override
	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.
	 * 
	 * This method is synchronized to ensure that authentication with the 
	 * remote server is serialized. This is needed to avoid the situation where
	 * multiple failed authentications occur and result in the remote account
	 * being locked. The CVSProviderPlugin enforces that there is one instance
	 * of a CVSRepositoryLocation per remote location thus this method is called
	 * for any connection made to this remote location.
	 */
	public Connection openConnection(IProgressMonitor monitor) throws CVSException {
		// Get the lock for the host to ensure that we are not connecting to the same host concurrently.
		Policy.checkCanceled(monitor);
		ILock hostLock;
		synchronized(hostLocks) {
			hostLock = hostLocks.get(getHost());
			if (hostLock == null) {
				hostLock = Job.getJobManager().newLock();
				hostLocks.put(getHost(), hostLock);
			}
		}
		try {
			boolean acquired = false;
			int count = 0;
			int timeout = CVSProviderPlugin.getPlugin().getTimeout();
			while (!acquired) {
				try {
					acquired = hostLock.acquire(1000);
				} catch (InterruptedException e) {
					// Ignore
				}
				if (timeout > 0 && count > timeout) {
					throw new CVSCommunicationException(NLS.bind(CVSMessages.CVSRepositoryLocation_72, getHost()));
				}
				count++;
				Policy.checkCanceled(monitor);
			}
			// Allow two ticks in case of a retry
			monitor.beginTask(NLS.bind(CVSMessages.CVSRepositoryLocation_openingConnection, new String[] { getHost() }), 2);
			ensureLocationCached();
			boolean cacheNeedsUpdate = false;
			// If the previous connection failed, prompt before attempting to connect
			if (previousAuthenticationFailed) {
				promptForUserInfo(null);
				// The authentication information has been change so update the cache
				cacheNeedsUpdate = true;
			}
			while (true) {
				try {
					// The following will throw an exception if authentication fails
					String password = this.password;
					if (password == null) {
						// If the instance has no password, obtain it from the cache
						password = retrievePassword();
					}
					if (user == null) {
						// This is possible if the cache was cleared somehow for a location with a mutable username
						throw new CVSAuthenticationException(CVSMessages.CVSRepositoryLocation_usernameRequired, CVSAuthenticationException.RETRY, this, null); 
					}
					//if (password == null)
					//	password = "";//$NON-NLS-1$ 
					Connection connection = createConnection(password, monitor);
					if (cacheNeedsUpdate)
						updateCachedLocation();
					previousAuthenticationFailed = false;
					return connection;
				} catch (CVSAuthenticationException ex) {
					previousAuthenticationFailed = true;
					if (ex.getRetryStatus() == CVSAuthenticationException.RETRY) {
						String message = ex.getMessage();
						promptForUserInfo(message);
						// The authentication information has been change so update the cache
						cacheNeedsUpdate = true;
					} else {
						throw ex;
					}
				}
			}
		} finally {
			hostLock.release();
			monitor.done();
		}
	}

	/*
	 * Prompt for the user authentication information (i.e. user name and password).
	 */
	private void promptForUserInfo(String message) throws CVSException {
		IUserAuthenticator authenticator = getAuthenticator();
		if (authenticator == null) {
			throw new CVSAuthenticationException(CVSMessages.CVSRepositoryLocation_noAuthenticator, CVSAuthenticationException.NO_RETRY,this);// 
		}
		authenticator.promptForUserInfo(this, this, message);
	}

	/*
	 * Ensure that this location is in the known repositories list
	 * and that the authentication information matches what is in the
	 * cache, if this instance is not the instance in the cache.
	 */
	private void ensureLocationCached() {
		String location = getLocation();
		KnownRepositories repositories = KnownRepositories.getInstance();
		if (repositories.isKnownRepository(location)) {
			try {
				// The repository is already known.
				// Ensure that the authentication information of this 
				// location matches that of the known location
				setAuthenticationInformation((CVSRepositoryLocation)repositories.getRepository(location));
			} catch (CVSException e) {
				// Log the exception and continue
				CVSProviderPlugin.log(e);
			}
		} else {
			// The repository is not known so record it so any authentication
			// information the user may provide is remembered
			repositories.addRepository(this, true /* broadcast */);
		}
	}

	/*
	 * Set the authentication information of this instance such that it matches the
	 * provided instances.
	 */
	private void setAuthenticationInformation(CVSRepositoryLocation other) {
		if (other != this) {
			// The instances differ so copy from the other location to this one
			if (other.getUserInfoCached()) {
				// The user info is cached for the other instance
				// so null all the values in this instance so the 
				// information is obtained from the cache
				this.allowCaching = true;
				if (!userFixed) this.user = null;
				if (!passwordFixed) this.password = null;
			} else {
				// The user info is not cached for the other instance so
				// copy the authentication information into this instance
				setAllowCaching(false); /* this will clear any cached values */
				// Only copy the username and password if they are not fixed.
				// (If they are fixed, they would be included in the location
				// identifier and therefore must already match)
				if (!other.userFixed)
					this.user = other.user;
				if (!other.passwordFixed)
					this.password = other.password;
			}
		}
	}

	/*
	 * The connection was successfully made. Update the cached
	 * repository location if it is a different instance than
	 * this location.
	 */
	private void updateCachedLocation() {
		try {
			CVSRepositoryLocation known = (CVSRepositoryLocation)KnownRepositories.getInstance().getRepository(getLocation());
			known.setAuthenticationInformation(this);
		} catch (CVSException e) {
			// Log the exception and continue
			CVSProviderPlugin.log(e);
		}
	}
	
	/*
	 * Implementation of inherited toString()
	 */
	public String toString() {
		return getLocation(true);
	}
	
	public boolean equals(Object o) {
		if (this == o) return true;
		if (!(o instanceof CVSRepositoryLocation)) return false;
		return getLocation().equals(((CVSRepositoryLocation)o).getLocation());
	}
	public int hashCode() {
		return getLocation().hashCode();
	}
	
	/*
	 * Set the username of the receiver if the username is mutable. Return the
	 * username from the keyring if available.
	 */
	private String retrieveUsername() {
		ISecurePreferences node = getCVSNode();
		if (node == null)
			return null;
		try {
			String username = node.get(USERNAME_KEY, null);
			if (username != null && isUsernameMutable())
				setUsername(username);
			return username;
		} catch (StorageException e) { // most likely invalid keyring password or corrupted data
			CVSProviderPlugin.log(IStatus.ERROR, e.getMessage(), e);
		}
		return null;
	}
	
	/*
	 * Return the cached password from the keyring. 
	 * Also, set the username of the receiver if the username is mutable
	 */
	private String retrievePassword() {
		ISecurePreferences node = getCVSNode();
		if (node == null)
			return null;
		try {
			retrieveUsername();
			return node.get(PASSWORD_KEY, null);
		} catch (StorageException e) { // most likely invalid keyring password or corrupted data
			CVSProviderPlugin.log(IStatus.ERROR, e.getMessage(), e);
		}
		return null;
	}
	@Override
	public void setPassword(String password) {
		if (passwordFixed)
			throw new UnsupportedOperationException();
		// We set the password here but it will be cleared 
		// if the user info is cached using updateCache()
		this.password = password;
		// The password has been changed, reset the flag, so we won't 
		// prompt before attempting to connect
		previousAuthenticationFailed = false;
	}
	
	@Override
	public void setUsername(String user) {
		if (userFixed)
			throw new UnsupportedOperationException();
		this.user = user;
	}
	
	public void setUserMuteable(boolean muteable) {
		userFixed = !muteable;
	}
	
	public void setAllowCaching(boolean value) {
		allowCaching = value;
		if (allowCaching) {
			updateCache();
		} else {
			if (password == null)
				password = retrievePassword();
			removeNode();
		}
	}
	
	public void updateCache() {
		// Nothing to cache if the password is fixed
		if (passwordFixed || ! allowCaching) return;
		// Nothing to cache if the password is null and the user is fixed
		if (password == null && userFixed) return;
		if (updateCache(user, password)) {
			// If the cache was updated, null the password field
			// so we will obtain the password from the cache when needed
			password = null;
		}
		ensurePreferencesStored();
	}

	/*
	 * Cache the user info in the keyring. Return true if the operation
	 * succeeded and false otherwise. If an error occurs, it will be logged.
	 */
	private boolean updateCache(String username, String password) {
		ISecurePreferences node = getCVSNode();
		if (node == null)
			return false;
		try {
			node.put(USERNAME_KEY, username, false);
			node.put(PASSWORD_KEY, password, true);
			node.flush();
		} catch (StorageException e) {
			CVSProviderPlugin.log(IStatus.ERROR, e.getMessage(), e);
			return false;
		} catch (IOException e) {
			CVSProviderPlugin.log(IStatus.ERROR, e.getMessage(), e);
			return false;
		}
		return true;
	}
	
	/*
	 * 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 {
			monitor = Policy.monitorFor(monitor);
			monitor.beginTask(null, 100);
			ICVSFolder root = CVSWorkspaceRoot.getCVSFolderFor(ResourcesPlugin.getWorkspace().getRoot());
			Session session = new Session(this, root, false /* output to console */);
			session.open(Policy.subMonitorFor(monitor, 50), false /* read-only */);
			try {
				IStatus status = Command.VERSION.execute(session, this, Policy.subMonitorFor(monitor, 50));
				// Log any non-ok status
				if (! status.isOK()) {
					CVSProviderPlugin.log(status);
				}
			} finally {
				session.close();
				monitor.done();
			}
		} 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(int serverType) {
		// Second, check the code of the status itself to see if it is NT
		switch (serverType) {
			case CVS_SERVER:
			case CVSNT_SERVER:
			case UNKNOWN_SERVER:
			case UNSUPPORTED_SERVER:
				serverPlatform = serverType;
				break;
			default:
				// We had an error status with no info about the server.
				// Mark it as undetermined.
				serverPlatform = UNDETERMINED_PLATFORM;
		}
	}
	
	@Override
	public void flushUserInfo() {
		removeNode();
	}
	
	/*
	 * Return the command string that is to be used by the EXT connection method.
	 */
	String[] getExtCommand(String password) throws IOException {
		// Get the user specified connection parameters
		String CVS_RSH = CVSProviderPlugin.getPlugin().getCvsRshCommand();
		String CVS_RSH_PARAMETERS = CVSProviderPlugin.getPlugin().getCvsRshParameters();
		String CVS_SERVER = CVSProviderPlugin.getPlugin().getCvsServer();
		if(CVS_RSH == null || CVS_SERVER == null) {
			throw new IOException(CVSMessages.EXTServerConnection_varsNotSet); 
		}
		
		// If there is only one token, assume it is the command and use the default parameters and order
		if (CVS_RSH_PARAMETERS == null || CVS_RSH_PARAMETERS.length() == 0) {
			if (port != USE_DEFAULT_PORT)
				throw new IOException(CVSMessages.EXTServerConnection_invalidPort); 
			return new String[] {CVS_RSH, host, "-l", user, CVS_SERVER, INVOKE_SVR_CMD}; //$NON-NLS-1$
		}

		// Substitute any variables for their appropriate values
		CVS_RSH_PARAMETERS = stringReplace(CVS_RSH_PARAMETERS, USER_VARIABLE, user);
		CVS_RSH_PARAMETERS = stringReplace(CVS_RSH_PARAMETERS, PASSWORD_VARIABLE, password);
		CVS_RSH_PARAMETERS = stringReplace(CVS_RSH_PARAMETERS, HOST_VARIABLE, host);
		CVS_RSH_PARAMETERS = stringReplace(CVS_RSH_PARAMETERS, PORT_VARIABLE, Integer.valueOf(port).toString());

		// Build the command list to be sent to the OS.
		List<String> commands = new ArrayList<String>();
		commands.add(CVS_RSH);
		StringTokenizer tokenizer = new StringTokenizer(CVS_RSH_PARAMETERS);
		while (tokenizer.hasMoreTokens()) {
			String next = tokenizer.nextToken();
			commands.add(next);
		}
		commands.add(CVS_SERVER);
		commands.add(INVOKE_SVR_CMD);
		return commands.toArray(new String[commands.size()]);
	}

	/*
	 * Replace all occurrences of oldString with newString
	 */
	private String stringReplace(String string, String oldString, String newString) {
		int index = string.toLowerCase().indexOf(oldString);
		if (index == -1) return string;
		return stringReplace(
			string.substring(0, index) + newString + string.substring(index + oldString.length()),
			oldString, newString);
	}

	/**
	 * Return the server message with the prefix removed.
	 * Server aborted messages typically start with 
	 *    "cvs server: ..."
	 *    "cvs [server aborted]: ..."
	 *    "cvs rtag: ..."
	 */
	public String getServerMessageWithoutPrefix(String errorLine, String prefix) {
		String message = errorLine;
		int firstSpace = message.indexOf(' ');
		if(firstSpace != -1) {						
			// remove the program name and the space
			message = message.substring(firstSpace + 1);
			// Quick fix to handle changes in server message format (see Bug 45138)
			if (prefix.startsWith("[")) { //$NON-NLS-1$
				// This is the server aborted message
				// Remove the pattern "[command_name aborted]: "
				int closingBracket = message.indexOf("]: "); //$NON-NLS-1$
				if (closingBracket == -1) return null;
				// get what is inside the brackets
				String realPrefix = message.substring(1, closingBracket);
				// check that there is two words and the second word is "aborted"
				int space = realPrefix.indexOf(' ');
				if (space == -1) return null;
				if (realPrefix.indexOf(' ', space +1) != -1) return null;
				if (!realPrefix.substring(space +1).equals("aborted")) return null; //$NON-NLS-1$
				// It's a match, return the rest of the line
				message = message.substring(closingBracket + 2);
				if (message.charAt(0) == ' ') {
					message = message.substring(1);
				}
				return message;
			} else {
				// This is the server command message
				// Remove the pattern "command_name: "
				int colon = message.indexOf(": "); //$NON-NLS-1$
				if (colon == -1) return null;
				// get what is before the colon
				String realPrefix = message.substring(0, colon);
				// ensure that it is a single word
				if (realPrefix.indexOf(' ') != -1) return null;
				message = message.substring(colon + 1);
				if (message.charAt(0) == ' ') {
					message = message.substring(1);
				}
				return message;
			}
		}
		// This is not a server message with the desired prefix
		return null;
	}

	@Override
	public IUserAuthenticator getUserAuthenticator() {
		return getAuthenticator();
	}
	
	@Override
	public void setUserAuthenticator(IUserAuthenticator authenticator) {
		CVSRepositoryLocation.authenticator = authenticator;
	}
	
	/*
	 * Return the preferences node for this repository
	 */
	public Preferences getPreferences() {
		if (!hasPreferences()) {
			ensurePreferencesStored();
		}
		return internalGetPreferences();
	}
	
	private Preferences internalGetPreferences() {
		return getParentPreferences().node(getPreferenceName());
	}
	
	private boolean hasPreferences() {
		try {
			return getParentPreferences().nodeExists(getPreferenceName());
		} catch (BackingStoreException e) {
			CVSProviderPlugin.log(IStatus.ERROR, NLS.bind(CVSMessages.CVSRepositoryLocation_74, new String[] { getLocation(true) }), e); 
			return false;
		}
	}
	
	/**
	 * Return a unique name that identifies this location but
	 * does not contain any slashes (/). Also, do not use ':'.
	 * Although a valid path character, the initial core implementation
	 * didn't handle it well.
	 */
	private String getPreferenceName() {
		return getLocation().replace('/', '%').replace(':', '%');
	}

	public void storePreferences() {
		Preferences prefs = internalGetPreferences();
		// Must store at least one preference in the node
		prefs.put(PREF_LOCATION, getLocation());
		flushPreferences();
	}
	
	private void flushPreferences() {
		try {
			internalGetPreferences().flush();
		} catch (BackingStoreException e) {
			CVSProviderPlugin.log(IStatus.ERROR, NLS.bind(CVSMessages.CVSRepositoryLocation_75, new String[] { getLocation(true) }), e); 
		}
	}

	private void ensurePreferencesStored() {
		if (!hasPreferences()) {
			storePreferences();
		}
	}

	@Override
	public boolean getUserInfoCached() {
		ISecurePreferences node = getCVSNode();
		if (node == null)
			return false;
		try {
			String password = node.get(PASSWORD_KEY, null);
			return (password != null);
		} catch (StorageException e) { // most likely invalid keyring password or corrupted data
			CVSProviderPlugin.log(IStatus.ERROR, e.getMessage(), e);
		}
		return false;
	}

	/**
	 * At this time information is saved in a simplistic flat form. In future, this 
	 * can be modified into a hierarchy of storing information in "connections"
	 * where "connection" would combine "server" and "account" information (allowing
	 * user to have the same password for different connections on the server).
	 * 
	 * Hopefully, we'll get some simplified notion of "account" from Higgins into Equinox
	 * and then we'll be able to re-use it.
	 * 
	 * For now, the structure is rather simple:
	 * node: "CVS" 										"/CVS/"
	 * 		node: account_name							name combines all attributes
	 * 			| value: login
	 * 			| value: password
	 */
	private ISecurePreferences getCVSNode() {
		ISecurePreferences preferences = SecurePreferencesFactory.getDefault();
		if (preferences == null)
			return null;
		String accountName = EncodingUtils.encodeSlashes(getLocation(true));
		String path = cvsNameSegment + accountName;
		try {
			return preferences.node(path);
		} catch (IllegalArgumentException e) {
			return null; // invalid path
		}
	}
}
