Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ private DefaultBeanIntrospector() {
public void introspect(final IntrospectionContext icontext) {
BeanInfo beanInfo = null;
try {
beanInfo = Introspector.getBeanInfo(icontext.getTargetClass());
beanInfo = Introspector.getBeanInfo(icontext.getTargetClass(), icontext.getStopClass());
} catch (final IntrospectionException e) {
// no descriptors are added to the context
log.error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
class DefaultIntrospectionContext implements IntrospectionContext {
/** The current class for introspection. */
private final Class<?> currentClass;
/** The stop class for introspection. */
private final Class<?> stopClass;

/** A map for storing the already added property descriptors. */
private final Map<String, PropertyDescriptor> descriptors;
Expand All @@ -49,7 +51,20 @@ class DefaultIntrospectionContext implements IntrospectionContext {
* @param cls the current class
*/
public DefaultIntrospectionContext(final Class<?> cls) {
this(cls, null);
}

/**
*
* Creates a new instance of {@code DefaultIntrospectionContext} and sets
* the current class for introspection.
*
* @param cls the current class
* @param stopCls the stop class
*/
public DefaultIntrospectionContext(final Class<?> cls, final Class<?> stopCls) {
currentClass = cls;
stopClass = stopCls;
descriptors = new HashMap<>();
}

Expand All @@ -58,6 +73,11 @@ public Class<?> getTargetClass() {
return currentClass;
}

@Override
public Class<?> getStopClass() {
return stopClass;
}

@Override
public void addPropertyDescriptor(final PropertyDescriptor desc) {
if (desc == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ public interface IntrospectionContext {
*/
Class<?> getTargetClass();

/**
* The baseclass at which to stop the analysis.
* Any methods/properties/events in the stopClass or in its baseclasses will be ignored in the analysis.
*
* @return the stop class
*/
Class<?> getStopClass();

/**
* Adds the given property descriptor to this context. This method is called
* by a {@code BeanIntrospector} during introspection for each detected
Expand Down
47 changes: 40 additions & 7 deletions src/main/java/org/apache/commons/beanutils2/PropertyUtilsBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,18 @@ protected static PropertyUtilsBean getInstance() {

/** Base constructor */
public PropertyUtilsBean() {
this(new CopyOnWriteArrayList<>());
resetBeanIntrospectors();
}

public PropertyUtilsBean(List<BeanIntrospector> introspectors) {
descriptorsCache = new WeakFastHashMap<>();
descriptorsCache.setFast(true);
mappedDescriptorsCache = new WeakFastHashMap<>();
mappedDescriptorsCache.setFast(true);
introspectors = new CopyOnWriteArrayList<>();
resetBeanIntrospectors();
this.introspectors = new CopyOnWriteArrayList<>(introspectors);
}



/**
* Gets the configured {@link Resolver} implementation used by BeanUtils.
* <p>
Expand Down Expand Up @@ -968,6 +970,24 @@ public PropertyDescriptor getPropertyDescriptor(Object bean,

}

/**
* <p>Retrieve the property descriptors for the specified class,
* introspecting and caching them the first time a particular bean class
* is encountered.</p>
*
* <p><strong>FIXME</strong> - Does not work with DynaBeans.</p>
*
* @param beanClass Bean class for which property descriptors are requested
* @return the property descriptors
*
* @throws IllegalArgumentException if {@code beanClass} is null
*/
public PropertyDescriptor[] getPropertyDescriptors(final Class<?> beanClass, final Class<?> stopClass) {

return getIntrospectionData(beanClass, stopClass).getDescriptors();

}

/**
* <p>Retrieve the property descriptors for the specified bean,
* introspecting and caching them the first time a particular bean class
Expand Down Expand Up @@ -2107,14 +2127,27 @@ private Object invokeMethod(
* @throws IllegalArgumentException if the bean class is <b>null</b>
*/
private BeanIntrospectionData getIntrospectionData(final Class<?> beanClass) {
return getIntrospectionData(beanClass, null);
}

/**
* Obtains the {@code BeanIntrospectionData} object describing the specified bean
* class. This object is looked up in the internal cache. If necessary, introspection
* is performed now on the affected bean class, and the results object is created.
*
* @param beanClass the bean class in question
* @return the {@code BeanIntrospectionData} object for this class
* @throws IllegalArgumentException if the bean class is <b>null</b>
*/
private BeanIntrospectionData getIntrospectionData(final Class<?> beanClass, final Class<?> stopClass) {
if (beanClass == null) {
throw new IllegalArgumentException("No bean class specified");
}

// Look up any cached information for this bean class
BeanIntrospectionData data = descriptorsCache.get(beanClass);
if (data == null) {
data = fetchIntrospectionData(beanClass);
data = fetchIntrospectionData(beanClass, stopClass);
descriptorsCache.put(beanClass, data);
}

Expand All @@ -2128,8 +2161,8 @@ private BeanIntrospectionData getIntrospectionData(final Class<?> beanClass) {
* @param beanClass the class to be inspected
* @return a data object with the results of introspection
*/
private BeanIntrospectionData fetchIntrospectionData(final Class<?> beanClass) {
final DefaultIntrospectionContext ictx = new DefaultIntrospectionContext(beanClass);
private BeanIntrospectionData fetchIntrospectionData(final Class<?> beanClass, final Class<?> stopClass) {
final DefaultIntrospectionContext ictx = new DefaultIntrospectionContext(beanClass, stopClass);

for (final BeanIntrospector bi : introspectors) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ public Class<?> getTargetClass() {
throw new UnsupportedOperationException("Unexpected method call!");
}

@Override
public Class<?> getStopClass() {
throw new UnsupportedOperationException("Unexpected method call!");
}

@Override
public void addPropertyDescriptor(final PropertyDescriptor desc) {
throw new UnsupportedOperationException("Unexpected method call!");
Expand Down