org.apache.commons.beanutils.BeanIntrospectionData Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.beanutils;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
*
* An internally used helper class for storing introspection information about a bean
* class.
*
*
* This class is used by {@link PropertyUtilsBean}. When accessing bean properties via
* reflection information about the properties available and their types and access
* methods must be present. {@code PropertyUtilsBean} stores this information in a cache
* so that it can be accessed quickly. The cache stores instances of this class.
*
*
* This class mainly stores information about the properties of a bean class. Per default,
* this is contained in {@code PropertyDescriptor} objects. Some additional information
* required by the {@code BeanUtils} library is also stored here.
*
*
* @version $Id$
* @since 1.9.1
*/
class BeanIntrospectionData {
/** An array with property descriptors for the managed bean class. */
private final PropertyDescriptor[] descriptors;
/** A map for remembering the write method names for properties. */
private final Map writeMethodNames;
/**
* Creates a new instance of {@code BeanIntrospectionData} and initializes its
* completely.
*
* @param descs the array with the descriptors of the available properties
*/
public BeanIntrospectionData(final PropertyDescriptor[] descs) {
this(descs, setUpWriteMethodNames(descs));
}
/**
* Creates a new instance of {@code BeanIntrospectionData} and allows setting the map
* with write method names. This constructor is mainly used for testing purposes.
*
* @param descs the array with the descriptors of the available properties
* @param writeMethNames the map with the names of write methods
*/
BeanIntrospectionData(final PropertyDescriptor[] descs, final Map writeMethNames) {
descriptors = descs;
writeMethodNames = writeMethNames;
}
/**
* Returns the array with property descriptors.
*
* @return the property descriptors for the associated bean class
*/
public PropertyDescriptor[] getDescriptors() {
return descriptors;
}
/**
* Returns the {@code PropertyDescriptor} for the property with the specified name. If
* this property is unknown, result is null.
*
* @param name the name of the property in question
* @return the {@code PropertyDescriptor} for this property or null
*/
public PropertyDescriptor getDescriptor(final String name) {
for (final PropertyDescriptor pd : getDescriptors()) {
if (name.equals(pd.getName())) {
return pd;
}
}
return null;
}
/**
* Returns the write method for the property determined by the given
* {@code PropertyDescriptor}. This information is normally available in the
* descriptor object itself. However, at least by the ORACLE implementation, the
* method is stored as a {@code SoftReference}. If this reference has been freed by
* the GC, it may be the case that the method cannot be obtained again. Then,
* additional information stored in this object is necessary to obtain the method
* again.
*
* @param beanCls the class of the affected bean
* @param desc the {@code PropertyDescriptor} of the desired property
* @return the write method for this property or null if there is none
*/
public Method getWriteMethod(final Class> beanCls, final PropertyDescriptor desc) {
Method method = desc.getWriteMethod();
if (method == null) {
final String methodName = writeMethodNames.get(desc.getName());
if (methodName != null) {
method = MethodUtils.getAccessibleMethod(beanCls, methodName,
desc.getPropertyType());
if (method != null) {
try {
desc.setWriteMethod(method);
} catch (final IntrospectionException e) {
// ignore, in this case the method is not cached
}
}
}
}
return method;
}
/**
* Initializes the map with the names of the write methods for the supported
* properties. The method names - if defined - need to be stored separately because
* they may get lost when the GC claims soft references used by the
* {@code PropertyDescriptor} objects.
*
* @param descs the array with the descriptors of the available properties
* @return the map with the names of write methods for properties
*/
private static Map setUpWriteMethodNames(final PropertyDescriptor[] descs) {
final Map methods = new HashMap();
for (final PropertyDescriptor pd : descs) {
final Method method = pd.getWriteMethod();
if (method != null) {
methods.put(pd.getName(), method.getName());
}
}
return methods;
}
}