/*
* eXist Open Source Native XML Database
* Copyright (C) 2001-06 Wolfgang M. Meier
* wolfgang@exist-db.org
* http://exist.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package org.exist.http.servlets;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Logger;
import org.exist.xquery.Constants;
/** A wrapper for requests processed by a servlet.
* @author Wolfgang Meier <wolfgang@exist-db.org>
* @author Pierrick Brihaye <pierrick.brihaye@free.fr>
*/
public class HttpRequestWrapper implements RequestWrapper {
private HttpServletRequest servletRequest;
private String formEncoding = null;
private String containerEncoding = null;
private Map params = null;
private String pathInfo = null;
private String servletPath = null;
private static Logger LOG = Logger.getLogger(HttpRequestWrapper.class.getName());
public HttpRequestWrapper(HttpServletRequest servletRequest, String formEncoding,
String containerEncoding) {
this(servletRequest, formEncoding, containerEncoding, true);
}
/**
* Constructs a wrapper for the given servlet request.
* @param servletRequest The request as viewed by the servlet
* @param formEncoding The encoding of the request's forms
* @param containerEncoding The encoding of the servlet
*/
public HttpRequestWrapper(HttpServletRequest servletRequest, String formEncoding,
String containerEncoding, boolean parseMultipart) {
this.servletRequest = servletRequest;
this.formEncoding = formEncoding;
this.containerEncoding = containerEncoding;
this.pathInfo = servletRequest.getPathInfo();
this.servletPath = servletRequest.getServletPath();
if(parseMultipart && ServletFileUpload.isMultipartContent(servletRequest)) {
parseMultipartContent();
}
}
public Object getAttribute(String name) {
return servletRequest.getAttribute(name);
}
public Enumeration getAttributeNames() {
return servletRequest.getAttributeNames();
}
/**
* Returns an array of Cookies
*/
public Cookie[] getCookies()
{
return servletRequest.getCookies();
}
private static void addParameter(Map map, String paramName, Object value)
{
Object old = map.get(paramName);
if(old != null)
{
if(old instanceof List)
{
((List)old).add(value);
}
else
{
ArrayList list = new ArrayList();
list.add(old);
list.add(value);
map.put(paramName, list);
}
}
else
{
map.put(paramName, value);
}
}
/**
* Parses multi-part requests in order to set the parameters.
*/
private void parseMultipartContent() {
// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
// Dizzzz: Wonder why this should be zero
factory.setSizeThreshold(0);
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
try
{
this.params = new HashMap();
List items = upload.parseRequest(this.servletRequest);
for(Iterator i = items.iterator(); i.hasNext(); )
{
FileItem next = (FileItem) i.next();
addParameter(params, next.getFieldName(), next);
}
// Dizzzz: Why not use servletRequest.getParameterMap()
//also get parameters from the querystring
String qs = servletRequest.getQueryString();
if(qs != null && qs.length() > 0)
{
String nvps[] = qs.split("&");
if(nvps != null && nvps.length > 0)
{
HashMap qsParams = new HashMap();
for(int i = 0; i < nvps.length; i++)
{
String nvp[] = nvps[i].split("=");
if(nvp != null && nvp.length == 2 && !params.containsKey(nvp[0]))
{
addParameter(qsParams, nvp[0], nvp[1]);
}
}
params.putAll(qsParams);
}
}
} catch (FileUploadException e) {
// TODO: handle this
e.printStackTrace();
}
}
/**
* Get file item
*
* @param obj List or Fileitem
* @return First Fileitem in list or Fileitem.
*/
private FileItem getFileItem(Object obj) {
if(obj instanceof List)
return (FileItem)((List)obj).get(0);
else
return (FileItem)obj;
}
/**
* @param value
* @return
*/
private String decode(String value) {
if(containerEncoding == null)
//TODO : use file.encoding system property ?
containerEncoding = "ISO-8859-1";
if(containerEncoding.equals(formEncoding))
return value;
try {
byte[] bytes = value.getBytes(containerEncoding);
return new String(bytes, formEncoding);
} catch (UnsupportedEncodingException e) {
LOG.warn(e);
return value;
}
}
/** @see javax.servlet.http.HttpServletRequest#getInputStream()
*/
public InputStream getInputStream() throws IOException {
return servletRequest.getInputStream();
}
/** @see javax.servlet.http.HttpServletRequest#getCharacterEncoding()
*/
public String getCharacterEncoding() {
return servletRequest.getCharacterEncoding();
}
/**@see javax.servlet.http.HttpServletRequest#getContentLength()
*/
public int getContentLength() {
return servletRequest.getContentLength();
}
/**@see javax.servlet.http.HttpServletRequest#getContentType()
*/
public String getContentType() {
return servletRequest.getContentType();
}
/**@see javax.servlet.http.HttpServletRequest#getContextPath()
*/
public String getContextPath() {
return servletRequest.getContextPath();
}
/**@see javax.servlet.http.HttpServletRequest#getHeader(String)
*/
public String getHeader(String arg0) {
return servletRequest.getHeader(arg0);
}
/**@see javax.servlet.http.HttpServletRequest#getCharacterEncoding()
* @return An enumeration of header names
*/
public Enumeration getHeaderNames() {
return servletRequest.getHeaderNames();
}
/**@see javax.servlet.http.HttpServletRequest#getHeaders(String)
*/
public Enumeration getHeaders(String arg0) {
return servletRequest.getHeaders(arg0);
}
/**@see javax.servlet.http.HttpServletRequest#getMethod()
*/
public String getMethod() {
return servletRequest.getMethod();
}
/**@see javax.servlet.http.HttpServletRequest#getParameter(String)
*/
public String getParameter(String name)
{
if(params == null)
{
String value = servletRequest.getParameter(name);
if(formEncoding == null || value == null)
return value;
return decode(value);
}
else
{
Object o = params.get(name);
if(o == null)
{
return null;
}
if(o instanceof List)
{
List lst = ((List)o);
o = lst.get(0);
}
if(o instanceof FileItem)
{
FileItem fi = (FileItem)o;
if(formEncoding == null)
{
return fi.getString();
}
else
{
try
{
return fi.getString(formEncoding);
}
catch (UnsupportedEncodingException e)
{
LOG.warn(e);
return null;
}
}
}
else if(o instanceof String)
{
return (String)o;
}
return null;
}
}
/**@see javax.servlet.http.HttpServletRequest#getParameter(String)
*/
public File getFileUploadParam(String name) {
if(params == null)
return null;
Object o = params.get(name);
if(o == null)
return null;
FileItem item = getFileItem(o);
if(item.isFormField())
return null;
return ((DiskFileItem)item).getStoreLocation();
}
/**@see javax.servlet.http.HttpServletRequest#getParameter(String)
*/
public String getUploadedFileName(String name) {
if(params == null)
return null;
Object o = params.get(name);
if(o == null)
return null;
FileItem item = getFileItem(o);
if(item.isFormField())
return null;
// Get filename from FileItem
String itemName = item.getName();
if(itemName == null)
return null;
// Several browsers, e.g. MSIE send a full path of the LOCALLY stored
// file instead of the filename alone.
// Jakarta's Commons FileUpload package does not repair this
// so we should remove all supplied path information.
// If there are (back) slashes in the Filename, we have
// a full path. Find the last (back) slash, take remaining text
int lastFileSepPos = Math.max(itemName.lastIndexOf("/"), itemName.lastIndexOf("\\") );
String documentName=itemName;
if (lastFileSepPos != Constants.STRING_NOT_FOUND){
documentName=itemName.substring(lastFileSepPos + 1);
}
return documentName;
}
/**@see javax.servlet.http.HttpServletRequest#getParameterNames()
*/
public Enumeration getParameterNames() {
if(params == null)
return servletRequest.getParameterNames();
else {
return Collections.enumeration(params.keySet());
}
}
/**@see javax.servlet.http.HttpServletRequest#getParameterValues(String)
*/
public String[] getParameterValues(String key) {
if(params == null)
{
String[] values = servletRequest.getParameterValues(key);
if(formEncoding == null || values == null)
return values;
for(int i = 0; i < values.length; i++) {
values[i] = decode(values[i]);
}
return values;
}
else
{
Object obj = params.get(key);
if(obj == null)
return null;
String[] values;
if(obj instanceof List)
{
List list = (List)obj;
values = new String[list.size()];
int j = 0;
for(Iterator i = list.iterator(); i.hasNext(); j++)
{
Object o = i.next();
if(o instanceof FileItem)
{
FileItem item = (FileItem)o;
try {
values[j] = formEncoding == null ? item.getString() : item.getString(formEncoding);
} catch (UnsupportedEncodingException e) {
LOG.warn(e);
e.printStackTrace();
}
}
else
{
values[j] = (String)o;
}
}
}
else
{
values = new String[1];
if(obj instanceof FileItem)
{
FileItem item = (FileItem)obj;
try {
values[0] = formEncoding == null ? item.getString() : item.getString(formEncoding);
} catch (UnsupportedEncodingException e) {
LOG.warn(e);
e.printStackTrace();
}
}
else
{
values[0] = (String)obj;
}
}
return values;
}
}
/**@see javax.servlet.http.HttpServletRequest#getPathInfo()
*/
public String getPathInfo() {
return pathInfo;
}
/**@see javax.servlet.http.HttpServletRequest#getPathTranslated()
*/
public String getPathTranslated() {
return servletRequest.getPathTranslated();
}
/**@see javax.servlet.http.HttpServletRequest#getProtocol()
*/
public String getProtocol() {
return servletRequest.getProtocol();
}
/**@see javax.servlet.http.HttpServletRequest#getQueryString()
*/
public String getQueryString() {
return servletRequest.getQueryString();
}
/**@see javax.servlet.http.HttpServletRequest#getRemoteAddr()
*/
public String getRemoteAddr() {
return servletRequest.getRemoteAddr();
}
/**@see javax.servlet.http.HttpServletRequest#getRemoteHost()
*/
public String getRemoteHost() {
return servletRequest.getRemoteHost();
}
/**@see javax.servlet.http.HttpServletRequest#getRemotePort()
*/
public int getRemotePort() {
return servletRequest.getRemotePort();
}
/**@see javax.servlet.http.HttpServletRequest#getRemoteUser()
*/
public String getRemoteUser() {
return servletRequest.getRemoteUser();
}
/**@see javax.servlet.http.HttpServletRequest#getRequestedSessionId()
*/
public String getRequestedSessionId() {
return servletRequest.getRequestedSessionId();
}
/**@see javax.servlet.http.HttpServletRequest#getRequestURI()
*/
public String getRequestURI() {
return servletRequest.getRequestURI();
}
/**@see javax.servlet.http.HttpServletRequest#getRequestURL()
*/
public StringBuffer getRequestURL() {
return servletRequest.getRequestURL();
}
/**@see javax.servlet.http.HttpServletRequest#getScheme()
*/
public String getScheme() {
return servletRequest.getScheme();
}
/**@see javax.servlet.http.HttpServletRequest#getServerName()
*/
public String getServerName() {
return servletRequest.getServerName();
}
/**@see javax.servlet.http.HttpServletRequest#getServerPort()
*/
public int getServerPort() {
return servletRequest.getServerPort();
}
/**@see javax.servlet.http.HttpServletRequest#getServletPath()
*/
public String getServletPath() {
return servletPath;
}
/**@see javax.servlet.http.HttpServletRequest#getSession()
*/
public SessionWrapper getSession() {
HttpSession session = servletRequest.getSession();
if(session == null)
return null;
else
return new HttpSessionWrapper(session);
}
/**@see javax.servlet.http.HttpServletRequest#getSession(boolean)
*/
public SessionWrapper getSession(boolean arg0) {
HttpSession session = servletRequest.getSession(arg0);
if(session == null)
return null;
else
return new HttpSessionWrapper(session);
}
/**@see javax.servlet.http.HttpServletRequest#getUserPrincipal()
*/
public Principal getUserPrincipal() {
return servletRequest.getUserPrincipal();
}
/**@see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie()
*/
public boolean isRequestedSessionIdFromCookie() {
return servletRequest.isRequestedSessionIdFromCookie();
}
/**@see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL()
*/
public boolean isRequestedSessionIdFromURL() {
return servletRequest.isRequestedSessionIdFromURL();
}
/**@see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid()
*/
public boolean isRequestedSessionIdValid() {
return servletRequest.isRequestedSessionIdValid();
}
/**@see javax.servlet.http.HttpServletRequest#isSecure()
*/
public boolean isSecure() {
return servletRequest.isSecure();
}
/**@see javax.servlet.http.HttpServletRequest#isUserInRole(String)
*/
public boolean isUserInRole(String arg0) {
return servletRequest.isUserInRole(arg0);
}
/**@see javax.servlet.http.HttpServletRequest#removeAttribute(String)
*/
public void removeAttribute(String arg0) {
servletRequest.removeAttribute(arg0);
}
/**@see javax.servlet.http.HttpServletRequest#setAttribute(String, Object)
*/
public void setAttribute(String arg0, Object arg1) {
servletRequest.setAttribute(arg0, arg1);
}
/**@see javax.servlet.http.HttpServletRequest#setCharacterEncoding(String)
*/
public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException {
servletRequest.setCharacterEncoding(arg0);
}
public void setPathInfo(String arg0) {
pathInfo = arg0;
}
public void setServletPath(String arg0) {
servletPath = arg0;
}
}