diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 7aa77ec18..964159f65 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -27,7 +27,7 @@ spotless { kotlin { ktlint().editorConfigOverride( mapOf( - "indent_size" to "4", + "indent_size" to "2", ), ) } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt index a6b17a2c4..790cfc486 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt @@ -17,119 +17,119 @@ import org.gradle.jvm.application.scripts.TemplateBasedScriptGenerator import org.gradle.jvm.toolchain.JavaToolchainService abstract class ShadowApplicationPlugin : Plugin { - private lateinit var project: Project - private lateinit var javaApplication: JavaApplication + private lateinit var project: Project + private lateinit var javaApplication: JavaApplication - override fun apply(project: Project) { - this.project = project - this.javaApplication = project.extensions.getByType(JavaApplication::class.java) + override fun apply(project: Project) { + this.project = project + this.javaApplication = project.extensions.getByType(JavaApplication::class.java) - addRunTask() - addCreateScriptsTask() - configureDistSpec() - configureJarMainClass() - configureInstallTask() - } + addRunTask() + addCreateScriptsTask() + configureDistSpec() + configureJarMainClass() + configureInstallTask() + } - protected open fun configureJarMainClass() { - val classNameProvider = javaApplication.mainClass - shadowJar.configure { jar -> - jar.inputs.property("mainClassName", classNameProvider) - jar.doFirst { - jar.manifest.attributes["Main-Class"] = classNameProvider.get() - } - } + protected open fun configureJarMainClass() { + val classNameProvider = javaApplication.mainClass + shadowJar.configure { jar -> + jar.inputs.property("mainClassName", classNameProvider) + jar.doFirst { + jar.manifest.attributes["Main-Class"] = classNameProvider.get() + } } + } - protected open fun addRunTask() { - project.tasks.register(SHADOW_RUN_TASK_NAME, JavaJarExec::class.java) { - val install = project.tasks.named(SHADOW_INSTALL_TASK_NAME, Sync::class.java) - it.dependsOn(install) - it.mainClass.set("-jar") - it.description = "Runs this project as a JVM application using the shadow jar" - it.group = ApplicationPlugin.APPLICATION_GROUP - it.conventionMapping.map("jvmArgs") { javaApplication.applicationDefaultJvmArgs } - it.jarFile.fileProvider( - project.providers.provider { - project.file("${install.get().destinationDir.path}/lib/${shadowJar.get().archiveFile.get().asFile.name}") - }, - ) - val toolchain = project.extensions.getByType(JavaPluginExtension::class.java).toolchain - val defaultLauncher = project.extensions.getByType(JavaToolchainService::class.java) - .launcherFor(toolchain) - it.javaLauncher.set(defaultLauncher) - } + protected open fun addRunTask() { + project.tasks.register(SHADOW_RUN_TASK_NAME, JavaJarExec::class.java) { + val install = project.tasks.named(SHADOW_INSTALL_TASK_NAME, Sync::class.java) + it.dependsOn(install) + it.mainClass.set("-jar") + it.description = "Runs this project as a JVM application using the shadow jar" + it.group = ApplicationPlugin.APPLICATION_GROUP + it.conventionMapping.map("jvmArgs") { javaApplication.applicationDefaultJvmArgs } + it.jarFile.fileProvider( + project.providers.provider { + project.file("${install.get().destinationDir.path}/lib/${shadowJar.get().archiveFile.get().asFile.name}") + }, + ) + val toolchain = project.extensions.getByType(JavaPluginExtension::class.java).toolchain + val defaultLauncher = project.extensions.getByType(JavaToolchainService::class.java) + .launcherFor(toolchain) + it.javaLauncher.set(defaultLauncher) } + } - protected open fun addCreateScriptsTask() { - project.tasks.register(SHADOW_SCRIPTS_TASK_NAME, CreateStartScripts::class.java) { - (it.unixStartScriptGenerator as TemplateBasedScriptGenerator).template = - project.resources.text.fromString(this::class.java.requireResourceAsText("internal/unixStartScript.txt")) - (it.windowsStartScriptGenerator as TemplateBasedScriptGenerator).template = - project.resources.text.fromString(this::class.java.requireResourceAsText("internal/windowsStartScript.txt")) - it.description = "Creates OS specific scripts to run the project as a JVM application using the shadow jar" - it.group = ApplicationPlugin.APPLICATION_GROUP - it.classpath = project.files(shadowJar) - it.conventionMapping.map("mainClassName") { javaApplication.mainClass.get() } - it.conventionMapping.map("applicationName") { javaApplication.applicationName } - it.conventionMapping.map("outputDir") { project.layout.buildDirectory.dir("scriptsShadow").get().asFile } - it.conventionMapping.map("defaultJvmOpts") { javaApplication.applicationDefaultJvmArgs } - it.inputs.files(project.files(shadowJar)) - } + protected open fun addCreateScriptsTask() { + project.tasks.register(SHADOW_SCRIPTS_TASK_NAME, CreateStartScripts::class.java) { + (it.unixStartScriptGenerator as TemplateBasedScriptGenerator).template = + project.resources.text.fromString(this::class.java.requireResourceAsText("internal/unixStartScript.txt")) + (it.windowsStartScriptGenerator as TemplateBasedScriptGenerator).template = + project.resources.text.fromString(this::class.java.requireResourceAsText("internal/windowsStartScript.txt")) + it.description = "Creates OS specific scripts to run the project as a JVM application using the shadow jar" + it.group = ApplicationPlugin.APPLICATION_GROUP + it.classpath = project.files(shadowJar) + it.conventionMapping.map("mainClassName") { javaApplication.mainClass.get() } + it.conventionMapping.map("applicationName") { javaApplication.applicationName } + it.conventionMapping.map("outputDir") { project.layout.buildDirectory.dir("scriptsShadow").get().asFile } + it.conventionMapping.map("defaultJvmOpts") { javaApplication.applicationDefaultJvmArgs } + it.inputs.files(project.files(shadowJar)) } + } - protected open fun configureInstallTask() { - project.tasks.named(SHADOW_INSTALL_TASK_NAME, Sync::class.java).configure { task -> - val applicationName = project.providers.provider { javaApplication.applicationName } + protected open fun configureInstallTask() { + project.tasks.named(SHADOW_INSTALL_TASK_NAME, Sync::class.java).configure { task -> + val applicationName = project.providers.provider { javaApplication.applicationName } - task.doFirst { - if ( - !task.destinationDir.listFiles().isNullOrEmpty() && - ( - !task.destinationDir.resolve("lib").isDirectory || - !task.destinationDir.resolve("bin").isDirectory - ) - ) { - throw GradleException( - "The specified installation directory '${task.destinationDir}' is neither empty nor does it contain an installation for '${applicationName.get()}'.\n" + - "If you really want to install to this directory, delete it and run the install task again.\n" + - "Alternatively, choose a different installation directory.", - ) - } - } - task.doLast { - task.eachFile { - if (it.path == "bin/${applicationName.get()}") { - it.mode = 0x755 - } - } - } + task.doFirst { + if ( + !task.destinationDir.listFiles().isNullOrEmpty() && + ( + !task.destinationDir.resolve("lib").isDirectory || + !task.destinationDir.resolve("bin").isDirectory + ) + ) { + throw GradleException( + "The specified installation directory '${task.destinationDir}' is neither empty nor does it contain an installation for '${applicationName.get()}'.\n" + + "If you really want to install to this directory, delete it and run the install task again.\n" + + "Alternatively, choose a different installation directory.", + ) + } + } + task.doLast { + task.eachFile { + if (it.path == "bin/${applicationName.get()}") { + it.mode = 0x755 + } } + } } + } - protected open fun configureDistSpec() { - project.extensions.getByType(DistributionContainer::class.java) - .register(ShadowBasePlugin.DISTRIBUTION_NAME) { distributions -> - distributions.contents { contents -> - contents.from(project.file("src/dist")) - contents.into("lib") { lib -> - lib.from(shadowJar) - lib.from(project.configurations.named(ShadowBasePlugin.CONFIGURATION_NAME)) - } - contents.into("bin") { bin -> - bin.from(project.tasks.named(SHADOW_SCRIPTS_TASK_NAME)) - bin.filePermissions { it.unix(493) } - } - } - } - } + protected open fun configureDistSpec() { + project.extensions.getByType(DistributionContainer::class.java) + .register(ShadowBasePlugin.DISTRIBUTION_NAME) { distributions -> + distributions.contents { contents -> + contents.from(project.file("src/dist")) + contents.into("lib") { lib -> + lib.from(shadowJar) + lib.from(project.configurations.named(ShadowBasePlugin.CONFIGURATION_NAME)) + } + contents.into("bin") { bin -> + bin.from(project.tasks.named(SHADOW_SCRIPTS_TASK_NAME)) + bin.filePermissions { it.unix(493) } + } + } + } + } - protected val shadowJar: TaskProvider - get() = project.tasks.named(ShadowJavaPlugin.SHADOW_JAR_TASK_NAME, ShadowJar::class.java) + protected val shadowJar: TaskProvider + get() = project.tasks.named(ShadowJavaPlugin.SHADOW_JAR_TASK_NAME, ShadowJar::class.java) - companion object { - const val SHADOW_RUN_TASK_NAME: String = "runShadow" - const val SHADOW_SCRIPTS_TASK_NAME: String = "startShadowScripts" - const val SHADOW_INSTALL_TASK_NAME: String = "installShadowDist" - } + companion object { + const val SHADOW_RUN_TASK_NAME: String = "runShadow" + const val SHADOW_SCRIPTS_TASK_NAME: String = "startShadowScripts" + const val SHADOW_INSTALL_TASK_NAME: String = "installShadowDist" + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.kt index 94c8a051e..c095ae9c3 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.kt @@ -8,24 +8,24 @@ import org.gradle.util.GradleVersion abstract class ShadowBasePlugin : Plugin { - override fun apply(project: Project) { - if (GradleVersion.current() < GradleVersion.version("8.3")) { - throw GradleException("This version of Shadow supports Gradle 8.3+ only. Please upgrade.") - } - project.extensions.create(EXTENSION_NAME, ShadowExtension::class.java, project) - project.configurations.create(CONFIGURATION_NAME) - project.tasks.register(KnowsTask.NAME, KnowsTask::class.java) { knows -> - knows.group = GROUP_NAME - knows.description = KnowsTask.DESC - } + override fun apply(project: Project) { + if (GradleVersion.current() < GradleVersion.version("8.3")) { + throw GradleException("This version of Shadow supports Gradle 8.3+ only. Please upgrade.") } - - companion object { - const val SHADOW: String = "shadow" - const val GROUP_NAME: String = SHADOW - const val EXTENSION_NAME: String = SHADOW - const val CONFIGURATION_NAME: String = SHADOW - const val COMPONENT_NAME: String = SHADOW - const val DISTRIBUTION_NAME: String = SHADOW + project.extensions.create(EXTENSION_NAME, ShadowExtension::class.java, project) + project.configurations.create(CONFIGURATION_NAME) + project.tasks.register(KnowsTask.NAME, KnowsTask::class.java) { knows -> + knows.group = GROUP_NAME + knows.description = KnowsTask.DESC } + } + + companion object { + const val SHADOW: String = "shadow" + const val GROUP_NAME: String = SHADOW + const val EXTENSION_NAME: String = SHADOW + const val CONFIGURATION_NAME: String = SHADOW + const val COMPONENT_NAME: String = SHADOW + const val DISTRIBUTION_NAME: String = SHADOW + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.kt index 6b22883a1..871f15d7b 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.kt @@ -5,10 +5,10 @@ import org.gradle.api.publish.maven.MavenPublication @Deprecated("This is deprecated since 8.3.2") abstract class ShadowExtension(project: Project) { - private val components = project.components + private val components = project.components - @Deprecated("configure publication using component.shadow directly.") - fun component(publication: MavenPublication) { - publication.from(components.findByName(ShadowBasePlugin.COMPONENT_NAME)) - } + @Deprecated("configure publication using component.shadow directly.") + fun component(publication: MavenPublication) { + publication.from(components.findByName(ShadowBasePlugin.COMPONENT_NAME)) + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt index 5eb6fecd5..35dfdf3b7 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt @@ -18,94 +18,94 @@ import org.gradle.jvm.tasks.Jar import org.gradle.plugin.devel.plugins.JavaGradlePluginPlugin abstract class ShadowJavaPlugin @Inject constructor( - private val softwareComponentFactory: SoftwareComponentFactory, + private val softwareComponentFactory: SoftwareComponentFactory, ) : Plugin { - override fun apply(project: Project) { - val shadowConfiguration = project.configurations.getByName(ShadowBasePlugin.CONFIGURATION_NAME) - val shadowTaskProvider = configureShadowTask(project, shadowConfiguration) + override fun apply(project: Project) { + val shadowConfiguration = project.configurations.getByName(ShadowBasePlugin.CONFIGURATION_NAME) + val shadowTaskProvider = configureShadowTask(project, shadowConfiguration) - project.configurations.named(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME) { - it.extendsFrom(shadowConfiguration) - } + project.configurations.named(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME) { + it.extendsFrom(shadowConfiguration) + } - val shadowRuntimeElements = project.configurations.create(SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME) { - it.extendsFrom(shadowConfiguration) - it.isCanBeConsumed = true - it.isCanBeResolved = false - it.attributes { attr -> - attr.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage::class.java, Usage.JAVA_RUNTIME)) - attr.attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category::class.java, Category.LIBRARY)) - attr.attribute( - LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, - project.objects.named(LibraryElements::class.java, LibraryElements.JAR), - ) - attr.attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling::class.java, Bundling.SHADOWED)) - } - it.outgoing.artifact(shadowTaskProvider) - } + val shadowRuntimeElements = project.configurations.create(SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME) { + it.extendsFrom(shadowConfiguration) + it.isCanBeConsumed = true + it.isCanBeResolved = false + it.attributes { attr -> + attr.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage::class.java, Usage.JAVA_RUNTIME)) + attr.attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category::class.java, Category.LIBRARY)) + attr.attribute( + LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, + project.objects.named(LibraryElements::class.java, LibraryElements.JAR), + ) + attr.attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling::class.java, Bundling.SHADOWED)) + } + it.outgoing.artifact(shadowTaskProvider) + } - project.components.named("java", AdhocComponentWithVariants::class.java) { - it.addVariantsFromConfiguration(shadowRuntimeElements) { variant -> - variant.mapToOptional() - } - } + project.components.named("java", AdhocComponentWithVariants::class.java) { + it.addVariantsFromConfiguration(shadowRuntimeElements) { variant -> + variant.mapToOptional() + } + } - val shadowComponent = softwareComponentFactory.adhoc(ShadowBasePlugin.COMPONENT_NAME) - project.components.add(shadowComponent) - shadowComponent.addVariantsFromConfiguration(shadowRuntimeElements) { variant -> - variant.mapToMavenScope("runtime") - } + val shadowComponent = softwareComponentFactory.adhoc(ShadowBasePlugin.COMPONENT_NAME) + project.components.add(shadowComponent) + shadowComponent.addVariantsFromConfiguration(shadowRuntimeElements) { variant -> + variant.mapToMavenScope("runtime") + } - project.plugins.withType(JavaGradlePluginPlugin::class.java).configureEach { - // Remove the gradleApi so it isn't merged into the jar file. - // This is required because 'java-gradle-plugin' adds gradleApi() to the 'api' configuration. - // See https://github.com/gradle/gradle/blob/972c3e5c6ef990dd2190769c1ce31998a9402a79/subprojects/plugin-development/src/main/java/org/gradle/plugin/de - project.configurations.named(JavaPlugin.API_CONFIGURATION_NAME) { - it.dependencies.remove(project.dependencies.gradleApi()) - } - // Compile only gradleApi() to make sure the plugin can compile against Gradle API. - project.configurations.named(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME) { - it.dependencies.add(project.dependencies.gradleApi()) - } - } + project.plugins.withType(JavaGradlePluginPlugin::class.java).configureEach { + // Remove the gradleApi so it isn't merged into the jar file. + // This is required because 'java-gradle-plugin' adds gradleApi() to the 'api' configuration. + // See https://github.com/gradle/gradle/blob/972c3e5c6ef990dd2190769c1ce31998a9402a79/subprojects/plugin-development/src/main/java/org/gradle/plugin/de + project.configurations.named(JavaPlugin.API_CONFIGURATION_NAME) { + it.dependencies.remove(project.dependencies.gradleApi()) + } + // Compile only gradleApi() to make sure the plugin can compile against Gradle API. + project.configurations.named(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME) { + it.dependencies.add(project.dependencies.gradleApi()) + } } + } - private fun configureShadowTask(project: Project, shadowConfiguration: Configuration): TaskProvider { - val sourceSets = project.extensions.getByType(SourceSetContainer::class.java) - val jarTask = project.tasks.named(JavaPlugin.JAR_TASK_NAME, Jar::class.java) - val taskProvider = project.tasks.register(SHADOW_JAR_TASK_NAME, ShadowJar::class.java) { shadow -> - shadow.group = ShadowBasePlugin.GROUP_NAME - shadow.description = "Create a combined JAR of project and runtime dependencies" - shadow.archiveClassifier.set("all") - shadow.manifest.inheritFrom(jarTask.get().manifest) - val attrProvider = jarTask.map { it.manifest.attributes["Class-Path"]?.toString().orEmpty() } - val files = project.objects.fileCollection().from(shadowConfiguration) - shadow.doFirst { - if (!files.isEmpty) { - val attrs = listOf(attrProvider.getOrElse("")) + files.map { it.name } - shadow.manifest.attributes["Class-Path"] = attrs.joinToString(" ").trim() - } - } - shadow.from(sourceSets.getByName("main").output) - shadow.configurations = listOf( - project.configurations.findByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME) - ?: project.configurations.getByName("runtime"), - ) - shadow.exclude( - "META-INF/INDEX.LIST", - "META-INF/*.SF", - "META-INF/*.DSA", - "META-INF/*.RSA", - "module-info.class", - ) + private fun configureShadowTask(project: Project, shadowConfiguration: Configuration): TaskProvider { + val sourceSets = project.extensions.getByType(SourceSetContainer::class.java) + val jarTask = project.tasks.named(JavaPlugin.JAR_TASK_NAME, Jar::class.java) + val taskProvider = project.tasks.register(SHADOW_JAR_TASK_NAME, ShadowJar::class.java) { shadow -> + shadow.group = ShadowBasePlugin.GROUP_NAME + shadow.description = "Create a combined JAR of project and runtime dependencies" + shadow.archiveClassifier.set("all") + shadow.manifest.inheritFrom(jarTask.get().manifest) + val attrProvider = jarTask.map { it.manifest.attributes["Class-Path"]?.toString().orEmpty() } + val files = project.objects.fileCollection().from(shadowConfiguration) + shadow.doFirst { + if (!files.isEmpty) { + val attrs = listOf(attrProvider.getOrElse("")) + files.map { it.name } + shadow.manifest.attributes["Class-Path"] = attrs.joinToString(" ").trim() } - project.artifacts.add(shadowConfiguration.name, taskProvider) - return taskProvider + } + shadow.from(sourceSets.getByName("main").output) + shadow.configurations = listOf( + project.configurations.findByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME) + ?: project.configurations.getByName("runtime"), + ) + shadow.exclude( + "META-INF/INDEX.LIST", + "META-INF/*.SF", + "META-INF/*.DSA", + "META-INF/*.RSA", + "module-info.class", + ) } + project.artifacts.add(shadowConfiguration.name, taskProvider) + return taskProvider + } - companion object { - const val SHADOW_JAR_TASK_NAME: String = "shadowJar" - const val SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME: String = "shadowRuntimeElements" - } + companion object { + const val SHADOW_JAR_TASK_NAME: String = "shadowJar" + const val SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME: String = "shadowRuntimeElements" + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPlugin.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPlugin.kt index 0b5c58e3c..93fce387e 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPlugin.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPlugin.kt @@ -8,21 +8,21 @@ import org.gradle.api.plugins.JavaPlugin abstract class ShadowPlugin : Plugin { - override fun apply(project: Project) { - project.run { - plugins.apply(ShadowBasePlugin::class.java) - plugins.withType(JavaPlugin::class.java) { - plugins.apply(ShadowJavaPlugin::class.java) - } - plugins.withType(ApplicationPlugin::class.java) { - plugins.apply(ShadowApplicationPlugin::class.java) - } - // Apply the legacy plugin last - // Because we apply the ShadowJavaPlugin/ShadowApplication plugin in a withType callback for the - // respective JavaPlugin/ApplicationPlugin, it may still apply before the shadowJar task is created etc. - // If the user applies shadow before those plugins. However, this is fine, because this was also - // the behavior with the old plugin when applying in that order. - plugins.apply(LegacyShadowPlugin::class.java) - } + override fun apply(project: Project) { + project.run { + plugins.apply(ShadowBasePlugin::class.java) + plugins.withType(JavaPlugin::class.java) { + plugins.apply(ShadowJavaPlugin::class.java) + } + plugins.withType(ApplicationPlugin::class.java) { + plugins.apply(ShadowApplicationPlugin::class.java) + } + // Apply the legacy plugin last + // Because we apply the ShadowJavaPlugin/ShadowApplication plugin in a withType callback for the + // respective JavaPlugin/ApplicationPlugin, it may still apply before the shadowJar task is created etc. + // If the user applies shadow before those plugins. However, this is fine, because this was also + // the behavior with the old plugin when applying in that order. + plugins.apply(LegacyShadowPlugin::class.java) } + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowStats.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowStats.kt index 01cc1b761..f59d9a5fd 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowStats.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowStats.kt @@ -3,63 +3,63 @@ package com.github.jengelman.gradle.plugins.shadow import org.gradle.api.GradleException open class ShadowStats { - open var totalTime: Long = 0 - open var jarStartTime: Long = 0 - open var jarEndTime: Long = 0 - open var jarCount: Int = 1 - open var processingJar: Boolean = false - open val relocations: MutableMap = mutableMapOf() + open var totalTime: Long = 0 + open var jarStartTime: Long = 0 + open var jarEndTime: Long = 0 + open var jarCount: Int = 1 + open var processingJar: Boolean = false + open val relocations: MutableMap = mutableMapOf() - open val relocationString: String - get() { - return relocations.map { (k, v) -> "$k → $v" } - .sorted() - .joinToString("\n") - } + open val relocationString: String + get() { + return relocations.map { (k, v) -> "$k → $v" } + .sorted() + .joinToString("\n") + } - open val jarTiming: Long - get() = jarEndTime - jarStartTime + open val jarTiming: Long + get() = jarEndTime - jarStartTime - open val totalTimeSecs: Double - get() = totalTime / 1000.0 + open val totalTimeSecs: Double + get() = totalTime / 1000.0 - open val averageTimePerJar: Double - get() = totalTime / jarCount.toDouble() + open val averageTimePerJar: Double + get() = totalTime / jarCount.toDouble() - open val averageTimeSecsPerJar: Double - get() = averageTimePerJar / 1000.0 + open val averageTimeSecsPerJar: Double + get() = averageTimePerJar / 1000.0 - open val buildScanData: Map - get() = mapOf( - "dependencies" to jarCount.toString(), - "relocations" to relocationString, - ) + open val buildScanData: Map + get() = mapOf( + "dependencies" to jarCount.toString(), + "relocations" to relocationString, + ) - open fun relocate(src: String, dst: String) { - relocations[src] = dst - } + open fun relocate(src: String, dst: String) { + relocations[src] = dst + } - open fun startJar() { - if (processingJar) throw GradleException("Can only time one entry at a time") - processingJar = true - jarStartTime = System.currentTimeMillis() - } + open fun startJar() { + if (processingJar) throw GradleException("Can only time one entry at a time") + processingJar = true + jarStartTime = System.currentTimeMillis() + } - open fun finishJar() { - if (processingJar) { - jarEndTime = System.currentTimeMillis() - jarCount++ - totalTime += jarTiming - processingJar = false - } + open fun finishJar() { + if (processingJar) { + jarEndTime = System.currentTimeMillis() + jarCount++ + totalTime += jarTiming + processingJar = false } + } - open fun printStats() { - println(this) - } + open fun printStats() { + println(this) + } - override fun toString(): String { - return """ + override fun toString(): String { + return """ ******************* GRADLE SHADOW STATS @@ -67,6 +67,6 @@ open class ShadowStats { Total Time: ${totalTimeSecs}s [${totalTime}ms] Average Time/Jar: ${averageTimeSecsPerJar}s [${averageTimePerJar}ms] ******************* - """.trimIndent() - } + """.trimIndent() + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/impl/RelocatorRemapper.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/impl/RelocatorRemapper.kt index be5353bf8..fc0335803 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/impl/RelocatorRemapper.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/impl/RelocatorRemapper.kt @@ -14,51 +14,51 @@ import org.objectweb.asm.commons.Remapper * @author John Engelman */ open class RelocatorRemapper( - private val relocators: List, - private val stats: ShadowStats, + private val relocators: List, + private val stats: ShadowStats, ) : Remapper() { - private val classPattern: Pattern = Pattern.compile("(\\[*)?L(.+)") + private val classPattern: Pattern = Pattern.compile("(\\[*)?L(.+)") - open fun hasRelocators(): Boolean = relocators.isNotEmpty() + open fun hasRelocators(): Boolean = relocators.isNotEmpty() - override fun mapValue(value: Any): Any { - return if (value is String) { - map(value) - } else { - super.mapValue(value) - } + override fun mapValue(value: Any): Any { + return if (value is String) { + map(value) + } else { + super.mapValue(value) } + } - override fun map(name: String): String { - var newName = name - var prefix = "" - var suffix = "" + override fun map(name: String): String { + var newName = name + var prefix = "" + var suffix = "" - val matcher = classPattern.matcher(newName) - if (matcher.matches()) { - prefix = matcher.group(1) + "L" - suffix = "" - newName = matcher.group(2) - } - - for (relocator in relocators) { - if (relocator.canRelocateClass(newName)) { - val classContext = RelocateClassContext.builder().className(newName).stats(stats).build() - return prefix + relocator.relocateClass(classContext) + suffix - } else if (relocator.canRelocatePath(newName)) { - val pathContext = RelocatePathContext.builder().path(newName).stats(stats).build() - return prefix + relocator.relocatePath(pathContext) + suffix - } - } - - return name + val matcher = classPattern.matcher(newName) + if (matcher.matches()) { + prefix = matcher.group(1) + "L" + suffix = "" + newName = matcher.group(2) } - open fun mapPath(path: String): String { - return map(path.substring(0, path.indexOf('.'))) + for (relocator in relocators) { + if (relocator.canRelocateClass(newName)) { + val classContext = RelocateClassContext.builder().className(newName).stats(stats).build() + return prefix + relocator.relocateClass(classContext) + suffix + } else if (relocator.canRelocatePath(newName)) { + val pathContext = RelocatePathContext.builder().path(newName).stats(stats).build() + return prefix + relocator.relocatePath(pathContext) + suffix + } } - open fun mapPath(path: ShadowCopyAction.RelativeArchivePath): String { - return mapPath(path.pathString) - } + return name + } + + open fun mapPath(path: String): String { + return map(path.substring(0, path.indexOf('.'))) + } + + open fun mapPath(path: ShadowCopyAction.RelativeArchivePath): String { + return mapPath(path.pathString) + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/AbstractDependencyFilter.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/AbstractDependencyFilter.kt index 087e27930..74144effe 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/AbstractDependencyFilter.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/AbstractDependencyFilter.kt @@ -11,95 +11,95 @@ import org.gradle.api.specs.Spec import org.gradle.api.specs.Specs internal sealed class AbstractDependencyFilter( - private val project: Project, + private val project: Project, ) : DependencyFilter { - protected val includeSpecs: MutableList> = mutableListOf() - protected val excludeSpecs: MutableList> = mutableListOf() + protected val includeSpecs: MutableList> = mutableListOf() + protected val excludeSpecs: MutableList> = mutableListOf() - protected abstract fun resolve( - dependencies: Set, - includedDependencies: MutableSet, - excludedDependencies: MutableSet, - ) + protected abstract fun resolve( + dependencies: Set, + includedDependencies: MutableSet, + excludedDependencies: MutableSet, + ) - override fun resolve(configuration: FileCollection): FileCollection { - val includedDeps = mutableSetOf() - val excludedDeps = mutableSetOf() - configuration as Configuration - resolve(configuration.resolvedConfiguration.firstLevelModuleDependencies, includedDeps, excludedDeps) - return project.files(configuration.files) - - project.files(excludedDeps.flatMap { it.moduleArtifacts.map(ResolvedArtifact::getFile) }) - } + override fun resolve(configuration: FileCollection): FileCollection { + val includedDeps = mutableSetOf() + val excludedDeps = mutableSetOf() + configuration as Configuration + resolve(configuration.resolvedConfiguration.firstLevelModuleDependencies, includedDeps, excludedDeps) + return project.files(configuration.files) - + project.files(excludedDeps.flatMap { it.moduleArtifacts.map(ResolvedArtifact::getFile) }) + } - override fun resolve(configurations: Collection): FileCollection { - return configurations.map { resolve(it) } - .reduceOrNull { acc, fileCollection -> acc + fileCollection } - ?: project.files() - } + override fun resolve(configurations: Collection): FileCollection { + return configurations.map { resolve(it) } + .reduceOrNull { acc, fileCollection -> acc + fileCollection } + ?: project.files() + } - /** - * Exclude dependencies that match the provided spec. - */ - override fun exclude(spec: Spec): DependencyFilter = apply { - excludeSpecs.add(spec) - } + /** + * Exclude dependencies that match the provided spec. + */ + override fun exclude(spec: Spec): DependencyFilter = apply { + excludeSpecs.add(spec) + } - /** - * Include dependencies that match the provided spec. - */ - override fun include(spec: Spec): DependencyFilter = apply { - includeSpecs.add(spec) - } + /** + * Include dependencies that match the provided spec. + */ + override fun include(spec: Spec): DependencyFilter = apply { + includeSpecs.add(spec) + } - /** - * Create a spec that matches the provided project notation on group, name, and version. - */ - override fun project(notation: Map): Spec { - return dependency(dependency = project.dependencies.project(notation)) - } + /** + * Create a spec that matches the provided project notation on group, name, and version. + */ + override fun project(notation: Map): Spec { + return dependency(dependency = project.dependencies.project(notation)) + } - /** - * Create a spec that matches the default configuration for the provided project path on group, name, and version. - */ - override fun project(notation: String): Spec { - return dependency( - dependency = project.dependencies.project( - mapOf( - "path" to notation, - "configuration" to "default", - ), - ), - ) - } + /** + * Create a spec that matches the default configuration for the provided project path on group, name, and version. + */ + override fun project(notation: String): Spec { + return dependency( + dependency = project.dependencies.project( + mapOf( + "path" to notation, + "configuration" to "default", + ), + ), + ) + } - /** - * Create a spec that matches dependencies using the provided notation on group, name, and version. - */ - override fun dependency(notation: Any): Spec { - return dependency(dependency = project.dependencies.create(notation)) - } + /** + * Create a spec that matches dependencies using the provided notation on group, name, and version. + */ + override fun dependency(notation: Any): Spec { + return dependency(dependency = project.dependencies.create(notation)) + } - /** - * Create a spec that matches the provided dependency on group, name, and version. - */ - override fun dependency(dependency: Dependency): Spec { - return Spec { resolvedDependency -> - (dependency.group == null || resolvedDependency.moduleGroup.matches(dependency.group!!.toRegex())) && - resolvedDependency.moduleName.matches(dependency.name.toRegex()) && - (dependency.version == null || resolvedDependency.moduleVersion.matches(dependency.version!!.toRegex())) - } + /** + * Create a spec that matches the provided dependency on group, name, and version. + */ + override fun dependency(dependency: Dependency): Spec { + return Spec { resolvedDependency -> + (dependency.group == null || resolvedDependency.moduleGroup.matches(dependency.group!!.toRegex())) && + resolvedDependency.moduleName.matches(dependency.name.toRegex()) && + (dependency.version == null || resolvedDependency.moduleVersion.matches(dependency.version!!.toRegex())) } + } - /** - * Create a spec that matches the provided closure. - */ - override fun dependency(closure: Closure<*>): Spec { - return Specs.convertClosureToSpec(closure) - } + /** + * Create a spec that matches the provided closure. + */ + override fun dependency(closure: Closure<*>): Spec { + return Specs.convertClosureToSpec(closure) + } - protected fun ResolvedDependency.isIncluded(): Boolean { - val include = includeSpecs.isEmpty() || includeSpecs.any { it.isSatisfiedBy(this) } - val exclude = excludeSpecs.isNotEmpty() && excludeSpecs.any { it.isSatisfiedBy(this) } - return include && !exclude - } + protected fun ResolvedDependency.isIncluded(): Boolean { + val include = includeSpecs.isEmpty() || includeSpecs.any { it.isSatisfiedBy(this) } + val exclude = excludeSpecs.isNotEmpty() && excludeSpecs.any { it.isSatisfiedBy(this) } + return include && !exclude + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.kt index 3f6be3d9b..13f6730f7 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.kt @@ -7,22 +7,22 @@ import java.util.Date import java.util.Properties internal class CleanProperties : Properties() { - @Throws(IOException::class) - override fun store(writer: Writer, comments: String) { - super.store(StripCommentsWithTimestampBufferedWriter(writer), comments) - } + @Throws(IOException::class) + override fun store(writer: Writer, comments: String) { + super.store(StripCommentsWithTimestampBufferedWriter(writer), comments) + } - private class StripCommentsWithTimestampBufferedWriter(out: Writer) : BufferedWriter(out) { - private val lengthOfExpectedTimestamp = ("#" + Date().toString()).length + private class StripCommentsWithTimestampBufferedWriter(out: Writer) : BufferedWriter(out) { + private val lengthOfExpectedTimestamp = ("#" + Date().toString()).length - @Throws(IOException::class) - override fun write(str: String) { - if (str.couldBeCommentWithTimestamp) return - super.write(str) - } + @Throws(IOException::class) + override fun write(str: String) { + if (str.couldBeCommentWithTimestamp) return + super.write(str) + } - private val String?.couldBeCommentWithTimestamp: Boolean get() { - return this != null && startsWith("#") && length == lengthOfExpectedTimestamp - } + private val String?.couldBeCommentWithTimestamp: Boolean get() { + return this != null && startsWith("#") && length == lengthOfExpectedTimestamp } + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilter.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilter.kt index 25604eaf2..b10468286 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilter.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilter.kt @@ -4,17 +4,17 @@ import org.gradle.api.Project import org.gradle.api.artifacts.ResolvedDependency internal class DefaultDependencyFilter( - project: Project, + project: Project, ) : AbstractDependencyFilter(project) { - override fun resolve( - dependencies: Set, - includedDependencies: MutableSet, - excludedDependencies: MutableSet, - ) { - dependencies.forEach { - if (if (it.isIncluded()) includedDependencies.add(it) else excludedDependencies.add(it)) { - resolve(it.children, includedDependencies, excludedDependencies) - } - } + override fun resolve( + dependencies: Set, + includedDependencies: MutableSet, + excludedDependencies: MutableSet, + ) { + dependencies.forEach { + if (if (it.isIncluded()) includedDependencies.add(it) else excludedDependencies.add(it)) { + resolve(it.children, includedDependencies, excludedDependencies) + } } + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultZipCompressor.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultZipCompressor.kt index 244bccd84..d002cb2b4 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultZipCompressor.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultZipCompressor.kt @@ -7,19 +7,19 @@ import org.apache.tools.zip.ZipOutputStream import org.gradle.api.UncheckedIOException internal class DefaultZipCompressor( - allowZip64Mode: Boolean, - private val entryCompressionMethod: Int, + allowZip64Mode: Boolean, + private val entryCompressionMethod: Int, ) : ZipCompressor { - private val zip64Mode = if (allowZip64Mode) Zip64Mode.AsNeeded else Zip64Mode.Never + private val zip64Mode = if (allowZip64Mode) Zip64Mode.AsNeeded else Zip64Mode.Never - override fun createArchiveOutputStream(destination: File): ZipOutputStream { - try { - return ZipOutputStream(destination).apply { - setUseZip64(zip64Mode) - setMethod(entryCompressionMethod) - } - } catch (e: Exception) { - throw UncheckedIOException("Unable to create ZIP output stream for file $destination.", e) - } + override fun createArchiveOutputStream(destination: File): ZipOutputStream { + try { + return ZipOutputStream(destination).apply { + setUseZip64(zip64Mode) + setMethod(entryCompressionMethod) + } + } catch (e: Exception) { + throw UncheckedIOException("Unable to create ZIP output stream for file $destination.", e) } + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DependencyFilter.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DependencyFilter.kt index 993165cf0..b6ddff4b3 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DependencyFilter.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DependencyFilter.kt @@ -7,48 +7,48 @@ import org.gradle.api.file.FileCollection import org.gradle.api.specs.Spec interface DependencyFilter { - /** - * Resolve a FileCollection against the include/exclude rules in the filter. - */ - fun resolve(configuration: FileCollection): FileCollection - - /** - * Resolve all FileCollections against the include/exclude rules in the filter and combine the results. - */ - fun resolve(configurations: Collection): FileCollection - - /** - * Exclude dependencies that match the provided spec. - */ - fun exclude(spec: Spec): DependencyFilter - - /** - * Include dependencies that match the provided spec. - */ - fun include(spec: Spec): DependencyFilter - - /** - * Create a spec that matches the provided project notation on group, name, and version. - */ - fun project(notation: Map): Spec - - /** - * Create a spec that matches the default configuration for the provided project path on group, name, and version. - */ - fun project(notation: String): Spec - - /** - * Create a spec that matches dependencies using the provided notation on group, name, and version. - */ - fun dependency(notation: Any): Spec - - /** - * Create a spec that matches the provided dependency on group, name, and version. - */ - fun dependency(dependency: Dependency): Spec - - /** - * Create a spec that matches the provided closure. - */ - fun dependency(closure: Closure<*>): Spec + /** + * Resolve a FileCollection against the include/exclude rules in the filter. + */ + fun resolve(configuration: FileCollection): FileCollection + + /** + * Resolve all FileCollections against the include/exclude rules in the filter and combine the results. + */ + fun resolve(configurations: Collection): FileCollection + + /** + * Exclude dependencies that match the provided spec. + */ + fun exclude(spec: Spec): DependencyFilter + + /** + * Include dependencies that match the provided spec. + */ + fun include(spec: Spec): DependencyFilter + + /** + * Create a spec that matches the provided project notation on group, name, and version. + */ + fun project(notation: Map): Spec + + /** + * Create a spec that matches the default configuration for the provided project path on group, name, and version. + */ + fun project(notation: String): Spec + + /** + * Create a spec that matches dependencies using the provided notation on group, name, and version. + */ + fun dependency(notation: Any): Spec + + /** + * Create a spec that matches the provided dependency on group, name, and version. + */ + fun dependency(dependency: Dependency): Spec + + /** + * Create a spec that matches the provided closure. + */ + fun dependency(closure: Closure<*>): Spec } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/JavaJarExec.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/JavaJarExec.kt index 316320d82..3f62f20a3 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/JavaJarExec.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/JavaJarExec.kt @@ -6,17 +6,17 @@ import org.gradle.api.tasks.JavaExec import org.gradle.api.tasks.TaskAction internal abstract class JavaJarExec : JavaExec() { - @get:InputFile - abstract val jarFile: RegularFileProperty + @get:InputFile + abstract val jarFile: RegularFileProperty - @TaskAction - override fun exec() { - val allArgs = buildList { - add(jarFile.get().asFile.path) - // Must cast args to List here to avoid type mismatch. - addAll(args as List) - } - setArgs(allArgs) - super.exec() + @TaskAction + override fun exec() { + val allArgs = buildList { + add(jarFile.get().asFile.path) + // Must cast args to List here to avoid type mismatch. + addAll(args as List) } + setArgs(allArgs) + super.exec() + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeDependencyFilter.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeDependencyFilter.kt index df6bf5bc2..44b4d3a55 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeDependencyFilter.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeDependencyFilter.kt @@ -4,27 +4,27 @@ import org.gradle.api.Project import org.gradle.api.artifacts.ResolvedDependency internal class MinimizeDependencyFilter( - project: Project, + project: Project, ) : AbstractDependencyFilter(project) { - override fun resolve( - dependencies: Set, - includedDependencies: MutableSet, - excludedDependencies: MutableSet, - ) { - dependencies.forEach { - if (it.isIncluded() && !isParentExcluded(excludedDependencies, it)) { - includedDependencies.add(it) - } else { - excludedDependencies.add(it) - } - resolve(it.children, includedDependencies, excludedDependencies) - } + override fun resolve( + dependencies: Set, + includedDependencies: MutableSet, + excludedDependencies: MutableSet, + ) { + dependencies.forEach { + if (it.isIncluded() && !isParentExcluded(excludedDependencies, it)) { + includedDependencies.add(it) + } else { + excludedDependencies.add(it) + } + resolve(it.children, includedDependencies, excludedDependencies) } + } - private fun isParentExcluded( - excludedDependencies: Set, - dependency: ResolvedDependency, - ): Boolean { - return excludedDependencies.any { it in dependency.parents } - } + private fun isParentExcluded( + excludedDependencies: Set, + dependency: ResolvedDependency, + ): Boolean { + return excludedDependencies.any { it in dependency.parents } + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/UnusedTracker.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/UnusedTracker.kt index 504459d60..269f1b15a 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/UnusedTracker.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/UnusedTracker.kt @@ -13,79 +13,79 @@ import org.vafer.jdependency.ClazzpathUnit /** Tracks unused classes in the project classpath. */ internal class UnusedTracker private constructor( - classDirs: Iterable, - classJars: FileCollection, - private val _toMinimize: FileCollection, + classDirs: Iterable, + classJars: FileCollection, + private val _toMinimize: FileCollection, ) { - private val projectUnits: List - private val cp = Clazzpath() + private val projectUnits: List + private val cp = Clazzpath() - init { - projectUnits = classDirs.map { cp.addClazzpathUnit(it) } + classJars.map { cp.addClazzpathUnit(it) } - } + init { + projectUnits = classDirs.map { cp.addClazzpathUnit(it) } + classJars.map { cp.addClazzpathUnit(it) } + } - @get:InputFiles - val toMinimize: FileCollection get() = _toMinimize + @get:InputFiles + val toMinimize: FileCollection get() = _toMinimize - fun findUnused(): Set { - val unused = cp.clazzes.toMutableSet() - for (cpu in projectUnits) { - unused.removeAll(cpu.clazzes) - unused.removeAll(cpu.transitiveDependencies) - } - return unused.map { it.name }.toSet() + fun findUnused(): Set { + val unused = cp.clazzes.toMutableSet() + for (cpu in projectUnits) { + unused.removeAll(cpu.clazzes) + unused.removeAll(cpu.transitiveDependencies) } + return unused.map { it.name }.toSet() + } - fun addDependency(jarOrDir: File) { - if (_toMinimize.contains(jarOrDir)) { - cp.addClazzpathUnit(jarOrDir) - } + fun addDependency(jarOrDir: File) { + if (_toMinimize.contains(jarOrDir)) { + cp.addClazzpathUnit(jarOrDir) } + } - companion object { - @JvmStatic - fun forProject( - apiJars: FileCollection, - sourceSetsClassesDirs: Iterable, - toMinimize: FileCollection, - ): UnusedTracker { - return UnusedTracker(sourceSetsClassesDirs, apiJars, toMinimize) - } + companion object { + @JvmStatic + fun forProject( + apiJars: FileCollection, + sourceSetsClassesDirs: Iterable, + toMinimize: FileCollection, + ): UnusedTracker { + return UnusedTracker(sourceSetsClassesDirs, apiJars, toMinimize) + } - @JvmStatic - fun getApiJarsFromProject(project: Project): FileCollection { - val apiDependencies = project.configurations.findByName("api")?.dependencies - ?: return project.files() - val runtimeConfiguration = project.configurations.findByName("runtimeClasspath") - ?: project.configurations.getByName("runtime") - val apiJars = mutableListOf() - apiDependencies.forEach { dep -> - when (dep) { - is ProjectDependency -> { - apiJars.addAll(getApiJarsFromProject(dep.dependencyProject)) - addJar(runtimeConfiguration, dep, apiJars) - } - is SelfResolvingDependency -> { - apiJars.addAll(dep.resolve()) - } - else -> { - addJar(runtimeConfiguration, dep, apiJars) - apiJars.add(runtimeConfiguration.find { it.name.startsWith("${dep.name}-") } as File) - } - } - } - return project.files(apiJars) + @JvmStatic + fun getApiJarsFromProject(project: Project): FileCollection { + val apiDependencies = project.configurations.findByName("api")?.dependencies + ?: return project.files() + val runtimeConfiguration = project.configurations.findByName("runtimeClasspath") + ?: project.configurations.getByName("runtime") + val apiJars = mutableListOf() + apiDependencies.forEach { dep -> + when (dep) { + is ProjectDependency -> { + apiJars.addAll(getApiJarsFromProject(dep.dependencyProject)) + addJar(runtimeConfiguration, dep, apiJars) + } + is SelfResolvingDependency -> { + apiJars.addAll(dep.resolve()) + } + else -> { + addJar(runtimeConfiguration, dep, apiJars) + apiJars.add(runtimeConfiguration.find { it.name.startsWith("${dep.name}-") } as File) + } } + } + return project.files(apiJars) + } - private fun addJar(config: Configuration, dep: Dependency, result: MutableList) { - config.find { isProjectDependencyFile(it, dep) }?.let { result.add(it) } - } + private fun addJar(config: Configuration, dep: Dependency, result: MutableList) { + config.find { isProjectDependencyFile(it, dep) }?.let { result.add(it) } + } - private fun isProjectDependencyFile(file: File, dep: Dependency): Boolean { - val fileName = file.name - val dependencyName = dep.name - return fileName == "$dependencyName.jar" || - (fileName.startsWith("$dependencyName-") && fileName.endsWith(".jar")) - } + private fun isProjectDependencyFile(file: File, dep: Dependency): Boolean { + val fileName = file.name + val dependencyName = dep.name + return fileName == "$dependencyName.jar" || + (fileName.startsWith("$dependencyName-") && fileName.endsWith(".jar")) } + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/Utils.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/Utils.kt index 38179d9d1..24b0abb5d 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/Utils.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/Utils.kt @@ -3,9 +3,9 @@ package com.github.jengelman.gradle.plugins.shadow.internal import java.io.InputStream internal fun Class<*>.requireResourceAsText(name: String): String { - return requireResourceAsStream(name).bufferedReader().readText() + return requireResourceAsStream(name).bufferedReader().readText() } private fun Class<*>.requireResourceAsStream(name: String): InputStream { - return getResourceAsStream(name) ?: error("Resource $name not found.") + return getResourceAsStream(name) ?: error("Resource $name not found.") } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/legacy/LegacyShadowPlugin.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/legacy/LegacyShadowPlugin.kt index 834ee364d..45441c642 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/legacy/LegacyShadowPlugin.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/legacy/LegacyShadowPlugin.kt @@ -9,5 +9,5 @@ import org.gradle.api.Project * This allows older build logic to keep on working as if that old plugin ID was applied. */ abstract class LegacyShadowPlugin : Plugin { - override fun apply(project: Project): Unit = Unit + override fun apply(project: Project): Unit = Unit } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocateClassContext.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocateClassContext.kt index 8d3b321e5..ec06e07ff 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocateClassContext.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocateClassContext.kt @@ -3,20 +3,20 @@ package com.github.jengelman.gradle.plugins.shadow.relocation import com.github.jengelman.gradle.plugins.shadow.ShadowStats data class RelocateClassContext( - val className: String, - val stats: ShadowStats, + val className: String, + val stats: ShadowStats, ) { - class Builder { - private var className = "" - private var stats = ShadowStats() + class Builder { + private var className = "" + private var stats = ShadowStats() - fun className(className: String): Builder = apply { this.className = className } - fun stats(stats: ShadowStats): Builder = apply { this.stats = stats } - fun build(): RelocateClassContext = RelocateClassContext(className, stats) - } + fun className(className: String): Builder = apply { this.className = className } + fun stats(stats: ShadowStats): Builder = apply { this.stats = stats } + fun build(): RelocateClassContext = RelocateClassContext(className, stats) + } - companion object { - @JvmStatic - fun builder(): Builder = Builder() - } + companion object { + @JvmStatic + fun builder(): Builder = Builder() + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocatePathContext.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocatePathContext.kt index 87babb5d6..a9cf9cce9 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocatePathContext.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocatePathContext.kt @@ -3,20 +3,20 @@ package com.github.jengelman.gradle.plugins.shadow.relocation import com.github.jengelman.gradle.plugins.shadow.ShadowStats data class RelocatePathContext( - val path: String, - val stats: ShadowStats, + val path: String, + val stats: ShadowStats, ) { - class Builder { - private var path = "" - private var stats = ShadowStats() + class Builder { + private var path = "" + private var stats = ShadowStats() - fun path(path: String): Builder = apply { this.path = path } - fun stats(stats: ShadowStats): Builder = apply { this.stats = stats } - fun build(): RelocatePathContext = RelocatePathContext(path, stats) - } + fun path(path: String): Builder = apply { this.path = path } + fun stats(stats: ShadowStats): Builder = apply { this.stats = stats } + fun build(): RelocatePathContext = RelocatePathContext(path, stats) + } - companion object { - @JvmStatic - fun builder(): Builder = Builder() - } + companion object { + @JvmStatic + fun builder(): Builder = Builder() + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/Relocator.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/Relocator.kt index d754ba7a1..03fea7f5d 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/Relocator.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/Relocator.kt @@ -7,17 +7,17 @@ package com.github.jengelman.gradle.plugins.shadow.relocation * @author John Engelman */ interface Relocator { - fun canRelocatePath(path: String): Boolean + fun canRelocatePath(path: String): Boolean - fun relocatePath(context: RelocatePathContext): String + fun relocatePath(context: RelocatePathContext): String - fun canRelocateClass(className: String): Boolean + fun canRelocateClass(className: String): Boolean - fun relocateClass(context: RelocateClassContext): String + fun relocateClass(context: RelocateClassContext): String - fun applyToSourceContent(sourceContent: String): String + fun applyToSourceContent(sourceContent: String): String - companion object { - val ROLE: String = Relocator::class.java.name - } + companion object { + val ROLE: String = Relocator::class.java.name + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocator.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocator.kt index 4e3185eff..98feac8f3 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocator.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocator.kt @@ -14,143 +14,143 @@ import org.gradle.api.tasks.Optional */ @CacheableRelocator open class SimpleRelocator @JvmOverloads constructor( - pattern: String?, - shadedPattern: String?, - includes: List?, - excludes: List?, - private val _isRawString: Boolean = false, + pattern: String?, + shadedPattern: String?, + includes: List?, + excludes: List?, + private val _isRawString: Boolean = false, ) : Relocator { - private val _pattern: String? - private val _pathPattern: String - private val _shadedPattern: String? - private val _shadedPathPattern: String - private val _includes = mutableSetOf() - private val _excludes = mutableSetOf() - - init { - if (_isRawString) { - _pathPattern = pattern.orEmpty() - _shadedPathPattern = shadedPattern.orEmpty() - _pattern = null // not used for raw string relocator - _shadedPattern = null // not used for raw string relocator - } else { - if (pattern == null) { - _pattern = "" - _pathPattern = "" - } else { - _pattern = pattern.replace('/', '.') - _pathPattern = pattern.replace('.', '/') - } - if (shadedPattern == null) { - _shadedPattern = "hidden.${_pattern}" - _shadedPathPattern = "hidden/$_pathPattern" - } else { - _shadedPattern = shadedPattern.replace('/', '.') - _shadedPathPattern = shadedPattern.replace('.', '/') - } - } - _includes += normalizePatterns(includes) - _excludes += normalizePatterns(excludes) + private val _pattern: String? + private val _pathPattern: String + private val _shadedPattern: String? + private val _shadedPathPattern: String + private val _includes = mutableSetOf() + private val _excludes = mutableSetOf() + + init { + if (_isRawString) { + _pathPattern = pattern.orEmpty() + _shadedPathPattern = shadedPattern.orEmpty() + _pattern = null // not used for raw string relocator + _shadedPattern = null // not used for raw string relocator + } else { + if (pattern == null) { + _pattern = "" + _pathPattern = "" + } else { + _pattern = pattern.replace('/', '.') + _pathPattern = pattern.replace('.', '/') + } + if (shadedPattern == null) { + _shadedPattern = "hidden.${_pattern}" + _shadedPathPattern = "hidden/$_pathPattern" + } else { + _shadedPattern = shadedPattern.replace('/', '.') + _shadedPathPattern = shadedPattern.replace('.', '/') + } } - - @get:Input - @get:Optional - open val pattern: String? get() = _pattern - - @get:Input - open val pathPattern: String get() = _pathPattern - - @get:Input - @get:Optional - open val shadedPattern: String? get() = _shadedPattern - - @get:Input - open val shadedPathPattern: String get() = _shadedPathPattern - - @get:Input - open val isRawString: Boolean get() = _isRawString - - @get:Input - open val includes: Set get() = _includes - - @get:Input - open val excludes: Set get() = _excludes - - open fun include(pattern: String): SimpleRelocator = apply { - _includes += normalizePatterns(listOf(pattern)) + _includes += normalizePatterns(includes) + _excludes += normalizePatterns(excludes) + } + + @get:Input + @get:Optional + open val pattern: String? get() = _pattern + + @get:Input + open val pathPattern: String get() = _pathPattern + + @get:Input + @get:Optional + open val shadedPattern: String? get() = _shadedPattern + + @get:Input + open val shadedPathPattern: String get() = _shadedPathPattern + + @get:Input + open val isRawString: Boolean get() = _isRawString + + @get:Input + open val includes: Set get() = _includes + + @get:Input + open val excludes: Set get() = _excludes + + open fun include(pattern: String): SimpleRelocator = apply { + _includes += normalizePatterns(listOf(pattern)) + } + + open fun exclude(pattern: String): SimpleRelocator = apply { + _excludes += normalizePatterns(listOf(pattern)) + } + + override fun canRelocatePath(path: String): Boolean { + if (_isRawString) return Pattern.compile(_pathPattern).matcher(path).find() + // If string is too short - no need to perform expensive string operations + if (path.length < _pathPattern.length) return false + val adjustedPath = if (path.endsWith(".class")) { + // Safeguard against strings containing only ".class" + if (path.length == 6) return false + path.dropLast(6) + } else { + path } - - open fun exclude(pattern: String): SimpleRelocator = apply { - _excludes += normalizePatterns(listOf(pattern)) + // Allow for annoying option of an extra / on the front of a path. See MSHADE-119 comes from getClass().getResource("/a/b/c.properties"). + val startIndex = if (adjustedPath.startsWith("/")) 1 else 0 + val pathStartsWithPattern = adjustedPath.startsWith(_pathPattern, startIndex) + return pathStartsWithPattern && isIncluded(adjustedPath) && !isExcluded(adjustedPath) + } + + override fun canRelocateClass(className: String): Boolean { + return !_isRawString && !className.contains('/') && canRelocatePath(className.replace('.', '/')) + } + + override fun relocatePath(context: RelocatePathContext): String { + val path = context.path + context.stats.relocate(_pathPattern, _shadedPathPattern) + return if (_isRawString) { + path.replace(_pathPattern.toRegex(), _shadedPathPattern) + } else { + path.replaceFirst(_pathPattern, _shadedPathPattern) } - - override fun canRelocatePath(path: String): Boolean { - if (_isRawString) return Pattern.compile(_pathPattern).matcher(path).find() - // If string is too short - no need to perform expensive string operations - if (path.length < _pathPattern.length) return false - val adjustedPath = if (path.endsWith(".class")) { - // Safeguard against strings containing only ".class" - if (path.length == 6) return false - path.dropLast(6) - } else { - path - } - // Allow for annoying option of an extra / on the front of a path. See MSHADE-119 comes from getClass().getResource("/a/b/c.properties"). - val startIndex = if (adjustedPath.startsWith("/")) 1 else 0 - val pathStartsWithPattern = adjustedPath.startsWith(_pathPattern, startIndex) - return pathStartsWithPattern && isIncluded(adjustedPath) && !isExcluded(adjustedPath) + } + + override fun relocateClass(context: RelocateClassContext): String { + context.stats.relocate(_pathPattern, _shadedPathPattern) + return context.className.replaceFirst(_pattern.orEmpty(), _shadedPattern.orEmpty()) + } + + override fun applyToSourceContent(sourceContent: String): String { + return if (_isRawString) { + sourceContent + } else { + sourceContent.replace("\\b$_pattern".toRegex(), _shadedPattern.orEmpty()) } - - override fun canRelocateClass(className: String): Boolean { - return !_isRawString && !className.contains('/') && canRelocatePath(className.replace('.', '/')) + } + + private fun normalizePatterns(patterns: Collection?) = buildSet { + for (pattern in patterns.orEmpty()) { + // Regex patterns don't need to be normalized and stay as is + if (pattern.startsWith(SelectorUtils.REGEX_HANDLER_PREFIX)) { + add(pattern) + continue + } + + val classPattern = pattern.replace('.', '/') + add(classPattern) + + if (classPattern.endsWith("/*")) { + val packagePattern = classPattern.substring(0, classPattern.lastIndexOf('/')) + add(packagePattern) + } } + } - override fun relocatePath(context: RelocatePathContext): String { - val path = context.path - context.stats.relocate(_pathPattern, _shadedPathPattern) - return if (_isRawString) { - path.replace(_pathPattern.toRegex(), _shadedPathPattern) - } else { - path.replaceFirst(_pathPattern, _shadedPathPattern) - } - } - - override fun relocateClass(context: RelocateClassContext): String { - context.stats.relocate(_pathPattern, _shadedPathPattern) - return context.className.replaceFirst(_pattern.orEmpty(), _shadedPattern.orEmpty()) - } - - override fun applyToSourceContent(sourceContent: String): String { - return if (_isRawString) { - sourceContent - } else { - sourceContent.replace("\\b$_pattern".toRegex(), _shadedPattern.orEmpty()) - } - } + private fun isIncluded(path: String): Boolean { + return _includes.isEmpty() || _includes.any { SelectorUtils.matchPath(it, path, "/", true) } + } - private fun normalizePatterns(patterns: Collection?) = buildSet { - for (pattern in patterns.orEmpty()) { - // Regex patterns don't need to be normalized and stay as is - if (pattern.startsWith(SelectorUtils.REGEX_HANDLER_PREFIX)) { - add(pattern) - continue - } - - val classPattern = pattern.replace('.', '/') - add(classPattern) - - if (classPattern.endsWith("/*")) { - val packagePattern = classPattern.substring(0, classPattern.lastIndexOf('/')) - add(packagePattern) - } - } - } - - private fun isIncluded(path: String): Boolean { - return _includes.isEmpty() || _includes.any { SelectorUtils.matchPath(it, path, "/", true) } - } - - private fun isExcluded(path: String): Boolean { - return _excludes.any { SelectorUtils.matchPath(it, path, "/", true) } - } + private fun isExcluded(path: String): Boolean { + return _excludes.any { SelectorUtils.matchPath(it, path, "/", true) } + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/DefaultInheritManifest.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/DefaultInheritManifest.kt index 0a16a6037..20f9d7ff6 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/DefaultInheritManifest.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/DefaultInheritManifest.kt @@ -7,39 +7,39 @@ import org.gradle.api.java.archives.internal.DefaultManifest import org.gradle.api.java.archives.internal.DefaultManifestMergeSpec open class DefaultInheritManifest @JvmOverloads constructor( - private val fileResolver: FileResolver, - private val internalManifest: DefaultManifest = DefaultManifest(fileResolver), + private val fileResolver: FileResolver, + private val internalManifest: DefaultManifest = DefaultManifest(fileResolver), ) : InheritManifest, - Manifest by internalManifest { - private val inheritMergeSpecs = mutableListOf() + Manifest by internalManifest { + private val inheritMergeSpecs = mutableListOf() - override fun inheritFrom( - vararg inheritPaths: Any, - ): InheritManifest { - return inheritFrom(inheritPaths = inheritPaths, action = null) - } + override fun inheritFrom( + vararg inheritPaths: Any, + ): InheritManifest { + return inheritFrom(inheritPaths = inheritPaths, action = null) + } - override fun inheritFrom( - vararg inheritPaths: Any, - action: Action<*>?, - ): InheritManifest = apply { - val mergeSpec = DefaultManifestMergeSpec() - mergeSpec.from(*inheritPaths) - inheritMergeSpecs.add(mergeSpec) - @Suppress("UNCHECKED_CAST") - (action as? Action)?.execute(mergeSpec) - } + override fun inheritFrom( + vararg inheritPaths: Any, + action: Action<*>?, + ): InheritManifest = apply { + val mergeSpec = DefaultManifestMergeSpec() + mergeSpec.from(*inheritPaths) + inheritMergeSpecs.add(mergeSpec) + @Suppress("UNCHECKED_CAST") + (action as? Action)?.execute(mergeSpec) + } - override fun getEffectiveManifest(): DefaultManifest { - var base = DefaultManifest(fileResolver) - inheritMergeSpecs.forEach { - base = it.merge(base, fileResolver) - } - base.from(internalManifest) - return base.effectiveManifest + override fun getEffectiveManifest(): DefaultManifest { + var base = DefaultManifest(fileResolver) + inheritMergeSpecs.forEach { + base = it.merge(base, fileResolver) } + base.from(internalManifest) + return base.effectiveManifest + } - override fun writeTo(path: Any): Manifest = apply { - effectiveManifest.writeTo(path) - } + override fun writeTo(path: Any): Manifest = apply { + effectiveManifest.writeTo(path) + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/InheritManifest.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/InheritManifest.kt index d14ecb18f..13c3a3ab3 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/InheritManifest.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/InheritManifest.kt @@ -4,7 +4,7 @@ import org.gradle.api.Action import org.gradle.api.java.archives.Manifest interface InheritManifest : Manifest { - fun inheritFrom(vararg inheritPaths: Any): InheritManifest + fun inheritFrom(vararg inheritPaths: Any): InheritManifest - fun inheritFrom(vararg inheritPaths: Any, action: Action<*>?): InheritManifest + fun inheritFrom(vararg inheritPaths: Any, action: Action<*>?): InheritManifest } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/KnowsTask.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/KnowsTask.kt index 35cc81b74..c7531ca6d 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/KnowsTask.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/KnowsTask.kt @@ -6,19 +6,19 @@ import org.gradle.api.tasks.TaskAction abstract class KnowsTask : DefaultTask() { - @TaskAction - fun knows() { - logger.info( - """ + @TaskAction + fun knows() { + logger.info( + """ No, The Shadow Knows.... ${this::class.java.requireResourceAsText("/shadowBanner.txt")} - """.trimIndent(), - ) - } + """.trimIndent(), + ) + } - companion object { - const val NAME: String = "knows" - const val DESC: String = "Do you know who knows?" - } + companion object { + const val NAME: String = "knows" + const val DESC: String = "Do you know who knows?" + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.kt index 244d3f53a..5149de444 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.kt @@ -39,409 +39,409 @@ import org.objectweb.asm.commons.ClassRemapper import org.slf4j.LoggerFactory open class ShadowCopyAction internal constructor( - private val zipFile: File, - private val compressor: ZipCompressor, - private val documentationRegistry: DocumentationRegistry, - private val encoding: String?, - private val transformers: List, - private val relocators: List, - private val patternSet: PatternSet, - private val stats: ShadowStats, - private val preserveFileTimestamps: Boolean, - private val minimizeJar: Boolean, - private val unusedTracker: UnusedTracker?, + private val zipFile: File, + private val compressor: ZipCompressor, + private val documentationRegistry: DocumentationRegistry, + private val encoding: String?, + private val transformers: List, + private val relocators: List, + private val patternSet: PatternSet, + private val stats: ShadowStats, + private val preserveFileTimestamps: Boolean, + private val minimizeJar: Boolean, + private val unusedTracker: UnusedTracker?, ) : CopyAction { - constructor( - zipFile: File, - compressor: ZipCompressor, - documentationRegistry: DocumentationRegistry, - encoding: String?, - transformers: List, - relocators: List, - patternSet: PatternSet, - stats: ShadowStats, - preserveFileTimestamps: Boolean, - minimizeJar: Boolean, - ) : this( - zipFile, - compressor, - documentationRegistry, - encoding, - transformers, - relocators, - patternSet, - stats, - preserveFileTimestamps, - minimizeJar, - null, - ) - - override fun execute(stream: CopyActionProcessingStream): WorkResult { - val unusedClasses = if (minimizeJar && unusedTracker != null) { - stream.process( - object : BaseStreamAction() { - override fun visitFile(fileDetails: FileCopyDetails) { - // All project sources are already present, we just need - // to deal with JAR dependencies. - if (isArchive(fileDetails)) { - unusedTracker.addDependency(fileDetails.file) - } - } - }, - ) - unusedTracker.findUnused() - } else { - emptySet() - } - - val zipOutStream = try { - compressor.createArchiveOutputStream(zipFile) as ZipOutputStream - } catch (e: Exception) { - throw GradleException("Could not create ZIP '$zipFile'", e) - } - - try { - zipOutStream.use { outputStream -> - stream.process( - StreamAction( - outputStream, - encoding, - transformers, - relocators, - patternSet, - unusedClasses, - stats, - ), - ) - processTransformers(outputStream) + constructor( + zipFile: File, + compressor: ZipCompressor, + documentationRegistry: DocumentationRegistry, + encoding: String?, + transformers: List, + relocators: List, + patternSet: PatternSet, + stats: ShadowStats, + preserveFileTimestamps: Boolean, + minimizeJar: Boolean, + ) : this( + zipFile, + compressor, + documentationRegistry, + encoding, + transformers, + relocators, + patternSet, + stats, + preserveFileTimestamps, + minimizeJar, + null, + ) + + override fun execute(stream: CopyActionProcessingStream): WorkResult { + val unusedClasses = if (minimizeJar && unusedTracker != null) { + stream.process( + object : BaseStreamAction() { + override fun visitFile(fileDetails: FileCopyDetails) { + // All project sources are already present, we just need + // to deal with JAR dependencies. + if (isArchive(fileDetails)) { + unusedTracker.addDependency(fileDetails.file) } - } catch (e: IOException) { - throw Zip64RequiredException( - "${e.cause?.message}\n\nTo build this archive, please enable the zip64 extension.\n" + - "See: ${documentationRegistry.getDslRefForProperty(Zip::class.java, "zip64")}", - ) - } - return WorkResults.didWork(true) + } + }, + ) + unusedTracker.findUnused() + } else { + emptySet() } - private fun processTransformers(stream: ZipOutputStream) { - transformers.forEach { transformer -> - if (transformer.hasTransformedResource()) { - transformer.modifyOutputStream(stream, preserveFileTimestamps) - } - } + val zipOutStream = try { + compressor.createArchiveOutputStream(zipFile) as ZipOutputStream + } catch (e: Exception) { + throw GradleException("Could not create ZIP '$zipFile'", e) } - private fun getArchiveTimeFor(timestamp: Long): Long { - return if (preserveFileTimestamps) timestamp else CONSTANT_TIME_FOR_ZIP_ENTRIES + try { + zipOutStream.use { outputStream -> + stream.process( + StreamAction( + outputStream, + encoding, + transformers, + relocators, + patternSet, + unusedClasses, + stats, + ), + ) + processTransformers(outputStream) + } + } catch (e: IOException) { + throw Zip64RequiredException( + "${e.cause?.message}\n\nTo build this archive, please enable the zip64 extension.\n" + + "See: ${documentationRegistry.getDslRefForProperty(Zip::class.java, "zip64")}", + ) } - - private fun setArchiveTimes(zipEntry: ZipEntry): ZipEntry { - if (!preserveFileTimestamps) { - zipEntry.time = CONSTANT_TIME_FOR_ZIP_ENTRIES - } - return zipEntry + return WorkResults.didWork(true) + } + + private fun processTransformers(stream: ZipOutputStream) { + transformers.forEach { transformer -> + if (transformer.hasTransformedResource()) { + transformer.modifyOutputStream(stream, preserveFileTimestamps) + } } + } - abstract class BaseStreamAction : CopyActionProcessingStreamAction { - protected fun isArchive(fileDetails: FileCopyDetails): Boolean { - return fileDetails.relativePath.pathString.endsWith(".jar") - } + private fun getArchiveTimeFor(timestamp: Long): Long { + return if (preserveFileTimestamps) timestamp else CONSTANT_TIME_FOR_ZIP_ENTRIES + } - protected fun isClass(fileDetails: FileCopyDetails): Boolean { - return fileDetails.path.endsWith(".class") - } + private fun setArchiveTimes(zipEntry: ZipEntry): ZipEntry { + if (!preserveFileTimestamps) { + zipEntry.time = CONSTANT_TIME_FOR_ZIP_ENTRIES + } + return zipEntry + } - override fun processFile(details: FileCopyDetailsInternal) { - if (details.isDirectory) visitDir(details) else visitFile(details) - } + abstract class BaseStreamAction : CopyActionProcessingStreamAction { + protected fun isArchive(fileDetails: FileCopyDetails): Boolean { + return fileDetails.relativePath.pathString.endsWith(".jar") + } - protected open fun visitDir(dirDetails: FileCopyDetails) {} + protected fun isClass(fileDetails: FileCopyDetails): Boolean { + return fileDetails.path.endsWith(".class") + } - protected abstract fun visitFile(fileDetails: FileCopyDetails) + override fun processFile(details: FileCopyDetailsInternal) { + if (details.isDirectory) visitDir(details) else visitFile(details) } - private inner class StreamAction( - private val zipOutStr: ZipOutputStream, - encoding: String?, - private val transformers: List, - private val relocators: List, - private val patternSet: PatternSet, - private val unused: Set, - private val stats: ShadowStats, - ) : BaseStreamAction() { - private val remapper = RelocatorRemapper(relocators, stats) - private val visitedFiles = mutableSetOf() - - init { - if (encoding != null) { - this.zipOutStr.setEncoding(encoding) - } - } + protected open fun visitDir(dirDetails: FileCopyDetails) {} - override fun visitFile(fileDetails: FileCopyDetails) { - if (!isArchive(fileDetails)) { - try { - val isClass = isClass(fileDetails) - if (!remapper.hasRelocators() || !isClass) { - if (!isTransformable(fileDetails)) { - val mappedPath = remapper.map(fileDetails.relativePath.pathString) - val archiveEntry = ZipEntry(mappedPath) - archiveEntry.time = getArchiveTimeFor(fileDetails.lastModified) - archiveEntry.unixMode = UnixStat.FILE_FLAG or fileDetails.permissions.toUnixNumeric() - zipOutStr.putNextEntry(archiveEntry) - fileDetails.copyTo(zipOutStr) - zipOutStr.closeEntry() - } else { - transform(fileDetails) - } - } else if (isClass && !isUnused(fileDetails.path)) { - remapClass(fileDetails) - } - recordVisit(fileDetails.relativePath) - } catch (e: Exception) { - throw GradleException("Could not add $fileDetails to ZIP '$zipFile'.", e) - } - } else { - processArchive(fileDetails) - } - } + protected abstract fun visitFile(fileDetails: FileCopyDetails) + } - private fun recordVisit(path: RelativePath): Boolean { - return visitedFiles.add(path.pathString) - } + private inner class StreamAction( + private val zipOutStr: ZipOutputStream, + encoding: String?, + private val transformers: List, + private val relocators: List, + private val patternSet: PatternSet, + private val unused: Set, + private val stats: ShadowStats, + ) : BaseStreamAction() { + private val remapper = RelocatorRemapper(relocators, stats) + private val visitedFiles = mutableSetOf() + + init { + if (encoding != null) { + this.zipOutStr.setEncoding(encoding) + } + } - private fun processArchive(fileDetails: FileCopyDetails) { - stats.startJar() - ZipFile(fileDetails.file).use { archive -> - archive.entries.asSequence() - .map { - ArchiveFileTreeElement(RelativeArchivePath(it)) - } - .filter { - patternSet.asSpec.isSatisfiedBy(it.asFileTreeElement()) - }.forEach { archiveElement -> - if (archiveElement.relativePath.isFile) { - visitArchiveFile(archiveElement, archive) - } - } + override fun visitFile(fileDetails: FileCopyDetails) { + if (!isArchive(fileDetails)) { + try { + val isClass = isClass(fileDetails) + if (!remapper.hasRelocators() || !isClass) { + if (!isTransformable(fileDetails)) { + val mappedPath = remapper.map(fileDetails.relativePath.pathString) + val archiveEntry = ZipEntry(mappedPath) + archiveEntry.time = getArchiveTimeFor(fileDetails.lastModified) + archiveEntry.unixMode = UnixStat.FILE_FLAG or fileDetails.permissions.toUnixNumeric() + zipOutStr.putNextEntry(archiveEntry) + fileDetails.copyTo(zipOutStr) + zipOutStr.closeEntry() + } else { + transform(fileDetails) } - stats.finishJar() + } else if (isClass && !isUnused(fileDetails.path)) { + remapClass(fileDetails) + } + recordVisit(fileDetails.relativePath) + } catch (e: Exception) { + throw GradleException("Could not add $fileDetails to ZIP '$zipFile'.", e) } + } else { + processArchive(fileDetails) + } + } - private fun visitArchiveDirectory(archiveDir: RelativeArchivePath) { - if (recordVisit(archiveDir)) { - zipOutStr.putNextEntry(archiveDir.entry) - zipOutStr.closeEntry() - } - } + private fun recordVisit(path: RelativePath): Boolean { + return visitedFiles.add(path.pathString) + } - private fun visitArchiveFile(archiveFile: ArchiveFileTreeElement, archive: ZipFile) { - val archiveFilePath = archiveFile.relativePath - if (archiveFile.isClassFile || !isTransformable(archiveFile)) { - if (recordVisit(archiveFilePath) && !isUnused(archiveFilePath.entry.name)) { - if (!remapper.hasRelocators() || !archiveFile.isClassFile) { - copyArchiveEntry(archiveFilePath, archive) - } else { - remapClass(archiveFilePath, archive) - } - } - } else { - transform(archiveFile, archive) + private fun processArchive(fileDetails: FileCopyDetails) { + stats.startJar() + ZipFile(fileDetails.file).use { archive -> + archive.entries.asSequence() + .map { + ArchiveFileTreeElement(RelativeArchivePath(it)) + } + .filter { + patternSet.asSpec.isSatisfiedBy(it.asFileTreeElement()) + }.forEach { archiveElement -> + if (archiveElement.relativePath.isFile) { + visitArchiveFile(archiveElement, archive) } - } + } + } + stats.finishJar() + } - private fun addParentDirectories(file: RelativeArchivePath?) { - file?.let { - addParentDirectories(it.parent) - if (!it.isFile) { - visitArchiveDirectory(it) - } - } - } + private fun visitArchiveDirectory(archiveDir: RelativeArchivePath) { + if (recordVisit(archiveDir)) { + zipOutStr.putNextEntry(archiveDir.entry) + zipOutStr.closeEntry() + } + } - private fun isUnused(classPath: String): Boolean { - val classPathWithoutExtension = classPath.substringBeforeLast(".") - val className = classPathWithoutExtension.replace('/', '.') - val result = unused.contains(className) - if (result) { - logger.debug("Dropping unused class: $className") - } - return result + private fun visitArchiveFile(archiveFile: ArchiveFileTreeElement, archive: ZipFile) { + val archiveFilePath = archiveFile.relativePath + if (archiveFile.isClassFile || !isTransformable(archiveFile)) { + if (recordVisit(archiveFilePath) && !isUnused(archiveFilePath.entry.name)) { + if (!remapper.hasRelocators() || !archiveFile.isClassFile) { + copyArchiveEntry(archiveFilePath, archive) + } else { + remapClass(archiveFilePath, archive) + } } + } else { + transform(archiveFile, archive) + } + } - private fun remapClass(file: RelativeArchivePath, archive: ZipFile) { - if (file.isClassFile) { - val zipEntry = setArchiveTimes(ZipEntry(remapper.mapPath(file) + ".class")) - addParentDirectories(RelativeArchivePath(zipEntry)) - remapClass(archive.getInputStream(file.entry), file.pathString, file.entry.time) - } + private fun addParentDirectories(file: RelativeArchivePath?) { + file?.let { + addParentDirectories(it.parent) + if (!it.isFile) { + visitArchiveDirectory(it) } + } + } - private fun remapClass(fileCopyDetails: FileCopyDetails) { - if (fileCopyDetails.name.endsWith(".class")) { - fileCopyDetails.file.inputStream().use { - remapClass(it, fileCopyDetails.path, fileCopyDetails.lastModified) - } - } - } + private fun isUnused(classPath: String): Boolean { + val classPathWithoutExtension = classPath.substringBeforeLast(".") + val className = classPathWithoutExtension.replace('/', '.') + val result = unused.contains(className) + if (result) { + logger.debug("Dropping unused class: $className") + } + return result + } - /** - * Applies remapping to the given class with the specified relocation path. The remapped class is then written - * to the zip file. [classInputStream] is closed automatically to prevent future file leaks. - * See #364 and #408. - */ - private fun remapClass(classInputStream: InputStream, path: String, lastModified: Long) { - // We don't pass the ClassReader here. This forces the ClassWriter to rebuild the constant pool. - // Copying the original constant pool should be avoided because it would keep references - // to the original class names. This is not a problem at runtime (because these entries in the - // constant pool are never used), but confuses some tools such as Felix' maven-bundle-plugin - // that use the constant pool to determine the dependencies of a class. - val cw = ClassWriter(0) - val cr = ClassReader(classInputStream) - val cv = ClassRemapper(cw, remapper) - - try { - cr.accept(cv, ClassReader.EXPAND_FRAMES) - } catch (t: Throwable) { - throw GradleException("Error in ASM processing class $path", t) - } + private fun remapClass(file: RelativeArchivePath, archive: ZipFile) { + if (file.isClassFile) { + val zipEntry = setArchiveTimes(ZipEntry(remapper.mapPath(file) + ".class")) + addParentDirectories(RelativeArchivePath(zipEntry)) + remapClass(archive.getInputStream(file.entry), file.pathString, file.entry.time) + } + } - val renamedClass = cw.toByteArray() - // Temporarily remove the multi-release prefix. - val multiReleasePrefix = "^META-INF/versions/\\d+/".toRegex().find(path)?.value.orEmpty() - val newPath = path.replace(multiReleasePrefix, "") - val mappedName = multiReleasePrefix + remapper.mapPath(newPath) - try { - // Now we put it back on so the class file is written out with the right extension. - val archiveEntry = ZipEntry("$mappedName.class") - archiveEntry.time = getArchiveTimeFor(lastModified) - zipOutStr.putNextEntry(archiveEntry) - renamedClass.inputStream().use { - it.copyTo(zipOutStr) - } - zipOutStr.closeEntry() - } catch (ignored: ZipException) { - logger.warn("We have a duplicate $mappedName in source project") - } + private fun remapClass(fileCopyDetails: FileCopyDetails) { + if (fileCopyDetails.name.endsWith(".class")) { + fileCopyDetails.file.inputStream().use { + remapClass(it, fileCopyDetails.path, fileCopyDetails.lastModified) } + } + } - private fun copyArchiveEntry(archiveFile: RelativeArchivePath, archive: ZipFile) { - val mappedPath = remapper.map(archiveFile.entry.name) - val entry = ZipEntry(mappedPath) - entry.time = getArchiveTimeFor(archiveFile.entry.time) - val mappedFile = RelativeArchivePath(entry) - addParentDirectories(mappedFile) - zipOutStr.putNextEntry(mappedFile.entry) - archive.getInputStream(archiveFile.entry).use { - it.copyTo(zipOutStr) - } - zipOutStr.closeEntry() + /** + * Applies remapping to the given class with the specified relocation path. The remapped class is then written + * to the zip file. [classInputStream] is closed automatically to prevent future file leaks. + * See #364 and #408. + */ + private fun remapClass(classInputStream: InputStream, path: String, lastModified: Long) { + // We don't pass the ClassReader here. This forces the ClassWriter to rebuild the constant pool. + // Copying the original constant pool should be avoided because it would keep references + // to the original class names. This is not a problem at runtime (because these entries in the + // constant pool are never used), but confuses some tools such as Felix' maven-bundle-plugin + // that use the constant pool to determine the dependencies of a class. + val cw = ClassWriter(0) + val cr = ClassReader(classInputStream) + val cv = ClassRemapper(cw, remapper) + + try { + cr.accept(cv, ClassReader.EXPAND_FRAMES) + } catch (t: Throwable) { + throw GradleException("Error in ASM processing class $path", t) + } + + val renamedClass = cw.toByteArray() + // Temporarily remove the multi-release prefix. + val multiReleasePrefix = "^META-INF/versions/\\d+/".toRegex().find(path)?.value.orEmpty() + val newPath = path.replace(multiReleasePrefix, "") + val mappedName = multiReleasePrefix + remapper.mapPath(newPath) + try { + // Now we put it back on so the class file is written out with the right extension. + val archiveEntry = ZipEntry("$mappedName.class") + archiveEntry.time = getArchiveTimeFor(lastModified) + zipOutStr.putNextEntry(archiveEntry) + renamedClass.inputStream().use { + it.copyTo(zipOutStr) } + zipOutStr.closeEntry() + } catch (ignored: ZipException) { + logger.warn("We have a duplicate $mappedName in source project") + } + } - override fun visitDir(dirDetails: FileCopyDetails) { - try { - // Trailing slash in name indicates that entry is a directory - val path = dirDetails.relativePath.pathString + "/" - val archiveEntry = ZipEntry(path) - archiveEntry.time = getArchiveTimeFor(dirDetails.lastModified) - archiveEntry.unixMode = UnixStat.DIR_FLAG or dirDetails.permissions.toUnixNumeric() - zipOutStr.putNextEntry(archiveEntry) - zipOutStr.closeEntry() - recordVisit(dirDetails.relativePath) - } catch (e: Exception) { - throw GradleException("Could not add $dirDetails to ZIP '$zipFile'.", e) - } - } + private fun copyArchiveEntry(archiveFile: RelativeArchivePath, archive: ZipFile) { + val mappedPath = remapper.map(archiveFile.entry.name) + val entry = ZipEntry(mappedPath) + entry.time = getArchiveTimeFor(archiveFile.entry.time) + val mappedFile = RelativeArchivePath(entry) + addParentDirectories(mappedFile) + zipOutStr.putNextEntry(mappedFile.entry) + archive.getInputStream(archiveFile.entry).use { + it.copyTo(zipOutStr) + } + zipOutStr.closeEntry() + } - private fun transform(element: ArchiveFileTreeElement, archive: ZipFile) { - transformAndClose(element, archive.getInputStream(element.relativePath.entry)) - } + override fun visitDir(dirDetails: FileCopyDetails) { + try { + // Trailing slash in name indicates that entry is a directory + val path = dirDetails.relativePath.pathString + "/" + val archiveEntry = ZipEntry(path) + archiveEntry.time = getArchiveTimeFor(dirDetails.lastModified) + archiveEntry.unixMode = UnixStat.DIR_FLAG or dirDetails.permissions.toUnixNumeric() + zipOutStr.putNextEntry(archiveEntry) + zipOutStr.closeEntry() + recordVisit(dirDetails.relativePath) + } catch (e: Exception) { + throw GradleException("Could not add $dirDetails to ZIP '$zipFile'.", e) + } + } - private fun transform(details: FileCopyDetails) { - transformAndClose(details, details.file.inputStream()) - } + private fun transform(element: ArchiveFileTreeElement, archive: ZipFile) { + transformAndClose(element, archive.getInputStream(element.relativePath.entry)) + } - private fun transformAndClose(element: FileTreeElement, inputStream: InputStream) { - inputStream.use { steam -> - val mappedPath = remapper.map(element.relativePath.pathString) - transformers.find { - it.canTransformResource(element) - }?.transform( - TransformerContext.builder() - .path(mappedPath) - .inputStream(steam) - .relocators(relocators) - .stats(stats) - .build(), - ) - } - } + private fun transform(details: FileCopyDetails) { + transformAndClose(details, details.file.inputStream()) + } - private fun isTransformable(element: FileTreeElement): Boolean { - return transformers.any { it.canTransformResource(element) } - } + private fun transformAndClose(element: FileTreeElement, inputStream: InputStream) { + inputStream.use { steam -> + val mappedPath = remapper.map(element.relativePath.pathString) + transformers.find { + it.canTransformResource(element) + }?.transform( + TransformerContext.builder() + .path(mappedPath) + .inputStream(steam) + .relocators(relocators) + .stats(stats) + .build(), + ) + } } - open inner class RelativeArchivePath( - open val entry: ZipEntry, - ) : RelativePath( - !entry.isDirectory, - // `dir/` will be split into ["dir", ""], we have to trim empty segments here. - *entry.name.split('/').filter(CharSequence::isNotEmpty).toTypedArray(), - ) { - open val isClassFile: Boolean get() = lastName.endsWith(".class") - - override fun getParent(): RelativeArchivePath? { - return if (segments.size <= 1) { - null - } else { - // Parent is always a directory so add / to the end of the path - val parentPath = segments.dropLast(1).joinToString("/") + "/" - val entry = setArchiveTimes(ZipEntry(parentPath)) - RelativeArchivePath(entry) - } - } + private fun isTransformable(element: FileTreeElement): Boolean { + return transformers.any { it.canTransformResource(element) } + } + } + + open inner class RelativeArchivePath( + open val entry: ZipEntry, + ) : RelativePath( + !entry.isDirectory, + // `dir/` will be split into ["dir", ""], we have to trim empty segments here. + *entry.name.split('/').filter(CharSequence::isNotEmpty).toTypedArray(), + ) { + open val isClassFile: Boolean get() = lastName.endsWith(".class") + + override fun getParent(): RelativeArchivePath? { + return if (segments.size <= 1) { + null + } else { + // Parent is always a directory so add / to the end of the path + val parentPath = segments.dropLast(1).joinToString("/") + "/" + val entry = setArchiveTimes(ZipEntry(parentPath)) + RelativeArchivePath(entry) + } } + } - open class ArchiveFileTreeElement( - private val archivePath: RelativeArchivePath, - ) : FileTreeElement { - open val isClassFile: Boolean get() = archivePath.isClassFile + open class ArchiveFileTreeElement( + private val archivePath: RelativeArchivePath, + ) : FileTreeElement { + open val isClassFile: Boolean get() = archivePath.isClassFile - override fun isDirectory(): Boolean = archivePath.entry.isDirectory + override fun isDirectory(): Boolean = archivePath.entry.isDirectory - override fun getLastModified(): Long = archivePath.entry.lastModifiedDate.time + override fun getLastModified(): Long = archivePath.entry.lastModifiedDate.time - override fun getSize(): Long = archivePath.entry.size + override fun getSize(): Long = archivePath.entry.size - override fun getName(): String = archivePath.pathString + override fun getName(): String = archivePath.pathString - override fun getPath(): String = archivePath.lastName + override fun getPath(): String = archivePath.lastName - override fun getRelativePath(): RelativeArchivePath = archivePath + override fun getRelativePath(): RelativeArchivePath = archivePath - @Deprecated("Deprecated in Java") - override fun getMode(): Int = archivePath.entry.unixMode + @Deprecated("Deprecated in Java") + override fun getMode(): Int = archivePath.entry.unixMode - override fun getPermissions(): FilePermissions = DefaultFilePermissions(mode) + override fun getPermissions(): FilePermissions = DefaultFilePermissions(mode) - open fun asFileTreeElement(): FileTreeElement { - return DefaultFileTreeElement(null, RelativePath(!isDirectory, *archivePath.segments), null, null) - } + open fun asFileTreeElement(): FileTreeElement { + return DefaultFileTreeElement(null, RelativePath(!isDirectory, *archivePath.segments), null, null) + } - override fun getFile(): File = throw UnsupportedOperationException() + override fun getFile(): File = throw UnsupportedOperationException() - override fun open(): InputStream = throw UnsupportedOperationException() + override fun open(): InputStream = throw UnsupportedOperationException() - override fun copyTo(outputStream: OutputStream): Unit = throw UnsupportedOperationException() + override fun copyTo(outputStream: OutputStream): Unit = throw UnsupportedOperationException() - override fun copyTo(file: File): Boolean = throw UnsupportedOperationException() - } + override fun copyTo(file: File): Boolean = throw UnsupportedOperationException() + } - companion object { - private val logger = LoggerFactory.getLogger(ShadowCopyAction::class.java) - val CONSTANT_TIME_FOR_ZIP_ENTRIES: Long = GregorianCalendar(1980, 1, 1, 0, 0, 0).timeInMillis - } + companion object { + private val logger = LoggerFactory.getLogger(ShadowCopyAction::class.java) + val CONSTANT_TIME_FOR_ZIP_ENTRIES: Long = GregorianCalendar(1980, 1, 1, 0, 0, 0).timeInMillis + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt index 912a9bf01..bdb9806f0 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt @@ -42,303 +42,303 @@ import org.gradle.api.tasks.util.PatternSet @CacheableTask abstract class ShadowJar : - Jar(), - ShadowSpec { - private val _transformers = mutableListOf() - private val _relocators = mutableListOf() - private val _configurations = mutableListOf() - private val _stats = ShadowStats() - private val _includedDependencies = project.files(Callable { _dependencyFilter.resolve(_configurations) }) - - @Transient - private val dependencyFilterForMinimize = MinimizeDependencyFilter(project) - - private var minimizeJar = false - private var _isEnableRelocation = false - private var _relocationPrefix = ShadowBasePlugin.SHADOW - private var _toMinimize: FileCollection? = null - private var _apiJars: FileCollection? = null - private var _sourceSetsClassesDirs: FileCollection? = null - - @Transient - private var _dependencyFilter: DependencyFilter = DefaultDependencyFilter(project) - - init { - duplicatesStrategy = DuplicatesStrategy.INCLUDE - manifest = DefaultInheritManifest(services.get(FileResolver::class.java)) - - inputs.property("minimize") { minimizeJar } - outputs.doNotCacheIf("Has one or more transforms or relocators that are not cacheable") { - _transformers.any { !isCacheableTransform(it::class.java) } || - _relocators.any { !isCacheableRelocator(it::class.java) } - } + Jar(), + ShadowSpec { + private val _transformers = mutableListOf() + private val _relocators = mutableListOf() + private val _configurations = mutableListOf() + private val _stats = ShadowStats() + private val _includedDependencies = project.files(Callable { _dependencyFilter.resolve(_configurations) }) + + @Transient + private val dependencyFilterForMinimize = MinimizeDependencyFilter(project) + + private var minimizeJar = false + private var _isEnableRelocation = false + private var _relocationPrefix = ShadowBasePlugin.SHADOW + private var _toMinimize: FileCollection? = null + private var _apiJars: FileCollection? = null + private var _sourceSetsClassesDirs: FileCollection? = null + + @Transient + private var _dependencyFilter: DependencyFilter = DefaultDependencyFilter(project) + + init { + duplicatesStrategy = DuplicatesStrategy.INCLUDE + manifest = DefaultInheritManifest(services.get(FileResolver::class.java)) + + inputs.property("minimize") { minimizeJar } + outputs.doNotCacheIf("Has one or more transforms or relocators that are not cacheable") { + _transformers.any { !isCacheableTransform(it::class.java) } || + _relocators.any { !isCacheableRelocator(it::class.java) } } - - @get:Internal - override val stats: ShadowStats get() = _stats - - @get:Classpath - val toMinimize: FileCollection - get() { - if (_toMinimize == null) { - _toMinimize = if (minimizeJar) { - dependencyFilterForMinimize.resolve(_configurations) - .minus(apiJars) - } else { - project.objects.fileCollection() - } - } - return _toMinimize!! - } - - @get:Classpath - val apiJars: FileCollection - get() { - if (_apiJars == null) { - _apiJars = if (minimizeJar) { - UnusedTracker.getApiJarsFromProject(project) - } else { - project.objects.fileCollection() - } - } - return _apiJars!! - } - - @get:InputFiles - @get:PathSensitive(PathSensitivity.RELATIVE) - val sourceSetsClassesDirs: FileCollection - get() { - if (_sourceSetsClassesDirs == null) { - val allClassesDirs = project.objects.fileCollection() - if (minimizeJar) { - project.extensions.getByType(SourceSetContainer::class.java).forEach { sourceSet -> - allClassesDirs.from(sourceSet.output.classesDirs) - } - } - _sourceSetsClassesDirs = allClassesDirs.filter { it.isDirectory } - } - return _sourceSetsClassesDirs!! - } - - @get:Classpath - val includedDependencies: FileCollection get() = _includedDependencies - - @get:Internal - val rootPatternSet: PatternSet - get() { - return (mainSpec.buildRootResolver() as DefaultCopySpec.DefaultCopySpecResolver).patternSet - } - - @get:Internal - val internalCompressor: ZipCompressor - get() { - return when (entryCompression) { - ZipEntryCompression.DEFLATED -> DefaultZipCompressor(isZip64, ZipOutputStream.DEFLATED) - ZipEntryCompression.STORED -> DefaultZipCompressor(isZip64, ZipOutputStream.STORED) - else -> throw IllegalArgumentException("Unknown Compression type $entryCompression") - } - } - - @get:Nested - var transformers: List - get() = _transformers - set(value) { - _transformers.clear() - _transformers.addAll(value) - } - - @get:Nested - var relocators: List - get() = _relocators - set(value) { - _relocators.clear() - _relocators.addAll(value) - } - - @get:Classpath - @get:Optional - var configurations: List - get() = _configurations - set(value) { - _configurations.clear() - _configurations.addAll(value) - } - - @get:Internal - var dependencyFilter: DependencyFilter - get() = _dependencyFilter - set(value) { - _dependencyFilter = value - } - - @get:Input - var isEnableRelocation: Boolean - get() = _isEnableRelocation - set(value) { - _isEnableRelocation = value - } - - @get:Input - var relocationPrefix: String - get() = _relocationPrefix - set(value) { - _relocationPrefix = value + } + + @get:Internal + override val stats: ShadowStats get() = _stats + + @get:Classpath + val toMinimize: FileCollection + get() { + if (_toMinimize == null) { + _toMinimize = if (minimizeJar) { + dependencyFilterForMinimize.resolve(_configurations) + .minus(apiJars) + } else { + project.objects.fileCollection() } - - @Internal - override fun getManifest(): InheritManifest = super.getManifest() as InheritManifest - - override fun minimize(): ShadowJar = apply { - minimizeJar = true + } + return _toMinimize!! } - override fun minimize(action: Action?): ShadowJar = apply { - minimize() - action?.execute(dependencyFilterForMinimize) - } - - override fun createCopyAction(): CopyAction { - val documentationRegistry = services.get(DocumentationRegistry::class.java) - val unusedTracker = if (minimizeJar) { - UnusedTracker.forProject(apiJars, sourceSetsClassesDirs.files, toMinimize) + @get:Classpath + val apiJars: FileCollection + get() { + if (_apiJars == null) { + _apiJars = if (minimizeJar) { + UnusedTracker.getApiJarsFromProject(project) } else { - null + project.objects.fileCollection() } - return ShadowCopyAction( - archiveFile.get().asFile, - internalCompressor, - documentationRegistry, - metadataCharset, - _transformers, - _relocators, - rootPatternSet, - _stats, - isPreserveFileTimestamps, - minimizeJar, - unusedTracker, - ) - } - - override fun dependencies(action: Action?): ShadowJar = apply { - action?.execute(_dependencyFilter) - } - - override fun transform(clazz: Class): ShadowJar { - return transform(clazz, null) - } - - override fun transform(clazz: Class, action: Action?): ShadowJar = apply { - val transformer = clazz.getDeclaredConstructor().newInstance() - addTransform(transformer, action) - } - - override fun transform(transformer: Transformer): ShadowJar = apply { - addTransform(transformer, null) + } + return _apiJars!! } - override fun mergeServiceFiles(): ShadowJar { - return runCatching { - transform(ServiceFileTransformer::class.java, null) - }.getOrDefault(this) + @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) + val sourceSetsClassesDirs: FileCollection + get() { + if (_sourceSetsClassesDirs == null) { + val allClassesDirs = project.objects.fileCollection() + if (minimizeJar) { + project.extensions.getByType(SourceSetContainer::class.java).forEach { sourceSet -> + allClassesDirs.from(sourceSet.output.classesDirs) + } + } + _sourceSetsClassesDirs = allClassesDirs.filter { it.isDirectory } + } + return _sourceSetsClassesDirs!! } - override fun mergeServiceFiles(rootPath: String): ShadowJar { - return runCatching { - transform(ServiceFileTransformer::class.java) { - it.setPath(rootPath) - } - }.getOrDefault(this) - } + @get:Classpath + val includedDependencies: FileCollection get() = _includedDependencies - override fun mergeServiceFiles(action: Action?): ShadowJar { - return runCatching { - transform(ServiceFileTransformer::class.java, action) - }.getOrDefault(this) + @get:Internal + val rootPatternSet: PatternSet + get() { + return (mainSpec.buildRootResolver() as DefaultCopySpec.DefaultCopySpecResolver).patternSet } - override fun mergeGroovyExtensionModules(): ShadowJar { - return runCatching { - transform(GroovyExtensionModuleTransformer::class.java, null) - }.getOrDefault(this) + @get:Internal + val internalCompressor: ZipCompressor + get() { + return when (entryCompression) { + ZipEntryCompression.DEFLATED -> DefaultZipCompressor(isZip64, ZipOutputStream.DEFLATED) + ZipEntryCompression.STORED -> DefaultZipCompressor(isZip64, ZipOutputStream.STORED) + else -> throw IllegalArgumentException("Unknown Compression type $entryCompression") + } } - override fun append(resourcePath: String): ShadowJar { - return runCatching { - transform(AppendingTransformer::class.java) { - it.resource = resourcePath - } - }.getOrDefault(this) + @get:Nested + var transformers: List + get() = _transformers + set(value) { + _transformers.clear() + _transformers.addAll(value) } - override fun relocate(pattern: String, destination: String): ShadowJar { - return relocate(pattern, destination, null) + @get:Nested + var relocators: List + get() = _relocators + set(value) { + _relocators.clear() + _relocators.addAll(value) } - override fun relocate( - pattern: String, - destination: String, - action: Action?, - ): ShadowJar = apply { - val relocator = SimpleRelocator(pattern, destination, mutableListOf(), mutableListOf()) - addRelocator(relocator, action) + @get:Classpath + @get:Optional + var configurations: List + get() = _configurations + set(value) { + _configurations.clear() + _configurations.addAll(value) } - override fun relocate(relocator: Relocator): ShadowJar = apply { - addRelocator(relocator, null) + @get:Internal + var dependencyFilter: DependencyFilter + get() = _dependencyFilter + set(value) { + _dependencyFilter = value } - override fun relocate(clazz: Class): ShadowJar { - return relocate(clazz, null) + @get:Input + var isEnableRelocation: Boolean + get() = _isEnableRelocation + set(value) { + _isEnableRelocation = value } - override fun relocate(clazz: Class, action: Action?): ShadowJar = apply { - val relocator = clazz.getDeclaredConstructor().newInstance() - addRelocator(relocator, action) + @get:Input + var relocationPrefix: String + get() = _relocationPrefix + set(value) { + _relocationPrefix = value } - @TaskAction - override fun copy() { - if (_isEnableRelocation) { - configureRelocation() - } - from(_includedDependencies) - super.copy() - logger.info(_stats.toString()) - } + @Internal + override fun getManifest(): InheritManifest = super.getManifest() as InheritManifest - private fun addRelocator(relocator: R, configure: Action?) { - configure?.execute(relocator) - _relocators.add(relocator) - } + override fun minimize(): ShadowJar = apply { + minimizeJar = true + } - private fun addTransform(transformer: T, action: Action?) { - action?.execute(transformer) - _transformers.add(transformer) - } + override fun minimize(action: Action?): ShadowJar = apply { + minimize() + action?.execute(dependencyFilterForMinimize) + } - private fun isCacheableRelocator(clazz: Class): Boolean { - return clazz.isAnnotationPresent(CacheableRelocator::class.java) + override fun createCopyAction(): CopyAction { + val documentationRegistry = services.get(DocumentationRegistry::class.java) + val unusedTracker = if (minimizeJar) { + UnusedTracker.forProject(apiJars, sourceSetsClassesDirs.files, toMinimize) + } else { + null } - - private fun isCacheableTransform(clazz: Class): Boolean { - return clazz.isAnnotationPresent(CacheableTransformer::class.java) + return ShadowCopyAction( + archiveFile.get().asFile, + internalCompressor, + documentationRegistry, + metadataCharset, + _transformers, + _relocators, + rootPatternSet, + _stats, + isPreserveFileTimestamps, + minimizeJar, + unusedTracker, + ) + } + + override fun dependencies(action: Action?): ShadowJar = apply { + action?.execute(_dependencyFilter) + } + + override fun transform(clazz: Class): ShadowJar { + return transform(clazz, null) + } + + override fun transform(clazz: Class, action: Action?): ShadowJar = apply { + val transformer = clazz.getDeclaredConstructor().newInstance() + addTransform(transformer, action) + } + + override fun transform(transformer: Transformer): ShadowJar = apply { + addTransform(transformer, null) + } + + override fun mergeServiceFiles(): ShadowJar { + return runCatching { + transform(ServiceFileTransformer::class.java, null) + }.getOrDefault(this) + } + + override fun mergeServiceFiles(rootPath: String): ShadowJar { + return runCatching { + transform(ServiceFileTransformer::class.java) { + it.setPath(rootPath) + } + }.getOrDefault(this) + } + + override fun mergeServiceFiles(action: Action?): ShadowJar { + return runCatching { + transform(ServiceFileTransformer::class.java, action) + }.getOrDefault(this) + } + + override fun mergeGroovyExtensionModules(): ShadowJar { + return runCatching { + transform(GroovyExtensionModuleTransformer::class.java, null) + }.getOrDefault(this) + } + + override fun append(resourcePath: String): ShadowJar { + return runCatching { + transform(AppendingTransformer::class.java) { + it.resource = resourcePath + } + }.getOrDefault(this) + } + + override fun relocate(pattern: String, destination: String): ShadowJar { + return relocate(pattern, destination, null) + } + + override fun relocate( + pattern: String, + destination: String, + action: Action?, + ): ShadowJar = apply { + val relocator = SimpleRelocator(pattern, destination, mutableListOf(), mutableListOf()) + addRelocator(relocator, action) + } + + override fun relocate(relocator: Relocator): ShadowJar = apply { + addRelocator(relocator, null) + } + + override fun relocate(clazz: Class): ShadowJar { + return relocate(clazz, null) + } + + override fun relocate(clazz: Class, action: Action?): ShadowJar = apply { + val relocator = clazz.getDeclaredConstructor().newInstance() + addRelocator(relocator, action) + } + + @TaskAction + override fun copy() { + if (_isEnableRelocation) { + configureRelocation() } - - private fun configureRelocation() { - val packages = mutableSetOf() - configurations.forEach { configuration -> - configuration.files.forEach { jarFile -> - JarFile(jarFile).use { jf -> - jf.entries().asSequence().forEach { entry -> - if (entry.name.endsWith(".class") && entry.name != "module-info.class") { - packages.add(entry.name.substringBeforeLast('/').replace('/', '.')) - } - } - } + from(_includedDependencies) + super.copy() + logger.info(_stats.toString()) + } + + private fun addRelocator(relocator: R, configure: Action?) { + configure?.execute(relocator) + _relocators.add(relocator) + } + + private fun addTransform(transformer: T, action: Action?) { + action?.execute(transformer) + _transformers.add(transformer) + } + + private fun isCacheableRelocator(clazz: Class): Boolean { + return clazz.isAnnotationPresent(CacheableRelocator::class.java) + } + + private fun isCacheableTransform(clazz: Class): Boolean { + return clazz.isAnnotationPresent(CacheableTransformer::class.java) + } + + private fun configureRelocation() { + val packages = mutableSetOf() + configurations.forEach { configuration -> + configuration.files.forEach { jarFile -> + JarFile(jarFile).use { jf -> + jf.entries().asSequence().forEach { entry -> + if (entry.name.endsWith(".class") && entry.name != "module-info.class") { + packages.add(entry.name.substringBeforeLast('/').replace('/', '.')) } + } } - packages.forEach { - relocate(it, "$_relocationPrefix.$it") - } + } + } + packages.forEach { + relocate(it, "$_relocationPrefix.$it") } + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowSpec.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowSpec.kt index 04caf7315..826d201ba 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowSpec.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowSpec.kt @@ -11,61 +11,61 @@ import org.gradle.api.Action import org.gradle.api.file.CopySpec interface ShadowSpec : CopySpec { - fun minimize(): ShadowSpec + fun minimize(): ShadowSpec - fun minimize(action: Action?): ShadowSpec + fun minimize(action: Action?): ShadowSpec - fun dependencies(action: Action?): ShadowSpec + fun dependencies(action: Action?): ShadowSpec - @Throws( - InstantiationException::class, - IllegalAccessException::class, - NoSuchMethodException::class, - InvocationTargetException::class, - ) - fun transform(clazz: Class): ShadowSpec + @Throws( + InstantiationException::class, + IllegalAccessException::class, + NoSuchMethodException::class, + InvocationTargetException::class, + ) + fun transform(clazz: Class): ShadowSpec - @Throws( - InstantiationException::class, - IllegalAccessException::class, - NoSuchMethodException::class, - InvocationTargetException::class, - ) - fun transform(clazz: Class, action: Action?): ShadowSpec + @Throws( + InstantiationException::class, + IllegalAccessException::class, + NoSuchMethodException::class, + InvocationTargetException::class, + ) + fun transform(clazz: Class, action: Action?): ShadowSpec - fun transform(transformer: Transformer): ShadowSpec + fun transform(transformer: Transformer): ShadowSpec - fun mergeServiceFiles(): ShadowSpec + fun mergeServiceFiles(): ShadowSpec - fun mergeServiceFiles(rootPath: String): ShadowSpec + fun mergeServiceFiles(rootPath: String): ShadowSpec - fun mergeServiceFiles(action: Action?): ShadowSpec + fun mergeServiceFiles(action: Action?): ShadowSpec - fun mergeGroovyExtensionModules(): ShadowSpec + fun mergeGroovyExtensionModules(): ShadowSpec - fun append(resourcePath: String): ShadowSpec + fun append(resourcePath: String): ShadowSpec - fun relocate(pattern: String, destination: String): ShadowSpec + fun relocate(pattern: String, destination: String): ShadowSpec - fun relocate(pattern: String, destination: String, action: Action?): ShadowSpec + fun relocate(pattern: String, destination: String, action: Action?): ShadowSpec - fun relocate(relocator: Relocator): ShadowSpec + fun relocate(relocator: Relocator): ShadowSpec - @Throws( - InstantiationException::class, - IllegalAccessException::class, - NoSuchMethodException::class, - InvocationTargetException::class, - ) - fun relocate(clazz: Class): ShadowSpec + @Throws( + InstantiationException::class, + IllegalAccessException::class, + NoSuchMethodException::class, + InvocationTargetException::class, + ) + fun relocate(clazz: Class): ShadowSpec - @Throws( - InstantiationException::class, - IllegalAccessException::class, - NoSuchMethodException::class, - InvocationTargetException::class, - ) - fun relocate(clazz: Class, action: Action?): ShadowSpec + @Throws( + InstantiationException::class, + IllegalAccessException::class, + NoSuchMethodException::class, + InvocationTargetException::class, + ) + fun relocate(clazz: Class, action: Action?): ShadowSpec - val stats: ShadowStats + val stats: ShadowStats } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformer.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformer.kt index 3bd32275a..132c9efa3 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformer.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformer.kt @@ -10,14 +10,14 @@ import org.gradle.api.file.FileTreeElement * @author John Engelman */ open class ApacheLicenseResourceTransformer : Transformer by NoOpTransformer { - override fun canTransformResource(element: FileTreeElement): Boolean { - val path = element.relativePath.pathString - return LICENSE_PATH.equals(path, ignoreCase = true) || - LICENSE_TXT_PATH.regionMatches(0, path, 0, LICENSE_TXT_PATH.length, ignoreCase = true) - } + override fun canTransformResource(element: FileTreeElement): Boolean { + val path = element.relativePath.pathString + return LICENSE_PATH.equals(path, ignoreCase = true) || + LICENSE_TXT_PATH.regionMatches(0, path, 0, LICENSE_TXT_PATH.length, ignoreCase = true) + } - private companion object { - private const val LICENSE_PATH = "META-INF/LICENSE" - private const val LICENSE_TXT_PATH = "META-INF/LICENSE.txt" - } + private companion object { + private const val LICENSE_PATH = "META-INF/LICENSE" + private const val LICENSE_TXT_PATH = "META-INF/LICENSE.txt" + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformer.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformer.kt index 2fa195e77..5f1c3347f 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformer.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformer.kt @@ -19,160 +19,160 @@ import org.gradle.api.tasks.Optional * @author John Engelman */ open class ApacheNoticeResourceTransformer : Transformer { - private val entries = mutableSetOf() - private val organizationEntries = mutableMapOf>() - private val charset get() = if (encoding.isNullOrEmpty()) Charsets.UTF_8 else Charset.forName(encoding) + private val entries = mutableSetOf() + private val organizationEntries = mutableMapOf>() + private val charset get() = if (encoding.isNullOrEmpty()) Charsets.UTF_8 else Charset.forName(encoding) - /** - * MSHADE-101 :: NullPointerException when projectName is missing - */ - @get:Input - var projectName: String = "" + /** + * MSHADE-101 :: NullPointerException when projectName is missing + */ + @get:Input + var projectName: String = "" - @get:Input - var addHeader: Boolean = true + @get:Input + var addHeader: Boolean = true - @get:Input - var preamble1: String = """ + @get:Input + var preamble1: String = """ // ------------------------------------------------------------------ // NOTICE file corresponding to the section 4d of The Apache License, // Version 2.0, in this case for - """.trimIndent() - - @get:Input - var preamble2: String = "\n// ------------------------------------------------------------------\n" - - @get:Input - var preamble3: String = "This product includes software developed at\n" - - @get:Input - var organizationName: String = "The Apache Software Foundation" - - @get:Input - var organizationURL: String = "http://www.apache.org/" - - @get:Input - var inceptionYear: String = "2006" - - @get:Optional - @get:Input - var copyright: String? = null - - /** - * The file encoding of the `NOTICE` file. - */ - @get:Optional - @get:Input - var encoding: String? = null - - override fun canTransformResource(element: FileTreeElement): Boolean { - val path = element.relativePath.pathString - return NOTICE_PATH.equals(path, ignoreCase = true) || NOTICE_TXT_PATH.equals(path, ignoreCase = true) + """.trimIndent() + + @get:Input + var preamble2: String = "\n// ------------------------------------------------------------------\n" + + @get:Input + var preamble3: String = "This product includes software developed at\n" + + @get:Input + var organizationName: String = "The Apache Software Foundation" + + @get:Input + var organizationURL: String = "http://www.apache.org/" + + @get:Input + var inceptionYear: String = "2006" + + @get:Optional + @get:Input + var copyright: String? = null + + /** + * The file encoding of the `NOTICE` file. + */ + @get:Optional + @get:Input + var encoding: String? = null + + override fun canTransformResource(element: FileTreeElement): Boolean { + val path = element.relativePath.pathString + return NOTICE_PATH.equals(path, ignoreCase = true) || NOTICE_TXT_PATH.equals(path, ignoreCase = true) + } + + override fun transform(context: TransformerContext) { + if (entries.isEmpty()) { + val year = SimpleDateFormat("yyyy").format(Date()).let { + if (inceptionYear != it) "$inceptionYear-$it" else it + } + // add headers + if (addHeader) { + entries.add("$preamble1$projectName$preamble2") + } else { + entries.add("") + } + // fake second entry, we'll look for a real one later + entries.add("$projectName\nCopyright $year $organizationName\n") + entries.add("$preamble3$organizationName ($organizationURL).\n") } - override fun transform(context: TransformerContext) { - if (entries.isEmpty()) { - val year = SimpleDateFormat("yyyy").format(Date()).let { - if (inceptionYear != it) "$inceptionYear-$it" else it - } - // add headers - if (addHeader) { - entries.add("$preamble1$projectName$preamble2") - } else { - entries.add("") + val reader = context.inputStream.bufferedReader(charset) + var line = reader.readLine() + val sb = StringBuffer() + var currentOrg: MutableSet? = null + var lineCount = 0 + while (line != null) { + val trimmedLine = line.trim() + if (!trimmedLine.startsWith("//")) { + if (trimmedLine.isNotEmpty()) { + if (trimmedLine.startsWith("- ")) { + // resource-bundle 1.3 mode + if (lineCount == 1 && sb.toString().contains("This product includes/uses software(s) developed by")) { + currentOrg = organizationEntries.getOrPut(sb.toString().trim()) { TreeSet() } + sb.setLength(0) + } else if (sb.isNotEmpty() && currentOrg != null) { + currentOrg.add(sb.toString()) + sb.setLength(0) } - // fake second entry, we'll look for a real one later - entries.add("$projectName\nCopyright $year $organizationName\n") - entries.add("$preamble3$organizationName ($organizationURL).\n") + } + sb.append(line).append("\n") + lineCount++ + } else { + val entry = sb.toString() + if (entry.startsWith(projectName) && entry.contains("Copyright ")) { + copyright = entry + } + if (currentOrg == null) { + entries.add(entry) + } else { + currentOrg.add(entry) + } + sb.setLength(0) + lineCount = 0 + currentOrg = null } + } - val reader = context.inputStream.bufferedReader(charset) - var line = reader.readLine() - val sb = StringBuffer() - var currentOrg: MutableSet? = null - var lineCount = 0 - while (line != null) { - val trimmedLine = line.trim() - if (!trimmedLine.startsWith("//")) { - if (trimmedLine.isNotEmpty()) { - if (trimmedLine.startsWith("- ")) { - // resource-bundle 1.3 mode - if (lineCount == 1 && sb.toString().contains("This product includes/uses software(s) developed by")) { - currentOrg = organizationEntries.getOrPut(sb.toString().trim()) { TreeSet() } - sb.setLength(0) - } else if (sb.isNotEmpty() && currentOrg != null) { - currentOrg.add(sb.toString()) - sb.setLength(0) - } - } - sb.append(line).append("\n") - lineCount++ - } else { - val entry = sb.toString() - if (entry.startsWith(projectName) && entry.contains("Copyright ")) { - copyright = entry - } - if (currentOrg == null) { - entries.add(entry) - } else { - currentOrg.add(entry) - } - sb.setLength(0) - lineCount = 0 - currentOrg = null - } - } - - line = reader.readLine() - } - if (sb.isNotEmpty()) { - if (currentOrg == null) { - entries.add(sb.toString()) - } else { - currentOrg.add(sb.toString()) - } - } + line = reader.readLine() } - - override fun hasTransformedResource(): Boolean = true - - override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { - val zipEntry = ZipEntry(NOTICE_PATH) - zipEntry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, zipEntry.time) - os.putNextEntry(zipEntry) - - val writer = PrintWriter(os.writer(charset)) - - var count = 0 - for (line in entries) { - count++ - if (line == copyright && count != 2) continue - if (count == 2 && copyright != null) { - writer.print(copyright) - writer.print('\n') - } else { - writer.print(line) - writer.print('\n') - } - if (count == 3) { - // do org stuff - for ((key, value) in organizationEntries) { - writer.print(key) - writer.print('\n') - for (l in value) { - writer.print(l) - } - writer.print('\n') - } - } + if (sb.isNotEmpty()) { + if (currentOrg == null) { + entries.add(sb.toString()) + } else { + currentOrg.add(sb.toString()) + } + } + } + + override fun hasTransformedResource(): Boolean = true + + override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { + val zipEntry = ZipEntry(NOTICE_PATH) + zipEntry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, zipEntry.time) + os.putNextEntry(zipEntry) + + val writer = PrintWriter(os.writer(charset)) + + var count = 0 + for (line in entries) { + count++ + if (line == copyright && count != 2) continue + if (count == 2 && copyright != null) { + writer.print(copyright) + writer.print('\n') + } else { + writer.print(line) + writer.print('\n') + } + if (count == 3) { + // do org stuff + for ((key, value) in organizationEntries) { + writer.print(key) + writer.print('\n') + for (l in value) { + writer.print(l) + } + writer.print('\n') } - - writer.flush() - entries.clear() + } } - private companion object { - private const val NOTICE_PATH = "META-INF/NOTICE" - private const val NOTICE_TXT_PATH = "META-INF/NOTICE.txt" - } + writer.flush() + entries.clear() + } + + private companion object { + private const val NOTICE_PATH = "META-INF/NOTICE" + private const val NOTICE_TXT_PATH = "META-INF/NOTICE.txt" + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformer.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformer.kt index f28b8014c..3cc27f60a 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformer.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformer.kt @@ -18,37 +18,37 @@ import org.gradle.api.tasks.Optional @CacheableTransformer @Suppress("ktlint:standard:backing-property-naming") open class AppendingTransformer : Transformer { - /** - * Defer initialization, see [issue 763](https://github.com/GradleUp/shadow/issues/763). - */ - private var _data: ByteArrayOutputStream? = null - private inline val data get() = if (_data == null) ByteArrayOutputStream().also { _data = it } else _data!! - - @get:Optional - @get:Input - var resource: String? = null - - override fun canTransformResource(element: FileTreeElement): Boolean { - return resource.equals(element.relativePath.pathString, ignoreCase = true) + /** + * Defer initialization, see [issue 763](https://github.com/GradleUp/shadow/issues/763). + */ + private var _data: ByteArrayOutputStream? = null + private inline val data get() = if (_data == null) ByteArrayOutputStream().also { _data = it } else _data!! + + @get:Optional + @get:Input + var resource: String? = null + + override fun canTransformResource(element: FileTreeElement): Boolean { + return resource.equals(element.relativePath.pathString, ignoreCase = true) + } + + override fun transform(context: TransformerContext) { + context.inputStream.use { + it.copyTo(data) + data.write('\n'.code) } + } - override fun transform(context: TransformerContext) { - context.inputStream.use { - it.copyTo(data) - data.write('\n'.code) - } - } - - override fun hasTransformedResource(): Boolean { - return data.size() > 0 - } + override fun hasTransformedResource(): Boolean { + return data.size() > 0 + } - override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { - val entry = ZipEntry(requireNotNull(resource)) - entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time) - os.putNextEntry(entry) + override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { + val entry = ZipEntry(requireNotNull(resource)) + entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time) + os.putNextEntry(entry) - data.toByteArray().inputStream().copyTo(os) - data.reset() - } + data.toByteArray().inputStream().copyTo(os) + data.reset() + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.kt index 258623830..8616a2605 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.kt @@ -22,113 +22,113 @@ import org.gradle.api.file.FileTreeElement * @author John Engelman */ open class ComponentsXmlResourceTransformer : Transformer { - private val components = mutableMapOf() - - override fun canTransformResource(element: FileTreeElement): Boolean { - return COMPONENTS_XML_PATH == element.relativePath.pathString - } - - override fun transform(context: TransformerContext) { - val newDom = try { - val bis = object : BufferedInputStream(context.inputStream) { - @Throws(IOException::class) - override fun close() { - // leave ZIP open - } - } - Xpp3DomBuilder.build(XmlStreamReader(bis)) - } catch (e: Exception) { - throw IOException("Error parsing components.xml in ${context.inputStream}", e) + private val components = mutableMapOf() + + override fun canTransformResource(element: FileTreeElement): Boolean { + return COMPONENTS_XML_PATH == element.relativePath.pathString + } + + override fun transform(context: TransformerContext) { + val newDom = try { + val bis = object : BufferedInputStream(context.inputStream) { + @Throws(IOException::class) + override fun close() { + // leave ZIP open } + } + Xpp3DomBuilder.build(XmlStreamReader(bis)) + } catch (e: Exception) { + throw IOException("Error parsing components.xml in ${context.inputStream}", e) + } - // Only try to merge in components if there are some elements in the component-set - if (newDom.getChild("components") == null) return - - val children = newDom.getChild("components").getChildren("component") - for (component in children) { - var role: String? = getValue(component, "role") - role = getRelocatedClass(role, context) - setValue(component, "role", role) - - val roleHint = getValue(component, "role-hint") - - var impl: String? = getValue(component, "implementation") - impl = getRelocatedClass(impl, context) - setValue(component, "implementation", impl) - - val key = "$role:$roleHint" - // TODO: use the tools in Plexus to merge these properly. For now, I just need an all-or-nothing - // configuration carry over - components[key]?.getChild("configuration")?.let { - component.addChild(it) - } - - val requirements = component.getChild("requirements") - if (requirements != null && requirements.childCount > 0) { - for (r in requirements.childCount - 1 downTo 0) { - val requirement = requirements.getChild(r) - var requiredRole: String? = getValue(requirement, "role") - requiredRole = getRelocatedClass(requiredRole, context) - setValue(requirement, "role", requiredRole) - } - } - components[key] = component + // Only try to merge in components if there are some elements in the component-set + if (newDom.getChild("components") == null) return + + val children = newDom.getChild("components").getChildren("component") + for (component in children) { + var role: String? = getValue(component, "role") + role = getRelocatedClass(role, context) + setValue(component, "role", role) + + val roleHint = getValue(component, "role-hint") + + var impl: String? = getValue(component, "implementation") + impl = getRelocatedClass(impl, context) + setValue(component, "implementation", impl) + + val key = "$role:$roleHint" + // TODO: use the tools in Plexus to merge these properly. For now, I just need an all-or-nothing + // configuration carry over + components[key]?.getChild("configuration")?.let { + component.addChild(it) + } + + val requirements = component.getChild("requirements") + if (requirements != null && requirements.childCount > 0) { + for (r in requirements.childCount - 1 downTo 0) { + val requirement = requirements.getChild(r) + var requiredRole: String? = getValue(requirement, "role") + requiredRole = getRelocatedClass(requiredRole, context) + setValue(requirement, "role", requiredRole) } + } + components[key] = component } + } - override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { - val entry = ZipEntry(COMPONENTS_XML_PATH) - entry.time = getEntryTimestamp(preserveFileTimestamps, entry.time) - os.putNextEntry(entry) + override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { + val entry = ZipEntry(COMPONENTS_XML_PATH) + entry.time = getEntryTimestamp(preserveFileTimestamps, entry.time) + os.putNextEntry(entry) - transformedResource.inputStream().use { - it.copyTo(os) - } - components.clear() + transformedResource.inputStream().use { + it.copyTo(os) } - - override fun hasTransformedResource(): Boolean = components.isNotEmpty() - - @get:Throws(IOException::class) - private val transformedResource: ByteArray - get() { - val os = ByteArrayOutputStream(1024 * 4) - XmlStreamWriter(os).use { writer -> - val dom = Xpp3Dom("component-set") - val componentDom = Xpp3Dom("components") - dom.addChild(componentDom) - for (component in components.values) { - componentDom.addChild(component) - } - Xpp3DomWriter.write(writer, dom) - } - return os.toByteArray() + components.clear() + } + + override fun hasTransformedResource(): Boolean = components.isNotEmpty() + + @get:Throws(IOException::class) + private val transformedResource: ByteArray + get() { + val os = ByteArrayOutputStream(1024 * 4) + XmlStreamWriter(os).use { writer -> + val dom = Xpp3Dom("component-set") + val componentDom = Xpp3Dom("components") + dom.addChild(componentDom) + for (component in components.values) { + componentDom.addChild(component) } + Xpp3DomWriter.write(writer, dom) + } + return os.toByteArray() + } - companion object { - const val COMPONENTS_XML_PATH: String = "META-INF/plexus/components.xml" - - private fun getRelocatedClass(className: String?, context: TransformerContext): String? { - val stats = context.stats - if (!className.isNullOrEmpty()) { - for (relocator in context.relocators) { - if (relocator.canRelocateClass(className)) { - val relocateClassContext = RelocateClassContext(className, stats) - return relocator.relocateClass(relocateClassContext) - } - } - } - return className + companion object { + const val COMPONENTS_XML_PATH: String = "META-INF/plexus/components.xml" + + private fun getRelocatedClass(className: String?, context: TransformerContext): String? { + val stats = context.stats + if (!className.isNullOrEmpty()) { + for (relocator in context.relocators) { + if (relocator.canRelocateClass(className)) { + val relocateClassContext = RelocateClassContext(className, stats) + return relocator.relocateClass(relocateClassContext) + } } + } + return className + } - private fun getValue(dom: Xpp3Dom, element: String): String { - return dom.getChild(element).value.orEmpty() - } + private fun getValue(dom: Xpp3Dom, element: String): String { + return dom.getChild(element).value.orEmpty() + } - private fun setValue(dom: Xpp3Dom, element: String, value: String?) { - val child = dom.getChild(element) - if (child == null || value.isNullOrEmpty()) return - child.value = value - } + private fun setValue(dom: Xpp3Dom, element: String, value: String?) { + val child = dom.getChild(element) + if (child == null || value.isNullOrEmpty()) return + child.value = value } + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DontIncludeResourceTransformer.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DontIncludeResourceTransformer.kt index b11ed219b..15ac00db7 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DontIncludeResourceTransformer.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DontIncludeResourceTransformer.kt @@ -12,12 +12,12 @@ import org.gradle.api.tasks.Optional * @author John Engelman */ open class DontIncludeResourceTransformer : Transformer by NoOpTransformer { - @get:Optional - @get:Input - var resource: String? = null + @get:Optional + @get:Input + var resource: String? = null - override fun canTransformResource(element: FileTreeElement): Boolean { - val path = element.relativePath.pathString - return !resource.isNullOrEmpty() && path.endsWith(resource!!) - } + override fun canTransformResource(element: FileTreeElement): Boolean { + val path = element.relativePath.pathString + return !resource.isNullOrEmpty() && path.endsWith(resource!!) + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformer.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformer.kt index 6b6e79687..e5bbce6d6 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformer.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformer.kt @@ -26,81 +26,81 @@ import org.gradle.api.file.FileTreeElement */ @CacheableTransformer open class GroovyExtensionModuleTransformer : Transformer { - private val module = Properties() + private val module = Properties() - /** - * default to Groovy 2.4 or earlier - */ - private var legacy = true + /** + * default to Groovy 2.4 or earlier + */ + private var legacy = true - override fun canTransformResource(element: FileTreeElement): Boolean { - val path = element.relativePath.pathString - if (path == GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATH) { - // Groovy 2.5+ - legacy = false - return true - } - return path == GROOVY_LEGACY_EXTENSION_MODULE_DESCRIPTOR_PATH + override fun canTransformResource(element: FileTreeElement): Boolean { + val path = element.relativePath.pathString + if (path == GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATH) { + // Groovy 2.5+ + legacy = false + return true } + return path == GROOVY_LEGACY_EXTENSION_MODULE_DESCRIPTOR_PATH + } - override fun transform(context: TransformerContext) { - val props = Properties() - props.load(context.inputStream) - props.forEach { key, value -> - when (key as String) { - MODULE_NAME_KEY -> handle(key, value as String) { - module.setProperty(key, MERGED_MODULE_NAME) - } - MODULE_VERSION_KEY -> handle(key, value as String) { - module.setProperty(key, MERGED_MODULE_VERSION) - } - EXTENSION_CLASSES_KEY, - STATIC_EXTENSION_CLASSES_KEY, - -> handle(key, value as String) { existingValue -> - module.setProperty(key, "$existingValue,$value") - } - } + override fun transform(context: TransformerContext) { + val props = Properties() + props.load(context.inputStream) + props.forEach { key, value -> + when (key as String) { + MODULE_NAME_KEY -> handle(key, value as String) { + module.setProperty(key, MERGED_MODULE_NAME) + } + MODULE_VERSION_KEY -> handle(key, value as String) { + module.setProperty(key, MERGED_MODULE_VERSION) } + EXTENSION_CLASSES_KEY, + STATIC_EXTENSION_CLASSES_KEY, + -> handle(key, value as String) { existingValue -> + module.setProperty(key, "$existingValue,$value") + } + } } + } - private fun handle(key: String, value: String, mergeValue: (String) -> Unit) { - val existingValue = module.getProperty(key) - if (existingValue != null) { - mergeValue(existingValue) - } else { - module.setProperty(key, value) - } + private fun handle(key: String, value: String, mergeValue: (String) -> Unit) { + val existingValue = module.getProperty(key) + if (existingValue != null) { + mergeValue(existingValue) + } else { + module.setProperty(key, value) } + } - override fun hasTransformedResource(): Boolean = module.isNotEmpty() + override fun hasTransformedResource(): Boolean = module.isNotEmpty() - override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { - val name = if (legacy) GROOVY_LEGACY_EXTENSION_MODULE_DESCRIPTOR_PATH else GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATH - val entry = ZipEntry(name) - entry.time = getEntryTimestamp(preserveFileTimestamps, entry.time) - os.putNextEntry(entry) - module.inputStream().use { - it.copyTo(os) - } - os.closeEntry() + override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { + val name = if (legacy) GROOVY_LEGACY_EXTENSION_MODULE_DESCRIPTOR_PATH else GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATH + val entry = ZipEntry(name) + entry.time = getEntryTimestamp(preserveFileTimestamps, entry.time) + os.putNextEntry(entry) + module.inputStream().use { + it.copyTo(os) } + os.closeEntry() + } - private companion object { - private fun Properties.inputStream(): InputStream { - val os = ByteArrayOutputStream() - store(os, null) - return ByteArrayInputStream(os.toByteArray()) - } - - private const val GROOVY_LEGACY_EXTENSION_MODULE_DESCRIPTOR_PATH = - "META-INF/services/org.codehaus.groovy.runtime.ExtensionModule" - private const val GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATH = - "META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule" - private const val MODULE_NAME_KEY = "moduleName" - private const val MODULE_VERSION_KEY = "moduleVersion" - private const val EXTENSION_CLASSES_KEY = "extensionClasses" - private const val STATIC_EXTENSION_CLASSES_KEY = "staticExtensionClasses" - private const val MERGED_MODULE_NAME = "MergedByShadowJar" - private const val MERGED_MODULE_VERSION = "1.0.0" + private companion object { + private fun Properties.inputStream(): InputStream { + val os = ByteArrayOutputStream() + store(os, null) + return ByteArrayInputStream(os.toByteArray()) } + + private const val GROOVY_LEGACY_EXTENSION_MODULE_DESCRIPTOR_PATH = + "META-INF/services/org.codehaus.groovy.runtime.ExtensionModule" + private const val GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATH = + "META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule" + private const val MODULE_NAME_KEY = "moduleName" + private const val MODULE_VERSION_KEY = "moduleVersion" + private const val EXTENSION_CLASSES_KEY = "extensionClasses" + private const val STATIC_EXTENSION_CLASSES_KEY = "staticExtensionClasses" + private const val MERGED_MODULE_NAME = "MergedByShadowJar" + private const val MERGED_MODULE_VERSION = "1.0.0" + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/IncludeResourceTransformer.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/IncludeResourceTransformer.kt index 53540fc54..fa69cf8d4 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/IncludeResourceTransformer.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/IncludeResourceTransformer.kt @@ -18,22 +18,22 @@ import org.gradle.api.tasks.PathSensitivity * @author John Engelman */ open class IncludeResourceTransformer : Transformer by NoOpTransformer { - @get:InputFile - @get:PathSensitive(PathSensitivity.NONE) - var file: File? = null + @get:InputFile + @get:PathSensitive(PathSensitivity.NONE) + var file: File? = null - @get:Input - var resource: String? = null + @get:Input + var resource: String? = null - override fun hasTransformedResource(): Boolean = file?.exists() == true + override fun hasTransformedResource(): Boolean = file?.exists() == true - override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { - val entry = ZipEntry(requireNotNull(resource)) - entry.time = getEntryTimestamp(preserveFileTimestamps, entry.time) - os.putNextEntry(entry) + override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { + val entry = ZipEntry(requireNotNull(resource)) + entry.time = getEntryTimestamp(preserveFileTimestamps, entry.time) + os.putNextEntry(entry) - requireNotNull(file).inputStream().use { inputStream -> - inputStream.copyTo(os) - } + requireNotNull(file).inputStream().use { inputStream -> + inputStream.copyTo(os) } + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformer.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformer.kt index 37f565fe9..53e3cbf19 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformer.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformer.kt @@ -25,66 +25,66 @@ import org.gradle.api.file.FileTreeElement */ @CacheableTransformer open class Log4j2PluginsCacheFileTransformer : Transformer { - private val temporaryFiles = mutableListOf() - private val relocators = mutableListOf() - private var stats: ShadowStats? = null + private val temporaryFiles = mutableListOf() + private val relocators = mutableListOf() + private var stats: ShadowStats? = null - override fun canTransformResource(element: FileTreeElement): Boolean { - return PluginProcessor.PLUGIN_CACHE_FILE == element.name - } + override fun canTransformResource(element: FileTreeElement): Boolean { + return PluginProcessor.PLUGIN_CACHE_FILE == element.name + } - override fun transform(context: TransformerContext) { - val temporaryFile = File.createTempFile("Log4j2Plugins", ".dat") - temporaryFile.deleteOnExit() - temporaryFiles.add(temporaryFile) - val fos = temporaryFile.outputStream() - context.inputStream.use { - it.copyTo(fos) - } + override fun transform(context: TransformerContext) { + val temporaryFile = File.createTempFile("Log4j2Plugins", ".dat") + temporaryFile.deleteOnExit() + temporaryFiles.add(temporaryFile) + val fos = temporaryFile.outputStream() + context.inputStream.use { + it.copyTo(fos) + } - relocators.addAll(context.relocators) + relocators.addAll(context.relocators) - if (stats == null) { - stats = context.stats - } + if (stats == null) { + stats = context.stats } + } - override fun hasTransformedResource(): Boolean { - // This functionality matches the original plugin, however, I'm not clear what - // the exact logic is. From what I can tell temporaryFiles should be never be empty - // if anything has been performed. - val hasTransformedMultipleFiles = temporaryFiles.size > 1 - val hasAtLeastOneFileAndRelocator = temporaryFiles.isNotEmpty() && relocators.isNotEmpty() - return hasTransformedMultipleFiles || hasAtLeastOneFileAndRelocator - } + override fun hasTransformedResource(): Boolean { + // This functionality matches the original plugin, however, I'm not clear what + // the exact logic is. From what I can tell temporaryFiles should be never be empty + // if anything has been performed. + val hasTransformedMultipleFiles = temporaryFiles.size > 1 + val hasAtLeastOneFileAndRelocator = temporaryFiles.isNotEmpty() && relocators.isNotEmpty() + return hasTransformedMultipleFiles || hasAtLeastOneFileAndRelocator + } - override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { - val pluginCache = PluginCache() - pluginCache.loadCacheFiles(urlEnumeration) - relocatePlugins(pluginCache) - val entry = ZipEntry(PluginProcessor.PLUGIN_CACHE_FILE) - entry.time = getEntryTimestamp(preserveFileTimestamps, entry.time) - os.putNextEntry(entry) - pluginCache.writeCache(CloseShieldOutputStream.wrap(os)) - temporaryFiles.clear() - } + override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { + val pluginCache = PluginCache() + pluginCache.loadCacheFiles(urlEnumeration) + relocatePlugins(pluginCache) + val entry = ZipEntry(PluginProcessor.PLUGIN_CACHE_FILE) + entry.time = getEntryTimestamp(preserveFileTimestamps, entry.time) + os.putNextEntry(entry) + pluginCache.writeCache(CloseShieldOutputStream.wrap(os)) + temporaryFiles.clear() + } - private fun relocatePlugins(pluginCache: PluginCache) { - pluginCache.allCategories.values.forEach { currentMap -> - currentMap.values.forEach { currentPluginEntry -> - val className = currentPluginEntry.className - val relocateClassContext = RelocateClassContext(className, requireNotNull(stats)) - relocators.firstOrNull { it.canRelocateClass(className) }?.let { relocator -> - // Then we perform that relocation and update the plugin entry to reflect the new value. - currentPluginEntry.className = relocator.relocateClass(relocateClassContext) - } - } + private fun relocatePlugins(pluginCache: PluginCache) { + pluginCache.allCategories.values.forEach { currentMap -> + currentMap.values.forEach { currentPluginEntry -> + val className = currentPluginEntry.className + val relocateClassContext = RelocateClassContext(className, requireNotNull(stats)) + relocators.firstOrNull { it.canRelocateClass(className) }?.let { relocator -> + // Then we perform that relocation and update the plugin entry to reflect the new value. + currentPluginEntry.className = relocator.relocateClass(relocateClassContext) } + } } + } - private val urlEnumeration: Enumeration - get() { - val urls = temporaryFiles.map { it.toURI().toURL() } - return Collections.enumeration(urls) - } + private val urlEnumeration: Enumeration + get() { + val urls = temporaryFiles.map { it.toURI().toURL() } + return Collections.enumeration(urls) + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformer.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformer.kt index e925cc08b..6e1965ba5 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformer.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformer.kt @@ -18,57 +18,57 @@ import org.slf4j.LoggerFactory * @author Chris Rankin */ open class ManifestAppenderTransformer : Transformer { - private var manifestContents = ByteArray(0) - private val _attributes = mutableListOf>>() + private var manifestContents = ByteArray(0) + private val _attributes = mutableListOf>>() - @get:Input - open val attributes: List>> get() = _attributes + @get:Input + open val attributes: List>> get() = _attributes - override fun canTransformResource(element: FileTreeElement): Boolean { - return MANIFEST_NAME.equals(element.relativePath.pathString, ignoreCase = true) - } + override fun canTransformResource(element: FileTreeElement): Boolean { + return MANIFEST_NAME.equals(element.relativePath.pathString, ignoreCase = true) + } - override fun transform(context: TransformerContext) { - if (manifestContents.isEmpty()) { - try { - context.inputStream.use { inputStream -> - val outputStream = ByteArrayOutputStream() - inputStream.copyTo(outputStream) - manifestContents = outputStream.toByteArray() - } - } catch (e: IOException) { - logger.warn("Failed to read MANIFEST.MF", e) - } + override fun transform(context: TransformerContext) { + if (manifestContents.isEmpty()) { + try { + context.inputStream.use { inputStream -> + val outputStream = ByteArrayOutputStream() + inputStream.copyTo(outputStream) + manifestContents = outputStream.toByteArray() } + } catch (e: IOException) { + logger.warn("Failed to read MANIFEST.MF", e) + } } + } - override fun hasTransformedResource(): Boolean = _attributes.isNotEmpty() + override fun hasTransformedResource(): Boolean = _attributes.isNotEmpty() - override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { - val entry = ZipEntry(MANIFEST_NAME) - entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time) - os.putNextEntry(entry) - os.write(manifestContents) + override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { + val entry = ZipEntry(MANIFEST_NAME) + entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time) + os.putNextEntry(entry) + os.write(manifestContents) - if (_attributes.isNotEmpty()) { - for ((key, value) in _attributes) { - os.write(key.toByteArray()) - os.write(SEPARATOR) - os.write(value.toString().toByteArray()) - os.write(EOL) - } - os.write(EOL) - _attributes.clear() - } + if (_attributes.isNotEmpty()) { + for ((key, value) in _attributes) { + os.write(key.toByteArray()) + os.write(SEPARATOR) + os.write(value.toString().toByteArray()) + os.write(EOL) + } + os.write(EOL) + _attributes.clear() } + } - open fun append(name: String, value: Comparable<*>): ManifestAppenderTransformer = apply { - _attributes.add(Pair(name, value)) - } + open fun append(name: String, value: Comparable<*>): ManifestAppenderTransformer = apply { + _attributes.add(Pair(name, value)) + } - private companion object { - private val logger = LoggerFactory.getLogger(ManifestAppenderTransformer::class.java) - private val EOL = "\r\n".toByteArray() - private val SEPARATOR = ": ".toByteArray() - } + private companion object { + private val logger = LoggerFactory.getLogger(ManifestAppenderTransformer::class.java) + private val EOL = "\r\n".toByteArray() + private val SEPARATOR = ": ".toByteArray() + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestResourceTransformer.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestResourceTransformer.kt index fb2ced9ce..900e4cb98 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestResourceTransformer.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestResourceTransformer.kt @@ -23,66 +23,66 @@ import org.slf4j.LoggerFactory * @author John Engelman */ open class ManifestResourceTransformer : Transformer { - private var manifestDiscovered = false - private var manifest: Manifest? = null + private var manifestDiscovered = false + private var manifest: Manifest? = null - @get:Optional - @get:Input - var mainClass: String? = null + @get:Optional + @get:Input + var mainClass: String? = null - @get:Optional - @get:Input - var manifestEntries: MutableMap? = null + @get:Optional + @get:Input + var manifestEntries: MutableMap? = null - override fun canTransformResource(element: FileTreeElement): Boolean { - val path = element.relativePath.pathString - return JarFile.MANIFEST_NAME.equals(path, ignoreCase = true) - } + override fun canTransformResource(element: FileTreeElement): Boolean { + val path = element.relativePath.pathString + return JarFile.MANIFEST_NAME.equals(path, ignoreCase = true) + } - override fun transform(context: TransformerContext) { - // We just want to take the first manifest we come across as that's our project's manifest. This is the behavior - // now which is situational at best. Right now there is no context passed in with the processing so we cannot - // tell what artifact is being processed. - if (!manifestDiscovered) { - try { - manifest = Manifest(context.inputStream) - manifestDiscovered = true - } catch (e: IOException) { - logger.warn("Failed to read MANIFEST.MF", e) - } - } + override fun transform(context: TransformerContext) { + // We just want to take the first manifest we come across as that's our project's manifest. This is the behavior + // now which is situational at best. Right now there is no context passed in with the processing so we cannot + // tell what artifact is being processed. + if (!manifestDiscovered) { + try { + manifest = Manifest(context.inputStream) + manifestDiscovered = true + } catch (e: IOException) { + logger.warn("Failed to read MANIFEST.MF", e) + } } + } - override fun hasTransformedResource(): Boolean = true - - override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { - // If we didn't find a manifest, then let's create one. - if (manifest == null) { - manifest = Manifest() - } - - val attributes = manifest!!.mainAttributes - mainClass?.let { - attributes[Attributes.Name.MAIN_CLASS] = it - } - manifestEntries?.forEach { (key, value) -> - attributes[Attributes.Name(key)] = value - } + override fun hasTransformedResource(): Boolean = true - val entry = ZipEntry(JarFile.MANIFEST_NAME) - entry.time = getEntryTimestamp(preserveFileTimestamps, entry.time) - os.putNextEntry(entry) - manifest!!.write(os) + override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { + // If we didn't find a manifest, then let's create one. + if (manifest == null) { + manifest = Manifest() } - open fun attributes(attributes: Map): ManifestResourceTransformer = apply { - if (manifestEntries == null) { - manifestEntries = LinkedHashMap() - } - manifestEntries!!.putAll(attributes) + val attributes = manifest!!.mainAttributes + mainClass?.let { + attributes[Attributes.Name.MAIN_CLASS] = it } + manifestEntries?.forEach { (key, value) -> + attributes[Attributes.Name(key)] = value + } + + val entry = ZipEntry(JarFile.MANIFEST_NAME) + entry.time = getEntryTimestamp(preserveFileTimestamps, entry.time) + os.putNextEntry(entry) + manifest!!.write(os) + } - private companion object { - private val logger = LoggerFactory.getLogger(ManifestResourceTransformer::class.java) + open fun attributes(attributes: Map): ManifestResourceTransformer = apply { + if (manifestEntries == null) { + manifestEntries = LinkedHashMap() } + manifestEntries!!.putAll(attributes) + } + + private companion object { + private val logger = LoggerFactory.getLogger(ManifestResourceTransformer::class.java) + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.kt index ba5a2632b..2501f04f0 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.kt @@ -90,138 +90,138 @@ import org.gradle.api.tasks.Internal * @author Marc Philipp */ open class PropertiesFileTransformer : Transformer { - private val propertiesEntries = mutableMapOf() - private val _charset get() = Charset.forName(charset) - - @get:Input - var paths: List = listOf() - - @get:Input - var mappings: Map> = mapOf() - - /** - * Optional values: first, latest, append. - */ - @get:Input - var mergeStrategy: String = "first" - - @get:Input - var mergeSeparator: String = "," - - @get:Input - var charset: String = "ISO_8859_1" - - /** - * Use [java.util.function.Function] here for compatibility with Groovy and Java. - */ - @get:Internal - var keyTransformer: Function = IDENTITY - - override fun canTransformResource(element: FileTreeElement): Boolean { - val path = element.relativePath.pathString - if (path in mappings) return true - for (key in mappings.keys) { - if (key.toRegex().containsMatchIn(path)) return true - } - if (path in paths) return true - for (p in paths) { - if (p.toRegex().containsMatchIn(path)) return true - } - return mappings.isEmpty() && paths.isEmpty() && path.endsWith(PROPERTIES_SUFFIX) + private val propertiesEntries = mutableMapOf() + private val _charset get() = Charset.forName(charset) + + @get:Input + var paths: List = listOf() + + @get:Input + var mappings: Map> = mapOf() + + /** + * Optional values: first, latest, append. + */ + @get:Input + var mergeStrategy: String = "first" + + @get:Input + var mergeSeparator: String = "," + + @get:Input + var charset: String = "ISO_8859_1" + + /** + * Use [java.util.function.Function] here for compatibility with Groovy and Java. + */ + @get:Internal + var keyTransformer: Function = IDENTITY + + override fun canTransformResource(element: FileTreeElement): Boolean { + val path = element.relativePath.pathString + if (path in mappings) return true + for (key in mappings.keys) { + if (key.toRegex().containsMatchIn(path)) return true } - - override fun transform(context: TransformerContext) { - val props = propertiesEntries[context.path] - val incoming = loadAndTransformKeys(context.inputStream) - if (props == null) { - propertiesEntries[context.path] = incoming + if (path in paths) return true + for (p in paths) { + if (p.toRegex().containsMatchIn(path)) return true + } + return mappings.isEmpty() && paths.isEmpty() && path.endsWith(PROPERTIES_SUFFIX) + } + + override fun transform(context: TransformerContext) { + val props = propertiesEntries[context.path] + val incoming = loadAndTransformKeys(context.inputStream) + if (props == null) { + propertiesEntries[context.path] = incoming + } else { + for ((key, value) in incoming) { + if (props.containsKey(key)) { + when (mergeStrategyFor(context.path).lowercase()) { + "latest" -> props[key] = value + "append" -> props[key] = props.getProperty(key as String) + mergeSeparatorFor(context.path) + value + "first" -> Unit + else -> Unit + } } else { - for ((key, value) in incoming) { - if (props.containsKey(key)) { - when (mergeStrategyFor(context.path).lowercase()) { - "latest" -> props[key] = value - "append" -> props[key] = props.getProperty(key as String) + mergeSeparatorFor(context.path) + value - "first" -> Unit - else -> Unit - } - } else { - props[key] = value - } - } + props[key] = value } + } } - - private fun loadAndTransformKeys(inputStream: InputStream): CleanProperties { - val props = CleanProperties() - // InputStream closed by caller, so we don't do it here. - props.load(inputStream.reader(_charset)) - return transformKeys(props) + } + + private fun loadAndTransformKeys(inputStream: InputStream): CleanProperties { + val props = CleanProperties() + // InputStream closed by caller, so we don't do it here. + props.load(inputStream.reader(_charset)) + return transformKeys(props) + } + + private fun transformKeys(properties: Properties): CleanProperties { + if (keyTransformer === IDENTITY) { + return properties as CleanProperties } - - private fun transformKeys(properties: Properties): CleanProperties { - if (keyTransformer === IDENTITY) { - return properties as CleanProperties - } - val result = CleanProperties() - properties.forEach { (key, value) -> - result[keyTransformer.apply(key as String)] = value - } - return result + val result = CleanProperties() + properties.forEach { (key, value) -> + result[keyTransformer.apply(key as String)] = value } + return result + } - private fun mergeStrategyFor(path: String): String { - mappings[path]?.let { - return it["mergeStrategy"] ?: mergeStrategy - } - for (key in mappings.keys) { - if (key.toRegex().containsMatchIn(path)) { - return mappings[key]?.get("mergeStrategy") ?: mergeStrategy - } - } - return mergeStrategy + private fun mergeStrategyFor(path: String): String { + mappings[path]?.let { + return it["mergeStrategy"] ?: mergeStrategy } - - private fun mergeSeparatorFor(path: String): String { - mappings[path]?.let { - return it["mergeSeparator"] ?: mergeSeparator - } - for (key in mappings.keys) { - if (key.toRegex().containsMatchIn(path)) { - return mappings[key]?.get("mergeSeparator") ?: mergeSeparator - } - } - return mergeSeparator + for (key in mappings.keys) { + if (key.toRegex().containsMatchIn(path)) { + return mappings[key]?.get("mergeStrategy") ?: mergeStrategy + } } + return mergeStrategy + } - override fun hasTransformedResource(): Boolean { - return propertiesEntries.isNotEmpty() + private fun mergeSeparatorFor(path: String): String { + mappings[path]?.let { + return it["mergeSeparator"] ?: mergeSeparator } - - override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { - // cannot close the writer as the OutputStream needs to remain open - val zipWriter = os.writer(_charset) - propertiesEntries.forEach { (path, props) -> - val entry = ZipEntry(path) - entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time) - os.putNextEntry(entry) - props.toReader().use { - it.copyTo(zipWriter) - } - zipWriter.flush() - os.closeEntry() - } + for (key in mappings.keys) { + if (key.toRegex().containsMatchIn(path)) { + return mappings[key]?.get("mergeSeparator") ?: mergeSeparator + } } - - private fun Properties.toReader(): InputStreamReader { - val os = ByteArrayOutputStream() - os.writer(Charset.forName(charset)).use { writer -> - store(writer, "") - } - return os.toByteArray().inputStream().reader(_charset) + return mergeSeparator + } + + override fun hasTransformedResource(): Boolean { + return propertiesEntries.isNotEmpty() + } + + override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { + // cannot close the writer as the OutputStream needs to remain open + val zipWriter = os.writer(_charset) + propertiesEntries.forEach { (path, props) -> + val entry = ZipEntry(path) + entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time) + os.putNextEntry(entry) + props.toReader().use { + it.copyTo(zipWriter) + } + zipWriter.flush() + os.closeEntry() } + } - private companion object { - private const val PROPERTIES_SUFFIX = ".properties" - private val IDENTITY = Function { it } + private fun Properties.toReader(): InputStreamReader { + val os = ByteArrayOutputStream() + os.writer(Charset.forName(charset)).use { writer -> + store(writer, "") } + return os.toByteArray().inputStream().reader(_charset) + } + + private companion object { + private const val PROPERTIES_SUFFIX = ".properties" + private val IDENTITY = Function { it } + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.kt index 824ac063a..d2f4e37db 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.kt @@ -29,88 +29,88 @@ import org.gradle.api.tasks.util.PatternSet */ @CacheableTransformer open class ServiceFileTransformer( - private val patternSet: PatternSet = PatternSet() - .include(SERVICES_PATTERN) - .exclude(GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATTERN), + private val patternSet: PatternSet = PatternSet() + .include(SERVICES_PATTERN) + .exclude(GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATTERN), ) : Transformer, - PatternFilterable by patternSet { - private val serviceEntries = mutableMapOf() + PatternFilterable by patternSet { + private val serviceEntries = mutableMapOf() - override fun canTransformResource(element: FileTreeElement): Boolean { - val target = if (element is ShadowCopyAction.ArchiveFileTreeElement) element.asFileTreeElement() else element - return patternSet.asSpec.isSatisfiedBy(target) - } + override fun canTransformResource(element: FileTreeElement): Boolean { + val target = if (element is ShadowCopyAction.ArchiveFileTreeElement) element.asFileTreeElement() else element + return patternSet.asSpec.isSatisfiedBy(target) + } - override fun transform(context: TransformerContext) { - val lines = context.inputStream.bufferedReader().readLines().toMutableList() - var targetPath = context.path - context.relocators.forEach { rel -> - if (rel.canRelocateClass(File(targetPath).name)) { - val classContext = RelocateClassContext.builder().className(targetPath).stats(context.stats).build() - targetPath = rel.relocateClass(classContext) - } - lines.forEachIndexed { i, line -> - if (rel.canRelocateClass(line)) { - val lineContext = RelocateClassContext.builder().className(line).stats(context.stats).build() - lines[i] = rel.relocateClass(lineContext) - } - } - } - lines.forEach { line -> - serviceEntries[targetPath] = serviceEntries.getOrDefault(targetPath, ServiceStream()).apply { - append(ByteArrayInputStream(line.toByteArray())) - } + override fun transform(context: TransformerContext) { + val lines = context.inputStream.bufferedReader().readLines().toMutableList() + var targetPath = context.path + context.relocators.forEach { rel -> + if (rel.canRelocateClass(File(targetPath).name)) { + val classContext = RelocateClassContext.builder().className(targetPath).stats(context.stats).build() + targetPath = rel.relocateClass(classContext) + } + lines.forEachIndexed { i, line -> + if (rel.canRelocateClass(line)) { + val lineContext = RelocateClassContext.builder().className(line).stats(context.stats).build() + lines[i] = rel.relocateClass(lineContext) } + } + } + lines.forEach { line -> + serviceEntries[targetPath] = serviceEntries.getOrDefault(targetPath, ServiceStream()).apply { + append(ByteArrayInputStream(line.toByteArray())) + } } + } - override fun hasTransformedResource(): Boolean = serviceEntries.isNotEmpty() + override fun hasTransformedResource(): Boolean = serviceEntries.isNotEmpty() - override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { - serviceEntries.forEach { (path, stream) -> - val entry = ZipEntry(path) - entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time) - os.putNextEntry(entry) - stream.toInputStream().use { - it.copyTo(os) - } - os.closeEntry() - } + override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { + serviceEntries.forEach { (path, stream) -> + val entry = ZipEntry(path) + entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time) + os.putNextEntry(entry) + stream.toInputStream().use { + it.copyTo(os) + } + os.closeEntry() } + } - /** - * {@inheritDoc} - */ - @Input - override fun getIncludes(): Set = patternSet.includes + /** + * {@inheritDoc} + */ + @Input + override fun getIncludes(): Set = patternSet.includes - /** - * {@inheritDoc} - */ - @Input - override fun getExcludes(): Set = patternSet.excludes + /** + * {@inheritDoc} + */ + @Input + override fun getExcludes(): Set = patternSet.excludes - open fun setPath(path: String): PatternFilterable = apply { - patternSet.setIncludes(listOf("$path/**")) - } + open fun setPath(path: String): PatternFilterable = apply { + patternSet.setIncludes(listOf("$path/**")) + } - open class ServiceStream : ByteArrayOutputStream(1024) { - @Throws(IOException::class) - open fun append(inputStream: InputStream) { - if (count > 0 && buf[count - 1] != '\n'.code.toByte() && buf[count - 1] != '\r'.code.toByte()) { - val newline = "\n".toByteArray() - write(newline, 0, newline.size) - } - inputStream.use { - it.copyTo(this) - } - } - - open fun toInputStream(): InputStream = ByteArrayInputStream(buf, 0, count) + open class ServiceStream : ByteArrayOutputStream(1024) { + @Throws(IOException::class) + open fun append(inputStream: InputStream) { + if (count > 0 && buf[count - 1] != '\n'.code.toByte() && buf[count - 1] != '\r'.code.toByte()) { + val newline = "\n".toByteArray() + write(newline, 0, newline.size) + } + inputStream.use { + it.copyTo(this) + } } - private companion object { - private const val SERVICES_PATTERN = "META-INF/services/**" - private const val GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATTERN = - "META-INF/services/org.codehaus.groovy.runtime.ExtensionModule" - } + open fun toInputStream(): InputStream = ByteArrayInputStream(buf, 0, count) + } + + private companion object { + private const val SERVICES_PATTERN = "META-INF/services/**" + private const val GROOVY_EXTENSION_MODULE_DESCRIPTOR_PATTERN = + "META-INF/services/org.codehaus.groovy.runtime.ExtensionModule" + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Transformer.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Transformer.kt index 9a2aa5e5c..6039d8db4 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Transformer.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Transformer.kt @@ -13,21 +13,21 @@ import org.gradle.api.tasks.Internal * @author John Engelman */ interface Transformer : Named { - fun canTransformResource(element: FileTreeElement): Boolean + fun canTransformResource(element: FileTreeElement): Boolean - fun transform(context: TransformerContext) + fun transform(context: TransformerContext) - fun hasTransformedResource(): Boolean + fun hasTransformedResource(): Boolean - fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) + fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) - @Internal - override fun getName(): String = this::class.java.simpleName + @Internal + override fun getName(): String = this::class.java.simpleName } object NoOpTransformer : Transformer { - override fun canTransformResource(element: FileTreeElement): Boolean = false - override fun transform(context: TransformerContext): Unit = Unit - override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean): Unit = Unit - override fun hasTransformedResource(): Boolean = false + override fun canTransformResource(element: FileTreeElement): Boolean = false + override fun transform(context: TransformerContext): Unit = Unit + override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean): Unit = Unit + override fun hasTransformedResource(): Boolean = false } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerContext.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerContext.kt index f80f19392..00a7801f9 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerContext.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerContext.kt @@ -6,36 +6,36 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowCopyAction import java.io.InputStream data class TransformerContext @JvmOverloads constructor( - val path: String, - val inputStream: InputStream, - val relocators: List = emptyList(), - val stats: ShadowStats = ShadowStats(), + val path: String, + val inputStream: InputStream, + val relocators: List = emptyList(), + val stats: ShadowStats = ShadowStats(), ) { - class Builder { - private var path = "" - private var inputStream: InputStream? = null - private var relocators = emptyList() - private var stats = ShadowStats() + class Builder { + private var path = "" + private var inputStream: InputStream? = null + private var relocators = emptyList() + private var stats = ShadowStats() - fun path(path: String): Builder = apply { this.path = path } - fun inputStream(inputStream: InputStream): Builder = apply { this.inputStream = inputStream } - fun relocators(relocators: List): Builder = apply { this.relocators = relocators } - fun stats(stats: ShadowStats): Builder = apply { this.stats = stats } - fun build(): TransformerContext = TransformerContext( - path = path, - inputStream = inputStream ?: error("inputStream is required"), - relocators = relocators, - stats = stats, - ) - } + fun path(path: String): Builder = apply { this.path = path } + fun inputStream(inputStream: InputStream): Builder = apply { this.inputStream = inputStream } + fun relocators(relocators: List): Builder = apply { this.relocators = relocators } + fun stats(stats: ShadowStats): Builder = apply { this.stats = stats } + fun build(): TransformerContext = TransformerContext( + path = path, + inputStream = inputStream ?: error("inputStream is required"), + relocators = relocators, + stats = stats, + ) + } - companion object { - @JvmStatic - fun builder(): Builder = Builder() + companion object { + @JvmStatic + fun builder(): Builder = Builder() - @JvmStatic - fun getEntryTimestamp(preserveFileTimestamps: Boolean, entryTime: Long): Long { - return if (preserveFileTimestamps) entryTime else ShadowCopyAction.CONSTANT_TIME_FOR_ZIP_ENTRIES - } + @JvmStatic + fun getEntryTimestamp(preserveFileTimestamps: Boolean, entryTime: Long): Long { + return if (preserveFileTimestamps) entryTime else ShadowCopyAction.CONSTANT_TIME_FOR_ZIP_ENTRIES } + } } diff --git a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformer.kt b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformer.kt index 1b5b6d0f8..b0d74d03b 100644 --- a/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformer.kt +++ b/api/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformer.kt @@ -24,59 +24,59 @@ import org.xml.sax.InputSource */ @CacheableTransformer open class XmlAppendingTransformer : Transformer { - private var doc: Document? = null + private var doc: Document? = null - @get:Input - var ignoreDtd: Boolean = true + @get:Input + var ignoreDtd: Boolean = true - @get:Optional - @get:Input - var resource: String? = null + @get:Optional + @get:Input + var resource: String? = null - override fun canTransformResource(element: FileTreeElement): Boolean { - return resource?.equals(element.relativePath.pathString, ignoreCase = true) == true - } + override fun canTransformResource(element: FileTreeElement): Boolean { + return resource?.equals(element.relativePath.pathString, ignoreCase = true) == true + } - override fun transform(context: TransformerContext) { - val r = try { - SAXBuilder(XMLReaders.NONVALIDATING).apply { - expandEntities = false - if (ignoreDtd) { - entityResolver = EntityResolver { _, _ -> InputSource(StringReader("")) } - } - }.build(context.inputStream) - } catch (e: JDOMException) { - throw RuntimeException("Error processing resource $resource: ${e.message}", e) + override fun transform(context: TransformerContext) { + val r = try { + SAXBuilder(XMLReaders.NONVALIDATING).apply { + expandEntities = false + if (ignoreDtd) { + entityResolver = EntityResolver { _, _ -> InputSource(StringReader("")) } } + }.build(context.inputStream) + } catch (e: JDOMException) { + throw RuntimeException("Error processing resource $resource: ${e.message}", e) + } - if (doc == null) { - doc = r - } else { - val root = r.rootElement - root.attributes.forEach { a -> - val mergedEl = doc!!.rootElement - val mergedAtt = mergedEl.getAttribute(a.name, a.namespace) - if (mergedAtt == null) { - mergedEl.setAttribute(a) - } - } - root.children.forEach { n -> - doc!!.rootElement.addContent(n.clone()) - } + if (doc == null) { + doc = r + } else { + val root = r.rootElement + root.attributes.forEach { a -> + val mergedEl = doc!!.rootElement + val mergedAtt = mergedEl.getAttribute(a.name, a.namespace) + if (mergedAtt == null) { + mergedEl.setAttribute(a) } + } + root.children.forEach { n -> + doc!!.rootElement.addContent(n.clone()) + } } + } - override fun hasTransformedResource(): Boolean = doc != null + override fun hasTransformedResource(): Boolean = doc != null - override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { - val entry = ZipEntry(resource) - entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time) - os.putNextEntry(entry) - XMLOutputter(Format.getPrettyFormat()).output(doc, os) - doc = null - } + override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { + val entry = ZipEntry(resource) + entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time) + os.putNextEntry(entry) + XMLOutputter(Format.getPrettyFormat()).output(doc, os) + doc = null + } - companion object { - const val XSI_NS: String = "http://www.w3.org/2001/XMLSchema-instance" - } + companion object { + const val XSI_NS: String = "http://www.w3.org/2001/XMLSchema-instance" + } }