< prev index next >
src/jdk.jartool/share/classes/sun/tools/jar/Main.java
Print this page
*** 45,55 ****
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.function.Consumer;
- import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.*;
--- 45,54 ----
*** 58,76 ****
import java.util.jar.Manifest;
import java.text.MessageFormat;
import jdk.internal.module.Checks;
import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModuleInfo;
import jdk.internal.module.ModuleInfoExtender;
import jdk.internal.module.ModuleResolution;
import jdk.internal.util.jar.JarIndex;
import static jdk.internal.util.jar.JarIndex.INDEX_NAME;
import static java.util.jar.JarFile.MANIFEST_NAME;
import static java.util.stream.Collectors.joining;
- import static java.util.stream.Collectors.toSet;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
/**
* This class implements a simple utility for creating files in the JAR
* (Java Archive) file format. The JAR format is based on the ZIP file
--- 57,75 ----
import java.util.jar.Manifest;
import java.text.MessageFormat;
import jdk.internal.module.Checks;
import jdk.internal.module.ModuleHashes;
+ import jdk.internal.module.ModuleHashesBuilder;
import jdk.internal.module.ModuleInfo;
import jdk.internal.module.ModuleInfoExtender;
import jdk.internal.module.ModuleResolution;
import jdk.internal.util.jar.JarIndex;
import static jdk.internal.util.jar.JarIndex.INDEX_NAME;
import static java.util.jar.JarFile.MANIFEST_NAME;
import static java.util.stream.Collectors.joining;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
/**
* This class implements a simple utility for creating files in the JAR
* (Java Archive) file format. The JAR format is based on the ZIP file
*** 1928,1939 ****
Hasher hasher = new Hasher(md, fname);
ModuleHashes moduleHashes = hasher.computeHashes(mn);
if (moduleHashes != null) {
extender.hashes(moduleHashes);
} else {
! // should it issue warning or silent?
! System.out.println("warning: no module is recorded in hash in " + mn);
}
}
if (moduleResolution.value() != 0) {
extender.moduleResolution(moduleResolution);
--- 1927,1937 ----
Hasher hasher = new Hasher(md, fname);
ModuleHashes moduleHashes = hasher.computeHashes(mn);
if (moduleHashes != null) {
extender.hashes(moduleHashes);
} else {
! warn("warning: no module is recorded in hash in " + mn);
}
}
if (moduleResolution.value() != 0) {
extender.moduleResolution(moduleResolution);
*** 1945,1958 ****
/**
* Compute and record hashes
*/
private class Hasher {
final ModuleFinder finder;
- final Map<String, Path> moduleNameToPath;
final Set<String> modules;
- final Configuration configuration;
Hasher(ModuleDescriptor descriptor, String fname) throws IOException {
// Create a module finder that finds the modular JAR
// being created/updated
URI uri = Paths.get(fname).toUri();
ModuleReference mref = new ModuleReference(descriptor, uri) {
--- 1943,1955 ----
/**
* Compute and record hashes
*/
private class Hasher {
+ final ModuleHashesBuilder hashesBuilder;
final ModuleFinder finder;
final Set<String> modules;
Hasher(ModuleDescriptor descriptor, String fname) throws IOException {
// Create a module finder that finds the modular JAR
// being created/updated
URI uri = Paths.get(fname).toUri();
ModuleReference mref = new ModuleReference(descriptor, uri) {
*** 1978,2098 ****
public Set<ModuleReference> findAll() {
return Collections.singleton(mref);
}
});
! // Determine the modules that matches the modulesToHash pattern
! this.modules = moduleFinder.findAll().stream()
! .map(moduleReference -> moduleReference.descriptor().name())
.filter(mn -> modulesToHash.matcher(mn).find())
.collect(Collectors.toSet());
! // a map from a module name to Path of the modular JAR
! this.moduleNameToPath = moduleFinder.findAll().stream()
! .map(ModuleReference::descriptor)
! .map(ModuleDescriptor::name)
! .collect(Collectors.toMap(Function.identity(), mn -> moduleToPath(mn)));
! Configuration config = null;
! try {
! config = Configuration.empty()
! .resolveRequires(ModuleFinder.ofSystem(), finder, modules);
! } catch (ResolutionException e) {
! // should it throw an error? or emit a warning
! System.out.println("warning: " + e.getMessage());
! }
! this.configuration = config;
}
/**
! * Compute hashes of the modules that depend upon the specified
* module directly or indirectly.
*/
ModuleHashes computeHashes(String name) {
! // 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 in --hash-modules,
! // as well as the modular jar file that is being created / updated
! 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);
!
! // add an empty set
! 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;
! }
!
! private Path moduleToPath(String name) {
! ModuleReference mref = moduleFinder.find(name).orElseThrow(
! () -> new InternalError(formatMsg2("error.hash.dep",name , name)));
!
! URI uri = mref.location().get();
! Path path = Paths.get(uri);
! String fn = path.getFileName().toString();
! if (!fn.endsWith(".jar")) {
! throw new UnsupportedOperationException(path + " is not a modular JAR");
! }
! return path;
}
}
}
--- 1975,2022 ----
public Set<ModuleReference> findAll() {
return Collections.singleton(mref);
}
});
! // Determine the modules that matches the pattern {@code modulesToHash}
! Set<String> roots = finder.findAll().stream()
! .map(ref -> ref.descriptor().name())
.filter(mn -> modulesToHash.matcher(mn).find())
.collect(Collectors.toSet());
! // use system module path unless it creates a modular JAR for
! // a module that is present in the system image e.g. upgradeable
! // module
! ModuleFinder system;
! String name = descriptor.name();
! if (name != null && ModuleFinder.ofSystem().find(name).isPresent()) {
! system = ModuleFinder.of();
! } else {
! system = ModuleFinder.ofSystem();
! }
! // get a resolved module graph
! Configuration config =
! Configuration.empty().resolveRequires(system, finder, roots);
!
! // filter modules resolved from the system module finder
! this.modules = config.modules().stream()
! .map(ResolvedModule::name)
! .filter(mn -> roots.contains(mn) && !system.find(mn).isPresent())
! .collect(Collectors.toSet());
! this.hashesBuilder = new ModuleHashesBuilder(config, modules);
}
/**
! * Compute hashes of the specified module.
! *
! * It records the hashing modules that depend upon the specified
* module directly or indirectly.
*/
ModuleHashes computeHashes(String name) {
! if (hashesBuilder == null)
return null;
! return hashesBuilder.computeHashes(Set.of(name)).get(name);
}
}
}
< prev index next >