Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
GRAILS-2495 delayed object references and creation to the extent poss…
…ible
  • Loading branch information
burtbeckwith committed Mar 28, 2010
1 parent 54a1c33 commit 58e924e
Showing 1 changed file with 87 additions and 76 deletions.
@@ -1,12 +1,12 @@
/*
* 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.
Expand All @@ -19,6 +19,16 @@
import groovy.lang.Closure;
import groovy.lang.GroovyObject;
import groovy.lang.MissingMethodException;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.groovy.grails.commons.ControllerArtefactHandler;
Expand All @@ -35,20 +45,12 @@
import org.springframework.validation.Errors;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
* Implements the "redirect" Controller method for action redirection
*
* Implements the "redirect" Controller method for action redirection.
*
* @author Graeme Rocher
* @since 0.2
*
*
* Created Oct 27, 2005
*/
public class RedirectDynamicMethod extends AbstractDynamicMethodInvocation {
Expand All @@ -67,140 +69,150 @@ public class RedirectDynamicMethod extends AbstractDynamicMethodInvocation {
private static final String ARGUMENT_FRAGMENT = "fragment";
public static final String ARGUMENT_ERRORS = "errors";


private static final Log LOG = LogFactory.getLog(RedirectDynamicMethod.class);
private UrlMappingsHolder urlMappingsHolder;
private boolean useJessionId = false;
private ApplicationContext applicationContext;

/**
* Constructor.
* @param applicationContext
*/
public RedirectDynamicMethod(ApplicationContext applicationContext) {
super(METHOD_PATTERN);
if(applicationContext.containsBean(UrlMappingsHolder.BEAN_ID))
this.urlMappingsHolder = (UrlMappingsHolder)applicationContext.getBean(UrlMappingsHolder.BEAN_ID);

GrailsApplication application = (GrailsApplication) applicationContext.getBean(GrailsApplication.APPLICATION_ID);
if (applicationContext.containsBean(UrlMappingsHolder.BEAN_ID)) {
urlMappingsHolder = (UrlMappingsHolder)applicationContext.getBean(UrlMappingsHolder.BEAN_ID);
}

GrailsApplication application = (GrailsApplication)applicationContext.getBean(GrailsApplication.APPLICATION_ID);
Object o = application.getFlatConfig().get(GRAILS_VIEWS_ENABLE_JSESSIONID);
if(o instanceof Boolean) {
if (o instanceof Boolean) {
useJessionId = (Boolean) o;
}
this.applicationContext = applicationContext;

}

@SuppressWarnings("unchecked")
@Override
public Object invoke(Object target, String methodName, Object[] arguments) {
if(arguments.length == 0)
if (arguments.length == 0) {
throw new MissingMethodException(METHOD_SIGNATURE,target.getClass(),arguments);
}

Map argMap = arguments[0] instanceof Map ? (Map)arguments[0] : Collections.EMPTY_MAP;
if(argMap.size() == 0){
if (argMap.isEmpty()) {
throw new MissingMethodException(METHOD_SIGNATURE,target.getClass(),arguments);
}

GrailsWebRequest webRequest = (GrailsWebRequest)RequestContextHolder.currentRequestAttributes();

HttpServletRequest request = webRequest.getCurrentRequest();
HttpServletResponse response = webRequest.getCurrentResponse();

if(request.getAttribute(GRAILS_REDIRECT_ISSUED)!=null) {
if (request.getAttribute(GRAILS_REDIRECT_ISSUED) != null) {
throw new CannotRedirectException("Cannot issue a redirect(..) here. A previous call to redirect(..) has already redirected the response.");
}
if(response.isCommitted()) {

HttpServletResponse response = webRequest.getCurrentResponse();
if (response.isCommitted()) {
throw new CannotRedirectException("Cannot issue a redirect(..) here. The response has already been committed either by another redirect or by directly writing to the response.");
}


Object actionRef = argMap.get(ARGUMENT_ACTION);
String controllerName = getControllerName(target, argMap);

Object id = argMap.get(ARGUMENT_ID);
String frag = argMap.get(ARGUMENT_FRAGMENT) != null ? argMap.get(ARGUMENT_FRAGMENT).toString() : null;
Object uri = argMap.get(ARGUMENT_URI);
String url = argMap.containsKey(ARGUMENT_URL) ? argMap.get(ARGUMENT_URL).toString() : null;
Map params = (Map)argMap.get(ARGUMENT_PARAMS);
if(params==null)params = new HashMap();
Errors errors = (Errors)argMap.get(ARGUMENT_ERRORS);
GroovyObject controller = (GroovyObject)target;

// if there are errors add it to the list of errors
Errors controllerErrors = (Errors)controller.getProperty( ControllerDynamicMethods.ERRORS_PROPERTY );
if(controllerErrors != null) {
Errors controllerErrors = (Errors)controller.getProperty(ControllerDynamicMethods.ERRORS_PROPERTY);
Errors errors = (Errors)argMap.get(ARGUMENT_ERRORS);
if (controllerErrors != null) {
controllerErrors.addAllErrors(errors);
}
else {
controller.setProperty( ControllerDynamicMethods.ERRORS_PROPERTY, errors);
controller.setProperty(ControllerDynamicMethods.ERRORS_PROPERTY, errors);
}

Object uri = argMap.get(ARGUMENT_URI);
String url = argMap.containsKey(ARGUMENT_URL) ? argMap.get(ARGUMENT_URL).toString() : null;
String actualUri;
GrailsApplicationAttributes attrs = webRequest.getAttributes();

if(uri != null) {
if (uri != null) {
GrailsApplicationAttributes attrs = webRequest.getAttributes();
actualUri = attrs.getApplicationUri(request) + uri.toString();
}
else if(url != null) {
else if (url != null) {
actualUri = url;
}
else {
String actionName = establishActionName(actionRef, target, webRequest);
else {
Object actionRef = argMap.get(ARGUMENT_ACTION);
String actionName = establishActionName(actionRef, target);
String controllerName = getControllerName(target, argMap);
controllerName = controllerName != null ? controllerName : webRequest.getControllerName();

if(LOG.isDebugEnabled()) {
LOG.debug("Dynamic method [redirect] looking up URL mapping for controller ["+controllerName+"] and action ["+actionName+"] and params ["+params+"] with ["+urlMappingsHolder+"]");
Map params = (Map)argMap.get(ARGUMENT_PARAMS);
if (params == null) {
params = new HashMap();
}

if (LOG.isDebugEnabled()) {
LOG.debug("Dynamic method [redirect] looking up URL mapping for controller ["+controllerName+"] and action ["+actionName+"] and params ["+params+"] with ["+urlMappingsHolder+"]");
}


Object id = argMap.get(ARGUMENT_ID);
try {
if( id != null ) params.put( ARGUMENT_ID, id );
if (id != null) {
params.put(ARGUMENT_ID, id);
}

UrlCreator urlMapping = urlMappingsHolder.getReverseMapping( controllerName, actionName, params );
if( LOG.isDebugEnabled() && urlMapping == null ) {
LOG.debug( "Dynamic method [redirect] no URL mapping found for params [" + params + "]" );
UrlCreator urlMapping = urlMappingsHolder.getReverseMapping(controllerName, actionName, params);
if (urlMapping == null && LOG.isDebugEnabled()) {
LOG.debug("Dynamic method [redirect] no URL mapping found for params [" + params + "]");
}

actualUri = urlMapping.createURL( controllerName, actionName, params, request.getCharacterEncoding(), frag );
String frag = argMap.get(ARGUMENT_FRAGMENT) != null ? argMap.get(ARGUMENT_FRAGMENT).toString() : null;
actualUri = urlMapping.createURL(controllerName, actionName, params, request.getCharacterEncoding(), frag);

if( LOG.isDebugEnabled() ) {
LOG.debug( "Dynamic method [redirect] mapped to URL [" + actualUri + "]" );
if (LOG.isDebugEnabled()) {
LOG.debug("Dynamic method [redirect] mapped to URL [" + actualUri + "]");
}
}
finally {
if (id != null) {
params.remove(ARGUMENT_ID);
}

} finally {
if( id != null ) params.remove( ARGUMENT_ID );
}

}

return redirectResponse(actualUri, request,response);
}

@SuppressWarnings("unchecked")
private String getControllerName(Object target, Map argMap) {
return argMap.containsKey(ARGUMENT_CONTROLLER) ? argMap.get(ARGUMENT_CONTROLLER).toString() : GrailsNameUtils.getLogicalPropertyName(target.getClass().getName(), ControllerArtefactHandler.TYPE);
return argMap.containsKey(ARGUMENT_CONTROLLER) ?
argMap.get(ARGUMENT_CONTROLLER).toString() :
GrailsNameUtils.getLogicalPropertyName(target.getClass().getName(),
ControllerArtefactHandler.TYPE);
}


/*
* Redirects the response the the given URI
*/
private Object redirectResponse(String actualUri, HttpServletRequest request, HttpServletResponse response) {
if(LOG.isDebugEnabled()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Dynamic method [redirect] forwarding request to ["+actualUri +"]");
}

try {

if(LOG.isDebugEnabled()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Executing redirect with response ["+response+"]");
}

String redirectUrl = useJessionId ? response.encodeRedirectURL(actualUri) : actualUri;
response.sendRedirect(redirectUrl);
Map<String, RedirectEventListener> redirectListeners = applicationContext.getBeansOfType(RedirectEventListener.class);
for (RedirectEventListener redirectEventListener : redirectListeners.values()) {
redirectEventListener.responseRedirected(redirectUrl);
redirectEventListener.responseRedirected(redirectUrl);
}

request.setAttribute(GRAILS_REDIRECT_ISSUED, true);

} catch (IOException e) {
}
catch (IOException e) {
throw new CannotRedirectException("Error redirecting request for url ["+actualUri +"]: " + e.getMessage(),e);
}
return null;
Expand All @@ -209,18 +221,17 @@ private Object redirectResponse(String actualUri, HttpServletRequest request, Ht
/*
* Figures out the action name from the specified action reference (either a string or closure)
*/
private String establishActionName(Object actionRef, Object target, GrailsWebRequest webRequest) {
private String establishActionName(Object actionRef, Object target) {
String actionName = null;
if(actionRef instanceof String) {
actionName = (String)actionRef;
} else if(actionRef instanceof CharSequence) {
if (actionRef instanceof String) {
actionName = (String)actionRef;
}
else if (actionRef instanceof CharSequence) {
actionName = actionRef.toString();
}
else if(actionRef instanceof Closure) {
Closure c = (Closure)actionRef;
actionName = GrailsClassUtils.findPropertyNameForValue(target, c);
else if (actionRef instanceof Closure) {
actionName = GrailsClassUtils.findPropertyNameForValue(target, actionRef);
}
return actionName;
}

}

0 comments on commit 58e924e

Please sign in to comment.