package org.xnio.http;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
class HttpUpgradeParser {
private static final int VERSION = 0;
private static final int STATUS_CODE = 1;
private static final int MESSAGE = 2;
private static final int = 3;
private static final int = 4;
private static final int COMPLETE = 5;
private int parseState = 0;
private String httpVersion;
private int responseCode;
private String message;
private final Map<String, List<String>> = new HashMap<String, List<String>>();
private final StringBuilder current = new StringBuilder();
private String ;
void parse(final ByteBuffer buffer) throws IOException {
while (buffer.hasRemaining() && !isComplete()) {
switch (parseState) {
case VERSION:
parseVersion(buffer);
break;
case STATUS_CODE:
parseStatusCode(buffer);
break;
case MESSAGE:
parseMessage(buffer);
break;
case HEADER_NAME:
parseHeaderName(buffer);
break;
case HEADER_VALUE:
parseHeaderValue(buffer);
break;
case COMPLETE:
return;
}
}
}
private void (final ByteBuffer buffer) {
while (buffer.hasRemaining()) {
byte b = buffer.get();
if (b == '\r' || b == '\n') {
String key = headerName.toLowerCase(Locale.ENGLISH);
List<String> list = headers.get(key);
if(list == null) {
headers.put(key, list = new ArrayList<String>());
}
list.add(current.toString().trim());
parseState--;
current.setLength(0);
return;
} else {
current.append((char) b);
}
}
}
private void (final ByteBuffer buffer) throws IOException {
while (buffer.hasRemaining()) {
byte b = buffer.get();
if (b == '\r' || b == '\n') {
if (current.length() > 2) {
throw new IOException("Invalid response");
} else if (current.length() == 2) {
if (current.charAt(0) == '\n' &&
current.charAt(1) == '\r'
&& b == '\n') {
parseState = COMPLETE;
return;
}
throw new IOException("Invalid response");
}
current.append((char) b);
} else if (b == ':') {
headerName = current.toString().trim();
parseState++;
current.setLength(0);
return;
} else {
current.append((char) b);
}
}
}
private void parseMessage(final ByteBuffer buffer) throws IOException {
while (buffer.hasRemaining()) {
byte b = buffer.get();
if (b == '\r' || b == '\n') {
message = current.toString().trim();
parseState++;
current.setLength(0);
return;
} else {
current.append((char) b);
}
}
}
private void parseStatusCode(final ByteBuffer buffer) throws IOException {
while (buffer.hasRemaining()) {
byte b = buffer.get();
if (b == ' ' || b == '\t') {
responseCode = Integer.parseInt(current.toString().trim());
parseState++;
current.setLength(0);
return;
} else if (Character.isDigit(b)) {
current.append((char) b);
} else {
throw new IOException("Invalid response");
}
}
}
private void parseVersion(final ByteBuffer buffer) throws IOException {
while (buffer.hasRemaining()) {
byte b = buffer.get();
if (b == ' ' || b == '\t') {
httpVersion = current.toString().trim();
parseState++;
current.setLength(0);
return;
} else if(Character.isDigit(b) || Character.isAlphabetic(b) || b == '.' || b == '/') {
current.append((char) b);
} else {
throw new IOException("Invalid response");
}
}
}
boolean isComplete() {
return parseState == COMPLETE;
}
public String getHttpVersion() {
return httpVersion;
}
public int getResponseCode() {
return responseCode;
}
public String getMessage() {
return message;
}
public Map<String, List<String>> () {
return headers;
}
}