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.Properties;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
|
||||||
public final class ReflectionUtil {
|
public final class ReflectionUtil {
|
||||||
private static final Log log = LogFactory.getLog(ReflectionUtil.class);
|
private static final Log log = LogFactory.getLog(ReflectionUtil.class);
|
||||||
|
@ -47,7 +46,7 @@ public final class ReflectionUtil {
|
||||||
StringTokenizer tokenizer = new StringTokenizer(key, ".");
|
StringTokenizer tokenizer = new StringTokenizer(key, ".");
|
||||||
int tokenCount = tokenizer.countTokens();
|
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++) {
|
for (int j=0; j<tokenCount-1; j++) {
|
||||||
// Find getter method first
|
// Find getter method first
|
||||||
String name = tokenizer.nextToken();
|
String name = tokenizer.nextToken();
|
||||||
|
@ -67,43 +66,46 @@ public final class ReflectionUtil {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine data type of property
|
// Find setter method
|
||||||
Class propertyType = getField(targetClass, property).getType();
|
Method setterMethod = findSetterMethod(targetClass, property);
|
||||||
|
|
||||||
// Get setter method
|
// Get the first parameter type. This assumes that there is only one parameter.
|
||||||
String setterMethod = "set" + property.substring(0,1).toUpperCase() + property.substring(1);
|
if (setterMethod == null) {
|
||||||
|
throw new IllegalAccessException("Unable to find appropriate setter method signature for property: " + property);
|
||||||
|
}
|
||||||
|
Class paramType = setterMethod.getParameterTypes()[0];
|
||||||
|
|
||||||
// Set primitive type
|
// Set primitive type
|
||||||
debugInfo += ("." + setterMethod + "(" + propertyType.getName() + ": " + val + ")");
|
debugInfo += ("." + setterMethod + "(" + paramType.getName() + ": " + val + ")");
|
||||||
if (propertyType.isPrimitive()) {
|
if (paramType.isPrimitive()) {
|
||||||
if (propertyType == Boolean.TYPE) {
|
if (paramType == Boolean.TYPE) {
|
||||||
targetClass.getMethod(setterMethod, new Class[] {boolean.class}).invoke(target, new Object[] {Boolean.valueOf(val)});
|
setterMethod.invoke(target, new Object[] {Boolean.valueOf(val)});
|
||||||
} else if (propertyType == Integer.TYPE) {
|
} else if (paramType == Integer.TYPE) {
|
||||||
targetClass.getMethod(setterMethod, new Class[] {int.class}).invoke(target, new Object[] {Integer.valueOf(val)});
|
setterMethod.invoke(target, new Object[] {Integer.valueOf(val)});
|
||||||
} else if (propertyType == Long.TYPE) {
|
} else if (paramType == Long.TYPE) {
|
||||||
targetClass.getMethod(setterMethod, new Class[] {long.class}).invoke(target, new Object[] {Long.valueOf(val)});
|
setterMethod.invoke(target, new Object[] {Long.valueOf(val)});
|
||||||
} else if (propertyType == Double.TYPE) {
|
} else if (paramType == Double.TYPE) {
|
||||||
targetClass.getMethod(setterMethod, new Class[] {double.class}).invoke(target, new Object[] {Double.valueOf(val)});
|
setterMethod.invoke(target, new Object[] {Double.valueOf(val)});
|
||||||
} else if (propertyType == Float.TYPE) {
|
} else if (paramType == Float.TYPE) {
|
||||||
targetClass.getMethod(setterMethod, new Class[] {float.class}).invoke(target, new Object[] {Float.valueOf(val)});
|
setterMethod.invoke(target, new Object[] {Float.valueOf(val)});
|
||||||
} else if (propertyType == Short.TYPE) {
|
} else if (paramType == Short.TYPE) {
|
||||||
targetClass.getMethod(setterMethod, new Class[] {short.class}).invoke(target, new Object[] {Short.valueOf(val)});
|
setterMethod.invoke(target, new Object[] {Short.valueOf(val)});
|
||||||
} else if (propertyType == Byte.TYPE) {
|
} else if (paramType == Byte.TYPE) {
|
||||||
targetClass.getMethod(setterMethod, new Class[] {byte.class}).invoke(target, new Object[] {Byte.valueOf(val)});
|
setterMethod.invoke(target, new Object[] {Byte.valueOf(val)});
|
||||||
} else if (propertyType == Character.TYPE) {
|
} else if (paramType == Character.TYPE) {
|
||||||
targetClass.getMethod(setterMethod, new Class[] {char.class}).invoke(target, new Object[] {new Character(val.charAt(0))});
|
setterMethod.invoke(target, new Object[] {new Character(val.charAt(0))});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Set String type
|
// Set String type
|
||||||
if (propertyType == String.class) {
|
if (paramType == String.class) {
|
||||||
targetClass.getMethod(setterMethod, new Class[] {String.class}).invoke(target, new Object[] {val});
|
setterMethod.invoke(target, new Object[] {val});
|
||||||
|
|
||||||
// For unknown object type, try to call the valueOf method of the object
|
// For unknown object type, try to create an instance of the object using a String constructor
|
||||||
// to convert the string to the target object type
|
|
||||||
} else {
|
} else {
|
||||||
// Note valueOf method should be public and static
|
Constructor c = paramType.getConstructor(new Class[] {String.class});
|
||||||
Object param = propertyType.getMethod("valueOf", new Class[] {String.class}).invoke(null, new Object[] {val});
|
Object paramObject = c.newInstance(new Object[] {val});
|
||||||
targetClass.getMethod(setterMethod, new Class[] {propertyType}).invoke(target, new Object[] {param});
|
|
||||||
|
setterMethod.invoke(target, new Object[] {paramObject});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.debug(debugInfo);
|
log.debug(debugInfo);
|
||||||
|
@ -142,26 +144,31 @@ public final class ReflectionUtil {
|
||||||
return new Properties();
|
return new Properties();
|
||||||
} else {
|
} else {
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
Field[] fields = getAllFields(targetClass);
|
Method[] getterMethods = findAllGetterMethods(targetClass);
|
||||||
Method getterMethod;
|
for (int i=0; i<getterMethods.length; i++) {
|
||||||
for (int i=0; i<fields.length; i++) {
|
|
||||||
try {
|
try {
|
||||||
if ((getterMethod = isPropertyField(targetClass, fields[i])) != null) {
|
String propertyName = getPropertyName(getterMethods[i].getName());
|
||||||
if (fields[i].getType().isPrimitive() || fields[i].getType() == String.class) {
|
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;
|
Object val = null;
|
||||||
try {
|
try {
|
||||||
val = getterMethod.invoke(targetObject, null);
|
val = getterMethods[i].invoke(targetObject, null);
|
||||||
} catch (InvocationTargetException e) {
|
} catch (InvocationTargetException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
props.setProperty(prefix + fields[i].getName(), val + "");
|
props.setProperty(prefix + propertyName, val + "");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
Object val = getterMethod.invoke(targetObject, null);
|
Object val = getterMethods[i].invoke(targetObject, null);
|
||||||
if (val != null) {
|
if (val != null) {
|
||||||
props.putAll(retrieveClassProperties(fields[i].getName() + ".", val.getClass(), val));
|
props.putAll(retrieveClassProperties(propertyName + ".", val.getClass(), val));
|
||||||
}
|
}
|
||||||
} catch (InvocationTargetException e) {
|
} catch (InvocationTargetException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -169,7 +176,6 @@ public final class ReflectionUtil {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
// Let's catch any exception, cause this could be cause by the foreign class
|
// Let's catch any exception, cause this could be cause by the foreign class
|
||||||
t.printStackTrace();
|
t.printStackTrace();
|
||||||
|
@ -179,48 +185,91 @@ public final class ReflectionUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static Method isPropertyField(Class targetClass, Field targetField) {
|
private static Method findSetterMethod(Class targetClass, String propertyName) {
|
||||||
String fieldName = targetField.getName();
|
String methodName = "set" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
|
||||||
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);
|
|
||||||
|
|
||||||
// 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 {
|
try {
|
||||||
targetClass.getMethod(setMethod, new Class[]{targetField.getType()});
|
if (paramType[0].getConstructor(new Class[] {String.class}) != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
return null;
|
// Do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check getter method and return it if it exists
|
private static String getPropertyName(String methodName) {
|
||||||
try {
|
String name;
|
||||||
return targetClass.getMethod(getMethod, null);
|
if (methodName.startsWith("get")) {
|
||||||
} catch (NoSuchMethodException e1) {
|
name = methodName.substring(3);
|
||||||
try {
|
} else if (methodName.startsWith("set")) {
|
||||||
return targetClass.getMethod(isMethod, null);
|
name = methodName.substring(3);
|
||||||
} catch (NoSuchMethodException e2) {
|
} else if (methodName.startsWith("is")) {
|
||||||
return null;
|
name = methodName.substring(2);
|
||||||
}
|
} else {
|
||||||
}
|
name = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Field getField(Class targetClass, String fieldName) throws NoSuchFieldException {
|
return name.substring(0,1).toLowerCase() + name.substring(1);
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,6 @@ public abstract class ClassLoaderSPIConnectionFactory implements SPIConnectionFa
|
||||||
try {
|
try {
|
||||||
File f = new File(dir);
|
File f = new File(dir);
|
||||||
dir = f.getAbsolutePath();
|
dir = f.getAbsolutePath();
|
||||||
System.out.println(dir);
|
|
||||||
urls.add(f.toURL());
|
urls.add(f.toURL());
|
||||||
|
|
||||||
File[] files = f.listFiles();
|
File[] files = f.listFiles();
|
||||||
|
@ -71,7 +70,7 @@ public abstract class ClassLoaderSPIConnectionFactory implements SPIConnectionFa
|
||||||
|
|
||||||
URL u[] = new URL[urls.size()];
|
URL u[] = new URL[urls.size()];
|
||||||
urls.toArray(u);
|
urls.toArray(u);
|
||||||
return new URLClassLoader(u, ClassLoaderSPIConnectionFactory.class.getClassLoader());
|
return new URLClassLoader(u, Thread.currentThread().getContextClassLoader());
|
||||||
}
|
}
|
||||||
return ClassLoaderSPIConnectionFactory.class.getClassLoader();
|
return ClassLoaderSPIConnectionFactory.class.getClassLoader();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,11 @@ package org.apache.activemq.tool;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
import org.apache.activemq.tool.properties.ReflectionUtil;
|
import org.apache.activemq.tool.properties.ReflectionUtil;
|
||||||
|
|
||||||
public class ReflectionUtilTest extends TestCase {
|
public class ReflectionUtilTest extends TestCase {
|
||||||
private ReflectionUtilTest testData;
|
|
||||||
private String data;
|
|
||||||
|
|
||||||
public void testDataTypeConfig() {
|
public void testDataTypeConfig() {
|
||||||
TestClass3 targetObj = new TestClass3();
|
TestClass3 targetObj = new TestClass3();
|
||||||
|
@ -67,11 +66,11 @@ public class ReflectionUtilTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testValueOfMethod() {
|
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() {
|
public void testGetProperties() {
|
||||||
|
@ -100,15 +99,6 @@ public class ReflectionUtilTest extends TestCase {
|
||||||
targetObj.setTestData(testData);
|
targetObj.setTestData(testData);
|
||||||
|
|
||||||
Properties p = ReflectionUtil.retrieveObjectProperties(targetObj);
|
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("true", p.getProperty("booleanData"));
|
||||||
assertEquals("10", p.getProperty("byteData"));
|
assertEquals("10", p.getProperty("byteData"));
|
||||||
assertEquals("D", p.getProperty("charData"));
|
assertEquals("D", p.getProperty("charData"));
|
||||||
|
@ -118,6 +108,16 @@ public class ReflectionUtilTest extends TestCase {
|
||||||
assertEquals("1234567890", p.getProperty("longData"));
|
assertEquals("1234567890", p.getProperty("longData"));
|
||||||
assertEquals("1234", p.getProperty("shortData"));
|
assertEquals("1234", p.getProperty("shortData"));
|
||||||
assertEquals("Test.FOO.BAR", p.getProperty("stringData"));
|
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() {
|
public void testNestedConfig() {
|
||||||
|
@ -147,28 +147,6 @@ public class ReflectionUtilTest extends TestCase {
|
||||||
assertEquals("t5", t5.getStringData());
|
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 {
|
public class TestClass1 {
|
||||||
private boolean booleanData;
|
private boolean booleanData;
|
||||||
private int intData;
|
private int intData;
|
||||||
|
@ -267,4 +245,16 @@ public class ReflectionUtilTest extends TestCase {
|
||||||
this.testData = testData;
|
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