All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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]




© 2015 - 2024 Weber Informatics LLC | Privacy Policy