/***
**
** This library 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.1 of the License, or (at your option) any later version.
**
** This library 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 library; if not, write to the Free Software
** Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
**
**/
package com.partydj.io.servlet;
import java.io.*;
import java.net.*;
import java.security.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.google.common.collect.*;
import com.partydj.util.*;
/**
* @author mrappazz
*
*
**/
public class DefaultHttpServletRequest implements HttpServletRequest {
ChunkedByteBuffer requestBytes = new ChunkedByteBuffer();
private Multimap<String, String> parameterMap = HashMultimap.create();
private Map<String, MultipartData> multipartParameterMap = new HashMap<String, MultipartData>();
private String method = null;
private String requestedURI = null;
private String queryString = null;
private String httpVersionInfo = null;
private String contentType = null;
private Map<String, String> headerMap = new HashMap<String, String>();
private String remoteAddress;
public static DefaultHttpServletRequest create(InputStream inStream, InetAddress address) {
try {
DefaultHttpServletRequest request = new DefaultHttpServletRequest();
//should we check for inStream.available()?
request.requestBytes.append(inStream, true);
if (request.requestBytes.size() == 0) {
try {
Thread.sleep(50);
} catch (Exception e) {
}
request.requestBytes.append(inStream, true);
if (request.requestBytes.size() == 0) {
return null;
}
}
request.remoteAddress = address.getHostAddress();
ServletInputStream in = request.getInputStream();
byte[] buffer = new byte[1024];
int bytesRead = in.readLine(buffer, 0, buffer.length);
if (bytesRead > 0 && in.available() > 0) { //while? ignore (return;)
bytesRead = in.readLine(buffer, 0, buffer.length);
}
String initialLine = bytesRead > 0 ? new String(buffer, 0, bytesRead) : "GET / HTTP/1.1";
String[] initialLineParts = initialLine.split("\\s+");
request.method = initialLineParts[0];
request.requestedURI = initialLineParts[1];
try {
request.requestedURI = URLDecoder.decode(request.requestedURI, CharsetConstants.UTF8.name());
} catch (UnsupportedEncodingException e) {
request.requestedURI = URLDecoder.decode(request.requestedURI);
if (request.requestedURI == null) {
request.requestedURI = initialLineParts[1];
}
}
String[] parts = request.requestedURI.split("\\?", 2);
if (parts.length > 1) {
request.requestedURI = parts[0];
request.queryString = parts[1];
String[] paramKV = parts[1].split("&");
for (String kv : paramKV) {
String[] kAndV = kv.split("=");
request.parameterMap.put(kAndV[0], kAndV.length > 1 ? kAndV[1] : null);
}
}
request.httpVersionInfo = initialLineParts[2];
String prevHeaderKey = null;
while ((bytesRead = in.readLine(buffer, 0, buffer.length)) != -1) {
String headerElement = new String(buffer, 0, bytesRead).trim();
if (headerElement == null || headerElement.length() == 0) {
//an empty line signifies the end of the header
break;
}
String[] headerParts = headerElement.split(":", 2);
if (headerParts.length == 2) {
String key = URLDecoder.decode(headerParts[0].trim(), CharsetConstants.UTF8.name());
prevHeaderKey = key;
String value = URLDecoder.decode(headerParts[1].trim(), CharsetConstants.UTF8.name());
request.headerMap.put(key, value);
} else if (prevHeaderKey != null) {
//part of the previous header
String value = URLDecoder.decode(headerParts[0].trim(), CharsetConstants.UTF8.name());
request.headerMap.put(prevHeaderKey, request.headerMap.get(prevHeaderKey) + value);
}
}
//do special processing for POST form data with multipart encoding
String contentType = request.getHeader(HttpConstants.CONTENT_TYPE);
if (HttpConstants.POST.equalsIgnoreCase(request.getMethod()) && contentType != null && contentType.startsWith(HttpConstants.MULTIPART)) {
//seek the boundary marker
String boundaryMarker = null;
for (String contentTypeData : contentType.split("; ?")) {
if (contentTypeData.startsWith(HttpConstants.BOUNDARY)) {
boundaryMarker = contentTypeData.split("=")[1];
}
}
while ((bytesRead = in.readLine(buffer, 0, buffer.length)) != -1) {
if (new String(buffer, 0, bytesRead).trim().endsWith(boundaryMarker)) {
break;
}
}
while (in.available() > 0) {
Map<String, String> multipartDataHeader = new HashMap<String, String>();
//we are now at the beginning of the multipart data
while ((bytesRead = in.readLine(buffer, 0, buffer.length)) != -1) {
String multipartElement = new String(buffer, 0, bytesRead).trim();
if (multipartElement == null || multipartElement.length() == 0) {
//an empty line signifies the end of the multipartContentHeader
break;
}
int splitIndex = multipartElement.indexOf(":");
if (splitIndex >= 0) {
String key = URLDecoder.decode(multipartElement.substring(0, splitIndex), CharsetConstants.UTF8.name());
String value = URLDecoder.decode(multipartElement.substring(splitIndex + 2), CharsetConstants.UTF8.name());
multipartDataHeader.put(key, value);
}
}
//now we are at the data part of the data
CircularByteBuffer endBoundaryMarker = new CircularByteBuffer(boundaryMarker.length());
ChunkedByteBuffer multipartBinaryData = new ChunkedByteBuffer();
byte[] boundaryMarkerBytes = boundaryMarker.getBytes();
int readByte;
while ((readByte = in.read()) != -1) {
endBoundaryMarker.append((byte)readByte);
multipartBinaryData.append((byte)readByte);
if (endBoundaryMarker.isEqualTo(boundaryMarkerBytes)) {
break;
}
}
//read to the end of the line
in.readLine(buffer, 0, buffer.length);
//"unread" the boundary marker from the data
String boundaryMatch = new String(multipartBinaryData.unappend(boundaryMarker.length() + 4));
MultipartData multipart = new MultipartData(multipartDataHeader, multipartBinaryData);
String dataKey = multipart.getSubHeaderValue(HttpConstants.CONTENT_DISPOSITION, "name");
request.multipartParameterMap.put(dataKey, multipart);
//if the multipart has no content type, then it is likely just normal, form data. Try to put it in the regular parameter map.
if (multipart.getHeader(HttpConstants.CONTENT_TYPE) == null) {
request.parameterMap.put(dataKey, multipartBinaryData.toChunkedCharBuffer().toString());
}
}
} else {
String parameterString = null;
if ((bytesRead = in.readLine(buffer, 0, buffer.length)) != -1) {
parameterString = new String(buffer, 0, bytesRead).trim();
while ((bytesRead = in.readLine(buffer, 0, buffer.length)) != -1 && (parameterString == null || parameterString.length() == 0)) {
parameterString = new String(buffer, 0, bytesRead).trim();
}
}
if (parameterString != null && parameterString.length() > 0) {
request.parseParametersFromRequest(parameterString);
}
}
return request;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private DefaultHttpServletRequest() {
}
public ChunkedByteBuffer getRequestBytes() {
return requestBytes;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getAuthType()
*/
public String getAuthType() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getContextPath()
*/
public String getContextPath() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getCookies()
*/
public Cookie[] getCookies() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getDateHeader(java.lang.String)
*/
public long getDateHeader(String headerKey) {
try {
String header = getHeader(headerKey);
try {
Date date = new SimpleDateFormat().parse(header);
return date.getTime();
} catch (ParseException e) {
return Long.valueOf(header).longValue();
}
} catch (Exception e) {
return -1;
}
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String)
*/
public String getHeader(String headerKey) {
return headerMap.get(headerKey);
}
/**
* get the multipart data
*/
public MultipartData getMultipart(String key) {
return multipartParameterMap.get(key);
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getHeaderNames()
*/
public Enumeration getHeaderNames() {
return Collections.enumeration(headerMap.keySet());
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getHeaders(java.lang.String)
*/
public Enumeration getHeaders(String headerKey) {
String header = getHeader(headerKey);
return Collections.enumeration(Arrays.asList(header.split(",")));
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getIntHeader(java.lang.String)
*/
public int getIntHeader(String headerKey) {
try {
return Integer.valueOf(getHeader(headerKey)).intValue();
} catch (Exception e) {
return -1;
}
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getMethod()
*/
public String getMethod() {
return method;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getPathInfo()
*/
public String getPathInfo() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getPathTranslated()
*/
public String getPathTranslated() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getQueryString()
*/
public String getQueryString() {
return queryString;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getRemoteUser()
*/
public String getRemoteUser() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getRequestURI()
*/
public String getRequestURI() {
return requestedURI;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getRequestURL()
*/
public StringBuffer getRequestURL() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getRequestedSessionId()
*/
public String getRequestedSessionId() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getServletPath()
*/
public String getServletPath() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getSession()
*/
public HttpSession getSession() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getSession(boolean)
*/
public HttpSession getSession(boolean arg0) {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#getUserPrincipal()
*/
public Principal getUserPrincipal() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie()
*/
public boolean isRequestedSessionIdFromCookie() {
return false;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL()
*/
public boolean isRequestedSessionIdFromURL() {
return false;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl()
*/
public boolean isRequestedSessionIdFromUrl() {
return false;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid()
*/
public boolean isRequestedSessionIdValid() {
return false;
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String)
*/
public boolean isUserInRole(String arg0) {
return false;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getAttribute(java.lang.String)
*/
public Object getAttribute(String arg0) {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getAttributeNames()
*/
public Enumeration getAttributeNames() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getCharacterEncoding()
*/
public String getCharacterEncoding() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getContentLength()
*/
public int getContentLength() {
return 0;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getContentType()
*/
public String getContentType() {
return contentType != null ? contentType : "text/html";
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getInputStream()
*/
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStream() {
InputStream in = requestBytes.toInputStream();
@Override public int available() throws IOException {
return in.available();
}
@Override public int read() throws IOException {
return in.read();
}
};
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getLocale()
*/
public Locale getLocale() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getLocales()
*/
public Enumeration getLocales() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getParameter(java.lang.String)
*/
public String getParameter(String key) {
String value = null;
Collection<String> valueSet = parameterMap.get(key);
if (valueSet != null && valueSet.size() > 0) {
value = valueSet.iterator().next();
}
return value;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getParameterMap()
*/
public Map getParameterMap() {
return parameterMap.asMap();
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getParameterNames()
*/
public Enumeration getParameterNames() {
return Collections.enumeration(parameterMap.keySet());
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getParameterValues(java.lang.String)
*/
public String[] getParameterValues(String key) {
String[] values = null;
Collection<String> valueSet = parameterMap.get(key);
if (valueSet != null) {
values = valueSet.toArray(new String[valueSet.size()]);
}
return values;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getProtocol()
*/
public String getProtocol() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getReader()
*/
public BufferedReader getReader() throws IOException {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getRealPath(java.lang.String)
*/
public String getRealPath(String arg0) {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getRemoteAddr()
*/
public String getRemoteAddr() {
return remoteAddress;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getRemoteHost()
*/
public String getRemoteHost() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String)
*/
public RequestDispatcher getRequestDispatcher(String arg0) {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getScheme()
*/
public String getScheme() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getServerName()
*/
public String getServerName() {
return null;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#getServerPort()
*/
public int getServerPort() {
return 0;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#isSecure()
*/
public boolean isSecure() {
return false;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#removeAttribute(java.lang.String)
*/
public void removeAttribute(String arg0) {
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object)
*/
public void setAttribute(String arg0, Object arg1) {
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String)
*/
public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException {
}
private void parseParametersFromRequest(String paramString) {
//the last line of the request should have the parameters
if (paramString != null && paramString.length() > 0) {
String[] keyValuePairs = paramString.split("&");
for (String keyValuePair : keyValuePairs) {
String[] keyAndValue = keyValuePair.split("=");
String key = null;
try {
key = URLDecoder.decode(keyAndValue[0], CharsetConstants.UTF8.name());
} catch (UnsupportedEncodingException e) {
key = URLDecoder.decode(keyAndValue[0]);
if (key == null) {
key = keyAndValue[0];
}
}
;
String value = null;
try {
value = keyAndValue.length >= 2 ? URLDecoder.decode(keyAndValue[1], CharsetConstants.UTF8.name()) : null;
} catch (UnsupportedEncodingException e) {
value = URLDecoder.decode(keyAndValue[1]);
if (value == null) {
value = keyAndValue[1];
}
}
parameterMap.put(key, value);
}
}
}
public static class MultipartData {
public Map<String, String> header = null;
public ChunkedByteBuffer data = null;
public MultipartData(Map<String, String> header, ChunkedByteBuffer data) {
this.header = header;
this.data = data;
}
public ChunkedByteBuffer getData() {
return data;
}
public String getSubHeaderValue(String headerKey, String subHeaderKey) {
String headerValue = getHeader(headerKey);
if (headerValue != null) {
String[] subHeaders = headerValue.split("; ?");
for (String subHeaderChunk : subHeaders) {
String[] subHeader = subHeaderChunk.split("=");
if (subHeader.length > 0 && subHeader[0].equals(subHeaderKey)) {
return subHeader.length > 1 ? subHeader[1].substring(1, subHeader[1].length() - 1) : "";
}
}
}
return null;
}
public long getDateHeader(String headerKey) {
try {
String header = getHeader(headerKey);
try {
Date date = new SimpleDateFormat().parse(header);
return date.getTime();
} catch (ParseException e) {
return Long.valueOf(header).longValue();
}
} catch (Exception e) {
return -1;
}
}
public String getHeader(String headerKey) {
return header.get(headerKey);
}
public Enumeration getHeaderNames() {
return Collections.enumeration(header.keySet());
}
public Enumeration getHeaders(String headerKey) {
String header = getHeader(headerKey);
return Collections.enumeration(Arrays.asList(header.split(",")));
}
public int getIntHeader(String headerKey) {
try {
return Integer.valueOf(getHeader(headerKey)).intValue();
} catch (Exception e) {
return -1;
}
}
}
}