org.silverpeas.servlet.HttpRequest.java Source code

Java tutorial

Introduction

Here is the source code for org.silverpeas.servlet.HttpRequest.java

Source

/*
 * Copyright (C) 2000-2013 Silverpeas
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * As a special exception to the terms and conditions of version 3.0 of
 * the GPL, you may redistribute this Program in connection with Writer Free/Libre
 * Open Source Software ("FLOSS") applications as described in Silverpeas's
 * FLOSS exception.  You should have recieved a copy of the text describing
 * the FLOSS exception, and it is also available here:
 * "http://www.silverpeas.org/legal/licensing"
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.silverpeas.servlet;

import com.silverpeas.util.StringUtil;
import com.silverpeas.util.i18n.I18NHelper;
import com.stratelia.silverpeas.peasCore.MainSessionController;
import com.stratelia.webactiv.util.DateUtil;
import com.stratelia.webactiv.util.GeneralPropertiesManager;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.lang.NotImplementedException;
import org.silverpeas.upload.FileUploadManager;
import org.silverpeas.upload.UploadedFile;

import javax.servlet.ServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.stratelia.silverpeas.peasCore.MainSessionController.MAIN_SESSION_CONTROLLER_ATT;

/**
 * An HTTP request decorating an HTTP servlet request with some additional methods and by changing
 * the implementation of some of its methods to take into account some Silverpeas specificities or
 * needs. For example, the <code>getParameter(java.lang.String)</code> method has been modified to
 * take into account also the parameters passed in a multipart/form-data stream.
 *
 * @author mmoquillon
 */
public class HttpRequest extends HttpServletRequestWrapper {

    private List<FileItem> fileItems = null;

    private HttpRequest(HttpServletRequest request) {
        super(request);
        // The decorated request is put into attributes in order to provide it to the REST web
        // services that deals with proxies...
        request.setAttribute(HttpRequest.class.getName(), this);
    }

    /**
     * Decorates the specified HTTP servlet request with an HttpRequest instance. If the request is
     * already an HttpRequest instance, then it is simply returned.
     *
     * @param request the Http servlet request to decorate.
     * @return an HttpRequest instance decorating the specified request.
     */
    public static HttpRequest decorate(final HttpServletRequest request) {
        return request instanceof HttpRequest ? (HttpRequest) request : new HttpRequest(request);
    }

    /**
     * Decorates the specified servlet request with an HttpRequest instance. If the request is already
     * an HttpRequest instance, then it is simply returned.
     *
     * @param request the servlet request to decorate. Must be of type HttpServletRequest.
     * @return an HttpRequest instance decorating the specified request.
     */
    public static HttpRequest decorate(final ServletRequest request) {
        return decorate((HttpServletRequest) request);
    }

    /**
     * Is this request within an anonymous user session?
     *
     * @return true if the request is sent in the context of an opened user session and this session
     * is for an anonymous user.
     */
    public boolean isWithinAnonymousUserSession() {
        MainSessionController controller = getMainSessionController();
        return controller != null && controller.getCurrentUserDetail().isAnonymous();
    }

    /**
     * Is this request within an opened user session?
     *
     * @return true if the request is sent in the context of a Silvepreas user session.
     */
    public boolean isWithinUserSession() {
        return getMainSessionController() != null;
    }

    /**
     * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant
     * multipart/form-data stream.
     *
     * @return a list of FileItem instances parsed from the request, in the order that they were
     * transmitted.
     */
    public List<FileItem> getFileItems() {
        return (fileItems == null ? fileItems = FileUploadUtil.parseRequest(this) : fileItems);
    }

    /**
     * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant
     * multipart/form-data stream and returns the item whose the name matches the specified one.
     *
     * @param name the name of the data to fetch.
     * @return the FileItem instance whose the name matches the specified one or null if no such data
     * exists in the multipart/form-data stream. The file item can be either a file or a parameter.
     */
    public FileItem getFileItem(String name) {
        FileItem item = null;
        List<FileItem> items = getFileItems();
        for (FileItem fileItem : items) {
            if (fileItem.getFieldName().equals(name)) {
                item = fileItem;
                break;
            }
        }
        return item;
    }

    /**
     * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant
     * multipart/form-data stream and returns the item whose the type is a file and the name matches
     * the specified one.
     * @param name the name of the file item to fetch.
     * @return the file item whose the name matches the specified one or null if no such data exists
     * in the multipart stream.
     */
    public FileItem getFile(String name) {
        return FileUploadUtil.getFile(getFileItems(), name);
    }

    /**
     * Processes an <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a> compliant
     * multipart/form-data stream and returns the item whose the type is a file. If there is several
     * items that represent a file, then only the first one is returned.
     * @return the file item representing a file in the multipart stream or null if no such data
     * exists in the multipart stream.
     */
    public FileItem getSingleFile() {
        return FileUploadUtil.getFile(getFileItems());
    }

