Replaced tabs with 4 spaces.

This commit is contained in:
vibul 2012-04-27 09:32:35 +10:00
parent 802e5366b2
commit 66b4735acd
22 changed files with 4123 additions and 4252 deletions

View File

@ -28,13 +28,14 @@ import org.jboss.netty.util.CharsetUtil;
public class HttpUploadClientHandler extends SimpleChannelUpstreamHandler {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(HttpUploadClientHandler.class);
private static final InternalLogger logger = InternalLoggerFactory
.getInstance(HttpUploadClientHandler.class);
private volatile boolean readingChunks;
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
if (!readingChunks) {
HttpResponse response = (HttpResponse) e.getMessage();
@ -42,8 +43,8 @@ public class HttpUploadClientHandler extends SimpleChannelUpstreamHandler {
logger.info("VERSION: " + response.getProtocolVersion());
if (!response.getHeaderNames().isEmpty()) {
for (String name: response.getHeaderNames()) {
for (String value: response.getHeaders(name)) {
for (String name : response.getHeaderNames()) {
for (String value : response.getHeaders(name)) {
logger.info("HEADER: " + name + " = " + value);
}
}

View File

@ -41,8 +41,8 @@ public class HttpUploadClientPipelineFactory implements ChannelPipelineFactory {
// Enable HTTPS if necessary.
if (ssl) {
SSLEngine engine =
SecureChatSslContextFactory.getClientContext().createSSLEngine();
SSLEngine engine = SecureChatSslContextFactory.getClientContext()
.createSSLEngine();
engine.setUseClientMode(true);
pipeline.addLast("ssl", new SslHandler(engine));
@ -50,7 +50,8 @@ public class HttpUploadClientPipelineFactory implements ChannelPipelineFactory {
pipeline.addLast("codec", new HttpClientCodec());
// Remove the following line if you don't want automatic content decompression.
// Remove the following line if you don't want automatic content
// decompression.
pipeline.addLast("inflater", new HttpContentDecompressor());
// to be used since huge file transfer

View File

@ -64,8 +64,8 @@ import org.jboss.netty.util.CharsetUtil;
public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(HttpUploadServerHandler.class);
private static final InternalLogger logger = InternalLoggerFactory
.getInstance(HttpUploadServerHandler.class);
private volatile HttpRequest request;
@ -96,7 +96,8 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
if (!readingChunks) {
// clean previous FileUpload if Any
if (decoder != null) {
@ -115,18 +116,18 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
responseContent.append("WELCOME TO THE WILD WILD WEB SERVER\r\n");
responseContent.append("===================================\r\n");
responseContent.append("VERSION: " +
request.getProtocolVersion().getText() + "\r\n");
responseContent.append("VERSION: "
+ request.getProtocolVersion().getText() + "\r\n");
responseContent.append("REQUEST_URI: " + request.getUri() +
"\r\n\r\n");
responseContent.append("REQUEST_URI: " + request.getUri()
+ "\r\n\r\n");
responseContent.append("\r\n\r\n");
// new method
List<Entry<String, String>> headers = request.getHeaders();
for (Entry<String, String> entry: headers) {
responseContent.append("HEADER: " + entry.getKey() + "=" +
entry.getValue() + "\r\n");
for (Entry<String, String> entry : headers) {
responseContent.append("HEADER: " + entry.getKey() + "="
+ entry.getValue() + "\r\n");
}
responseContent.append("\r\n\r\n");
@ -139,19 +140,19 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
CookieDecoder decoder = new CookieDecoder();
cookies = decoder.decode(value);
}
for (Cookie cookie: cookies) {
for (Cookie cookie : cookies) {
responseContent.append("COOKIE: " + cookie.toString() + "\r\n");
}
responseContent.append("\r\n\r\n");
QueryStringDecoder decoderQuery = new QueryStringDecoder(request
.getUri());
QueryStringDecoder decoderQuery = new QueryStringDecoder(
request.getUri());
Map<String, List<String>> uriAttributes = decoderQuery
.getParameters();
for (String key: uriAttributes.keySet()) {
for (String valuen: uriAttributes.get(key)) {
responseContent.append("URI: " + key + "=" + valuen +
"\r\n");
for (String key : uriAttributes.keySet()) {
for (String valuen : uriAttributes.get(key)) {
responseContent.append("URI: " + key + "=" + valuen
+ "\r\n");
}
}
responseContent.append("\r\n\r\n");
@ -174,10 +175,10 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
return;
}
responseContent.append("Is Chunked: " + request.isChunked() +
"\r\n");
responseContent.append("IsMultipart: " + decoder.isMultipart() +
"\r\n");
responseContent.append("Is Chunked: " + request.isChunked()
+ "\r\n");
responseContent.append("IsMultipart: " + decoder.isMultipart()
+ "\r\n");
if (request.isChunked()) {
// Chunk version
responseContent.append("Chunks: ");
@ -202,7 +203,8 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
return;
}
responseContent.append("o");
// example of reading chunk by chunk (minimize memory usage due to Factory)
// example of reading chunk by chunk (minimize memory usage due to
// Factory)
readHttpDataChunkByChunk(e.getChannel());
// example of reading only if at the end
if (chunk.isLast()) {
@ -230,7 +232,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
Channels.close(channel);
return;
}
for (InterfaceHttpData data: datas) {
for (InterfaceHttpData data : datas) {
writeHttpData(data);
}
responseContent.append("\r\n\r\nEND OF CONTENT AT FINAL END\r\n");
@ -267,25 +269,25 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
} catch (IOException e1) {
// Error while reading data from File, only print name and error
e1.printStackTrace();
responseContent.append("\r\nBODY Attribute: " +
attribute.getHttpDataType().name() + ": " +
attribute.getName() + " Error while reading value: " +
e1.getMessage() + "\r\n");
responseContent.append("\r\nBODY Attribute: "
+ attribute.getHttpDataType().name() + ": "
+ attribute.getName() + " Error while reading value: "
+ e1.getMessage() + "\r\n");
return;
}
if (value.length() > 100) {
responseContent.append("\r\nBODY Attribute: " +
attribute.getHttpDataType().name() + ": " +
attribute.getName() + " data too long\r\n");
responseContent.append("\r\nBODY Attribute: "
+ attribute.getHttpDataType().name() + ": "
+ attribute.getName() + " data too long\r\n");
} else {
responseContent.append("\r\nBODY Attribute: " +
attribute.getHttpDataType().name() + ": " +
attribute.toString() + "\r\n");
responseContent.append("\r\nBODY Attribute: "
+ attribute.getHttpDataType().name() + ": "
+ attribute.toString() + "\r\n");
}
} else {
responseContent.append("\r\nBODY FileUpload: " +
data.getHttpDataType().name() + ": " + data.toString() +
"\r\n");
responseContent.append("\r\nBODY FileUpload: "
+ data.getHttpDataType().name() + ": " + data.toString()
+ "\r\n");
if (data.getHttpDataType() == HttpDataType.FileUpload) {
FileUpload fileUpload = (FileUpload) data;
if (fileUpload.isCompleted()) {
@ -303,8 +305,8 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
responseContent.append("\r\n");
} else {
responseContent
.append("\tFile too long to be printed out:" +
fileUpload.length() + "\r\n");
.append("\tFile too long to be printed out:"
+ fileUpload.length() + "\r\n");
}
// fileUpload.isInMemory();// tells if the file is in Memory
// or on File
@ -322,15 +324,15 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
private void writeResponse(Channel channel) {
// Convert the response content to a ChannelBuffer.
ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent
.toString(), CharsetUtil.UTF_8);
ChannelBuffer buf = ChannelBuffers.copiedBuffer(
responseContent.toString(), CharsetUtil.UTF_8);
responseContent.setLength(0);
// Decide whether to close the connection or not.
boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(request
.getHeader(HttpHeaders.Names.CONNECTION)) ||
request.getProtocolVersion().equals(HttpVersion.HTTP_1_0) &&
!HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request
.getHeader(HttpHeaders.Names.CONNECTION))
|| request.getProtocolVersion().equals(HttpVersion.HTTP_1_0)
&& !HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request
.getHeader(HttpHeaders.Names.CONNECTION));
// Build the response object.
@ -343,8 +345,8 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
if (!close) {
// There's no need to add 'Content-Length' header
// if this is the last response.
response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String
.valueOf(buf.readableBytes()));
response.setHeader(HttpHeaders.Names.CONTENT_LENGTH,
String.valueOf(buf.readableBytes()));
}
Set<Cookie> cookies;
@ -358,11 +360,11 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
if (!cookies.isEmpty()) {
// Reset the cookies if necessary.
CookieEncoder cookieEncoder = new CookieEncoder(true);
for (Cookie cookie: cookies) {
for (Cookie cookie : cookies) {
cookieEncoder.addCookie(cookie);
}
response.addHeader(HttpHeaders.Names.SET_COOKIE, cookieEncoder
.encode());
response.addHeader(HttpHeaders.Names.SET_COOKIE,
cookieEncoder.encode());
}
// Write the response.
ChannelFuture future = channel.write(response);
@ -468,16 +470,16 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
responseContent.append("</body>");
responseContent.append("</html>");
ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent
.toString(), CharsetUtil.UTF_8);
ChannelBuffer buf = ChannelBuffers.copiedBuffer(
responseContent.toString(), CharsetUtil.UTF_8);
// Build the response object.
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1,
HttpResponseStatus.OK);
response.setContent(buf);
response.setHeader(HttpHeaders.Names.CONTENT_TYPE,
"text/html; charset=UTF-8");
response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buf
.readableBytes()));
response.setHeader(HttpHeaders.Names.CONTENT_LENGTH,
String.valueOf(buf.readableBytes()));
// Write the response.
e.getChannel().write(response);
}

View File

@ -30,15 +30,17 @@ public class HttpUploadServerPipelineFactory implements ChannelPipelineFactory {
ChannelPipeline pipeline = pipeline();
// Uncomment the following line if you want HTTPS
//SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
//engine.setUseClientMode(false);
//pipeline.addLast("ssl", new SslHandler(engine));
// SSLEngine engine =
// SecureChatSslContextFactory.getServerContext().createSSLEngine();
// engine.setUseClientMode(false);
// pipeline.addLast("ssl", new SslHandler(engine));
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("encoder", new HttpResponseEncoder());
// Remove the following line if you don't want automatic content compression.
// Remove the following line if you don't want automatic content
// compression.
pipeline.addLast("deflater", new HttpContentCompressor());
pipeline.addLast("handler", new HttpUploadServerHandler());

View File

@ -21,8 +21,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import org.jboss.netty.handler.codec.http.HttpRequest;
/**
* Default factory giving Attribute and FileUpload according to constructor
*

View File

@ -18,8 +18,6 @@ package org.jboss.netty.handler.codec.http;
import java.io.File;
import java.nio.charset.Charset;
import org.jboss.netty.handler.codec.http.HttpHeaders;
/**
* Disk FileUpload implementation that stores file into real files
*/

View File

@ -26,21 +26,12 @@ import java.util.TreeMap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.handler.codec.http.HttpChunk;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpPostBodyUtil.TransferEncodingMechanism;
import org.jboss.netty.handler.codec.http.HttpRequest;
/**
* This decoder will decode Body and can handle POST BODY.
*/
public class HttpPostRequestDecoder {
static final String MULTIPART_FORM_DATA = "multipart/form-data";
static final String BOUNDARY = "boundary";
/**
* Factory used to create InterfaceHttpData
*/
@ -98,8 +89,8 @@ public class HttpPostRequestDecoder {
private String multipartDataBoundary;
/**
* If multipart, there could be internal multiparts (mixed) to the global
* multipart. Only one level is allowed.
* If multipart, there could be internal multiparts (mixed) to the global multipart.
* Only one level is allowed.
*/
private String multipartMixedBoundary;
@ -125,15 +116,10 @@ public class HttpPostRequestDecoder {
/**
*
* @param request
* the request to decode
* @throws NullPointerException
* for request
* @throws IncompatibleDataDecoderException
* if the request has no body to decode
* @throws ErrorDataDecoderException
* if the default charset was wrong when decoding or other
* errors
* @param request the request to decode
* @throws NullPointerException for request
* @throws IncompatibleDataDecoderException if the request has no body to decode
* @throws ErrorDataDecoderException if the default charset was wrong when decoding or other errors
*/
public HttpPostRequestDecoder(HttpRequest request)
throws ErrorDataDecoderException, IncompatibleDataDecoderException {
@ -143,17 +129,11 @@ public class HttpPostRequestDecoder {
/**
*
* @param factory
* the factory used to create InterfaceHttpData
* @param request
* the request to decode
* @throws NullPointerException
* for request or factory
* @throws IncompatibleDataDecoderException
* if the request has no body to decode
* @throws ErrorDataDecoderException
* if the default charset was wrong when decoding or other
* errors
* @param factory the factory used to create InterfaceHttpData
* @param request the request to decode
* @throws NullPointerException for request or factory
* @throws IncompatibleDataDecoderException if the request has no body to decode
* @throws ErrorDataDecoderException if the default charset was wrong when decoding or other errors
*/
public HttpPostRequestDecoder(HttpDataFactory factory, HttpRequest request)
throws ErrorDataDecoderException, IncompatibleDataDecoderException {
@ -162,19 +142,12 @@ public class HttpPostRequestDecoder {
/**
*
* @param factory
* the factory used to create InterfaceHttpData
* @param request
* the request to decode
* @param charset
* the charset to use as default
* @throws NullPointerException
* for request or charset or factory
* @throws IncompatibleDataDecoderException
* if the request has no body to decode
* @throws ErrorDataDecoderException
* if the default charset was wrong when decoding or other
* errors
* @param factory the factory used to create InterfaceHttpData
* @param request the request to decode
* @param charset the charset to use as default
* @throws NullPointerException for request or charset or factory
* @throws IncompatibleDataDecoderException if the request has no body to decode
* @throws ErrorDataDecoderException if the default charset was wrong when decoding or other errors
*/
public HttpPostRequestDecoder(HttpDataFactory factory, HttpRequest request,
Charset charset) throws ErrorDataDecoderException,
@ -190,16 +163,14 @@ public class HttpPostRequestDecoder {
}
this.request = request;
HttpMethod method = request.getMethod();
if (method.equals(HttpMethod.POST) || method.equals(HttpMethod.PUT)
|| method.equals(HttpMethod.PATCH)) {
if (method.equals(HttpMethod.POST) || method.equals(HttpMethod.PUT) || method.equals(HttpMethod.PATCH)) {
bodyToDecode = true;
}
this.charset = charset;
this.factory = factory;
// Fill default values
if (this.request.containsHeader(HttpHeaders.Names.CONTENT_TYPE)) {
checkMultipart(this.request
.getHeader(HttpHeaders.Names.CONTENT_TYPE));
checkMultipart(this.request.getHeader(HttpHeaders.Names.CONTENT_TYPE));
} else {
isMultipart = false;
}
@ -214,43 +185,61 @@ public class HttpPostRequestDecoder {
}
/**
* states follow NOTSTARTED PREAMBLE ( (HEADERDELIMITER DISPOSITION (FIELD |
* FILEUPLOAD))* (HEADERDELIMITER DISPOSITION MIXEDPREAMBLE (MIXEDDELIMITER
* MIXEDDISPOSITION MIXEDFILEUPLOAD)+ MIXEDCLOSEDELIMITER)* CLOSEDELIMITER)+
* EPILOGUE
* states follow
* NOTSTARTED PREAMBLE (
* (HEADERDELIMITER DISPOSITION (FIELD | FILEUPLOAD))*
* (HEADERDELIMITER DISPOSITION MIXEDPREAMBLE
* (MIXEDDELIMITER MIXEDDISPOSITION MIXEDFILEUPLOAD)+
* MIXEDCLOSEDELIMITER)*
* CLOSEDELIMITER)+ EPILOGUE
*
* First status is: NOSTARTED
*
* Content-type: multipart/form-data, boundary=AaB03x => PREAMBLE in Header
*
* --AaB03x => HEADERDELIMITER content-disposition: form-data; name="field1"
* => DISPOSITION
*
* Joe Blow => FIELD --AaB03x => HEADERDELIMITER content-disposition:
* form-data; name="pics" => DISPOSITION Content-type: multipart/mixed,
* boundary=BbC04y
*
* --BbC04y => MIXEDDELIMITER Content-disposition: attachment;
* filename="file1.txt" => MIXEDDISPOSITION Content-Type: text/plain
*
* ... contents of file1.txt ... => MIXEDFILEUPLOAD --BbC04y =>
* MIXEDDELIMITER Content-disposition: file; filename="file2.gif" =>
* MIXEDDISPOSITION Content-type: image/gif Content-Transfer-Encoding:
* binary
*
* ...contents of file2.gif... => MIXEDFILEUPLOAD --BbC04y-- =>
* MIXEDCLOSEDELIMITER --AaB03x-- => CLOSEDELIMITER
*
* Once CLOSEDELIMITER is found, last status is EPILOGUE
Content-type: multipart/form-data, boundary=AaB03x => PREAMBLE in Header
--AaB03x => HEADERDELIMITER
content-disposition: form-data; name="field1" => DISPOSITION
Joe Blow => FIELD
--AaB03x => HEADERDELIMITER
content-disposition: form-data; name="pics" => DISPOSITION
Content-type: multipart/mixed, boundary=BbC04y
--BbC04y => MIXEDDELIMITER
Content-disposition: attachment; filename="file1.txt" => MIXEDDISPOSITION
Content-Type: text/plain
... contents of file1.txt ... => MIXEDFILEUPLOAD
--BbC04y => MIXEDDELIMITER
Content-disposition: file; filename="file2.gif" => MIXEDDISPOSITION
Content-type: image/gif
Content-Transfer-Encoding: binary
...contents of file2.gif... => MIXEDFILEUPLOAD
--BbC04y-- => MIXEDCLOSEDELIMITER
--AaB03x-- => CLOSEDELIMITER
Once CLOSEDELIMITER is found, last status is EPILOGUE
*/
private enum MultiPartStatus {
NOTSTARTED, PREAMBLE, HEADERDELIMITER, DISPOSITION, FIELD, FILEUPLOAD, MIXEDPREAMBLE, MIXEDDELIMITER, MIXEDDISPOSITION, MIXEDFILEUPLOAD, MIXEDCLOSEDELIMITER, CLOSEDELIMITER, PREEPILOGUE, EPILOGUE
NOTSTARTED,
PREAMBLE,
HEADERDELIMITER,
DISPOSITION,
FIELD,
FILEUPLOAD,
MIXEDPREAMBLE,
MIXEDDELIMITER,
MIXEDDISPOSITION,
MIXEDFILEUPLOAD,
MIXEDCLOSEDELIMITER,
CLOSEDELIMITER,
PREEPILOGUE,
EPILOGUE
}
/**
* Check from the request ContentType if this request is a Multipart
* request.
*
* Check from the request ContentType if this request is a Multipart request.
* @param contentType
* @throws ErrorDataDecoderException
*/
@ -259,9 +248,9 @@ public class HttpPostRequestDecoder {
// Check if Post using "multipart/form-data; boundary=--89421926422648"
String[] headerContentType = splitHeaderContentType(contentType);
if (headerContentType[0].toLowerCase().startsWith(
MULTIPART_FORM_DATA)
&& headerContentType[1].toLowerCase().startsWith(
BOUNDARY)) {
HttpHeaders.Values.MULTIPART_FORM_DATA) &&
headerContentType[1].toLowerCase().startsWith(
HttpHeaders.Values.BOUNDARY)) {
String[] boundary = headerContentType[1].split("=");
if (boundary.length != 2) {
throw new ErrorDataDecoderException("Needs a boundary value");
@ -276,7 +265,6 @@ public class HttpPostRequestDecoder {
/**
* True if this request is a Multipart request
*
* @return True if this request is a Multipart request
*/
public boolean isMultipart() {
@ -286,12 +274,11 @@ public class HttpPostRequestDecoder {
/**
* This method returns a List of all HttpDatas from body.<br>
*
* If chunked, all chunks must have been offered using offer() method. If
* not, NotEnoughDataDecoderException will be raised.
* If chunked, all chunks must have been offered using offer() method.
* If not, NotEnoughDataDecoderException will be raised.
*
* @return the list of HttpDatas from Body part for POST method
* @throws NotEnoughDataDecoderException
* Need more chunks
* @throws NotEnoughDataDecoderException Need more chunks
*/
public List<InterfaceHttpData> getBodyHttpDatas()
throws NotEnoughDataDecoderException {
@ -302,16 +289,14 @@ public class HttpPostRequestDecoder {
}
/**
* This method returns a List of all HttpDatas with the given name from
* body.<br>
*
* If chunked, all chunks must have been offered using offer() method. If
* not, NotEnoughDataDecoderException will be raised.
* This method returns a List of all HttpDatas with the given name from body.<br>
*
* If chunked, all chunks must have been offered using offer() method.
* If not, NotEnoughDataDecoderException will be raised.
* @param name
* @return All Body HttpDatas with the given name (ignore case)
* @throws NotEnoughDataDecoderException
* need more chunks
* @throws NotEnoughDataDecoderException need more chunks
*/
public List<InterfaceHttpData> getBodyHttpDatas(String name)
throws NotEnoughDataDecoderException {
@ -322,17 +307,14 @@ public class HttpPostRequestDecoder {
}
/**
* This method returns the first InterfaceHttpData with the given name from
* body.<br>
* This method returns the first InterfaceHttpData with the given name from body.<br>
*
* If chunked, all chunks must have been offered using offer() method. If
* not, NotEnoughDataDecoderException will be raised.
* If chunked, all chunks must have been offered using offer() method.
* If not, NotEnoughDataDecoderException will be raised.
*
* @param name
* @return The first Body InterfaceHttpData with the given name (ignore
* case)
* @throws NotEnoughDataDecoderException
* need more chunks
* @return The first Body InterfaceHttpData with the given name (ignore case)
* @throws NotEnoughDataDecoderException need more chunks
*/
public InterfaceHttpData getBodyHttpData(String name)
throws NotEnoughDataDecoderException {
@ -348,23 +330,19 @@ public class HttpPostRequestDecoder {
/**
* Initialized the internals from a new chunk
*
* @param chunk
* the new received chunk
* @throws ErrorDataDecoderException
* if there is a problem with the charset decoding or other
* errors
* @param chunk the new received chunk
* @throws ErrorDataDecoderException if there is a problem with the charset decoding or
* other errors
*/
public void offer(HttpChunk chunk) throws ErrorDataDecoderException {
ChannelBuffer chunked = chunk.getContent();
if (undecodedChunk == null) {
undecodedChunk = chunked;
} else {
// undecodedChunk = ChannelBuffers.wrappedBuffer(undecodedChunk,
// chunk.getContent());
//undecodedChunk = ChannelBuffers.wrappedBuffer(undecodedChunk, chunk.getContent());
// less memory usage
undecodedChunk = ChannelBuffers.wrappedBuffer(undecodedChunk,
chunked);
undecodedChunk = ChannelBuffers.wrappedBuffer(
undecodedChunk, chunked);
}
if (chunk.isLast()) {
isLastChunk = true;
@ -373,14 +351,12 @@ public class HttpPostRequestDecoder {
}
/**
* True if at current status, there is an available decoded
* InterfaceHttpData from the Body.
* True if at current status, there is an available decoded InterfaceHttpData from the Body.
*
* This method works for chunked and not chunked request.
*
* @return True if at current status, there is a decoded InterfaceHttpData
* @throws EndOfDataDecoderException
* No more data will be available
* @throws EndOfDataDecoderException No more data will be available
*/
public boolean hasNext() throws EndOfDataDecoderException {
if (currentStatus == MultiPartStatus.EPILOGUE) {
@ -389,18 +365,16 @@ public class HttpPostRequestDecoder {
throw new EndOfDataDecoderException();
}
}
return bodyListHttpData.size() > 0
&& bodyListHttpDataRank < bodyListHttpData.size();
return bodyListHttpData.size() > 0 &&
bodyListHttpDataRank < bodyListHttpData.size();
}
/**
* Returns the next available InterfaceHttpData or null if, at the time it
* is called, there is no more available InterfaceHttpData. A subsequent
* call to offer(httpChunk) could enable more data.
* Returns the next available InterfaceHttpData or null if, at the time it is called, there is no more
* available InterfaceHttpData. A subsequent call to offer(httpChunk) could enable more data.
*
* @return the next available InterfaceHttpData or null if none
* @throws EndOfDataDecoderException
* No more data will be available
* @throws EndOfDataDecoderException No more data will be available
*/
public InterfaceHttpData next() throws EndOfDataDecoderException {
if (hasNext()) {
@ -411,14 +385,12 @@ public class HttpPostRequestDecoder {
/**
* This method will parse as much as possible data and fill the list and map
*
* @throws ErrorDataDecoderException
* if there is a problem with the charset decoding or other
* errors
* @throws ErrorDataDecoderException if there is a problem with the charset decoding or
* other errors
*/
private void parseBody() throws ErrorDataDecoderException {
if (currentStatus == MultiPartStatus.PREEPILOGUE
|| currentStatus == MultiPartStatus.EPILOGUE) {
if (currentStatus == MultiPartStatus.PREEPILOGUE ||
currentStatus == MultiPartStatus.EPILOGUE) {
if (isLastChunk) {
currentStatus = MultiPartStatus.EPILOGUE;
}
@ -433,7 +405,6 @@ public class HttpPostRequestDecoder {
/**
* Utility function to add a new decoded data
*
* @param data
*/
private void addHttpData(InterfaceHttpData data) {
@ -450,12 +421,11 @@ public class HttpPostRequestDecoder {
}
/**
* This method fill the map and list with as much Attribute as possible from
* Body in not Multipart mode.
* This method fill the map and list with as much Attribute as possible from Body in
* not Multipart mode.
*
* @throws ErrorDataDecoderException
* if there is a problem with the charset decoding or other
* errors
* @throws ErrorDataDecoderException if there is a problem with the charset decoding or
* other errors
*/
private void parseBodyAttributes() throws ErrorDataDecoderException {
int firstpos = undecodedChunk.readerIndex();
@ -476,19 +446,15 @@ public class HttpPostRequestDecoder {
currentStatus = MultiPartStatus.FIELD;
equalpos = currentpos - 1;
String key = decodeAttribute(
undecodedChunk.toString(firstpos, equalpos
- firstpos, charset), charset);
currentAttribute = factory
.createAttribute(request, key);
undecodedChunk.toString(firstpos, equalpos - firstpos, charset),
charset);
currentAttribute = factory.createAttribute(request, key);
firstpos = currentpos;
} else if (read == '&') { // special empty FIELD
currentStatus = MultiPartStatus.DISPOSITION;
ampersandpos = currentpos - 1;
String key = decodeAttribute(
undecodedChunk.toString(firstpos, ampersandpos
- firstpos, charset), charset);
currentAttribute = factory
.createAttribute(request, key);
String key = decodeAttribute(undecodedChunk.toString(firstpos, ampersandpos - firstpos, charset), charset);
currentAttribute = factory.createAttribute(request, key);
currentAttribute.setValue(""); // empty
addHttpData(currentAttribute);
currentAttribute = null;
@ -500,8 +466,7 @@ public class HttpPostRequestDecoder {
if (read == '&') {
currentStatus = MultiPartStatus.DISPOSITION;
ampersandpos = currentpos - 1;
setFinalBuffer(undecodedChunk.slice(firstpos,
ampersandpos - firstpos));
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos));
firstpos = currentpos;
contRead = true;
} else if (read == HttpCodecUtil.CR) {
@ -511,15 +476,14 @@ public class HttpPostRequestDecoder {
if (read == HttpCodecUtil.LF) {
currentStatus = MultiPartStatus.PREEPILOGUE;
ampersandpos = currentpos - 2;
setFinalBuffer(undecodedChunk.slice(firstpos,
ampersandpos - firstpos));
setFinalBuffer(
undecodedChunk.slice(firstpos, ampersandpos - firstpos));
firstpos = currentpos;
contRead = false;
} else {
// Error
contRead = false;
throw new ErrorDataDecoderException(
"Bad end of line");
throw new ErrorDataDecoderException("Bad end of line");
}
} else {
currentpos--;
@ -527,8 +491,8 @@ public class HttpPostRequestDecoder {
} else if (read == HttpCodecUtil.LF) {
currentStatus = MultiPartStatus.PREEPILOGUE;
ampersandpos = currentpos - 1;
setFinalBuffer(undecodedChunk.slice(firstpos,
ampersandpos - firstpos));
setFinalBuffer(
undecodedChunk.slice(firstpos, ampersandpos - firstpos));
firstpos = currentpos;
contRead = false;
}
@ -542,9 +506,9 @@ public class HttpPostRequestDecoder {
// special case
ampersandpos = currentpos;
if (ampersandpos > firstpos) {
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos
- firstpos));
} else if (!currentAttribute.isCompleted()) {
setFinalBuffer(
undecodedChunk.slice(firstpos, ampersandpos - firstpos));
} else if (! currentAttribute.isCompleted()) {
setFinalBuffer(ChannelBuffers.EMPTY_BUFFER);
}
firstpos = currentpos;
@ -555,8 +519,8 @@ public class HttpPostRequestDecoder {
// reset index except if to continue in case of FIELD status
if (currentStatus == MultiPartStatus.FIELD) {
currentAttribute.addContent(
undecodedChunk.slice(firstpos, currentpos
- firstpos), false);
undecodedChunk.slice(firstpos, currentpos - firstpos),
false);
firstpos = currentpos;
}
undecodedChunk.readerIndex(firstpos);
@ -574,11 +538,11 @@ public class HttpPostRequestDecoder {
}
}
private void setFinalBuffer(ChannelBuffer buffer)
throws ErrorDataDecoderException, IOException {
private void setFinalBuffer(ChannelBuffer buffer) throws ErrorDataDecoderException, IOException {
currentAttribute.addContent(buffer, true);
String value = decodeAttribute(currentAttribute.getChannelBuffer()
.toString(charset), charset);
String value = decodeAttribute(
currentAttribute.getChannelBuffer().toString(charset),
charset);
currentAttribute.setValue(value);
addHttpData(currentAttribute);
currentAttribute = null;
@ -586,7 +550,6 @@ public class HttpPostRequestDecoder {
/**
* Decode component
*
* @param s
* @param charset
* @return the decoded component
@ -607,9 +570,7 @@ public class HttpPostRequestDecoder {
/**
* Parse the Body for multipart
*
* @throws ErrorDataDecoderException
* if there is a problem with the charset decoding or other
* errors
* @throws ErrorDataDecoderException if there is a problem with the charset decoding or other errors
*/
private void parseBodyMultipart() throws ErrorDataDecoderException {
if (undecodedChunk == null || undecodedChunk.readableBytes() == 0) {
@ -619,8 +580,8 @@ public class HttpPostRequestDecoder {
InterfaceHttpData data = decodeMultipart(currentStatus);
while (data != null) {
addHttpData(data);
if (currentStatus == MultiPartStatus.PREEPILOGUE
|| currentStatus == MultiPartStatus.EPILOGUE) {
if (currentStatus == MultiPartStatus.PREEPILOGUE ||
currentStatus == MultiPartStatus.EPILOGUE) {
break;
}
data = decodeMultipart(currentStatus);
@ -641,8 +602,7 @@ public class HttpPostRequestDecoder {
*
* @param state
* @return the next decoded InterfaceHttpData or null if none until now.
* @throws ErrorDataDecoderException
* if an error occurs
* @throws ErrorDataDecoderException if an error occurs
*/
private InterfaceHttpData decodeMultipart(MultiPartStatus state)
throws ErrorDataDecoderException {
@ -687,8 +647,8 @@ public class HttpPostRequestDecoder {
.get(HttpPostBodyUtil.NAME);
if (currentAttribute == null) {
try {
currentAttribute = factory.createAttribute(request,
nameAttribute.getValue());
currentAttribute = factory.createAttribute(request, nameAttribute
.getValue());
} catch (NullPointerException e) {
throw new ErrorDataDecoderException(e);
} catch (IllegalArgumentException e) {
@ -742,13 +702,9 @@ public class HttpPostRequestDecoder {
/**
* Find the next Multipart Delimiter
*
* @param delimiter
* delimiter to find
* @param dispositionStatus
* the next status if the delimiter is a start
* @param closeDelimiterStatus
* the next status if the delimiter is a close delimiter
* @param delimiter delimiter to find
* @param dispositionStatus the next status if the delimiter is a start
* @param closeDelimiterStatus the next status if the delimiter is a close delimiter
* @return the next InterfaceHttpData if any
* @throws ErrorDataDecoderException
*/
@ -787,7 +743,6 @@ public class HttpPostRequestDecoder {
/**
* Find the next Disposition
*
* @return the next InterfaceHttpData if any
* @throws ErrorDataDecoderException
*/
@ -809,29 +764,25 @@ public class HttpPostRequestDecoder {
return null;
}
String[] contents = splitMultipartHeader(newline);
if (contents[0]
.equalsIgnoreCase(HttpPostBodyUtil.CONTENT_DISPOSITION)) {
if (contents[0].equalsIgnoreCase(HttpPostBodyUtil.CONTENT_DISPOSITION)) {
boolean checkSecondArg = false;
if (currentStatus == MultiPartStatus.DISPOSITION) {
checkSecondArg = contents[1]
.equalsIgnoreCase(HttpPostBodyUtil.FORM_DATA);
} else {
checkSecondArg = contents[1]
.equalsIgnoreCase(HttpPostBodyUtil.ATTACHMENT)
|| contents[1]
.equalsIgnoreCase(HttpPostBodyUtil.ATTACHMENT) ||
contents[1]
.equalsIgnoreCase(HttpPostBodyUtil.FILE);
}
if (checkSecondArg) {
// read next values and store them in the map as Attribute
for (int i = 2; i < contents.length; i++) {
for (int i = 2; i < contents.length; i ++) {
String[] values = contents[i].split("=");
Attribute attribute;
try {
attribute = factory.createAttribute(
request,
values[0].trim(),
decodeAttribute(cleanString(values[1]),
charset));
attribute = factory.createAttribute(request, values[0].trim(),
decodeAttribute(cleanString(values[1]), charset));
} catch (NullPointerException e) {
throw new ErrorDataDecoderException(e);
} catch (IllegalArgumentException e) {
@ -869,11 +820,9 @@ public class HttpPostRequestDecoder {
}
currentFieldAttributes.put(HttpHeaders.Names.CONTENT_LENGTH,
attribute);
} else if (contents[0]
.equalsIgnoreCase(HttpHeaders.Names.CONTENT_TYPE)) {
} else if (contents[0].equalsIgnoreCase(HttpHeaders.Names.CONTENT_TYPE)) {
// Take care of possible "multipart/mixed"
if (contents[1]
.equalsIgnoreCase(HttpPostBodyUtil.MULTIPART_MIXED)) {
if (contents[1].equalsIgnoreCase(HttpPostBodyUtil.MULTIPART_MIXED)) {
if (currentStatus == MultiPartStatus.DISPOSITION) {
String[] values = contents[2].split("=");
multipartMixedBoundary = "--" + values[1];
@ -884,7 +833,7 @@ public class HttpPostRequestDecoder {
"Mixed Multipart found in a previous Mixed Multipart");
}
} else {
for (int i = 1; i < contents.length; i++) {
for (int i = 1; i < contents.length; i ++) {
if (contents[i].toLowerCase().startsWith(
HttpHeaders.Values.CHARSET)) {
String[] values = contents[i].split("=");
@ -898,17 +847,14 @@ public class HttpPostRequestDecoder {
} catch (IllegalArgumentException e) {
throw new ErrorDataDecoderException(e);
}
currentFieldAttributes.put(
HttpHeaders.Values.CHARSET, attribute);
currentFieldAttributes.put(HttpHeaders.Values.CHARSET,
attribute);
} else {
Attribute attribute;
try {
attribute = factory.createAttribute(
request,
attribute = factory.createAttribute(request,
contents[0].trim(),
decodeAttribute(
cleanString(contents[i]),
charset));
decodeAttribute(cleanString(contents[i]), charset));
} catch (NullPointerException e) {
throw new ErrorDataDecoderException(e);
} catch (IllegalArgumentException e) {
@ -920,8 +866,8 @@ public class HttpPostRequestDecoder {
}
}
} else {
throw new ErrorDataDecoderException("Unknown Params: "
+ newline);
throw new ErrorDataDecoderException("Unknown Params: " +
newline);
}
}
// Is it a FileUpload
@ -954,9 +900,7 @@ public class HttpPostRequestDecoder {
/**
* Get the FileUpload (new one or current one)
*
* @param delimiter
* the delimiter to use
* @param delimiter the delimiter to use
* @return the InterfaceHttpData if any
* @throws ErrorDataDecoderException
*/
@ -978,8 +922,7 @@ public class HttpPostRequestDecoder {
}
if (code.equals(HttpPostBodyUtil.TransferEncodingMechanism.BIT7.value)) {
localCharset = HttpPostBodyUtil.US_ASCII;
} else if (code
.equals(HttpPostBodyUtil.TransferEncodingMechanism.BIT8.value)) {
} else if (code.equals(HttpPostBodyUtil.TransferEncodingMechanism.BIT8.value)) {
localCharset = HttpPostBodyUtil.ISO_8859_1;
mechanism = TransferEncodingMechanism.BIT8;
} else if (code
@ -1015,7 +958,7 @@ public class HttpPostRequestDecoder {
.get(HttpHeaders.Names.CONTENT_LENGTH);
long size;
try {
size = lengthAttribute != null ? Long.parseLong(lengthAttribute
size = lengthAttribute != null? Long.parseLong(lengthAttribute
.getValue()) : 0L;
} catch (IOException e) {
throw new ErrorDataDecoderException(e);
@ -1023,7 +966,8 @@ public class HttpPostRequestDecoder {
size = 0;
}
try {
currentFileUpload = factory.createFileUpload(request,
currentFileUpload = factory.createFileUpload(
request,
nameAttribute.getValue(), filenameAttribute.getValue(),
contentTypeAttribute.getValue(), mechanism.value,
localCharset, size);
@ -1078,25 +1022,21 @@ public class HttpPostRequestDecoder {
}
/**
* Remove all Attributes that should be cleaned between two FileUpload in
* Mixed mode
* Remove all Attributes that should be cleaned between two FileUpload in Mixed mode
*/
private void cleanMixedAttributes() {
currentFieldAttributes.remove(HttpHeaders.Values.CHARSET);
currentFieldAttributes.remove(HttpHeaders.Names.CONTENT_LENGTH);
currentFieldAttributes
.remove(HttpHeaders.Names.CONTENT_TRANSFER_ENCODING);
currentFieldAttributes.remove(HttpHeaders.Names.CONTENT_TRANSFER_ENCODING);
currentFieldAttributes.remove(HttpHeaders.Names.CONTENT_TYPE);
currentFieldAttributes.remove(HttpPostBodyUtil.FILENAME);
}
/**
* Read one line up to the CRLF or LF
*
* @return the String from one line
* @throws NotEnoughDataDecoderException
* Need more chunks and reset the readerInder to the previous
* value
* @throws NotEnoughDataDecoderException Need more chunks and
* reset the readerInder to the previous value
*/
private String readLine() throws NotEnoughDataDecoderException {
int readerIndex = undecodedChunk.readerIndex();
@ -1126,13 +1066,10 @@ public class HttpPostRequestDecoder {
/**
* Read a FileUpload data as Byte (Binary) and add the bytes directly to the
* FileUpload. If the delimiter is found, the FileUpload is completed.
*
* @param delimiter
* @throws NotEnoughDataDecoderException
* Need more chunks but do not reset the readerInder since some
* values will be already added to the FileOutput
* @throws ErrorDataDecoderException
* write IO error occurs with the FileUpload
* @throws NotEnoughDataDecoderException Need more chunks but
* do not reset the readerInder since some values will be already added to the FileOutput
* @throws ErrorDataDecoderException write IO error occurs with the FileUpload
*/
private void readFileUploadByteMultipart(String delimiter)
throws NotEnoughDataDecoderException, ErrorDataDecoderException {
@ -1147,7 +1084,7 @@ public class HttpPostRequestDecoder {
if (newLine) {
// Check the delimiter
if (nextByte == delimiter.codePointAt(index)) {
index++;
index ++;
if (delimiter.length() == index) {
found = true;
break;
@ -1196,8 +1133,8 @@ public class HttpPostRequestDecoder {
}
}
}
ChannelBuffer buffer = undecodedChunk.slice(readerIndex, lastPosition
- readerIndex);
ChannelBuffer buffer = undecodedChunk.slice(readerIndex, lastPosition -
readerIndex);
if (found) {
// found so lastPosition is correct and final
try {
@ -1208,8 +1145,7 @@ public class HttpPostRequestDecoder {
throw new ErrorDataDecoderException(e);
}
} else {
// possibly the delimiter is partially found but still the last
// position is OK
// possibly the delimiter is partially found but still the last position is OK
try {
currentFileUpload.addContent(buffer, false);
// last valid char (not CR, not LF, not beginning of delimiter)
@ -1223,9 +1159,7 @@ public class HttpPostRequestDecoder {
/**
* Load the field value from a Multipart request
*
* @throws NotEnoughDataDecoderException
* Need more chunks
* @throws NotEnoughDataDecoderException Need more chunks
* @throws ErrorDataDecoderException
*/
private void loadFieldMultipart(String delimiter)
@ -1242,7 +1176,7 @@ public class HttpPostRequestDecoder {
if (newLine) {
// Check the delimiter
if (nextByte == delimiter.codePointAt(index)) {
index++;
index ++;
if (delimiter.length() == index) {
found = true;
break;
@ -1291,13 +1225,12 @@ public class HttpPostRequestDecoder {
}
if (found) {
// found so lastPosition is correct
// but position is just after the delimiter (either close
// delimiter or simple one)
// but position is just after the delimiter (either close delimiter or simple one)
// so go back of delimiter size
try {
currentAttribute.addContent(
undecodedChunk.slice(readerIndex, lastPosition
- readerIndex), true);
undecodedChunk.slice(readerIndex, lastPosition - readerIndex),
true);
} catch (IOException e) {
throw new ErrorDataDecoderException(e);
}
@ -1305,8 +1238,8 @@ public class HttpPostRequestDecoder {
} else {
try {
currentAttribute.addContent(
undecodedChunk.slice(readerIndex, lastPosition
- readerIndex), false);
undecodedChunk.slice(readerIndex, lastPosition - readerIndex),
false);
} catch (IOException e) {
throw new ErrorDataDecoderException(e);
}
@ -1321,13 +1254,12 @@ public class HttpPostRequestDecoder {
/**
* Clean the String from any unallowed character
*
* @return the cleaned String
*/
private String cleanString(String field) {
StringBuilder sb = new StringBuilder(field.length());
int i = 0;
for (i = 0; i < field.length(); i++) {
for (i = 0; i < field.length(); i ++) {
char nextChar = field.charAt(i);
if (nextChar == HttpCodecUtil.COLON) {
sb.append(HttpCodecUtil.SP);
@ -1350,7 +1282,6 @@ public class HttpPostRequestDecoder {
/**
* Skip one empty line
*
* @return True if one empty line was skipped
*/
private boolean skipOneLine() {
@ -1378,7 +1309,6 @@ public class HttpPostRequestDecoder {
/**
* Split the very first line (Content-Type value) in 2 Strings
*
* @param sb
* @return the array of 2 Strings
*/
@ -1394,7 +1324,7 @@ public class HttpPostRequestDecoder {
return new String[] { sb, "" };
}
if (sb.charAt(aEnd) == ';') {
aEnd--;
aEnd --;
}
bStart = HttpPostBodyUtil.findNonWhitespace(sb, aEnd);
bEnd = HttpPostBodyUtil.findEndOfString(sb);
@ -1404,10 +1334,9 @@ public class HttpPostRequestDecoder {
/**
* Split one header in Multipart
*
* @param sb
* @return an array of String where rank 0 is the name of the header,
* follows by several values that were separated by ';' or ','
* @return an array of String where rank 0 is the name of the header, follows by several
* values that were separated by ';' or ','
*/
private String[] splitMultipartHeader(String sb) {
ArrayList<String> headers = new ArrayList<String>(1);
@ -1417,15 +1346,15 @@ public class HttpPostRequestDecoder {
int valueStart;
int valueEnd;
nameStart = HttpPostBodyUtil.findNonWhitespace(sb, 0);
for (nameEnd = nameStart; nameEnd < sb.length(); nameEnd++) {
for (nameEnd = nameStart; nameEnd < sb.length(); nameEnd ++) {
char ch = sb.charAt(nameEnd);
if (ch == ':' || Character.isWhitespace(ch)) {
break;
}
}
for (colonEnd = nameEnd; colonEnd < sb.length(); colonEnd++) {
for (colonEnd = nameEnd; colonEnd < sb.length(); colonEnd ++) {
if (sb.charAt(colonEnd) == ':') {
colonEnd++;
colonEnd ++;
break;
}
}
@ -1439,19 +1368,19 @@ public class HttpPostRequestDecoder {
} else {
values = svalue.split(",");
}
for (String value : values) {
for (String value: values) {
headers.add(value.trim());
}
String[] array = new String[headers.size()];
for (int i = 0; i < headers.size(); i++) {
for (int i = 0; i < headers.size(); i ++) {
array[i] = headers.get(i);
}
return array;
}
/**
* Exception when try reading data from request in chunked format, and not
* enough data are available (need more chunks)
* Exception when try reading data from request in chunked format, and not enough
* data are available (need more chunks)
*/
public static class NotEnoughDataDecoderException extends Exception {
/**

View File

@ -73,8 +73,8 @@ public class HttpPostRequestEncoder implements ChunkedInput {
private String multipartDataBoundary;
/**
* If multipart, there could be internal multiparts (mixed) to the global
* multipart. Only one level is allowed.
* If multipart, there could be internal multiparts (mixed) to the global multipart.
* Only one level is allowed.
*/
private String multipartMixedBoundary;
/**
@ -84,14 +84,10 @@ public class HttpPostRequestEncoder implements ChunkedInput {
/**
*
* @param request
* the request to encode
* @param multipart
* True if the FORM is a ENCTYPE="multipart/form-data"
* @throws NullPointerException
* for request
* @throws ErrorDataEncoderException
* if the request is not a POST
* @param request the request to encode
* @param multipart True if the FORM is a ENCTYPE="multipart/form-data"
* @throws NullPointerException for request
* @throws ErrorDataEncoderException if the request is not a POST
*/
public HttpPostRequestEncoder(HttpRequest request, boolean multipart)
throws ErrorDataEncoderException {
@ -101,40 +97,28 @@ public class HttpPostRequestEncoder implements ChunkedInput {
/**
*
* @param factory
* the factory used to create InterfaceHttpData
* @param request
* the request to encode
* @param multipart
* True if the FORM is a ENCTYPE="multipart/form-data"
* @throws NullPointerException
* for request and factory
* @throws ErrorDataEncoderException
* if the request is not a POST
* @param factory the factory used to create InterfaceHttpData
* @param request the request to encode
* @param multipart True if the FORM is a ENCTYPE="multipart/form-data"
* @throws NullPointerException for request and factory
* @throws ErrorDataEncoderException if the request is not a POST
*/
public HttpPostRequestEncoder(HttpDataFactory factory, HttpRequest request,
boolean multipart) throws ErrorDataEncoderException {
public HttpPostRequestEncoder(HttpDataFactory factory, HttpRequest request, boolean multipart)
throws ErrorDataEncoderException {
this(factory, request, multipart, HttpCodecUtil.DEFAULT_CHARSET);
}
/**
*
* @param factory
* the factory used to create InterfaceHttpData
* @param request
* the request to encode
* @param multipart
* True if the FORM is a ENCTYPE="multipart/form-data"
* @param charset
* the charset to use as default
* @throws NullPointerException
* for request or charset or factory
* @throws ErrorDataEncoderException
* if the request is not a POST
* @param factory the factory used to create InterfaceHttpData
* @param request the request to encode
* @param multipart True if the FORM is a ENCTYPE="multipart/form-data"
* @param charset the charset to use as default
* @throws NullPointerException for request or charset or factory
* @throws ErrorDataEncoderException if the request is not a POST
*/
public HttpPostRequestEncoder(HttpDataFactory factory, HttpRequest request,
boolean multipart, Charset charset)
throws ErrorDataEncoderException {
boolean multipart, Charset charset) throws ErrorDataEncoderException {
if (factory == null) {
throw new NullPointerException("factory");
}
@ -145,8 +129,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
throw new NullPointerException("charset");
}
if (request.getMethod() != HttpMethod.POST) {
throw new ErrorDataEncoderException(
"Cannot create a Encoder if not a POST");
throw new ErrorDataEncoderException("Cannot create a Encoder if not a POST");
}
this.request = request;
this.charset = charset;
@ -171,8 +154,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
}
/**
* Does the last non empty chunk already encoded so that next chunk will be
* empty (last chunk)
* Does the last non empty chunk already encoded so that next chunk will be empty (last chunk)
*/
private boolean isLastChunk;
/**
@ -195,7 +177,6 @@ public class HttpPostRequestEncoder implements ChunkedInput {
/**
* True if this request is a Multipart request
*
* @return True if this request is a Multipart request
*/
public boolean isMultipart() {
@ -228,7 +209,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
/**
* This method returns a List of all InterfaceHttpData from body part.<br>
*
* @return the list of InterfaceHttpData from Body part
*/
public List<InterfaceHttpData> getBodyListAttributes() {
@ -237,13 +218,9 @@ public class HttpPostRequestEncoder implements ChunkedInput {
/**
* Set the Body HttpDatas list
*
* @param datas
* @throws NullPointerException
* for datas
* @throws ErrorDataEncoderException
* if the encoding is in error or if the finalize were already
* done
* @throws NullPointerException for datas
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
*/
public void setBodyHttpDatas(List<InterfaceHttpData> datas)
throws ErrorDataEncoderException {
@ -255,23 +232,17 @@ public class HttpPostRequestEncoder implements ChunkedInput {
currentFileUpload = null;
duringMixedMode = false;
multipartHttpDatas.clear();
for (InterfaceHttpData data : datas) {
for (InterfaceHttpData data: datas) {
addBodyHttpData(data);
}
}
/**
* Add a simple attribute in the body as Name=Value
*
* @param name
* name of the parameter
* @param value
* the value of the parameter
* @throws NullPointerException
* for name
* @throws ErrorDataEncoderException
* if the encoding is in error or if the finalize were already
* done
* @param name name of the parameter
* @param value the value of the parameter
* @throws NullPointerException for name
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
*/
public void addBodyAttribute(String name, String value)
throws ErrorDataEncoderException {
@ -288,25 +259,15 @@ public class HttpPostRequestEncoder implements ChunkedInput {
/**
* Add a file as a FileUpload
*
* @param name
* the name of the parameter
* @param file
* the file to be uploaded (if not Multipart mode, only the
* filename will be included)
* @param contentType
* the associated contentType for the File
* @param isText
* True if this file should be transmitted in Text format (else
* binary)
* @throws NullPointerException
* for name and file
* @throws ErrorDataEncoderException
* if the encoding is in error or if the finalize were already
* done
* @param name the name of the parameter
* @param file the file to be uploaded (if not Multipart mode, only the filename will be included)
* @param contentType the associated contentType for the File
* @param isText True if this file should be transmitted in Text format (else binary)
* @throws NullPointerException for name and file
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
*/
public void addBodyFileUpload(String name, File file, String contentType,
boolean isText) throws ErrorDataEncoderException {
public void addBodyFileUpload(String name, File file, String contentType, boolean isText)
throws ErrorDataEncoderException {
if (name == null) {
throw new NullPointerException("name");
}
@ -325,9 +286,8 @@ public class HttpPostRequestEncoder implements ChunkedInput {
if (!isText) {
contentTransferEncoding = HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value;
}
FileUpload fileUpload = factory.createFileUpload(request, name,
file.getName(), scontentType, contentTransferEncoding, null,
file.length());
FileUpload fileUpload = factory.createFileUpload(request, name, file.getName(),
scontentType, contentTransferEncoding, null, file.length());
try {
fileUpload.setContent(file);
} catch (IOException e) {
@ -337,26 +297,15 @@ public class HttpPostRequestEncoder implements ChunkedInput {
}
/**
* Add a series of Files associated with one File parameter (implied Mixed
* mode in Multipart)
*
* @param name
* the name of the parameter
* @param file
* the array of files
* @param contentType
* the array of content Types associated with each file
* @param isText
* the array of isText attribute (False meaning binary mode) for
* each file
* @throws NullPointerException
* also throws if array have different sizes
* @throws ErrorDataEncoderException
* if the encoding is in error or if the finalize were already
* done
* Add a series of Files associated with one File parameter (implied Mixed mode in Multipart)
* @param name the name of the parameter
* @param file the array of files
* @param contentType the array of content Types associated with each file
* @param isText the array of isText attribute (False meaning binary mode) for each file
* @throws NullPointerException also throws if array have different sizes
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
*/
public void addBodyFileUploads(String name, File[] file,
String[] contentType, boolean[] isText)
public void addBodyFileUploads(String name, File[] file, String[] contentType, boolean[] isText)
throws ErrorDataEncoderException {
if (file.length != contentType.length && file.length != isText.length) {
throw new NullPointerException("Different array length");
@ -368,37 +317,30 @@ public class HttpPostRequestEncoder implements ChunkedInput {
/**
* Add the InterfaceHttpData to the Body list
*
* @param data
* @throws NullPointerException
* for data
* @throws ErrorDataEncoderException
* if the encoding is in error or if the finalize were already
* done
* @throws NullPointerException for data
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
*/
public void addBodyHttpData(InterfaceHttpData data)
throws ErrorDataEncoderException {
if (headerFinalized) {
throw new ErrorDataEncoderException(
"Cannot add value once finalized");
throw new ErrorDataEncoderException("Cannot add value once finalized");
}
if (data == null) {
throw new NullPointerException("data");
}
bodyListDatas.add(data);
if (!isMultipart) {
if (! isMultipart) {
if (data instanceof Attribute) {
Attribute attribute = (Attribute) data;
try {
// name=value& with encoded name and attribute
String key = encodeAttribute(attribute.getName(), charset);
String value = encodeAttribute(attribute.getValue(),
charset);
Attribute newattribute = factory.createAttribute(request,
key, value);
String value = encodeAttribute(attribute.getValue(), charset);
Attribute newattribute = factory.createAttribute(request, key, value);
multipartHttpDatas.add(newattribute);
globalBodySize += newattribute.getName().length() + 1
+ newattribute.length() + 1;
globalBodySize += newattribute.getName().length() + 1 +
newattribute.length() + 1;
} catch (IOException e) {
throw new ErrorDataEncoderException(e);
}
@ -407,35 +349,45 @@ public class HttpPostRequestEncoder implements ChunkedInput {
FileUpload fileUpload = (FileUpload) data;
// name=filename& with encoded name and filename
String key = encodeAttribute(fileUpload.getName(), charset);
String value = encodeAttribute(fileUpload.getFilename(),
charset);
Attribute newattribute = factory.createAttribute(request, key,
value);
String value = encodeAttribute(fileUpload.getFilename(), charset);
Attribute newattribute = factory.createAttribute(request, key, value);
multipartHttpDatas.add(newattribute);
globalBodySize += newattribute.getName().length() + 1
+ newattribute.length() + 1;
globalBodySize += newattribute.getName().length() + 1 +
newattribute.length() + 1;
}
return;
}
/*
* Logic: if not Attribute: add Data to body list if (duringMixedMode)
* add endmixedmultipart delimiter currentFileUpload = null
* duringMixedMode = false; add multipart delimiter, multipart body
* header and Data to multipart list reset currentFileUpload,
* duringMixedMode if FileUpload: take care of multiple file for one
* field => mixed mode if (duringMixeMode) if (currentFileUpload.name ==
* data.name) add mixedmultipart delimiter, mixedmultipart body header
* and Data to multipart list else add endmixedmultipart delimiter,
* multipart body header and Data to multipart list currentFileUpload =
* data duringMixedMode = false; else if (currentFileUpload.name ==
* data.name) change multipart body header of previous file into
* multipart list to mixedmultipart start, mixedmultipart body header
* add mixedmultipart delimiter, mixedmultipart body header and Data to
* multipart list duringMixedMode = true else add multipart delimiter,
* multipart body header and Data to multipart list currentFileUpload =
* data duringMixedMode = false; Do not add last delimiter! Could be: if
* duringmixedmode: endmixedmultipart + endmultipart else only
* endmultipart
* Logic:
* if not Attribute:
* add Data to body list
* if (duringMixedMode)
* add endmixedmultipart delimiter
* currentFileUpload = null
* duringMixedMode = false;
* add multipart delimiter, multipart body header and Data to multipart list
* reset currentFileUpload, duringMixedMode
* if FileUpload: take care of multiple file for one field => mixed mode
* if (duringMixeMode)
* if (currentFileUpload.name == data.name)
* add mixedmultipart delimiter, mixedmultipart body header and Data to multipart list
* else
* add endmixedmultipart delimiter, multipart body header and Data to multipart list
* currentFileUpload = data
* duringMixedMode = false;
* else
* if (currentFileUpload.name == data.name)
* change multipart body header of previous file into multipart list to
* mixedmultipart start, mixedmultipart body header
* add mixedmultipart delimiter, mixedmultipart body header and Data to multipart list
* duringMixedMode = true
* else
* add multipart delimiter, multipart body header and Data to multipart list
* currentFileUpload = data
* duringMixedMode = false;
* Do not add last delimiter! Could be:
* if duringmixedmode: endmixedmultipart + endmultipart
* else only endmultipart
*/
if (data instanceof Attribute) {
if (duringMixedMode) {
@ -454,16 +406,15 @@ public class HttpPostRequestEncoder implements ChunkedInput {
internal.addValue("--" + multipartDataBoundary + "\r\n");
// content-disposition: form-data; name="field1"
Attribute attribute = (Attribute) data;
internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": "
+ HttpPostBodyUtil.FORM_DATA + "; " + HttpPostBodyUtil.NAME
+ "=\"" + encodeAttribute(attribute.getName(), charset)
+ "\"\r\n");
internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": " +
HttpPostBodyUtil.FORM_DATA + "; " +
HttpPostBodyUtil.NAME + "=\"" +
encodeAttribute(attribute.getName(), charset) + "\"\r\n");
Charset localcharset = attribute.getCharset();
if (localcharset != null) {
// Content-Type: charset=charset
internal.addValue(HttpHeaders.Names.CONTENT_TYPE + ": "
+ HttpHeaders.Values.CHARSET + "=" + localcharset
+ "\r\n");
internal.addValue(HttpHeaders.Names.CONTENT_TYPE + ": " +
HttpHeaders.Values.CHARSET + "=" + localcharset + "\r\n");
}
// CRLF between body header and data
internal.addValue("\r\n");
@ -479,23 +430,20 @@ public class HttpPostRequestEncoder implements ChunkedInput {
}
boolean localMixed = false;
if (duringMixedMode) {
if (currentFileUpload != null
&& currentFileUpload.getName().equals(
fileUpload.getName())) {
if (currentFileUpload != null &&
currentFileUpload.getName().equals(fileUpload.getName())) {
// continue a mixed mode
localMixed = true;
} else {
// end a mixed mode
// add endmixedmultipart delimiter, multipart body header
// and
// add endmixedmultipart delimiter, multipart body header and
// Data to multipart list
internal.addValue("--" + multipartMixedBoundary + "--");
multipartHttpDatas.add(internal);
multipartMixedBoundary = null;
// start a new one (could be replaced if mixed start again
// from here
// start a new one (could be replaced if mixed start again from here
internal = new InternalAttribute();
internal.addValue("\r\n");
localMixed = false;
@ -504,20 +452,17 @@ public class HttpPostRequestEncoder implements ChunkedInput {
duringMixedMode = false;
}
} else {
if (currentFileUpload != null
&& currentFileUpload.getName().equals(
fileUpload.getName())) {
if (currentFileUpload != null &&
currentFileUpload.getName().equals(fileUpload.getName())) {
// create a new mixed mode (from previous file)
// change multipart body header of previous file into
// multipart list to
// change multipart body header of previous file into multipart list to
// mixedmultipart start, mixedmultipart body header
// change Internal (size()-2 position in multipartHttpDatas)
// from (line starting with *)
// --AaB03x
// * Content-Disposition: form-data; name="files";
// filename="file1.txt"
// * Content-Disposition: form-data; name="files"; filename="file1.txt"
// Content-Type: text/plain
// to (lines starting with *)
// --AaB03x
@ -528,42 +473,33 @@ public class HttpPostRequestEncoder implements ChunkedInput {
// * Content-Disposition: file; filename="file1.txt"
// Content-Type: text/plain
initMixedMultipart();
InternalAttribute pastAttribute = (InternalAttribute) multipartHttpDatas
.get(multipartHttpDatas.size() - 2);
InternalAttribute pastAttribute =
(InternalAttribute) multipartHttpDatas.get(multipartHttpDatas.size() - 2);
// remove past size
globalBodySize -= pastAttribute.size();
String replacement = HttpPostBodyUtil.CONTENT_DISPOSITION
+ ": " + HttpPostBodyUtil.FORM_DATA + "; "
+ HttpPostBodyUtil.NAME + "=\""
+ encodeAttribute(fileUpload.getName(), charset)
+ "\"\r\n";
replacement += HttpHeaders.Names.CONTENT_TYPE + ": "
+ HttpPostBodyUtil.MULTIPART_MIXED + "; "
+ HttpHeaders.Values.BOUNDARY + "="
+ multipartMixedBoundary + "\r\n\r\n";
String replacement = HttpPostBodyUtil.CONTENT_DISPOSITION + ": " +
HttpPostBodyUtil.FORM_DATA + "; " + HttpPostBodyUtil.NAME + "=\"" +
encodeAttribute(fileUpload.getName(), charset) + "\"\r\n";
replacement += HttpHeaders.Names.CONTENT_TYPE + ": " +
HttpPostBodyUtil.MULTIPART_MIXED + "; " + HttpHeaders.Values.BOUNDARY +
"=" + multipartMixedBoundary + "\r\n\r\n";
replacement += "--" + multipartMixedBoundary + "\r\n";
replacement += HttpPostBodyUtil.CONTENT_DISPOSITION
+ ": "
+ HttpPostBodyUtil.FILE
+ "; "
+ HttpPostBodyUtil.FILENAME
+ "=\""
+ encodeAttribute(fileUpload.getFilename(), charset)
+ "\"\r\n";
replacement += HttpPostBodyUtil.CONTENT_DISPOSITION + ": " +
HttpPostBodyUtil.FILE + "; " + HttpPostBodyUtil.FILENAME + "=\"" +
encodeAttribute(fileUpload.getFilename(), charset) +
"\"\r\n";
pastAttribute.setValue(replacement, 1);
// update past size
globalBodySize += pastAttribute.size();
// now continue
// add mixedmultipart delimiter, mixedmultipart body header
// and
// add mixedmultipart delimiter, mixedmultipart body header and
// Data to multipart list
localMixed = true;
duringMixedMode = true;
} else {
// a simple new multipart
// add multipart delimiter, multipart body header and Data
// to multipart list
//add multipart delimiter, multipart body header and Data to multipart list
localMixed = false;
currentFileUpload = fileUpload;
duringMixedMode = false;
@ -575,42 +511,36 @@ public class HttpPostRequestEncoder implements ChunkedInput {
// Data to multipart list
internal.addValue("--" + multipartMixedBoundary + "\r\n");
// Content-Disposition: file; filename="file1.txt"
internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": "
+ HttpPostBodyUtil.FILE + "; "
+ HttpPostBodyUtil.FILENAME + "=\""
+ encodeAttribute(fileUpload.getFilename(), charset)
+ "\"\r\n");
internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": " +
HttpPostBodyUtil.FILE + "; " + HttpPostBodyUtil.FILENAME + "=\"" +
encodeAttribute(fileUpload.getFilename(), charset) +
"\"\r\n");
} else {
internal.addValue("--" + multipartDataBoundary + "\r\n");
// Content-Disposition: form-data; name="files";
// filename="file1.txt"
internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": "
+ HttpPostBodyUtil.FORM_DATA + "; "
+ HttpPostBodyUtil.NAME + "=\""
+ encodeAttribute(fileUpload.getName(), charset)
+ "\"; " + HttpPostBodyUtil.FILENAME + "=\""
+ encodeAttribute(fileUpload.getFilename(), charset)
+ "\"\r\n");
// Content-Disposition: form-data; name="files"; filename="file1.txt"
internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": " +
HttpPostBodyUtil.FORM_DATA + "; " + HttpPostBodyUtil.NAME + "=\"" +
encodeAttribute(fileUpload.getName(), charset) + "\"; " +
HttpPostBodyUtil.FILENAME + "=\"" +
encodeAttribute(fileUpload.getFilename(), charset) +
"\"\r\n");
}
// Content-Type: image/gif
// Content-Type: text/plain; charset=ISO-8859-1
// Content-Transfer-Encoding: binary
internal.addValue(HttpHeaders.Names.CONTENT_TYPE + ": "
+ fileUpload.getContentType());
String contentTransferEncoding = fileUpload
.getContentTransferEncoding();
if (contentTransferEncoding != null
&& contentTransferEncoding
.equals(HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value)) {
internal.addValue("\r\n"
+ HttpHeaders.Names.CONTENT_TRANSFER_ENCODING
+ ": "
+ HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value
+ "\r\n\r\n");
internal.addValue(HttpHeaders.Names.CONTENT_TYPE + ": " +
fileUpload.getContentType());
String contentTransferEncoding = fileUpload.getContentTransferEncoding();
if (contentTransferEncoding != null &&
contentTransferEncoding.equals(
HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value)) {
internal.addValue("\r\n" + HttpHeaders.Names.CONTENT_TRANSFER_ENCODING +
": " + HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value +
"\r\n\r\n");
} else if (fileUpload.getCharset() != null) {
internal.addValue("; " + HttpHeaders.Values.CHARSET + "="
+ fileUpload.getCharset() + "\r\n\r\n");
internal.addValue("; " + HttpHeaders.Values.CHARSET + "=" +
fileUpload.getCharset() + "\r\n\r\n");
} else {
internal.addValue("\r\n\r\n");
}
@ -626,20 +556,19 @@ public class HttpPostRequestEncoder implements ChunkedInput {
private ListIterator<InterfaceHttpData> iterator;
/**
* Finalize the request by preparing the Header in the request and returns
* the request ready to be sent.<br>
* Finalize the request by preparing the Header in the request and
* returns the request ready to be sent.<br>
* Once finalized, no data must be added.<br>
* If the request does not need chunk (isChunked() == false), this request
* is the only object to send to the remote server.
* If the request does not need chunk (isChunked() == false),
* this request is the only object to send to
* the remote server.
*
* @return the request object (chunked or not according to size of body)
* @throws ErrorDataEncoderException
* if the encoding is in error or if the finalize were already
* done
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
*/
public HttpRequest finalizeRequest() throws ErrorDataEncoderException {
// Finalize the multipartHttpDatas
if (!headerFinalized) {
if (! headerFinalized) {
if (isMultipart) {
InternalAttribute internal = new InternalAttribute();
if (duringMixedMode) {
@ -656,13 +585,12 @@ public class HttpPostRequestEncoder implements ChunkedInput {
} else {
throw new ErrorDataEncoderException("Header already encoded");
}
List<String> contentTypes = request
.getHeaders(HttpHeaders.Names.CONTENT_TYPE);
List<String> transferEncoding = request
.getHeaders(HttpHeaders.Names.TRANSFER_ENCODING);
List<String> contentTypes = request.getHeaders(HttpHeaders.Names.CONTENT_TYPE);
List<String> transferEncoding =
request.getHeaders(HttpHeaders.Names.TRANSFER_ENCODING);
if (contentTypes != null) {
request.removeHeader(HttpHeaders.Names.CONTENT_TYPE);
for (String contentType : contentTypes) {
for (String contentType: contentTypes) {
// "multipart/form-data; boundary=--89421926422648"
if (contentType.toLowerCase().startsWith(
HttpHeaders.Values.MULTIPART_FORM_DATA)) {
@ -671,14 +599,13 @@ public class HttpPostRequestEncoder implements ChunkedInput {
HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED)) {
// ignore
} else {
request.addHeader(HttpHeaders.Names.CONTENT_TYPE,
contentType);
request.addHeader(HttpHeaders.Names.CONTENT_TYPE, contentType);
}
}
}
if (isMultipart) {
String value = HttpHeaders.Values.MULTIPART_FORM_DATA + "; "
+ HttpHeaders.Values.BOUNDARY + "=" + multipartDataBoundary;
String value = HttpHeaders.Values.MULTIPART_FORM_DATA + "; " +
HttpHeaders.Values.BOUNDARY + "=" + multipartDataBoundary;
request.addHeader(HttpHeaders.Names.CONTENT_TYPE, value);
} else {
// Not multipart
@ -693,18 +620,17 @@ public class HttpPostRequestEncoder implements ChunkedInput {
realSize -= 1; // last '&' removed
iterator = multipartHttpDatas.listIterator();
}
request.setHeader(HttpHeaders.Names.CONTENT_LENGTH,
String.valueOf(realSize));
request.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String
.valueOf(realSize));
if (realSize > HttpPostBodyUtil.chunkSize) {
isChunked = true;
if (transferEncoding != null) {
request.removeHeader(HttpHeaders.Names.TRANSFER_ENCODING);
for (String v : transferEncoding) {
for (String v: transferEncoding) {
if (v.equalsIgnoreCase(HttpHeaders.Values.CHUNKED)) {
// ignore
} else {
request.addHeader(HttpHeaders.Names.TRANSFER_ENCODING,
v);
request.addHeader(HttpHeaders.Names.TRANSFER_ENCODING, v);
}
}
}
@ -728,12 +654,10 @@ public class HttpPostRequestEncoder implements ChunkedInput {
/**
* Encode one attribute
*
* @param s
* @param charset
* @return the encoded attribute
* @throws ErrorDataEncoderException
* if the encoding is in error
* @throws ErrorDataEncoderException if the encoding is in error
*/
private static String encodeAttribute(String s, Charset charset)
throws ErrorDataEncoderException {
@ -752,26 +676,24 @@ public class HttpPostRequestEncoder implements ChunkedInput {
*/
private ChannelBuffer currentBuffer;
/**
* The current InterfaceHttpData to encode (used if more chunks are
* available)
* The current InterfaceHttpData to encode (used if more chunks are available)
*/
private InterfaceHttpData currentData;
/**
* If not multipart, does the currentBuffer stands for the Key or for the
* Value
* If not multipart, does the currentBuffer stands for the Key or for the Value
*/
private boolean isKey = true;
/**
*
* @return the next ChannelBuffer to send as a HttpChunk and modifying
* currentBuffer accordingly
* @return the next ChannelBuffer to send as a HttpChunk and modifying currentBuffer
* accordingly
*/
private ChannelBuffer fillChannelBuffer() {
int length = currentBuffer.readableBytes();
if (length > HttpPostBodyUtil.chunkSize) {
ChannelBuffer slice = currentBuffer.slice(
currentBuffer.readerIndex(), HttpPostBodyUtil.chunkSize);
ChannelBuffer slice =
currentBuffer.slice(currentBuffer.readerIndex(), HttpPostBodyUtil.chunkSize);
currentBuffer.skipBytes(HttpPostBodyUtil.chunkSize);
return slice;
} else {
@ -783,18 +705,15 @@ public class HttpPostRequestEncoder implements ChunkedInput {
}
/**
* From the current context (currentBuffer and currentData), returns the
* next HttpChunk (if possible) trying to get sizeleft bytes more into the
* currentBuffer. This is the Multipart version.
* From the current context (currentBuffer and currentData), returns the next HttpChunk
* (if possible) trying to get sizeleft bytes more into the currentBuffer.
* This is the Multipart version.
*
* @param sizeleft
* the number of bytes to try to get from currentData
* @param sizeleft the number of bytes to try to get from currentData
* @return the next HttpChunk or null if not enough bytes were found
* @throws ErrorDataEncoderException
* if the encoding is in error
* @throws ErrorDataEncoderException if the encoding is in error
*/
private HttpChunk encodeNextChunkMultipart(int sizeleft)
throws ErrorDataEncoderException {
private HttpChunk encodeNextChunkMultipart(int sizeleft) throws ErrorDataEncoderException {
if (currentData == null) {
return null;
}
@ -832,7 +751,8 @@ public class HttpPostRequestEncoder implements ChunkedInput {
if (currentBuffer == null) {
currentBuffer = buffer;
} else {
currentBuffer = ChannelBuffers.wrappedBuffer(currentBuffer, buffer);
currentBuffer = ChannelBuffers.wrappedBuffer(currentBuffer,
buffer);
}
if (currentBuffer.readableBytes() < HttpPostBodyUtil.chunkSize) {
currentData = null;
@ -843,18 +763,15 @@ public class HttpPostRequestEncoder implements ChunkedInput {
}
/**
* From the current context (currentBuffer and currentData), returns the
* next HttpChunk (if possible) trying to get sizeleft bytes more into the
* currentBuffer. This is the UrlEncoded version.
* From the current context (currentBuffer and currentData), returns the next HttpChunk
* (if possible) trying to get sizeleft bytes more into the currentBuffer.
* This is the UrlEncoded version.
*
* @param sizeleft
* the number of bytes to try to get from currentData
* @param sizeleft the number of bytes to try to get from currentData
* @return the next HttpChunk or null if not enough bytes were found
* @throws ErrorDataEncoderException
* if the encoding is in error
* @throws ErrorDataEncoderException if the encoding is in error
*/
private HttpChunk encodeNextChunkUrlEncoded(int sizeleft)
throws ErrorDataEncoderException {
private HttpChunk encodeNextChunkUrlEncoded(int sizeleft) throws ErrorDataEncoderException {
if (currentData == null) {
return null;
}
@ -866,14 +783,14 @@ public class HttpPostRequestEncoder implements ChunkedInput {
buffer = ChannelBuffers.wrappedBuffer(key.getBytes());
isKey = false;
if (currentBuffer == null) {
currentBuffer = ChannelBuffers.wrappedBuffer(buffer,
ChannelBuffers.wrappedBuffer("=".getBytes()));
// continue
currentBuffer = ChannelBuffers.wrappedBuffer(
buffer, ChannelBuffers.wrappedBuffer("=".getBytes()));
//continue
size -= buffer.readableBytes() + 1;
} else {
currentBuffer = ChannelBuffers.wrappedBuffer(currentBuffer,
buffer, ChannelBuffers.wrappedBuffer("=".getBytes()));
// continue
//continue
size -= buffer.readableBytes() + 1;
}
if (currentBuffer.readableBytes() >= HttpPostBodyUtil.chunkSize) {
@ -890,8 +807,9 @@ public class HttpPostRequestEncoder implements ChunkedInput {
if (buffer.readableBytes() < size) {
// delimiter
isKey = true;
delimiter = iterator.hasNext() ? ChannelBuffers.wrappedBuffer("&"
.getBytes()) : null;
delimiter = iterator.hasNext() ?
ChannelBuffers.wrappedBuffer("&".getBytes()) :
null;
}
if (buffer.capacity() == 0) {
// end for current InterfaceHttpData, need potentially more data
@ -912,7 +830,8 @@ public class HttpPostRequestEncoder implements ChunkedInput {
}
if (currentBuffer == null) {
if (delimiter != null) {
currentBuffer = ChannelBuffers.wrappedBuffer(buffer, delimiter);
currentBuffer = ChannelBuffers.wrappedBuffer(buffer,
delimiter);
} else {
currentBuffer = buffer;
}
@ -938,18 +857,15 @@ public class HttpPostRequestEncoder implements ChunkedInput {
@Override
public void close() throws Exception {
// NO since the user can want to reuse (broadcast for instance)
// cleanFiles();
//NO since the user can want to reuse (broadcast for instance) cleanFiles();
}
/**
* Returns the next available HttpChunk. The caller is responsible to test
* if this chunk is the last one (isLast()), in order to stop calling this
* method.
* Returns the next available HttpChunk. The caller is responsible to test if this chunk is the
* last one (isLast()), in order to stop calling this method.
*
* @return the next available HttpChunk
* @throws ErrorDataEncoderException
* if the encoding is in error
* @throws ErrorDataEncoderException if the encoding is in error
*/
@Override
public HttpChunk nextChunk() throws ErrorDataEncoderException {
@ -964,7 +880,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
size -= currentBuffer.readableBytes();
}
if (size <= 0) {
// NextChunk from buffer
//NextChunk from buffer
buffer = fillChannelBuffer();
return new DefaultHttpChunk(buffer);
}
@ -979,15 +895,15 @@ public class HttpPostRequestEncoder implements ChunkedInput {
} else {
HttpChunk chunk = encodeNextChunkUrlEncoded(size);
if (chunk != null) {
// NextChunk Url from currentData
//NextChunk Url from currentData
return chunk;
}
}
size = HttpPostBodyUtil.chunkSize - currentBuffer.readableBytes();
}
if (!iterator.hasNext()) {
if (! iterator.hasNext()) {
isLastChunk = true;
// NextChunk as last non empty from buffer
//NextChunk as last non empty from buffer
buffer = currentBuffer;
currentBuffer = null;
return new DefaultHttpChunk(buffer);
@ -1002,21 +918,20 @@ public class HttpPostRequestEncoder implements ChunkedInput {
}
if (chunk == null) {
// not enough
size = HttpPostBodyUtil.chunkSize
- currentBuffer.readableBytes();
size = HttpPostBodyUtil.chunkSize - currentBuffer.readableBytes();
continue;
}
// NextChunk from data
//NextChunk from data
return chunk;
}
// end since no more data
isLastChunk = true;
if (currentBuffer == null) {
isLastChunkSent = true;
// LastChunk with no more data
//LastChunk with no more data
return new DefaultHttpChunk(ChannelBuffers.EMPTY_BUFFER);
}
// Previous LastChunk with no more data
//Previous LastChunk with no more data
buffer = currentBuffer;
currentBuffer = null;
return new DefaultHttpChunk(buffer);
@ -1027,7 +942,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
return isLastChunkSent;
}
@Override
public boolean hasNextChunk() throws Exception {
return !isLastChunkSent;
}
@ -1067,5 +982,4 @@ public class HttpPostRequestEncoder implements ChunkedInput {
super(arg0, arg1);
}
}
}

View File

@ -17,8 +17,6 @@ package org.jboss.netty.handler.codec.http;
import java.nio.charset.Charset;
import org.jboss.netty.handler.codec.http.HttpHeaders;
/**
* Default FileUpload implementation that stores file into memory.<br><br>
*