/**
   * 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);
      }
    }
  }
Exemple #2
0
  /**
   * Defines a Module based on a specification. Use of this method is required by any ModuleLoader
   * implementations in order to fully define a Module.
   *
   * @param moduleSpec The module specification to create the Module from
   * @return The defined Module
   * @throws ModuleLoadException If any dependent modules can not be loaded
   */
  protected final Module defineModule(ModuleSpec moduleSpec) throws ModuleLoadException {

    final ModuleIdentifier moduleIdentifier = moduleSpec.getIdentifier();
    FutureModule futureModule = moduleMap.get(moduleIdentifier);
    if (futureModule == null) {
      FutureModule newFuture = new FutureModule(moduleIdentifier);
      futureModule = moduleMap.putIfAbsent(moduleIdentifier, newFuture);
      if (futureModule == null) futureModule = newFuture;
    }
    // early detect
    if (futureModule.module != null) {
      throw new ModuleAlreadyExistsException(moduleIdentifier.toString());
    }
    try {
      final List<Dependency> dependencies =
          new ArrayList<Dependency>(moduleSpec.getDependencies().size());
      for (DependencySpec dependencySpec : moduleSpec.getDependencies()) {
        final Module dependencyModule;
        try {
          dependencyModule = loadModule(dependencySpec.getModuleIdentifier());
        } catch (ModuleLoadException e) {
          if (dependencySpec.isOptional()) {
            continue;
          } else {
            throw e;
          }
        }
        final Dependency dependency = new Dependency(dependencyModule, dependencySpec.isExport());
        dependencies.add(dependency);
      }
      final Module module = new Module(moduleSpec, dependencies, moduleSpec.getModuleFlags(), this);
      synchronized (futureModule) {
        futureModule.setModule(module);
      }
      return module;
    } catch (ModuleLoadException e) {
      futureModule.setModule(null);
      throw e;
    } catch (RuntimeException e) {
      futureModule.setModule(null);
      throw e;
    } catch (Error e) {
      futureModule.setModule(null);
      throw e;
    }
  }
  /**
   * Defines a Module based on a specification. May only be called from {@link
   * #loadModuleLocal(ModuleIdentifier)}.
   *
   * @param moduleSpec The module specification to create the Module from
   * @param futureModule the future module to populate
   * @return The defined Module
   * @throws ModuleLoadException If any dependent modules can not be loaded
   */
  private Module defineModule(final ConcreteModuleSpec moduleSpec, final FutureModule futureModule)
      throws ModuleLoadException {

    final ModuleLogger log = Module.log;
    final ModuleIdentifier moduleIdentifier = moduleSpec.getModuleIdentifier();

    final Module module = new Module(moduleSpec, this, futureModule);
    module.getClassLoaderPrivate().recalculate();
    module.setDependencies(Arrays.asList(moduleSpec.getDependencies()));
    log.moduleDefined(moduleIdentifier, this);
    try {
      futureModule.setModule(module);
      return module;
    } catch (RuntimeException e) {
      log.trace(e, "Failed to load module %s", moduleIdentifier);
      throw e;
    } catch (Error e) {
      log.trace(e, "Failed to load module %s", moduleIdentifier);
      throw e;
    }
  }