< 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 >