Some more progress in multipart
This commit is contained in:
parent
a700cf2863
commit
e4a5af69db
5 changed files with 153 additions and 69 deletions
|
|
@ -29,25 +29,28 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: boundry
|
* A stream that is handled as a iterator. The stream will read
|
||||||
|
* until it gets to a boundary and will return -1 (end of stream).
|
||||||
|
* The stream will not return any data until the {@link #next()}
|
||||||
|
* method is called.
|
||||||
*
|
*
|
||||||
* @author Ziver
|
* @author Ziver
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class BufferedBoundaryInputStream extends FilterInputStream{
|
public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
/** The size of the buffer in bytes */
|
/** The size of the buffer in bytes */
|
||||||
public static final int DEFAULT_BUF_SIZE = 8192;
|
private static final int DEFAULT_BUF_SIZE = 8192;
|
||||||
|
|
||||||
/** The raw buffer */
|
/** The raw buffer */
|
||||||
protected byte buffer[];
|
private byte buffer[];
|
||||||
|
/** The current position in the buffer */
|
||||||
|
private int buf_pos = 0;
|
||||||
/** The end position of the buffer */
|
/** The end position of the buffer */
|
||||||
protected int buf_end = 0;
|
private int buf_end = 0;
|
||||||
/** The current position in the buffer */
|
/** Boundary position, 0< means no boundary found */
|
||||||
protected int buf_pos = 0;
|
private int buf_bound_pos;
|
||||||
/** The boundary (the delimiter) */
|
/** The boundary (the delimiter) */
|
||||||
protected byte[] boundary;
|
private byte[] boundary;
|
||||||
/** Boundary position, 0< means no boundary found */
|
|
||||||
protected int bound_pos;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -67,10 +70,10 @@ public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
*/
|
*/
|
||||||
public BufferedBoundaryInputStream(InputStream in, int buf_size){
|
public BufferedBoundaryInputStream(InputStream in, int buf_size){
|
||||||
super(in);
|
super(in);
|
||||||
|
buf_pos = 0;
|
||||||
buf_end = 0;
|
buf_end = 0;
|
||||||
buf_pos = 0;
|
buf_bound_pos = -1;
|
||||||
buffer = new byte[buf_size];
|
buffer = new byte[buf_size];
|
||||||
bound_pos = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -109,7 +112,7 @@ public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
return -1; // EOF
|
return -1; // EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bound_pos == buf_pos)
|
if(buf_bound_pos == buf_pos)
|
||||||
return -1; // boundary
|
return -1; // boundary
|
||||||
return buffer[buf_pos++];
|
return buffer[buf_pos++];
|
||||||
}
|
}
|
||||||
|
|
@ -137,7 +140,7 @@ public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
if(fillBuffer() <= 0)
|
if(fillBuffer() <= 0)
|
||||||
return -1; // EOF
|
return -1; // EOF
|
||||||
}
|
}
|
||||||
if(bound_pos == buf_pos)
|
if(buf_bound_pos == buf_pos)
|
||||||
return -1; // boundary
|
return -1; // boundary
|
||||||
|
|
||||||
// The request is larger then the buffer size
|
// The request is larger then the buffer size
|
||||||
|
|
@ -146,8 +149,8 @@ public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
len = leftover;
|
len = leftover;
|
||||||
}
|
}
|
||||||
// the boundary is in the read range
|
// the boundary is in the read range
|
||||||
if(buf_pos < bound_pos && bound_pos < buf_pos+len){
|
if(buf_pos < buf_bound_pos && buf_bound_pos < buf_pos+len){
|
||||||
len = buf_pos - bound_pos;
|
len = buf_bound_pos - buf_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
System.arraycopy(buffer, buf_pos, b, off, len);
|
System.arraycopy(buffer, buf_pos, b, off, len);
|
||||||
|
|
@ -155,11 +158,19 @@ public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
|
/**
|
||||||
|
* @return if there is more data to read
|
||||||
|
*/
|
||||||
|
public boolean isOnBoundary(){
|
||||||
|
return buf_bound_pos == buf_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* Skips over the boundary at the current position in the buffer
|
* Skips over the boundary at the current position in the buffer
|
||||||
*/
|
*/
|
||||||
public boolean next(){
|
public boolean next(){
|
||||||
if(bound_pos == buf_pos){
|
if(buf_bound_pos == buf_pos){
|
||||||
buf_pos += boundary.length;
|
buf_pos += boundary.length;
|
||||||
searchNextBoundary();
|
searchNextBoundary();
|
||||||
return buf_end >= buf_pos;
|
return buf_end >= buf_pos;
|
||||||
|
|
@ -173,15 +184,15 @@ public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
protected void searchNextBoundary(){
|
protected void searchNextBoundary(){
|
||||||
for(int i=buf_pos; i<buf_end; i++){
|
for(int i=buf_pos; i<buf_end; i++){
|
||||||
for(int b=0; b < boundary.length; b++){
|
for(int b=0; b < boundary.length; b++){
|
||||||
if(buffer[i] != boundary[b])
|
if(buffer[i+b] != boundary[b])
|
||||||
break;
|
break;
|
||||||
else if(b == boundary.length-1){
|
else if(b == boundary.length-1){
|
||||||
bound_pos = i;
|
buf_bound_pos = i;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bound_pos = -1;
|
buf_bound_pos = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -216,13 +227,6 @@ public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
System.arraycopy(b, 0, boundary, 0, b.length);
|
System.arraycopy(b, 0, boundary, 0, b.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return if there is more data to read
|
|
||||||
*/
|
|
||||||
public boolean isOnBoundary(){
|
|
||||||
return bound_pos == buf_pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return an estimate of the number of bytes that can be read (or skipped
|
* @return an estimate of the number of bytes that can be read (or skipped
|
||||||
* over) from this buffered input stream without blocking.
|
* over) from this buffered input stream without blocking.
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ public class IOUtil {
|
||||||
StringBuilder str = new StringBuilder();
|
StringBuilder str = new StringBuilder();
|
||||||
BufferedReader in = null;
|
BufferedReader in = null;
|
||||||
if(reader instanceof BufferedReader)
|
if(reader instanceof BufferedReader)
|
||||||
reader = (BufferedReader) reader;
|
in = (BufferedReader) reader;
|
||||||
else
|
else
|
||||||
in = new BufferedReader(reader);
|
in = new BufferedReader(reader);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ public class MultipartParser implements Iterable<MultipartField>{
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
try {
|
try {
|
||||||
IOUtil.copyStream(buffIn, new NullWriter());
|
IOUtil.copyStream(buffIn, new NullWriter());
|
||||||
return boundaryIn.next();
|
return boundaryIn.isOnBoundary();
|
||||||
} catch (IOException e){
|
} catch (IOException e){
|
||||||
logger.log(Level.SEVERE, null, e);
|
logger.log(Level.SEVERE, null, e);
|
||||||
}
|
}
|
||||||
|
|
@ -130,14 +130,13 @@ public class MultipartParser implements Iterable<MultipartField>{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MultipartField next() {
|
public MultipartField next() {
|
||||||
if (!hasNext())
|
|
||||||
return null;
|
|
||||||
try {
|
try {
|
||||||
HttpHeader header = parser.read();
|
boundaryIn.next();
|
||||||
String tmp = buffIn.readLine(); // read the new line after the delimiter
|
String tmp = buffIn.readLine(); // read the new line after the delimiter
|
||||||
if (tmp == null && tmp.equals("--"))
|
if (tmp == null || tmp.equals("--"))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
HttpHeader header = parser.read();
|
||||||
String disposition = header.getHeader(HEADER_CONTENT_DISPOSITION);
|
String disposition = header.getHeader(HEADER_CONTENT_DISPOSITION);
|
||||||
if (disposition != null){
|
if (disposition != null){
|
||||||
HashMap<String,String> map = new HashMap<>();
|
HashMap<String,String> map = new HashMap<>();
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ public class MultipartStringField implements MultipartField {
|
||||||
|
|
||||||
protected MultipartStringField(Map<String,String> header, BufferedReader in) throws IOException {
|
protected MultipartStringField(Map<String,String> header, BufferedReader in) throws IOException {
|
||||||
this.name = header.get("name");
|
this.name = header.get("name");
|
||||||
value = IOUtil.getContentAsString(in);
|
value = in.readLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import org.junit.Test;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -36,51 +37,117 @@ import static org.junit.Assert.assertTrue;
|
||||||
public class BufferedBoundaryInputStreamTest {
|
public class BufferedBoundaryInputStreamTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void normal() throws IOException {
|
public void read_normal() throws IOException {
|
||||||
StringInputStream inin = new StringInputStream("aaa#aaaaaaaaaaaaaaaa#aaaaaaaaaaaaaaa#");
|
StringInputStream inin = new StringInputStream("aaa#a##aaaaaaa#");
|
||||||
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
||||||
|
|
||||||
in.setBoundary("#");
|
in.setBoundary("#");
|
||||||
|
|
||||||
int n = 0;
|
assertEquals('a', in.read());
|
||||||
for(n=0; in.read() != -1; n++);
|
assertEquals('a', in.read());
|
||||||
assertEquals(3, n);
|
assertEquals('a', in.read());
|
||||||
|
assertEquals(-1, in.read());
|
||||||
|
assertTrue(in.isOnBoundary());
|
||||||
|
|
||||||
in.next();
|
in.next();
|
||||||
n = 0;
|
assertEquals('a', in.read());
|
||||||
for(n=0; in.read() != -1; n++);
|
assertEquals(-1, in.read());
|
||||||
assertEquals(16, n);
|
assertTrue(in.isOnBoundary());
|
||||||
|
|
||||||
in.next();
|
in.next();
|
||||||
n = 0;
|
assertEquals(-1, in.read());
|
||||||
for(n=0; in.read() != -1; n++);
|
assertTrue(in.isOnBoundary());
|
||||||
assertEquals(15, n);
|
|
||||||
|
in.next();
|
||||||
|
assertEquals('a', in.read());
|
||||||
|
assertEquals('a', in.read());
|
||||||
|
assertEquals('a', in.read());
|
||||||
|
assertEquals('a', in.read());
|
||||||
|
assertEquals('a', in.read());
|
||||||
|
assertEquals('a', in.read());
|
||||||
|
assertEquals('a', in.read());
|
||||||
|
assertEquals(-1, in.read());
|
||||||
|
assertTrue(in.isOnBoundary());
|
||||||
|
|
||||||
in.next();
|
in.next();
|
||||||
assertEquals(-1, in.read());
|
assertEquals(-1, in.read());
|
||||||
|
assertFalse(in.isOnBoundary());
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void readArr_normal() throws IOException {
|
||||||
|
StringInputStream inin = new StringInputStream("aaa#aaaaaaaaaaaaaaaa#aaaaaaaaaaaaaaa#");
|
||||||
|
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
||||||
|
in.setBoundary("#");
|
||||||
|
|
||||||
|
byte[] buff = new byte[100];
|
||||||
|
int n = in.read(buff);
|
||||||
|
assertEquals(3, n);
|
||||||
|
|
||||||
|
in.next();
|
||||||
|
n = in.read(buff);
|
||||||
|
assertEquals(16, n);
|
||||||
|
|
||||||
|
in.next();
|
||||||
|
n = in.read(buff);
|
||||||
|
assertEquals(15, n);
|
||||||
|
|
||||||
|
in.next();
|
||||||
|
n = in.read(buff);
|
||||||
|
assertEquals(-1, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void read_multiCharBoundary() throws IOException {
|
||||||
|
StringInputStream inin = new StringInputStream("aaa1234");
|
||||||
|
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
||||||
|
in.setBoundary("1234");
|
||||||
|
|
||||||
|
byte[] buff = new byte[100];
|
||||||
|
assertEquals(3, in.read(buff));
|
||||||
|
assertEquals(-1, in.read());
|
||||||
|
assertTrue(in.isOnBoundary());
|
||||||
|
|
||||||
|
in.next();
|
||||||
|
assertEquals(-1, in.read(buff));
|
||||||
|
assertFalse(in.isOnBoundary());
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void readArr_multiCharBoundary() throws IOException {
|
||||||
|
StringInputStream inin = new StringInputStream("aaa1234");
|
||||||
|
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
||||||
|
in.setBoundary("1234");
|
||||||
|
|
||||||
|
assertEquals('a', in.read());
|
||||||
|
assertEquals('a', in.read());
|
||||||
|
assertEquals('a', in.read());
|
||||||
|
assertEquals(-1, in.read());
|
||||||
|
assertTrue(in.isOnBoundary());
|
||||||
|
|
||||||
|
in.next();
|
||||||
|
assertEquals(-1, in.read());
|
||||||
|
assertFalse(in.isOnBoundary());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void startWithBound() throws IOException {
|
public void read_startWithBound() throws IOException {
|
||||||
StringInputStream inin = new StringInputStream("#aaa");
|
StringInputStream inin = new StringInputStream("#aaa");
|
||||||
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
||||||
in.setBoundary("#");
|
in.setBoundary("#");
|
||||||
|
|
||||||
assertEquals(-1, in.read());
|
assertEquals(-1, in.read());
|
||||||
|
}
|
||||||
inin = new StringInputStream("#aaa");
|
@Test
|
||||||
in = new BufferedBoundaryInputStream(inin);
|
public void readArr_startWithBound() throws IOException {
|
||||||
in.setBoundary("#");
|
StringInputStream inin = new StringInputStream("#aaa");
|
||||||
|
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
||||||
|
in.setBoundary("#");
|
||||||
|
|
||||||
assertEquals(-1, in.read(new byte[10], 0, 10));
|
assertEquals(-1, in.read(new byte[10], 0, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onlyBoundaries() throws IOException {
|
public void read_onlyBoundaries() throws IOException {
|
||||||
StringInputStream inin = new StringInputStream("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
StringInputStream inin = new StringInputStream("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||||
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
||||||
|
|
||||||
in.setBoundary("a");
|
in.setBoundary("a");
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
|
|
@ -93,9 +160,26 @@ public class BufferedBoundaryInputStreamTest {
|
||||||
}
|
}
|
||||||
assertEquals(35, n);
|
assertEquals(35, n);
|
||||||
}
|
}
|
||||||
|
@Test
|
||||||
|
public void readArr_onlyBoundaries() throws IOException {
|
||||||
|
StringInputStream inin = new StringInputStream("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
||||||
|
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
||||||
|
in.setBoundary("a");
|
||||||
|
|
||||||
|
byte[] buff = new byte[100];
|
||||||
|
int n;
|
||||||
|
for(n=1; true; n++){
|
||||||
|
assertEquals(-1, in.read(buff));
|
||||||
|
assertEquals(-1, in.read(buff));
|
||||||
|
in.next();
|
||||||
|
if(!in.isOnBoundary())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assertEquals(35, n);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void noBounds() throws IOException {
|
public void read_noBounds() throws IOException {
|
||||||
String data = "1234567891011121314151617181920";
|
String data = "1234567891011121314151617181920";
|
||||||
StringInputStream inin = new StringInputStream(data);
|
StringInputStream inin = new StringInputStream(data);
|
||||||
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
||||||
|
|
@ -108,18 +192,15 @@ public class BufferedBoundaryInputStreamTest {
|
||||||
}
|
}
|
||||||
assertEquals(data, output.toString());
|
assertEquals(data, output.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void next() throws IOException {
|
public void readArr_noBounds() throws IOException {
|
||||||
StringInputStream inin = new StringInputStream("a#a#");
|
String data = "1234567891011121314151617181920";
|
||||||
|
StringInputStream inin = new StringInputStream(data);
|
||||||
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin);
|
||||||
in.setBoundary("#");
|
in.setBoundary("#");
|
||||||
|
|
||||||
assertEquals('a', in.read());
|
byte[] buff = new byte[100];
|
||||||
assertEquals(-1, in.read());
|
assertEquals(data.length(), in.read(buff));
|
||||||
assertEquals(true, in.next());
|
assertEquals(data, new String(buff, 0, data.length()));
|
||||||
assertEquals('a', in.read());
|
|
||||||
assertEquals(-1, in.read());
|
|
||||||
assertEquals(false, in.next());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue