/* * Copyright The OpenTelemetry Authors * SPDX-License-Identifier: Apache-2.0 */ package io.opentelemetry.javaagent.muzzle.matcher /** * Entry point for the muzzle gradle plugin. * *
In order to understand this class and its weirdness, one has to remember that there are three * different independent class loaders at play here. * *
First, Gradle class loader that has loaded the muzzle-check plugin that calls this class. This * one has a lot of Gradle specific stuff and we don't want it to be available during muzzle checks. * *
Second, there is agent or instrumentation class loader, which contains all * InstrumentationModules and helper classes. The actual muzzle check process happens "inside" that * class loader. This means that we load {@code * io.opentelemetry.javaagent.tooling.muzzle.ClassLoaderMatcher} from it and we allow it to find all * InstrumentationModules from agent class loader. * *
Finally, there is user class loader. It contains the specific version of the instrumented * library that we want to muzzle-check: "does this version provide all the expected hooks and * classes and methods that our instrumentations expect". */ // TODO the next line is not true anymore. Switch from System.err to Gradle logger. // Runs in special classloader so tedious to provide access to the Gradle logger. class MuzzleGradlePluginUtil { companion object { /** * Verifies that all instrumentations present in the {@code agentClassLoader} can be safely * applied to the passed {@code userClassLoader}. * *
This method throws whenever one of the following step fails (and {@code assertPass} is * true): * *
When {@code assertPass = false} this method behaves in an opposite way: failure in any of * the first two steps is expected (helper classes are not injected at all). * *
This method is repeatedly called by the {@code :muzzle} gradle task - each tested dependency
* version passes different {@code userClassLoader}.
*/
@Suppress("UNCHECKED_CAST")
fun assertInstrumentationMuzzled(agentClassLoader: ClassLoader, userClassLoader: ClassLoader, assertPass: Boolean) {
val matcherClass = agentClassLoader.loadClass("io.opentelemetry.javaagent.tooling.muzzle.ClassLoaderMatcher")
// We cannot reference Mismatch class directly here, because we are loaded from a differen
// classloader.
// We cannot reference Mismatch class directly here, because we are loaded from a differen
// classloader.
val allMismatches = matcherClass
.getMethod("matchesAll", ClassLoader::class.java, Boolean::class.javaPrimitiveType)
.invoke(null, userClassLoader, assertPass)
as Map Called by the {@code printMuzzleReferences} gradle task.
*/
fun printMuzzleReferences(instrumentationClassLoader: ClassLoader) {
val matcherClass = instrumentationClassLoader.loadClass(
"io.opentelemetry.javaagent.tooling.muzzle.ReferencesPrinter")
matcherClass.getMethod("printMuzzleReferences").invoke(null)
}
}
}