blob: 43bf95605dd3407063f76b1e1fd52920111c2ef7 [file] [log] [blame]
package org.codehaus.groovy.grails.web.metaclass;
import groovy.lang.Closure;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import groovy.lang.MissingMethodException;
import groovy.lang.MissingPropertyException;
import groovy.lang.ProxyMetaClass;
import groovy.lang.TracingInterceptor;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.codehaus.groovy.grails.commons.DefaultGrailsApplication;
import org.codehaus.groovy.grails.commons.GrailsApplication;
import org.codehaus.groovy.grails.commons.metaclass.PropertyAccessProxyMetaClass;
import org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper;
import org.codehaus.groovy.grails.web.servlet.mvc.SimpleGrailsControllerHelper;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
public class ControllerMetaClassTests extends TestCase {
private GenericApplicationContext context;
public void testMetaClassProxy()
throws Exception {
GroovyClassLoader gcl = new GroovyClassLoader();
Class groovyClass = gcl.parseClass( "class TestClass {\n" +
"def testMethod() {\n" +
"}\n" +
"}" );
ProxyMetaClass pmc = ProxyMetaClass.getInstance(groovyClass);
// proof of concept to try out proxy meta class
pmc.setInterceptor( new TracingInterceptor() {
public boolean doInvoke() {
return false;
}
});
GroovyObject go = (GroovyObject)groovyClass.newInstance();
go.setMetaClass( pmc );
try {
// invoke real method
go.invokeMethod("testMethod", new Object[]{});
// invoke fake method
go.invokeMethod("fakeMethod", new Object[]{});
}
catch(MissingMethodException mme) {
fail("Missing method exception should not have been thrown!");
}
}
public void testParamsDynamicProperty() throws Exception {
GroovyClassLoader gcl = new GroovyClassLoader();
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
request.addParameter("testParam", "testValue");
Class groovyClass = gcl.parseClass( "class TestController {\n" +
"def testMethod() {\n" +
"}\n" +
"}" );
GrailsApplication application = new DefaultGrailsApplication(new Class[] { groovyClass },gcl);
GroovyObject go = configureDynamicGO(groovyClass,application, request,response);
try {
Object params = go.getProperty( "params" );
assertNotNull(params);
assertTrue(params instanceof Map);
Map paramsMap = (Map)params;
assertTrue(paramsMap.containsKey("testParam"));
assertEquals("testValue",paramsMap.get("testParam"));
}
catch(MissingMethodException mme) {
fail("Missing method exception should not have been thrown!");
}
catch(MissingPropertyException mpex) {
fail("Missing property exception should not have been thrown!");
}
}
public void testRedirectDynamicMethod() throws Exception {
GroovyClassLoader gcl = new GroovyClassLoader();
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
request.addParameter("testParam", "testValue");
Class groovyClass = gcl.parseClass( "class TestController {\n" +
"@Property next = {\n" +
"return ['success':this.params['testParam2']]" +
"}\n" +
"@Property list = {\n" +
"return redirect(action:this.next,params:['testParam2':'testValue2'])\n" +
"}\n" +
"}" );
Class secondController = gcl.parseClass( "class SecondController {\n" +
"@Property list = {\n" +
"return redirect(action:'test/list',params:['testParam2':'testValue2'])\n" +
"}\n" +
"}" );
GrailsApplication application = new DefaultGrailsApplication(new Class[] { groovyClass,secondController },gcl);
GroovyObject go = configureDynamicGO(groovyClass, application,request,response);
GroovyObject go2 = configureDynamicGO(secondController, application,request,response);
// first test redirection within the same controller
try {
Closure closure = (Closure)go.getProperty("list");
Object returnValue = closure.call();
assertNotNull(returnValue);
assertTrue(returnValue instanceof ModelAndView);
Map model = ((ModelAndView)returnValue).getModel();
assertEquals("testValue2", model.get("success"));
}
catch(MissingMethodException mme) {
fail("Missing method exception should not have been thrown!");
}
catch(MissingPropertyException mpex) {
fail("Missing property exception should not have been thrown!");
}
// now redirection to another controller
try {
Closure closure = (Closure)go2.getProperty("list");
Object returnValue = closure.call();
assertNotNull(returnValue);
assertTrue(returnValue instanceof ModelAndView);
Map model = ((ModelAndView)returnValue).getModel();
assertEquals("testValue2", model.get("success"));
}
catch(MissingMethodException mme) {
fail("Missing method exception should not have been thrown!");
}
catch(MissingPropertyException mpex) {
fail("Missing property exception should not have been thrown!");
}
}
public void testChainDynamicMethod() throws Exception {
GroovyClassLoader gcl = new GroovyClassLoader();
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
request.addParameter("testParam", "testValue");
Class groovyClass = gcl.parseClass( "class TestController {\n" +
"@Property next = {\n" +
"chain(action:this.next2,model:['mymodel2':'myvalue2'],params:['testParam2':this.params['testParam2']])\n" +
"}\n" +
"@Property next2 = {\n" +
"return ['success':this.params['testParam2']]" +
"}\n" +
"@Property list = {\n" +
"chain(action:this.next,model:['mymodel':'myvalue'],params:['testParam2':'testValue2'])\n" +
"}\n" +
"}" );
Class secondController = gcl.parseClass( "class SecondController {\n" +
"@Property list = {\n" +
"return chain(action:'test/list',model:['mymodel':'myvalue'],params:['testParam2':'testValue2'])\n" +
"}\n" +
"}" );
GrailsApplication application = new DefaultGrailsApplication(new Class[] { groovyClass,secondController },gcl);
GroovyObject go = configureDynamicGO(groovyClass, application,request,response);
GroovyObject go2 = configureDynamicGO(secondController, application,request,response);
// first test redirection within the same controller
try {
Closure closure = (Closure)go.getProperty("list");
Object returnValue = closure.call();
assertNotNull(returnValue);
assertTrue(returnValue instanceof ModelAndView);
Map model = ((ModelAndView)returnValue).getModel();
assertEquals("myvalue", model.get("mymodel"));
assertEquals("myvalue2", model.get("mymodel2"));
assertEquals("testValue2", model.get("success"));
}
catch(MissingMethodException mme) {
fail("Missing method exception should not have been thrown!");
}
catch(MissingPropertyException mpex) {
fail("Missing property exception should not have been thrown!");
}
// now redirection to another controller
try {
Closure closure = (Closure)go2.getProperty("list");
Object returnValue = closure.call();
assertNotNull(returnValue);
assertTrue(returnValue instanceof ModelAndView);
Map model = ((ModelAndView)returnValue).getModel();
assertEquals("myvalue", model.get("mymodel"));
assertEquals("testValue2", model.get("success"));
}
catch(MissingMethodException mme) {
fail("Missing method exception should not have been thrown!");
}
catch(MissingPropertyException mpex) {
fail("Missing property exception should not have been thrown!");
}
}
private GroovyObject configureDynamicGO(Class groovyClass,GrailsApplication application, HttpServletRequest request, HttpServletResponse response)
throws Exception {
ProxyMetaClass pmc = PropertyAccessProxyMetaClass.getInstance(groovyClass);
// proof of concept to try out proxy meta class
if(context == null)
this.context = new GenericApplicationContext();
BeanDefinition bd = new RootBeanDefinition(groovyClass,false);
context.registerBeanDefinition( groovyClass.getName(), bd );
GrailsControllerHelper helper = new SimpleGrailsControllerHelper(application,context);
GroovyObject go = (GroovyObject)groovyClass.newInstance();
pmc.setInterceptor( new ControllerDynamicMethodsInterceptor(go,helper,request,response) );
go.setMetaClass( pmc );
return go;
}
}