projects/guix·blob python-team · refs

297 lines · 12.8 KiB

1From a52c4ef44c0553a399a8a47e528db92e3bf51c6c Mon Sep 17 00:00:00 2001
2From: Alan Bateman <[email protected]>
3Date: Wed, 29 Apr 2020 08:38:28 +0100
4Subject: [PATCH] 8243666: ModuleHashes attribute generated for JMOD and JAR
5 files depends on timestamps
6See: https://bugs.openjdk.org/browse/JDK-8243666
7
8Reviewed-by: mchung
9---
10
11diff -ru orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java
12--- orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java 1970-01-01 01:00:01.000000000 +0100
13+++ jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java 2022-04-12 16:47:15.690423653 +0200
14@@ -27,9 +27,8 @@
15
16 import java.io.PrintStream;
17 import java.lang.module.Configuration;
18+import java.lang.module.ModuleReference;
19 import java.lang.module.ResolvedModule;
20-import java.net.URI;
21-import java.nio.file.Path;
22 import java.nio.file.Paths;
23 import java.util.ArrayDeque;
24 import java.util.Collections;
25@@ -40,7 +39,6 @@
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.function.Consumer;
29-import java.util.function.Function;
30 import java.util.stream.Stream;
31 import static java.util.stream.Collectors.*;
32
33@@ -116,27 +114,17 @@
34 mods.addAll(ns);
35
36 if (!ns.isEmpty()) {
37- Map<String, Path> moduleToPath = ns.stream()
38- .collect(toMap(Function.identity(), this::moduleToPath));
39- hashes.put(mn, ModuleHashes.generate(moduleToPath, "SHA-256"));
40+ Set<ModuleReference> mrefs = ns.stream()
41+ .map(name -> configuration.findModule(name)
42+ .orElseThrow(InternalError::new))
43+ .map(ResolvedModule::reference)
44+ .collect(toSet());
45+ hashes.put(mn, ModuleHashes.generate(mrefs, "SHA-256"));
46 }
47 });
48 return hashes;
49 }
50
51- private Path moduleToPath(String name) {
52- ResolvedModule rm = configuration.findModule(name).orElseThrow(
53- () -> new InternalError("Selected module " + name + " not on module path"));
54-
55- URI uri = rm.reference().location().get();
56- Path path = Paths.get(uri);
57- String fn = path.getFileName().toString();
58- if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
59- throw new UnsupportedOperationException(path + " is not a modular JAR or jmod file");
60- }
61- return path;
62- }
63-
64 /*
65 * Utility class
66 */
67diff -ru orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java
68--- orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java 1970-01-01 01:00:01.000000000 +0100
69+++ jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java 2022-04-12 16:58:05.639985936 +0200
70@@ -26,17 +26,21 @@
71 package jdk.internal.module;
72
73 import java.io.IOException;
74+import java.io.InputStream;
75 import java.io.UncheckedIOException;
76-import java.nio.ByteBuffer;
77-import java.nio.channels.FileChannel;
78-import java.nio.file.Path;
79+import java.lang.module.ModuleReader;
80+import java.lang.module.ModuleReference;
81+import java.nio.charset.StandardCharsets;
82 import java.security.MessageDigest;
83 import java.security.NoSuchAlgorithmException;
84+import java.util.Arrays;
85 import java.util.Collections;
86 import java.util.HashMap;
87 import java.util.Map;
88 import java.util.Objects;
89 import java.util.Set;
90+import java.util.TreeMap;
91+import java.util.function.Supplier;
92
93 /**
94 * The result of hashing the contents of a number of module artifacts.
95@@ -60,8 +64,8 @@
96 * @param algorithm the algorithm used to create the hashes
97 * @param nameToHash the map of module name to hash value
98 */
99- public ModuleHashes(String algorithm, Map<String, byte[]> nameToHash) {
100- this.algorithm = algorithm;
101+ ModuleHashes(String algorithm, Map<String, byte[]> nameToHash) {
102+ this.algorithm = Objects.requireNonNull(algorithm);
103 this.nameToHash = Collections.unmodifiableMap(nameToHash);
104 }
105
106@@ -95,54 +99,125 @@
107 }
108
109 /**
110- * Computes the hash for the given file with the given message digest
111- * algorithm.
112+ * Computes a hash from the names and content of a module.
113 *
114+ * @param reader the module reader to access the module content
115+ * @param algorithm the name of the message digest algorithm to use
116+ * @return the hash
117+ * @throws IllegalArgumentException if digest algorithm is not supported
118 * @throws UncheckedIOException if an I/O error occurs
119 * @throws RuntimeException if the algorithm is not available
120 */
121- public static byte[] computeHash(Path file, String algorithm) {
122+ private static byte[] computeHash(ModuleReader reader, String algorithm) {
123+ MessageDigest md;
124 try {
125- MessageDigest md = MessageDigest.getInstance(algorithm);
126-
127- // Ideally we would just mmap the file but this consumes too much
128- // memory when jlink is running concurrently on very large jmods
129- try (FileChannel fc = FileChannel.open(file)) {
130- ByteBuffer bb = ByteBuffer.allocate(32*1024);
131- while (fc.read(bb) > 0) {
132- bb.flip();
133- md.update(bb);
134- assert bb.remaining() == 0;
135- bb.clear();
136- }
137- }
138-
139- return md.digest();
140+ md = MessageDigest.getInstance(algorithm);
141 } catch (NoSuchAlgorithmException e) {
142- throw new RuntimeException(e);
143+ throw new IllegalArgumentException(e);
144+ }
145+ try {
146+ byte[] buf = new byte[32*1024];
147+ reader.list().sorted().forEach(rn -> {
148+ md.update(rn.getBytes(StandardCharsets.UTF_8));
149+ try (InputStream in = reader.open(rn).orElseThrow(java.util.NoSuchElementException::new)) {
150+ int n;
151+ while ((n = in.read(buf)) > 0) {
152+ md.update(buf, 0, n);
153+ }
154+ } catch (IOException ioe) {
155+ throw new UncheckedIOException(ioe);
156+ }
157+ });
158 } catch (IOException ioe) {
159 throw new UncheckedIOException(ioe);
160 }
161+ return md.digest();
162 }
163
164 /**
165- * Computes the hash for every entry in the given map, returning a
166- * {@code ModuleHashes} to encapsulate the result. The map key is
167- * the entry name, typically the module name. The map value is the file
168- * path to the entry (module artifact).
169+ * Computes a hash from the names and content of a module.
170 *
171+ * @param supplier supplies the module reader to access the module content
172+ * @param algorithm the name of the message digest algorithm to use
173+ * @return the hash
174+ * @throws IllegalArgumentException if digest algorithm is not supported
175+ * @throws UncheckedIOException if an I/O error occurs
176+ */
177+ static byte[] computeHash(Supplier<ModuleReader> supplier, String algorithm) {
178+ try (ModuleReader reader = supplier.get()) {
179+ return computeHash(reader, algorithm);
180+ } catch (IOException ioe) {
181+ throw new UncheckedIOException(ioe);
182+ }
183+ }
184+
185+ /**
186+ * Computes the hash from the names and content of a set of modules. Returns
187+ * a {@code ModuleHashes} to encapsulate the result.
188+ * @param mrefs the set of modules
189+ * @param algorithm the name of the message digest algorithm to use
190 * @return ModuleHashes that encapsulates the hashes
191+ * @throws IllegalArgumentException if digest algorithm is not supported
192+ * @throws UncheckedIOException if an I/O error occurs
193 */
194- public static ModuleHashes generate(Map<String, Path> map, String algorithm) {
195+ static ModuleHashes generate(Set<ModuleReference> mrefs, String algorithm) {
196 Map<String, byte[]> nameToHash = new HashMap<>();
197- for (Map.Entry<String, Path> entry: map.entrySet()) {
198- String name = entry.getKey();
199- Path path = entry.getValue();
200- nameToHash.put(name, computeHash(path, algorithm));
201+ for (ModuleReference mref : mrefs) {
202+ try (ModuleReader reader = mref.open()) {
203+ byte[] hash = computeHash(reader, algorithm);
204+ nameToHash.put(mref.descriptor().name(), hash);
205+ } catch (IOException ioe) {
206+ throw new UncheckedIOException(ioe);
207+ }
208 }
209 return new ModuleHashes(algorithm, nameToHash);
210 }
211
212+ @Override
213+ public int hashCode() {
214+ int h = algorithm.hashCode();
215+ for (Map.Entry<String, byte[]> e : nameToHash.entrySet()) {
216+ h = h * 31 + e.getKey().hashCode();
217+ h = h * 31 + Arrays.hashCode(e.getValue());
218+ }
219+ return h;
220+ }
221+
222+ @Override
223+ public boolean equals(Object obj) {
224+ if (!(obj instanceof ModuleHashes))
225+ return false;
226+ ModuleHashes other = (ModuleHashes) obj;
227+ if (!algorithm.equals(other.algorithm)
228+ || nameToHash.size() != other.nameToHash.size())
229+ return false;
230+ for (Map.Entry<String, byte[]> e : nameToHash.entrySet()) {
231+ String name = e.getKey();
232+ byte[] hash = e.getValue();
233+ if (!Arrays.equals(hash, other.nameToHash.get(name)))
234+ return false;
235+ }
236+ return true;
237+ }
238+
239+ @Override
240+ public String toString() {
241+ StringBuilder sb = new StringBuilder(algorithm);
242+ sb.append(" ");
243+ nameToHash.entrySet()
244+ .stream()
245+ .sorted(Map.Entry.comparingByKey())
246+ .forEach(e -> {
247+ sb.append(e.getKey());
248+ sb.append("=");
249+ byte[] ba = e.getValue();
250+ for (byte b : ba) {
251+ sb.append(String.format("%02x", b & 0xff));
252+ }
253+ });
254+ return sb.toString();
255+ }
256+
257 /**
258 * This is used by jdk.internal.module.SystemModules class
259 * generated at link time.
260diff -ru orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java
261--- orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java 1970-01-01 01:00:01.000000000 +0100
262+++ jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java 2022-04-12 16:43:12.967868689 +0200
263@@ -1,5 +1,5 @@
264 /*
265- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
266+ * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
267 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
268 *
269 * This code is free software; you can redistribute it and/or modify it
270diff -ru orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java
271--- orig/jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java 1970-01-01 01:00:01.000000000 +0100
272+++ jdk-3cc80be736f2/jdk/src/java.base/share/classes/jdk/internal/module/ModuleReferences.java 2022-04-12 16:43:12.971868797 +0200
273@@ -1,5 +1,5 @@
274 /*
275- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
276+ * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
277 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
278 *
279 * This code is free software; you can redistribute it and/or modify it
280@@ -95,7 +95,7 @@
281 Path file) {
282 URI uri = file.toUri();
283 Supplier<ModuleReader> supplier = () -> new JarModuleReader(file, uri);
284- HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
285+ HashSupplier hasher = (a) -> ModuleHashes.computeHash(supplier, a);
286 return newModule(attrs, uri, supplier, patcher, hasher);
287 }
288
289@@ -105,7 +105,7 @@
290 static ModuleReference newJModModule(ModuleInfo.Attributes attrs, Path file) {
291 URI uri = file.toUri();
292 Supplier<ModuleReader> supplier = () -> new JModModuleReader(file, uri);
293- HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
294+ HashSupplier hasher = (a) -> ModuleHashes.computeHash(supplier, a);
295 return newModule(attrs, uri, supplier, null, hasher);
296 }
297