1- @file:Suppress(" DuplicatedCode" )
2-
31package com.github.jengelman.gradle.plugins.shadow.internal
42
53import com.github.jengelman.gradle.plugins.shadow.relocation.Relocator
6- import com.github.jengelman.gradle.plugins.shadow.relocation.relocateClass
7- import com.github.jengelman.gradle.plugins.shadow.relocation.relocatePath
84import java.lang.classfile.Annotation
95import java.lang.classfile.AnnotationElement
106import java.lang.classfile.AnnotationValue
@@ -64,25 +60,34 @@ import java.lang.constant.DynamicConstantDesc
6460import java.lang.constant.MethodHandleDesc
6561import java.lang.constant.MethodTypeDesc
6662import java.lang.constant.PackageDesc
67- import java.util.regex.Pattern
68- import java.util.zip.ZipException
6963import kotlin.jvm.optionals.getOrNull
70- import org.apache.tools.zip.UnixStat
71- import org.apache.tools.zip.ZipOutputStream
7264import org.gradle.api.GradleException
7365import org.gradle.api.file.FileCopyDetails
74- import org.gradle.api.logging.Logger
7566
76- /* *
77- * Ported from ASM's Remapper and JDK's ClassRemapperImpl to use Java 24 Class-File API.
78- *
79- * @author John Engelman
80- */
81- internal class RelocatorRemapper (
67+ @Suppress(" unused" ) // Used by Multi-Release JARs for Java 24+.
68+ internal fun FileCopyDetails.remapClass (relocators : Set <Relocator >): ByteArray =
69+ file.readBytes().let { bytes ->
70+ var modified = false
71+ val remapper = RelocatorRemapper (relocators) { modified = true }
72+
73+ val newBytes =
74+ try {
75+ val classFile = ClassFile .of()
76+ val classModel = classFile.parse(bytes)
77+ val newClassDesc = remapper.mapClassDesc(classModel.thisClass().asSymbol())
78+ classFile.transformClass(classModel, newClassDesc, remapper.asClassTransform())
79+ } catch (t: Throwable ) {
80+ throw GradleException (" Error in Class-File API processing class $path " , t)
81+ }
82+
83+ // If we didn't need to change anything, keep the original bytes as-is
84+ if (modified) newBytes else bytes
85+ }
86+
87+ private class RelocatorRemapper (
8288 private val relocators : Set <Relocator >,
83- private val onModified : () -> Unit = {} ,
89+ private val onModified : () -> Unit ,
8490) {
85-
8691 fun asClassTransform (): ClassTransform = ClassTransform { clb, cle ->
8792 when (cle) {
8893 is FieldModel ->
@@ -204,42 +209,7 @@ internal class RelocatorRemapper(
204209 else ClassDesc .ofDescriptor(" L$mappedInternalName ;" )
205210 }
206211
207- private fun map (name : String , mapLiterals : Boolean = false): String {
208- // Maybe a list of types.
209- val newName = name.split(' ;' ).joinToString(" ;" ) { mapNameImpl(it, mapLiterals) }
210-
211- if (newName != name) {
212- onModified()
213- }
214- return newName
215- }
216-
217- private fun mapNameImpl (name : String , mapLiterals : Boolean ): String {
218- var newName = name
219- var prefix = " "
220- var suffix = " "
221-
222- val matcher = classPattern.matcher(newName)
223- if (matcher.matches()) {
224- prefix = matcher.group(1 ) + " L"
225- suffix = " "
226- newName = matcher.group(2 )
227- }
228-
229- for (relocator in relocators) {
230- if (mapLiterals && relocator.skipStringConstants) {
231- continue
232- } else if (relocator.canRelocateClass(newName)) {
233- return prefix + relocator.relocateClass(newName) + suffix
234- } else if (relocator.canRelocatePath(newName)) {
235- return prefix + relocator.relocatePath(newName) + suffix
236- }
237- }
238-
239- return name
240- }
241-
242- private fun asFieldTransform (): FieldTransform = FieldTransform { fb, fe ->
212+ private fun asFieldTransform () = FieldTransform { fb, fe ->
243213 when (fe) {
244214 is ConstantValueAttribute -> {
245215 val constant = fe.constant()
@@ -263,7 +233,7 @@ internal class RelocatorRemapper(
263233 }
264234 }
265235
266- private fun asMethodTransform (): MethodTransform = MethodTransform { mb, me ->
236+ private fun asMethodTransform () = MethodTransform { mb, me ->
267237 when (me) {
268238 is AnnotationDefaultAttribute ->
269239 mb.with (AnnotationDefaultAttribute .of(mapAnnotationValue(me.defaultValue())))
@@ -296,7 +266,7 @@ internal class RelocatorRemapper(
296266 }
297267 }
298268
299- private fun asCodeTransform (): CodeTransform = CodeTransform { cob, coe ->
269+ private fun asCodeTransform () = CodeTransform { cob, coe ->
300270 when (coe) {
301271 is FieldInstruction ->
302272 cob.fieldAccess(
@@ -545,58 +515,6 @@ internal class RelocatorRemapper(
545515 )
546516 }
547517
548- private companion object {
549- /* * https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html */
550- val classPattern: Pattern = Pattern .compile(" ([\\ [()BCDFIJSZ]*)?L([^;]+);?" )
551- }
552- }
553-
554- @Suppress(" unused" , " DuplicatedCode" ) // Used by Multi-Release JARs for Java 24+.
555- internal fun FileCopyDetails.remapClass (
556- relocators : Set <Relocator >,
557- zipOutStr : ZipOutputStream ,
558- preserveFileTimestamps : Boolean ,
559- lastModified : Long ,
560- logger : Logger ,
561- ) {
562- file.readBytes().let { bytes ->
563- var modified = false
564- val multiReleasePrefix = " ^META-INF/versions/\\ d+/" .toRegex().find(path)?.value.orEmpty()
565- val remapper = RelocatorRemapper (relocators) { modified = true }
566-
567- val newBytes =
568- try {
569- val classFile = ClassFile .of()
570- val classModel = classFile.parse(bytes)
571- val originalClassDesc = classModel.thisClass().asSymbol()
572- val newClassDesc = remapper.mapClassDesc(originalClassDesc)
573- classFile.transformClass(classModel, newClassDesc, remapper.asClassTransform())
574- } catch (t: Throwable ) {
575- throw GradleException (" Error in Class-File API processing class $path " , t)
576- }
577-
578- val finalBytes =
579- if (modified) {
580- newBytes
581- } else {
582- // If we didn't need to change anything, keep the original bytes as-is
583- bytes
584- }
585-
586- // Multi-release prefix was calculated earlier.
587- val newPath = path.replace(multiReleasePrefix, " " )
588- val relocatedPath = multiReleasePrefix + relocators.relocatePath(newPath)
589- try {
590- val entry =
591- zipEntry(relocatedPath, preserveFileTimestamps, lastModified) {
592- unixMode = UnixStat .FILE_FLAG or permissions.toUnixNumeric()
593- }
594- // Now we put it back on so the class file is written out with the right extension.
595- zipOutStr.putNextEntry(entry)
596- zipOutStr.write(finalBytes)
597- zipOutStr.closeEntry()
598- } catch (_: ZipException ) {
599- logger.warn(" We have a duplicate $relocatedPath in source project" )
600- }
601- }
518+ private fun map (name : String , mapLiterals : Boolean = false): String =
519+ relocators.mapName(name = name, mapLiterals = mapLiterals, onModified = onModified)
602520}
0 commit comments