/*
* Copyright 2005-2006 the original author or authors.
*
* Licensed 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.strecks.util;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.strecks.converter.BindableBean;
import org.strecks.converter.Converter;
import org.strecks.converter.DatePatternConverter;
import org.strecks.exceptions.ApplicationRuntimeException;
import org.strecks.util.impl.ArrayConverter;
import org.strecks.util.impl.ClassWithNoArgMethod;
import org.strecks.util.impl.ClassWithNullMethod;
import org.strecks.util.impl.ClassWithPrivateMethod;
import org.strecks.util.impl.ClassWithVoidMethod;
import org.strecks.util.impl.ClassWithWildcardTypes;
import org.strecks.util.impl.ComparableIntegerSubclass;
import org.strecks.util.impl.GenericClass;
import org.strecks.util.impl.JavaBean;
import org.strecks.util.impl.MapContainingList;
import org.strecks.util.impl.MyClass;
import org.strecks.util.impl.MyClass.AbstractClass;
import org.strecks.util.impl.MyClass.PublicClass;
import org.strecks.validator.internal.impl.BeanWithGetterValidator;
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* @author Phil Zoio
*/
public class TestReflectHelper
{
@Test(expectedExceptions=ApplicationRuntimeException.class)
public void testGetMethodWithArg() throws Exception
{
JavaBean bean = new JavaBean();
assert null != ReflectHelper.getMethod(bean, "setBooleanProperty");
}
@Test
public void testGetNoArgMethod() throws Exception
{
JavaBean bean = new JavaBean();
assert null != ReflectHelper.getMethod(bean, "isBooleanProperty");
}
@Test
public void testGetPropertyName() throws Exception
{
Assert.assertEquals(ReflectHelper.getPropertyName("setBooleanProperty"), "booleanProperty");
}
@Test
public void testGetGetterName() throws Exception
{
Assert.assertEquals(ReflectHelper.getPropertyName("setBooleanProperty"), "booleanProperty");
}
@Test
public void testGetSetter() throws Exception
{
Method getter = BeanWithGetterValidator.class.getMethod("getProperty");
Assert.assertEquals(ReflectHelper.getSetter(getter).getName(), "setProperty");
}
@Test
public void testCheckSetterMethodName() throws Exception
{
Method setter = BeanWithGetterValidator.class.getMethod("setProperty", new Class[]
{
String.class
});
Assert.assertEquals(ReflectHelper.checkSetterMethodName(setter), "setProperty");
}
@Test
public void testCheckInvalidSetterMethodName() throws Exception
{
Method setter = BeanWithGetterValidator.class.getMethod("getProperty");
try
{
ReflectHelper.checkSetterMethodName(setter);
}
catch (ApplicationRuntimeException e)
{
Assert
.assertEquals(
e.getMessage(),
"Method public java.lang.String org.strecks.validator.internal.impl.BeanWithGetterValidator.getProperty() "
+ "declared in class org.strecks.validator.internal.impl.BeanWithGetterValidator is not a setter method");
}
}
@Test
public void testParameterLength() throws Exception
{
Class c = MyClass.class;
Method method = c.getMethod("methodWithOneParam", new Class[]
{
String.class
});
ReflectHelper.checkParameterTypeLength(method, 1);
}
@Test(expectedExceptions=ApplicationRuntimeException.class)
public void testParameterLength2() throws Exception
{
Class c = MyClass.class;
Method method = c.getMethod("methodWithTwoParams", new Class[]
{
String.class, String.class
});
ReflectHelper.checkParameterTypeLength(method, 1);
}
@Test
public void testIsGetter() throws SecurityException, NoSuchMethodException
{
BindableBean bean = new BindableBean();
Class<? extends BindableBean> clazz = bean.getClass();
Method method = clazz.getMethod("isBoolValue");
assert ReflectHelper.isGetter(method);
method = clazz.getMethod("getBooleanValue");
assert ReflectHelper.isGetter(method);
method = clazz.getMethod("getDateValue");
assert ReflectHelper.isGetter(method);
}
@Test
public void testIsSetter() throws SecurityException, NoSuchMethodException
{
BindableBean bean = new BindableBean();
Class<? extends BindableBean> clazz = bean.getClass();
Method method = clazz.getMethod("setBoolValue", new Class[]
{
Boolean.TYPE
});
assert ReflectHelper.isSetter(method);
method = clazz.getMethod("setDateValue", new Class[]
{
String.class
});
assert ReflectHelper.isSetter(method);
}
@Test
public void testInvokeMethod1() throws Exception
{
ClassWithVoidMethod instance = new ClassWithVoidMethod();
ReflectHelper.invokeMethod(instance, "method");
Assert.assertEquals(instance.getInvokeCount(), 1);
}
@Test
public void testInvokeMethodNull() throws Exception
{
ClassWithVoidMethod instance = new ClassWithVoidMethod();
ReflectHelper.invokeMethod(instance, "method", Void.TYPE);
Assert.assertEquals(instance.getInvokeCount(), 1);
}
@Test
public void testInvokeReturnNull() throws Exception
{
ClassWithNullMethod instance = new ClassWithNullMethod();
assert null == ReflectHelper.invokeMethod(instance, "method", String.class);
Assert.assertEquals(instance.getInvokeCount(), 1);
}
@Test
public void testInvokeMethod2() throws Exception
{
ClassWithNoArgMethod instance = new ClassWithNoArgMethod();
Object invokeVoidMethod = ReflectHelper.invokeMethod(instance, "method");
Assert.assertEquals(invokeVoidMethod, "hello");
}
@Test
public void testInvokeMethodWithNullArg() throws Exception
{
ClassWithNoArgMethod instance = new ClassWithNoArgMethod();
Object invokeVoidMethod = ReflectHelper.invokeMethod(instance, "method", null);
Assert.assertEquals(invokeVoidMethod, "hello");
}
@Test
public void testInvokeMethodWithClassCheck() throws Exception
{
ClassWithNoArgMethod instance = new ClassWithNoArgMethod();
String invokeVoidMethod = ReflectHelper.invokeMethod(instance, "method", String.class);
Assert.assertEquals(invokeVoidMethod, "hello");
}
@Test
public void testInvokeMethodWithFailedClassCheck() throws Exception
{
try
{
ClassWithNoArgMethod instance = new ClassWithNoArgMethod();
Object invokeVoidMethod = ReflectHelper.invokeMethod(instance, "method", Integer.class);
Assert.assertEquals(invokeVoidMethod, "hello");
}
catch (ApplicationRuntimeException e)
{
Assert.assertEquals(e.getMessage(),
"Unable to cast result hello of method method() of class org.strecks.util.impl.ClassWithNoArgMethod "
+ "to return type class java.lang.Integer");
}
}
@Test
public void testInvokeNonexistentMethod() throws Exception
{
try
{
ClassWithNoArgMethod instance = new ClassWithNoArgMethod();
Object invokeVoidMethod = ReflectHelper.invokeMethod(instance, "nonexistent", String.class);
Assert.assertEquals(invokeVoidMethod, "hello");
}
catch (ApplicationRuntimeException e)
{
Assert.assertEquals(e.getMessage(),
"No method nonexistent() of class org.strecks.util.impl.ClassWithNoArgMethod");
}
}
@Test
public void testInvokePrivateMethod() throws Exception
{
try
{
ClassWithPrivateMethod instance = new ClassWithPrivateMethod();
Object invokeVoidMethod = ReflectHelper.invokeMethod(instance, "method", String.class);
Assert.assertEquals(invokeVoidMethod, "hello");
}
catch (ApplicationRuntimeException e)
{
Assert.assertEquals(e.getMessage(),
"No method method() of class org.strecks.util.impl.ClassWithPrivateMethod");
}
}
@Test
public void testNewInstance()
{
assert null != ReflectHelper.createInstance("org.strecks.util.impl.MyClass", MyClass.class);
assert null != ReflectHelper.createInstance("org.strecks.util.impl.MyClass$PublicClass", PublicClass.class);
}
@Test
public void testClassNotFound()
{
try
{
ReflectHelper.createInstance("org.strecks.util.impl.NoClassHere", null);
Assert.fail();
}
catch (ApplicationRuntimeException e)
{
Assert.assertEquals(e.getMessage(),
"Unable to create new instance of org.strecks.util.impl.NoClassHere as class cannot be located");
}
}
@Test
public void testPrivateClass()
{
try
{
assert null != ReflectHelper.createInstance("org.strecks.util.impl.MyClass$PrivateClass", null);
Assert.fail();
}
catch (ApplicationRuntimeException e)
{
Assert
.assertEquals(e.getMessage(),
"Illegal access in attempting to create instance of class org.strecks.util.impl.MyClass$PrivateClass");
}
}
@Test
public void testAbstractClass()
{
try
{
assert null != ReflectHelper.createInstance("org.strecks.util.impl.MyClass$AbstractClass",
AbstractClass.class);
Assert.fail();
}
catch (ApplicationRuntimeException e)
{
Assert
.assertEquals(e.getMessage(),
"Unable to create new instance of class org.strecks.util.impl.MyClass$AbstractClass as class cannot be instantiated");
}
}
@Test
public void testDuffType()
{
try
{
ReflectHelper.createInstance("org.strecks.util.impl.MyClass", Integer.class);
Assert.fail();
}
catch (ApplicationRuntimeException e)
{
Assert
.assertEquals(e.getMessage(),
"Class org.strecks.util.impl.MyClass was instantiated but was not an instance of the type class java.lang.Integer");
}
}
@Test
public void testCheckGenericType1()
{
assert ReflectHelper.checkGenericType(GenericClass.class, Comparable.class, Integer.class);
assert !ReflectHelper.checkGenericType(GenericClass.class, Comparable.class, String.class);
assert ReflectHelper.checkGenericType(GenericClass.class, List.class, String.class);
// check a class which has no generic interfaces
assert ReflectHelper.checkGenericType(String.class, List.class, String.class);
}
@Test
public void testGenericType()
{
assert Integer.class == ReflectHelper.getGenericType(GenericClass.class, Comparable.class);
// check a class which does not have a generic implementation of the given interfaces
assert null == ReflectHelper.getGenericType(GenericClass.class, List.class);
// check a class which has no generic interfaces
assert null == ReflectHelper.getGenericType(String.class, List.class);
assert String.class == ReflectHelper.getGenericType(DatePatternConverter.class, Converter.class);
// this one goes down a hierarchy 3 deep to find the generic type
assert Integer.class == ReflectHelper.getGenericType(ComparableIntegerSubclass.class, Comparable.class);
}
@Test
public void testGenericTypes()
{
Type[] genericTypes = ReflectHelper.getGenericTypes(MapContainingList.class, Map.class);
assert genericTypes[0].equals(String.class);
assert genericTypes[1] instanceof ParameterizedType;
Assert.assertEquals(ReflectHelper.getTypeDescription(genericTypes[0]), "class java.lang.String");
Assert.assertEquals(ReflectHelper.getTypeDescription(genericTypes[1]),
"parameterized interface java.util.List (class java.lang.String)");
genericTypes = ReflectHelper.getGenericTypes(ArrayConverter.class, Converter.class);
assert genericTypes[0] instanceof GenericArrayType;
assert genericTypes[1] instanceof ParameterizedType;
Assert.assertEquals(ReflectHelper.getTypeDescription(genericTypes[0]), "array of class java.lang.String");
Assert.assertEquals(ReflectHelper.getTypeDescription(genericTypes[1]),
"parameterized interface java.util.List (class java.lang.Integer)");
genericTypes = ReflectHelper.getGenericTypes(HashMap.class, Map.class);
assert genericTypes[0] instanceof TypeVariable;
assert genericTypes[1] instanceof TypeVariable;
Assert.assertEquals(ReflectHelper.getTypeDescription(genericTypes[0]),
"type variable named K bounded by (class java.lang.Object)");
Assert.assertEquals(ReflectHelper.getTypeDescription(genericTypes[1]),
"type variable named V bounded by (class java.lang.Object)");
}
@Test
public void testWildCardType() throws SecurityException, NoSuchMethodException
{
Method method = getWildcardMethod("setUpperValue");
Assert.assertEquals(ReflectHelper.getTypeDescription(method.getGenericParameterTypes()[0]),
"parameterized interface java.util.Collection (wildcard generic type with upper bound (interface java.util.List))");
method = getWildcardMethod("setLowerValue");
Assert.assertEquals(ReflectHelper.getTypeDescription(method.getGenericParameterTypes()[0]),
"parameterized interface java.util.Collection (wildcard generic type with upper bound (class java.lang.Object) and lower bound (class java.util.ArrayList))");
}
private Method getWildcardMethod(String methodName)
{
Method[] methods = ClassWithWildcardTypes.class.getMethods();
Method method = null;
for (int i = 0; i < methods.length; i++)
{
String name = methods[i].getName();
if (name.startsWith(methodName))
{
method = methods[i];
break;
}
}
Assert.assertNotNull(method);
return method;
}
@Test
public void testGetBeanPropertyType()
{
JavaBean bean = new JavaBean();
Class<?> beanPropertyType = ReflectHelper.getBeanPropertyType(bean, "booleanProperty");
Assert.assertEquals(beanPropertyType, Boolean.TYPE);
}
@Test
public void testUnknownGetBeanPropertyType()
{
JavaBean bean = new JavaBean();
try
{
ReflectHelper.getBeanPropertyType(bean, "unknownProperty");
}
catch (ApplicationRuntimeException e)
{
Assert
.assertEquals(e.getMessage(),
"Unable to read property descriptor for bean org.strecks.util.impl.JavaBean, property unknownProperty");
}
}
}