Skip to content

Commit

Permalink
Migrate codegen to be a plugin (#3401)
Browse files Browse the repository at this point in the history
  • Loading branch information
Anuraag Agrawal authored Jun 24, 2021
1 parent 1f3faca commit 220ea41
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 287 deletions.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.gradle.codegen

import net.bytebuddy.ByteBuddy
import net.bytebuddy.build.Plugin
import net.bytebuddy.description.type.TypeDescription
import net.bytebuddy.dynamic.ClassFileLocator
import net.bytebuddy.dynamic.DynamicType
import java.io.File
import java.net.URL
import java.net.URLClassLoader

/**
* Starting from version 1.10.15, ByteBuddy gradle plugin transformations require that plugin
* classes are given as class instances instead of a class name string. To be able to still use a
* plugin implementation that is not a buildscript dependency, this reimplements the previous logic
* by taking a delegate class name and class path as arguments and loading the plugin class from the
* provided classloader when the plugin is instantiated.
*/
class ClasspathByteBuddyPlugin(
classPath: Iterable<File>, sourceDirectory: File, className: String
) : Plugin {
private val delegate = pluginFromClassPath(classPath, sourceDirectory, className)

override fun apply(
builder: DynamicType.Builder<*>,
typeDescription: TypeDescription,
classFileLocator: ClassFileLocator
): DynamicType.Builder<*> {
return delegate.apply(builder, typeDescription, classFileLocator)
}

override fun close() {
delegate.close()
}

override fun matches(typeDefinitions: TypeDescription): Boolean {
return delegate.matches(typeDefinitions)
}

companion object {
private fun pluginFromClassPath(
classPath: Iterable<File>, sourceDirectory: File, className: String
): Plugin {
val classLoader = classLoaderFromClassPath(classPath, sourceDirectory)
try {
val clazz = Class.forName(className, false, classLoader)
return clazz.getDeclaredConstructor().newInstance() as Plugin
} catch (e: Exception) {
throw IllegalStateException("Failed to create ByteBuddy plugin instance", e)
}
}

private fun classLoaderFromClassPath(
classPath: Iterable<File>, sourceDirectory: File
): ClassLoader {
val urls = mutableListOf<URL>()
urls.add(fileAsUrl(sourceDirectory))
for (file in classPath) {
urls.add(fileAsUrl(file))
}
return URLClassLoader(urls.toTypedArray(), ByteBuddy::class.java.classLoader)
}

private fun fileAsUrl(file: File): URL {
return file.toURI().toURL()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.gradle.codegen

import net.bytebuddy.build.Plugin.Factory.UsingReflection.ArgumentResolver
import net.bytebuddy.build.gradle.Transformation
import org.gradle.api.tasks.Classpath
import org.gradle.api.tasks.Input
import java.io.File

/**
* Special implementation of [Transformation] is required as classpath argument must be
* exposed to Gradle via [Classpath] annotation, which cannot be done if it is returned by
* [Transformation.getArguments].
*/
class ClasspathTransformation(
@get:Classpath val classpath: Iterable<File>,
@get:Input val pluginClassName: String
) : Transformation() {
override fun makeArgumentResolvers(): List<ArgumentResolver> {
return listOf(
ArgumentResolver.ForIndex(0, classpath),
ArgumentResolver.ForIndex(2, pluginClassName)
)
}
}
Loading

0 comments on commit 220ea41

Please sign in to comment.