org.apache.click.ClickRequestWrapper.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.click.ClickRequestWrapper.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.click;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.click.service.FileUploadService;
import org.apache.click.util.ClickUtils;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;

/**
 * Provides a custom HttpServletRequest class for shielding users from
 * multipart request parameters. Thus calling request.getParameter(String)
 * will still work properly.
 */
class ClickRequestWrapper extends HttpServletRequestWrapper {

    /**
     * The <tt>FileItem</tt> objects for <tt>"multipart"</tt> POST requests.
     */
    private final Map<String, FileItem[]> fileItemMap;

    /** The request is a multi-part file upload POST request. */
    private final boolean isMultipartRequest;

    /** The map of <tt>"multipart"</tt> request parameter values. */
    private final Map<String, String[]> multipartParameterMap;

    /** The wrapped servlet request. */
    private final HttpServletRequest request;

    // Constructors -----------------------------------------------------------

    /**
     * @see HttpServletRequestWrapper(HttpServletRequest)
     */
    ClickRequestWrapper(final HttpServletRequest request, final FileUploadService fileUploadService) {
        super(request);

        this.isMultipartRequest = ClickUtils.isMultipartRequest(request);
        this.request = request;

        if (isMultipartRequest) {

            Map<String, String[]> requestParams = new HashMap<String, String[]>();
            Map<String, FileItem[]> fileItems = new HashMap<String, FileItem[]>();

            try {
                List<FileItem> itemsList = new ArrayList<FileItem>();

                try {

                    itemsList = fileUploadService.parseRequest(request);

                } catch (FileUploadException fue) {
                    request.setAttribute(FileUploadService.UPLOAD_EXCEPTION, fue);
                }

                for (FileItem fileItem : itemsList) {
                    String name = fileItem.getFieldName();
                    String value = null;

                    // Form fields are placed in the request parameter map,
                    // while file uploads are placed in the file item map.
                    if (fileItem.isFormField()) {

                        if (request.getCharacterEncoding() == null) {
                            value = fileItem.getString();

                        } else {
                            try {
                                value = fileItem.getString(request.getCharacterEncoding());

                            } catch (UnsupportedEncodingException ex) {
                                throw new RuntimeException(ex);
                            }
                        }

                        // Add the form field value to the parameters.
                        addToMapAsString(requestParams, name, value);

                    } else {
                        // Add the file item to the list of file items.
                        addToMapAsFileItem(fileItems, name, fileItem);
                    }
                }

            } catch (Throwable t) {

                // Don't throw error here as it will break Context creation.
                // Instead add the error as a request attribute.
                request.setAttribute(Context.CONTEXT_FATAL_ERROR, t);

            } finally {
                fileItemMap = Collections.unmodifiableMap(fileItems);
                multipartParameterMap = Collections.unmodifiableMap(requestParams);
            }

        } else {
            fileItemMap = Collections.emptyMap();
            multipartParameterMap = Collections.emptyMap();
        }
    }

    // Public Methods ---------------------------------------------------------

    /**
     * Returns a map of <tt>FileItem arrays</tt> keyed on request parameter
     * name for "multipart" POST requests (file uploads). Thus each map entry
     * will consist of one or more <tt>FileItem</tt> objects.
     *
     * @return map of <tt>FileItem arrays</tt> keyed on request parameter name
     * for "multipart" POST requests
     */
    public Map<String, FileItem[]> getFileItemMap() {
        return fileItemMap;
    }

    /**
     * @see javax.servlet.ServletRequest#getParameter(String)
     */
    @Override
    public String getParameter(String name) {
        if (isMultipartRequest) {
            Object value = getMultipartParameterMap().get(name);

            if (value instanceof String) {
                return (String) value;
            }

            if (value instanceof String[]) {
                String[] array = (String[]) value;
                if (array.length >= 1) {
                    return array[0];
                } else {
                    return null;
                }
            }

            return (value == null ? null : value.toString());

        } else {
            return request.getParameter(name);
        }
    }

    /**
     * @see javax.servlet.ServletRequest#getParameterNames()
     */
    @Override
    @SuppressWarnings("unchecked")
    public Enumeration getParameterNames() {
        if (isMultipartRequest) {
            return Collections.enumeration(getMultipartParameterMap().keySet());

        } else {
            return request.getParameterNames();
        }
    }

    /**
     * @see javax.servlet.ServletRequest#getParameterValues(String)
     */
    @Override
    public String[] getParameterValues(String name) {
        if (isMultipartRequest) {
            Object values = getMultipartParameterMap().get(name);
            if (values instanceof String) {
                return new String[] { values.toString() };
            }
            if (values instanceof String[]) {
                return (String[]) values;
            } else {
                return null;
            }

        } else {
            return request.getParameterValues(name);
        }
    }

    /**
     * @see javax.servlet.ServletRequest#getParameterMap()
     */
    @Override
    @SuppressWarnings("unchecked")
    public Map getParameterMap() {
        if (isMultipartRequest) {
            return getMultipartParameterMap();
        } else {
            return request.getParameterMap();
        }
    }

    // Package Private Methods ------------------------------------------------

    /**
     * Return the map of <tt>"multipart"</tt> request parameter map.
     *
     * @return the <tt>"multipart"</tt> request parameter map
     */
    @SuppressWarnings("unchecked")
    Map getMultipartParameterMap() {
        if (request.getAttribute(ClickServlet.MOCK_MODE_ENABLED) == null) {
            return multipartParameterMap;
        } else {
            // In mock mode return the request parameter map. This ensures
            // calling request.setParameter(x,y) works for both normal and
            // multipart requests.
            return request.getParameterMap();
        }
    }

    // Private Methods --------------------------------------------------------

    /**
     * Stores the specified value in a FileItem array in the map, under the
     * specified name. Thus two values stored under the same name will be
     * stored in the same array.
     *
     * @param map the map to add the specified name and value to
     * @param name the name of the map key
     * @param value the value to add to the FileItem array
     */
    private void addToMapAsFileItem(Map<String, FileItem[]> map, String name, FileItem value) {
        FileItem[] oldValues = map.get(name);
        FileItem[] newValues = null;
        if (oldValues == null) {
            newValues = new FileItem[] { value };
        } else {
            newValues = new FileItem[oldValues.length + 1];
            System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
            newValues[oldValues.length] = value;
        }
        map.put(name, newValues);
    }

    /**
     * Stores the specified value in an String array in the map, under the
     * specified name. Thus two values stored under the same name will be
     * stored in the same array.
     *
     * @param map the map to add the specified name and value to
     * @param name the name of the map key
     * @param value the value to add to the string array
     */
    private void addToMapAsString(Map<String, String[]> map, String name, String value) {
        String[] oldValues = map.get(name);
        String[] newValues = null;
        if (oldValues == null) {
            newValues = new String[] { value };
        } else {
            newValues = new String[oldValues.length + 1];
            System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
            newValues[oldValues.length] = value;
        }
        map.put(name, newValues);
    }

}