Some more progress in multipart

This commit is contained in:
Ziver Koc 2016-07-11 18:05:21 +02:00
parent a700cf2863
commit e4a5af69db
5 changed files with 153 additions and 69 deletions

View file

@ -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.

View file

@ -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);

View file

@ -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<>();

View file

@ -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

View file

@ -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());
} }
} }