From 9fbdace920c10fa1e0d4488e3bde44dc25905c19 Mon Sep 17 00:00:00 2001 From: Mateusz Rzeszutek Date: Wed, 5 Oct 2022 22:29:05 +0200 Subject: [PATCH] Fix Restlet v2 `Message#getAttributes` calls (#6796) Fixes #6563 --- ...ry.instrumentation.muzzle-check.gradle.kts | 50 ++++++++----------- .../restlet-1.0/javaagent/build.gradle.kts | 4 +- .../restlet-2.0/javaagent/build.gradle.kts | 4 +- .../v2_0/internal/RestletHeadersGetter.java | 48 ++++++++++++++++-- 4 files changed, 72 insertions(+), 34 deletions(-) diff --git a/gradle-plugins/src/main/kotlin/io.opentelemetry.instrumentation.muzzle-check.gradle.kts b/gradle-plugins/src/main/kotlin/io.opentelemetry.instrumentation.muzzle-check.gradle.kts index 1e4e46113b36..71b6f48dca04 100644 --- a/gradle-plugins/src/main/kotlin/io.opentelemetry.instrumentation.muzzle-check.gradle.kts +++ b/gradle-plugins/src/main/kotlin/io.opentelemetry.instrumentation.muzzle-check.gradle.kts @@ -132,26 +132,6 @@ tasks.register("printMuzzleReferences") { } } -val projectRepositories = mutableListOf().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 { + return project.repositories + .filterIsInstance() + .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 { +fun inverseOf(muzzleDirective: MuzzleDirective, system: RepositorySystem, session: RepositorySystemSession, repos: List): Set { val inverseDirectives = mutableSetOf() 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) = seque } }.distinct().take(RANGE_COUNT_LIMIT) -fun muzzleDirectiveToArtifacts(muzzleDirective: MuzzleDirective, system: RepositorySystem, session: RepositorySystemSession) = sequence { +fun muzzleDirectiveToArtifacts(muzzleDirective: MuzzleDirective, system: RepositorySystem, session: RepositorySystemSession, repos: List) = sequence { 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) diff --git a/instrumentation/restlet/restlet-1.0/javaagent/build.gradle.kts b/instrumentation/restlet/restlet-1.0/javaagent/build.gradle.kts index 4877ec3fb758..f24a086eae09 100644 --- a/instrumentation/restlet/restlet-1.0/javaagent/build.gradle.kts +++ b/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) } } diff --git a/instrumentation/restlet/restlet-2.0/javaagent/build.gradle.kts b/instrumentation/restlet/restlet-2.0/javaagent/build.gradle.kts index 410d3b8a4042..c88a2e6cad51 100644 --- a/instrumentation/restlet/restlet-2.0/javaagent/build.gradle.kts +++ b/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) } diff --git a/instrumentation/restlet/restlet-2.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v2_0/internal/RestletHeadersGetter.java b/instrumentation/restlet/restlet-2.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v2_0/internal/RestletHeadersGetter.java index 8000838585c3..e4f91c64d185 100644 --- a/instrumentation/restlet/restlet-2.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v2_0/internal/RestletHeadersGetter.java +++ b/instrumentation/restlet/restlet-2.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v2_0/internal/RestletHeadersGetter.java @@ -5,25 +5,67 @@ 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 { + 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 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 attributes = (Map) GET_ATTRIBUTES.invoke(carrier); + return (Series) attributes.get("org.restlet.http.headers"); + } catch (Throwable e) { + return null; + } } }