mirror of https://github.com/apache/activemq.git
Modify the reflection utility to be able to recognize property of type object and setter with string param.
git-svn-id: https://svn.apache.org/repos/asf/incubator/activemq/trunk@417699 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
faff4999f4
commit
0dbcc1f4af
|
@ -23,10 +23,9 @@ import java.util.StringTokenizer;
|
|||
import java.util.Properties;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
public final class ReflectionUtil {
|
||||
private static final Log log = LogFactory.getLog(ReflectionUtil.class);
|
||||
|
@ -47,7 +46,7 @@ public final class ReflectionUtil {
|
|||
StringTokenizer tokenizer = new StringTokenizer(key, ".");
|
||||
int tokenCount = tokenizer.countTokens();
|
||||
|
||||
// For nested settings, get the object first. -2, do not count the first and last token
|
||||
// For nested settings, get the object first. -1, do not count the last token
|
||||
for (int j=0; j<tokenCount-1; j++) {
|
||||
// Find getter method first
|
||||
String name = tokenizer.nextToken();
|
||||
|
@ -67,43 +66,46 @@ public final class ReflectionUtil {
|
|||
return;
|
||||
}
|
||||
|
||||
// Determine data type of property
|
||||
Class propertyType = getField(targetClass, property).getType();
|
||||
// Find setter method
|
||||
Method setterMethod = findSetterMethod(targetClass, property);
|
||||
|
||||
// Get setter method
|
||||
String setterMethod = "set" + property.substring(0,1).toUpperCase() + property.substring(1);
|
||||
// Get the first parameter type. This assumes that there is only one parameter.
|
||||
if (setterMethod == null) {
|
||||
throw new IllegalAccessException("Unable to find appropriate setter method signature for property: " + property);
|
||||
}
|
||||
Class paramType = setterMethod.getParameterTypes()[0];
|
||||
|
||||
// Set primitive type
|
||||
debugInfo += ("." + setterMethod + "(" + propertyType.getName() + ": " + val + ")");
|
||||
if (propertyType.isPrimitive()) {
|
||||
if (propertyType == Boolean.TYPE) {
|
||||
targetClass.getMethod(setterMethod, new Class[] {boolean.class}).invoke(target, new Object[] {Boolean.valueOf(val)});
|
||||
} else if (propertyType == Integer.TYPE) {
|
||||
targetClass.getMethod(setterMethod, new Class[] {int.class}).invoke(target, new Object[] {Integer.valueOf(val)});
|
||||
} else if (propertyType == Long.TYPE) {
|
||||
targetClass.getMethod(setterMethod, new Class[] {long.class}).invoke(target, new Object[] {Long.valueOf(val)});
|
||||
} else if (propertyType == Double.TYPE) {
|
||||
targetClass.getMethod(setterMethod, new Class[] {double.class}).invoke(target, new Object[] {Double.valueOf(val)});
|
||||
} else if (propertyType == Float.TYPE) {
|
||||
targetClass.getMethod(setterMethod, new Class[] {float.class}).invoke(target, new Object[] {Float.valueOf(val)});
|
||||
} else if (propertyType == Short.TYPE) {
|
||||
targetClass.getMethod(setterMethod, new Class[] {short.class}).invoke(target, new Object[] {Short.valueOf(val)});
|
||||
} else if (propertyType == Byte.TYPE) {
|
||||
targetClass.getMethod(setterMethod, new Class[] {byte.class}).invoke(target, new Object[] {Byte.valueOf(val)});
|
||||
} else if (propertyType == Character.TYPE) {
|
||||
targetClass.getMethod(setterMethod, new Class[] {char.class}).invoke(target, new Object[] {new Character(val.charAt(0))});
|
||||
debugInfo += ("." + setterMethod + "(" + paramType.getName() + ": " + val + ")");
|
||||
if (paramType.isPrimitive()) {
|
||||
if (paramType == Boolean.TYPE) {
|
||||
setterMethod.invoke(target, new Object[] {Boolean.valueOf(val)});
|
||||
} else if (paramType == Integer.TYPE) {
|
||||
setterMethod.invoke(target, new Object[] {Integer.valueOf(val)});
|
||||
} else if (paramType == Long.TYPE) {
|
||||
setterMethod.invoke(target, new Object[] {Long.valueOf(val)});
|
||||
} else if (paramType == Double.TYPE) {
|
||||
setterMethod.invoke(target, new Object[] {Double.valueOf(val)});
|
||||
} else if (paramType == Float.TYPE) {
|
||||
setterMethod.invoke(target, new Object[] {Float.valueOf(val)});
|
||||
} else if (paramType == Short.TYPE) {
|
||||
setterMethod.invoke(target, new Object[] {Short.valueOf(val)});
|
||||
} else if (paramType == Byte.TYPE) {
|
||||
setterMethod.invoke(target, new Object[] {Byte.valueOf(val)});
|
||||
} else if (paramType == Character.TYPE) {
|
||||
setterMethod.invoke(target, new Object[] {new Character(val.charAt(0))});
|
||||
}
|
||||
} else {
|
||||
// Set String type
|
||||
if (propertyType == String.class) {
|
||||
targetClass.getMethod(setterMethod, new Class[] {String.class}).invoke(target, new Object[] {val});
|
||||
if (paramType == String.class) {
|
||||
setterMethod.invoke(target, new Object[] {val});
|
||||
|
||||
// For unknown object type, try to call the valueOf method of the object
|
||||
// to convert the string to the target object type
|
||||
// For unknown object type, try to create an instance of the object using a String constructor
|
||||
} else {
|
||||
// Note valueOf method should be public and static
|
||||
Object param = propertyType.getMethod("valueOf", new Class[] {String.class}).invoke(null, new Object[] {val});
|
||||
targetClass.getMethod(setterMethod, new Class[] {propertyType}).invoke(target, new Object[] {param});
|
||||
Constructor c = paramType.getConstructor(new Class[] {String.class});
|
||||
Object paramObject = c.newInstance(new Object[] {val});
|
||||
|
||||
setterMethod.invoke(target, new Object[] {paramObject});
|
||||
}
|
||||
}
|
||||
log.debug(debugInfo);
|
||||
|
@ -142,26 +144,31 @@ public final class ReflectionUtil {
|
|||
return new Properties();
|
||||
} else {
|
||||
Properties props = new Properties();
|
||||
Field[] fields = getAllFields(targetClass);
|
||||
Method getterMethod;
|
||||
for (int i=0; i<fields.length; i++) {
|
||||
Method[] getterMethods = findAllGetterMethods(targetClass);
|
||||
for (int i=0; i<getterMethods.length; i++) {
|
||||
try {
|
||||
if ((getterMethod = isPropertyField(targetClass, fields[i])) != null) {
|
||||
if (fields[i].getType().isPrimitive() || fields[i].getType() == String.class) {
|
||||
String propertyName = getPropertyName(getterMethods[i].getName());
|
||||
Class retType = getterMethods[i].getReturnType();
|
||||
|
||||
// If primitive or string type, return it
|
||||
if (retType.isPrimitive() || retType == String.class) {
|
||||
// Check for an appropriate setter method to consider it as a property
|
||||
if (findSetterMethod(targetClass, propertyName) != null) {
|
||||
Object val = null;
|
||||
try {
|
||||
val = getterMethod.invoke(targetObject, null);
|
||||
val = getterMethods[i].invoke(targetObject, null);
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
props.setProperty(prefix + fields[i].getName(), val + "");
|
||||
props.setProperty(prefix + propertyName, val + "");
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
Object val = getterMethod.invoke(targetObject, null);
|
||||
Object val = getterMethods[i].invoke(targetObject, null);
|
||||
if (val != null) {
|
||||
props.putAll(retrieveClassProperties(fields[i].getName() + ".", val.getClass(), val));
|
||||
props.putAll(retrieveClassProperties(propertyName + ".", val.getClass(), val));
|
||||
}
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -169,7 +176,6 @@ public final class ReflectionUtil {
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
// Let's catch any exception, cause this could be cause by the foreign class
|
||||
t.printStackTrace();
|
||||
|
@ -179,48 +185,91 @@ public final class ReflectionUtil {
|
|||
}
|
||||
}
|
||||
|
||||
protected static Method isPropertyField(Class targetClass, Field targetField) {
|
||||
String fieldName = targetField.getName();
|
||||
String getMethod = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
|
||||
String isMethod = "is" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
|
||||
String setMethod = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
|
||||
private static Method findSetterMethod(Class targetClass, String propertyName) {
|
||||
String methodName = "set" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
|
||||
|
||||
// Check setter method
|
||||
Method[] methods = targetClass.getMethods();
|
||||
for (int i=0; i<methods.length; i++) {
|
||||
if (methods[i].getName().equals(methodName) && isSetterMethod(methods[i])) {
|
||||
return methods[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Method findGetterMethod(Class targetClass, String propertyName) {
|
||||
String methodName1 = "get" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
|
||||
String methodName2 = "is" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
|
||||
|
||||
Method[] methods = targetClass.getMethods();
|
||||
for (int i=0; i<methods.length; i++) {
|
||||
if ((methods[i].getName().equals(methodName1) || methods[i].getName().equals(methodName2)) && isGetterMethod(methods[i])) {
|
||||
return methods[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Method[] findAllGetterMethods(Class targetClass) {
|
||||
List getterMethods = new ArrayList();
|
||||
Method[] methods = targetClass.getMethods();
|
||||
|
||||
for (int i=0; i<methods.length; i++) {
|
||||
if (isGetterMethod(methods[i])) {
|
||||
getterMethods.add(methods[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return (Method[])getterMethods.toArray(new Method[] {});
|
||||
}
|
||||
|
||||
private static boolean isGetterMethod(Method method) {
|
||||
// Check method signature first
|
||||
// If 'get' method, must return a non-void value
|
||||
// If 'is' method, must return a boolean value
|
||||
// Both must have no parameters
|
||||
// Method must not belong to the Object class to prevent infinite loop
|
||||
return (((method.getName().startsWith("is") && method.getReturnType() == Boolean.TYPE) ||
|
||||
(method.getName().startsWith("get") && method.getReturnType() != Void.TYPE)) &&
|
||||
(method.getParameterTypes().length == 0) && method.getDeclaringClass() != Object.class);
|
||||
}
|
||||
|
||||
private static boolean isSetterMethod(Method method) {
|
||||
// Check method signature first
|
||||
if (method.getName().startsWith("set") && method.getReturnType() == Void.TYPE) {
|
||||
Class[] paramType = method.getParameterTypes();
|
||||
// Check that it can only accept one parameter
|
||||
if (paramType.length == 1) {
|
||||
// Check if parameter is a primitive or can accept a String parameter
|
||||
if (paramType[0].isPrimitive() || paramType[0] == String.class) {
|
||||
return true;
|
||||
} else {
|
||||
// Check if object can accept a string as a constructor
|
||||
try {
|
||||
targetClass.getMethod(setMethod, new Class[]{targetField.getType()});
|
||||
if (paramType[0].getConstructor(new Class[] {String.class}) != null) {
|
||||
return true;
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check getter method and return it if it exists
|
||||
try {
|
||||
return targetClass.getMethod(getMethod, null);
|
||||
} catch (NoSuchMethodException e1) {
|
||||
try {
|
||||
return targetClass.getMethod(isMethod, null);
|
||||
} catch (NoSuchMethodException e2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private static String getPropertyName(String methodName) {
|
||||
String name;
|
||||
if (methodName.startsWith("get")) {
|
||||
name = methodName.substring(3);
|
||||
} else if (methodName.startsWith("set")) {
|
||||
name = methodName.substring(3);
|
||||
} else if (methodName.startsWith("is")) {
|
||||
name = methodName.substring(2);
|
||||
} else {
|
||||
name = "";
|
||||
}
|
||||
|
||||
public static Field getField(Class targetClass, String fieldName) throws NoSuchFieldException {
|
||||
while (targetClass != null) {
|
||||
try {
|
||||
return targetClass.getDeclaredField(fieldName);
|
||||
} catch (NoSuchFieldException e) {
|
||||
targetClass = targetClass.getSuperclass();
|
||||
}
|
||||
}
|
||||
throw new NoSuchFieldException(fieldName);
|
||||
}
|
||||
|
||||
public static Field[] getAllFields(Class targetClass) {
|
||||
List fieldList = new ArrayList();
|
||||
while (targetClass != null) {
|
||||
fieldList.addAll(Arrays.asList(targetClass.getDeclaredFields()));
|
||||
targetClass = targetClass.getSuperclass();
|
||||
}
|
||||
return (Field[])fieldList.toArray(new Field[0]);
|
||||
return name.substring(0,1).toLowerCase() + name.substring(1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@ public abstract class ClassLoaderSPIConnectionFactory implements SPIConnectionFa
|
|||
try {
|
||||
File f = new File(dir);
|
||||
dir = f.getAbsolutePath();
|
||||
System.out.println(dir);
|
||||
urls.add(f.toURL());
|
||||
|
||||
File[] files = f.listFiles();
|
||||
|
@ -71,7 +70,7 @@ public abstract class ClassLoaderSPIConnectionFactory implements SPIConnectionFa
|
|||
|
||||
URL u[] = new URL[urls.size()];
|
||||
urls.toArray(u);
|
||||
return new URLClassLoader(u, ClassLoaderSPIConnectionFactory.class.getClassLoader());
|
||||
return new URLClassLoader(u, Thread.currentThread().getContextClassLoader());
|
||||
}
|
||||
return ClassLoaderSPIConnectionFactory.class.getClassLoader();
|
||||
}
|
||||
|
|
|
@ -19,12 +19,11 @@ package org.apache.activemq.tool;
|
|||
import junit.framework.TestCase;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.activemq.tool.properties.ReflectionUtil;
|
||||
|
||||
public class ReflectionUtilTest extends TestCase {
|
||||
private ReflectionUtilTest testData;
|
||||
private String data;
|
||||
|
||||
public void testDataTypeConfig() {
|
||||
TestClass3 targetObj = new TestClass3();
|
||||
|
@ -67,11 +66,11 @@ public class ReflectionUtilTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testValueOfMethod() {
|
||||
ReflectionUtilTest targetObj = new ReflectionUtilTest();
|
||||
TestClass4 targetObj = new TestClass4();
|
||||
|
||||
ReflectionUtil.configureClass(targetObj, "testData", "TEST.FOO.BAR");
|
||||
ReflectionUtil.configureClass(targetObj, "testFile", "TEST.FOO.BAR");
|
||||
|
||||
assertEquals("TEST.FOO.BAR", targetObj.testData.data);
|
||||
assertEquals("TEST.FOO.BAR", targetObj.testFile.toString());
|
||||
}
|
||||
|
||||
public void testGetProperties() {
|
||||
|
@ -100,15 +99,6 @@ public class ReflectionUtilTest extends TestCase {
|
|||
targetObj.setTestData(testData);
|
||||
|
||||
Properties p = ReflectionUtil.retrieveObjectProperties(targetObj);
|
||||
assertEquals("false", p.getProperty("testData.booleanData"));
|
||||
assertEquals("15", p.getProperty("testData.byteData"));
|
||||
assertEquals("G", p.getProperty("testData.charData"));
|
||||
assertEquals("765.43", p.getProperty("testData.doubleData"));
|
||||
assertEquals("543.21", p.getProperty("testData.floatData"));
|
||||
assertEquals("654321", p.getProperty("testData.intData"));
|
||||
assertEquals("987654321", p.getProperty("testData.longData"));
|
||||
assertEquals("4321", p.getProperty("testData.shortData"));
|
||||
assertEquals("BAR.TEST.FOO", p.getProperty("testData.stringData"));
|
||||
assertEquals("true", p.getProperty("booleanData"));
|
||||
assertEquals("10", p.getProperty("byteData"));
|
||||
assertEquals("D", p.getProperty("charData"));
|
||||
|
@ -118,6 +108,16 @@ public class ReflectionUtilTest extends TestCase {
|
|||
assertEquals("1234567890", p.getProperty("longData"));
|
||||
assertEquals("1234", p.getProperty("shortData"));
|
||||
assertEquals("Test.FOO.BAR", p.getProperty("stringData"));
|
||||
assertEquals("false", p.getProperty("testData.booleanData"));
|
||||
assertEquals("15", p.getProperty("testData.byteData"));
|
||||
assertEquals("G", p.getProperty("testData.charData"));
|
||||
assertEquals("765.43", p.getProperty("testData.doubleData"));
|
||||
assertEquals("543.21", p.getProperty("testData.floatData"));
|
||||
assertEquals("654321", p.getProperty("testData.intData"));
|
||||
assertEquals("987654321", p.getProperty("testData.longData"));
|
||||
assertEquals("4321", p.getProperty("testData.shortData"));
|
||||
assertEquals("BAR.TEST.FOO", p.getProperty("testData.stringData"));
|
||||
|
||||
}
|
||||
|
||||
public void testNestedConfig() {
|
||||
|
@ -147,28 +147,6 @@ public class ReflectionUtilTest extends TestCase {
|
|||
assertEquals("t5", t5.getStringData());
|
||||
}
|
||||
|
||||
public static ReflectionUtilTest valueOf(String data) {
|
||||
ReflectionUtilTest test = new ReflectionUtilTest();
|
||||
test.data = data;
|
||||
return test;
|
||||
}
|
||||
|
||||
public ReflectionUtilTest getTestData() {
|
||||
return testData;
|
||||
}
|
||||
|
||||
public void setTestData(ReflectionUtilTest testData) {
|
||||
this.testData = testData;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public class TestClass1 {
|
||||
private boolean booleanData;
|
||||
private int intData;
|
||||
|
@ -267,4 +245,16 @@ public class ReflectionUtilTest extends TestCase {
|
|||
this.testData = testData;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestClass4 {
|
||||
private File testFile;
|
||||
|
||||
public String getTestFile() {
|
||||
return testFile.toString();
|
||||
}
|
||||
|
||||
public void setTestFile(String testFile) {
|
||||
this.testFile = new File(testFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue