Skip to content
14 changes: 5 additions & 9 deletions api/shadow.api
Original file line number Diff line number Diff line change
Expand Up @@ -250,19 +250,15 @@ public final class com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar$Co
public final synthetic fun getShadowJar (Lorg/gradle/api/tasks/TaskContainer;)Lorg/gradle/api/tasks/TaskProvider;
}

public class com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformer : com/github/jengelman/gradle/plugins/shadow/transformers/ResourceTransformer {
public class com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformer : com/github/jengelman/gradle/plugins/shadow/transformers/PatternFilterableResourceTransformer {
public fun <init> ()V
public fun canTransformResource (Lorg/gradle/api/file/FileTreeElement;)Z
public fun getName ()Ljava/lang/String;
public fun getObjectFactory ()Lorg/gradle/api/model/ObjectFactory;
public fun hasTransformedResource ()Z
public fun modifyOutputStream (Lorg/apache/tools/zip/ZipOutputStream;Z)V
public fun transform (Lcom/github/jengelman/gradle/plugins/shadow/transformers/TransformerContext;)V
public fun <init> (Lorg/gradle/api/tasks/util/PatternSet;)V
public synthetic fun <init> (Lorg/gradle/api/tasks/util/PatternSet;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
}

public class com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformer : com/github/jengelman/gradle/plugins/shadow/transformers/ResourceTransformer {
public class com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformer : com/github/jengelman/gradle/plugins/shadow/transformers/PatternFilterableResourceTransformer {
public fun <init> (Lorg/gradle/api/model/ObjectFactory;)V
public fun canTransformResource (Lorg/gradle/api/file/FileTreeElement;)Z
public fun <init> (Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/tasks/util/PatternSet;)V
public fun getAddHeader ()Lorg/gradle/api/provider/Property;
public fun getCharsetName ()Lorg/gradle/api/provider/Property;
public fun getCopyright ()Lorg/gradle/api/provider/Property;
Expand Down
2 changes: 2 additions & 0 deletions docs/changes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

- Add `PatternFilterableResourceTransformer` to simplify pattern based `ResourceTransformer`s. ([#1849](https://github.com/GradleUp/shadow/pull/1849))
- Expose `patternSet` of `ServiceFileTransformer` as `public`. ([#1849](https://github.com/GradleUp/shadow/pull/1849))
- Expose `patternSet` of `ApacheLicenseResourceTransformer` as `public`. ([#1850](https://github.com/GradleUp/shadow/pull/1850))
- Expose `patternSet` of `ApacheNoticeResourceTransformer` as `public`. ([#1850](https://github.com/GradleUp/shadow/pull/1850))

### Changed

Expand Down
39 changes: 39 additions & 0 deletions docs/configuration/merging/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,41 @@ It must be added using the [`transform`][ShadowJar.transform] methods.
}
```

## Configuring Resource Transformer Filtering by Pattern

There are lots of built-in [`ResourceTransformer`][ResourceTransformer]s provided by Shadow. Some of them extend
[`PatternFilterableResourceTransformer`][PatternFilterableResourceTransformer], which extends
[`PatternFilterable`][PatternFilterable] to provide `include`/`exclude` pattern filtering capabilities. e.g.

- [`ApacheLicenseResourceTransformer`][ApacheLicenseResourceTransformer]
- [`ApacheNoticeResourceTransformer`][ApacheNoticeResourceTransformer]
- [`ServiceFileTransformer`][ServiceFileTransformer]
- ...

You can use `include`/`exclude` and more methods to configure the patterns for those
[`ResourceTransformer`][ResourceTransformer]s that support it. For example:

=== "Kotlin"

```kotlin
tasks.shadowJar {
transform<com.github.jengelman.gradle.plugins.shadow.transformers.ApacheLicenseResourceTransformer>() {
include("META-INF/LICENSE.*")
exclude("META-INF/LICENSE.log")
}
}
```

=== "Groovy"

```groovy
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
transform(com.github.jengelman.gradle.plugins.shadow.transformers.ApacheLicenseResourceTransformer) {
include 'META-INF/LICENSE.*'
exclude 'META-INF/LICENSE.log'
}
}
```


[AbstractCopyTask]: https://docs.gradle.org/current/dsl/org.gradle.api.tasks.AbstractCopyTask.html
Expand All @@ -558,8 +593,12 @@ It must be added using the [`transform`][ShadowJar.transform] methods.
[Jar]: https://docs.gradle.org/current/dsl/org.gradle.api.tasks.bundling.Jar.html
[Log4j2PluginsCacheFileTransformer]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.transformers/-log4j2-plugins-cache-file-transformer/index.html
[ResourceTransformer]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.transformers/-resource-transformer/index.html
[ApacheLicenseResourceTransformer]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.transformers/-apache-license-resource-transformer/index.html
[ApacheNoticeResourceTransformer]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.transformers/-apache-notice-resource-transformer/index.html
[ServiceFileTransformer]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.transformers/-service-file-transformer/index.html
[PreserveFirstFoundResourceTransformer]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.transformers/-preserve-first-found-resource-transformer/index.html
[PatternFilterable]: https://docs.gradle.org/current/kotlin-dsl/gradle/org.gradle.api.tasks.util/-pattern-filterable/index.html
[PatternFilterableResourceTransformer]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.transformers/-pattern-filterable-resource-transformer/index.html
[ShadowJar.append]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.tasks/-shadow-jar/append.html
[ShadowJar.failOnDuplicateEntries]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.tasks/-shadow-jar/fail-on-duplicate-entries.html
[ShadowJar.from]: https://docs.gradle.org/current/dsl/org.gradle.jvm.tasks.Jar.html#org.gradle.jvm.tasks.Jar:from(java.lang.Object,%20org.gradle.api.Action)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.github.jengelman.gradle.plugins.shadow.transformers

import org.gradle.api.file.FileTreeElement
import org.gradle.api.tasks.util.PatternSet

/**
* Prevents duplicate copies of the license.
Expand All @@ -10,14 +10,15 @@ import org.gradle.api.file.FileTreeElement
* @author John Engelman
*/
@CacheableTransformer
public open class ApacheLicenseResourceTransformer : ResourceTransformer by ResourceTransformer.Companion {
override fun canTransformResource(element: FileTreeElement): Boolean {
val path = element.path
return LICENSE_PATH.equals(path, ignoreCase = true) ||
LICENSE_TXT_PATH.regionMatches(0, path, 0, LICENSE_TXT_PATH.length, ignoreCase = true) ||
LICENSE_MD_PATH.regionMatches(0, path, 0, LICENSE_MD_PATH.length, ignoreCase = true)
}

public open class ApacheLicenseResourceTransformer @JvmOverloads constructor(
patternSet: PatternSet = PatternSet()
.apply { isCaseSensitive = false }
.include(
LICENSE_PATH,
LICENSE_TXT_PATH,
LICENSE_MD_PATH,
),
) : PatternFilterableResourceTransformer(patternSet = patternSet) {
private companion object {
private const val LICENSE_PATH = "META-INF/LICENSE"
private const val LICENSE_TXT_PATH = "META-INF/LICENSE.txt"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import java.util.Locale
import java.util.TreeSet
import javax.inject.Inject
import org.apache.tools.zip.ZipOutputStream
import org.gradle.api.file.FileTreeElement
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.util.PatternSet

/**
* Merges `META-INF/NOTICE.TXT` files.
Expand All @@ -22,9 +22,10 @@ import org.gradle.api.tasks.Input
* @author John Engelman
*/
@CacheableTransformer
public open class ApacheNoticeResourceTransformer @Inject constructor(
public open class ApacheNoticeResourceTransformer(
final override val objectFactory: ObjectFactory,
) : ResourceTransformer {
patternSet: PatternSet,
) : PatternFilterableResourceTransformer(patternSet) {
private val entries = mutableSetOf<String>()
private val organizationEntries = mutableMapOf<String, MutableSet<String>>()
private inline val charset get() = Charset.forName(charsetName.get())
Expand Down Expand Up @@ -75,12 +76,17 @@ public open class ApacheNoticeResourceTransformer @Inject constructor(
@get:Input
public open val charsetName: Property<String> = objectFactory.property(Charsets.UTF_8.name())

override fun canTransformResource(element: FileTreeElement): Boolean {
val path = element.path
return NOTICE_PATH.equals(path, ignoreCase = true) ||
NOTICE_TXT_PATH.equals(path, ignoreCase = true) ||
NOTICE_MD_PATH.equals(path, ignoreCase = true)
}
@Inject
public constructor(objectFactory: ObjectFactory) : this(
objectFactory,
patternSet = PatternSet()
.apply { isCaseSensitive = false }
.include(
NOTICE_PATH,
NOTICE_TXT_PATH,
NOTICE_MD_PATH,
),
)

override fun transform(context: TransformerContext) {
val projectName = projectName.get()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import org.gradle.api.tasks.util.PatternSet
* @author John Engelman
*/
@CacheableTransformer
public open class ServiceFileTransformer(
public open class ServiceFileTransformer @JvmOverloads constructor(
patternSet: PatternSet = PatternSet()
.include(SERVICES_PATTERN)
.exclude(PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,14 @@ class ApacheLicenseResourceTransformerTest : BaseTransformerTest<ApacheLicenseRe
assertThat(transformer.canTransformResource("META-INF/License.md")).isTrue()
assertThat(transformer.canTransformResource("META-INF/MANIFEST.MF")).isFalse()
}

@Test
fun canTransformByPattern() {
assertThat(transformer.canTransformResource("META-INF/LICENSE.txt")).isTrue()
assertThat(transformer.canTransformResource("META-INF/LICENSE.log")).isFalse()
transformer.exclude("META-INF/LICENSE.txt")
transformer.include("META-INF/LICENSE.*")
assertThat(transformer.canTransformResource("META-INF/LICENSE.txt")).isFalse()
assertThat(transformer.canTransformResource("META-INF/LICENSE.log")).isTrue()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ class ApacheNoticeResourceTransformerTest : BaseTransformerTest<ApacheNoticeReso
assertThat(transformer.canTransformResource("META-INF/MANIFEST.MF")).isFalse()
}

@Test
fun canTransformByPattern() {
assertThat(transformer.canTransformResource("META-INF/NOTICE.txt")).isTrue()
assertThat(transformer.canTransformResource("META-INF/NOTICE.log")).isFalse()
transformer.exclude("META-INF/NOTICE.txt")
transformer.include("META-INF/NOTICE.*")
assertThat(transformer.canTransformResource("META-INF/NOTICE.txt")).isFalse()
assertThat(transformer.canTransformResource("META-INF/NOTICE.log")).isTrue()
}

@Test
fun preamble1ShouldHaveATrailingSpace() {
val baos = ByteArrayOutputStream()
Expand Down