< prev index next >

src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java

Print this page


   1 /*
   2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  27 
  28 import java.io.ByteArrayInputStream;
  29 import java.io.ByteArrayOutputStream;
  30 import java.io.File;
  31 import java.io.IOException;
  32 import java.io.InputStream;
  33 import java.io.OutputStream;
  34 import java.io.PrintWriter;
  35 import java.io.UncheckedIOException;
  36 import java.lang.module.Configuration;
  37 import java.lang.module.ModuleReader;
  38 import java.lang.module.ModuleReference;
  39 import java.lang.module.ModuleFinder;
  40 import java.lang.module.ModuleDescriptor;
  41 import java.lang.module.ModuleDescriptor.Exports;
  42 import java.lang.module.ModuleDescriptor.Opens;
  43 import java.lang.module.ModuleDescriptor.Provides;
  44 import java.lang.module.ModuleDescriptor.Requires;
  45 import java.lang.module.ModuleDescriptor.Version;
  46 import java.lang.module.ResolutionException;
  47 import java.lang.module.ResolvedModule;
  48 import java.net.URI;
  49 import java.nio.file.FileSystems;
  50 import java.nio.file.FileVisitOption;
  51 import java.nio.file.FileVisitResult;
  52 import java.nio.file.Files;
  53 import java.nio.file.InvalidPathException;
  54 import java.nio.file.Path;
  55 import java.nio.file.PathMatcher;
  56 import java.nio.file.Paths;
  57 import java.nio.file.SimpleFileVisitor;
  58 import java.nio.file.StandardCopyOption;
  59 import java.nio.file.attribute.BasicFileAttributes;
  60 import java.text.MessageFormat;
  61 import java.util.ArrayDeque;
  62 import java.util.ArrayList;
  63 import java.util.Collection;
  64 import java.util.Collections;
  65 import java.util.Comparator;
  66 import java.util.Deque;
  67 import java.util.HashMap;
  68 import java.util.HashSet;
  69 import java.util.LinkedHashMap;
  70 import java.util.List;
  71 import java.util.Locale;
  72 import java.util.Map;
  73 import java.util.MissingResourceException;
  74 import java.util.Optional;
  75 import java.util.ResourceBundle;
  76 import java.util.Set;
  77 import java.util.TreeSet;
  78 import java.util.function.Consumer;
  79 import java.util.function.Function;
  80 import java.util.function.Predicate;
  81 import java.util.function.Supplier;
  82 import java.util.jar.JarEntry;
  83 import java.util.jar.JarFile;
  84 import java.util.jar.JarOutputStream;
  85 import java.util.stream.Collectors;
  86 import java.util.regex.Pattern;
  87 import java.util.regex.PatternSyntaxException;
  88 import java.util.zip.ZipEntry;
  89 import java.util.zip.ZipException;
  90 import java.util.zip.ZipFile;
  91 
  92 import jdk.internal.jmod.JmodFile;
  93 import jdk.internal.jmod.JmodFile.Section;
  94 import jdk.internal.joptsimple.BuiltinHelpFormatter;
  95 import jdk.internal.joptsimple.NonOptionArgumentSpec;
  96 import jdk.internal.joptsimple.OptionDescriptor;
  97 import jdk.internal.joptsimple.OptionException;
  98 import jdk.internal.joptsimple.OptionParser;
  99 import jdk.internal.joptsimple.OptionSet;
 100 import jdk.internal.joptsimple.OptionSpec;
 101 import jdk.internal.joptsimple.ValueConverter;
 102 import jdk.internal.loader.ResourceHelper;
 103 import jdk.internal.module.ModuleHashes;

 104 import jdk.internal.module.ModuleInfo;
 105 import jdk.internal.module.ModuleInfoExtender;
 106 import jdk.internal.module.ModulePath;
 107 import jdk.internal.module.ModuleResolution;
 108 import jdk.tools.jlink.internal.Utils;
 109 
 110 import static java.util.stream.Collectors.joining;
 111 
 112 /**
 113  * Implementation for the jmod tool.
 114  */
 115 public class JmodTask {
 116 
 117     static class CommandException extends RuntimeException {
 118         private static final long serialVersionUID = 0L;
 119         boolean showUsage;
 120 
 121         CommandException(String key, Object... args) {
 122             super(getMessageOrKey(key, args));
 123         }


 772             public void accept(JarEntry je) {
 773                 try (InputStream in = jarfile.getInputStream(je)) {
 774                     out.writeEntry(in, Section.CLASSES, je.getName());
 775                 } catch (IOException e) {
 776                     throw new UncheckedIOException(e);
 777                 }
 778             }
 779             @Override
 780             public boolean test(JarEntry je) {
 781                 String name = je.getName();
 782                 // ## no support for excludes. Is it really needed?
 783                 return !name.endsWith(MODULE_INFO) && !je.isDirectory();
 784             }
 785         }
 786     }
 787 
 788     /**
 789      * Compute and record hashes
 790      */
 791     private class Hasher {
 792         final ModuleFinder moduleFinder;
 793         final Map<String, Path> moduleNameToPath;
 794         final Set<String> modules;
 795         final Configuration configuration;
 796         final boolean dryrun = options.dryrun;
 797         Hasher(ModuleFinder finder) {
 798             this.moduleFinder = finder;
 799             // Determine the modules that matches the pattern {@code modulesToHash}
 800             this.modules = moduleFinder.findAll().stream()
 801                 .map(mref -> mref.descriptor().name())
 802                 .filter(mn -> options.modulesToHash.matcher(mn).find())
 803                 .collect(Collectors.toSet());
 804 
 805             // a map from a module name to Path of the packaged module
 806             this.moduleNameToPath = moduleFinder.findAll().stream()
 807                 .map(mref -> mref.descriptor().name())
 808                 .collect(Collectors.toMap(Function.identity(), mn -> moduleToPath(mn)));

 809 
 810             // get a resolved module graph
 811             Configuration config = null;
 812             try {
 813                 config = Configuration.empty()
 814                     .resolveRequires(ModuleFinder.ofSystem(), moduleFinder, modules);
 815             } catch (ResolutionException e) {
 816                 warning("warn.module.resolution.fail", e.getMessage());
 817             }
 818             this.configuration = config;





 819         }
 820 
 821         /**
 822          * This method is for jmod hash command.
 823          *
 824          * Identify the base modules in the module graph, i.e. no outgoing edge
 825          * to any of the modules to be hashed.
 826          *
 827          * For each base module M, compute the hashes of all modules that depend
 828          * upon M directly or indirectly.  Then update M's module-info.class
 829          * to record the hashes.
 830          */
 831         boolean run() {
 832             if (configuration == null)
 833                 return false;
 834 
 835             // transposed graph containing the the packaged modules and
 836             // its transitive dependences matching --hash-modules
 837             Map<String, Set<String>> graph = new HashMap<>();
 838             for (String root : modules) {
 839                 Deque<String> deque = new ArrayDeque<>();
 840                 deque.add(root);
 841                 Set<String> visited = new HashSet<>();
 842                 while (!deque.isEmpty()) {
 843                     String mn = deque.pop();
 844                     if (!visited.contains(mn)) {
 845                         visited.add(mn);
 846 
 847                         if (modules.contains(mn))
 848                             graph.computeIfAbsent(mn, _k -> new HashSet<>());
 849 
 850                         ResolvedModule resolvedModule = configuration.findModule(mn).get();
 851                         for (ResolvedModule dm : resolvedModule.reads()) {
 852                             String name = dm.name();
 853                             if (!visited.contains(name)) {
 854                                 deque.push(name);
 855                             }
 856 
 857                             // reverse edge
 858                             if (modules.contains(name) && modules.contains(mn)) {
 859                                 graph.computeIfAbsent(name, _k -> new HashSet<>()).add(mn);
 860                             }
 861                         }
 862                     }
 863                 }
 864             }
 865 
 866             if (dryrun)
 867                 out.println("Dry run:");

 868 
 869             // each node in a transposed graph is a matching packaged module
 870             // in which the hash of the modules that depend upon it is recorded
 871             graph.entrySet().stream()
 872                 .filter(e -> !e.getValue().isEmpty())
 873                 .forEach(e -> {
 874                     String mn = e.getKey();
 875                     Map<String, Path> modulesForHash = e.getValue().stream()
 876                             .collect(Collectors.toMap(Function.identity(),
 877                                                       moduleNameToPath::get));
 878                     ModuleHashes hashes = ModuleHashes.generate(modulesForHash, "SHA-256");
 879                     if (dryrun) {
 880                         out.format("%s%n", mn);
 881                         hashes.names().stream()
 882                               .sorted()
 883                               .forEach(name -> out.format("  hashes %s %s %s%n",
 884                                   name, hashes.algorithm(), hashes.hashFor(name)));
 885                     } else {
 886                         try {
 887                             updateModuleInfo(mn, hashes);
 888                         } catch (IOException ex) {
 889                             throw new UncheckedIOException(ex);
 890                         }
 891                     }
 892                 });
 893             return true;
 894         }
 895 
 896         /**
 897          * Compute hashes of the specified module.
 898          *
 899          * It records the hashing modules that depend upon the specified
 900          * module directly or indirectly.
 901          */
 902         ModuleHashes computeHashes(String name) {
 903             if (configuration == null)
 904                 return null;
 905 
 906             // the transposed graph includes all modules in the resolved graph
 907             Map<String, Set<String>> graph = transpose();
 908 
 909             // find the modules that transitively depend upon the specified name
 910             Deque<String> deque = new ArrayDeque<>();
 911             deque.add(name);
 912             Set<String> mods = visitNodes(graph, deque);
 913 
 914             // filter modules matching the pattern specified --hash-modules
 915             // as well as itself as the jmod file is being generated
 916             Map<String, Path> modulesForHash = mods.stream()
 917                 .filter(mn -> !mn.equals(name) && modules.contains(mn))
 918                 .collect(Collectors.toMap(Function.identity(), moduleNameToPath::get));
 919 
 920             if (modulesForHash.isEmpty())
 921                 return null;
 922 
 923            return ModuleHashes.generate(modulesForHash, "SHA-256");
 924         }
 925 
 926         /**
 927          * Returns all nodes traversed from the given roots.
 928          */
 929         private Set<String> visitNodes(Map<String, Set<String>> graph,
 930                                        Deque<String> roots) {
 931             Set<String> visited = new HashSet<>();
 932             while (!roots.isEmpty()) {
 933                 String mn = roots.pop();
 934                 if (!visited.contains(mn)) {
 935                     visited.add(mn);
 936                     // the given roots may not be part of the graph
 937                     if (graph.containsKey(mn)) {
 938                         for (String dm : graph.get(mn)) {
 939                             if (!visited.contains(dm)) {
 940                                 roots.push(dm);
 941                             }
 942                         }
 943                     }
 944                 }
 945             }
 946             return visited;
 947         }
 948 
 949         /**
 950          * Returns a transposed graph from the resolved module graph.
 951          */
 952         private Map<String, Set<String>> transpose() {
 953             Map<String, Set<String>> transposedGraph = new HashMap<>();
 954             Deque<String> deque = new ArrayDeque<>(modules);
 955 
 956             Set<String> visited = new HashSet<>();
 957             while (!deque.isEmpty()) {
 958                 String mn = deque.pop();
 959                 if (!visited.contains(mn)) {
 960                     visited.add(mn);
 961 
 962                     transposedGraph.computeIfAbsent(mn, _k -> new HashSet<>());
 963 
 964                     ResolvedModule resolvedModule = configuration.findModule(mn).get();
 965                     for (ResolvedModule dm : resolvedModule.reads()) {
 966                         String name = dm.name();
 967                         if (!visited.contains(name)) {
 968                             deque.push(name);
 969                         }
 970 
 971                         // reverse edge
 972                         transposedGraph.computeIfAbsent(name, _k -> new HashSet<>())
 973                                 .add(mn);
 974                     }
 975                 }
 976             }
 977             return transposedGraph;
 978         }
 979 
 980         /**
 981          * Reads the given input stream of module-info.class and write
 982          * the extended module-info.class with the given ModuleHashes
 983          *
 984          * @param in       InputStream of module-info.class
 985          * @param out      OutputStream to write the extended module-info.class
 986          * @param hashes   ModuleHashes
 987          */
 988         private void recordHashes(InputStream in, OutputStream out, ModuleHashes hashes)
 989             throws IOException
 990         {
 991             ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in);
 992             extender.hashes(hashes);
 993             extender.write(out);
 994         }
 995 
 996         private void updateModuleInfo(String name, ModuleHashes moduleHashes)
 997             throws IOException


