diff options
author | Simon Ogorodnik <sem-oro@yandex.ru> | 2016-12-06 16:24:43 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-06 16:24:43 +0300 |
commit | 2d03ad01f650bc997dce076abaab0a61c2301a96 (patch) | |
tree | 957dbe5280cf1114cfecfca35d18b264be195255 /runners/gradle-plugin/src | |
parent | 5d030c6303270d8955b71c6738afd9c80d73662f (diff) | |
parent | 546e8edfd95c16665319bc371c6ccf63706ad1e4 (diff) | |
download | dokka-2d03ad01f650bc997dce076abaab0a61c2301a96.tar.gz dokka-2d03ad01f650bc997dce076abaab0a61c2301a96.tar.bz2 dokka-2d03ad01f650bc997dce076abaab0a61c2301a96.zip |
Merge pull request #123 from Kotlin/isolated-classloader
Now dokka-fatjar complete isolated from poisonous Gradle environment
Diffstat (limited to 'runners/gradle-plugin/src')
4 files changed, 117 insertions, 29 deletions
diff --git a/runners/gradle-plugin/src/main/kotlin/ProxyUtils.kt b/runners/gradle-plugin/src/main/kotlin/ProxyUtils.kt new file mode 100644 index 00000000..7bdf2f9d --- /dev/null +++ b/runners/gradle-plugin/src/main/kotlin/ProxyUtils.kt @@ -0,0 +1,46 @@ +package org.jetbrains.dokka + +import java.lang.reflect.InvocationHandler +import java.lang.reflect.InvocationTargetException +import java.lang.reflect.Method +import java.lang.reflect.Proxy + + +/** + * Warning! Hard reflection magic used here. + * + * Creates [java.lang.reflect.Proxy] with pass through invocation algorithm, + * to create access proxy for [delegate] into [targetClassLoader]. + */ +@Suppress("UNCHECKED_CAST") +inline fun <reified T : Any> automagicTypedProxy(targetClassLoader: ClassLoader, delegate: Any): T = + automagicProxy(targetClassLoader, T::class.java, delegate) as T + + +/** + * Warning! Hard reflection magic used here. + * + * Creates [java.lang.reflect.Proxy] with pass through invocation algorithm, + * to create access proxy for [delegate] into [targetClassLoader]. + * + */ +fun automagicProxy(targetClassLoader: ClassLoader, targetType: Class<*>, delegate: Any): Any = + Proxy.newProxyInstance( + targetClassLoader, + arrayOf(targetType), + DelegatedInvocationHandler(delegate) + ) + +class DelegatedInvocationHandler(private val delegate: Any) : InvocationHandler { + + @Throws(Throwable::class) + override fun invoke(proxy: Any, method: Method, args: Array<Any?>?): Any? { + val delegateMethod = delegate.javaClass.getMethod(method.name, *method.parameterTypes) + try { + delegateMethod.isAccessible = true + return delegateMethod.invoke(delegate, *(args ?: emptyArray())) + } catch (ex: InvocationTargetException) { + throw ex.targetException + } + } +} diff --git a/runners/gradle-plugin/src/main/kotlin/logger.kt b/runners/gradle-plugin/src/main/kotlin/logger.kt deleted file mode 100644 index 715c1f04..00000000 --- a/runners/gradle-plugin/src/main/kotlin/logger.kt +++ /dev/null @@ -1,18 +0,0 @@ -package org.jetbrains.dokka.gradle - -import org.gradle.api.logging.Logger -import org.jetbrains.dokka.DokkaLogger - -class DokkaGradleLogger(val logger: Logger) : DokkaLogger { - override fun error(message: String) { - logger.error(message) - } - - override fun info(message: String) { - logger.info(message) - } - - override fun warn(message: String) { - logger.warn(message) - } -}
\ No newline at end of file diff --git a/runners/gradle-plugin/src/main/kotlin/main.kt b/runners/gradle-plugin/src/main/kotlin/main.kt index 49c3b8ba..51061415 100644 --- a/runners/gradle-plugin/src/main/kotlin/main.kt +++ b/runners/gradle-plugin/src/main/kotlin/main.kt @@ -8,15 +8,24 @@ import org.gradle.api.file.FileCollection import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.plugins.JavaPluginConvention import org.gradle.api.tasks.* -import org.jetbrains.dokka.DocumentationOptions -import org.jetbrains.dokka.DokkaGenerator -import org.jetbrains.dokka.SourceLinkDefinition +import org.jetbrains.dokka.DokkaBootstrap +import org.jetbrains.dokka.automagicTypedProxy +import org.jetbrains.dokka.gradle.ClassloaderContainer.fatJarClassLoader import java.io.File import java.io.Serializable +import java.net.URLClassLoader import java.util.* +import java.util.function.BiConsumer open class DokkaPlugin : Plugin<Project> { + + val properties = Properties() + + init { + properties.load(javaClass.getResourceAsStream("/META-INF/gradle-plugins/org.jetbrains.dokka.properties")) + } override fun apply(project: Project) { + version = properties.getProperty("dokka-version") project.tasks.create("dokka", DokkaTask::class.java).apply { moduleName = project.name outputDirectory = File(project.buildDir, "dokka").absolutePath @@ -24,6 +33,13 @@ open class DokkaPlugin : Plugin<Project> { } } +var version: String? = null + +object ClassloaderContainer { + @JvmField + var fatJarClassLoader: ClassLoader? = null +} + open class DokkaTask : DefaultTask() { init { group = JavaBasePlugin.DOCUMENTATION_GROUP @@ -47,6 +63,8 @@ open class DokkaTask : DefaultTask() { var jdkVersion: Int = 6 @Input var sourceDirs: Iterable<File> = emptyList() + @Input + var dokkaFatJar: Any = "org.jetbrains.dokka:dokka-fatjar:$version" protected open val sdkProvider: SdkProvider? = null @@ -65,8 +83,27 @@ open class DokkaTask : DefaultTask() { linkMappings.add(mapping) } + + fun loadFatJar() { + if (fatJarClassLoader == null) { + val fatjar = if (dokkaFatJar is File) + dokkaFatJar as File + else { + val dependency = project.buildscript.dependencies.create(dokkaFatJar) + val configuration = project.buildscript.configurations.detachedConfiguration(dependency) + configuration.description = "Dokka main jar" + configuration.resolve().first() + } + + fatJarClassLoader = URLClassLoader(arrayOf(fatjar.toURI().toURL())) + } + } + + @TaskAction fun generate() { + loadFatJar() + val project = project val sdkProvider = sdkProvider val sourceDirectories = getSourceDirectories() @@ -83,17 +120,39 @@ open class DokkaTask : DefaultTask() { return } - DokkaGenerator( - DokkaGradleLogger(logger), + val bootstrapClass = fatJarClassLoader!!.loadClass("org.jetbrains.dokka.DokkaBootstrapImpl") + + val bootstrapInstance = bootstrapClass.constructors.first().newInstance() + + val bootstrapProxy: DokkaBootstrap = automagicTypedProxy(javaClass.classLoader, bootstrapInstance) + + bootstrapProxy.configure( + BiConsumer { level, message -> + when (level) { + "info" -> logger.info(message) + "warn" -> logger.warn(message) + "error" -> logger.error(message) + } + }, + moduleName, classpath.map { it.absolutePath }, sourceDirectories.map { it.absolutePath }, samples.filterNotNull().map { project.file(it).absolutePath }, includes.filterNotNull().map { project.file(it).absolutePath }, - moduleName, - DocumentationOptions(outputDirectory, outputFormat, - sourceLinks = linkMappings.map { SourceLinkDefinition(project.file(it.dir).absolutePath, it.url, it.suffix) }, - jdkVersion = jdkVersion) - ).generate() + outputDirectory, + outputFormat, + false, + false, + false, + false, + 6, + true, + linkMappings.map { + val path = project.file(it.dir).absolutePath + "$path=${it.url}${it.suffix}" + }) + + bootstrapProxy.generate() } fun getSourceDirectories(): Collection<File> { diff --git a/runners/gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka.properties b/runners/gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka.properties index b42cfe9f..068bd352 100644 --- a/runners/gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka.properties +++ b/runners/gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka.properties @@ -1 +1,2 @@ -implementation-class=org.jetbrains.dokka.gradle.DokkaPlugin
\ No newline at end of file +implementation-class=org.jetbrains.dokka.gradle.DokkaPlugin +dokka-version=<version>
\ No newline at end of file |