201 lines
7.4 KiB
Java
201 lines
7.4 KiB
Java
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
|
// Use of this source code is governed by a MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package io.gitea.mylyn.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 io.gitea.*;
|
|
import io.gitea.auth.*;
|
|
import io.gitea.model.*;
|
|
import io.gitea.api.UserApi;
|
|
import io.gitea.mylyn.core.exceptions.GiteaException;
|
|
import io.gitea.mylyn.core.exceptions.GiteaExceptionHandler;
|
|
import io.gitea.mylyn.core.exceptions.UnknownRepositoryException;
|
|
|
|
/**
|
|
* The ConnectionManager is a singleton that handles all GiteaConnection
|
|
* instances in a HashMap. The key in this HashMap is the URL to the Gitea
|
|
* instance constructed using a TaskRepository class.
|
|
*/
|
|
public class ConnectionManager {
|
|
|
|
/**
|
|
* The HashMap used to store all GiteaConnections
|
|
*/
|
|
private static HashMap<String, GiteaConnection> connections = new HashMap<String, GiteaConnection>();
|
|
|
|
/**
|
|
* The pattern is used to verify a ULR to a valid Gitea repository URL. group 1
|
|
* -> server including protocol (without trailing '/') group 2 ->
|
|
* repository/project path excluding potential ".git"
|
|
*
|
|
* trick: for server we are locking for any character which is not / which is
|
|
* same as looking not greedy to all character until /
|
|
*
|
|
* example: https://forge.chapril.org/gitea/mylyn-gitea.git group 1 =>
|
|
* https//forge.chapril.org group 2 => gitea/mylyn-gitea
|
|
*/
|
|
private static Pattern URLPattern = Pattern.compile("(https?://(?:[^\\/]*))/((?:.*?)/(?:[^\\/]*?))(?:\\.git)?$");
|
|
|
|
/**
|
|
* Returns the GiteaConnection for the given task repository
|
|
*
|
|
* @param repository
|
|
* @return
|
|
* @throws GiteaException
|
|
*/
|
|
static public GiteaConnection get(TaskRepository repository) throws GiteaException {
|
|
return get(repository, false);
|
|
}
|
|
|
|
/**
|
|
* Returns the GiteaConnection for the given task repository. If it fails for
|
|
* whatever reason, it returns null.
|
|
*
|
|
* @param repository
|
|
* @return
|
|
*/
|
|
static public GiteaConnection getSafe(TaskRepository repository) {
|
|
try {
|
|
return get(repository);
|
|
} catch (GiteaException e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gitea connection configuration.
|
|
*/
|
|
static public ApiClient getConfiguration() {
|
|
return Configuration.getDefaultApiClient();
|
|
}
|
|
|
|
/**
|
|
* Constructs a "pseudo" URL string for the given task repository.
|
|
*
|
|
* @param repository
|
|
* @return
|
|
*/
|
|
private static String constructHash(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 GiteaConnection if the task
|
|
* repository is a valid repository.
|
|
*
|
|
* @param repository
|
|
* @return
|
|
* @throws GiteaException
|
|
*/
|
|
// FIXME: redesign to limit this function to validation but not configuration
|
|
static GiteaConnection validate(TaskRepository repository) throws GiteaException {
|
|
try {
|
|
String projectPath = null;
|
|
String host = null;
|
|
|
|
// Extract host&project path from valid url
|
|
if (repository.getProperty("giteaBaseUrl").trim().length() > 0) {
|
|
host = repository.getProperty("giteaBaseUrl").trim();
|
|
if (!repository.getUrl().startsWith(host)) {
|
|
throw new GiteaException("Invalid repository URL!");
|
|
}
|
|
|
|
projectPath = repository.getUrl().replaceFirst(Matcher.quoteReplacement(host), "");
|
|
if (projectPath.startsWith("/")) {
|
|
projectPath = projectPath.substring(1);
|
|
}
|
|
} else {
|
|
Matcher matcher = URLPattern.matcher(repository.getUrl());
|
|
if (!matcher.find()) {
|
|
throw new GiteaException("Invalid Project-URL!");
|
|
}
|
|
|
|
projectPath = matcher.group(2);
|
|
host = matcher.group(1);
|
|
}
|
|
|
|
// Configure credentials
|
|
String username = repository.getCredentials(AuthenticationType.REPOSITORY).getUserName();
|
|
String password = repository.getCredentials(AuthenticationType.REPOSITORY).getPassword();
|
|
|
|
ApiClient defaultClient = Configuration.getDefaultApiClient();
|
|
defaultClient.setBasePath(GiteaConnection.apiVersion.getBasePath(host));
|
|
|
|
if (repository.getProperty("usePrivateToken") != null
|
|
&& repository.getProperty("usePrivateToken").equals("true")) {
|
|
ApiKeyAuth accessToken = (ApiKeyAuth) defaultClient.getAuthentication("AccessToken");
|
|
accessToken.setApiKey(password); // token is stored in the password field.
|
|
|
|
} else {
|
|
HttpBasicAuth basicAuth = (HttpBasicAuth) defaultClient.getAuthentication("BasicAuth");
|
|
basicAuth.setUsername(username);
|
|
basicAuth.setPassword(password);
|
|
}
|
|
|
|
// Get user related repository list
|
|
UserApi userApi = new UserApi();
|
|
List<Repository> repositories = userApi.userCurrentListRepos(0, 0);
|
|
for (Repository p : repositories) {
|
|
if (p.getFullName().equals(projectPath)) {
|
|
GiteaConnection connection = new GiteaConnection(host, p, new GiteaAttributeMapper(repository));
|
|
return connection;
|
|
}
|
|
}
|
|
// At this point the authentication was successful, but the corresponding
|
|
// repository
|
|
// could not be found! which not not occurs with Gitea.
|
|
throw new UnknownRepositoryException(projectPath);
|
|
} catch (GiteaException e) {
|
|
throw e;
|
|
} catch (Exception e) {
|
|
throw GiteaExceptionHandler.handle(e);
|
|
} catch (Error e) {
|
|
throw GiteaExceptionHandler.handle(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a *valid* GiteaConnection, otherwise this method throws an exception.
|
|
*
|
|
* @param repository
|
|
* @param forceUpdate if true, a new GiteaConnection instance will be created,
|
|
* even if a Gitea Connection already exists for the given
|
|
* task repository
|
|
* @return connection
|
|
* @throws GiteaException
|
|
*/
|
|
static GiteaConnection get(TaskRepository repository, boolean forceUpdate) throws GiteaException {
|
|
try {
|
|
String hash = constructHash(repository);
|
|
if (connections.containsKey(hash) && !forceUpdate) {
|
|
return connections.get(hash);
|
|
} else {
|
|
GiteaConnection connection = validate(repository);
|
|
|
|
connections.put(hash, connection);
|
|
connection.update();
|
|
|
|
return connection;
|
|
}
|
|
} catch (GiteaException e) {
|
|
throw e;
|
|
} catch (Exception e) {
|
|
throw GiteaExceptionHandler.handle(e);
|
|
} catch (Error e) {
|
|
throw GiteaExceptionHandler.handle(e);
|
|
}
|
|
}
|
|
|
|
}
|