Fixed Java 9+ reflection issue
This commit is contained in:
parent
c4f7823ba3
commit
2ea486a05d
2 changed files with 49 additions and 10 deletions
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 Ziver Koc
|
||||
* Copyright (c) 2020-2025 Ziver Koc
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -24,9 +24,7 @@
|
|||
|
||||
package zutil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
|
@ -248,4 +246,46 @@ public class ClassUtil {
|
|||
|
||||
return fields;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds a method definition that is public and accessible for a given method.
|
||||
* This is required for Java 9+ compatibility when reflecting on internal classes.
|
||||
*
|
||||
* @param method the method to search for.
|
||||
* @return a public Method that can be called by reflection without throwing an exception, or the original method will be returned.
|
||||
*/
|
||||
public static Method getAccessibleMethod(Method method) {
|
||||
if (Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
|
||||
// The method is already accessible so return it directly
|
||||
return method;
|
||||
}
|
||||
|
||||
String methodName = method.getName();
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
|
||||
// Check implemented interfaces for the method (e.g., finding Map.Entry.getKey())
|
||||
for (Class<?> interfaceClass : method.getDeclaringClass().getInterfaces()) {
|
||||
try {
|
||||
Method interfaceMethod = interfaceClass.getMethod(methodName, paramTypes);
|
||||
if (Modifier.isPublic(interfaceMethod.getDeclaringClass().getModifiers())) {
|
||||
return interfaceMethod;
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
// Interface does not have this method, continue loop
|
||||
}
|
||||
}
|
||||
|
||||
// Check if superclass has the method
|
||||
Class<?> superClass = method.getDeclaringClass().getSuperclass();
|
||||
if (superClass != null) {
|
||||
try {
|
||||
Method superMethod = superClass.getMethod(methodName, paramTypes);
|
||||
return getAccessibleMethod(superMethod);
|
||||
} catch (NoSuchMethodException e) {}
|
||||
}
|
||||
|
||||
// No public version was found, return original
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2020 Ziver Koc
|
||||
* Copyright (c) 2020-2025 Ziver Koc
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -152,7 +152,7 @@ public class Templator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Will parse or re-parse the source template.
|
||||
* Will parse or reparse the source template.
|
||||
*/
|
||||
private void parseTemplate(String tmpl) {
|
||||
tmplRoot = parseTemplate(new TemplateNode(), tmpl, new MutableInt(), null);
|
||||
|
|
@ -396,11 +396,11 @@ public class Templator {
|
|||
if (attrib.endsWith("()")) { // Is this a function call?
|
||||
if (attrib.length() > 2) {
|
||||
String funcName = attrib.substring(0, attrib.length()-2);
|
||||
// Using a loop as the direct lookup throws a exception if no field was found
|
||||
// Using a loop as the direct lookup throws an exception if no field was found
|
||||
// So this is probably a bit faster
|
||||
for (Method m : obj.getClass().getMethods()) {
|
||||
if (m.getParameterTypes().length == 0 && m.getName().equals(funcName)) {
|
||||
m.setAccessible(true);
|
||||
m = ClassUtil.getAccessibleMethod(m);
|
||||
return m.invoke(obj);
|
||||
}
|
||||
}
|
||||
|
|
@ -411,11 +411,10 @@ public class Templator {
|
|||
else if (obj instanceof Collection && "length".equals(attrib))
|
||||
return ((Collection) obj).size();
|
||||
else {
|
||||
// Using a loop as the direct lookup throws a exception if no field was found
|
||||
// Using a loop as the direct lookup throws an exception if no field was found
|
||||
// So this is probably a bit faster
|
||||
for (Field field : ClassUtil.getAllDeclaredFields(obj.getClass())) { // Only look for public fields
|
||||
if (field.getName().equals(attrib)) {
|
||||
field.setAccessible(true);
|
||||
return field.get(obj);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue