/*
* This software is distributed under the terms of the FSF
* Gnu Lesser General Public License (see lgpl.txt).
*
* This program is distributed WITHOUT ANY WARRANTY. See the
* GNU General Public License for more details.
*/
package com.scooterframework.web.controller;
import java.io.IOException;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.scooterframework.admin.Constants;
import com.scooterframework.admin.EnvConfig;
import com.scooterframework.common.util.CurrentThreadCache;
import com.scooterframework.common.util.CurrentThreadCacheClient;
import com.scooterframework.web.route.MatchMaker;
import com.scooterframework.web.route.RequestInfo;
import com.scooterframework.web.route.RouteConfig;
import com.scooterframework.web.route.RouteConstants;
import com.scooterframework.web.route.RouteInfo;
/**
* <p><strong>RestfulRequestProcessor</strong> contains the processing logic that
* the {@link MainActionServlet} performs as it receives each servlet request
* from the container. You can customize the request processing behavior by
* subclassing this class and overriding the method(s) whose behavior you are
* interested in changing.</p>
*
* @author (Fei) John Chen
*/
public class RestfulRequestProcessor extends BaseRequestProcessor {
public static final String DEFAULT_CONTROLLER_CLASS = "com.scooterframework.builtin.RestfulCRUDController";
private static final String CACHE_KEY_ROUTE_TYPE = "cache.key.route_type";
/**
* Constructor
*/
public RestfulRequestProcessor() {
}
/**
* <p>Process an <tt>HttpServletRequest</tt>.</p>
*
* @param aps properties of request
* @param request The servlet request we are processing
* @param response The servlet response we are creating
* @return execution result
* @throws java.io.IOException
* @throws javax.servlet.ServletException
*/
public String executeRequest(ActionProperties aps,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
CurrentThreadCache.set(CACHE_KEY_ROUTE_TYPE, aps.routeType);
return super.executeRequest(aps, request, response);
}
/**
* Sets up action properties for the action execution. The properties are
* wrapped up in an <tt>ActionProperties</tt> instance.
*
* @param request The servlet request we are processing
* @return an ActionProperties instance
*/
public ActionProperties prepareActionProperties(String requestPath,
String requestHttpMethod, HttpServletRequest request) {
ActionProperties aps = super.prepareActionProperties(requestPath, requestHttpMethod, request);
RequestInfo requestInfo = new RequestInfo(requestPath, requestHttpMethod);
log.debug(" requestInfo: " + requestInfo);
RouteInfo routeInfo = MatchMaker.getInstance().match(requestInfo);
log.debug("matched route: " + routeInfo);
//setup field values
Map<String, String> requiredFieldValues = routeInfo.getRequiredFieldValues();
if (requiredFieldValues != null) {
CurrentThreadCacheClient.cacheFieldValues(requiredFieldValues);
for(Map.Entry<String, String> entry : requiredFieldValues.entrySet()) {
request.setAttribute(entry.getKey(), entry.getValue());
}
}
aps.controller = routeInfo.getController();
aps.controllerClassName = routeInfo.getControllerClassName();
aps.action = routeInfo.getAction();
aps.model = routeInfo.getModel();
aps.format = routeInfo.getFormat();
aps.resource = routeInfo.getResourceName();
aps.routeType = routeInfo.getRouteType();
aps.requiredFieldValues = requiredFieldValues;
aps.cacheable = routeInfo.getCacheable();
return aps;
}
/**
* Puts some action properties in <tt>request</tt> object.
*/
protected void registerActionProperties(HttpServletRequest request, ActionProperties aps) {
super.registerActionProperties(request, aps);
CurrentThreadCacheClient.cacheResource(aps.resource);
request.setAttribute(Constants.RESOURCE, aps.resource);
CurrentThreadCacheClient.cacheCacheable(aps.cacheable);
request.setAttribute(Constants.REQUEST_CACHEABLE, aps.cacheable);
Map<String, String> requiredFieldValues = aps.requiredFieldValues;
if (requiredFieldValues != null) {
CurrentThreadCacheClient.cacheFieldValues(requiredFieldValues);
for(Map.Entry<String, String> entry : requiredFieldValues.entrySet()) {
request.setAttribute(entry.getKey(), entry.getValue());
}
}
}
/**
* Returns class name of default controller. This default controller is used
* when application specific controller is not available and the
* <tt>auto.rest</tt> property is set to true in the routes.properties
* file. Subclass must override this method if a different default
* controller class is used.
*/
protected String getDefaultControllerClassName() {
if (!RouteConstants.ROUTE_TYPE_REST.equals(CurrentThreadCache.get(CACHE_KEY_ROUTE_TYPE))) {
return super.getDefaultControllerClassName();
}
return DEFAULT_CONTROLLER_CLASS;
}
/**
* Returns default view file directory name.
*
* @return default view file directory name.
*/
protected String getDefaultViewFilesDirectoryName() {
if (!RouteConstants.ROUTE_TYPE_REST.equals(CurrentThreadCache.get(CACHE_KEY_ROUTE_TYPE))) {
return super.getDefaultViewFilesDirectoryName();
}
String dirName = null;
if (RouteConfig.getInstance().allowAutoREST()) {
dirName = EnvConfig.getInstance().getDefaultViewFilesDirectoryForREST();
}
return dirName;
}
}