diff --git a/java/javax/el/BeanELResolver.java b/java/javax/el/BeanELResolver.java index 9372854..3b6c373 100644 --- a/java/javax/el/BeanELResolver.java +++ b/java/javax/el/BeanELResolver.java @@ -89,7 +89,7 @@ } context.setPropertyResolved(base, property); - Method m = this.property(context, base, property).read(context); + Method m = this.property(context, base, property).read(context, base); try { return m.invoke(base, (Object[]) null); } catch (InvocationTargetException e) { @@ -117,7 +117,7 @@ "resolverNotWriteable", base.getClass().getName())); } - Method m = this.property(context, base, property).write(context); + Method m = this.property(context, base, property).write(context, base); try { m.invoke(base, value); } catch (InvocationTargetException e) { @@ -147,7 +147,7 @@ // Find the matching method Method matchingMethod = - Util.findMethod(base.getClass(), methodName, paramTypes, params); + Util.findMethod(base.getClass(), base, methodName, paramTypes, params); Object[] parameters = Util.buildParameters( matchingMethod.getParameterTypes(), matchingMethod.isVarArgs(), @@ -176,7 +176,7 @@ } context.setPropertyResolved(base, property); - return this.readOnly || this.property(context, base, property).isReadOnly(); + return this.readOnly || this.property(context, base, property).isReadOnly(base); } @Override @@ -295,22 +295,14 @@ return this.type; } - public boolean isReadOnly() { + public boolean isReadOnly(Object base) { return this.write == null && - (null == (this.write = Util.getMethod(this.owner, descriptor.getWriteMethod()))); + (null == (this.write = Util.getMethod(this.owner, base, descriptor.getWriteMethod()))); } - public Method getWriteMethod() { - return write(null); - } - - public Method getReadMethod() { - return this.read(null); - } - - private Method write(ELContext ctx) { + private Method write(ELContext ctx, Object base) { if (this.write == null) { - this.write = Util.getMethod(this.owner, descriptor.getWriteMethod()); + this.write = Util.getMethod(this.owner, base, descriptor.getWriteMethod()); if (this.write == null) { throw new PropertyNotWritableException(Util.message(ctx, "propertyNotWritable", new Object[] { @@ -320,9 +312,9 @@ return this.write; } - private Method read(ELContext ctx) { + private Method read(ELContext ctx, Object base) { if (this.read == null) { - this.read = Util.getMethod(this.owner, descriptor.getReadMethod()); + this.read = Util.getMethod(this.owner, base, descriptor.getReadMethod()); if (this.read == null) { throw new PropertyNotFoundException(Util.message(ctx, "propertyNotReadable", new Object[] { diff --git a/java/javax/el/StaticFieldELResolver.java b/java/javax/el/StaticFieldELResolver.java index de34cd0..e3cc72a 100644 --- a/java/javax/el/StaticFieldELResolver.java +++ b/java/javax/el/StaticFieldELResolver.java @@ -112,7 +112,7 @@ } else { Method match = - Util.findMethod(clazz, methodName, paramTypes, params); + Util.findMethod(clazz, base, methodName, paramTypes, params); int modifiers = match.getModifiers(); if (!Modifier.isStatic(modifiers)) { diff --git a/java/javax/el/Util.java b/java/javax/el/Util.java index 31d7e56..61c7112 100644 --- a/java/javax/el/Util.java +++ b/java/javax/el/Util.java @@ -17,8 +17,10 @@ package javax.el; import java.lang.ref.WeakReference; +import java.lang.reflect.AccessibleObject; import java.lang.reflect.Array; import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.security.AccessController; @@ -197,7 +199,7 @@ * This method duplicates code in org.apache.el.util.ReflectionUtil. When * making changes keep the code in sync. */ - static Method findMethod(Class clazz, String methodName, + static Method findMethod(Class clazz, Object base, String methodName, Class[] paramTypes, Object[] paramValues) { if (clazz == null || methodName == null) { @@ -216,7 +218,7 @@ Wrapper result = findWrapper(clazz, wrappers, methodName, paramTypes, paramValues); - return getMethod(clazz, (Method) result.unWrap()); + return getMethod(clazz, base, (Method) result.unWrap()); } /* @@ -539,8 +541,9 @@ * This method duplicates code in org.apache.el.util.ReflectionUtil. When * making changes keep the code in sync. */ - static Method getMethod(Class type, Method m) { - if (m == null || Modifier.isPublic(type.getModifiers())) { + static Method getMethod(Class type, Object base, Method m) { + JreCompat jreCompat = JreCompat.getInstance(); + if (m == null || jreCompat.canAcccess(type, base, m)) { return m; } Class[] inf = type.getInterfaces(); @@ -548,7 +551,7 @@ for (int i = 0; i < inf.length; i++) { try { mp = inf[i].getMethod(m.getName(), m.getParameterTypes()); - mp = getMethod(mp.getDeclaringClass(), mp); + mp = getMethod(mp.getDeclaringClass(), base, mp); if (mp != null) { return mp; } @@ -560,7 +563,7 @@ if (sup != null) { try { mp = sup.getMethod(m.getName(), m.getParameterTypes()); - mp = getMethod(mp.getDeclaringClass(), mp); + mp = getMethod(mp.getDeclaringClass(), base, mp); if (mp != null) { return mp; } @@ -836,4 +839,65 @@ return Thread.currentThread().getContextClassLoader(); } } + + + private static class JreCompat { + + private static final JreCompat instance; + + static { + if (Jre9Compat.isSupported()) { + instance = new Jre9Compat(); + } else { + instance = new JreCompat(); + } + } + + public static JreCompat getInstance() { + return instance; + } + + /** + * + * @param type The type the accessible object belongs to + * @param base The specific instance of the type to be tested + * @param accessibleObject The method/field/constructor to be tested + * + * @return {code true} if the AccessibleObject can be accessed otherwise + * {code false} + */ + public boolean canAcccess(Class type, Object base, AccessibleObject accessibleObject) { + return Modifier.isPublic(type.getModifiers()); + } + } + + + private static class Jre9Compat extends JreCompat { + + private static final Method canAccessMethod; + + static { + Method m1 = null; + try { + m1 = AccessibleObject.class.getMethod("canAccess", new Class[] { Object.class }); + } catch (NoSuchMethodException e) { + // Expected for Java 8 + } + canAccessMethod = m1; + } + + public static boolean isSupported() { + return canAccessMethod != null; + } + + @Override + public boolean canAcccess(Class type, Object base, AccessibleObject accessibleObject) { + try { + return ((Boolean) canAccessMethod.invoke(accessibleObject, base)).booleanValue(); + } catch (IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) { + return false; + } + } + } }