package de.weingardt.mylyn.gitlab.core;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.mylyn.commons.net.AuthenticationType;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.gitlab.api.GitlabAPI;
import org.gitlab.api.models.GitlabProject;
import org.gitlab.api.models.GitlabSession;
import de.weingardt.mylyn.gitlab.core.exceptions.GitlabException;
import de.weingardt.mylyn.gitlab.core.exceptions.GitlabExceptionHandler;
import de.weingardt.mylyn.gitlab.core.exceptions.UnknownProjectException;
/**
* The ConnectionManager is a singleton that handles all
* GitlabConnection instances in a HashMap. The key in this HashMap
* is the URL to the Gitlab instance constructed using a TaskRepository
* class.
* @author paul
*
*/
public class ConnectionManager {
/**
* The HashMap used to store all GitlabConnections
*/
private static HashMap<String, GitlabConnection> connections = new HashMap<String, GitlabConnection>();
/**
* The pattern is used to verify a ULR to a valid Gitlab project URL.
*/
private static Pattern URLPattern = Pattern.compile("((?:http|https)://(?:.*))/((?:[^\\/]*?)/(?:[^\\/]*?))$");
/**
* Returns the GitlabConnection for the given task repository
* @param repository
* @return
* @throws GitlabException
*/
static public GitlabConnection get(TaskRepository repository) throws GitlabException {
return get(repository, false);
}
/**
* Returns the GitlabConnection for the given task repository. If it
* failes for whatever reason, it returns null.
* @param repository
* @return
*/
static public GitlabConnection getSafe(TaskRepository repository) {
try {
return get(repository);
} catch (GitlabException e) {
return null;
}
}
/**
* Constructs a URL string for the given task repository.
* @param repository
* @return
*/
private static String constructURL(TaskRepository repository) {
String username = repository.getCredentials(AuthenticationType.REPOSITORY).getUserName();
String password = repository.getCredentials(AuthenticationType.REPOSITORY).getPassword();
return repository.getUrl() + "?username=" + username + "&password=" + password.hashCode();
}
/**
* Validates the given task repository and returns a GitlabConnection if
* the task repository is a valid repository.
* @param repository
* @return
* @throws GitlabException
*/
static GitlabConnection validate(TaskRepository repository) throws GitlabException {
try {
Matcher matcher = URLPattern.matcher(repository.getUrl());
if(!matcher.find()) {
throw new GitlabException("Invalid Project-URL!");
}
String projectPath = matcher.group(2);
String host = matcher.group(1);
String username = repository.getCredentials(AuthenticationType.REPOSITORY).getUserName();
String password= repository.getCredentials(AuthenticationType.REPOSITORY).getPassword();
GitlabSession session = null;
if(repository.getProperty("usePrivateToken") != null && repository.getProperty("usePrivateToken").equals("true")) {
session = GitlabAPI.connect(host, password).getCurrentSession();
} else {
session = GitlabAPI.connect(host, username, password);
}
GitlabAPI api = GitlabAPI.connect(host, session.getPrivateToken());
if(projectPath.endsWith(".git")) {
projectPath = projectPath.substring(0, projectPath.length() - 4);
}
List<GitlabProject> projects = api.getProjects();
for(GitlabProject p : projects) {
if(p.getPathWithNamespace().equals(projectPath)) {
GitlabConnection connection = new GitlabConnection(host, p, session,
new GitlabAttributeMapper(repository));
return connection;
}
}
// At this point the authentication was successful, but the corresponding project
// could not be found!
throw new UnknownProjectException(projectPath);
} catch(GitlabException e) {
throw e;
} catch(Exception e) {
throw GitlabExceptionHandler.handle(e);
} catch(Error e) {
throw GitlabExceptionHandler.handle(e);
}
}
/**
* Returns a *valid* GitlabConnection, otherwise this method throws an exception.
* @param repository
* @param forceUpdate if true, a new GitlabConnection instance will be created, even if a Gitlab
* Connection already exists for the given task repository
* @return
* @throws GitlabException
*/
static GitlabConnection get(TaskRepository repository, boolean forceUpdate) throws GitlabException {
try {
String hash = constructURL(repository);
if(connections.containsKey(hash) && !forceUpdate) {
return connections.get(hash);
} else {
GitlabConnection connection = validate(repository);
connections.put(hash, connection);
connection.update();
return connection;
}
} catch(GitlabException e) {
throw e;
} catch(Exception e) {
throw GitlabExceptionHandler.handle(e);
} catch(Error e) {
throw GitlabExceptionHandler.handle(e);
}
}
}