Skip to content

Commit

Permalink
Refine CachedIntrospectionResults property introspection
Browse files Browse the repository at this point in the history
Closes gh-28445
  • Loading branch information
jhoeller committed May 11, 2022
1 parent 159a99b commit 50177b1
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.Collections;
import java.util.LinkedHashMap;
Expand Down Expand Up @@ -287,10 +288,12 @@ private CachedIntrospectionResults(Class<?> beanClass) throws BeansException {
// Only allow all name variants of Class properties
continue;
}
if (pd.getWriteMethod() == null && pd.getPropertyType() != null &&
(ClassLoader.class.isAssignableFrom(pd.getPropertyType()) ||
ProtectionDomain.class.isAssignableFrom(pd.getPropertyType()))) {
// Ignore ClassLoader and ProtectionDomain read-only properties - no need to bind to those
if (URL.class == beanClass && "content".equals(pd.getName())) {
// Only allow URL attribute introspection, not content resolution
continue;
}
if (pd.getWriteMethod() == null && isInvalidReadOnlyPropertyType(pd.getPropertyType())) {
// Ignore read-only properties such as ClassLoader - no need to bind to those
continue;
}
if (logger.isTraceEnabled()) {
Expand Down Expand Up @@ -328,10 +331,8 @@ private void introspectInterfaces(Class<?> beanClass, Class<?> currClass) throws
// GenericTypeAwarePropertyDescriptor leniently resolves a set* write method
// against a declared read method, so we prefer read method descriptors here.
pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
if (pd.getWriteMethod() == null && pd.getPropertyType() != null &&
(ClassLoader.class.isAssignableFrom(pd.getPropertyType()) ||
ProtectionDomain.class.isAssignableFrom(pd.getPropertyType()))) {
// Ignore ClassLoader and ProtectionDomain read-only properties - no need to bind to those
if (pd.getWriteMethod() == null && isInvalidReadOnlyPropertyType(pd.getPropertyType())) {
// Ignore read-only properties such as ClassLoader - no need to bind to those
continue;
}
this.propertyDescriptors.put(pd.getName(), pd);
Expand All @@ -342,6 +343,12 @@ private void introspectInterfaces(Class<?> beanClass, Class<?> currClass) throws
}
}

private boolean isInvalidReadOnlyPropertyType(@Nullable Class<?> returnType) {
return (returnType != null && (AutoCloseable.class.isAssignableFrom(returnType) ||
ClassLoader.class.isAssignableFrom(returnType) ||
ProtectionDomain.class.isAssignableFrom(returnType)));
}


BeanInfo getBeanInfo() {
return this.beanInfo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.core.OverridingClassLoader;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.UrlResource;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
Expand Down Expand Up @@ -152,7 +153,7 @@ public void setPropertyTypeMismatch() {
}

@Test
public void propertyDescriptors() {
public void propertyDescriptors() throws Exception {
TestBean target = new TestBean();
target.setSpouse(new TestBean());
BeanWrapper accessor = createAccessor(target);
Expand Down Expand Up @@ -181,11 +182,29 @@ public void propertyDescriptors() {
assertThat(accessor.isReadableProperty("class.package")).isFalse();
assertThat(accessor.isReadableProperty("class.module")).isFalse();
assertThat(accessor.isReadableProperty("class.classLoader")).isFalse();
assertThat(accessor.isReadableProperty("class.name")).isTrue();
assertThat(accessor.isReadableProperty("class.simpleName")).isTrue();
assertThat(accessor.isReadableProperty("classLoader")).isTrue();
assertThat(accessor.isWritableProperty("classLoader")).isTrue();
OverridingClassLoader ocl = new OverridingClassLoader(getClass().getClassLoader());
accessor.setPropertyValue("classLoader", ocl);
assertThat(accessor.getPropertyValue("classLoader")).isSameAs(ocl);

accessor = createAccessor(new UrlResource("https://spring.io"));

assertThat(accessor.isReadableProperty("class.package")).isFalse();
assertThat(accessor.isReadableProperty("class.module")).isFalse();
assertThat(accessor.isReadableProperty("class.classLoader")).isFalse();
assertThat(accessor.isReadableProperty("class.name")).isTrue();
assertThat(accessor.isReadableProperty("class.simpleName")).isTrue();
assertThat(accessor.isReadableProperty("URL.protocol")).isTrue();
assertThat(accessor.isReadableProperty("URL.host")).isTrue();
assertThat(accessor.isReadableProperty("URL.port")).isTrue();
assertThat(accessor.isReadableProperty("URL.file")).isTrue();
assertThat(accessor.isReadableProperty("URL.content")).isFalse();
assertThat(accessor.isReadableProperty("inputStream")).isFalse();
assertThat(accessor.isReadableProperty("filename")).isTrue();
assertThat(accessor.isReadableProperty("description")).isTrue();
}

@Test
Expand Down

0 comments on commit 50177b1

Please sign in to comment.