1057                  JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget))
1058             {
1059                 jf.stream().forEach(e -> {
1060                     try (InputStream in = jf.getInputStream(e.section(), e.name())) {
1061                         if (e.name().equals(MODULE_INFO)) {
1062                             // replace module-info.class
1063                             ModuleInfoExtender extender =
1064                                 ModuleInfoExtender.newExtender(in);
1065                             extender.hashes(moduleHashes);
1066                             jos.writeEntry(extender.toByteArray(), e.section(), e.name());
1067                         } else {
1068                             jos.writeEntry(in, e);
1069                         }
1070                     } catch (IOException x) {
1071                         throw new UncheckedIOException(x);
1072                     }
1073                 });
1074             }
1075         }
1076 
1077         private Path moduleToPath(String name) {
1078             ModuleReference mref = moduleFinder.find(name).orElseThrow(
1079                 () -> new InternalError("Selected module " + name + " not on module path"));
1080 
1081             URI uri = mref.location().get();
1082             Path path = Paths.get(uri);
1083             String fn = path.getFileName().toString();
1084             if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
1085                 throw new InternalError(path + " is not a modular JAR or jmod file");
1086             }
1087             return path;
1088         }
1089     }
1090 
1091     static class ClassPathConverter implements ValueConverter<Path> {
1092         static final ValueConverter<Path> INSTANCE = new ClassPathConverter();
1093 
1094         @Override
1095         public Path convert(String value) {
1096             try {
1097                 Path path = CWD.resolve(value);


   1 /*
   2  * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  27 
  28 import java.io.ByteArrayInputStream;
  29 import java.io.ByteArrayOutputStream;
  30 import java.io.File;
  31 import java.io.IOException;
  32 import java.io.InputStream;
  33 import java.io.OutputStream;
  34 import java.io.PrintWriter;
  35 import java.io.UncheckedIOException;
  36 import java.lang.module.Configuration;
  37 import java.lang.module.ModuleReader;
  38 import java.lang.module.ModuleReference;
  39 import java.lang.module.ModuleFinder;
  40 import java.lang.module.ModuleDescriptor;
  41 import java.lang.module.ModuleDescriptor.Exports;
  42 import java.lang.module.ModuleDescriptor.Opens;
  43 import java.lang.module.ModuleDescriptor.Provides;
  44 import java.lang.module.ModuleDescriptor.Requires;
  45 import java.lang.module.ModuleDescriptor.Version;
  46 import java.lang.module.ResolutionException;

  47 import java.net.URI;
  48 import java.nio.file.FileSystems;
  49 import java.nio.file.FileVisitOption;
  50 import java.nio.file.FileVisitResult;
  51 import java.nio.file.Files;
  52 import java.nio.file.InvalidPathException;
  53 import java.nio.file.Path;
  54 import java.nio.file.PathMatcher;
  55 import java.nio.file.Paths;
  56 import java.nio.file.SimpleFileVisitor;
  57 import java.nio.file.StandardCopyOption;
  58 import java.nio.file.attribute.BasicFileAttributes;
  59 import java.text.MessageFormat;

  60 import java.util.ArrayList;
  61 import java.util.Collection;
  62 import java.util.Collections;
  63 import java.util.Comparator;


  64 import java.util.HashSet;
  65 import java.util.LinkedHashMap;
  66 import java.util.List;
  67 import java.util.Locale;
  68 import java.util.Map;
  69 import java.util.MissingResourceException;
  70 import java.util.Optional;
  71 import java.util.ResourceBundle;
  72 import java.util.Set;
  73 import java.util.TreeSet;
  74 import java.util.function.Consumer;
  75 import java.util.function.Function;
  76 import java.util.function.Predicate;
  77 import java.util.function.Supplier;
  78 import java.util.jar.JarEntry;
  79 import java.util.jar.JarFile;
  80 import java.util.jar.JarOutputStream;
  81 import java.util.stream.Collectors;
  82 import java.util.regex.Pattern;
  83 import java.util.regex.PatternSyntaxException;
  84 import java.util.zip.ZipEntry;
  85 import java.util.zip.ZipException;
  86 import java.util.zip.ZipFile;
  87 
  88 import jdk.internal.jmod.JmodFile;
  89 import jdk.internal.jmod.JmodFile.Section;
  90 import jdk.internal.joptsimple.BuiltinHelpFormatter;
  91 import jdk.internal.joptsimple.NonOptionArgumentSpec;
  92 import jdk.internal.joptsimple.OptionDescriptor;
  93 import jdk.internal.joptsimple.OptionException;
  94 import jdk.internal.joptsimple.OptionParser;
  95 import jdk.internal.joptsimple.OptionSet;
  96 import jdk.internal.joptsimple.OptionSpec;
  97 import jdk.internal.joptsimple.ValueConverter;
  98 import jdk.internal.loader.ResourceHelper;
  99 import jdk.internal.module.ModuleHashes;
 100 import jdk.internal.module.ModuleHashesBuilder;
 101 import jdk.internal.module.ModuleInfo;
 102 import jdk.internal.module.ModuleInfoExtender;
 103 import jdk.internal.module.ModulePath;
 104 import jdk.internal.module.ModuleResolution;
 105 import jdk.tools.jlink.internal.Utils;
 106 
 107 import static java.util.stream.Collectors.joining;
 108 
 109 /**
 110  * Implementation for the jmod tool.
 111  */
 112 public class JmodTask {
 113 
 114     static class CommandException extends RuntimeException {
 115         private static final long serialVersionUID = 0L;
 116         boolean showUsage;
 117 
 118         CommandException(String key, Object... args) {
 119             super(getMessageOrKey(key, args));
 120         }


 769             public void accept(JarEntry je) {
 770                 try (InputStream in = jarfile.getInputStream(je)) {
 771                     out.writeEntry(in, Section.CLASSES, je.getName());
 772                 } catch (IOException e) {
 773                     throw new UncheckedIOException(e);
 774                 }
 775             }
 776             @Override
 777             public boolean test(JarEntry je) {
 778                 String name = je.getName();
 779                 // ## no support for excludes. Is it really needed?
 780                 return !name.endsWith(MODULE_INFO) && !je.isDirectory();
 781             }
 782         }
 783     }
 784 
 785     /**
 786      * Compute and record hashes
 787      */
 788     private class Hasher {
 789         final ModuleHashesBuilder hashesBuilder;
 790         final Map<String, Path> moduleNameToPath;
 791         final Set<String> modules;

 792         final boolean dryrun = options.dryrun;
 793         Hasher(ModuleFinder finder) {

 794             // Determine the modules that matches the pattern {@code modulesToHash}
 795             this.modules = finder.findAll().stream()
 796                 .map(mref -> mref.descriptor().name())
 797                 .filter(mn -> options.modulesToHash.matcher(mn).find())
 798                 .collect(Collectors.toSet());
 799 
 800             // a map from a module name to Path of the packaged module
 801             this.moduleNameToPath = finder.findAll().stream()
 802                 .map(mref -> mref.descriptor().name())
 803                 .filter(modules::contains)
 804                 .collect(Collectors.toMap(Function.identity(), mn -> moduleToPath(finder, mn)));
 805 
 806             // get a resolved module graph
 807             Configuration config = null;
 808             try {
 809                 config = Configuration.empty()
 810                     .resolveRequires(ModuleFinder.ofSystem(), finder, modules);
 811             } catch (ResolutionException e) {
 812                 warning("warn.module.resolution.fail", e.getMessage());
 813             }
 814 
 815             // ModuleHashesBuilder is constructed with the moduleNameToPath arguments
 816             // so that creating java.base.jmod will compute the hash from this
 817             // explicit path rather than the location from the resolved module
 818             this.hashesBuilder = config != null
 819                 ? new ModuleHashesBuilder(config, moduleNameToPath) : null;
 820         }
 821 
 822         /**
 823          * This method is for jmod hash command.
 824          *
 825          * Identify the base modules in the module graph, i.e. no outgoing edge
 826          * to any of the modules to be hashed.
 827          *
 828          * For each base module M, compute the hashes of all modules that depend
 829          * upon M directly or indirectly.  Then update M's module-info.class
 830          * to record the hashes.
 831          */
 832         boolean run() {
 833             if (hashesBuilder == null)
 834                 return false;
 835 
 836             if (dryrun) {































 837                 out.println("Dry run:");
 838             }
 839 
 840             hashesBuilder.computeHashes(modules).entrySet().forEach(e -> {




 841                 String mn = e.getKey();
 842                 ModuleHashes hashes = e.getValue();



 843                 if (dryrun) {
 844                     out.format("%s%n", mn);
 845                     hashes.names().stream()
 846                           .sorted()
 847                           .forEach(name -> out.format("  hashes %s %s %s%n",
 848                               name, hashes.algorithm(), toHex(hashes.hashFor(name))));
 849                 } else {
 850                     try {
 851                         updateModuleInfo(mn, hashes);
 852                     } catch (IOException ex) {
 853                         throw new UncheckedIOException(ex);
 854                     }
 855                 }
 856             });
 857             return true;
 858         }
 859 
 860         /**
 861          * Compute hashes of the specified module.
 862          *
 863          * It records the hashing modules that depend upon the specified
 864          * module directly or indirectly.
 865          */
 866         ModuleHashes computeHashes(String name) {
 867             if (hashesBuilder == null)
 868                 return null;
 869 
 870             return hashesBuilder.computeHashes(Set.of(name)).get(name);







































































 871         }
 872 
 873         /**
 874          * Reads the given input stream of module-info.class and write
 875          * the extended module-info.class with the given ModuleHashes
 876          *
 877          * @param in       InputStream of module-info.class
 878          * @param out      OutputStream to write the extended module-info.class
 879          * @param hashes   ModuleHashes
 880          */
 881         private void recordHashes(InputStream in, OutputStream out, ModuleHashes hashes)
 882             throws IOException
 883         {
 884             ModuleInfoExtender extender = ModuleInfoExtender.newExtender(in);
 885             extender.hashes(hashes);
 886             extender.write(out);
 887         }
 888 
 889         private void updateModuleInfo(String name, ModuleHashes moduleHashes)
 890             throws IOException


 950                  JmodOutputStream jos = JmodOutputStream.newOutputStream(tempTarget))
 951             {
 952                 jf.stream().forEach(e -> {
 953                     try (InputStream in = jf.getInputStream(e.section(), e.name())) {
 954                         if (e.name().equals(MODULE_INFO)) {
 955                             // replace module-info.class
 956                             ModuleInfoExtender extender =
 957                                 ModuleInfoExtender.newExtender(in);
 958                             extender.hashes(moduleHashes);
 959                             jos.writeEntry(extender.toByteArray(), e.section(), e.name());
 960                         } else {
 961                             jos.writeEntry(in, e);
 962                         }
 963                     } catch (IOException x) {
 964                         throw new UncheckedIOException(x);
 965                     }
 966                 });
 967             }
 968         }
 969 
 970         private Path moduleToPath(ModuleFinder moduleFinder, String name) {
 971             ModuleReference mref = moduleFinder.find(name).orElseThrow(
 972                 () -> new InternalError("Selected module " + name + " not on module path"));
 973 
 974             URI uri = mref.location().get();
 975             Path path = Paths.get(uri);
 976             String fn = path.getFileName().toString();
 977             if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
 978                 throw new InternalError(path + " is not a modular JAR or jmod file");
 979             }
 980             return path;
 981         }
 982     }
 983 
 984     static class ClassPathConverter implements ValueConverter<Path> {
 985         static final ValueConverter<Path> INSTANCE = new ClassPathConverter();
 986 
 987         @Override
 988         public Path convert(String value) {
 989             try {
 990                 Path path = CWD.resolve(value);


< prev index next >