com.redhat.ceylon.common.config.Repositories Maven / Gradle / Ivy
package com.redhat.ceylon.common.config;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import com.redhat.ceylon.common.Constants;
import com.redhat.ceylon.common.FileUtil;
/**
* Repositories is a wrapper around a CeylonConfig object providing easy access to
* repository related configuration information.
*
* Ceylon uses a set of local and remote repositories for its modules.
* The order and significance of the lookup (which is fixed) is:
*
* system - Essential system modules
* cache - A cache of modules that were previously downloaded from remote repositories
* output - Where the compiler stores newly created modules
* lookup - User-defined local repositories
* global - Predefined non-remote repositories
* remote - User defined remote repositories
* other - Predefined remote repositories (like Herd)
*
* The "system" section by default contains a reference to the system global repository,
* which by default is +SYSTEM (see below). Do not override.
*
* The "cache" section is where modules downloaded from remote repositories are kept so they
* don't have to be downloaded each time. By default this is +CACHE (see below).
*
* The "output" section is where newly compiled modules are stored. By default this is "./modules".
*
* The "lookup" section is for modules local to the project and other user-defined
* repositories. By default this is +LOCAL (see below).
*
* The "global" section is meant for predefined, essential, non-remote repositories.
* By default this is +USER (see below). It's normally not advisable to override this.
*
* The "remote" section is meant for user-defined remote repositories. By default this is empty.
*
* The "other" section is meant for predefined, essential, remote repositories. By default
* this is +REMOTE (see below). It's normally not advisable to override this.
*
* The [repositories] section in a configuration file can be used to override the default
* values for those entries thereby changing or extending the lookup order. Take a look at
* the following example:
*
* [repositories]
* output=./output # Store new modules in the local `output` folder
* cache=/huge-disk/tom/ceylon/repocache # Store the cached modules on a bigger disk
* lookup=./modules
* lookup=./extra-modules
* lookup=/usr/local/ceylon/even-more-modules
* remote=http://ceylon.example.com # An external site with Ceylon modules
*
* First of all, the values for output and cache (as well as system, but you should normally
* never try overriding it) can only be specified once, while the others (lookup, global and
* remote) can be specified multiple times, Ceylon will try them one by one in the order you
* specify in this list.
*
* NB: When we say "in the order you specify" we refer to the ones with the same key name,
* so if you add several remote repositories they will be tried in the order you specify,
* but you cannot change the main ordering: lookup repositories will always be tried before
* global, which will always be tried before remote.
*
* The remote entry doesn't have any default value, so it can be easily used without having to
* worry about preexisting values. It's specifically meant to add extra (normally remote)
* repositories that will be tried after all other options have been exhausted.
*
* It's also possible to define single repositories in their own named sections. Either so
* you can easily refer to them by name or because you need to specify credentials in case
* of repositories that need authentication. For example:
*
* [repository "Test"]
* url=https://modules.ceylon-lang.org/repo/1
* user=john
* password=secret
*
* You can then refer to that from with the [repositories] section like this (see the + sign):
*
* [repositories]
* output=+Test
*
* Or from the command line:
*
* ceylon compile --out +Test com.example.helloworld
*
* There are several predefined repositories like this that have default values but that can
* be overridden by explicitly redefining them in the configuration file. These repositories are:
*
* SYSTEM - Which normally is something like "%CEYLONHOME%/repo". Do not override.
*
* LOCAL - By default this is "./modules".
*
* CACHE - By default this points to "%USER_HOME%/.ceylon/cache".
*
* USER - By default this is "%USER_HOME%/.ceylon/repo". It's normally not advisable to override this.
*
* REMOTE - By default this is points to the official Ceylon Herd repository. It's normally not advisable
* to override this.
*
* @author Tako Schotanus ([email protected])
*/
public class Repositories {
private CeylonConfig config;
private static final String SECTION_REPOSITORY = "repository";
private static final String SECTION_REPOSITORIES = "repositories";
public static final String REPO_TYPE_SYSTEM = "system";
public static final String REPO_TYPE_OUTPUT = "output";
public static final String REPO_TYPE_CACHE = "cache";
public static final String REPO_TYPE_LOCAL_LOOKUP = "lookup";
public static final String REPO_TYPE_GLOBAL_LOOKUP = "global";
public static final String REPO_TYPE_REMOTE_LOOKUP = "remote";
public static final String REPO_TYPE_OTHER_LOOKUP = "other";
private static final String REPO_NAME_SYSTEM = "SYSTEM";
private static final String REPO_NAME_LOCAL = "LOCAL";
private static final String REPO_NAME_CACHE = "CACHE";
private static final String REPO_NAME_USER = "USER";
private static final String REPO_NAME_REMOTE = "REMOTE";
private static final String REPO_NAME_MAVEN = "MAVEN";
private static final String ITEM_PASSWORD = "password";
private static final String ITEM_PASSWORD_KS = "password-keystore";
private static final String ITEM_PASSWORD_KS_ALIAS = "password-alias";
private static final String ITEM_USER = "user";
private static final String ITEM_URL = "url";
private static Repositories instance;
public static Repositories get() {
if (instance == null) {
instance = new Repositories();
}
return instance;
}
public static void set(Repositories repos) {
instance = repos;
}
public static Repositories withConfig(CeylonConfig config) {
return new Repositories(config);
}
public interface Repository {
public String getName();
public String getUrl();
public Credentials getCredentials();
}
public static class SimpleRepository implements Repository {
private final String name;
private final String url;
private final Credentials credentials;
public String getName() {
return name;
}
public String getUrl() {
return url;
}
public Credentials getCredentials() {
return credentials;
}
public SimpleRepository(String name, String url, Credentials credentials) {
this.name = name;
if (url.startsWith("~/") || url.startsWith("~\\")) {
url = new File(System.getProperty("user.home"), url.substring(2)).getPath();
}
this.url = url;
this.credentials = credentials;
}
}
public static class RepositoryRef implements Repository {
private final Repository ref;
public String getName() {
return ref.getName();
}
public String getUrl() {
return ref.getUrl();
}
public Credentials getCredentials() {
return ref.getCredentials();
}
public RepositoryRef(Repository ref) {
this.ref= ref;
}
}
private Repositories() {
this(CeylonConfig.get());
}
private Repositories(CeylonConfig config) {
this.config = config;
}
private String repoKey(String repoName, String itemName) {
return SECTION_REPOSITORY + "." + repoName + "." + itemName;
}
public Repository getRepository(String repoName) {
String url = config.getOption(repoKey(repoName, ITEM_URL));
if (url != null) {
String user = config.getOption(repoKey(repoName, ITEM_USER));
String password = config.getOption(repoKey(repoName, ITEM_PASSWORD));
final String alias = config.getOption(repoKey(repoName, ITEM_PASSWORD_KS_ALIAS));
String keystore = config.getOption(repoKey(repoName, ITEM_PASSWORD_KS));
String prompt = ConfigMessages.msg("repository.password.prompt", user, url);
Credentials credentials = Credentials.create(user, password, keystore, alias, prompt);
return new SimpleRepository(repoName, url, credentials);
} else {
if (REPO_NAME_SYSTEM.equals(repoName)) {
File dir = getSystemRepoDir();
if (dir != null) {
// $INSTALLDIR/repo
return new SimpleRepository(REPO_NAME_SYSTEM, dir.getAbsolutePath(), null);
}
} else if (REPO_NAME_LOCAL.equals(repoName)) {
// ./modules
File dir = new File(".", Constants.DEFAULT_MODULE_DIR);
return new SimpleRepository(REPO_NAME_LOCAL, dir.getPath(), null);
} else if (REPO_NAME_CACHE.equals(repoName)) {
// $HOME/.ceylon/cache
File dir = getCacheRepoDir();
return new SimpleRepository(REPO_NAME_CACHE, dir.getAbsolutePath(), null);
} else if (REPO_NAME_USER.equals(repoName)) {
// $HOME/.ceylon/repo
File userRepoDir = getUserRepoDir();
return new SimpleRepository(REPO_NAME_USER, userRepoDir.getAbsolutePath(), null);
} else if (REPO_NAME_REMOTE.equals(repoName)) {
// https://modules.ceylon-lang.org
return new SimpleRepository(REPO_NAME_REMOTE, Constants.REPO_URL_CEYLON, null);
} else if (REPO_NAME_MAVEN.equals(repoName)) {
// aether:
return new SimpleRepository(REPO_NAME_MAVEN, "aether:", null);
}
return null;
}
}
private String reposTypeKey(String repoType) {
return SECTION_REPOSITORIES + "." + repoType;
}
public Repository[] getRepositoriesByType(String repoType) {
String urls[] = config.getOptionValues(reposTypeKey(repoType));
if (urls != null) {
ArrayList repos = new ArrayList(urls.length);
for (int i = 0; i < urls.length; i++) {
String url = urls[i];
Repository repo;
if (url.startsWith("+")) {
String name = url.substring(1);
repo = new RepositoryRef(getRepository(name));
} else {
String name = "%" + repoType + "-" + (i + 1);
repo = new SimpleRepository(name, url, null);
}
if (repo != null) {
repos.add(repo);
}
}
if (!repos.isEmpty()) {
Repository[] result = new Repository[repos.size()];
return repos.toArray(result);
}
}
return null;
}
public Repository[] getRepositoriesByTypeWithDefaults(String repoType) {
if (repoType.equals(REPO_TYPE_SYSTEM)) {
return new Repository[] { getSystemRepository() };
} else if (repoType.equals(REPO_TYPE_OUTPUT)) {
return new Repository[] { getOutputRepository() };
} else if (repoType.equals(REPO_TYPE_CACHE)) {
return new Repository[] { getCacheRepository() };
} else if (repoType.equals(REPO_TYPE_LOCAL_LOOKUP)) {
return getLocalLookupRepositories();
} else if (repoType.equals(REPO_TYPE_GLOBAL_LOOKUP)) {
return getGlobalLookupRepositories();
} else if (repoType.equals(REPO_TYPE_REMOTE_LOOKUP)) {
return getRemoteLookupRepositories();
} else if (repoType.equals(REPO_TYPE_OTHER_LOOKUP)) {
return getOtherLookupRepositories();
} else {
return getRepositoriesByType(repoType);
}
}
public Repository getRepositoryByType(String repoType) {
Repository[] repos = getRepositoriesByType(repoType);
if (repos != null) {
return repos[0];
} else {
return null;
}
}
public Repository getRepositoryByTypeWithDefaults(String repoType) {
Repository[] repos = getRepositoriesByTypeWithDefaults(repoType);
if (repos != null) {
return repos[0];
} else {
return null;
}
}
public void setRepositoriesByType(String repoType, Repository[] repos) {
String key = reposTypeKey(repoType);
if (repos != null) {
ArrayList urls = new ArrayList(repos.length);
for (Repository repo : repos) {
String url;
if (repo instanceof RepositoryRef) {
url = "+" + repo.getName();
} else {
url = repo.getUrl();
}
urls.add(url);
}
if (!urls.isEmpty()) {
String[] values = new String[urls.size()];
config.setOptionValues(key, urls.toArray(values));
} else {
config.removeOption(key);
}
} else {
config.removeOption(key);
}
}
public Map getRepositories() {
HashMap repos = new HashMap();
repos.put(REPO_TYPE_SYSTEM, getRepositoriesByType(REPO_TYPE_SYSTEM));
repos.put(REPO_TYPE_OUTPUT, getRepositoriesByType(REPO_TYPE_OUTPUT));
repos.put(REPO_TYPE_CACHE, getRepositoriesByType(REPO_TYPE_CACHE));
repos.put(REPO_TYPE_LOCAL_LOOKUP, getRepositoriesByType(REPO_TYPE_LOCAL_LOOKUP));
repos.put(REPO_TYPE_GLOBAL_LOOKUP, getRepositoriesByType(REPO_TYPE_GLOBAL_LOOKUP));
repos.put(REPO_TYPE_REMOTE_LOOKUP, getRepositoriesByType(REPO_TYPE_REMOTE_LOOKUP));
repos.put(REPO_TYPE_OTHER_LOOKUP, getRepositoriesByType(REPO_TYPE_OTHER_LOOKUP));
return repos;
}
public void setRepositories(Map repos) {
setRepositoriesByType(REPO_TYPE_SYSTEM, repos.get(REPO_TYPE_SYSTEM));
setRepositoriesByType(REPO_TYPE_OUTPUT, repos.get(REPO_TYPE_OUTPUT));
setRepositoriesByType(REPO_TYPE_CACHE, repos.get(REPO_TYPE_CACHE));
setRepositoriesByType(REPO_TYPE_LOCAL_LOOKUP, repos.get(REPO_TYPE_LOCAL_LOOKUP));
setRepositoriesByType(REPO_TYPE_GLOBAL_LOOKUP, repos.get(REPO_TYPE_GLOBAL_LOOKUP));
setRepositoriesByType(REPO_TYPE_REMOTE_LOOKUP, repos.get(REPO_TYPE_REMOTE_LOOKUP));
setRepositoriesByType(REPO_TYPE_OTHER_LOOKUP, repos.get(REPO_TYPE_OTHER_LOOKUP));
}
public File getSystemRepoDir() {
String ceylonSystemRepo = System.getProperty(Constants.PROP_CEYLON_SYSTEM_REPO);
if (ceylonSystemRepo != null) {
return new File(ceylonSystemRepo);
} else {
File userDir = FileUtil.getInstallDir();
if (userDir != null) {
return new File(userDir, "repo");
}
}
return null;
}
public File getUserRepoDir() {
String ceylonUserRepo = System.getProperty(Constants.PROP_CEYLON_USER_REPO);
if (ceylonUserRepo != null) {
return new File(ceylonUserRepo);
} else {
File userDir = FileUtil.getUserDir();
return new File(userDir, "repo");
}
}
public File getCacheRepoDir() {
String ceylonUserRepo = System.getProperty(Constants.PROP_CEYLON_CACHE_REPO);
if (ceylonUserRepo != null) {
return new File(ceylonUserRepo);
} else {
File userDir = FileUtil.getUserDir();
return new File(userDir, "cache");
}
}
public Repository getSystemRepository() {
Repository repo = getRepositoryByType(REPO_TYPE_SYSTEM);
if (repo == null) {
repo = getRepository(REPO_NAME_SYSTEM);
}
return repo;
}
public Repository getOutputRepository() {
Repository repo = getRepositoryByType(REPO_TYPE_OUTPUT);
if (repo == null) {
repo = getRepository(REPO_NAME_LOCAL);
}
return repo;
}
public Repository getCacheRepository() {
Repository repo = getRepositoryByType(REPO_TYPE_CACHE);
if (repo == null) {
repo = getRepository(REPO_NAME_CACHE);
}
return repo;
}
public Repository[] getLocalLookupRepositories() {
Repository[] repos = getRepositoriesByType(REPO_TYPE_LOCAL_LOOKUP);
if (repos == null) {
repos = new Repository[1];
// By default "./modules"
repos[0] = getRepository(REPO_NAME_LOCAL);
}
return repos;
}
public Repository[] getGlobalLookupRepositories() {
Repository[] repos = getRepositoriesByType(REPO_TYPE_GLOBAL_LOOKUP);
if (repos == null) {
repos = new Repository[1];
// By default "$HOME/.ceylon/repo"
repos[0] = getRepository(REPO_NAME_USER);
}
return repos;
}
public Repository[] getRemoteLookupRepositories() {
Repository[] repos = getRepositoriesByType(REPO_TYPE_REMOTE_LOOKUP);
if (repos == null) {
repos = new Repository[0];
}
return repos;
}
public Repository[] getOtherLookupRepositories() {
Repository[] repos = getRepositoriesByType(REPO_TYPE_OTHER_LOOKUP);
if (repos == null) {
repos = new Repository[2];
// By default "https://modules.ceylon-lang.org" and "aether:"
repos[0] = getRepository(REPO_NAME_REMOTE);
repos[1] = getRepository(REPO_NAME_MAVEN);
}
return repos;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy