All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.britesnow.snow.web.RequestContext Maven / Gradle / Ivy

/* Copyright 2009 Jeremy Chone - Licensed under the Apache License, Version 2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 */
package com.britesnow.snow.web;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.lang.reflect.Array;
import java.net.URLDecoder;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.britesnow.snow.util.HttpRequestUtil;
import com.britesnow.snow.util.MapUtil;
import com.britesnow.snow.util.ObjectUtil;
import com.britesnow.snow.web.auth.AuthToken;
import com.google.common.base.Throwables;

public class RequestContext {
    static private Logger       logger             = LoggerFactory.getLogger(RequestContext.class);

    HttpServletRequest          req;
    HttpServletResponse         res;
    ServletContext              servletContext;

    private ServletFileUpload   fileUploader;
    private boolean             isParamInitialized = false;
    private boolean             isMultipart        = false;
    private List             fileItems;

    // built on demand
    private Map paramMap           = null;

    // built on demand
    private Map cookieMap;

    private String              resourcePath;
    private Deque       framePathsStack;

    // this is the HashMap for the "m" model map
    private Map                 webModel           = new HashMap();

    // usually set by the WebController.service
    private WebActionResponse   webActionResponse;

    // optional
    private String              pathInfo;

    // set by AuthService.authRequest
    private AuthToken             authToken;

    public RequestContext(HttpServletRequest req, HttpServletResponse res, ServletContext servletContext,
                            ServletFileUpload fileUploader) {
        this.req = req;
        this.res = res;
        this.servletContext = servletContext;
        this.fileUploader = fileUploader;
        init();
    }

    protected void init() {
    }

    /*--------- Auth Methods ---------*/

    public AuthToken getAuthToken() {
        return authToken;
    }

    public void setAuthToken(AuthToken auth) {
        this.authToken = auth;
    }

    @SuppressWarnings("unchecked")
    public  T getUser(Class userClass) {
        if (authToken != null && userClass.isInstance(authToken.getUser())) {
            return (T) authToken.getUser();
        } else {
            return null;
        }
    }

    /*--------- /Auth Methods ---------*/

    // --------- Attribute Access --------- //
    public void setAttribute(String name, Object obj) {
        req.setAttribute(name, obj);
    }

    public void removeAttribute(String name) {
        req.removeAttribute(name);
    }

    public Object getAttribute(String name) {
        return req.getAttribute(name);
    }

    public  T getAttributeAs(String name, Class cls) {
        return getAttributeAs(name, cls, null);
    }

    public  T getAttributeAs(String name, Class cls, T defaultValue) {
        Object value = req.getAttribute(name);
        if (value != null) {
            if (cls.isInstance(value)) {
                return (T) value;

            } else {
                // otherwise, get get the toString and try to get it with the ObjectUtil.
                return ObjectUtil.getValue(value.toString(), cls, defaultValue);
            }
        } else {
            return defaultValue;
        }
    }

    // --------- /Attribute Access --------- //

    /*--------- Param Methods ---------*/

    // mostly for Mock objects
    protected void setParamMap(Map paramMap) {
        this.paramMap = paramMap;
        isParamInitialized = true;
    }

    public Map getParamMap() {
        initParamsIfNeeded();
        return paramMap;
    }

    /**
     * A map of all the param starting with the prefix.
     * 
     * @param prefix
     * @return The key is the string after the prefix, and the value, is the value itself. Return null if no param
     *         started with the prefix.
     */
    public Map getParamMap(String prefix) {
        Map allParamMap = getParamMap();
        Map prefixParamMap = null;
        if (allParamMap != null && prefix != null) {
            for (String paramName : allParamMap.keySet()) {

                if (paramName.startsWith(prefix)) {
                    if (prefixParamMap == null) {
                        prefixParamMap = new HashMap();
                    }
                    Object value = allParamMap.get(paramName);
                    prefixParamMap.put(paramName.substring(prefix.length()), value);
                }
            }

        }
        return prefixParamMap;
    }

    /**
     * @param 
     * @param prefix
     * @param cls
     * @return The list of values given a param prefix
     */
    public  List getParamMapValues(String prefix, Class cls) {
        List list = new ArrayList();
        Map prefixParamMap = getParamMap(prefix);
        if (prefixParamMap != null) {
            for (Object valueObj : prefixParamMap.values()) {
                if (valueObj instanceof String) {
                    T value = ObjectUtil.getValue((String) valueObj, cls, null);
                    if (value != null) {
                        list.add(value);
                    }
                }

            }
        }
        return list;
    }

    /**
     * Simple method to get the Request value for a given parameter name. Return null if the value is null or empty.
     * 
     * @param name
     *            parameter value
     * @return
     */
    public String getParam(String name) {
        return getParamAs(name, String.class, null);
    }

    /**
     * Return the param value as "cls" class object. If the value is null (or empty string) return null.
     * 
     * @param 
     * @param name
     * @param cls
     * @return the http param value if exist or valid, otherwise, null.
     */
    public  T getParamAs(String name, Class cls) {
        return getParamAs(name, cls, null);
    }

    /**
     * Return the param value as "cls" class object. If the value is null (or empty string) return the defaultValue.
* * Note: For the first call, this method will parse the request (in case of a multipart).
* *
Issues *
    *
  • FIXME: Need to fix the multipart handling. Can be simplified
  • *
*
* * @param * Class of the return element * @param name * of the parameter * @param cls * Class of the return element * @param defaultValue * Default value in case of an error or null/empty value * @return */ @SuppressWarnings("unchecked") public T getParamAs(String name, Class cls, T defaultValue) { Map paramMap = getParamMap(); if (paramMap == null) { return defaultValue; } // if we have a primitive type or array, then, just get the single value and convert it to the appropriate type if (ObjectUtil.isPrimitive(cls) || cls.isArray() || cls == FileItem.class || cls.isEnum()) { // first, try to get it from the paramMap Object valueObject = paramMap.get(name); if (isMultipart) { // HACK // if not found, try to get it from the regular HttpServletRequest // (in the case of a multiPart post, // HttpServletRequest.getParameter still have the URL params) if (valueObject == null) { valueObject = getReq().getParameter(name); } } if (valueObject == null) { return defaultValue; } else if (valueObject instanceof String) { return (T) ObjectUtil.getValue((String) valueObject, cls, defaultValue); } else if (valueObject instanceof String[]) { return (T) ObjectUtil.getValue((String[]) valueObject, cls, defaultValue); } else { // hope for the best (should be a fileItem) return (T) valueObject; } } // otherwise, if it is not a primitive type, attempt to create the targeted object with the corresponding // paramMap else { Map subParamMap = getParamMap(name + "."); // i.e., "product." if (subParamMap != null) { try { T value = cls.newInstance(); ObjectUtil.populate(value, subParamMap); return value; } catch (Exception e) { logger.warn(e.getMessage()); return defaultValue; } } else { return defaultValue; } } } private void initParamsIfNeeded() { if (!isParamInitialized) { isMultipart = ServletFileUpload.isMultipartContent(getReq()); if (isMultipart) { try { fileItems = fileUploader.parseRequest(getReq()); paramMap = new HashMap(); Map paramBaseClasses = new HashMap(); boolean hasMultivalues = false; for (Object item : fileItems) { FileItem fileItem = (FileItem) item; String paramName = fileItem.getFieldName(); // in case of normal fields, take the string value. otherwise // put the whole file item into the map. Object value; Class paramBaseClass; if (fileItem.isFormField()) { try { value = fileItem.getString("UTF-8"); } catch (UnsupportedEncodingException e) { value = fileItem.getString(); } paramBaseClass = String.class; } else { value = fileItem; paramBaseClass = FileItem.class; } // make sure that the client isn't calling something that is mixing and // matching parameter types... // todo - could support this as Object arrays or arrays of most specific shared super class. Class prevBaseClass = paramBaseClasses.put(paramName, paramBaseClass); if (prevBaseClass != null && !prevBaseClass.equals(paramBaseClass)) { throw new IllegalArgumentException("parameter " + paramName + " has mixed parameter types (expected all file or all string)"); } // if there is already a value, then, create a list if (paramMap.containsKey(paramName)) { hasMultivalues = true; Object prevValue = paramMap.get(paramName); if (prevValue instanceof List) { ((List) prevValue).add(value); } else { List values = new ArrayList(2); values.add(prevValue); values.add(value); paramMap.put(paramName, values); } } else { paramMap.put(paramName, value); } } // if we had multivalues, need to change the list to arrays if (hasMultivalues) { for (String name : paramMap.keySet()) { Object value = paramMap.get(name); if (value instanceof List) { List valueList = (List) value; Object[] valueArray = (Object[]) Array.newInstance(paramBaseClasses.get(name), valueList.size()); valueList.toArray(valueArray); paramMap.put(name, valueArray); } } } } catch (FileUploadException e) { // TODO Auto-generated catch block logger.error(e.getMessage()); } } else { paramMap = new HashMap(); // By the httpServletRequest spect, we can assume the type of // the return Map (name and values) Map reqMap = getReq().getParameterMap(); // now, simplify the map, by replacing single string array to // the string itself. for (String paramName : reqMap.keySet()) { String[] values = reqMap.get(paramName); if (values.length == 1) { paramMap.put(paramName, values[0]); } else { paramMap.put(paramName, values); } } } isParamInitialized = true; } } /*--------- /Param Methods ---------*/ /*--------- Cookie Methods ---------*/ public Map getCookieMap() { if (cookieMap == null) { cookieMap = new HashMap(); Cookie[] cookies = getReq().getCookies(); if (cookies != null) { for (Cookie c : cookies) { String value = c.getValue(); try { value = URLDecoder.decode(value, "UTF-8"); } catch (Exception e) { // YES, ignore for now. If failed, the raw value will be in the cookie. } cookieMap.put(c.getName(), value); } } } return cookieMap; } public String getCookie(String name) { return getCookieMap().get(name); } public T getCookie(String name, Class cls, T defaultValue) { return ObjectUtil.getValue(getCookie(name), cls, defaultValue); } public void setCookie(String name, Object value) { // update the response HttpRequestUtil.setCookieValue(getRes(), name, value, true); // update the cookieMap (making sure that the template gets what we send to the browser) if (value != null) { getCookieMap().put(name, value.toString()); } else { removeCookie(name); } } public void removeCookie(String name) { // update the response HttpRequestUtil.removeCookie(getReq(), getRes(), name); // update the cookieMap getCookieMap().remove(name); } /*--------- /Cookie Methods ---------*/ // --------- WebState Methods --------- // /** * @param stateContext * @return return a WebState for a given uiContext. Never return null. */ /* * TODO: needs to implement WebStateHandler public WebStateHandle getWebState(String stateContext){ if (webStateMap * == null){ webStateMap = new HashMap(); } WebStateHandle webState = * webStateMap.get(stateContext); if (webState == null){ webState = * getWebStateHandleFactory().constructWebStateHandle(stateContext, this); webStateMap.put(stateContext, webState); * } return webState; } */ // --------- /WebState Methods --------- // // --------- Paths --------- // public String[] getResourcePaths() { return splitPath(getResourcePath()); } public String getResourcePathAt(int i) { return pathAt(getResourcePaths(), i); } public T getResourcePathAt(int i, Class cls) { return pathAt(getResourcePaths(), i, cls, null); } public T getResourcePathAt(int i, Class cls, T defaultValue) { return pathAt(getResourcePaths(), i, cls, defaultValue); } public String getResourcePath() { return resourcePath; } public void setResourcePath(String resourcePath) { this.resourcePath = resourcePath; } public void setFramePaths(String[] framePaths) { if (framePaths != null) { ArrayDeque stack = new ArrayDeque(); stack.addAll(Arrays.asList(framePaths)); framePathsStack = stack; } } public String popFramePath() { if (framePathsStack != null && !framePathsStack.isEmpty()) { return framePathsStack.pop(); } else { return null; } } // --------- /Paths --------- // // --------- Utilities for Paths --------- // // TODO: probably does not need to be that complicated. Might want to use Guava here. static private String[] splitPath(String path) { String[] paths = null; String[] tmpPaths = path.split("/"); // remove the first element (always empty since the currentPri // start starts with "/") if (tmpPaths.length > 1) { paths = new String[tmpPaths.length - 1]; if (tmpPaths.length > 1) { System.arraycopy(tmpPaths, 1, paths, 0, paths.length); } } else { paths = new String[0]; } return paths; } static private String pathAt(String[] paths, int i) { if (paths.length > i) { return paths[i]; } else { return null; } } public T pathAt(String[] paths, int i, Class cls, T defaultValue) { String valueStr = pathAt(paths, i); return ObjectUtil.getValue(valueStr, cls, defaultValue); } // --------- /Utilities for Paths --------- // /*--------- Writer ---------*/ public Writer getWriter() { try { return res.getWriter(); } catch (IOException e) { throw Throwables.propagate(e); } } /*--------- /Writer ---------*/ /*--------- RootModel ---------*/ /** * Return the value in the model map (the m.**) with the appropriate type or null if not found. * * @see #getModelValue(String, Class, Object) */ public T getModelValue(String namePath, Class cls) { return getModelValue(namePath, cls, null); } /** * Return the value in the model map (the m.**) with the appropriate type and fall back value. * * @param * @param namePath * path deliminated with the ".". Note that the "m." should not be in this namePath. * @param cls * The type of the value to be casted to * @param defaultValue * The fall back value * @return */ public T getModelValue(String namePath, Class cls, T defaultValue) { return MapUtil.getDeepValue(webModel, namePath, cls, defaultValue); } /** * @return the Model M (use for the page model "m") */ public Map getWebModel() { return webModel; } /*--------- /RootModel ---------*/ public WebActionResponse getWebActionResponse() { return webActionResponse; } public void setWebActionResponse(WebActionResponse webActionResponse) { this.webActionResponse = webActionResponse; } /*--------- HttpServlet ---------*/ public HttpServletRequest getReq() { return req; } public HttpServletResponse getRes() { return res; } public ServletContext getServletContext() { return servletContext; } public String getContextPath() { HttpServletRequest request = getReq(); if (request != null) { return request.getContextPath(); } return null; } public String getPathInfo() { if (pathInfo == null) { if (req != null) { // first try the traditional way pathInfo = req.getPathInfo(); // otherwise build it from the requestURI if (pathInfo == null) { // remove the contextPath pathInfo = req.getRequestURI().substring(req.getContextPath().length()); try { pathInfo = URLDecoder.decode(pathInfo, "UTF-8"); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block logger.error(e.getMessage()); } } } } return pathInfo; } /*--------- /HttpServlet ---------*/ }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy