From 831ab8f805302e3ed92860fb7e6c87423e367a6d Mon Sep 17 00:00:00 2001 From: eyalkoren <41850454+eyalkoren@users.noreply.github.com> Date: Tue, 23 Apr 2019 11:50:56 +0300 Subject: [PATCH] Fix Manifest version reading error to support jar:file protocol (#601) --- .../bci/bytebuddy/CustomElementMatchers.java | 23 ++++++++++++++++--- .../bytebuddy/CustomElementMatchersTest.java | 18 +++++++++++++-- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/apm-agent-core/src/main/java/co/elastic/apm/agent/bci/bytebuddy/CustomElementMatchers.java b/apm-agent-core/src/main/java/co/elastic/apm/agent/bci/bytebuddy/CustomElementMatchers.java index 2d0c9da86d..ac20887f8c 100644 --- a/apm-agent-core/src/main/java/co/elastic/apm/agent/bci/bytebuddy/CustomElementMatchers.java +++ b/apm-agent-core/src/main/java/co/elastic/apm/agent/bci/bytebuddy/CustomElementMatchers.java @@ -23,13 +23,15 @@ import com.blogspot.mydailyjava.weaklockfree.WeakConcurrentMap; import net.bytebuddy.description.NamedElement; import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.dynamic.ClassFileLocator; import net.bytebuddy.matcher.ElementMatcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nullable; +import java.io.IOException; +import java.net.JarURLConnection; import java.net.URL; +import java.net.URLConnection; import java.security.CodeSource; import java.security.ProtectionDomain; import java.util.Collection; @@ -135,14 +137,21 @@ public boolean matches(@Nullable ProtectionDomain protectionDomain) { private static @Nullable Version readImplementationVersionFromManifest(@Nullable ProtectionDomain protectionDomain) { Version version = null; + JarFile jarFile = null; try { if (protectionDomain != null) { CodeSource codeSource = protectionDomain.getCodeSource(); if (codeSource != null) { URL jarUrl = codeSource.getLocation(); if (jarUrl != null) { - JarFile jar = new JarFile(jarUrl.getFile()); - Manifest manifest = jar.getManifest(); + // does not yet establish an actual connection + URLConnection urlConnection = jarUrl.openConnection(); + if (urlConnection instanceof JarURLConnection) { + jarFile = ((JarURLConnection) urlConnection).getJarFile(); + } else { + jarFile = new JarFile(jarUrl.getFile()); + } + Manifest manifest = jarFile.getManifest(); if (manifest != null) { String implementationVersion = manifest.getMainAttributes().getValue("Implementation-Version"); if (implementationVersion != null) { @@ -156,6 +165,14 @@ public boolean matches(@Nullable ProtectionDomain protectionDomain) { } } catch (Exception e) { logger.error("Cannot read implementation version based on ProtectionDomain " + protectionDomain, e); + } finally { + if (jarFile != null) { + try { + jarFile.close(); + } catch (IOException e) { + logger.error("Error closing JarFile", e); + } + } } return version; } diff --git a/apm-agent-core/src/test/java/co/elastic/apm/agent/bci/bytebuddy/CustomElementMatchersTest.java b/apm-agent-core/src/test/java/co/elastic/apm/agent/bci/bytebuddy/CustomElementMatchersTest.java index 7c4b337a91..1d979358a9 100644 --- a/apm-agent-core/src/test/java/co/elastic/apm/agent/bci/bytebuddy/CustomElementMatchersTest.java +++ b/apm-agent-core/src/test/java/co/elastic/apm/agent/bci/bytebuddy/CustomElementMatchersTest.java @@ -23,6 +23,10 @@ import org.apache.http.client.HttpClient; import org.junit.jupiter.api.Test; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.CodeSigner; +import java.security.CodeSource; import java.security.ProtectionDomain; import java.util.List; @@ -50,9 +54,19 @@ void testClassLoaderCanLoadClass() { } @Test - void testSemVerLteMatcher() { + void testSemVerLteWithFileUrl() { // Relying on Apache httpclient-4.5.6.jar - ProtectionDomain protectionDomain = HttpClient.class.getProtectionDomain(); + testSemVerLteMatcher(HttpClient.class.getProtectionDomain()); + } + + @Test + void testSemVerLteWithJarFileUrl() throws MalformedURLException { + URL originalUrl = HttpClient.class.getProtectionDomain().getCodeSource().getLocation(); + URL jarFileUrl = new URL("jar:" + originalUrl.toString() + "!/"); + testSemVerLteMatcher(new ProtectionDomain(new CodeSource(jarFileUrl, new CodeSigner[0]), null)); + } + + private void testSemVerLteMatcher(ProtectionDomain protectionDomain) { assertThat(implementationVersionLte("3").matches(protectionDomain)).isFalse(); assertThat(implementationVersionLte("3.2").matches(protectionDomain)).isFalse(); assertThat(implementationVersionLte("3.15.10").matches(protectionDomain)).isFalse();