blob: 6f51460e4c52135b91586bca1a443e61d0c08c68 [file] [log] [blame]
/*
* Copyright 2004-2005 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.codehaus.groovy.grails.web.metaclass;
import groovy.lang.Closure;
import groovy.lang.GroovyObject;
import groovy.lang.MissingPropertyException;
import org.codehaus.groovy.grails.commons.GrailsControllerClass;
import org.codehaus.groovy.grails.commons.GrailsApplication;
import org.codehaus.groovy.grails.commons.metaclass.AbstractDynamicMethodInvocation;
import org.codehaus.groovy.grails.commons.metaclass.GenericDynamicProperty;
import org.codehaus.groovy.grails.commons.metaclass.GroovyDynamicMethodsInterceptor;
import org.codehaus.groovy.grails.scaffolding.GrailsScaffolder;
import org.codehaus.groovy.grails.web.servlet.GrailsHttpServletRequest;
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes;
import org.codehaus.groovy.grails.web.servlet.FlashScope;
import org.codehaus.groovy.grails.web.servlet.mvc.GrailsControllerHelper;
import org.springframework.validation.Errors;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.IntrospectionException;
/**
* Adds dynamic methods and properties for Grails Controllers
*
* @author Graeme Rocher
* @since Oct 24, 2005
*/
public class ControllerDynamicMethods extends
GroovyDynamicMethodsInterceptor {
public static final String REQUEST_PROPERTY = "request";
public static final String SERVLET_CONTEXT = "servletContext";
public static final String FLASH_SCOPE_PROPERTY = "flash";
public static final String GRAILS_ATTRIBUTES = "grailsAttributes";
public static final String GRAILS_APPLICATION = "grailsApplication";
public static final String RESPONSE_PROPERTY = "response";
public static final String RENDER_VIEW_PROPERTY = "renderView";
public static final String ERRORS_PROPERTY = "errors";
public static final String HAS_ERRORS_METHOD = "hasErrors";
public static final String MODEL_AND_VIEW_PROPERTY = "modelAndView";
public static final String ACTION_URI_PROPERTY = "actionUri";
public static final String CONTROLLER_URI_PROPERTY = "controllerUri";
protected GrailsControllerClass controllerClass;
protected GrailsScaffolder scaffolder;
private boolean scaffolding;
public ControllerDynamicMethods( GroovyObject controller,GrailsControllerHelper helper,HttpServletRequest request, HttpServletResponse response) throws IntrospectionException {
super(controller);
this.controllerClass = helper.getControllerClassByName(controller.getClass().getName());
// add dynamic properties
addDynamicProperty(new GetParamsDynamicProperty(request,response));
addDynamicProperty(new GetSessionDynamicProperty(request,response));
addDynamicProperty(new GenericDynamicProperty(REQUEST_PROPERTY, HttpServletRequest.class,new GrailsHttpServletRequest( request,controller),true) );
addDynamicProperty(new GenericDynamicProperty(RESPONSE_PROPERTY, HttpServletResponse.class,response,true) );
addDynamicProperty(new GenericDynamicProperty(SERVLET_CONTEXT, ServletContext.class,helper.getServletContext(),true) );
addDynamicProperty(new GenericDynamicProperty(FLASH_SCOPE_PROPERTY, FlashScope.class,helper.getGrailsAttributes().getFlashScope(request),false) );
addDynamicProperty(new GenericDynamicProperty(ERRORS_PROPERTY, Errors.class, null, false));
addDynamicProperty(new GenericDynamicProperty(MODEL_AND_VIEW_PROPERTY, ModelAndView.class,null,false));
addDynamicProperty(new GenericDynamicProperty(GRAILS_ATTRIBUTES, GrailsApplicationAttributes.class,helper.getGrailsAttributes(),true));
addDynamicProperty(new GenericDynamicProperty(GRAILS_APPLICATION, GrailsApplication.class,helper.getGrailsAttributes().getGrailsApplication(),true));
addDynamicProperty(new GenericDynamicProperty(ACTION_URI_PROPERTY,String.class,null,false));
addDynamicProperty(new GenericDynamicProperty(CONTROLLER_URI_PROPERTY,String.class,null,false));
addDynamicProperty(new GenericDynamicProperty(RENDER_VIEW_PROPERTY,Boolean.class, Boolean.TRUE,false));
// add dynamic methods
addDynamicMethodInvocation( new RedirectDynamicMethod(helper,request,response) );
addDynamicMethodInvocation( new ChainDynamicMethod(helper, request, response ) );
addDynamicMethodInvocation( new RenderDynamicMethod(helper,request,response));
addDynamicMethodInvocation( new BindDynamicMethod(request,response));
// the hasErrors() dynamic method that checks of there are any errors in the controller
addDynamicMethodInvocation( new AbstractDynamicMethodInvocation(HAS_ERRORS_METHOD) {
public Object invoke(Object target, Object[] arguments) {
GroovyObject controller = (GroovyObject)target;
Errors errors = (Errors)controller.getProperty(ERRORS_PROPERTY);
return Boolean.valueOf(errors.hasErrors());
}
});
this.scaffolding = this.controllerClass.isScaffolding();
// if the controller is scaffolding get the scaffolder, then loop through all the
// support actions by the scaffolder and register dynamic properties for those that don't exist
if(this.scaffolding) {
this.scaffolder = helper.getScaffolderForController(controllerClass.getFullName());
if(this.scaffolder == null) {
throw new IllegalStateException("Scaffolder is null when controller scaffold property is set to 'true'");
}
String[] scaffoldActions = this.scaffolder.getSupportedActionNames();
for (int i = 0; i < scaffoldActions.length; i++) {
try {
controller.getProperty(scaffoldActions[i]);
}
catch(MissingPropertyException mpe) {
addDynamicProperty(new GenericDynamicProperty( scaffoldActions[i],
Closure.class,
scaffolder.getAction(controller,scaffoldActions[i]),
true));
}
}
}
}
}