/***
* Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
* All rights reserved.
*
* 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 br.com.caelum.vraptor.http.ognl;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyCollection;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory;
import javassist.util.proxy.ProxyObject;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import ognl.TypeConverter;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import br.com.caelum.vraptor.converter.LongConverter;
import br.com.caelum.vraptor.converter.StringConverter;
import br.com.caelum.vraptor.core.Converters;
import br.com.caelum.vraptor.ioc.Container;
import br.com.caelum.vraptor.proxy.JavassistProxifier;
import br.com.caelum.vraptor.proxy.ObjenesisInstanceCreator;
import br.com.caelum.vraptor.proxy.Proxifier;
import br.com.caelum.vraptor.proxy.ReflectionInstanceCreator;
public class ReflectionBasedNullHandlerTest {
private OgnlContext context;
private @Mock Container container;
private @Mock EmptyElementsRemoval removal;
private @Mock Converters converters;
private Proxifier proxifier;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
AbstractOgnlTestSupport.configOgnl(converters);
this.proxifier = new JavassistProxifier(new ReflectionInstanceCreator());
this.context = (OgnlContext) Ognl.createDefaultContext(null);
context.setTraceEvaluations(true);
context.put("removal", removal);
context.put("nullHandler", new GenericNullHandler(removal));
context.put("proxifier", proxifier);
when(container.instanceFor(Converters.class)).thenReturn(converters);
when(converters.to(String.class)).thenReturn(new StringConverter());
when(converters.to(Long.class)).thenReturn(new LongConverter());
}
@Test
public void shouldInstantiateAnObjectIfRequiredToSetAProperty() throws OgnlException {
House house = new House();
Ognl.setValue("mouse.name", context, house, "James");
assertThat(house.getMouse().getName(), is(equalTo("James")));
}
@Test
public void shouldInstantiateAListOfStrings() throws OgnlException {
House house = new House();
Ognl.setValue("mouse.eyeColors[0]", context, house, "Blue");
Ognl.setValue("mouse.eyeColors[1]", context, house, "Green");
verify(removal).add(anyCollection());
assertThat(house.getMouse().getEyeColors().get(0), is(equalTo("Blue")));
assertThat(house.getMouse().getEyeColors().get(1), is(equalTo("Green")));
}
public static class House {
private Mouse mouse;
public void setMouse(Mouse cat) {
this.mouse = cat;
}
public Mouse getMouse() {
return mouse;
}
}
@Test
public void shouldNotInstantiateIfLastTerm() throws OgnlException, NoSuchMethodException {
final TypeConverter typeConverter = mock(TypeConverter.class);
final House house = new House();
final Mouse tom = new Mouse();
Method method = House.class.getDeclaredMethod("setMouse", Mouse.class);
when(typeConverter.convertValue(context, house, method, "mouse", "22", Mouse.class)).thenReturn(tom);
Ognl.setTypeConverter(context, typeConverter);
Ognl.setValue("mouse", context, house, "22");
assertThat(house.getMouse(), is(equalTo(tom)));
}
@Test
public void shouldFoundASetter() throws Exception {
final House aSimpleJavaBeans = new House();
final List<Method> methodsOfHouseClass = Arrays.asList(House.class.getMethods());
Method foundMethod = new ReflectionBasedNullHandler(proxifier).findSetter(aSimpleJavaBeans, "Mouse", Mouse.class);
assertThat(methodsOfHouseClass, hasItem(foundMethod));
assertThat(foundMethod.toGenericString(), startsWith("public void "));
assertThat(foundMethod.getName(), is(startsWith("setMouse")));
}
@Test
public void shouldFoundAGetter() throws Exception {
final House aSimpleJavaBeans = new House();
final List<Method> methodsOfHouseClass = Arrays.asList(House.class.getMethods());
Method foundMethod = new ReflectionBasedNullHandler(proxifier).findGetter(aSimpleJavaBeans, "Mouse");
assertThat(methodsOfHouseClass, hasItem(foundMethod));
assertTrue(Mouse.class.isAssignableFrom(foundMethod.getReturnType()));
assertThat(foundMethod.getName(), is(startsWith("getMouse")));
}
@SuppressWarnings("unchecked")
public static <T> T proxify(final T pojo) {
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(pojo.getClass());
Class<?> proxyClass = factory.createClass();
Object proxyInstance = new ObjenesisInstanceCreator().instanceFor(proxyClass);
ProxyObject proxyObject = (ProxyObject) proxyInstance;
proxyObject.setHandler(new MethodHandler() {
public Object invoke(final Object self, final Method thisMethod, final Method proceed, Object[] args)
throws Throwable {
return pojo;
}
});
return (T) proxyInstance;
}
@Test
public void shouldFoundASetterEvenWithAProxyObject() throws Exception {
final House aSimpleJavaBeans = new House();
House beanProxified = proxify(aSimpleJavaBeans);
final List<Method> methodsOfHouseClass = Arrays.asList(House.class.getMethods());
Method foundMethod = new ReflectionBasedNullHandler(proxifier).findSetter(beanProxified, "Mouse", Mouse.class);
assertThat(methodsOfHouseClass, hasItem(foundMethod));
assertThat(foundMethod.toGenericString(), startsWith("public void "));
assertThat(foundMethod.getName(), is(startsWith("setMouse")));
}
@Test
public void shouldFoundAGetterWithAProxyObject() throws Exception {
final House aSimpleJavaBeans = new House();
House beanProxified = proxify(aSimpleJavaBeans);
final List<Method> methodsOfHouseClass = Arrays.asList(House.class.getMethods());
Method foundMethod = new ReflectionBasedNullHandler(proxifier).findGetter(beanProxified, "Mouse");
assertThat(methodsOfHouseClass, hasItem(foundMethod));
assertTrue(Mouse.class.isAssignableFrom(foundMethod.getReturnType()));
assertThat(foundMethod.getName(), is(startsWith("getMouse")));
}
}