package org.simpleframework.http.validate; import java.io.IOException; import java.io.InputStream; import java.io.PushbackInputStream; import java.util.HashMap; import java.util.Map; import org.simpleframework.common.buffer.ArrayBuffer; import org.simpleframework.common.buffer.Buffer; import org.simpleframework.http.StatusLine; public class Extractor { private static final String CONTENT_LENGTH = "Content-Length"; private static final byte[] LINE = new byte[] {13,10}; private static final byte[] REQUEST = new byte[] {13,10,13,10}; private final Buffer buffer; private final byte[] block; private final boolean debug; public Extractor(boolean debug) { this.buffer = new ArrayBuffer(512, 2048); this.block = new byte[1024]; this.debug = debug; } public Result extractResponse(PushbackInputStream in) throws IOException { StatusLine statusLine = extractStatus(in); if(statusLine == null) { return null; } Map<String, String> header = extractHeader(in); Buffer body = extractBody(header, in); return new Result(statusLine, header, body); } public StatusLine extractStatus(PushbackInputStream in) throws IOException { Buffer buffer = extractLine(in); if(buffer == null) { return null; } return new StatusParser(buffer); } public Buffer extractLine(PushbackInputStream in) throws IOException { int byteCount = 0; int count = 0; int pos = 0; read: { buffer.clear(); while((count = in.read(block)) != -1) { int seek = 0; while(seek < count) { if(block[seek++] != LINE[pos++]) { pos = 0; } if(pos == LINE.length) { buffer.append(block, 0, seek); in.unread(block, seek, count - seek); break read; } byteCount++; } try { buffer.append(block, 0, seek); } catch(Exception e) { throw new IOException("Append failed with "+buffer.encode()); } } } if(byteCount <= 0) { return null; } return buffer; } public Map<String, String> extractHeader(PushbackInputStream in) throws IOException { Map<String, String> map = new HashMap<String, String>(); int count = 0; int pos = 0; read: { buffer.clear(); while((count = in.read(block)) != -1) { int seek = 0; while(seek < count) { if(block[seek++] != REQUEST[pos++]) { pos = 0; } if(pos == REQUEST.length) { buffer.append(block, 0, seek); in.unread(block, seek, count - seek); break read; } } buffer.append(block, 0, seek); } } HeaderParser parser = new HeaderParser(buffer); while(parser.hasMore()) { Header header = parser.next(); String name = header.getName(); String value = header.getValue(); map.put(name, value); } return map; } public Buffer extractBody(Map<String, String> map, PushbackInputStream in) throws IOException { String contentLength = map.get(CONTENT_LENGTH); int length = Integer.parseInt(contentLength); Buffer body = new ArrayBuffer(length, length); while(length > 0) { int remaining = Math.min(length, block.length); int count = in.read(block, 0, remaining); if(count == -1) { break; } else { if(debug) { //System.out.println("Reading body ["+length+"] remains"); } } body.append(block, 0, count); length -= count; } return body; } public Buffer extractAll(InputStream in) throws IOException { Buffer buffer = new ArrayBuffer(2048, 1048576); int count = 0; while((count = in.read(block)) != -1) { buffer.append(block, 0, count); } return buffer; } }