    /**
     * Is this request has a cookie with the specified name?
     *
     * @param name the name of the cookie.
     * @return true if a cookie with the specified name is carried by this request, false otherwise.
     */
    public boolean hasCookie(String name) {
        if (StringUtil.isNotDefined(name)) {
            return false;
        }
        boolean found = false;
        Cookie[] cookies = getCookies();
        for (int i = 0; i < cookies.length && !found; i++) {
            found = cookies[i].getName().equals(name);
        }
        return found;
    }

    @Override
    public int getServerPort() {
        return GeneralPropertiesManager.getInteger("server.http.port", super.getServerPort());
    }

    @Override
    public boolean isSecure() {
        return !GeneralPropertiesManager.getBoolean("server.mixed", false)
                && (super.isSecure() || GeneralPropertiesManager.getBoolean("server.ssl", false));
    }

    /**
     * Gets the main controller in the current user session. If the current session doesn't match an
     * opened user session in Silverpeas, then null is returned.
     *
     * @return the main session controller mapped with this request.
     */
    public MainSessionController getMainSessionController() {
        HttpSession session = getSession(false);
        if (session != null) {
            return (MainSessionController) session.getAttribute(MAIN_SESSION_CONTROLLER_ATT);
        }
        return null;
    }

    /**
     * Gets the language of the user behind this request.
     *
     * @return the language of the user as he has chosen in its profile in Silverpeas.
     */
    public String getUserLanguage() {
        String language = I18NHelper.defaultLanguage;
        MainSessionController mainSessionController = getMainSessionController();
        if (mainSessionController != null) {
            language = mainSessionController.getFavoriteLanguage();
        }
        return language;
    }

    /**
     * Retrieves from {@link HttpServletRequest} a collection of {@link UploadedFile}.
     *
     * @return collection of {@link UploadedFile}. Empty collection if no uploaded file exists.
     */
    public Collection<UploadedFile> getUploadedFiles() {
        Collection<UploadedFile> uploadedFiles = new ArrayList<UploadedFile>();
        MainSessionController mainSessionController = getMainSessionController();
        if (mainSessionController != null) {
            uploadedFiles = FileUploadManager.getUploadedFiles(this, mainSessionController.getCurrentUserDetail());
        }
        return uploadedFiles;
    }

    /**
     * Get a parameter value as a Long.
     *
     * @param attributeName the name of the attribute.
     * @return the value of the attribute as a long.
     */
    public Long getAttributeAsLong(String attributeName) {
        return asLong(getAttribute(attributeName));
    }

