Fix method iterable logic.  methodPath, httpMethod working
MODIFY
dd-java-agent/instrumentation/jax-rs-annotations-1/src/main/java/datadog/trace/instrumentation/jaxrs1/JaxRsAnnotationsDecorator.java
dd-java-agent/instrumentation/jax-rs-annotations-1/src/main/java/datadog/trace/instrumentation/jaxrs1/JaxRsAnnotationsDecorator.java
@@ -86,13 +86,13 @@ public class JaxRsAnnotationsDecorator extends BaseDecorator {
final Path classPath = findClassPath(target);
for (final Method current : new OverriddenMethodIterable(target, method)) {
if (httpMethod == null) {
- httpMethod = locateHttpMethod(method);
+ httpMethod = locateHttpMethod(current);
}
if (methodPath == null) {
- methodPath = findMethodPath(method);
+ methodPath = findMethodPath(current);
}
// TODO figure out if these will ever be on different methods.
- if (method != null && methodPath != null) {
+ if (httpMethod != null && methodPath != null) {
break;
}
}

MODIFY
dd-java-agent/instrumentation/jax-rs-annotations-1/src/main/java/datadog/trace/instrumentation/jaxrs1/JaxRsAnnotationsInstrumentation.java
dd-java-agent/instrumentation/jax-rs-annotations-1/src/main/java/datadog/trace/instrumentation/jaxrs1/JaxRsAnnotationsInstrumentation.java
@@ -50,7 +50,10 @@ public final class JaxRsAnnotationsInstrumentation extends Instrumenter.Default
@Override
public String[] helperClassNames() {
return new String[] {
- "datadog.trace.agent.decorator.BaseDecorator", packageName + ".JaxRsAnnotationsDecorator",
+ "datadog.trace.agent.decorator.BaseDecorator",
+ packageName + ".JaxRsAnnotationsDecorator",
+ packageName + ".OverriddenMethodIterable",
+ packageName + ".OverriddenMethodIterable$MethodIterator",
};
}

MODIFY
dd-java-agent/instrumentation/jax-rs-annotations-1/src/main/java/datadog/trace/instrumentation/jaxrs1/OverriddenMethodIterable.java
dd-java-agent/instrumentation/jax-rs-annotations-1/src/main/java/datadog/trace/instrumentation/jaxrs1/OverriddenMethodIterable.java
@@ -2,12 +2,15 @@ package datadog.trace.instrumentation.jaxrs1;
import java.lang.reflect.Method;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
+import java.util.List;
import java.util.Queue;
+import java.util.Set;
public class OverriddenMethodIterable implements Iterable<Method> {
- private final Class baseClass;
+ private final Class<?> baseClass;
private final Method baseMethod;
public OverriddenMethodIterable(final Class target, final Method baseMethod) {
@@ -17,18 +20,31 @@ public class OverriddenMethodIterable implements Iterable<Method> {
@Override
public Iterator<Method> iterator() {
- return new Iterator<Method>() {
+ return new MethodIterator();
+ }
+
+ public class MethodIterator implements Iterator<Method> {
private Method next = baseMethod;
- private Class<?> currentClass = baseClass;
- private boolean analyzeCurrentClass = !baseMethod.getDeclaringClass().equals(baseClass);
- private final Queue<Class<?>> interfaces = new LinkedList<>();
+ private final Set<Class<?>> queuedInterfaces = new HashSet<>();
+ private final Queue<Class<?>> classesToCheck = new LinkedList<>();
+
+ public MethodIterator() {
+ final List<Class<?>> currentInterfaces = Arrays.asList(baseClass.getInterfaces());
+ queuedInterfaces.addAll(currentInterfaces);
+ classesToCheck.addAll(currentInterfaces);
+
+ final Class<?> superclass = baseClass.getSuperclass();
+ if (superclass != null) {
+ classesToCheck.add(superclass);
+ }
+ }
@Override
public boolean hasNext() {
if (next == null) {
calculateNext();
}
- return next == null;
+ return next != null;
}
@Override
@@ -40,42 +56,34 @@ public class OverriddenMethodIterable implements Iterable<Method> {
@Override
public void remove() {
- // Ignore
+ throw new UnsupportedOperationException();
}
private void calculateNext() {
- if (currentClass == null) {
- return;
+ while (next == null && !classesToCheck.isEmpty()) {
+ final Class currentClass = classesToCheck.remove();
+ queueNewInterfaces(currentClass.getInterfaces());
+
+ final Class<?> superClass = currentClass.getSuperclass();
+ if (superClass != null) {
+ classesToCheck.add(currentClass.getSuperclass());
}
- if (analyzeCurrentClass) {
+
next = findMatchingMethod(currentClass.getDeclaredMethods());
- if (next != null) {
- return;
- }
- interfaces.addAll(Arrays.asList(currentClass.getInterfaces()));
- }
- if (!interfaces.isEmpty()) {
- final Class<?> nextInterface = interfaces.remove();
- interfaces.addAll(Arrays.asList(nextInterface.getInterfaces()));
- next = findMatchingMethod(nextInterface.getDeclaredMethods());
- if (next != null) {
- return;
- }
- } else {
- currentClass = currentClass.getSuperclass();
- analyzeCurrentClass = true;
}
}
private Method findMatchingMethod(final Method[] methods) {
nextMethod:
for (final Method method : methods) {
- if (!baseMethod.getName().equals(method.getName())) {
+ if (!baseMethod.getReturnType().equals(method.getReturnType())) {
continue;
}
- if (!baseMethod.getReturnType().equals(method.getReturnType())) {
+
+ if (!baseMethod.getName().equals(method.getName())) {
continue;
}
+
final Class<?>[] baseParameterTypes = baseMethod.getParameterTypes();
final Class<?>[] parameterTypes = method.getParameterTypes();
if (baseParameterTypes.length != parameterTypes.length) {
@@ -90,6 +98,13 @@ public class OverriddenMethodIterable implements Iterable<Method> {
}
return null;
}
- };
+
+ private void queueNewInterfaces(final Class[] interfaces) {
+ for (final Class clazz : interfaces) {
+ if (queuedInterfaces.add(clazz)) {
+ classesToCheck.add(clazz);
+ }
+ }
+ }
}
}

Fix method iterable logic.  methodPath, httpMethod working