diff --git a/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformerSpec.groovy b/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformerSpec.groovy
deleted file mode 100644
index abacd4498..000000000
--- a/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformerSpec.groovy
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.github.jengelman.gradle.plugins.shadow.transformers
-
-import com.github.jengelman.gradle.plugins.shadow.ShadowStats
-import com.github.jengelman.gradle.plugins.shadow.relocation.Relocator
-import com.github.jengelman.gradle.plugins.shadow.relocation.SimpleRelocator
-import org.apache.logging.log4j.core.config.plugins.processor.PluginCache
-import org.apache.tools.zip.ZipOutputStream
-import spock.lang.Specification
-
-import static java.util.Collections.singletonList
-import static org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor.PLUGIN_CACHE_FILE
-
-/**
- * @author Paul Nelson Baker
- * @since 2018-08
- * @see GitHub
- * @see LinkedIn
- */
-class Log4j2PluginsCacheFileTransformerSpec extends Specification {
-
- Log4j2PluginsCacheFileTransformer transformer
-
- void setup() {
- transformer = new Log4j2PluginsCacheFileTransformer()
- }
-
- void "should transform for a single file"() {
- when:
- transformer.transform(new TransformerContext(PLUGIN_CACHE_FILE, getResourceStream(PLUGIN_CACHE_FILE)))
-
- then:
- transformer.hasTransformedResource()
- }
-
- void "should transform"() {
- given:
- def relocators = singletonList(new SimpleRelocator())
-
- when:
- transformer.transform(new TransformerContext(PLUGIN_CACHE_FILE, getResourceStream(PLUGIN_CACHE_FILE), relocators))
-
- then:
- transformer.hasTransformedResource()
- }
-
- void "relocate classes inside DAT file"() {
- given:
- String pattern = "org.apache.logging"
- String destination = "new.location.org.apache.logging"
-
- List relocators = singletonList(new SimpleRelocator(pattern, destination))
-
- when:
- transformer.transform(new TransformerContext(PLUGIN_CACHE_FILE, getResourceStream(PLUGIN_CACHE_FILE), relocators))
-
- then:
- transformer.hasTransformedResource()
-
- when:
- // Write out to a fake jar file
- def testableZipFile = File.createTempFile("testable-zip-file-", ".jar")
- def fileOutputStream = new FileOutputStream(testableZipFile)
- def bufferedOutputStream = new BufferedOutputStream(fileOutputStream)
- def zipOutputStream = new ZipOutputStream(bufferedOutputStream)
-
- transformer.modifyOutputStream(zipOutputStream, true)
-
- zipOutputStream.close()
- bufferedOutputStream.close()
- fileOutputStream.close()
-
- then:
- // Pull the data back out and make sure it was transformed
- PluginCache cache = new PluginCache()
- def urlString = "jar:" + testableZipFile.toURI().toURL() + "!/" + PLUGIN_CACHE_FILE
- cache.loadCacheFiles(Collections.enumeration([new URL(urlString)]))
-
- cache.getCategory("lookup")["date"].className == "new.location.org.apache.logging.log4j.core.lookup.DateLookup"
-
- }
-
- InputStream getResourceStream(String resource) {
- return this.class.getClassLoader().getResourceAsStream(resource)
- }
-}
diff --git a/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerSpec.groovy b/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerSpec.groovy
deleted file mode 100644
index 72a5e40c3..000000000
--- a/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerSpec.groovy
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License") you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.github.jengelman.gradle.plugins.shadow.transformers
-
-import com.github.jengelman.gradle.plugins.shadow.transformers.PropertiesFileTransformer.MergeStrategy
-import spock.lang.Unroll
-
-import static groovy.lang.Closure.IDENTITY
-
-@Unroll
-class PropertiesFileTransformerSpec extends TransformerSpecSupport {
-
- void "Path #path #transform transformed"() {
- given:
- Transformer transformer = new PropertiesFileTransformer(objectFactory)
-
- when:
- boolean actual = transformer.canTransformResource(getFileElement(path))
-
- then:
- actual == expected
-
- where:
- path || expected
- 'foo.properties' || true
- 'foo/bar.properties' || true
- 'foo.props' || false
-
- transform = expected ? 'can be' : 'can not be'
- }
-
- void exerciseAllTransformConfigurations() {
- given:
- def element = getFileElement(path)
- Transformer transformer = new PropertiesFileTransformer(objectFactory)
- transformer.mergeStrategy.set(MergeStrategy.from(mergeStrategy))
- transformer.mergeSeparator.set(mergeSeparator)
-
- when:
- if (transformer.canTransformResource(element)) {
- transformer.transform(context(path, input1))
- transformer.transform(context(path, input2))
- }
-
- then:
- output == toMap(transformer.propertiesEntries[path])
-
- where:
- path | mergeStrategy | mergeSeparator | input1 | input2 || output
- 'f.properties' | 'first' | '' | ['foo': 'foo'] | ['foo': 'bar'] || ['foo': 'foo']
- 'f.properties' | 'latest' | '' | ['foo': 'foo'] | ['foo': 'bar'] || ['foo': 'bar']
- 'f.properties' | 'append' | ',' | ['foo': 'foo'] | ['foo': 'bar'] || ['foo': 'foo,bar']
- 'f.properties' | 'append' | ';' | ['foo': 'foo'] | ['foo': 'bar'] || ['foo': 'foo;bar']
- }
-
- void exerciseAllTransformConfigurationsWithPaths() {
- given:
- def element = getFileElement(path)
- Transformer transformer = new PropertiesFileTransformer(objectFactory)
- transformer.paths.set(paths)
- transformer.mergeStrategy.set(MergeStrategy.from('first'))
-
- when:
- if (transformer.canTransformResource(element)) {
- transformer.transform(context(path, input1))
- transformer.transform(context(path, input2))
- }
-
- then:
- output == toMap(transformer.propertiesEntries[path])
-
- where:
- path | paths | input1 | input2 || output
- 'f.properties' | ['f.properties'] | ['foo': 'foo'] | ['foo': 'bar'] || ['foo': 'foo']
- 'foo.properties' | ['.*.properties'] | ['foo': 'foo'] | ['foo': 'bar'] || ['foo': 'foo']
- 'foo.properties' | ['.*bar'] | ['foo': 'foo'] | ['foo': 'bar'] || [:]
- 'foo.properties' | [] | ['foo': 'foo'] | ['foo': 'bar'] || ['foo': 'foo']
- }
-
- void exerciseAllTransformConfigurationsWithMappings() {
- given:
- def element = getFileElement(path)
- Transformer transformer = new PropertiesFileTransformer(objectFactory)
- transformer.mappings.set(mappings)
- transformer.mergeStrategy.set(MergeStrategy.from('latest'))
-
- when:
- if (transformer.canTransformResource(element)) {
- transformer.transform(context(path, input1))
- transformer.transform(context(path, input2))
- }
-
- then:
- output == toMap(transformer.propertiesEntries[path])
-
- where:
- path | mappings | input1 | input2 || output
- 'f.properties' | ['f.properties': [mergeStrategy: 'first']] | ['foo': 'foo'] | ['foo': 'bar'] || ['foo': 'foo']
- 'f.properties' | ['f.properties': [mergeStrategy: 'latest']] | ['foo': 'foo'] | ['foo': 'bar'] || ['foo': 'bar']
- 'f.properties' | ['f.properties': [mergeStrategy: 'append']] | ['foo': 'foo'] | ['foo': 'bar'] || ['foo': 'foo,bar']
- 'f.properties' | ['f.properties': [mergeStrategy: 'append', mergeSeparator: ';']] | ['foo': 'foo'] | ['foo': 'bar'] || ['foo': 'foo;bar']
- 'foo.properties' | ['.*.properties': [mergeStrategy: 'first']] | ['foo': 'foo'] | ['foo': 'bar'] || ['foo': 'foo']
- 'foo.properties' | ['.*bar': [mergeStrategy: 'first']] | ['foo': 'foo'] | ['foo': 'bar'] || [:]
- }
-
- void appliesKeyTransformer() {
- given:
- def element = getFileElement(path)
- Transformer transformer = new PropertiesFileTransformer(objectFactory)
- transformer.keyTransformer.set(keyTransformer)
- transformer.mergeStrategy.set(MergeStrategy.from('append'))
-
- when:
- if (transformer.canTransformResource(element)) {
- transformer.transform(context(path, input1))
- transformer.transform(context(path, input2))
- }
-
- then:
- output == toMap(transformer.propertiesEntries[path])
-
- where:
- path | keyTransformer | input1 | input2 || output
- 'foo.properties' | IDENTITY | ['foo': 'bar'] | ['FOO': 'baz'] || ['foo': 'bar', 'FOO': 'baz']
- 'foo.properties' | { key -> key.toUpperCase() } | ['foo': 'bar'] | ['FOO': 'baz'] || ['FOO': 'bar,baz']
- 'foo.properties' | { key -> 'bar.' + key.toLowerCase() } | ['foo': 'bar'] | ['FOO': 'baz'] || ['bar.foo': 'bar,baz']
- 'foo.properties' | { key -> key.replaceAll('^(foo)', 'bar.$1') } | ['foo': 'bar'] | ['FOO': 'baz'] || ['bar.foo': 'bar', 'FOO': 'baz']
- }
-
- void appliesCharset() {
- given:
- def element = getFileElement(path)
- def transformer = new PropertiesFileTransformer(objectFactory)
- transformer.charsetName.set(charset)
-
- when:
- if (transformer.canTransformResource(element)) {
- transformer.transform(context(path, input, charset))
- }
-
- then:
- output == toMap(transformer.propertiesEntries[path])
-
- where:
- path | charset | input || output
- 'utf8.properties' | 'utf-8' | ['foo': '传傳磨宿说説'] || ['foo': '传傳磨宿说説']
- }
-}
diff --git a/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerSpec.groovy b/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerSpec.groovy
deleted file mode 100644
index edee227ee..000000000
--- a/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerSpec.groovy
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.github.jengelman.gradle.plugins.shadow.transformers
-
-import spock.lang.Unroll
-
-@Unroll
-class ServiceFileTransformerSpec extends TransformerSpecSupport {
-
- def "#status path #path #transform transformed"() {
- given:
- def transformer = new ServiceFileTransformer()
- if (exclude) {
- transformer.exclude(path)
- }
-
- when:
- def actual = transformer.canTransformResource(getFileElement(path))
-
- then:
- actual == expected
-
- where:
- path | exclude | expected
- 'META-INF/services/java.sql.Driver' | false | true
- 'META-INF/services/io.dropwizard.logging.AppenderFactory' | false | true
- 'META-INF/services/org.apache.maven.Shade' | true | false
- 'META-INF/services/foo/bar/moo.goo.Zoo' | false | true
- 'foo/bar.properties' | false | false
- 'foo.props' | false | false
-
- transform = expected ? 'can be' : 'can not be'
- status = exclude ? 'excluded' : 'non-excluded'
- }
-
- def "transforms service file"() {
- given:
- def element = getFileElement(path)
- def transformer = new ServiceFileTransformer()
-
- when:
- if (transformer.canTransformResource(element)) {
- transformer.transform(context(path, input1))
- transformer.transform(context(path, input2))
- }
-
- then:
- transformer.hasTransformedResource()
- output == transformer.serviceEntries[path].toInputStream().text
-
- where:
- path | input1 | input2 || output
- 'META-INF/services/com.acme.Foo' | 'foo' | 'bar' || 'foo\nbar'
- 'META-INF/services/com.acme.Bar' | 'foo\nbar' | 'zoo' || 'foo\nbar\nzoo'
- }
-
- def "excludes Groovy extension module descriptor files by default"() {
- given:
- def transformer = new ServiceFileTransformer()
- def element = getFileElement('META-INF/services/org.codehaus.groovy.runtime.ExtensionModule')
-
- expect:
- !transformer.canTransformResource(element)
- }
-}
diff --git a/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerSpecSupport.groovy b/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerSpecSupport.groovy
deleted file mode 100644
index 818697e0b..000000000
--- a/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerSpecSupport.groovy
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.github.jengelman.gradle.plugins.shadow.transformers
-
-import com.github.jengelman.gradle.plugins.shadow.ShadowStats
-import org.gradle.api.file.FileTreeElement
-import org.gradle.api.file.RelativePath
-import org.gradle.api.internal.file.DefaultFileTreeElement
-import org.gradle.testfixtures.ProjectBuilder
-import spock.lang.Shared
-import spock.lang.Specification
-
-class TransformerSpecSupport extends Specification {
-
- protected static final def objectFactory = ProjectBuilder.builder().build().objects
-
- @Shared
- ShadowStats stats
-
- def setup() {
- stats = new ShadowStats()
- }
-
- protected static FileTreeElement getFileElement(String path) {
- // TODO: this should be replace with `createDefaultFileTreeElement` once this test gets migrated to Kotlin.
- return new DefaultFileTreeElement(null, RelativePath.parse(true, path), null, null)
- }
-
- protected static InputStream toInputStream(String str) {
- return new ByteArrayInputStream(str.bytes)
- }
-
- protected static InputStream toInputStream(Properties props, String charset) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream()
- baos.withWriter(charset) { w ->
- props.store(w, '')
- }
- new ByteArrayInputStream(baos.toByteArray())
- }
-
- protected static Properties toProperties(Map map) {
- map.inject(new Properties()) { Properties props, entry ->
- props.put(entry.key, entry.value)
- props
- }
- }
-
- protected static Map toMap(Properties props) {
- props.inject([:]) { Map map, entry ->
- map.put(entry.key, entry.value)
- map
- }
- }
-
- protected TransformerContext context(String path, Map input, String charset = 'ISO_8859_1') {
- TransformerContext.builder().path(path).inputStream(toInputStream(toProperties(input), charset)).stats(stats).build()
- }
-
- protected TransformerContext context(String path, String input) {
- TransformerContext.builder().path(path).inputStream(toInputStream(input)).stats(stats).build()
- }
-
-}
diff --git a/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy b/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy
index 23b88c502..81678db82 100644
--- a/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy
+++ b/src/funcTest/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy
@@ -16,8 +16,6 @@ abstract class PluginSpecification extends Specification {
@TempDir
Path dir
- public static final String SHADOW_VERSION = System.getProperty("shadowVersion")
-
AppendableMavenFileRepository repo
def setup() {
diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/Utils.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/Utils.kt
index 0871a3a6c..61d774cd6 100644
--- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/Utils.kt
+++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/Utils.kt
@@ -1,7 +1,12 @@
package com.github.jengelman.gradle.plugins.shadow.internal
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
import java.io.File
+import java.io.FileNotFoundException
import java.io.InputStream
+import java.nio.charset.Charset
+import java.util.Properties
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.file.RelativePath
@@ -45,12 +50,23 @@ internal inline fun unsafeLazy(noinline initializer: () -> T): Lazy {
return lazy(LazyThreadSafetyMode.NONE, initializer)
}
+internal fun Properties.inputStream(
+ charset: Charset = Charsets.ISO_8859_1,
+ comments: String = "",
+): ByteArrayInputStream {
+ val os = ByteArrayOutputStream()
+ os.writer(charset).use { writer ->
+ store(writer, comments)
+ }
+ return os.toByteArray().inputStream()
+}
+
internal fun Class<*>.requireResourceAsText(name: String): String {
return requireResourceAsStream(name).bufferedReader().readText()
}
private fun Class<*>.requireResourceAsStream(name: String): InputStream {
- return getResourceAsStream(name) ?: error("Resource $name not found.")
+ return getResourceAsStream(name) ?: throw FileNotFoundException("Resource $name not found.")
}
private val DummyFile = File("dummy")
diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.kt
index b09a42921..1e3a80a5d 100644
--- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.kt
+++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.kt
@@ -1,13 +1,12 @@
package com.github.jengelman.gradle.plugins.shadow.transformers
import com.github.jengelman.gradle.plugins.shadow.internal.CleanProperties
+import com.github.jengelman.gradle.plugins.shadow.internal.inputStream
import com.github.jengelman.gradle.plugins.shadow.internal.property
import com.github.jengelman.gradle.plugins.shadow.transformers.PropertiesFileTransformer.MergeStrategy
import groovy.lang.Closure
import groovy.lang.Closure.IDENTITY
-import java.io.ByteArrayOutputStream
import java.io.InputStream
-import java.io.InputStreamReader
import java.nio.charset.Charset
import java.util.Properties
import javax.inject.Inject
@@ -102,9 +101,11 @@ import org.gradle.api.tasks.Internal
public open class PropertiesFileTransformer @Inject constructor(
final override val objectFactory: ObjectFactory,
) : Transformer {
- private val propertiesEntries = mutableMapOf()
private inline val charset get() = Charset.forName(charsetName.get())
+ @get:Internal
+ internal val propertiesEntries = mutableMapOf()
+
@get:Input
public open val paths: ListProperty = objectFactory.listProperty(String::class.java)
@@ -226,7 +227,7 @@ public open class PropertiesFileTransformer @Inject constructor(
val entry = ZipEntry(path)
entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time)
os.putNextEntry(entry)
- props.toReader().use {
+ props.inputStream(charset).reader(charset).use {
it.copyTo(zipWriter)
}
zipWriter.flush()
@@ -234,14 +235,6 @@ public open class PropertiesFileTransformer @Inject constructor(
}
}
- private fun Properties.toReader(): InputStreamReader {
- val os = ByteArrayOutputStream()
- os.writer(charset).use { writer ->
- store(writer, "")
- }
- return os.toByteArray().inputStream().reader(charset)
- }
-
public enum class MergeStrategy {
First,
Latest,
diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.kt
index 6d26c2a99..3f8023e64 100644
--- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.kt
+++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.kt
@@ -11,6 +11,7 @@ import org.apache.tools.zip.ZipEntry
import org.apache.tools.zip.ZipOutputStream
import org.gradle.api.file.FileTreeElement
import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.util.PatternFilterable
import org.gradle.api.tasks.util.PatternSet
@@ -34,7 +35,8 @@ public open class ServiceFileTransformer(
.exclude(GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATTERN),
) : Transformer,
PatternFilterable by patternSet {
- private val serviceEntries = mutableMapOf()
+ @get:Internal
+ internal val serviceEntries = mutableMapOf()
override fun canTransformResource(element: FileTreeElement): Boolean {
val target = if (element is ShadowCopyAction.ArchiveFileTreeElement) element.asFileTreeElement() else element
diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.kt
index bf7c6cf3d..b5c9a070e 100644
--- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.kt
+++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.kt
@@ -179,11 +179,13 @@ class SimpleRelocatorTest {
.isEqualTo("META-INF/hidden.org.foo.xml")
}
- private fun SimpleRelocator.relocatePath(path: String): String {
- return relocatePath(RelocatePathContext(path))
- }
-
- private fun SimpleRelocator.relocateClass(className: String): String {
- return relocateClass(RelocateClassContext(className))
+ private companion object {
+ fun SimpleRelocator.relocatePath(path: String): String {
+ return relocatePath(RelocatePathContext(path))
+ }
+
+ fun SimpleRelocator.relocateClass(className: String): String {
+ return relocateClass(RelocateClassContext(className))
+ }
}
}
diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.kt
index 4d3b72b41..3c2782e61 100644
--- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.kt
+++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.kt
@@ -8,7 +8,7 @@ import org.junit.jupiter.api.Test
/**
* Modified from [org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ApacheLicenseResourceTransformerTest.java).
*/
-class ApacheLicenseResourceTransformerTest : TransformerTestSupport() {
+class ApacheLicenseResourceTransformerTest : BaseTransformerTest() {
init {
setupTurkishLocale()
@@ -16,11 +16,11 @@ class ApacheLicenseResourceTransformerTest : TransformerTestSupport() {
+class ApacheNoticeResourceTransformerTest : BaseTransformerTest() {
init {
setupTurkishLocale()
@@ -17,12 +17,12 @@ class ApacheNoticeResourceTransformerTest : TransformerTestSupport() {
+class AppendingTransformerTest : BaseTransformerTest() {
init {
setupTurkishLocale()
@@ -18,8 +18,8 @@ class AppendingTransformerTest : TransformerTestSupport()
fun testCanTransformResource() {
transformer.resource.set("abcdefghijklmnopqrstuvwxyz")
- assertThat(transformer.canTransformResource(getFileElement("abcdefghijklmnopqrstuvwxyz"))).isTrue()
- assertThat(transformer.canTransformResource(getFileElement("ABCDEFGHIJKLMNOPQRSTUVWXYZ"))).isTrue()
- assertThat(transformer.canTransformResource(getFileElement("META-INF/MANIFEST.MF"))).isFalse()
+ assertThat(transformer.canTransformResource("abcdefghijklmnopqrstuvwxyz")).isTrue()
+ assertThat(transformer.canTransformResource("ABCDEFGHIJKLMNOPQRSTUVWXYZ")).isTrue()
+ assertThat(transformer.canTransformResource("META-INF/MANIFEST.MF")).isFalse()
}
}
diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerTestSupport.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt
similarity index 79%
rename from src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerTestSupport.kt
rename to src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt
index 1acc05f10..18b0c4dbc 100644
--- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerTestSupport.kt
+++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt
@@ -1,8 +1,10 @@
package com.github.jengelman.gradle.plugins.shadow.transformers
+import com.github.jengelman.gradle.plugins.shadow.ShadowStats
import com.github.jengelman.gradle.plugins.shadow.internal.createDefaultFileTreeElement
import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer.Companion.create
import com.github.jengelman.gradle.plugins.shadow.util.testObjectFactory
+import java.io.FileNotFoundException
import java.io.InputStream
import java.lang.reflect.ParameterizedType
import java.nio.file.Path
@@ -11,11 +13,10 @@ import java.util.zip.ZipFile
import kotlin.io.path.createTempFile
import kotlin.io.path.outputStream
import org.apache.tools.zip.ZipOutputStream
-import org.gradle.api.file.FileTreeElement
import org.gradle.api.file.RelativePath
import org.junit.jupiter.api.BeforeEach
-abstract class TransformerTestSupport {
+abstract class BaseTransformerTest {
protected lateinit var transformer: T
private set
@@ -23,7 +24,7 @@ abstract class TransformerTestSupport {
get() = TransformerContext(MANIFEST_NAME, requireResourceAsStream(MANIFEST_NAME))
protected fun requireResourceAsStream(name: String): InputStream {
- return this::class.java.classLoader.getResourceAsStream(name) ?: error("Resource $name not found.")
+ return this::class.java.classLoader.getResourceAsStream(name) ?: throw FileNotFoundException("Resource $name not found.")
}
@BeforeEach
@@ -35,9 +36,11 @@ abstract class TransformerTestSupport {
protected companion object {
const val MANIFEST_NAME: String = "META-INF/MANIFEST.MF"
+ val sharedStats = ShadowStats()
- fun getFileElement(path: String): FileTreeElement {
- return createDefaultFileTreeElement(relativePath = RelativePath.parse(true, path))
+ fun Transformer.canTransformResource(path: String): Boolean {
+ val element = createDefaultFileTreeElement(relativePath = RelativePath.parse(true, path))
+ return canTransformResource(element)
}
fun readFrom(jarPath: Path, resourceName: String = MANIFEST_NAME): List {
@@ -59,7 +62,7 @@ abstract class TransformerTestSupport {
}
/**
- * NOTE: The Turkish locale has an usual case transformation for the letters "I" and "i", making it a prime
+ * NOTE: The Turkish locale has a usual case transformation for the letters "I" and "i", making it a prime
* choice to test for improper case-less string comparisons.
*/
fun setupTurkishLocale() {
diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.kt
index d419e84e1..43640d449 100644
--- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.kt
+++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.kt
@@ -8,7 +8,7 @@ import org.junit.jupiter.api.Test
/**
* Modified from [org.apache.maven.plugins.shade.resource.ComponentsXmlResourceTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ComponentsXmlResourceTransformerTest.java).
*/
-class ComponentsXmlResourceTransformerTest : TransformerTestSupport() {
+class ComponentsXmlResourceTransformerTest : BaseTransformerTest() {
@Test
fun testConfigurationMerging() {
XMLUnit.setNormalizeWhitespace(true)
diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformerTest.kt
new file mode 100644
index 000000000..48a4b1ff3
--- /dev/null
+++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformerTest.kt
@@ -0,0 +1,55 @@
+package com.github.jengelman.gradle.plugins.shadow.transformers
+
+import assertk.assertThat
+import assertk.assertions.isEqualTo
+import assertk.assertions.isTrue
+import com.github.jengelman.gradle.plugins.shadow.relocation.SimpleRelocator
+import java.io.File
+import java.net.URL
+import java.util.Collections
+import org.apache.logging.log4j.core.config.plugins.processor.PluginCache
+import org.apache.tools.zip.ZipOutputStream
+import org.junit.jupiter.api.Test
+
+class Log4j2PluginsCacheFileTransformerTest : BaseTransformerTest() {
+ @Test
+ fun `should transform`() {
+ transformer.transform(context(SimpleRelocator()))
+ assertThat(transformer.hasTransformedResource()).isTrue()
+ }
+
+ @Test
+ fun `should transform for a single file`() {
+ transformer.transform(context())
+ assertThat(transformer.hasTransformedResource()).isTrue()
+ }
+
+ @Test
+ fun `relocate classes inside DAT file`() {
+ val relocator = SimpleRelocator("org.apache.logging", "new.location.org.apache.logging")
+ transformer.transform(context(relocator))
+ assertThat(transformer.hasTransformedResource()).isTrue()
+
+ // Write out to a fake jar file
+ val testableZipFile = File.createTempFile("testable-zip-file-", ".jar")
+ ZipOutputStream(testableZipFile.outputStream().buffered()).use { zipOutputStream ->
+ transformer.modifyOutputStream(zipOutputStream, true)
+ }
+
+ // Pull the data back out and make sure it was transformed
+ val cache = PluginCache()
+ val urlString = "jar:" + testableZipFile.toURI().toURL() + "!/" + PLUGIN_CACHE_FILE
+ cache.loadCacheFiles(Collections.enumeration(listOf(URL(urlString))))
+
+ assertThat(cache.getCategory("lookup")["date"]?.className)
+ .isEqualTo("new.location.org.apache.logging.log4j.core.lookup.DateLookup")
+ }
+
+ private fun context(vararg relocator: SimpleRelocator): TransformerContext {
+ return TransformerContext(PLUGIN_CACHE_FILE, requireResourceAsStream(PLUGIN_CACHE_FILE), relocator.toList())
+ }
+
+ private companion object {
+ const val PLUGIN_CACHE_FILE = "META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat"
+ }
+}
diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformerTest.kt
index c36db4cc0..e699711a7 100644
--- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformerTest.kt
+++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformerTest.kt
@@ -8,7 +8,7 @@ import assertk.assertions.isNotEmpty
import assertk.assertions.isTrue
import org.junit.jupiter.api.Test
-class ManifestAppenderTransformerTest : TransformerTestSupport() {
+class ManifestAppenderTransformerTest : BaseTransformerTest() {
@Test
fun testCanTransformResource() {
with(transformer) {
@@ -16,8 +16,8 @@ class ManifestAppenderTransformerTest : TransformerTestSupport() {
+class PropertiesFileTransformerTest : BaseTransformerTest() {
@Test
fun testHasTransformedResource() {
transformer.transform(manifestTransformerContext)
@@ -46,4 +54,282 @@ class PropertiesFileTransformerTest : TransformerTestSupport,
+ input2: Map,
+ expectedOutput: Map,
+ ) {
+ transformer.mergeStrategy.set(MergeStrategy.from(mergeStrategy))
+ transformer.mergeSeparator.set(mergeSeparator)
+
+ if (transformer.canTransformResource(path)) {
+ transformer.transform(context(path, input1))
+ transformer.transform(context(path, input2))
+ }
+
+ assertThat(transformer.propertiesEntries[path].orEmpty()).isEqualTo(expectedOutput)
+ }
+
+ @ParameterizedTest(name = "Paths={1}")
+ @MethodSource("transformConfigurationsWithPathsProvider")
+ fun exerciseAllTransformConfigurationsWithPaths(
+ path: String,
+ paths: List,
+ input1: Map,
+ input2: Map,
+ expectedOutput: Map,
+ ) {
+ transformer.paths.set(paths)
+ transformer.mergeStrategy.set(MergeStrategy.First)
+
+ if (transformer.canTransformResource(path)) {
+ transformer.transform(context(path, input1))
+ transformer.transform(context(path, input2))
+ }
+
+ assertThat(transformer.propertiesEntries[path].orEmpty()).isEqualTo(expectedOutput)
+ }
+
+ @ParameterizedTest(name = "Mappings={1}")
+ @MethodSource("transformConfigurationsWithMappingsProvider")
+ fun exerciseAllTransformConfigurationsWithMappings(
+ path: String,
+ mappings: Map>,
+ input1: Map,
+ input2: Map,
+ expectedOutput: Map,
+ ) {
+ transformer.mappings.set(mappings)
+ transformer.mergeStrategy.set(MergeStrategy.Latest)
+
+ if (transformer.canTransformResource(path)) {
+ transformer.transform(context(path, input1))
+ transformer.transform(context(path, input2))
+ }
+
+ assertThat(transformer.propertiesEntries[path].orEmpty()).isEqualTo(expectedOutput)
+ }
+
+ @ParameterizedTest(name = "KeyTransformer: {1}")
+ @MethodSource("appliesKeyTransformerProvider")
+ fun appliesKeyTransformer(
+ path: String,
+ keyTransformer: (String) -> String,
+ input1: Map,
+ input2: Map,
+ expectedOutput: Map,
+ ) {
+ transformer.mergeStrategy.set(MergeStrategy.Append)
+ transformer.keyTransformer.set(object : Closure(null) {
+ override fun call(vararg arguments: Any?): String {
+ return keyTransformer.invoke(arguments.first() as String)
+ }
+ })
+
+ if (transformer.canTransformResource(path)) {
+ transformer.transform(context(path, input1))
+ transformer.transform(context(path, input2))
+ }
+
+ assertThat(transformer.propertiesEntries[path].orEmpty()).isEqualTo(expectedOutput)
+ }
+
+ @ParameterizedTest(name = "Charset: {1}")
+ @MethodSource("appliesCharsetProvider")
+ fun appliesCharset(
+ path: String,
+ charset: String,
+ input: Map,
+ expectedOutput: Map,
+ ) {
+ transformer.charsetName.set(charset)
+
+ if (transformer.canTransformResource(path)) {
+ transformer.transform(context(path, input, Charset.forName(charset)))
+ }
+
+ assertThat(transformer.propertiesEntries[path].orEmpty()).isEqualTo(expectedOutput)
+ }
+
+ private companion object {
+ fun context(path: String, input: Map, charset: Charset = Charsets.ISO_8859_1): TransformerContext {
+ val properties = Properties().apply { putAll(input) }
+ return TransformerContext(path, properties.inputStream(charset), stats = sharedStats)
+ }
+
+ @JvmStatic
+ fun pathProvider() = listOf(
+ Arguments.of("foo.properties", true, "can be"),
+ Arguments.of("foo/bar.properties", true, "can be"),
+ Arguments.of("foo.props", false, "can not be"),
+ )
+
+ @JvmStatic
+ fun appliesCharsetProvider() = listOf(
+ Arguments.of(
+ "utf8.properties",
+ "utf-8",
+ mapOf("foo" to "传傳磨宿说説"),
+ mapOf("foo" to "传傳磨宿说説"),
+ ),
+ )
+
+ @JvmStatic
+ fun transformConfigurationsWithPathsProvider() = listOf(
+ Arguments.of(
+ "f.properties",
+ listOf("f.properties"),
+ mapOf("foo" to "foo"),
+ mapOf("foo" to "bar"),
+ mapOf("foo" to "foo"),
+ ),
+ Arguments.of(
+ "foo.properties",
+ listOf(".*.properties"),
+ mapOf("foo" to "foo"),
+ mapOf("foo" to "bar"),
+ mapOf("foo" to "foo"),
+ ),
+ Arguments.of(
+ "foo.properties",
+ listOf(".*bar"),
+ mapOf("foo" to "foo"),
+ mapOf("foo" to "bar"),
+ emptyMap(),
+ ),
+ Arguments.of(
+ "foo.properties",
+ emptyList(),
+ mapOf("foo" to "foo"),
+ mapOf("foo" to "bar"),
+ mapOf("foo" to "foo"),
+ ),
+ )
+
+ @JvmStatic
+ fun transformConfigurationsWithMappingsProvider() = listOf(
+ Arguments.of(
+ "f.properties",
+ mapOf("f.properties" to mapOf("mergeStrategy" to "first")),
+ mapOf("foo" to "foo"),
+ mapOf("foo" to "bar"),
+ mapOf("foo" to "foo"),
+ ),
+ Arguments.of(
+ "f.properties",
+ mapOf("f.properties" to mapOf("mergeStrategy" to "latest")),
+ mapOf("foo" to "foo"),
+ mapOf("foo" to "bar"),
+ mapOf("foo" to "bar"),
+ ),
+ Arguments.of(
+ "f.properties",
+ mapOf("f.properties" to mapOf("mergeStrategy" to "append")),
+ mapOf("foo" to "foo"),
+ mapOf("foo" to "bar"),
+ mapOf("foo" to "foo,bar"),
+ ),
+ Arguments.of(
+ "f.properties",
+ mapOf("f.properties" to mapOf("mergeStrategy" to "append", "mergeSeparator" to ";")),
+ mapOf("foo" to "foo"),
+ mapOf("foo" to "bar"),
+ mapOf("foo" to "foo;bar"),
+ ),
+ Arguments.of(
+ "foo.properties",
+ mapOf(".*.properties" to mapOf("mergeStrategy" to "first")),
+ mapOf("foo" to "foo"),
+ mapOf("foo" to "bar"),
+ mapOf("foo" to "foo"),
+ ),
+ Arguments.of(
+ "foo.properties",
+ mapOf(".*bar" to mapOf("mergeStrategy" to "first")),
+ mapOf("foo" to "foo"),
+ mapOf("foo" to "bar"),
+ emptyMap(),
+ ),
+ )
+
+ @JvmStatic
+ fun transformConfigurationsProvider() = listOf(
+ Arguments.of(
+ "f.properties",
+ "first",
+ "",
+ mapOf("foo" to "foo"),
+ mapOf("foo" to "bar"),
+ mapOf("foo" to "foo"),
+ ),
+ Arguments.of(
+ "f.properties",
+ "latest",
+ "",
+ mapOf("foo" to "foo"),
+ mapOf("foo" to "bar"),
+ mapOf("foo" to "bar"),
+ ),
+ Arguments.of(
+ "f.properties",
+ "append",
+ ",",
+ mapOf("foo" to "foo"),
+ mapOf("foo" to "bar"),
+ mapOf("foo" to "foo,bar"),
+ ),
+ Arguments.of(
+ "f.properties",
+ "append",
+ ";",
+ mapOf("foo" to "foo"),
+ mapOf("foo" to "bar"),
+ mapOf("foo" to "foo;bar"),
+ ),
+ )
+
+ @JvmStatic
+ fun appliesKeyTransformerProvider() = listOf(
+ Arguments.of(
+ "foo.properties",
+ { key: String -> key },
+ mapOf("foo" to "bar"),
+ mapOf("FOO" to "baz"),
+ mapOf("foo" to "bar", "FOO" to "baz"),
+ ),
+ Arguments.of(
+ "foo.properties",
+ { key: String -> key.uppercase() },
+ mapOf("foo" to "bar"),
+ mapOf("FOO" to "baz"),
+ mapOf("FOO" to "bar,baz"),
+ ),
+ Arguments.of(
+ "foo.properties",
+ { key: String -> "bar.${key.lowercase()}" },
+ mapOf("foo" to "bar"),
+ mapOf("FOO" to "baz"),
+ mapOf("bar.foo" to "bar,baz"),
+ ),
+ Arguments.of(
+ "foo.properties",
+ { key: String -> key.replaceFirst(Regex("^(foo)"), "bar.$1") },
+ mapOf("foo" to "bar"),
+ mapOf("FOO" to "baz"),
+ mapOf("bar.foo" to "bar", "FOO" to "baz"),
+ ),
+ )
+ }
}
diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt
new file mode 100644
index 000000000..55bec8828
--- /dev/null
+++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt
@@ -0,0 +1,64 @@
+package com.github.jengelman.gradle.plugins.shadow.transformers
+
+import assertk.assertThat
+import assertk.assertions.isEqualTo
+import assertk.assertions.isFalse
+import assertk.assertions.isTrue
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.Arguments
+import org.junit.jupiter.params.provider.MethodSource
+
+class ServiceFileTransformerTest : BaseTransformerTest() {
+ @ParameterizedTest(name = "{index} => path={0}, exclude={1}, expected={2}")
+ @MethodSource("canTransformResourceData")
+ fun testCanTransformResource(path: String, exclude: Boolean, expected: Boolean) {
+ if (exclude) {
+ transformer.exclude(path)
+ }
+ assertThat(transformer.canTransformResource(path)).isEqualTo(expected)
+ }
+
+ @ParameterizedTest(name = "{index} => path={0}")
+ @MethodSource("transformsServiceFileData")
+ fun `test transforms service file`(path: String, input1: String, input2: String, output: String) {
+ if (transformer.canTransformResource(path)) {
+ transformer.transform(context(path, input1))
+ transformer.transform(context(path, input2))
+ }
+
+ assertThat(transformer.hasTransformedResource()).isTrue()
+ assertThat(transformer.serviceEntries.getValue(path).toInputStream().bufferedReader().readText())
+ .isEqualTo(output)
+ }
+
+ @Test
+ fun `test excludes Groovy extension module descriptor files by default`() {
+ val element = "META-INF/services/org.codehaus.groovy.runtime.ExtensionModule"
+ assertThat(transformer.canTransformResource(element)).isFalse()
+ }
+
+ private companion object {
+ fun context(path: String, input: String): TransformerContext {
+ return TransformerContext(path, input.byteInputStream(), stats = sharedStats)
+ }
+
+ @JvmStatic
+ fun canTransformResourceData() = listOf(
+ // path, exclude, expected
+ Arguments.of("META-INF/services/java.sql.Driver", false, true),
+ Arguments.of("META-INF/services/io.dropwizard.logging.AppenderFactory", false, true),
+ Arguments.of("META-INF/services/org.apache.maven.Shade", true, false),
+ Arguments.of("META-INF/services/foo/bar/moo.goo.Zoo", false, true),
+ Arguments.of("foo/bar.properties", false, false),
+ Arguments.of("foo.props", false, false),
+ )
+
+ @JvmStatic
+ fun transformsServiceFileData() = listOf(
+ // path, input1, input2, output
+ Arguments.of("META-INF/services/com.acme.Foo", "foo", "bar", "foo\nbar"),
+ Arguments.of("META-INF/services/com.acme.Bar", "foo\nbar", "zoo", "foo\nbar\nzoo"),
+ )
+ }
+}
diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.kt
index b9eddbf31..eddd1a2d0 100644
--- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.kt
+++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.kt
@@ -5,7 +5,7 @@ import assertk.assertions.isFalse
import assertk.assertions.isTrue
import org.junit.jupiter.api.Test
-class XmlAppendingTransformerTest : TransformerTestSupport() {
+class XmlAppendingTransformerTest : BaseTransformerTest() {
init {
setupTurkishLocale()
@@ -15,8 +15,8 @@ class XmlAppendingTransformerTest : TransformerTestSupport