diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index 4266818771a..326313c7c56 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -11,21 +11,62 @@ import org.gradle.api.logging.Logging import java.util.Properties import java.io.FileNotFoundException import org.gradle.api.initialization.dsl.ScriptHandler +import java.lang.reflect.Method abstract class KotlinBasePluginWrapper: Plugin { + class object { + val pluginVersionsMap: MutableMap>> = hashMapOf() + } + val log = Logging.getLogger(this.javaClass) public override fun apply(project: Project) { + val sourceBuildScript = findSourceBuildScript(project) if (sourceBuildScript == null) { log.error("Failed to determine source cofiguration of kotlin plugin. Can not download core. Please verify that this or any parent project " + - "contains 'kotlin-gradle-plugin' in buildscript's classpath configuration.") + "contains 'kotlin-gradle-plugin' in buildscript's classpath configuration.") return } - val dependencyHandler : DependencyHandler = sourceBuildScript.getDependencies() - val configurationsContainer : ConfigurationContainer = sourceBuildScript.getConfigurations() + val kotlinPluginVersion = loadKotlinVersionFromResource() + project.getExtensions().getExtraProperties()?.set("kotlin.gradle.plugin.version", kotlinPluginVersion) + + val cls = pluginVersionsMap.getOrElse("$kotlinPluginVersion:${getPluginClassName()}", { loadPluginInIsolatedClassloader(kotlinPluginVersion, sourceBuildScript) }) + + val constructor = cls.getConstructor(javaClass()) + val method = cls.getMethod("apply", javaClass()) + log.debug("'apply' method found, invoking...") + + val plugin = constructor.newInstance(sourceBuildScript) + log.debug("Plugin class instantiated") + + method?.invoke(plugin, project) + log.debug("'apply' method invoked successfully") + } + + private fun loadPluginInIsolatedClassloader(projectVersion: String, sourceBuildScript: ScriptHandler): Class> { + val dependencyHandler: DependencyHandler = sourceBuildScript.getDependencies() + val configurationsContainer: ConfigurationContainer = sourceBuildScript.getConfigurations() + + log.debug("Creating configuration and dependency") + val kotlinPluginCoreCoordinates = "org.jetbrains.kotlin:kotlin-gradle-plugin-core:" + projectVersion + val dependency = dependencyHandler.create(kotlinPluginCoreCoordinates) + val configuration = configurationsContainer.detachedConfiguration(dependency) + + log.debug("Resolving [" + kotlinPluginCoreCoordinates + "]") + val kotlinPluginDependencies: List = configuration.getResolvedConfiguration().getFiles({ true })!!.map { it.toURI().toURL() } + log.debug("Resolved files: [" + kotlinPluginDependencies.toString() + "]") + log.debug("Load plugin in parent-last URL classloader") + val kotlinPluginClassloader = ParentLastURLClassLoader(kotlinPluginDependencies, this.javaClass.getClassLoader()) + log.debug("Class loader created") + val cls = Class.forName(getPluginClassName(), true, kotlinPluginClassloader) as Class> + log.debug("Plugin class loaded") + return cls + } + + private fun loadKotlinVersionFromResource(): String { log.debug("Loading version information") val props = Properties() val propFileName = "project.properties" @@ -39,29 +80,7 @@ abstract class KotlinBasePluginWrapper: Plugin { val projectVersion = props["project.version"] as String log.debug("Found project version [$projectVersion]") - project.getExtensions().getExtraProperties()?.set("kotlin.gradle.plugin.version", projectVersion) - - log.debug("Creating configuration and dependency") - val kotlinPluginCoreCoordinates = "org.jetbrains.kotlin:kotlin-gradle-plugin-core:" + projectVersion - val dependency = dependencyHandler.create(kotlinPluginCoreCoordinates) - val configuration = configurationsContainer.detachedConfiguration(dependency) - - log.debug("Resolving [" + kotlinPluginCoreCoordinates + "]") - val kotlinPluginDependencies : List = configuration.getResolvedConfiguration().getFiles({true})!!.map { it.toURI().toURL() } - log.debug("Resolved files: [" + kotlinPluginDependencies.toString() + "]") - log.debug("Load plugin in parent-last URL classloader") - val kotlinPluginClassloader = ParentLastURLClassLoader(kotlinPluginDependencies, this.javaClass.getClassLoader()) - log.debug("Class loader created") - val cls = Class.forName(getPluginClassName(), true, kotlinPluginClassloader) - log.debug("Plugin class loaded") - val constructor = cls.getConstructor(javaClass()) - val pluginInstance = constructor.newInstance(sourceBuildScript) - log.debug("Plugin class instantiated") - - val applyMethod = cls.getMethod("apply", javaClass()) - log.debug("'apply' method found, invoking...") - applyMethod.invoke(pluginInstance, project) - log.debug("'apply' method invoked successfully") + return projectVersion } public abstract fun getPluginClassName():String