--- old/src/jdk.jartool/share/classes/sun/tools/jar/Main.java 2017-01-11 15:23:19.000000000 -0800 +++ new/src/jdk.jartool/share/classes/sun/tools/jar/Main.java 2017-01-11 15:23:19.000000000 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -37,7 +37,6 @@ import java.lang.module.ModuleReader; import java.lang.module.ModuleReference; import java.lang.module.ResolutionException; -import java.lang.module.ResolvedModule; import java.net.URI; import java.nio.ByteBuffer; import java.nio.file.Path; @@ -46,7 +45,6 @@ import java.nio.file.StandardCopyOption; import java.util.*; import java.util.function.Consumer; -import java.util.function.Function; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -58,6 +56,7 @@ 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; @@ -66,7 +65,6 @@ 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; /** @@ -2235,10 +2233,9 @@ * Compute and record hashes */ private class Hasher { + final ModuleHashesBuilder hashesBuilder; final ModuleFinder finder; - final Map moduleNameToPath; final Set modules; - final Configuration configuration; Hasher(ModuleDescriptor descriptor, String fname) throws IOException { // Create a module finder that finds the modular JAR // being created/updated @@ -2274,12 +2271,6 @@ .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() @@ -2288,99 +2279,21 @@ // should it throw an error? or emit a warning System.out.println("warning: " + e.getMessage()); } - this.configuration = config; + this.hashesBuilder = config != null + ? new ModuleHashesBuilder(config, modules) : null; } /** - * Compute hashes of the modules that depend upon the specified + * Compute hashes of the specified module. + * + * It records the hashing 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> graph = transpose(); - - // find the modules that transitively depend upon the specified name - Deque deque = new ArrayDeque<>(); - deque.add(name); - Set 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 modulesForHash = mods.stream() - .filter(mn -> !mn.equals(name) && modules.contains(mn)) - .collect(Collectors.toMap(Function.identity(), moduleNameToPath::get)); - - if (modulesForHash.isEmpty()) + if (hashesBuilder == null) return null; - return ModuleHashes.generate(modulesForHash, "SHA-256"); - } - - /** - * Returns all nodes traversed from the given roots. - */ - private Set visitNodes(Map> graph, - Deque roots) { - Set 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> transpose() { - Map> transposedGraph = new HashMap<>(); - Deque deque = new ArrayDeque<>(modules); - - Set 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; + return hashesBuilder.computeHashes(Set.of(name)).get(name); } } }