Skip to content

Commit

Permalink
Backporting orphan-oss#40 to ognl-3-1-x branch.
Browse files Browse the repository at this point in the history
When scanning super interfaces in `OgnlRuntime#getMethods(Class, boolean)`, only default methods should be collected instead of all declared methods.
Also, super interfaces should be searched recursively so that it can handle deeper interface hierarchy.
  • Loading branch information
harawata committed Nov 15, 2017
1 parent 9c927cf commit 762994c
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 31 deletions.
74 changes: 44 additions & 30 deletions src/java/ognl/OgnlRuntime.java
Original file line number Diff line number Diff line change
Expand Up @@ -1789,43 +1789,57 @@ public static Map getMethods(Class targetClass, boolean staticMethods)
if ((result = (Map) cache.get(targetClass)) == null)
{
result = new HashMap(23);

List<Class> toExamined = new LinkedList<Class>();
for (Class c = targetClass; c != null; c = c.getSuperclass())
{
toExamined.add(c);

// Including interfaces is needed as from Java 8 intefaces can implement defaul methods
toExamined.addAll(Arrays.asList(c.getInterfaces()));
collectMethods(targetClass, result, staticMethods);
cache.put(targetClass, result);
}
}
}
return result;
}

for (Class c : toExamined)
{
Method[] ma = c.getDeclaredMethods();
private static void collectMethods(Class c, Map result, boolean staticMethods) {
Method[] ma = c.getDeclaredMethods();
for (int i = 0, icount = ma.length; i < icount; i++)
{
if (c.isInterface())
{
if (isDefaultMethod(ma[i]))
addMethodToResult(result, ma[i]);
continue;
}

for (int i = 0, icount = ma.length; i < icount; i++)
{
// skip over synthetic methods
// skip over synthetic methods
if (!isMethodCallable(ma[i]))
continue;

if (!isMethodCallable(ma[i]))
continue;
if (Modifier.isStatic(ma[i].getModifiers()) == staticMethods)
addMethodToResult(result, ma[i]);
}

if (Modifier.isStatic(ma[i].getModifiers()) == staticMethods)
{
List ml = (List) result.get(ma[i].getName());
Class superclass = c.getSuperclass();
if (superclass != null)
collectMethods(superclass, result, staticMethods);

if (ml == null)
result.put(ma[i].getName(), ml = new ArrayList());
for (Class iface : c.getInterfaces())
collectMethods(iface, result, staticMethods);
}

ml.add(ma[i]);
}
}
}
cache.put(targetClass, result);
}
}
}
return result;
private static void addMethodToResult(Map result, Method method)
{
List ml = (List) result.get(method.getName());
if (ml == null)
result.put(method.getName(), ml = new ArrayList());
ml.add(method);
}

/**
* Backport of java.lang.reflect.Method#isDefault()
*/
private static boolean isDefaultMethod(Method method)
{
return ((method.getModifiers()
& (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) == Modifier.PUBLIC)
&& method.getDeclaringClass().isInterface();
}

public static Map getAllMethods(Class targetClass, boolean staticMethods)
Expand Down
7 changes: 6 additions & 1 deletion src/test/java/ognl/Java8Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ public void testDefaultMethodOnSubClass() {

class SubClassWithDefaults extends ClassWithDefaults {

public String getName() { return "name"; }

}

class ClassWithDefaults /* implements InterfaceWithDefaults */ {
class ClassWithDefaults /* implements SubInterfaceWithDefaults */ {

}

Expand All @@ -33,5 +35,8 @@ class ClassWithDefaults /* implements InterfaceWithDefaults */ {
*
interface InterfaceWithDefaults {
default public void defaultMethod() { }
default public String getName() { return "name"; }
}
interface SubInterfaceWithDefaults extends InterfaceWithDefaults {
}
*/

0 comments on commit 762994c

Please sign in to comment.