diff --git a/dd-java-agent/instrumentation/jboss/jboss-modules-1.3/build.gradle b/dd-java-agent/instrumentation/jboss/jboss-modules-1.3/build.gradle index 8f45fb9e3e2..29cf37f8139 100644 --- a/dd-java-agent/instrumentation/jboss/jboss-modules-1.3/build.gradle +++ b/dd-java-agent/instrumentation/jboss/jboss-modules-1.3/build.gradle @@ -8,6 +8,16 @@ muzzle { apply from: "$rootDir/gradle/java.gradle" +addTestSuite("latestDepTest") + dependencies { compileOnly group: 'org.jboss.modules', name: 'jboss-modules', version: '1.3.0.Final' + testImplementation group: 'org.jboss.modules', name: 'jboss-modules', version: '1.3.0.Final' + latestDepTestImplementation group: 'org.jboss.modules', name: 'jboss-modules', version: '+' +} + +tasks.withType(Test).configureEach { + if (it.javaVersion.isJava9Compatible()) { + jvmArgs +='--add-exports=java.xml/com.sun.org.apache.xerces.internal.jaxp=ALL-UNNAMED' + } } diff --git a/dd-java-agent/instrumentation/jboss/jboss-modules-1.3/src/latestDepTest/groovy/ModuleNameExtractionTest.groovy b/dd-java-agent/instrumentation/jboss/jboss-modules-1.3/src/latestDepTest/groovy/ModuleNameExtractionTest.groovy new file mode 100644 index 00000000000..3517035e9de --- /dev/null +++ b/dd-java-agent/instrumentation/jboss/jboss-modules-1.3/src/latestDepTest/groovy/ModuleNameExtractionTest.groovy @@ -0,0 +1,21 @@ +import datadog.trace.agent.test.InstrumentationSpecification +import datadog.trace.instrumentation.jbossmodules.ModuleNameHelper +import org.jboss.modules.DependencySpec +import org.jboss.modules.Module +import org.jboss.modules.ModuleSpec + +class ModuleNameExtractionTest extends InstrumentationSpecification { + def "should be able to extract a module name"() { + given: + + ModuleSpec spec = ModuleSpec.build("dummy") + .addDependency(DependencySpec.createLocalDependencySpec()) + .create() + + Module module = new Module(spec, Module.getBootModuleLoader()) + + expect: + module != null + module.getName() == ModuleNameHelper.extractModuleName(module) + } +} diff --git a/dd-java-agent/instrumentation/jboss/jboss-modules-1.3/src/main/java/datadog/trace/instrumentation/jbossmodules/ModuleNameHelper.java b/dd-java-agent/instrumentation/jboss/jboss-modules-1.3/src/main/java/datadog/trace/instrumentation/jbossmodules/ModuleNameHelper.java index d99f2ded925..bc971a48767 100644 --- a/dd-java-agent/instrumentation/jboss/jboss-modules-1.3/src/main/java/datadog/trace/instrumentation/jbossmodules/ModuleNameHelper.java +++ b/dd-java-agent/instrumentation/jboss/jboss-modules-1.3/src/main/java/datadog/trace/instrumentation/jbossmodules/ModuleNameHelper.java @@ -1,19 +1,77 @@ package datadog.trace.instrumentation.jbossmodules; +import datadog.trace.util.MethodHandles; +import java.lang.invoke.MethodHandle; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.Nonnull; +import org.jboss.modules.Module; import org.jboss.modules.ModuleClassLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ModuleNameHelper { private ModuleNameHelper() {} + private static final Logger LOGGER = LoggerFactory.getLogger(ModuleNameHelper.class); + private static final MethodHandle MODULE_NAME_GETTER = resolveModuleNameGetter(); + + private static MethodHandle resolveModuleNameGetter() { + final ClassLoader classLoader = ModuleClassLoader.class.getClassLoader(); + final MethodHandles methodHandles = new MethodHandles(classLoader); + MethodHandle ret = null; + MethodHandle getModuleIdentifierHandle = null; + try { + // before 2.2 + getModuleIdentifierHandle = methodHandles.method(Module.class, "getIdentifier"); + if (getModuleIdentifierHandle != null) { + // chains the two method handle calls + ret = + java.lang.invoke.MethodHandles.filterReturnValue( + getModuleIdentifierHandle, + methodHandles.method( + Class.forName("org.jboss.modules.ModuleIdentifier", false, classLoader), + "getName")); + } + } catch (Throwable ignored) { + // here for caution. It's already caught and logged on MethodHandles + } + if (ret == null) { + // 2.2 onward + try { + ret = methodHandles.method(Module.class, "getName"); + } catch (Throwable ignored) { + } + } + if (ret == null) { + LOGGER.debug( + "Unable to resolve a method to establish jboss module name. If enabled, jee-split-by-deployment will not work properly"); + } + return ret; + } + private static final Pattern SUBDEPLOYMENT_MATCH = Pattern.compile("deployment(?>.+\\.ear)?\\.(.+)\\.[j|w]ar"); + static String extractModuleName(Module module) { + if (MODULE_NAME_GETTER == null) { + return null; + } + String moduleName = null; + try { + moduleName = (String) MODULE_NAME_GETTER.invoke(module); + } catch (Throwable ignored) { + } + return moduleName; + } + public static String extractDeploymentName(@Nonnull final ModuleClassLoader classLoader) { - final Matcher matcher = - SUBDEPLOYMENT_MATCH.matcher(classLoader.getModule().getIdentifier().getName()); + + final String moduleName = extractModuleName(classLoader.getModule()); + if (moduleName == null) { + return null; + } + final Matcher matcher = SUBDEPLOYMENT_MATCH.matcher(moduleName); if (matcher.matches()) { return matcher.group(1); } diff --git a/dd-java-agent/instrumentation/jboss/jboss-modules-1.3/src/test/groovy/ModuleNameExtractionTest.groovy b/dd-java-agent/instrumentation/jboss/jboss-modules-1.3/src/test/groovy/ModuleNameExtractionTest.groovy new file mode 100644 index 00000000000..7d38222f27f --- /dev/null +++ b/dd-java-agent/instrumentation/jboss/jboss-modules-1.3/src/test/groovy/ModuleNameExtractionTest.groovy @@ -0,0 +1,23 @@ +import datadog.trace.agent.test.InstrumentationSpecification +import datadog.trace.instrumentation.jbossmodules.ModuleNameHelper +import org.jboss.modules.DependencySpec +import org.jboss.modules.Module +import org.jboss.modules.ModuleIdentifier +import org.jboss.modules.ModuleSpec + +class ModuleNameExtractionTest extends InstrumentationSpecification { + def "should be able to extract a module name"() { + given: + ModuleIdentifier id = ModuleIdentifier.fromString("dummy") + + ModuleSpec spec = ModuleSpec.build(id) + .addDependency(DependencySpec.createLocalDependencySpec()) + .create() + + Module module = new Module(spec, Module.getBootModuleLoader()) + + expect: + module != null + module.getIdentifier().getName() == ModuleNameHelper.extractModuleName(module) + } +}