name.remal.gradle_plugins.plugins.classes_relocation.ClassesRelocationPlugin.kt Maven / Gradle / Ivy
package name.remal.gradle_plugins.plugins.classes_relocation
import name.remal.gradle_plugins.dsl.*
import name.remal.gradle_plugins.dsl.extensions.*
import name.remal.gradle_plugins.plugins.classes_processing.ClassesProcessingPlugin
import name.remal.gradle_plugins.plugins.code_quality.jacoco.JacocoSettingsPlugin
import name.remal.gradle_plugins.plugins.common.CommonSettingsPlugin
import name.remal.gradle_plugins.plugins.java.JavaPluginId
import name.remal.startsWith
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.internal.artifacts.dependencies.SelfResolvingDependencyInternal
import org.gradle.api.internal.artifacts.dsl.dependencies.DependencyFactory.ClassPathNotation
import org.gradle.api.tasks.AbstractCopyTask
import org.gradle.api.tasks.TaskContainer
private const val RELOCATE_CLASSES_CONFIGURATION_NAME = "relocateClasses"
private const val EXCLUDE_FROM_FORCED_CLASSES_RELOCATION_CONFIGURATION_NAME = "excludeFromForcedClassesRelocation"
private const val EXCLUDE_FROM_CLASSES_RELOCATION_CONFIGURATION_NAME = "excludeFromClassesRelocation"
@Plugin(
id = "name.remal.classes-relocation",
description = "Plugin that provides classes relocating functionality",
tags = ["java", "relocation", "shadow"]
)
@ApplyPlugins(JavaPluginId::class)
@ApplyPluginClasses(CommonSettingsPlugin::class, ClassesProcessingPlugin::class, JacocoSettingsPlugin::class)
class ClassesRelocationPlugin : BaseReflectiveProjectPlugin() {
@PluginAction(order = -1003)
fun ConfigurationContainer.`Create 'relocateClasses' configuration`() {
create(RELOCATE_CLASSES_CONFIGURATION_NAME) {
compileOnly.extendsFrom(it)
}
}
@PluginAction(order = -1002)
fun ConfigurationContainer.`Create 'excludeFromForcedClassesRelocation' configuration`(dependencies: DependencyHandler) {
create(EXCLUDE_FROM_FORCED_CLASSES_RELOCATION_CONFIGURATION_NAME) {
it.extendsFrom(runtimeClasspath)
it.beforeResolve { conf ->
val selfResolvingDependencies = compileClasspath.allDependencies.filterIsInstance(SelfResolvingDependencyInternal::class.java)
ClassPathNotation.values().forEach {
val displayName = it.displayName
val dependency = selfResolvingDependencies.firstOrNull { displayName == it.targetComponentId?.displayName }
if (dependency != null) {
conf.dependencies.add(dependency)
}
}
}
}
}
@PluginAction(order = -1001)
fun ConfigurationContainer.`Create 'excludeFromClassesRelocation' configuration`() {
create(EXCLUDE_FROM_CLASSES_RELOCATION_CONFIGURATION_NAME) {
it.extendsFrom(excludeFromForcedClassesRelocation)
}
}
@PluginAction(order = -1000)
fun ConfigurationContainer.`Make 'excludeFromClassesRelocation excluding 'compileClasspath'`() {
this.excludeFromClassesRelocation.beforeResolve { excludeFromClassesRelocation ->
val confsToSkip = relocateClasses.hierarchy + excludeFromClassesRelocation.hierarchy
compileClasspath.hierarchy.forEach { conf ->
if (conf !in confsToSkip) {
excludeFromClassesRelocation.dependencies.addAll(conf.dependencies)
}
}
}
}
@PluginAction("Support name.remal.gradle_plugins.api.RelocateClasses annotation")
fun supportRelocateClassesAnnotation() {
// It's implemented via RelocateClassesClassesProcessorsGradleTaskFactory
}
@PluginAction
fun TaskContainer.`Merge relocated classes in AbstractCopyTask tasks`() {
all(AbstractCopyTask::class.java) {
it.doSetup {
val relocatedClassesJavaPackageSegments = it.project.relocatedClassesJavaPackageName.split('.').toTypedArray()
it.eachFile {
if (it.relativePath.segments.startsWith(relocatedClassesJavaPackageSegments)) {
it.duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
}
}
}
}
}
val Project.relocatedClassesJavaPackageName get() = "$javaPackageName.internal._relocated"
val ConfigurationContainer.relocateClasses: Configuration get() = this[RELOCATE_CLASSES_CONFIGURATION_NAME]
val ConfigurationContainer.excludeFromForcedClassesRelocation: Configuration get() = this[EXCLUDE_FROM_FORCED_CLASSES_RELOCATION_CONFIGURATION_NAME]
val ConfigurationContainer.excludeFromClassesRelocation: Configuration get() = this[EXCLUDE_FROM_CLASSES_RELOCATION_CONFIGURATION_NAME]