Skip to content

Commit

Permalink
Add File and Path as string primitive (#7652)
Browse files Browse the repository at this point in the history
Since jdk 17 it's not possible to do deep reflection. The content of
File or Path instances are difficult to see content with deep
reflection, though the meaningful value is the toString representation
We are adding File and Path instances serialized as string primitive
and evaluated in EL as String as well
  • Loading branch information
jpbempel authored Sep 20, 2024
1 parent 0eb6f8c commit a6bcbc1
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,37 +26,38 @@ public class WellKnownClasses {

static {
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Class", WellKnownClasses::classToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.String", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Boolean", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Integer", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Long", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Double", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Character", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Byte", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Float", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Short", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.math.BigDecimal", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.math.BigInteger", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.time.Duration", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.time.Instant", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.time.LocalTime", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.time.LocalDate", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.time.LocalDateTime", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.util.UUID", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.net.URI", WellKnownClasses::genericToString);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.String", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Boolean", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Integer", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Long", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Double", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Character", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Byte", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Float", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.lang.Short", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.math.BigDecimal", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.math.BigInteger", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.time.Duration", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.time.Instant", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.time.LocalTime", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.time.LocalDate", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.time.LocalDateTime", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.util.UUID", String::valueOf);
TO_STRING_FINAL_SAFE_CLASSES.put("java.net.URI", String::valueOf);
}

private static final Map<String, Function<Object, String>> SAFE_TO_STRING_FUNCTIONS =
new HashMap<>();

static {
SAFE_TO_STRING_FUNCTIONS.putAll(TO_STRING_FINAL_SAFE_CLASSES);
SAFE_TO_STRING_FUNCTIONS.put(
"java.util.concurrent.atomic.AtomicBoolean", WellKnownClasses::genericToString);
SAFE_TO_STRING_FUNCTIONS.put(
"java.util.concurrent.atomic.AtomicInteger", WellKnownClasses::genericToString);
SAFE_TO_STRING_FUNCTIONS.put(
"java.util.concurrent.atomic.AtomicLong", WellKnownClasses::genericToString);
SAFE_TO_STRING_FUNCTIONS.put("java.util.concurrent.atomic.AtomicBoolean", String::valueOf);
SAFE_TO_STRING_FUNCTIONS.put("java.util.concurrent.atomic.AtomicInteger", String::valueOf);
SAFE_TO_STRING_FUNCTIONS.put("java.util.concurrent.atomic.AtomicLong", String::valueOf);
SAFE_TO_STRING_FUNCTIONS.put("java.io.File", String::valueOf);
// implementations of java.io.file.Path interfaces
SAFE_TO_STRING_FUNCTIONS.put("sun.nio.fs.UnixPath", String::valueOf);
SAFE_TO_STRING_FUNCTIONS.put("sun.nio.fs.WindowsPath", String::valueOf);
}

private static final Set<String> EQUALS_SAFE_CLASSES = new HashSet<>();
Expand All @@ -81,6 +82,9 @@ public class WellKnownClasses {
EQUALS_SAFE_CLASSES.add("java.time.LocalDateTime");
EQUALS_SAFE_CLASSES.add("java.util.UUID");
EQUALS_SAFE_CLASSES.add("java.net.URI");
EQUALS_SAFE_CLASSES.add("java.io.File");
EQUALS_SAFE_CLASSES.add("sun.nio.fs.UnixPath");
EQUALS_SAFE_CLASSES.add("sun.nio.fs.WindowsPath");
}

private static final Set<String> STRING_PRIMITIVES =
Expand All @@ -93,7 +97,10 @@ public class WellKnownClasses {
"java.time.LocalTime",
"java.time.LocalDate",
"java.time.LocalDateTime",
"java.util.UUID"));
"java.util.UUID",
"java.io.File",
"sun.nio.fs.UnixPath",
"sun.nio.fs.WindowsPath"));

private static final Map<Class<?>, Map<String, Function<Object, CapturedContext.CapturedValue>>>
SPECIAL_TYPE_ACCESS = new HashMap<>();
Expand Down Expand Up @@ -236,10 +243,6 @@ private static String classToString(Object o) {
return ((Class<?>) o).getTypeName();
}

private static String genericToString(Object o) {
return String.valueOf(o);
}

public static boolean isEqualsSafe(Class<?> clazz) {
return clazz.isPrimitive()
|| clazz.isEnum()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@
import datadog.trace.bootstrap.debugger.ProbeLocation;
import datadog.trace.bootstrap.debugger.util.TimeoutChecker;
import datadog.trace.test.util.Flaky;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.math.BigDecimal;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
Expand Down Expand Up @@ -308,6 +310,8 @@ static class WellKnownClasses {
OptionalLong maybeLong = OptionalLong.of(84);
Exception ex = new IllegalArgumentException("invalid arg");
StackTraceElement element = new StackTraceElement("Foo", "bar", "foo.java", 42);
File file = new File("/tmp/foo");
Path path = file.toPath();
}

@Test
Expand Down Expand Up @@ -384,6 +388,10 @@ public void wellKnownClasses() throws IOException {
assertPrimitiveValue(elementFields, "methodName", String.class.getTypeName(), "bar");
assertPrimitiveValue(elementFields, "fileName", String.class.getTypeName(), "foo.java");
assertPrimitiveValue(elementFields, "lineNumber", Integer.class.getTypeName(), "42");
// file
assertPrimitiveValue(objLocalFields, "file", File.class.getTypeName(), "/tmp/foo");
// path
assertPrimitiveValue(objLocalFields, "path", "sun.nio.fs.UnixPath", "/tmp/foo");
}

@Test
Expand Down

0 comments on commit a6bcbc1

Please sign in to comment.