Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
Expand All @@ -14,6 +15,7 @@
import java.util.OptionalLong;
import java.util.Set;
import java.util.function.Function;
import java.util.function.ToLongFunction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -58,6 +60,13 @@ public class WellKnownClasses {
// 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);
SAFE_TO_STRING_FUNCTIONS.put("java.util.Date", WellKnownClasses::dateToString);
}

private static final Map<String, ToLongFunction<Object>> LONG_FUNCTIONS = new HashMap<>();

static {
LONG_FUNCTIONS.put("java.util.Date", WellKnownClasses::dateToLongValue);
}

private static final Set<String> EQUALS_SAFE_CLASSES = new HashSet<>();
Expand Down Expand Up @@ -102,6 +111,8 @@ public class WellKnownClasses {
"sun.nio.fs.UnixPath",
"sun.nio.fs.WindowsPath"));

private static final Set<String> LONG_PRIMITIVES = new HashSet<>(Arrays.asList("java.util.Date"));

private static final Map<Class<?>, Map<String, Function<Object, CapturedContext.CapturedValue>>>
SPECIAL_TYPE_ACCESS = new HashMap<>();

Expand Down Expand Up @@ -211,6 +222,14 @@ public static boolean isStringPrimitive(String type) {
return STRING_PRIMITIVES.contains(type);
}

/**
* indicates if type is considered as a int/long primitive and can be compared to another long
* value or literal with Expression Language
*/
public static boolean isLongPrimitive(String type) {
return LONG_PRIMITIVES.contains(type);
}

/**
* @return a map of fields with function to access special field of a type, or null if type is not
* supported. This is used to avoid using reflection to access fields on well known types
Expand All @@ -232,6 +251,8 @@ public static Map<String, Function<Object, CapturedContext.CapturedValue>> getSp
}

/**
* @param type the type name of the object to generate a string representation for. Must be a
* concrete type, not a declared type. see {@link #isToStringSafe(String)}
* @return a function to generate a string representation of a type where the default toString
* method is not suitable
*/
Expand All @@ -243,12 +264,24 @@ private static String classToString(Object o) {
return ((Class<?>) o).getTypeName();
}

private static String dateToString(Object o) {
return Long.toString(((Date) o).getTime());
}

private static long dateToLongValue(Object o) {
return ((Date) o).getTime();
}

public static boolean isEqualsSafe(Class<?> clazz) {
return clazz.isPrimitive()
|| clazz.isEnum()
|| EQUALS_SAFE_CLASSES.contains(clazz.getTypeName());
}

public static ToLongFunction<Object> getLongPrimitiveValueFunction(String typeName) {
return LONG_FUNCTIONS.get(typeName);
}

private static class ThrowableFields {
public static final String BECAUSE_OVERRIDDEN =
"Special access method not safe to be called because overridden";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.ToLongFunction;

/** Represents any value of the expression language */
public interface Value<T> {
Expand Down Expand Up @@ -64,6 +65,11 @@ static Value<?> of(Object value) {
}
value = toString.apply(value);
}
if (WellKnownClasses.isLongPrimitive(typeName)) {
ToLongFunction<Object> longPrimitiveValueFunction =
WellKnownClasses.getLongPrimitiveValueFunction(typeName);
value = longPrimitiveValueFunction.applyAsLong(value);
}
if (value instanceof Boolean) {
return new BooleanValue((Boolean) value);
} else if (value instanceof Character) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -199,12 +200,13 @@ void redaction() throws IOException {
}

@Test
void stringPrimitives() throws IOException {
void primitives() throws IOException {
ProbeCondition probeCondition = loadFromResource("/test_conditional_10.json");
Map<String, Object> args = new HashMap<>();
args.put("uuid", UUID.fromString("a3cbe9e7-edd3-4bef-8e5b-59bfcb04cf91"));
args.put("duration", Duration.ofSeconds(42));
args.put("clazz", "foo".getClass());
args.put("now", new Date(1700000000000L)); // 2023-11-14T00:00:00Z
ValueReferenceResolver ctx = RefResolverHelper.createResolver(args, null);
assertTrue(probeCondition.execute(ctx));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,12 @@
"eq": [
{"ref": "clazz"},
"java.lang.String"]
}
}, {
"eq": [
{"ref": "now"},
1700000000000
]
}
]
}
}

"dsl": "isEmpty(emptyStr) && isEmpty(emptyList) && isEmpty(emptyMap) && isEmpty(emptyArray) && isUndefined(@exception)",
"json": {
"and": [
{"isEmpty": {"ref": "emptyStr"}},
{"isEmpty": {"ref": "emptyList"}},
{"isEmpty": {"ref": "emptyMap"}},
{"isEmpty": {"ref": "emptyArray"}},
{"isUndefined": {"ref": "@exception"}}

Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ static class WellKnownClasses {
UUID uuid = UUID.nameUUIDFromBytes("foobar".getBytes());
AtomicLong atomicLong = new AtomicLong(123);
URI uri = URI.create("https://www.datadoghq.com");
Optional<Date> maybeDate = Optional.of(new Date());
Optional<Date> maybeDate = Optional.of(new Date(1700000000000L));
Optional<Object> empty = Optional.empty();
OptionalInt maybeInt = OptionalInt.of(42);
OptionalDouble maybeDouble = OptionalDouble.of(3.14);
Expand Down Expand Up @@ -344,13 +344,12 @@ public void wellKnownClasses() throws IOException {
Map<String, Object> maybeDate = (Map<String, Object>) objLocalFields.get("maybeDate");
assertComplexClass(maybeDate, Optional.class.getTypeName());
Map<String, Object> maybeDateFields = (Map<String, Object>) maybeDate.get(FIELDS);
Map<String, Object> value = (Map<String, Object>) maybeDateFields.get("value");
assertComplexClass(value, Date.class.getTypeName());
assertPrimitiveValue(maybeDateFields, "value", Date.class.getTypeName(), "1700000000000");
// empty
Map<String, Object> empty = (Map<String, Object>) objLocalFields.get("empty");
assertComplexClass(empty, Optional.class.getTypeName());
Map<String, Object> emptyFields = (Map<String, Object>) empty.get(FIELDS);
value = (Map<String, Object>) emptyFields.get("value");
Map<String, Object> value = (Map<String, Object>) emptyFields.get("value");
assertEquals(Object.class.getTypeName(), value.get(TYPE));
assertTrue((Boolean) value.get(IS_NULL));
// maybeInt
Expand Down