Skip to content

Commit b7aed5a

Browse files
puredangerstuarthalloway
authored andcommitted
CLJ-2454 When reflectively finding a matching method, also check whether the method is module accessible to call, and if not use an accessible super method
Signed-off-by: Stuart Halloway <stu@cognitect.com>
1 parent c4dc881 commit b7aed5a

File tree

1 file changed

+53
-2
lines changed

1 file changed

+53
-2
lines changed

src/jvm/clojure/lang/Reflector.java

+53-2
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,11 @@ else if(methods.size() == 1)
153153
if(m == null)
154154
throw new IllegalArgumentException(noMethodReport(methodName,target,args));
155155

156-
if(!Modifier.isPublic(m.getDeclaringClass().getModifiers()))
156+
if(!Modifier.isPublic(m.getDeclaringClass().getModifiers()) || !canAccess(m, target))
157157
{
158158
//public method of non-public class, try to find it in hierarchy
159159
Method oldm = m;
160-
m = getAsMethodOfPublicBase(target.getClass(), m);
160+
m = getAsMethodOfAccessibleBase(target.getClass(), m, target);
161161
if(m == null)
162162
throw new IllegalArgumentException("Can't call public method of non-public class: " +
163163
oldm.toString());
@@ -173,6 +173,7 @@ else if(methods.size() == 1)
173173

174174
}
175175

176+
// DEPRECATED - replaced by getAsMethodOfAccessibleBase()
176177
public static Method getAsMethodOfPublicBase(Class c, Method m){
177178
for(Class iface : c.getInterfaces())
178179
{
@@ -197,6 +198,7 @@ public static Method getAsMethodOfPublicBase(Class c, Method m){
197198
return getAsMethodOfPublicBase(sc, m);
198199
}
199200

201+
// DEPRECATED - replaced by isAccessibleMatch()
200202
public static boolean isMatch(Method lhs, Method rhs) {
201203
if(!lhs.getName().equals(rhs.getName())
202204
|| !Modifier.isPublic(lhs.getDeclaringClass().getModifiers()))
@@ -221,6 +223,55 @@ public static boolean isMatch(Method lhs, Method rhs) {
221223
return match;
222224
}
223225

226+
public static Method getAsMethodOfAccessibleBase(Class c, Method m, Object target){
227+
for(Class iface : c.getInterfaces())
228+
{
229+
for(Method im : iface.getMethods())
230+
{
231+
if(isAccessibleMatch(im, m, target))
232+
{
233+
return im;
234+
}
235+
}
236+
}
237+
Class sc = c.getSuperclass();
238+
if(sc == null)
239+
return null;
240+
for(Method scm : sc.getMethods())
241+
{
242+
if(isAccessibleMatch(scm, m, target))
243+
{
244+
return scm;
245+
}
246+
}
247+
return getAsMethodOfAccessibleBase(sc, m, target);
248+
}
249+
250+
public static boolean isAccessibleMatch(Method lhs, Method rhs, Object target) {
251+
if(!lhs.getName().equals(rhs.getName())
252+
|| !Modifier.isPublic(lhs.getDeclaringClass().getModifiers())
253+
|| !canAccess(lhs, target))
254+
{
255+
return false;
256+
}
257+
258+
Class[] types1 = lhs.getParameterTypes();
259+
Class[] types2 = rhs.getParameterTypes();
260+
if(types1.length != types2.length)
261+
return false;
262+
263+
boolean match = true;
264+
for (int i=0; i<types1.length; ++i)
265+
{
266+
if(!types1[i].isAssignableFrom(types2[i]))
267+
{
268+
match = false;
269+
break;
270+
}
271+
}
272+
return match;
273+
}
274+
224275
public static Object invokeConstructor(Class c, Object[] args) {
225276
try
226277
{

0 commit comments

Comments
 (0)