Fix Restlet v2 `Message#getAttributes` calls
Fixes
MODIFY
gradle-plugins/src/main/kotlin/io.opentelemetry.instrumentation.muzzle-check.gradle.kts
gradle-plugins/src/main/kotlin/io.opentelemetry.instrumentation.muzzle-check.gradle.kts
@@ -132,26 +132,6 @@ tasks.register("printMuzzleReferences") {
}
}
-val projectRepositories = mutableListOf<RemoteRepository>().apply {
- // Manually add mavenCentral until https://github.com/gradle/gradle/issues/17295
- // Adding mavenLocal is much more complicated but hopefully isn't required for normal usage of
- // Muzzle.
- add(
- RemoteRepository.Builder(
- "MavenCentral", "default", "https://repo.maven.apache.org/maven2/")
- .build())
- for (repository in repositories) {
- if (repository is MavenArtifactRepository) {
- add(
- RemoteRepository.Builder(
- repository.getName(),
- "default",
- repository.url.toString())
- .build())
- }
- }
-}.toList()
-
val hasRelevantTask = gradle.startParameter.taskNames.any {
// removing leading ':' if present
val taskName = it.removePrefix(":")
@@ -167,18 +147,21 @@ if (hasRelevantTask) {
afterEvaluate {
var runAfter = muzzle
+ // the project repositories need to be retrieved after evaluation, before that the list is just empty
+ val projectRepositories = getProjectRepositories(project)
+
for (muzzleDirective in muzzleConfig.directives.get()) {
- logger.info("configured ${muzzleDirective}")
+ logger.info("configured $muzzleDirective")
if (muzzleDirective.coreJdk.get()) {
runAfter = addMuzzleTask(muzzleDirective, null, runAfter)
} else {
- for (singleVersion in muzzleDirectiveToArtifacts(muzzleDirective, system, session)) {
+ for (singleVersion in muzzleDirectiveToArtifacts(muzzleDirective, system, session, projectRepositories)) {
runAfter = addMuzzleTask(muzzleDirective, singleVersion, runAfter)
}
if (muzzleDirective.assertInverse.get()) {
- for (inverseDirective in inverseOf(muzzleDirective, system, session)) {
- for (singleVersion in muzzleDirectiveToArtifacts(inverseDirective, system, session)) {
+ for (inverseDirective in inverseOf(muzzleDirective, system, session, projectRepositories)) {
+ for (singleVersion in muzzleDirectiveToArtifacts(inverseDirective, system, session, projectRepositories)) {
runAfter = addMuzzleTask(inverseDirective, singleVersion, runAfter)
}
}
@@ -188,6 +171,18 @@ if (hasRelevantTask) {
}
}
+fun getProjectRepositories(project: Project): List<RemoteRepository> {
+ return project.repositories
+ .filterIsInstance<MavenArtifactRepository>()
+ .map {
+ RemoteRepository.Builder(
+ it.name,
+ "default",
+ it.url.toString())
+ .build()
+ }
+}
+
fun createInstrumentationClassloader(): ClassLoader {
logger.info("Creating instrumentation class loader for: $path")
val muzzleShadowJar = shadowModule.get().archiveFile.get()
@@ -309,7 +304,7 @@ fun createClassLoaderForTask(muzzleTaskConfiguration: Configuration): ClassLoade
return classpathLoader(muzzleTaskConfiguration + files(muzzleBootstrapShadowJar), ClassLoader.getPlatformClassLoader())
}
-fun inverseOf(muzzleDirective: MuzzleDirective, system: RepositorySystem, session: RepositorySystemSession): Set<MuzzleDirective> {
+fun inverseOf(muzzleDirective: MuzzleDirective, system: RepositorySystem, session: RepositorySystemSession, repos: List<RemoteRepository>): Set<MuzzleDirective> {
val inverseDirectives = mutableSetOf<MuzzleDirective>()
val allVersionsArtifact = DefaultArtifact(
@@ -325,7 +320,6 @@ fun inverseOf(muzzleDirective: MuzzleDirective, system: RepositorySystem, sessio
"jar",
muzzleDirective.versions.get())
- val repos = projectRepositories
val allRangeRequest = VersionRangeRequest().apply {
repositories = repos
artifact = allVersionsArtifact
@@ -374,7 +368,7 @@ fun filterVersions(range: VersionRangeResult, skipVersions: Set<String>) = seque
}
}.distinct().take(RANGE_COUNT_LIMIT)
-fun muzzleDirectiveToArtifacts(muzzleDirective: MuzzleDirective, system: RepositorySystem, session: RepositorySystemSession) = sequence<Artifact> {
+fun muzzleDirectiveToArtifacts(muzzleDirective: MuzzleDirective, system: RepositorySystem, session: RepositorySystemSession, repos: List<RemoteRepository>) = sequence<Artifact> {
val directiveArtifact: Artifact = DefaultArtifact(
muzzleDirective.group.get(),
muzzleDirective.module.get(),
@@ -383,7 +377,7 @@ fun muzzleDirectiveToArtifacts(muzzleDirective: MuzzleDirective, system: Reposit
muzzleDirective.versions.get())
val rangeRequest = VersionRangeRequest().apply {
- repositories = projectRepositories
+ repositories = repos
artifact = directiveArtifact
}
val rangeResult = system.resolveVersionRange(session, rangeRequest)

MODIFY
instrumentation/restlet/restlet-1.0/javaagent/build.gradle.kts
instrumentation/restlet/restlet-1.0/javaagent/build.gradle.kts
@@ -6,7 +6,9 @@ muzzle {
pass {
group.set("org.restlet")
module.set("org.restlet")
- versions.set("[1.0.0, 1.2-M1)")
+ // TODO: rename this module to restlet-1.1
+ versions.set("[1.1.0, 1.2-M1)")
+ extraDependency("com.noelios.restlet:com.noelios.restlet")
assertInverse.set(true)
}
}

MODIFY
instrumentation/restlet/restlet-2.0/javaagent/build.gradle.kts
instrumentation/restlet/restlet-2.0/javaagent/build.gradle.kts
@@ -4,8 +4,8 @@ plugins {
muzzle {
pass {
- group.set("org.restlet")
- module.set("org.restlet.jse")
+ group.set("org.restlet.jse")
+ module.set("org.restlet")
versions.set("[2.0.0,)")
assertInverse.set(true)
}

MODIFY
instrumentation/restlet/restlet-2.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v2_0/internal/RestletHeadersGetter.java
instrumentation/restlet/restlet-2.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v2_0/internal/RestletHeadersGetter.java
package io.opentelemetry.instrumentation.restlet.v2_0.internal;
+import static java.util.Collections.emptySet;
+
import io.opentelemetry.context.propagation.TextMapGetter;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+import javax.annotation.Nullable;
import org.restlet.Message;
import org.restlet.Request;
import org.restlet.util.Series;
final class RestletHeadersGetter implements TextMapGetter<Request> {
+ private static final MethodHandle GET_ATTRIBUTES;
+
+ static {
+ MethodHandle getAttributes = null;
+
+ MethodHandles.Lookup lookup = MethodHandles.lookup();
+ try {
+ getAttributes =
+ lookup.findVirtual(Message.class, "getAttributes", MethodType.methodType(Map.class));
+ } catch (NoSuchMethodException | IllegalAccessException e) {
+ // changed the return type to ConcurrentMap in version 2.1
+ try {
+ getAttributes =
+ lookup.findVirtual(
+ Message.class, "getAttributes", MethodType.methodType(ConcurrentMap.class));
+ } catch (NoSuchMethodException | IllegalAccessException ex) {
+ // ignored
+ }
+ }
+
+ GET_ATTRIBUTES = getAttributes;
+ }
+
@Override
public Iterable<String> keys(Request carrier) {
- return getHeaders(carrier).getNames();
+ Series<?> headers = getHeaders(carrier);
+ return headers == null ? emptySet() : headers.getNames();
}
@Override
public String get(Request carrier, String key) {
Series<?> headers = getHeaders(carrier);
- return headers.getFirstValue(key, /* ignoreCase = */ true);
+ return headers == null ? null : headers.getFirstValue(key, /* ignoreCase = */ true);
}
+ @SuppressWarnings("unchecked")
+ @Nullable
static Series<?> getHeaders(Message carrier) {
- return (Series<?>) carrier.getAttributes().get("org.restlet.http.headers");
+ if (GET_ATTRIBUTES == null) {
+ return null;
+ }
+ try {
+ Map<String, Object> attributes = (Map<String, Object>) GET_ATTRIBUTES.invoke(carrier);
+ return (Series<?>) attributes.get("org.restlet.http.headers");
+ } catch (Throwable e) {
+ return null;
+ }
}
}

Fix Restlet v2 `Message#getAttributes` calls (#6796)

Fixes #6563