/*******************************************************************************
* Signavio Core Components
* Copyright (C) 2012 Signavio GmbH
*
* This program 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 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
/**
*
*/
package com.signavio.platform.filters;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.catalina.util.RequestUtil;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.signavio.platform.exceptions.InputException;
import com.signavio.platform.exceptions.RequestException;
import com.signavio.platform.servlets.DispatcherServlet;
/**
* @author Bjoern Wagner
*
*/
public class ParseParametersFilter implements Filter {
/* (non-Javadoc)
* @see javax.servlet.Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
if (!(req instanceof HttpServletRequest)) {
chain.doFilter(req, res);
}
HttpServletRequest httpReq = (HttpServletRequest) req;
Map<String, List<String>> params = new HashMap<String, List<String>>();
parseUriParameters(httpReq, params);
parseStreamParameters(httpReq, params);
parseRequestParameters(httpReq, params);
filterParameters(params);
JSONObject jsonParams = parametersToJSONObject(params);
httpReq.setAttribute("params", jsonParams);
httpReq.setAttribute("javaParams", params);
chain.doFilter(httpReq, res);
}
/* (non-Javadoc)
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
public void init(FilterConfig config) throws ServletException {
// TODO Auto-generated method stub
}
/**
* Helper method that adds a new parameter to the map
* @param params
* @param key
* @param value
*/
private void addParameter(Map<String, List<String>> params, String key, String value) {
List<String> values = params.get(key);
if (values == null) {
values = new ArrayList<String>();
params.put(key, values);
}
values.add(value);
}
private void parseUriParameters(HttpServletRequest req, Map<String, List<String>> params) {
// get parameters form uri after the extension
String[] path = DispatcherServlet.parseURL( req.getRequestURI() );
if( path[3] != null && !path[3].equals("") ){
try {
addParameter(params, "suffix", URLDecoder.decode( path[3], "utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace(); // ignore exception
}
}
}
/**
* Read all parameters directly from the input stream. Necessary because parameters are not mapped to the
* HttpRequest.getParameter api on PUT requests
* @param req
* @param params
*/
private void parseStreamParameters(HttpServletRequest req, Map<String, List<String>> params) {
try {
String content = this.convertStreamToString(req.getInputStream());
if( content != null && content.length() >= 1 ){
Map<String, String[]> ps = new HashMap<String, String[]>();
RequestUtil.parseParameters(ps, content, "UTF-8");
for (String key : ps.keySet()) {
List<String> param = new ArrayList<String>();
for(String value : ps.get(key)) {
param.add(value);
}
params.put(key, param);
}
}
} catch (IOException e) {
throw new InputException(e);
}
}
/**
* Parse parameters using the HttpRequest API
* @param req
* @param params
*/
@SuppressWarnings("unchecked")
private void parseRequestParameters(HttpServletRequest req, Map<String, List<String>> params) {
// get all parameter and add those to the map
Enumeration<String> paramNames = req.getParameterNames();
while( paramNames.hasMoreElements() ){
String key = paramNames.nextElement();
String[] values = req.getParameterValues(key);
for (String value : values) {
addParameter(params, key, value);
}
}
}
/**
* Remove code from all parameters except those ending with '_xml'
* @param params
*/
private void filterParameters(Map<String, List<String>> params) {
for (String key : params.keySet()) {
if (!key.endsWith("_xml")&&!key.endsWith("_json")) {
List<String> filteredValues = new ArrayList<String>();
for (String value : params.get(key)) {
filteredValues.add(RequestUtil.filter(value));
}
params.put(key, filteredValues);
}
}
}
/**
* Convert map to json object containing strings for single values and a json array
* for multiple values
* @param params
* @return
*/
private JSONObject parametersToJSONObject(Map<String, List<String>> params) {
JSONObject jsonParams = new JSONObject();
for (String key : params.keySet()) {
try {
if (params.get(key).size() == 1) {
jsonParams.put(key, params.get(key).iterator().next());
} else {
jsonParams.put(key, new JSONArray(params.get(key)));
}
} catch(JSONException e) {
e.printStackTrace(); // ignore
}
}
return jsonParams;
}
/**
* Helper method. converts request input stream to java string
* @param is
* @return
*/
private String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
String separator = "";
while ((line = reader.readLine()) != null) {
sb.append(separator + line);
separator = "\n";
}
is.close();
} catch (IOException e) {
try {
is.close();
} catch (IOException e2) {}
throw new RequestException("platform.stream2StringFailed", e);
}
return sb.toString();
}
}