[jboss-cvs] jboss-seam/src/main/org/jboss/seam/servlet ...
Shane Bryzak
Shane_Bryzak at symantec.com
Mon Jan 22 11:19:28 EST 2007
User: sbryzak2
Date: 07/01/22 11:19:28
Added: src/main/org/jboss/seam/servlet MultipartRequest.java
SeamMultipartFilter.java
Log:
file upload tag, with _very_ basic support for multipart forms
Revision Changes Path
1.1 date: 2007/01/22 16:19:28; author: sbryzak2; state: Exp;jboss-seam/src/main/org/jboss/seam/servlet/MultipartRequest.java
Index: MultipartRequest.java
===================================================================
package org.jboss.seam.servlet;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* Request wrapper for supporting multipart requests, used for file uploading.
*
* @author Shane Bryzak
*/
public class MultipartRequest extends HttpServletRequestWrapper
{
public static final String WWW_FORM_URLENCODED_TYPE = "application/x-www-form-urlencoded";
private class PartWrapper
{
private Map<String,String> params;
private byte[] data;
public PartWrapper()
{
params = new HashMap<String,String>();
}
public Map<String,String> getParams()
{
return params;
}
public void setData(byte[] data)
{
this.data = data;
}
public byte[] getData()
{
return data;
}
}
private HttpServletRequest request;
private Map<String,PartWrapper> parameters;
public MultipartRequest(HttpServletRequest request)
{
super(request);
this.request = request;
}
private void parseRequest()
{
parameters = new HashMap<String,PartWrapper>();
boundaryMarker = getBoundary(request.getContentType());
if (boundaryMarker == null)
{
throw new RuntimeException("the request was rejected because "
+ "no multipart boundary was found");
}
// String charEncoding = request.getCharacterEncoding();
try
{
buffer = new byte[4096];
bufferEnd = 0;
input = request.getInputStream();
pos = 0;
fillBuffer();
byte[] boundary = readNextBoundary();
while (boundary != null || fillBuffer())
{
if (boundary != null)
parseBoundary(boundary);
boundary = readNextBoundary();
}
}
catch (IOException ex)
{
}
}
private void parseBoundary(byte[] boundary)
{
PartWrapper entry = new PartWrapper();
int start = 0;
for (int i = 0; i < boundary.length; i++)
{
if (checkSequence(boundary, i, CR_LF))
{
if (start < i - CR_LF.length)
{
String line = new String(boundary, start, i - CR_LF.length - start);
parseParams(line, ";", entry.getParams());
start = i;
}
if (checkSequence(boundary, i + CR_LF.length, CR_LF))
{
start = i + CR_LF.length;
break;
}
}
}
byte[] data = new byte[boundary.length - start];
System.arraycopy(boundary, start, data, 0, data.length);
entry.setData(data);
if (entry.getParams().containsKey("name"))
parameters.put(entry.getParams().get("name"), entry);
}
/**
* The boundary marker bytes. Each part is separated by a boundary marker
*/
private byte[] boundaryMarker;
/**
*
*/
private InputStream input;
/**
* Read buffer
*/
private byte[] buffer;
/**
* The read position in the buffer
*/
private int pos;
/**
* Total bytes read
*/
private int totalRead;
/**
* The last written byte position in the buffer
*/
private int bufferEnd;
/**
* Reads more data into the buffer if possible, shuffling the buffer
* contents if required
*
*/
private boolean fillBuffer()
throws IOException
{
if (totalRead >= request.getContentLength())
return false;
// If pos > 0, move the contents to the front of the buffer to make space
if (pos > 0)
{
System.arraycopy(buffer, pos, buffer, 0, bufferEnd - pos);
bufferEnd -= pos;
pos = 0;
}
// If the buffer is full, extend it
if (pos == 0 && bufferEnd >= buffer.length - 1)
{
byte[] newBuffer = new byte[buffer.length * 2];
System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
buffer = newBuffer;
}
int read = input.read(buffer, bufferEnd, buffer.length - bufferEnd);
if (read != -1)
{
bufferEnd += read;
totalRead += read;
}
return read != -1;
}
private static final byte CR = 0x0d;
private static final byte LF = 0x0a;
private static final byte[] CR_LF = {CR,LF};
private byte[] readNextBoundary()
throws IOException
{
int boundaryStart = -1;
for (int i = pos; i < bufferEnd; i++)
{
if (boundaryStart == -1 && checkSequence(buffer, i, boundaryMarker) &&
checkSequence(buffer, i + CR_LF.length, CR_LF))
{
// First boundary marker
boundaryStart = i + CR_LF.length;
}
else if (boundaryStart != -1 && checkSequence(buffer, i, boundaryMarker))
{
// Second boundary marker
byte[] boundary = new byte[i - boundaryMarker.length - boundaryStart - 4];
System.arraycopy(buffer, boundaryStart, boundary, 0, boundary.length);
pos = i - boundaryMarker.length;
return boundary;
}
}
return null;
}
/**
* Checks if a specified sequence of bytes ends at a specific position
* within a byte array.
*
* @param data
* @param pos
* @param seq
* @return boolean indicating if the sequence was found at the specified position
*/
private boolean checkSequence(byte[] data, int pos, byte[] seq)
{
if (pos - seq.length < 0 || pos > data.length)
return false;
for (int i = 0; i < seq.length; i++)
{
if (data[pos - seq.length + i] != seq[i])
return false;
}
return true;
}
private byte[] getBoundary(String contentType)
{
Map<String, String> params = parseParams(contentType, ";");
String boundaryStr = params.get("boundary");
if (boundaryStr == null) return null;
try
{
return boundaryStr.getBytes("ISO-8859-1");
}
catch (UnsupportedEncodingException e)
{
return boundaryStr.getBytes();
}
}
private static final Pattern PARAM_VALUE_PATTERN = Pattern
.compile("^\\s*([^\\s=]+)\\s*[=:]\\s*([^\\s]+)\\s*$");
private void parseParams(String paramStr, String separator, Map<String,String> target)
{
String[] parts = paramStr.split("[" + separator + "]");
for (String part : parts)
{
Matcher m = PARAM_VALUE_PATTERN.matcher(part);
if (m.matches())
{
String value = m.group(2);
// Strip double quotes
if (value.startsWith("\"") && value.endsWith("\""))
value = value.substring(1, value.length() - 1);
target.put(m.group(1), value);
}
}
}
private Map<String, String> parseParams(String paramStr, String separator)
{
Map<String, String> target = new HashMap<String, String>();
parseParams(paramStr, separator, target);
return target;
}
@Override
public Enumeration getParameterNames()
{
if (parameters == null)
parseRequest();
return Collections.enumeration(parameters.keySet());
}
public byte[] getFileBytes(String name)
{
if (parameters == null)
parseRequest();
PartWrapper wrapper = parameters.get(name);
return wrapper != null ? wrapper.getData() : null;
}
@Override
public String getParameter(String name)
{
if (parameters == null)
parseRequest();
PartWrapper wrapper = parameters.get(name);
return wrapper != null ? new String(wrapper.getData()) : super.getParameter(name);
// String[] values = (String[]) parameters.get(name);
//
// if (values == null)
// return null;
//
// return values[0];
}
@Override
public String[] getParameterValues(String name)
{
if (parameters == null)
parseRequest();
// return (String[]) parameters.get(name);
PartWrapper wrapper = parameters.get(name);
return wrapper != null ? new String[] { new String(parameters.get(name).getData()) } :
super.getParameterValues(name);
}
@Override
public Map getParameterMap()
{
if (parameters == null)
parseRequest();
Map<String,Object> params = new HashMap<String,Object>();
for (String name : parameters.keySet())
{
PartWrapper w = parameters.get(name);
params.put(name, new String(w.getData()));
}
return params;
}
@Override
public Object getAttribute(String string)
{
return super.getAttribute(string);
}
@Override
public String getContentType()
{
return WWW_FORM_URLENCODED_TYPE;
}
}
1.1 date: 2007/01/22 16:19:28; author: sbryzak2; state: Exp;jboss-seam/src/main/org/jboss/seam/servlet/SeamMultipartFilter.java
Index: SeamMultipartFilter.java
===================================================================
package org.jboss.seam.servlet;
import java.io.IOException;
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 javax.servlet.http.HttpServletResponse;
public class SeamMultipartFilter implements Filter
{
public static final String MULTIPART = "multipart/";
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
if (!(response instanceof HttpServletResponse))
{
chain.doFilter(request, response);
return;
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
if (isMultipartRequest(httpRequest))
{
chain.doFilter(new MultipartRequest(httpRequest), response);
}
else
{
chain.doFilter(request, response);
}
}
private boolean isMultipartRequest(HttpServletRequest request)
{
if (!"post".equals(request.getMethod().toLowerCase()))
{
return false;
}
String contentType = request.getContentType();
if (contentType == null)
{
return false;
}
if (contentType.toLowerCase().startsWith(MULTIPART))
{
return true;
}
return false;
}
public void init(FilterConfig filterConfig) { }
public void destroy() { }
}
More information about the jboss-cvs-commits
mailing list