org.apache.commons.beanutils.IntrospectorUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of commons-beanutils Show documentation
Show all versions of commons-beanutils Show documentation
BeanUtils provides an easy-to-use but flexible wrapper around reflection and introspection.
/*
* 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.lang.reflect.Modifier;
/**
* An internal class used for working with {@link java.beans.Introspector}.
*/
class IntrospectorUtils {
private IntrospectorUtils() {
throw new UnsupportedOperationException("do not call");
}
/**
* Property descriptors may contain synthetic methods for the read and write method
* due to a bug in the java api. This is a workaround.
*
* if beanClass or descriptors this method will just return
*
*
* See:
*
* http://bugs.sun.com/view_bug.do?bug_id=6528714
* https://issues.apache.org/jira/browse/BEANUTILS-340
*
* @param descriptors the descriptors to set
* @param beanClass the class the descriptors are associated with
*/
static void setNonSyntheticReadWriteMethods(Class beanClass, PropertyDescriptor[] descriptors) throws NoSuchMethodException, IntrospectionException {
if (beanClass == null || descriptors == null) {
return;
}
for (int i = 0; i < descriptors.length; i++) {
if (descriptors[i] != null) {
final PropertyDescriptor descriptor = descriptors[i];
final Method read = descriptor.getReadMethod();
final Method write = descriptor.getWriteMethod();
Method newRead = read;
Method newWrite = write;
if (MethodUtils.isSynthetic(newRead) || MethodUtils.isBridge(newRead)) {
newRead = findReadMethodNonSynPreference(beanClass, newRead.getName());
if(newRead != null && newWrite == null) {
// If the read method changes here and there was no
// write method before check to see if there is a write
// method for the new return type
String setterName = "set" + descriptor.getName().substring(0, 1).toUpperCase() + descriptor.getName().substring(1);
try {
newWrite = beanClass.getMethod(setterName, new Class>[]{ newRead.getReturnType()});
} catch (NoSuchMethodException e) {
// If we hit an exception here we can ignore it
// because there is definitely no write method for
// this property
}
}
}
if (MethodUtils.isSynthetic(newWrite) || MethodUtils.isBridge(newWrite)) {
//use the read method's return type as the type for the write method.
//The PropertyDescriptor classes forces them to be the same type so this is ok
if (newRead != null) {
newWrite = beanClass.getMethod(newWrite.getName(), new Class[]{ newRead.getReturnType()});
} else {
//rare case where there is only a write - single arg overloading here would be non-deterministic
final Method searchedWrite = findWriteMethodNonSynPreference(beanClass, newWrite.getName());
if (searchedWrite != null) {
newWrite = searchedWrite;
}
}
}
if (newRead != read) {
descriptor.setReadMethod(newRead);
}
if (newWrite != write) {
descriptor.setWriteMethod(newWrite);
}
}
}
}
/**
* Searches all methods on a class looking for a write method that is not synthetic & visible. If found, that method
* is returned. If a non-synthetic, visible method is NOT found then the a visible synthetic method may be returned.
* @param beanClass the class to search
* @param methodName the write method name
* @return the method or null
*/
private static Method findWriteMethodNonSynPreference(Class beanClass, String methodName) {
return findMethodNonSynPreference(beanClass, methodName, 1);
}
/**
* Searches all methods on a class looking for a read method that is not synthetic & visible. If found, that method
* is returned. If a non-synthetic, visible method is NOT found then the a visible synthetic method may be returned.
* @param beanClass the class to search
* @param methodName the write method name
* @return the method or null
*/
private static Method findReadMethodNonSynPreference(Class beanClass, String methodName) {
return findMethodNonSynPreference(beanClass, methodName, 0);
}
/** searches for the method with a given name and number of args. */
private static Method findMethodNonSynPreference(Class beanClass, String methodName, int argNum) {
final Method[] methods = beanClass.getMethods();
Method fallback = null;
for (int i = 0; i < methods.length; i ++) {
final Method m = methods[i];
if (methodName.equals(m.getName()) && m.getParameterTypes().length == argNum && !isPrivate(m)) {
if (!MethodUtils.isSynthetic(m) && !MethodUtils.isBridge(m)) {
return m;
}
fallback = m;
}
}
return fallback;
}
/** is a method private? */
private static boolean isPrivate(Method m) {
return (m.getModifiers() & Modifier.PRIVATE) != 0;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy