Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mergeGroovyExtensionModules() not working with Groovy 2.5+ #779

Merged
merged 1 commit into from
Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/docs/changes/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Change Log
## v7.1.3 (unreleased)
* The GroovyExtensionModuleTransformer now also works for Groovy 2.5+.

## v7.1.2 (2021-12-28)
* Upgrade log4j to 2.17.1 due to CVE-2021-45105 and CVE-2021-44832

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,25 @@ import org.gradle.api.file.FileTreeElement
/**
* Modified from eu.appsatori.gradle.fatjar.tasks.PrepareFiles.groovy
* <p>
* Resource transformer that merges Groovy extension module descriptor files into a single file. If there are several
* META-INF/services/org.codehaus.groovy.runtime.ExtensionModule resources spread across many JARs the individual
* entries will all be merged into a single META-INF/services/org.codehaus.groovy.runtime.ExtensionModule resource
* Resource transformer that merges Groovy extension module descriptor files into a single file.
* Groovy extension module descriptor files have the name org.codehaus.groovy.runtime.ExtensionModule
* and live in the META-INF/services (Groovy up to 2.4) or META-INF/groovy (Groovy 2.5+) directory.
* See https://issues.apache.org/jira/browse/GROOVY-8480 for more details of the change.
*
* If there are several descriptor files spread across many JARs the individual
* entries will be merged into a single descriptor file which will be
* packaged into the resultant JAR produced by the shadowing process.
* It will live in the legacy directory (META-INF/services) if all of the processed descriptor
* files came from the legacy location, otherwise it will be written into the now standard location (META-INF/groovy).
* Note that certain JDK9+ tooling will break when using the legacy location.
*/
@CacheableTransformer
class GroovyExtensionModuleTransformer implements Transformer {

private static final GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATH =
private static final GROOVY_LEGACY_EXTENSION_MODULE_DESCRIPTOR_PATH =
"META-INF/services/org.codehaus.groovy.runtime.ExtensionModule"
private static final GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATH =
"META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule"

private static final MODULE_NAME_KEY = 'moduleName'
private static final MODULE_VERSION_KEY = 'moduleVersion'
Expand All @@ -47,10 +56,16 @@ class GroovyExtensionModuleTransformer implements Transformer {
private static final MERGED_MODULE_VERSION = '1.0.0'

private final Properties module = new Properties()
private boolean legacy = true // default to Groovy 2.4 or earlier

@Override
boolean canTransformResource(FileTreeElement element) {
return element.relativePath.pathString == GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATH
def path = element.relativePath.pathString
if (path == GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATH) {
legacy = false // Groovy 2.5+
return true
}
return path == GROOVY_LEGACY_EXTENSION_MODULE_DESCRIPTOR_PATH
}

@Override
Expand Down Expand Up @@ -95,7 +110,7 @@ class GroovyExtensionModuleTransformer implements Transformer {

@Override
void modifyOutputStream(ZipOutputStream os, boolean preserveFileTimestamps) {
ZipEntry entry = new ZipEntry(GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATH)
ZipEntry entry = new ZipEntry(legacy ? GROOVY_LEGACY_EXTENSION_MODULE_DESCRIPTOR_PATH : GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATH)
entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time)
os.putNextEntry(entry)
IOUtil.copy(toInputStream(module), os)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,51 @@ staticExtensionClasses=com.acme.bar.SomeStaticExtension'''.stripIndent()).write(
assert props.getProperty('staticExtensionClasses') == 'com.acme.foo.FooStaticExtension,com.acme.bar.SomeStaticExtension'
}

def 'Groovy extension module transformer works for Groovy2_5+'() {
given:
def one = buildJar('one.jar')
.insertFile('META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule',
'''moduleName=foo
moduleVersion=1.0.5
extensionClasses=com.acme.foo.FooExtension,com.acme.foo.BarExtension
staticExtensionClasses=com.acme.foo.FooStaticExtension'''.stripIndent()).write()

def two = buildJar('two.jar')
.insertFile('META-INF/services/org.codehaus.groovy.runtime.ExtensionModule',
'''moduleName=bar
moduleVersion=2.3.5
extensionClasses=com.acme.bar.SomeExtension,com.acme.bar.AnotherExtension
staticExtensionClasses=com.acme.bar.SomeStaticExtension'''.stripIndent()).write()

buildFile << """
import ${GroovyExtensionModuleTransformer.name}
shadowJar {
from('${escapedPath(one)}')
from('${escapedPath(two)}')
}

shadowJar {
transform(GroovyExtensionModuleTransformer)
}
""".stripIndent()

when:
run('shadowJar')

then:
output.exists()

and:
def text = getJarFileContents(output, 'META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule')
def props = new Properties()
props.load(new StringReader(text))
props.getProperty('moduleName') == 'MergedByShadowJar'
props.getProperty('moduleVersion') == '1.0.0'
props.getProperty('extensionClasses') == 'com.acme.foo.FooExtension,com.acme.foo.BarExtension,com.acme.bar.SomeExtension,com.acme.bar.AnotherExtension'
props.getProperty('staticExtensionClasses') == 'com.acme.foo.FooStaticExtension,com.acme.bar.SomeStaticExtension'
doesNotContain(output, ['META-INF/services/org.codehaus.groovy.runtime.ExtensionModule'])
}

def 'Groovy extension module transformer short syntax'() {
given:
def one = buildJar('one.jar')
Expand Down