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)
|
* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -24,9 +24,7 @@
|
||||||
|
|
||||||
package zutil;
|
package zutil;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.*;
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
@ -248,4 +246,46 @@ public class ClassUtil {
|
||||||
|
|
||||||
return fields;
|
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)
|
* 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
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* 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) {
|
private void parseTemplate(String tmpl) {
|
||||||
tmplRoot = parseTemplate(new TemplateNode(), tmpl, new MutableInt(), null);
|
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.endsWith("()")) { // Is this a function call?
|
||||||
if (attrib.length() > 2) {
|
if (attrib.length() > 2) {
|
||||||
String funcName = attrib.substring(0, 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
|
// So this is probably a bit faster
|
||||||
for (Method m : obj.getClass().getMethods()) {
|
for (Method m : obj.getClass().getMethods()) {
|
||||||
if (m.getParameterTypes().length == 0 && m.getName().equals(funcName)) {
|
if (m.getParameterTypes().length == 0 && m.getName().equals(funcName)) {
|
||||||
m.setAccessible(true);
|
m = ClassUtil.getAccessibleMethod(m);
|
||||||
return m.invoke(obj);
|
return m.invoke(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -411,11 +411,10 @@ public class Templator {
|
||||||
else if (obj instanceof Collection && "length".equals(attrib))
|
else if (obj instanceof Collection && "length".equals(attrib))
|
||||||
return ((Collection) obj).size();
|
return ((Collection) obj).size();
|
||||||
else {
|
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
|
// So this is probably a bit faster
|
||||||
for (Field field : ClassUtil.getAllDeclaredFields(obj.getClass())) { // Only look for public fields
|
for (Field field : ClassUtil.getAllDeclaredFields(obj.getClass())) { // Only look for public fields
|
||||||
if (field.getName().equals(attrib)) {
|
if (field.getName().equals(attrib)) {
|
||||||
field.setAccessible(true);
|
|
||||||
return field.get(obj);
|
return field.get(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue