< prev index next >
src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java
Print this page
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
@@ -42,11 +42,10 @@
import java.lang.module.ModuleDescriptor.Opens;
import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleDescriptor.Requires;
import java.lang.module.ModuleDescriptor.Version;
import java.lang.module.ResolutionException;
-import java.lang.module.ResolvedModule;
import java.net.URI;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
@@ -56,17 +55,14 @@
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.MessageFormat;
-import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Deque;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -99,10 +95,11 @@
import jdk.internal.joptsimple.OptionSet;
import jdk.internal.joptsimple.OptionSpec;
import jdk.internal.joptsimple.ValueConverter;
import jdk.internal.loader.ResourceHelper;
import jdk.internal.module.ModuleHashes;
+import jdk.internal.module.ModuleHashesBuilder;
import jdk.internal.module.ModuleInfo;
import jdk.internal.module.ModuleInfoExtender;
import jdk.internal.module.ModulePath;
import jdk.internal.module.ModuleResolution;
import jdk.tools.jlink.internal.Utils;
@@ -787,37 +784,41 @@
/**
* Compute and record hashes
*/
private class Hasher {
- final ModuleFinder moduleFinder;
+ final ModuleHashesBuilder hashesBuilder;
final Map<String, Path> moduleNameToPath;
final Set<String> modules;
- final Configuration configuration;
final boolean dryrun = options.dryrun;
Hasher(ModuleFinder finder) {
- this.moduleFinder = finder;
// Determine the modules that matches the pattern {@code modulesToHash}
- this.modules = moduleFinder.findAll().stream()
+ this.modules = finder.findAll().stream()
.map(mref -> mref.descriptor().name())
.filter(mn -> options.modulesToHash.matcher(mn).find())
.collect(Collectors.toSet());
// a map from a module name to Path of the packaged module
- this.moduleNameToPath = moduleFinder.findAll().stream()
+ this.moduleNameToPath = finder.findAll().stream()
.map(mref -> mref.descriptor().name())
- .collect(Collectors.toMap(Function.identity(), mn -> moduleToPath(mn)));
+ .filter(modules::contains)
+ .collect(Collectors.toMap(Function.identity(), mn -> moduleToPath(finder, mn)));
// get a resolved module graph
Configuration config = null;
try {
config = Configuration.empty()
- .resolveRequires(ModuleFinder.ofSystem(), moduleFinder, modules);
+ .resolveRequires(ModuleFinder.ofSystem(), finder, modules);
} catch (ResolutionException e) {
warning("warn.module.resolution.fail", e.getMessage());
}
- this.configuration = config;
+
+ // ModuleHashesBuilder is constructed with the moduleNameToPath arguments
+ // so that creating java.base.jmod will compute the hash from this
+ // explicit path rather than the location from the resolved module
+ this.hashesBuilder = config != null
+ ? new ModuleHashesBuilder(config, moduleNameToPath) : null;
}
/**
* This method is for jmod hash command.
*
@@ -827,63 +828,26 @@
* For each base module M, compute the hashes of all modules that depend
* upon M directly or indirectly. Then update M's module-info.class
* to record the hashes.
*/
boolean run() {
- if (configuration == null)
+ if (hashesBuilder == null)
return false;
- // transposed graph containing the the packaged modules and
- // its transitive dependences matching --hash-modules
- Map<String, Set<String>> graph = new HashMap<>();
- for (String root : modules) {
- Deque<String> deque = new ArrayDeque<>();
- deque.add(root);
- Set<String> visited = new HashSet<>();
- while (!deque.isEmpty()) {
- String mn = deque.pop();
- if (!visited.contains(mn)) {
- visited.add(mn);
-
- if (modules.contains(mn))
- graph.computeIfAbsent(mn, _k -> new HashSet<>());
-
- ResolvedModule resolvedModule = configuration.findModule(mn).get();
- for (ResolvedModule dm : resolvedModule.reads()) {
- String name = dm.name();
- if (!visited.contains(name)) {
- deque.push(name);
- }
-
- // reverse edge
- if (modules.contains(name) && modules.contains(mn)) {
- graph.computeIfAbsent(name, _k -> new HashSet<>()).add(mn);
- }
- }
- }
- }
- }
-
- if (dryrun)
+ if (dryrun) {
out.println("Dry run:");
+ }
- // each node in a transposed graph is a matching packaged module
- // in which the hash of the modules that depend upon it is recorded
- graph.entrySet().stream()
- .filter(e -> !e.getValue().isEmpty())
- .forEach(e -> {
+ hashesBuilder.computeHashes(modules).entrySet().forEach(e -> {
String mn = e.getKey();
- Map<String, Path> modulesForHash = e.getValue().stream()
- .collect(Collectors.toMap(Function.identity(),
- moduleNameToPath::get));
- ModuleHashes hashes = ModuleHashes.generate(modulesForHash, "SHA-256");
+ ModuleHashes hashes = e.getValue();
if (dryrun) {
out.format("%s%n", mn);
hashes.names().stream()
.sorted()
.forEach(name -> out.format(" hashes %s %s %s%n",
- name, hashes.algorithm(), hashes.hashFor(name)));
+ name, hashes.algorithm(), toHex(hashes.hashFor(name))));
} else {
try {
updateModuleInfo(mn, hashes);
} catch (IOException ex) {
throw new UncheckedIOException(ex);
@@ -898,85 +862,14 @@
*
* It records the hashing modules that depend upon the specified
* module directly or indirectly.
*/
ModuleHashes computeHashes(String name) {
- if (configuration == null)
+ if (hashesBuilder == null)
return null;
- // the transposed graph includes all modules in the resolved graph
- Map<String, Set<String>> graph = transpose();
-
- // find the modules that transitively depend upon the specified name
- Deque<String> deque = new ArrayDeque<>();
- deque.add(name);
- Set<String> mods = visitNodes(graph, deque);
-
- // filter modules matching the pattern specified --hash-modules
- // as well as itself as the jmod file is being generated
- Map<String, Path> modulesForHash = mods.stream()
- .filter(mn -> !mn.equals(name) && modules.contains(mn))
- .collect(Collectors.toMap(Function.identity(), moduleNameToPath::get));
-
- if (modulesForHash.isEmpty())
- return null;
-
- return ModuleHashes.generate(modulesForHash, "SHA-256");
- }
-
- /**
- * Returns all nodes traversed from the given roots.
- */
- private Set<String> visitNodes(Map<String, Set<String>> graph,
- Deque<String> roots) {
- Set<String> visited = new HashSet<>();
- while (!roots.isEmpty()) {
- String mn = roots.pop();
- if (!visited.contains(mn)) {
- visited.add(mn);
- // the given roots may not be part of the graph
- if (graph.containsKey(mn)) {
- for (String dm : graph.get(mn)) {
- if (!visited.contains(dm)) {
- roots.push(dm);
- }
- }
- }
- }
- }
- return visited;
- }
-
- /**
- * Returns a transposed graph from the resolved module graph.
- */
- private Map<String, Set<String>> transpose() {
- Map<String, Set<String>> transposedGraph = new HashMap<>();
- Deque<String> deque = new ArrayDeque<>(modules);
-
- Set<String> visited = new HashSet<>();
- while (!deque.isEmpty()) {
- String mn = deque.pop();
- if (!visited.contains(mn)) {
- visited.add(mn);
-
- transposedGraph.computeIfAbsent(mn, _k -> new HashSet<>());
-
- ResolvedModule resolvedModule = configuration.findModule(mn).get();
- for (ResolvedModule dm : resolvedModule.reads()) {
- String name = dm.name();
- if (!visited.contains(name)) {
- deque.push(name);
- }
-
- // reverse edge
- transposedGraph.computeIfAbsent(name, _k -> new HashSet<>())
- .add(mn);
- }
- }
- }
- return transposedGraph;
+ return hashesBuilder.computeHashes(Set.of(name)).get(name);
}
/**
* Reads the given input stream of module-info.class and write
* the extended module-info.class with the given ModuleHashes
@@ -1072,11 +965,11 @@
}
});
}
}
- private Path moduleToPath(String name) {
+ private Path moduleToPath(ModuleFinder moduleFinder, String name) {
ModuleReference mref = moduleFinder.find(name).orElseThrow(
() -> new InternalError("Selected module " + name + " not on module path"));
URI uri = mref.location().get();
Path path = Paths.get(uri);
< prev index next >