Closed jamesfredley closed 1 month ago
Example decompiled domain classes with inheritance:
Gradle Artifact Transforms rough POC based on:
this rough POC currently puts the Verifier class files from Gradle's copy of Groovy (3.0.21) into the Groovy jar. It should use alternate versions compiled from the latest Groovy 4.0.x.
import org.gradle.api.artifacts.transform.InputArtifact
import org.gradle.api.artifacts.transform.TransformAction
import org.gradle.api.artifacts.transform.TransformOutputs
import org.gradle.api.artifacts.transform.TransformParameters
import org.gradle.api.file.ArchiveOperations
import org.gradle.api.file.FileSystemLocation
import org.gradle.api.provider.Provider
import java.util.jar.JarEntry
import java.util.jar.JarInputStream
import java.util.jar.JarOutputStream
import javax.inject.Inject
import static org.gradle.api.artifacts.type.ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE
buildscript {
repositories {
maven { url "https://repo.grails.org/grails/core" }
maven { url "https://plugins.gradle.org/m2/" }
mavenLocal()
}
dependencies {
classpath "javax.inject:javax.inject:1"
}
}
configurations.named("compileClasspath") {
attributes {
attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, "transformed-jar")
}
}
configurations.named("runtimeClasspath") {
attributes {
attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, "transformed-jar")
}
}
dependencies {
registerTransform(JavaModuleTransform) {
from.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, "jar")
to.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, "transformed-jar")
}
}
abstract class JavaModuleTransform implements TransformAction<TransformParameters.None> {
@InputArtifact
abstract Provider<FileSystemLocation> getInputArtifact()
@Inject
abstract ArchiveOperations getArchiveOperations()
private List<String> replaceFiles = ['org/codehaus/groovy/classgen/Verifier.class',
'org/codehaus/groovy/classgen/Verifier$1.class',
'org/codehaus/groovy/classgen/Verifier$2.class',
'org/codehaus/groovy/classgen/Verifier$3.class',
'org/codehaus/groovy/classgen/Verifier$4.class',
'org/codehaus/groovy/classgen/Verifier$5.class',
'org/codehaus/groovy/classgen/Verifier$6.class',
'org/codehaus/groovy/classgen/Verifier$7.class',
'org/codehaus/groovy/classgen/Verifier$8.class',
'org/codehaus/groovy/classgen/Verifier$9.class',
'org/codehaus/groovy/classgen/Verifier$10.class',
'org/codehaus/groovy/classgen/Verifier$11.class',
'org/codehaus/groovy/classgen/Verifier$12.class',
'org/codehaus/groovy/classgen/Verifier$13.class',
'org/codehaus/groovy/classgen/Verifier$14.class',
'org/codehaus/groovy/classgen/Verifier$15.class',
'org/codehaus/groovy/classgen/Verifier$DefaultArgsAction.class',
'org/codehaus/groovy/classgen/Verifier$SwapInitStatement$SwapInitInstruction.class',
'org/codehaus/groovy/classgen/Verifier$SwapInitStatement.class',
]
void writeEntry(JarOutputStream output, JarEntry jarEntry, JarInputStream input) {
def jarEntryName = jarEntry.toString()
if(jarEntryName in replaceFiles ) {
output.putNextEntry(new JarEntry(jarEntryName))
output.write(this.class.getResourceAsStream(
jarEntryName).readAllBytes())
} else {
output.putNextEntry(jarEntry)
output.write(input.readAllBytes())
}
output.closeEntry()
}
@Override
void transform(TransformOutputs outputs) {
def jarName = inputArtifact.get().asFile.name
if (!(jarName ==~ /^groovy-[0-9].[0-9].[0-9][0-9].jar$/)) {
outputs.file(inputArtifact)
} else {
def originalJar = getInputArtifact().get().asFile
def originalJarName = originalJar.name.substring(0, originalJar.name.lastIndexOf('.'))
def target = outputs.file(jarName.replace(".jar", "-transformed.jar"))
new JarInputStream(new FileInputStream(originalJar)).withStream { input ->
new JarOutputStream(new FileOutputStream(target), input.manifest).withStream { output ->
var jarEntry = input.nextJarEntry
while (jarEntry != null) {
writeEntry(output, jarEntry, input)
output.closeEntry()
jarEntry = input.nextJarEntry
}
output.closeEntry()
}
}
}
}
}
This is a blocker for Grails 7 release.
Opened upstream groovy ticket: https://issues.apache.org/jira/browse/GROOVY-11508
Domain inheritance can be solved in at least one of three ways.
findByNameAndAge("james", 56)
Groovy-5106 (domain inheritance) issues: https://issues.apache.org/jira/browse/GROOVY-5106
The interface GormEntity cannot be implemented more than once with different arguments: org.grails.datastore.gorm.GormEntity<grails.gorm.tests.XXX> and org.grails.datastore.gorm.GormEntity<grails.gorm.tests.XXX>
This also applies to other projects with inheritance tests https://github.com/search?q=org%3Agrails%20%2F*extends&type=code
https://github.com/search?q=org%3Agrails+%2F%2F%40Entity&type=code
I dug a bit more into a generated domain with a parent domain and each will have two generic traits with one trait implementing a generic interface and then the generic type parameter is used in many methods in GormEntity, which then forks out in a number of directions. Here is an very simplified view of what that looks like. At least the first two traits and first interface will generate "The interface XXX cannot be implemented more than once with different arguments" error when the child extends the parent. The compiler stops at the first one it bumps into.