11package datadog .trace .instrumentation .gradle ;
22
3+ import java .lang .reflect .Method ;
4+ import java .lang .reflect .Proxy ;
5+ import java .util .Arrays ;
6+ import org .gradle .api .logging .Logger ;
7+ import org .gradle .api .logging .Logging ;
38import org .gradle .initialization .ClassLoaderRegistry ;
9+ import org .gradle .internal .service .DefaultServiceRegistry ;
10+ import org .gradle .internal .service .ServiceRegistration ;
411import org .gradle .internal .service .ServiceRegistry ;
5- import org .gradle .internal .service .scopes .BuildScopeServices ;
612
713public class CiVisibilityGradleListenerInjector {
814
9- public static void inject (ServiceRegistry parentServices , BuildScopeServices buildScopeServices ) {
10- ClassLoaderRegistry classLoaderRegistry = parentServices .get (ClassLoaderRegistry .class );
11- Class <?> ciVisibilityGradleListener = loadCiVisibilityGradleListener (classLoaderRegistry );
12- buildScopeServices .register (
13- serviceRegistration -> serviceRegistration .add (ciVisibilityGradleListener ));
15+ private static final Logger LOGGER = Logging .getLogger (CiVisibilityGradleListenerInjector .class );
16+
17+ public static ClassLoaderRegistry getClassLoaderRegistry (ServiceRegistry [] serviceRegistries ) {
18+ for (ServiceRegistry serviceRegistry : serviceRegistries ) {
19+ ClassLoaderRegistry classLoaderRegistry =
20+ (ClassLoaderRegistry ) serviceRegistry .find (ClassLoaderRegistry .class );
21+ if (classLoaderRegistry != null ) {
22+ return classLoaderRegistry ;
23+ }
24+ }
25+ throw new RuntimeException (
26+ "Could not find ClassLoaderRegistry service in " + Arrays .toString (serviceRegistries ));
1427 }
1528
1629 /**
@@ -22,7 +35,7 @@ public static void inject(ServiceRegistry parentServices, BuildScopeServices bui
2235 * org.gradle.api.tasks.testing.Test} task), which is a plugin. Therefore, we cannot reference its
2336 * {@code Class} instance directly, and instead have to load it explicitly.
2437 */
25- private static Class <?> loadCiVisibilityGradleListener (ClassLoaderRegistry classLoaderRegistry ) {
38+ public static Class <?> loadCiVisibilityGradleListener (ClassLoaderRegistry classLoaderRegistry ) {
2639 try {
2740 return classLoaderRegistry
2841 .getPluginsClassLoader ()
@@ -31,4 +44,57 @@ private static Class<?> loadCiVisibilityGradleListener(ClassLoaderRegistry class
3144 throw new RuntimeException ("Could not load CI Visibility Gradle Listener" , e );
3245 }
3346 }
47+
48+ /**
49+ * Performs listener injection for Gradle v8.10+. As the tracer currently uses v8.4, some of the
50+ * required interfaces are not available at compile time, which is why reflection is used.
51+ */
52+ // TODO: once the tracer is bumped to use Gradle v8.10 replace reflection with regular invocations
53+ public static void injectCiVisibilityGradleListener (
54+ DefaultServiceRegistry buildScopeServices , ServiceRegistry ... parentServices ) {
55+ try {
56+ ClassLoaderRegistry classLoaderRegistry = getClassLoaderRegistry (parentServices );
57+ ClassLoader coreApiClassLoader = classLoaderRegistry .getGradleCoreApiClassLoader ();
58+ Class <?> serviceRegistrationActionClass =
59+ coreApiClassLoader .loadClass ("org.gradle.internal.service.ServiceRegistrationAction" );
60+
61+ Object serviceRegistrationAction =
62+ Proxy .newProxyInstance (
63+ coreApiClassLoader ,
64+ new Class <?>[] {serviceRegistrationActionClass },
65+ (proxy , method , args ) -> {
66+ if (method .getName ().equals ("registerServices" )) {
67+ ServiceRegistration serviceRegistration = (ServiceRegistration ) args [0 ];
68+ Class <?> ciVisibilityGradleListener =
69+ CiVisibilityGradleListenerInjector .loadCiVisibilityGradleListener (
70+ classLoaderRegistry );
71+ serviceRegistration .add (ciVisibilityGradleListener );
72+ return null ;
73+ }
74+ throw new UnsupportedOperationException ("Method not implemented" );
75+ });
76+
77+ Method register =
78+ DefaultServiceRegistry .class .getMethod ("register" , serviceRegistrationActionClass );
79+ register .invoke (buildScopeServices , serviceRegistrationAction );
80+
81+ } catch (Exception e ) {
82+ LOGGER .warn ("Could not inject CI Visibility Gradle listener" , e );
83+ }
84+ }
85+
86+ /** Performs listener injection for Gradle v8.3 - 8.9 */
87+ public static void injectCiVisibilityGradleListenerLegacy (
88+ DefaultServiceRegistry buildScopeServices , ServiceRegistry ... parentServices ) {
89+ try {
90+ ClassLoaderRegistry classLoaderRegistry =
91+ CiVisibilityGradleListenerInjector .getClassLoaderRegistry (parentServices );
92+ Class <?> ciVisibilityGradleListener =
93+ CiVisibilityGradleListenerInjector .loadCiVisibilityGradleListener (classLoaderRegistry );
94+ buildScopeServices .register (
95+ serviceRegistration -> serviceRegistration .add (ciVisibilityGradleListener ));
96+ } catch (Exception e ) {
97+ LOGGER .warn ("Could not inject CI Visibility Gradle listener" , e );
98+ }
99+ }
34100}
0 commit comments