ByteBuddy tasks no longer resolve dependencies at config time.
MODIFY
buildSrc/src/main/java/io/opentelemetry/instrumentation/gradle/bytebuddy/ByteBuddyPluginConfigurator.java
buildSrc/src/main/java/io/opentelemetry/instrumentation/gradle/bytebuddy/ByteBuddyPluginConfigurator.java
package io.opentelemetry.instrumentation.gradle.bytebuddy;
import java.io.File;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import net.bytebuddy.build.gradle.ByteBuddySimpleTask;
-import net.bytebuddy.build.gradle.PluginArgument;
import net.bytebuddy.build.gradle.Transformation;
import org.gradle.api.Project;
import org.gradle.api.Task;
@@ -42,13 +39,10 @@ public class ByteBuddyPluginConfigurator {
private final Project project;
private final SourceSet sourceSet;
private final String pluginClassName;
- private final List<Iterable<File>> inputClasspath;
+ private final Iterable<File> inputClasspath;
public ByteBuddyPluginConfigurator(
- Project project,
- SourceSet sourceSet,
- String pluginClassName,
- List<Iterable<File>> inputClasspath) {
+ Project project, SourceSet sourceSet, String pluginClassName, Iterable<File> inputClasspath) {
this.project = project;
this.sourceSet = sourceSet;
this.pluginClassName = pluginClassName;
@@ -87,13 +81,9 @@ public class ByteBuddyPluginConfigurator {
task.setTarget(classesDirectory);
task.setClassPath(compileTask.getClasspath());
- List<Iterable<File>> classPath = new ArrayList<>();
- classPath.add(Collections.singletonList(rawClassesDirectory));
- classPath.addAll(inputClasspath);
-
task.dependsOn(compileTask);
- task.getTransformations().add(createTransformation(classPath, pluginClassName));
+ task.getTransformations().add(createTransformation(inputClasspath, pluginClassName));
return task;
}
@@ -120,19 +110,9 @@ public class ByteBuddyPluginConfigurator {
}
private static Transformation createTransformation(
- List<Iterable<File>> classPath, String pluginClassName) {
- Transformation transformation = new Transformation();
+ Iterable<File> classPath, String pluginClassName) {
+ Transformation transformation = new ClasspathTransformation(classPath, pluginClassName);
transformation.setPlugin(ClasspathByteBuddyPlugin.class);
- addArgument(transformation, classPath);
- addArgument(transformation, pluginClassName);
return transformation;
}
-
- private static void addArgument(Transformation transformation, Object value) {
- List<PluginArgument> arguments = transformation.getArguments();
- PluginArgument argument = new PluginArgument();
- argument.setIndex(arguments.size());
- argument.setValue(value);
- arguments.add(argument);
- }
}

MODIFY
buildSrc/src/main/java/io/opentelemetry/instrumentation/gradle/bytebuddy/ClasspathByteBuddyPlugin.java
buildSrc/src/main/java/io/opentelemetry/instrumentation/gradle/bytebuddy/ClasspathByteBuddyPlugin.java
@@ -28,8 +28,14 @@ import net.bytebuddy.dynamic.DynamicType;
public class ClasspathByteBuddyPlugin implements Plugin {
private final Plugin delegate;
- public ClasspathByteBuddyPlugin(List<Iterable<File>> classPath, String className) {
- this.delegate = pluginFromClassPath(classPath, className);
+ /**
+ * classPath and className argument resolvers are explicitly added by {@link
+ * ClasspathTransformation}, sourceDirectory is automatically resolved as by default any {@link
+ * File} argument is resolved to source directory.
+ */
+ public ClasspathByteBuddyPlugin(
+ Iterable<File> classPath, File sourceDirectory, String className) {
+ this.delegate = pluginFromClassPath(classPath, sourceDirectory, className);
}
@Override
@@ -51,9 +57,10 @@ public class ClasspathByteBuddyPlugin implements Plugin {
return delegate.matches(typeDefinitions);
}
- private static Plugin pluginFromClassPath(List<Iterable<File>> classPath, String className) {
+ private static Plugin pluginFromClassPath(
+ Iterable<File> classPath, File sourceDirectory, String className) {
try {
- ClassLoader classLoader = classLoaderFromClassPath(classPath);
+ ClassLoader classLoader = classLoaderFromClassPath(classPath, sourceDirectory);
Class<?> clazz = Class.forName(className, false, classLoader);
return (Plugin) clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
@@ -61,20 +68,23 @@ public class ClasspathByteBuddyPlugin implements Plugin {
}
}
- private static ClassLoader classLoaderFromClassPath(List<Iterable<File>> classPath) {
+ private static ClassLoader classLoaderFromClassPath(
+ Iterable<File> classPath, File sourceDirectory) {
List<URL> urls = new ArrayList<>();
+ urls.add(fileAsUrl(sourceDirectory));
+
+ for (File file : classPath) {
+ urls.add(fileAsUrl(file));
+ }
- for (Iterable<File> fileList : classPath) {
- for (File file : fileList) {
+ return new URLClassLoader(urls.toArray(new URL[0]), ByteBuddy.class.getClassLoader());
+ }
+
+ private static URL fileAsUrl(File file) {
try {
- URL url = file.toURI().toURL();
- urls.add(url);
+ return file.toURI().toURL();
} catch (MalformedURLException e) {
throw new RuntimeException("Cannot resolve " + file + " as URL", e);
}
}
}
-
- return new URLClassLoader(urls.toArray(new URL[0]), ByteBuddy.class.getClassLoader());
- }
-}

ADD
buildSrc/src/main/java/io/opentelemetry/instrumentation/gradle/bytebuddy/ClasspathTransformation.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.gradle.bytebuddy;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+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;
+
+/**
+ * Special implementation of {@link Transformation} is required as classpath argument must be
+ * exposed to Gradle via {@link Classpath} annotation, which cannot be done if it is returned by
+ * {@link Transformation#getArguments()}.
+ */
+public class ClasspathTransformation extends Transformation {
+ private final Iterable<File> classpath;
+ private final String pluginClassName;
+
+ public ClasspathTransformation(Iterable<File> classpath, String pluginClassName) {
+ this.classpath = classpath;
+ this.pluginClassName = pluginClassName;
+ }
+
+ @Classpath
+ public Iterable<? extends File> getClasspath() {
+ return classpath;
+ }
+
+ @Input
+ public String getPluginClassName() {
+ return pluginClassName;
+ }
+
+ protected List<ArgumentResolver> makeArgumentResolvers() {
+ return Arrays.asList(
+ new ArgumentResolver.ForIndex(0, classpath),
+ new ArgumentResolver.ForIndex(2, pluginClassName));
+ }
+}

MODIFY
gradle/instrumentation.gradle
gradle/instrumentation.gradle
@@ -51,9 +51,7 @@ afterEvaluate {
}
def pluginName = 'io.opentelemetry.javaagent.tooling.muzzle.collector.MuzzleCodeGenerationPlugin'
- new ByteBuddyPluginConfigurator(project, sourceSets.main, pluginName, [
- project(':javaagent-tooling').configurations.instrumentationMuzzle.files,
- configurations.runtimeClasspath.files,
- sourceSets.main.output.files
- ]).configure()
+ new ByteBuddyPluginConfigurator(project, sourceSets.main, pluginName,
+ project(':javaagent-tooling').configurations.instrumentationMuzzle + configurations.runtimeClasspath
+ ).configure()
}

ByteBuddy tasks no longer resolve dependencies at config time. (#1715)