Skip to content

Commit

Permalink
Fix for #667 Illegal Access for JDK 9 or greater
Browse files Browse the repository at this point in the history
  • Loading branch information
agentgt authored and jknack committed Oct 3, 2021
1 parent e095219 commit a7adb10
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 3 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ jobs:
with:
java-version: ${{ matrix.java_version }}
- name: Install
run: mvn clean install -DskipTests
run: mvn clean install -DskipTests --batch-mode --no-transfer-progress
env:
BUILD_PORT: 0
BUILD_SECURE_PORT: 0
- name: Build
run: mvn clean package
run: mvn clean package --batch-mode --no-transfer-progress
env:
BUILD_PORT: 0
BUILD_SECURE_PORT: 0
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ private Map<String, M> cache(final Class<?> clazz) {
Set<M> members = members(clazz);
for (M m : members) {
// Mark as accessible.
if (m instanceof AccessibleObject) {
if (isUseSetAccessible(m) && m instanceof AccessibleObject) {
((AccessibleObject) m).setAccessible(true);
}
mcache.put(memberName(m), m);
Expand All @@ -88,6 +88,31 @@ private Map<String, M> cache(final Class<?> clazz) {
return mcache;
}

/**
* Determines whether or not to call
* {@link AccessibleObject#setAccessible(boolean)} on members before they are
* cached.
*
* Calling setAccessible on JDK 9 or later on private or protected declaring
* classes in modules will result in errors so the default implementation checks
* to see if the declared class cannonical name starts with "java." or "sun." to
* prevent most of these errors.
*
* Modular applications should create their own resolvers and override this
* method to prevent encapsulation violation errors.
*
* @param member Not null.
* @return true will cause setAccessible(true) to be called.
*/
protected boolean isUseSetAccessible(final M member) {
Class<?> dc = member.getDeclaringClass();
String dn = dc == null ? null : dc.getCanonicalName();
if (dn != null && (dn.startsWith("java.") || dn.startsWith("sun."))) {
return false;
}
return true;
}

/**
* Invoke the member in the given context.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.github.jknack.handlebars.context;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;

import java.lang.reflect.Method;
import java.util.Collections;

import org.junit.Test;

public class SetAccessibleValueResolverTest {

/*
* The following tests require JDK 9 or greater.
* To keep the tests from failing we use junit assume.
*/

@Test
public void testSetAccessibleOnJDK9OrGreater() throws Exception {
assumeTrue(getJavaVersion() >= 9);
MethodValueResolver mv = new MethodValueResolver() {

@Override
protected boolean isUseSetAccessible(Method m) {
return true;
}
};
try {
mv.resolve(Collections.emptyMap(), "doesNotMatter");
fail("Expect InaccessibleObjectException");
} catch (/* InaccessibleObjectException */ Exception e) {
}

mv = new MethodValueResolver();
mv.resolve(Collections.emptyMap(), "doesNotMatter");
Object result = mv.resolve(Collections.emptyMap(), "isEmpty");
assertEquals(Boolean.TRUE, result);
}

static int getJavaVersion() {
String version = System.getProperty("java.version");
if (version.startsWith("1.")) {
version = version.substring(2, 3);
} else {
int dot = version.indexOf(".");
if (dot != -1) {
version = version.substring(0, dot);
}
}
try {
return Integer.parseInt(version);
} catch (NumberFormatException e) {
return 8;
}
}

}

0 comments on commit a7adb10

Please sign in to comment.