/*
* Copyright (c) 1998-2012 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source 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, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package org.ireland.jnetty.http.wrapper;
import io.netty.handler.codec.http.QueryStringDecoder;
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 java.util.Map.Entry;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import org.ireland.jnetty.dispatch.HttpInvocation;
import org.ireland.jnetty.webapp.WebApp;
public class ForwardRequest extends HttpServletRequestWrapper
{
// the wrapped request
private HttpServletRequest _request;
private HttpServletResponse _response;
//the HttpInvocation for this ForwardRequest
private HttpInvocation _invocation;
//paremeters from the QueryString of forward + Original Parameters
private Map<String, String[]> _parameters;
public ForwardRequest(HttpServletRequest request)
{
super(request);
}
public ForwardRequest(HttpServletRequest request, HttpServletResponse response, HttpInvocation invocation)
{
super(request);
_request = request;
_response = response;
_invocation = invocation;
}
protected HttpInvocation getInvocation()
{
return _invocation;
}
public HttpServletResponse getResponse()
{
return _response;
}
@Override
public ServletContext getServletContext()
{
return _invocation.getWebApp();
}
@Override
public DispatcherType getDispatcherType()
{
return DispatcherType.FORWARD;
}
//
// HttpServletRequest
//
@Override
public String getRequestURI()
{
return _invocation.getContextURI();
}
@Override
public String getContextPath()
{
return _invocation.getFilterChainInvocation().getContextPath();
}
@Override
public String getServletPath()
{
return _invocation.getFilterChainInvocation().getServletPath();
}
@Override
public String getPathInfo()
{
return _invocation.getFilterChainInvocation().getPathInfo();
}
@Override
public String getQueryString()
{
return calculateQueryString();
}
protected String calculateQueryString()
{
// server/10j2
// server/1ks7 vs server/1233
String queryString = _invocation.getQueryString();
if (queryString != null)
return queryString;
return _request.getQueryString();
}
public WebApp getWebApp()
{
return _invocation.getWebApp();
}
@Override
public boolean isAsyncSupported()
{
return _invocation.getFilterChainInvocation().isAsyncSupported() && getRequest().isAsyncSupported();
}
@Override
public AsyncContext startAsync() throws IllegalStateException
{
if (!isAsyncSupported())
throw new IllegalStateException(
"The servlet '"+getServletName()+"' at '"+getServletPath()+"' does not support async because the servlet or one of the filters does not support asynchronous mode."
);
return super.startAsync();
}
public String getServletName()
{
if (_invocation != null)
{
return _invocation.getFilterChainInvocation().getServletName();
}
else
return null;
}
public HttpServletRequest unwrapRequest()
{
HttpServletRequest request = (HttpServletRequest) this.getRequest();
while (request instanceof ForwardRequest)
{
request = (HttpServletRequest) ((ForwardRequest) request).getRequest();
}
return request;
}
//
// parameter/form
//
/**
* Returns an enumeration of the form names.
*/
@Override
public Enumeration<String> getParameterNames()
{
if (_parameters == null)
{
_parameters = calculateQuery();
}
return Collections.enumeration(_parameters.keySet());
}
/**
* Returns a map of the form.
*/
@Override
public Map<String, String[]> getParameterMap()
{
if (_parameters == null)
{
_parameters = calculateQuery();
}
return Collections.unmodifiableMap(_parameters);
}
/**
* Returns the form's values for the given name.
*
* @param name
* key in the form
* @return value matching the key
*/
@Override
public String[] getParameterValues(String name)
{
if (_parameters == null)
{
_parameters = calculateQuery();
}
return _parameters.get(name);
}
/**
* Returns the form primary value for the given name.
*/
@Override
public String getParameter(String name)
{
String[] values = getParameterValues(name);
if (values != null && values.length > 0)
return values[0];
else
return null;
}
////////---------参数合并处理-------------------------------------------------------------
private Map<String, String[]> calculateQuery()
{
Map<String, List<String>> newParameters = parseQuery();
if(newParameters == null || newParameters.isEmpty())
return super.getParameterMap();
Map<String, String[]> oldParameters = super.getParameterMap();
if(oldParameters == null || oldParameters.isEmpty())
return convenMap(newParameters);
return mergeParameters(newParameters,oldParameters);
}
private Map<String, List<String>> parseQuery()
{
String queryString = _invocation.getQueryString();
if(queryString == null || queryString.isEmpty())
return null;
Map<String, List<String>> newParameters = new QueryStringDecoder(queryString,false).parameters();
return newParameters;
}
/**
* 合并新旧参数,新的参数优先
* @param newParameters
* @param oldParameters
* @return
*/
private Map<String,String[]> mergeParameters(Map<String, List<String>> newParameters,Map<String, String[]> oldParameters)
{
for(Entry<String, String[]> e : oldParameters.entrySet())
{
if(e.getValue() != null && e.getValue().length > 0)
{
List<String> list = newParameters.get(e.getKey());
if(list == null)
list = new ArrayList<String>(e.getValue().length);
for(String str : e.getValue())
{
list.add(str);
}
newParameters.put(e.getKey(), list);
}
}
return convenMap(newParameters);
}
private Map<String, String[]> convenMap(Map<String, List<String>> map)
{
Map<String, String[]> newMap = new HashMap<String, String[]>(map.size());
for(Entry<String, List<String>> e : map.entrySet())
{
if(e.getValue() != null)
{
List<String> list = e.getValue();
String[] strs = new String[list.size()];
for(int i=0; i<list.size(); i++)
{
strs[i] = list.get(i);
}
newMap.put(e.getKey(), strs);
}
}
return newMap;
}
//------------------------------------------------------------------------------------
}