|
9 | 9 |
|
10 | 10 | package org.elasticsearch.gradle.internal.dependencies.patches.hdfs; |
11 | 11 |
|
| 12 | +import org.elasticsearch.gradle.internal.dependencies.patches.PatcherInfo; |
| 13 | +import org.elasticsearch.gradle.internal.dependencies.patches.Utils; |
12 | 14 | import org.gradle.api.artifacts.transform.CacheableTransform; |
13 | 15 | import org.gradle.api.artifacts.transform.InputArtifact; |
14 | 16 | import org.gradle.api.artifacts.transform.TransformAction; |
|
20 | 22 | import org.gradle.api.tasks.Input; |
21 | 23 | import org.gradle.api.tasks.Optional; |
22 | 24 | import org.jetbrains.annotations.NotNull; |
23 | | -import org.objectweb.asm.ClassReader; |
24 | | -import org.objectweb.asm.ClassVisitor; |
25 | | -import org.objectweb.asm.ClassWriter; |
26 | 25 |
|
27 | 26 | import java.io.File; |
28 | | -import java.io.FileOutputStream; |
29 | | -import java.io.IOException; |
30 | | -import java.io.InputStream; |
31 | | -import java.util.Enumeration; |
32 | | -import java.util.HashMap; |
33 | 27 | import java.util.List; |
34 | | -import java.util.Locale; |
35 | | -import java.util.Map; |
36 | | -import java.util.function.Function; |
37 | | -import java.util.jar.JarEntry; |
38 | | -import java.util.jar.JarFile; |
39 | | -import java.util.jar.JarOutputStream; |
40 | 28 | import java.util.regex.Pattern; |
41 | 29 |
|
42 | | -import static java.util.Map.entry; |
43 | | -import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES; |
44 | | -import static org.objectweb.asm.ClassWriter.COMPUTE_MAXS; |
| 30 | +import static org.elasticsearch.gradle.internal.dependencies.patches.PatcherInfo.classPatcher; |
45 | 31 |
|
46 | 32 | @CacheableTransform |
47 | 33 | public abstract class HdfsClassPatcher implements TransformAction<HdfsClassPatcher.Parameters> { |
48 | 34 |
|
49 | | - record JarPatchers(String artifactTag, Pattern artifactPattern, Map<String, Function<ClassWriter, ClassVisitor>> jarPatchers) {} |
| 35 | + record JarPatchers(String artifactTag, Pattern artifactPattern, List<PatcherInfo> jarPatchers) {} |
50 | 36 |
|
51 | 37 | static final List<JarPatchers> allPatchers = List.of( |
52 | 38 | new JarPatchers( |
53 | 39 | "hadoop-common", |
54 | 40 | Pattern.compile("hadoop-common-(?!.*tests)"), |
55 | | - Map.ofEntries( |
56 | | - entry("org/apache/hadoop/util/ShutdownHookManager.class", ShutdownHookManagerPatcher::new), |
57 | | - entry("org/apache/hadoop/util/Shell.class", ShellPatcher::new), |
58 | | - entry("org/apache/hadoop/security/UserGroupInformation.class", SubjectGetSubjectPatcher::new) |
| 41 | + List.of( |
| 42 | + classPatcher( |
| 43 | + "org/apache/hadoop/util/ShutdownHookManager.class", |
| 44 | + "90641e0726fc9372479728ef9b7ae2be20fb7ab4cddd4938e55ffecadddd4d94", |
| 45 | + ShutdownHookManagerPatcher::new |
| 46 | + ), |
| 47 | + classPatcher( |
| 48 | + "org/apache/hadoop/util/Shell.class", |
| 49 | + "8837c7f3eeda3f658fc3d6595f18e77a4558220ff0becdf3e175fa4397a6fd0c", |
| 50 | + ShellPatcher::new |
| 51 | + ), |
| 52 | + classPatcher( |
| 53 | + "org/apache/hadoop/security/UserGroupInformation.class", |
| 54 | + "3c34bbc2716a6c8f4e356e78550599b0a4f01882712b4f7787d032fb10527212", |
| 55 | + SubjectGetSubjectPatcher::new |
| 56 | + ) |
59 | 57 | ) |
60 | 58 | ), |
61 | 59 | new JarPatchers( |
62 | 60 | "hadoop-client-api", |
63 | 61 | Pattern.compile("hadoop-client-api.*"), |
64 | | - Map.ofEntries( |
65 | | - entry("org/apache/hadoop/util/ShutdownHookManager.class", ShutdownHookManagerPatcher::new), |
66 | | - entry("org/apache/hadoop/util/Shell.class", ShellPatcher::new), |
67 | | - entry("org/apache/hadoop/security/UserGroupInformation.class", SubjectGetSubjectPatcher::new), |
68 | | - entry("org/apache/hadoop/security/authentication/client/KerberosAuthenticator.class", SubjectGetSubjectPatcher::new) |
| 62 | + List.of( |
| 63 | + classPatcher( |
| 64 | + "org/apache/hadoop/util/ShutdownHookManager.class", |
| 65 | + "90641e0726fc9372479728ef9b7ae2be20fb7ab4cddd4938e55ffecadddd4d94", |
| 66 | + ShutdownHookManagerPatcher::new |
| 67 | + ), |
| 68 | + classPatcher( |
| 69 | + "org/apache/hadoop/util/Shell.class", |
| 70 | + "8837c7f3eeda3f658fc3d6595f18e77a4558220ff0becdf3e175fa4397a6fd0c", |
| 71 | + ShellPatcher::new |
| 72 | + ), |
| 73 | + classPatcher( |
| 74 | + "org/apache/hadoop/security/UserGroupInformation.class", |
| 75 | + "3c34bbc2716a6c8f4e356e78550599b0a4f01882712b4f7787d032fb10527212", |
| 76 | + SubjectGetSubjectPatcher::new |
| 77 | + ), |
| 78 | + classPatcher( |
| 79 | + "org/apache/hadoop/security/authentication/client/KerberosAuthenticator.class", |
| 80 | + "6bab26c1032a38621c20050ec92067226d1d67972d0d370e412ca25f1df96b76", |
| 81 | + SubjectGetSubjectPatcher::new |
| 82 | + ) |
69 | 83 | ) |
70 | 84 | ) |
71 | 85 | ); |
@@ -95,55 +109,9 @@ public void transform(@NotNull TransformOutputs outputs) { |
95 | 109 | } else { |
96 | 110 | patchersToApply.forEach(patchers -> { |
97 | 111 | System.out.println("Patching " + inputFile.getName()); |
98 | | - |
99 | | - Map<String, Function<ClassWriter, ClassVisitor>> jarPatchers = new HashMap<>(patchers.jarPatchers()); |
100 | 112 | File outputFile = outputs.file(inputFile.getName().replace(".jar", "-patched.jar")); |
101 | | - |
102 | | - patchJar(inputFile, outputFile, jarPatchers); |
103 | | - |
104 | | - if (jarPatchers.isEmpty() == false) { |
105 | | - throw new IllegalArgumentException( |
106 | | - String.format( |
107 | | - Locale.ROOT, |
108 | | - "error patching [%s] with [%s]: the jar does not contain [%s]", |
109 | | - inputFile.getName(), |
110 | | - patchers.artifactPattern().toString(), |
111 | | - String.join(", ", jarPatchers.keySet()) |
112 | | - ) |
113 | | - ); |
114 | | - } |
| 113 | + Utils.patchJar(inputFile, outputFile, patchers.jarPatchers()); |
115 | 114 | }); |
116 | 115 | } |
117 | 116 | } |
118 | | - |
119 | | - private static void patchJar(File inputFile, File outputFile, Map<String, Function<ClassWriter, ClassVisitor>> jarPatchers) { |
120 | | - try (JarFile jarFile = new JarFile(inputFile); JarOutputStream jos = new JarOutputStream(new FileOutputStream(outputFile))) { |
121 | | - Enumeration<JarEntry> entries = jarFile.entries(); |
122 | | - while (entries.hasMoreElements()) { |
123 | | - JarEntry entry = entries.nextElement(); |
124 | | - String entryName = entry.getName(); |
125 | | - // Add the entry to the new JAR file |
126 | | - jos.putNextEntry(new JarEntry(entryName)); |
127 | | - |
128 | | - Function<ClassWriter, ClassVisitor> classPatcher = jarPatchers.remove(entryName); |
129 | | - if (classPatcher != null) { |
130 | | - byte[] classToPatch = jarFile.getInputStream(entry).readAllBytes(); |
131 | | - |
132 | | - ClassReader classReader = new ClassReader(classToPatch); |
133 | | - ClassWriter classWriter = new ClassWriter(classReader, COMPUTE_FRAMES | COMPUTE_MAXS); |
134 | | - classReader.accept(classPatcher.apply(classWriter), 0); |
135 | | - |
136 | | - jos.write(classWriter.toByteArray()); |
137 | | - } else { |
138 | | - // Read the entry's data and write it to the new JAR |
139 | | - try (InputStream is = jarFile.getInputStream(entry)) { |
140 | | - is.transferTo(jos); |
141 | | - } |
142 | | - } |
143 | | - jos.closeEntry(); |
144 | | - } |
145 | | - } catch (IOException ex) { |
146 | | - throw new RuntimeException(ex); |
147 | | - } |
148 | | - } |
149 | 117 | } |
0 commit comments