private void loadModule(String name, String version, boolean optional, boolean inCurrentClassLoader) throws IOException {
// skip JDK modules
if(JDKUtils.isJDKModule(name) || JDKUtils.isOracleJDKModule(name))
return;
if(loadedModules.containsKey(name)){
ArtifactResult loadedModule = loadedModules.get(name);
String resolvedVersion = loadedModuleVersions.get(name);
// we loaded the module already, but did we load it with the same version?
if(!Objects.equals(version, resolvedVersion)){
// version conflict, even if one was a missing optional
throw new RuntimeException("Requiring two modules with the same name ("+name+") but conflicting versions: "+version+" and "+resolvedVersion);
}
// now we're sure the version was the same
if(loadedModule == null){
// it was resolved to null so it was optional, but perhaps it's required now?
if(!optional){
throw new RuntimeException("Missing module: "+ModuleUtil.makeModuleName(name, version));
}
}
// already resolved and same version, we're good
return;
}
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())){
throw new RuntimeException("Missing module: "+ModuleUtil.makeModuleName(name, version));
}
// save even missing optional modules as nulls to not re-resolve them
loadedModules.put(name, result);
loadedModuleVersions.put(name, version);
if(result != null){
// everything we know should be in the current class loader
// plus everything from flat repositories
if(inCurrentClassLoader || result.repository() instanceof FlatRepository){
loadedModulesInCurrentClassLoader.add(name);
}
for(ArtifactResult dep : result.dependencies()){
loadModule(dep.name(), dep.version(), dep.importType() == ImportType.OPTIONAL, inCurrentClassLoader);
}
}
}