    /**
     * Returns an array of String objects containing all of the values the given request parameter
     * has, or null if the parameter does not exist. The parameters from a multipart/form-data stream
     * are also considered by this method, unlike of the default behavior of the decorated request.
     *
     * If the parameter has a single value, the array has a length of 1.
     *
     * @param name the name of the parameter whose value is requested.
     * @return an array of String objects containing the parameter's values.
     */
    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(name);
        if (values == null && isContentInMultipart()) {
            List<String> listOfValues = FileUploadUtil.getParameterValues(getFileItems(), name,
                    getCharacterEncoding());
            values = listOfValues.toArray(new String[listOfValues.size()]);
        }
        return values;
    }

    /**
     * Returns an Enumeration of String objects containing the names of the parameters contained in
     * this request. If the request has no parameters, the method returns an empty Enumeration. The
     * parameters from a multipart/form-data stream are also considered by this method, unlike of the
     * default behavior of the decorated request.
     *
     * @return an Enumeration of String objects, each String containing the name of a request
     * parameter; or an empty Enumeration if the request has no parameters.
     */
    @Override
    public Enumeration<String> getParameterNames() {
        Enumeration<String> names = super.getParameterNames();
        if (!names.hasMoreElements() && isContentInMultipart()) {
            List<FileItem> items = getFileItems();
            List<String> itemNames = new ArrayList<String>(items.size());
            for (FileItem item : items) {
                if (item.isFormField()) {
                    itemNames.add(item.getFieldName());
                }
            }
            names = Collections.enumeration(itemNames);
        }
        return names;
    }

    /**
     * Returns a java.util.Map of the parameters of this request.
     *
     * Request parameters are extra information sent with the request. For HTTP servlets, parameters
     * are contained in the query string or posted form data. The parameters from a
     * multipart/form-data stream are also considered by this method, unlike of the default behavior
     * of the decorated request.
     *
     * @return an immutable java.util.Map containing parameter names as keys and parameter values as
     * map values. The keys in the parameter map are of type String. The values in the parameter map
     * are of type String array.
     */
    @Override
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> map = super.getParameterMap();
        if (map.isEmpty() && isContentInMultipart()) {
            List<FileItem> items = getFileItems();
            map = new HashMap<String, String[]>(items.size());
            for (FileItem item : items) {
                if (item.isFormField()) {
                    String[] value;
                    try {
                        value = new String[] { item.getString(getCharacterEncoding()) };
                    } catch (UnsupportedEncodingException ex) {
                        value = new String[] { item.getString() };
                    }
                    map.put(item.getFieldName(), value);
                }
            }
            map = Collections.unmodifiableMap(map);
        }
        return map;
    }

    /**
     * Returns the value of a request parameter as a String, or null if the parameter does not exist.
     * Request parameters are extra information sent with the request. For HTTP servlets, parameters
     * are contained in the query string or posted form data. The parameters from a
     * multipart/form-data stream are also considered by this method, unlike of the default behavior
     * of the decorated request.
     *
     * You should only use this method when you are sure the parameter has only one value. If the
     * parameter might have more than one value, use getParameterValues(java.lang.String).
     *
     * If you use this method with a multivalued parameter, the value returned is equal to the first
     * value in the array returned by getParameterValues.
     *
     * If the parameter data was sent in the request body, such as occurs with an HTTP POST request,
     * then reading the body directly via getInputStream() or getReader() can interfere with the
     * execution of this method.
     *
     * @param name the name of the parameter.
     * @return the single value of the parameter.
     */
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if (value == null && isContentInMultipart()) {
            value = FileUploadUtil.getParameter(getFileItems(), name, null, getCharacterEncoding());
        }
        return value;
    }

    /**
     * Get a parameter value as a {@link RequestFile}.
     *
     * @param parameterName the name of the parameter.
     * @return the value of the parameter as a {@link RequestFile}.
     */
    public RequestFile getParameterAsRequestFile(String parameterName) {
        RequestFile requestFile = null;
        FileItem fileItem = FileUploadUtil.getFile(getFileItems(), parameterName);
        if (fileItem != null) {
            requestFile = new RequestFile(fileItem);
        }
        return requestFile;
    }

    /**
     * Get a parameter value as a boolean.
     *
     * @param parameterName the name of the parameter.
     * @return the value of the parameter as a boolean.
     */
    public boolean getParameterAsBoolean(String parameterName) {
        return asBoolean(getParameter(parameterName));
    }

    /**
     * Get a parameter value as a Long.
     *
     * @param parameterName the name of the parameter.
     * @return the value of the parameter as a long.
     */
    public Long getParameterAsLong(String parameterName) {
        return asLong(getParameter(parameterName));
    }

    /**
     * Get a parameter value as a Integer.
     *
     * @param parameterName the name of the parameter.
     * @return the value of the parameter as an integer.
     */
    public Integer getParameterAsInteger(String parameterName) {
        return asInteger(getParameter(parameterName));
    }

    /**
     * Get a date from a date parameter.
     *
     * @param dateParameterName the name of the parameter.
     * @return the value of the parameter as a date.
     * @throws java.text.ParseException if the parameter value isn't a date.
     */
    public Date getParameterAsDate(String dateParameterName) throws ParseException {
        return asDate(getParameter(dateParameterName), null);
    }

    /**
     * Get a date from one date parameter and one hour parameter.
     *
     * @param dateParameterName the name of the date parameter.
     * @param hourParameterName the name of the time parameter.
     * @return the value of the parameter as a date.
     * @throws java.text.ParseException if the parameter value isn't a date.
     */
    public Date getParameterAsDate(String dateParameterName, String hourParameterName) throws ParseException {
        return asDate(getParameter(dateParameterName), getParameter(hourParameterName));
    }

    private <T> boolean asBoolean(T object) {
        if (object instanceof Boolean) {
            return (Boolean) object;
        } else if (object instanceof String) {
            String typedObject = (String) object;
            return StringUtil.getBooleanValue(typedObject);
        }
        if (object != null) {
            throw new NotImplementedException();
        }
        return false;
    }

    private <T> Long asLong(T object) {
        if (object instanceof Number) {
            return ((Number) object).longValue();
        } else if (object instanceof String) {
            String typedObject = (String) object;
            if (StringUtil.isLong(typedObject)) {
                return Long.valueOf(typedObject);
            }
            return null;
        }
        if (object != null) {
            throw new NotImplementedException();
        }
        return null;
    }

    private <T> Integer asInteger(T object) {
        if (object instanceof Number) {
            return ((Number) object).intValue();
        } else if (object instanceof String) {
            String typedObject = (String) object;
            if (StringUtil.isInteger(typedObject)) {
                return Integer.valueOf(typedObject);
            }
            return null;
        }
        if (object != null) {
            throw new NotImplementedException();
        }
        return null;
    }

    private <T> Date asDate(T date, T hour) throws ParseException {
        if (date instanceof String) {
            String typedDate = (String) date;
            String typedHour = (String) hour;
            if (StringUtil.isDefined(typedDate)) {
                return DateUtil.stringToDate(typedDate, typedHour, getUserLanguage());
            }
            return null;
        }
        if (date != null) {
            throw new NotImplementedException();
        }
        return null;
    }

    /**
     * Is the content in this request is encoded in a multipart stream.
     * @return true if the content type of this request is a compilant multipart/form-data stream,
     * false otherwise.
     */
    public boolean isContentInMultipart() {
        return FileUploadUtil.isRequestMultipart(this);
    }

    @Override
    public String getCharacterEncoding() {
        String encoding = super.getCharacterEncoding();
        if (StringUtil.isNotDefined(encoding)) {
            encoding = FileUploadUtil.DEFAULT_ENCODING;
        }
        return encoding;
    }
}