MethodHandles.Lookup.defineClass for CGLIB class definition purposes

Spring's CGLIB fork is patched with local copies of affected files here, introducing the notion of a "contextClass" (e.g. the proxy superclass) which gets passed through to ReflectUtils.defineClass for delegating to MethodHandles.Lookup.defineClass eventually, against a privateLookupIn(contextClass) lookup context on JDK 9/10/11.

Issue: SPR-15859
This commit is contained in:
Juergen Hoeller
2018-04-11 12:47:55 +02:00
parent cdaa247861
commit 61c3db0869
15 changed files with 3153 additions and 206 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,9 +16,6 @@
package org.springframework.beans.factory.config;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;
import org.junit.After;
@@ -56,7 +53,7 @@ public class PropertyPlaceholderConfigurerTests {
@Before
public void setUp() {
public void setup() {
p1BeanDef = rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${" + P1 + "}")
.getBeanDefinition();
@@ -66,16 +63,14 @@ public class PropertyPlaceholderConfigurerTests {
ppcProperties = new Properties();
ppcProperties.setProperty(P1, P1_LOCAL_PROPS_VAL);
System.setProperty(P1, P1_SYSTEM_PROPS_VAL);
getModifiableSystemEnvironment().put(P1, P1_SYSTEM_ENV_VAL);
ppc = new PropertyPlaceholderConfigurer();
ppc.setProperties(ppcProperties);
}
@After
public void tearDown() {
public void cleanup() {
System.clearProperty(P1);
getModifiableSystemEnvironment().remove(P1);
}
@@ -95,7 +90,7 @@ public class PropertyPlaceholderConfigurerTests {
@Test
public void resolveFromSystemProperties() {
getModifiableSystemEnvironment().put("otherKey", "systemValue");
System.setProperty("otherKey", "systemValue");
p1BeanDef = rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${" + P1 + "}")
.addPropertyValue("sex", "${otherKey}")
@@ -105,12 +100,12 @@ public class PropertyPlaceholderConfigurerTests {
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_LOCAL_PROPS_VAL));
assertThat(bean.getSex(), equalTo("systemValue"));
getModifiableSystemEnvironment().remove("otherKey");
System.clearProperty("otherKey");
}
@Test
public void resolveFromLocalProperties() {
tearDown(); // eliminate entries from system props/environment
System.clearProperty(P1);
registerWithGeneratedName(p1BeanDef, bf);
ppc.postProcessBeanFactory(bf);
TestBean bean = bf.getBean(TestBean.class);
@@ -134,16 +129,6 @@ public class PropertyPlaceholderConfigurerTests {
assertThat(bean.getName(), equalTo(P1_SYSTEM_PROPS_VAL));
}
@Test
public void setSystemSystemPropertiesMode_toOverride_andResolveFromSystemEnvironment() {
registerWithGeneratedName(p1BeanDef, bf);
System.clearProperty(P1); // will now fall all the way back to system environment
ppc.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE);
ppc.postProcessBeanFactory(bf);
TestBean bean = bf.getBean(TestBean.class);
assertThat(bean.getName(), equalTo(P1_SYSTEM_ENV_VAL));
}
@Test
public void setSystemSystemPropertiesMode_toOverride_andSetSearchSystemEnvironment_toFalse() {
registerWithGeneratedName(p1BeanDef, bf);
@@ -160,7 +145,7 @@ public class PropertyPlaceholderConfigurerTests {
* settings regarding resolving properties from the environment.
*/
@Test
public void twoPlacholderConfigurers_withConflictingSettings() {
public void twoPlaceholderConfigurers_withConflictingSettings() {
String P2 = "p2";
String P2_LOCAL_PROPS_VAL = "p2LocalPropsVal";
String P2_SYSTEM_PROPS_VAL = "p2SystemPropsVal";
@@ -178,7 +163,6 @@ public class PropertyPlaceholderConfigurerTests {
ppc.postProcessBeanFactory(bf);
System.setProperty(P2, P2_SYSTEM_PROPS_VAL);
getModifiableSystemEnvironment().put(P2, P2_SYSTEM_ENV_VAL);
Properties ppc2Properties = new Properties();
ppc2Properties.put(P2, P2_LOCAL_PROPS_VAL);
@@ -198,7 +182,6 @@ public class PropertyPlaceholderConfigurerTests {
assertThat(p2Bean.getCountry(), equalTo(P2_SYSTEM_PROPS_VAL));
System.clearProperty(P2);
getModifiableSystemEnvironment().remove(P2);
}
@Test
@@ -228,100 +211,41 @@ public class PropertyPlaceholderConfigurerTests {
public void nullValueIsPreserved() {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setNullValue("customNull");
getModifiableSystemEnvironment().put("my.name", "customNull");
System.setProperty("my.name", "customNull");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean", rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${my.name}")
.getBeanDefinition());
ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), nullValue());
getModifiableSystemEnvironment().remove("my.name");
System.clearProperty("my.name");
}
@Test
public void trimValuesIsOffByDefault() {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
getModifiableSystemEnvironment().put("my.name", " myValue ");
System.setProperty("my.name", " myValue ");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean", rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${my.name}")
.getBeanDefinition());
ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), equalTo(" myValue "));
getModifiableSystemEnvironment().remove("my.name");
System.clearProperty("my.name");
}
@Test
public void trimValuesIsApplied() {
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setTrimValues(true);
getModifiableSystemEnvironment().put("my.name", " myValue ");
System.setProperty("my.name", " myValue ");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("testBean", rootBeanDefinition(TestBean.class)
.addPropertyValue("name", "${my.name}")
.getBeanDefinition());
ppc.postProcessBeanFactory(bf);
assertThat(bf.getBean(TestBean.class).getName(), equalTo("myValue"));
getModifiableSystemEnvironment().remove("my.name");
System.clearProperty("my.name");
}
@SuppressWarnings("unchecked")
private static Map<String, String> getModifiableSystemEnvironment() {
// for os x / linux
Class<?>[] classes = Collections.class.getDeclaredClasses();
Map<String, String> env = System.getenv();
for (Class<?> cl : classes) {
if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
try {
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
Object obj = field.get(env);
if (obj != null && obj.getClass().getName().equals("java.lang.ProcessEnvironment$StringEnvironment")) {
return (Map<String, String>) obj;
}
}
catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
// for windows
Class<?> processEnvironmentClass;
try {
processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
}
catch (Exception ex) {
throw new RuntimeException(ex);
}
try {
Field theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment");
theCaseInsensitiveEnvironmentField.setAccessible(true);
Object obj = theCaseInsensitiveEnvironmentField.get(null);
return (Map<String, String>) obj;
}
catch (NoSuchFieldException ex) {
// do nothing
}
catch (Exception ex) {
throw new RuntimeException(ex);
}
try {
Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment");
theEnvironmentField.setAccessible(true);
Object obj = theEnvironmentField.get(null);
return (Map<String, String>) obj;
}
catch (NoSuchFieldException ex) {
// do nothing
}
catch (Exception ex) {
throw new RuntimeException(ex);
}
throw new IllegalStateException();
}
}