/** * Try to load a module from this module loader. Returns {@code null} if the module is not found. * The returned module may not yet be resolved. The returned module may have a different name than * the given identifier if the identifier is an alias for another module. * * @param identifier the module identifier * @return the module * @throws ModuleLoadException if an error occurs while loading the module */ protected final Module loadModuleLocal(ModuleIdentifier identifier) throws ModuleLoadException { FutureModule futureModule = moduleMap.get(identifier); if (futureModule != null) { return futureModule.getModule(); } FutureModule newFuture = new FutureModule(identifier); futureModule = moduleMap.putIfAbsent(identifier, newFuture); if (futureModule != null) { return futureModule.getModule(); } boolean ok = false; try { final ModuleLogger log = Module.log; log.trace("Locally loading module %s from %s", identifier, this); final long startTime = Metrics.getCurrentCPUTime(); final ModuleSpec moduleSpec = findModule(identifier); loadTimeUpdater.addAndGet(this, Metrics.getCurrentCPUTime() - startTime); if (moduleSpec == null) { log.trace("Module %s not found from %s", identifier, this); return null; } if (!moduleSpec.getModuleIdentifier().equals(identifier)) { throw new ModuleLoadException("Module loader found a module with the wrong name"); } final Module module; if (moduleSpec instanceof AliasModuleSpec) { final ModuleIdentifier aliasTarget = ((AliasModuleSpec) moduleSpec).getAliasTarget(); try { newFuture.setModule(module = loadModuleLocal(aliasTarget)); } catch (RuntimeException e) { log.trace(e, "Failed to load module %s (alias for %s)", identifier, aliasTarget); throw e; } catch (Error e) { log.trace(e, "Failed to load module %s (alias for %s)", identifier, aliasTarget); throw e; } } else { module = defineModule((ConcreteModuleSpec) moduleSpec, newFuture); } log.trace("Loaded module %s from %s", identifier, this); ok = true; return module; } finally { if (!ok) { newFuture.setModule(null); moduleMap.remove(identifier, newFuture); } } }