/*******************************************************************************
* Copyright (c) 2013, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.team.build.internal.hjplugin.rtc;
import java.io.File;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.ibm.team.build.client.ClientFactory;
import com.ibm.team.build.client.ITeamBuildClient;
import com.ibm.team.build.client.ITeamBuildRequestClient;
import com.ibm.team.build.internal.PasswordHelper;
import com.ibm.team.build.internal.scm.RepositoryManager;
import com.ibm.team.build.internal.scm.RepositoryManager.IConsole;
import com.ibm.team.repository.client.ITeamRepository;
import com.ibm.team.repository.client.TeamPlatform;
import com.ibm.team.repository.common.TeamRepositoryException;
/**
* Build client implementation. Main entrypoint for access to Build and SCM client library APIs.
*/
public class BuildClient extends AbstractBuildClient {
private static final Logger LOGGER = Logger.getLogger(BuildClient.class.getName());
static {
TeamPlatform.startup();
}
private final Map<String, RepositoryConnection> fRepositoryConnections = new HashMap<String, RepositoryConnection>();
@Override
public ConnectionDetails getConnectionDetails(String repositoryAddress,
String userId, String password, int timeout) {
return new ConnectionDetails(repositoryAddress, userId, password, timeout);
}
@Override
public String determinePassword(File passwordFile, Locale clientLocale)
throws Exception {
String passwordToUse = getPasswordFromFile(passwordFile, clientLocale);
if (passwordToUse == null || passwordToUse.length() == 0) {
LOGGER.finer("No password determined because password determined is " //$NON-NLS-1$
+ (passwordToUse == null ? "null" : "empty")); //$NON-NLS-1$ //$NON-NLS-2$
throw new RTCConfigurationException(Messages.get(clientLocale).BuildClient_no_password());
}
return passwordToUse;
}
/**
* Get the password as provided by the passwordFile
*/
private String getPasswordFromFile(File passwordFile, Locale clientLocale) throws Exception {
if (passwordFile != null) {
String decryptedPassword = null;
try {
decryptedPassword = PasswordHelper.getPassword(passwordFile);
} catch (Exception exception) {
LOGGER.log(Level.FINER, "Problem reading password file " + passwordFile.getAbsolutePath(), exception);
throw new RTCConfigurationException(Messages.get(clientLocale).BuildClient_bad_password_file(passwordFile.getAbsolutePath()));
}
// An empty password text file returns an empty password string instead of throwing an exception
// See 255010: PasswordHelper.getPassword(passwordFile) returns empty string for invalid password file
if (decryptedPassword != null && decryptedPassword.length() == 0) {
throw new RTCConfigurationException(Messages.get(clientLocale).BuildClient_bad_password_file(passwordFile.getAbsolutePath()));
} else {
return decryptedPassword;
}
}
return null;
}
@Override
public synchronized RepositoryConnection getRepositoryConnection(ConnectionDetails connectionDetails) throws Exception {
RepositoryConnection connection = fRepositoryConnections.get(connectionDetails.getHashKey());
// remove connection if password has changed
if (connection != null && !connection.getConnectionDetails().getPassword().equals(connectionDetails.getPassword())) {
removeRepositoryConnection(connectionDetails);
connection = null;
}
// create new connection
if (connection == null) {
connection = createRepositoryConnection(connectionDetails);
fRepositoryConnections.put(connectionDetails.getHashKey(), connection);
LOGGER.finer("Added connection " + connectionDetails.getHashKey()); //$NON-NLS-1$
for (String connectionHashKey : fRepositoryConnections.keySet()) {
LOGGER.finer("Stored connection " + connectionHashKey); //$NON-NLS-1$
}
}
return connection;
}
@Override
public RepositoryConnection createRepositoryConnection(ConnectionDetails connectionDetails) throws TeamRepositoryException {
RepositoryManager repoMgr = createRepositoryManager(connectionDetails);
ITeamRepository repo = repoMgr.getRepository(connectionDetails.getRepositoryAddress(), true);
repo.setConnectionTimeout(connectionDetails.getTimeout());
RepositoryConnection connection = new RepositoryConnection(this, connectionDetails, repoMgr, repo);
return connection;
}
@Override
public synchronized RepositoryConnection removeRepositoryConnection(ConnectionDetails connectionDetails) {
RepositoryConnection repositoryConnection = fRepositoryConnections.get(connectionDetails.getHashKey());
// remove connection if password matches
if (repositoryConnection != null && repositoryConnection.getConnectionDetails().getPassword().equals(connectionDetails.getPassword())) {
fRepositoryConnections.remove(connectionDetails.getHashKey());
LOGGER.finer("Removed connection " + repositoryConnection.getConnectionDetails().getHashKey()); //$NON-NLS-1$
for (String connectionHashKey : fRepositoryConnections.keySet()) {
LOGGER.finer("Stored connection " + connectionHashKey); //$NON-NLS-1$
}
return repositoryConnection;
}
return null;
}
/**
* Creates the repository manager for the given connection details.
*
* @ShortOp
*/
private RepositoryManager createRepositoryManager(ConnectionDetails connectionDetails) throws TeamRepositoryException {
IConsole console = new IConsole() {
public void print(String message) {
LOGGER.finer(message);
}
};
return RepositoryManager.createForUsernameAndPassword(
connectionDetails.getRepositoryAddress(),
connectionDetails.getUserId(), connectionDetails.getPassword(),
console);
}
private ITeamBuildClient getBuildClient(ITeamRepository repo) {
return ClientFactory.getTeamBuildClient(repo);
}
private ITeamBuildRequestClient getBuildRequestClient(ITeamRepository repo) {
return ClientFactory.getTeamBuildRequestClient(repo);
}
}