2929import java .io .IOException ;
3030import java .io .InputStream ;
3131import java .util .Enumeration ;
32+ import java .util .HashMap ;
3233import java .util .List ;
34+ import java .util .Locale ;
3335import java .util .Map ;
36+ import java .util .Set ;
3437import java .util .function .Function ;
3538import java .util .jar .JarEntry ;
3639import java .util .jar .JarFile ;
3740import java .util .jar .JarOutputStream ;
41+ import java .util .regex .Pattern ;
3842import java .util .stream .Stream ;
3943
4044import static java .util .Map .entry ;
4145
4246@ CacheableTransform
4347public abstract class HdfsClassPatcher implements TransformAction <HdfsClassPatcher .Parameters > {
4448
45- record JarPatchers (String artifactName , Map <String , Function <ClassWriter , ClassVisitor >> jarPatchers ) {}
49+ record JarPatchers (String artifactTag , Pattern artifactPattern , Map <String , Function <ClassWriter , ClassVisitor >> jarPatchers ) {}
4650
4751 static final List <JarPatchers > allPatchers = List .of (
4852 new JarPatchers (
4953 "hadoop-common" ,
54+ Pattern .compile ("hadoop-common-(?!.*tests)" ),
5055 Map .ofEntries (
5156 entry ("org/apache/hadoop/util/ShutdownHookManager.class" , ShutdownHookManagerPatcher ::new ),
5257 entry ("org/apache/hadoop/util/Shell.class" , ShellPatcher ::new ),
@@ -55,6 +60,7 @@ record JarPatchers(String artifactName, Map<String, Function<ClassWriter, ClassV
5560 ),
5661 new JarPatchers (
5762 "hadoop-client-api" ,
63+ Pattern .compile ("hadoop-client-api.*" ),
5864 Map .ofEntries (
5965 entry ("org/apache/hadoop/util/ShutdownHookManager.class" , ShutdownHookManagerPatcher ::new ),
6066 entry ("org/apache/hadoop/util/Shell.class" , ShellPatcher ::new ),
@@ -81,14 +87,30 @@ public void transform(@NotNull TransformOutputs outputs) {
8187 File inputFile = getInputArtifact ().get ().getAsFile ();
8288
8389 List <String > matchingArtifacts = getParameters ().getMatchingArtifacts ();
84- if (matchingArtifacts .isEmpty () == false
85- && matchingArtifacts .stream ().noneMatch (supported -> inputFile .getName ().contains (supported ))) {
90+ List <JarPatchers > patchersToApply = allPatchers .stream ().filter (jp -> matchingArtifacts .contains (jp .artifactTag ()) &&
91+ jp .artifactPattern ().asMatchPredicate ().test (inputFile .getName ())).toList ();
92+ if (patchersToApply .isEmpty ()) {
8693 outputs .file (getInputArtifact ());
8794 } else {
88- Stream <JarPatchers > patchersToApply = allPatchers .stream ().filter (jp -> matchingArtifacts .contains (jp .artifactName ()));
8995 patchersToApply .forEach (patchers -> {
96+ System .out .println ("Patching " + inputFile .getName ());
97+
98+ Map <String , Function <ClassWriter , ClassVisitor >> jarPatchers = new HashMap <>(patchers .jarPatchers ());
9099 File outputFile = outputs .file (inputFile .getName ().replace (".jar" , "-patched.jar" ));
91- patchJar (inputFile , outputFile , patchers .jarPatchers ());
100+
101+ patchJar (inputFile , outputFile , jarPatchers );
102+
103+ if (jarPatchers .isEmpty () == false ) {
104+ throw new IllegalArgumentException (
105+ String .format (
106+ Locale .ROOT ,
107+ "error patching [%s] with [%s]: the jar does not contain [%s]" ,
108+ inputFile .getName (),
109+ patchers .artifactPattern ().toString (),
110+ String .join (", " , jarPatchers .keySet ())
111+ )
112+ );
113+ }
92114 });
93115 }
94116 }
@@ -102,7 +124,7 @@ private static void patchJar(File inputFile, File outputFile, Map<String, Functi
102124 // Add the entry to the new JAR file
103125 jos .putNextEntry (new JarEntry (entryName ));
104126
105- Function <ClassWriter , ClassVisitor > classPatcher = jarPatchers .get (entryName );
127+ Function <ClassWriter , ClassVisitor > classPatcher = jarPatchers .remove (entryName );
106128 if (classPatcher != null ) {
107129 byte [] classToPatch = jarFile .getInputStream (entry ).readAllBytes ();
108130
0 commit comments