Allow access coercion to be disabled.
I'm not disabling it by default because that would change behavior for anyone who was using reflection, which seems like annoying breakage. People who are using JMustache with Java 9 can configure a non-coercing DefaultCollector to eliminate the illegal access warnings.
This commit is contained in:
@@ -17,6 +17,16 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
*/
|
||||
public class DefaultCollector extends BasicCollector
|
||||
{
|
||||
private final boolean _allowAccessCoercion;
|
||||
|
||||
public DefaultCollector () {
|
||||
this(true);
|
||||
}
|
||||
|
||||
public DefaultCollector (boolean allowAccessCoercion) {
|
||||
_allowAccessCoercion = allowAccessCoercion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mustache.VariableFetcher createFetcher (Object ctx, String name) {
|
||||
Mustache.VariableFetcher fetcher = super.createFetcher(ctx, name);
|
||||
@@ -63,11 +73,21 @@ public class DefaultCollector extends BasicCollector
|
||||
}
|
||||
|
||||
protected Method getMethod (Class<?> clazz, String name) {
|
||||
if (_allowAccessCoercion) {
|
||||
// first check up the superclass chain
|
||||
for (Class<?> cc = clazz; cc != null && cc != Object.class; cc = cc.getSuperclass()) {
|
||||
Method m = getMethodOn(cc, name);
|
||||
if (m != null) return m;
|
||||
}
|
||||
} else {
|
||||
// if we only allow access to accessible methods, then we can just let the JVM handle
|
||||
// searching superclasses for the method
|
||||
try {
|
||||
return clazz.getMethod(name);
|
||||
} catch (Exception e) {
|
||||
// fall through
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -119,11 +139,21 @@ public class DefaultCollector extends BasicCollector
|
||||
}
|
||||
|
||||
private Method makeAccessible (Method m) {
|
||||
if (!m.isAccessible()) m.setAccessible(true);
|
||||
if (m.isAccessible()) return m;
|
||||
else if (!_allowAccessCoercion) return null;
|
||||
m.setAccessible(true);
|
||||
return m;
|
||||
}
|
||||
|
||||
protected Field getField (Class<?> clazz, String name) {
|
||||
if (!_allowAccessCoercion) {
|
||||
try {
|
||||
return clazz.getField(name);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Field f;
|
||||
try {
|
||||
f = clazz.getDeclaredField(name);
|
||||
|
||||
@@ -275,4 +275,22 @@ public class MustacheTest extends SharedTests
|
||||
test("k1v1k2v2", "{{#map.entrySet}}{{key}}{{value}}{{/map.entrySet}}",
|
||||
context("map", data));
|
||||
}
|
||||
|
||||
@Test public void testNoAccesCoercion () {
|
||||
Object ctx = new Object() {
|
||||
public Object foo () {
|
||||
return new Object() {
|
||||
public Object bar = new Object() {
|
||||
public String baz = "hello";
|
||||
private String quux = "hello";
|
||||
};
|
||||
};
|
||||
}
|
||||
};
|
||||
test("hello:hello", "{{foo.bar.baz}}:{{foo.bar.quux}}", ctx);
|
||||
Mustache.Compiler comp = Mustache.compiler().
|
||||
withCollector(new DefaultCollector(false)).
|
||||
defaultValue("missing");
|
||||
test(comp, "hello:missing", "{{foo.bar.baz}}:{{foo.bar.quux}}", ctx);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user