All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.redhat.ceylon.tools.moduleloading.ModuleLoadingTool Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
package com.redhat.ceylon.tools.moduleloading;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

import com.redhat.ceylon.cmr.api.ArtifactContext;
import com.redhat.ceylon.cmr.api.ModuleQuery;
import com.redhat.ceylon.cmr.api.RepositoryManager;
import com.redhat.ceylon.cmr.api.VersionComparator;
import com.redhat.ceylon.cmr.ceylon.RepoUsingTool;
import com.redhat.ceylon.common.Messages;
import com.redhat.ceylon.common.ModuleUtil;
import com.redhat.ceylon.common.Versions;
import com.redhat.ceylon.common.tool.Description;
import com.redhat.ceylon.common.tool.Option;
import com.redhat.ceylon.common.tool.ToolUsageError;
import com.redhat.ceylon.model.cmr.ArtifactResult;
import com.redhat.ceylon.model.cmr.ImportType;
import com.redhat.ceylon.model.cmr.JDKUtils;
import com.redhat.ceylon.model.cmr.JDKUtils.JDK;
import com.redhat.ceylon.model.typechecker.model.Module;

public abstract class ModuleLoadingTool extends RepoUsingTool {

    protected Map loadedModules = new HashMap<>();
    protected Map> loadedModuleVersions = new HashMap<>();
    protected boolean upgradeDist = true;

	public ModuleLoadingTool() {
		super(ModuleLoadingMessages.RESOURCE_BUNDLE);
	}
    
    @Option
    @Description("Downgrade which were compiled with a more recent "
            + "version of the distribution to the version of that module "
            + "present in this distribution (" + Versions.CEYLON_VERSION_NUMBER + "). "
            + "This might fail with a linker error at runtime. For example "
            + "if the module depended on an API present in the more "
            + "recent version, but absent from " + Versions.CEYLON_VERSION_NUMBER +". "
                    + "Allowed arguments are upgrade, downgrade or abort. Default: upgrade")
    public void setLinkWithCurrentDistribution(boolean downgradeDist) {
        this.upgradeDist = !downgradeDist;
    }
	
	protected String moduleVersion(String moduleNameOptVersion) throws IOException {
		return checkModuleVersionsOrShowSuggestions(
				getRepositoryManager(),
				ModuleUtil.moduleName(moduleNameOptVersion),
				ModuleUtil.moduleVersion(moduleNameOptVersion),
				ModuleQuery.Type.JVM,
				Versions.JVM_BINARY_MAJOR_VERSION,
				Versions.JVM_BINARY_MINOR_VERSION,
				// JS binary but don't care since JVM
				null, null);

	}
	
	protected boolean loadModule(String moduleName, String moduleVersion) throws IOException {
		return loadModule(moduleName, moduleVersion, false);
	}
	
	protected boolean loadModule(String moduleName, String moduleVersion, boolean optional) throws IOException {
		boolean success = false;
		if (moduleVersion != null) {
			success = true;
			success &= internalLoadModule(Module.LANGUAGE_MODULE_NAME, Versions.CEYLON_VERSION_NUMBER, false);
			success &= internalLoadModule("com.redhat.ceylon.common", Versions.CEYLON_VERSION_NUMBER, false);
            success &= internalLoadModule("com.redhat.ceylon.model", Versions.CEYLON_VERSION_NUMBER, false);
			success &= internalLoadModule("com.redhat.ceylon.module-resolver", Versions.CEYLON_VERSION_NUMBER, false);
			success &= internalLoadModule(moduleName, moduleVersion, false);
		}
		
		return success;
	}

	protected boolean shouldExclude(String moduleName, String version) {
		if(JDKUtils.jdk.providesVersion(JDK.JDK9.version)){
			moduleName = JDKUtils.getJava9ModuleName(moduleName, version);
		}
		return JDKUtils.isJDKModule(moduleName) || 
				JDKUtils.isOracleJDKModule(moduleName);
	}

	private boolean internalLoadModule(String name, String version, boolean optional) throws IOException {
        String key = name + "/" + version;
        if(loadedModules.containsKey(key))
            return true;
        if(shouldExclude(name, version)) {
            // let's not check the version and assume it's provided
            // treat it as a missing optional for the purpose of classpath
            loadedModules.put(key, null);
            return true;
        }
        // remember which version we loaded
        SortedSet loadedVersions = loadedModuleVersions.get(name);
        if(loadedVersions == null){
            loadedVersions = new TreeSet<>(VersionComparator.INSTANCE);
            loadedModuleVersions.put(name, loadedVersions);
        }
        loadedVersions.add(version);
        
        RepositoryManager repositoryManager = getRepositoryManager(upgradeDist);
        ArtifactContext artifactContext = new ArtifactContext(name, version, ArtifactContext.CAR, ArtifactContext.JAR);
        ArtifactResult result = repositoryManager.getArtifactResult(artifactContext);
        if(!optional
                && (result == null || result.artifact() == null || !result.artifact().exists())){
            String err = getModuleNotFoundErrorMessage(repositoryManager, name, version);
            errorAppend(err);
            errorNewline();
            return false;
        }
        // save even missing optional modules as nulls to not re-resolve them
        loadedModules.put(key, result);
        if(result != null){
            for(ArtifactResult dep : result.dependencies()){
                internalLoadModule(dep.name(), dep.version(), dep.importType() == ImportType.OPTIONAL);
            }
        }
        
        return true;
    }
	
	protected void errorOnConflictingModule(String module, String version) throws IOException{
	    boolean duplicate = false;
	    for(Map.Entry> entry : loadedModuleVersions.entrySet()){
	        if(entry.getValue().size() > 1){
	            duplicate = true;
	            printDuplicateModuleErrorMessage(entry.getKey(), entry.getValue());
	        }
	    }
	    if(duplicate)
	        throw new ToolUsageError(Messages.msg(bundle, "module.conflict.error", module, version));
	}

    private void printDuplicateModuleErrorMessage(String name, SortedSet versions) throws IOException {
        StringBuilder err = new StringBuilder();
        boolean first = true;
        for(String version : versions){
            if(first)
                first = false;
            else
                err.append(", ");
            err.append(version);
        }
        errorMsg("module.duplicate.error", name, err, versions.last());
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy