| 12,6 → 12,9 |
| import org.apache.mina.filter.codec.ProtocolDecoderOutput; |
| import org.apache.mina.filter.codec.demux.MessageDecoderAdapter; |
| import org.apache.mina.filter.codec.demux.MessageDecoderResult; |
| import org.objectweb.util.monolog.Monolog; |
| import org.objectweb.util.monolog.api.BasicLevel; |
| import org.objectweb.util.monolog.api.Logger; |
| import org.ow2.odis.encoder.GenericEncoder; |
| import org.ow2.odis.nio.Constant; |
| |
| 19,642 → 22,621 |
| * The Class HttpMessageDecoder. |
| */ |
| public class HttpMessageDecoder extends MessageDecoderAdapter { |
| |
| /** The Constant CONTENT_LENGTH. */ |
| private static final byte[] CONTENT_LENGTH = (HttpMessage.CONTENT_LENGTH + ":") |
| .getBytes(); |
| |
| /** The Constant COOKIE_COMMENT. */ |
| /** Logger for this class. */ |
| static final Logger LOGGER = Monolog.initialize().getLogger(HttpMessageDecoder.class.getName()); |
| |
| public static final String COOKIE_COMMENT = "comment"; |
| /** The Constant CONTENT_LENGTH. */ |
| private static final byte[] CONTENT_LENGTH = (HttpMessage.CONTENT_LENGTH + ":").getBytes(); |
| |
| /** The Constant COOKIE_DOMAIN. */ |
| public static final String COOKIE_DOMAIN = "domain"; |
| /** The Constant COOKIE_COMMENT. */ |
| |
| /** The Constant COOKIE_EXPIRES. */ |
| public static final String COOKIE_EXPIRES = "expires"; |
| public static final String COOKIE_COMMENT = "comment"; |
| |
| /** The Constant COOKIE_MAX_AGE. */ |
| public static final String COOKIE_MAX_AGE = "max-age"; |
| /** The Constant COOKIE_DOMAIN. */ |
| public static final String COOKIE_DOMAIN = "domain"; |
| |
| /** The Constant COOKIE_PATH. */ |
| public static final String COOKIE_PATH = "path"; |
| /** The Constant COOKIE_EXPIRES. */ |
| public static final String COOKIE_EXPIRES = "expires"; |
| |
| /** The Constant COOKIE_SECURE. */ |
| public static final String COOKIE_SECURE = "secure"; |
| /** The Constant COOKIE_MAX_AGE. */ |
| public static final String COOKIE_MAX_AGE = "max-age"; |
| |
| /** The Constant COOKIE_VERSION. */ |
| public static final String COOKIE_VERSION = "version"; |
| /** The Constant COOKIE_PATH. */ |
| public static final String COOKIE_PATH = "path"; |
| |
| /** The Constant SET_COOKIE. */ |
| public static final String SET_COOKIE = "Set-Cookie"; |
| /** The Constant COOKIE_SECURE. */ |
| public static final String COOKIE_SECURE = "secure"; |
| |
| /** The Constant CURRENT_MESSAGE. */ |
| private static final String CURRENT_MESSAGE = "CURRENT_MESSAGE"; |
| /** The Constant COOKIE_VERSION. */ |
| public static final String COOKIE_VERSION = "version"; |
| |
| /** The Constant INCOMPLETE_LINE. */ |
| private static final String INCOMPLETE_LINE = "INCOMPLETE_LINE"; |
| /** The Constant SET_COOKIE. */ |
| public static final String SET_COOKIE = "Set-Cookie"; |
| |
| /** The Constant TRANSFER_ENCODING. */ |
| public static final String TRANSFER_ENCODING = "Transfer-Encoding"; |
| /** The Constant CURRENT_MESSAGE. */ |
| private static final String CURRENT_MESSAGE = "CURRENT_MESSAGE"; |
| |
| /** The Constant CHUNKED. */ |
| public static final String CHUNKED = "chunked"; |
| /** The Constant INCOMPLETE_LINE. */ |
| private static final String INCOMPLETE_LINE = "INCOMPLETE_LINE"; |
| |
| /** The decoder. */ |
| private final CharsetDecoder decoder = Charset.defaultCharset() |
| .newDecoder(); |
| /** The Constant TRANSFER_ENCODING. */ |
| public static final String TRANSFER_ENCODING = "Transfer-Encoding"; |
| |
| /** The generic encoder. */ |
| private GenericEncoder genericEncoder = new GenericEncoder(); |
| /** The Constant CHUNKED. */ |
| public static final String CHUNKED = "chunked"; |
| |
| /** The Constant CRLF. */ |
| private static final String CRLF = "\r\n"; |
| /** The decoder. */ |
| private final CharsetDecoder decoder = Charset.defaultCharset().newDecoder(); |
| |
| /** The is client synchrony. */ |
| private boolean isClientSynchrone = false; |
| /** The generic encoder. */ |
| private GenericEncoder genericEncoder = new GenericEncoder(); |
| |
| /** |
| * Instantiates a new http message decoder. |
| */ |
| public HttpMessageDecoder() { |
| } |
| /** The Constant CRLF. */ |
| private static final String CRLF = "\r\n"; |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.apache.mina.filter.codec.demux.MessageDecoder#decodable(org.apache |
| * .mina.common.IoSession, org.apache.mina.common.ByteBuffer) |
| */ |
| public MessageDecoderResult decodable(IoSession session, ByteBuffer in) { |
| // Return NEED_DATA if the whole header is not read yet. |
| try { |
| if (isClientSynchrone) { |
| return messageComplete(in) ? MessageDecoderResult.OK |
| : MessageDecoderResult.NEED_DATA; |
| } else { |
| return ExistsAtLeastOneMessageComplete(in) ? MessageDecoderResult.OK |
| : MessageDecoderResult.NEED_DATA; |
| } |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| return MessageDecoderResult.NOT_OK; |
| } |
| /** The is client synchrony. */ |
| private boolean isClientSynchrone = false; |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.apache.mina.filter.codec.demux.MessageDecoder#decode(org.apache.mina |
| * .common.IoSession, org.apache.mina.common.ByteBuffer, |
| * org.apache.mina.filter.codec.ProtocolDecoderOutput) |
| */ |
| public MessageDecoderResult decode(IoSession session, ByteBuffer in, |
| ProtocolDecoderOutput out) throws Exception { |
| MessageDecoderResult result = MessageDecoderResult.NEED_DATA; |
| List allLines = null; |
| String buffer = null; |
| /** |
| * Instantiates a new http message decoder. |
| */ |
| public HttpMessageDecoder() { |
| } |
| |
| if (isClientSynchrone) { |
| allLines = getAllLines(in, 0, in.limit()); |
| result = writeMessage(allLines, session, out); |
| } else { |
| // saving limit value before managing in buffer |
| int limit = in.limit(); |
| List positions = MinaHelper.getPositions(in, |
| HttpMessageEncoder.STX, HttpMessageEncoder.ETX); |
| for (int i = 0; i < positions.size(); i++) { |
| int[] position = ((int[]) positions.get(i)); |
| int start = position[0]; |
| int end = position[1]; |
| if ((start != -1) && (end == -1)) { |
| buffer = getBuffer(in, start + 1, limit); |
| saveIncompleteLine(buffer, session); |
| // allLines = getAllLines(in, start + 1, limit); |
| //saveIncompleteLine(toString(allLines), session); |
| result = MessageDecoderResult.NEED_DATA; |
| } else if ((start == -1) && (end == -1)) { |
| buffer = (String) session.getAttribute(INCOMPLETE_LINE); |
| buffer += getBuffer(in, 0, limit); |
| saveIncompleteLine(buffer, session); |
| // allLines = getAllLines(in, 0, limit); |
| // allLines = appendLine(allLines, (String) session |
| // .getAttribute(INCOMPLETE_LINE), 0); |
| // saveIncompleteLine(toString(allLines), session); |
| result = MessageDecoderResult.NEED_DATA; |
| } else if ((start == -1) && (end != -1)) { |
| buffer = (String) session.getAttribute(INCOMPLETE_LINE); |
| buffer += getBuffer(in, 0, end-1); |
| allLines = getAllLines(buffer); |
| // allLines = getAllLines(in, 0, end); |
| // allLines = appendLine(allLines, (String) session |
| // .getAttribute(INCOMPLETE_LINE), 0); |
| result = writeMessage(allLines, session, out); |
| } else { |
| allLines = getAllLines(in, start + 1, end-1); |
| result = writeMessage(allLines, session, out); |
| } |
| } |
| } |
| return result; |
| } |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.mina.filter.codec.demux.MessageDecoder#decodable(org.apache |
| * .mina.common.IoSession, org.apache.mina.common.ByteBuffer) |
| */ |
| public MessageDecoderResult decodable(IoSession session, ByteBuffer in) { |
| // Return NEED_DATA if the whole header is not read yet. |
| try { |
| if (isClientSynchrone) { |
| return messageComplete(in) ? MessageDecoderResult.OK : MessageDecoderResult.NEED_DATA; |
| } else { |
| return ExistsAtLeastOneMessageComplete(in) ? MessageDecoderResult.OK : MessageDecoderResult.NEED_DATA; |
| } |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| return MessageDecoderResult.NOT_OK; |
| } |
| |
| /** |
| * Write message. |
| * |
| * @param lines |
| * the lines |
| * @param session |
| * the session |
| * @param out |
| * the out |
| * |
| * @return the message decoder result |
| * |
| * @throws Exception |
| * the exception |
| */ |
| private MessageDecoderResult writeMessage(List lines, IoSession session, |
| ProtocolDecoderOutput out) throws Exception { |
| HttpMessage message = getHttpMessage(lines, (HttpMessage) session |
| .getAttribute(CURRENT_MESSAGE), session); |
| session.removeAttribute(CURRENT_MESSAGE); |
| out.write(genericEncoder.encode(message)); |
| return MessageDecoderResult.OK; |
| } |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.apache.mina.filter.codec.demux.MessageDecoder#decode(org.apache.mina |
| * .common.IoSession, org.apache.mina.common.ByteBuffer, |
| * org.apache.mina.filter.codec.ProtocolDecoderOutput) |
| */ |
| public MessageDecoderResult decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception { |
| MessageDecoderResult result = MessageDecoderResult.NEED_DATA; |
| List allLines = null; |
| String buffer = null; |
| |
| /** |
| * Save incomplete line. |
| * |
| * @param line |
| * the line |
| * @param session |
| * the session |
| */ |
| private void saveIncompleteLine(String line, IoSession session) { |
| session.removeAttribute(INCOMPLETE_LINE); |
| session.setAttribute(INCOMPLETE_LINE, line.substring(0, |
| line.length() )); // remove |
| // carriage |
| // return added by toString |
| if (isClientSynchrone) { |
| allLines = getAllLines(in, 0, in.limit()); |
| result = writeMessage(allLines, session, out); |
| } else { |
| // saving limit value before managing in buffer |
| int limit = in.limit(); |
| List positions = MinaHelper.getPositions(in, HttpMessageEncoder.STX, HttpMessageEncoder.ETX); |
| for (int i = 0; i < positions.size(); i++) { |
| int[] position = ((int[]) positions.get(i)); |
| int start = position[0]; |
| int end = position[1]; |
| LOGGER.log(BasicLevel.DEBUG, "decode() start=" + start + " end=" + end + " in" + in); |
| if ((start != -1) && (end == -1)) { |
| buffer = getBuffer(in, start + 1, limit); |
| saveIncompleteLine(buffer, session); |
| // allLines = getAllLines(in, start + 1, limit); |
| // saveIncompleteLine(toString(allLines), session); |
| result = MessageDecoderResult.NEED_DATA; |
| } else if ((start == -1) && (end == -1)) { |
| buffer = (String) session.getAttribute(INCOMPLETE_LINE); |
| buffer += getBuffer(in, 0, limit); |
| saveIncompleteLine(buffer, session); |
| // allLines = getAllLines(in, 0, limit); |
| // allLines = appendLine(allLines, (String) session |
| // .getAttribute(INCOMPLETE_LINE), 0); |
| // saveIncompleteLine(toString(allLines), session); |
| result = MessageDecoderResult.NEED_DATA; |
| } else if ((start == -1) && (end != -1)) { |
| buffer = (String) session.getAttribute(INCOMPLETE_LINE); |
| buffer += getBuffer(in, 0, end - 1); |
| allLines = getAllLines(buffer); |
| // allLines = getAllLines(in, 0, end); |
| // allLines = appendLine(allLines, (String) session |
| // .getAttribute(INCOMPLETE_LINE), 0); |
| result = writeMessage(allLines, session, out); |
| } else { |
| allLines = getAllLines(in, start + 1, end - 1); |
| result = writeMessage(allLines, session, out); |
| } |
| } |
| } |
| return result; |
| } |
| |
| } |
| /** |
| * Write message. |
| * |
| * @param lines |
| * the lines |
| * @param session |
| * the session |
| * @param out |
| * the out |
| * |
| * @return the message decoder result |
| * |
| * @throws Exception |
| * the exception |
| */ |
| private MessageDecoderResult writeMessage(List lines, IoSession session, ProtocolDecoderOutput out) throws Exception { |
| HttpMessage message = getHttpMessage(lines, (HttpMessage) session.getAttribute(CURRENT_MESSAGE), session); |
| session.removeAttribute(CURRENT_MESSAGE); |
| out.write(genericEncoder.encode(message)); |
| return MessageDecoderResult.OK; |
| } |
| |
| /** |
| * Save incomplete line. |
| * |
| * @param line |
| * the line |
| * @param session |
| * the session |
| */ |
| private void saveIncompleteLine(String line, IoSession session) { |
| session.removeAttribute(INCOMPLETE_LINE); |
| session.setAttribute(INCOMPLETE_LINE, line.substring(0, line.length())); // remove |
| // carriage |
| // return added by toString |
| |
| /** |
| * Gets the all lines. |
| * |
| * @param in |
| * the in |
| * @param start |
| * the start |
| * @param end |
| * the end |
| * |
| * @return the all lines |
| * |
| * @throws Exception |
| * the exception |
| */ |
| private List getAllLines(ByteBuffer in, int start, int end) |
| throws Exception { |
| return getAllLines(getBuffer(in, start, end)); |
| } |
| |
| /** |
| * Split buffer in list of line |
| * @param buffer |
| * @return |
| */ |
| private List getAllLines(String buffer) { |
| List allLines = new ArrayList(); |
| |
| String[] tabLines = buffer.split(CRLF, -1); |
| for (int i = 0; i < tabLines.length; i++) { |
| // Remove CR and LF if persist in line |
| String line = tabLines[i].replaceAll("\n", "").replaceAll("\r", ""); |
| allLines.add(line); |
| } |
| tabLines = null; |
| return allLines; |
| } |
| |
| /** |
| * Get buffer part of buffer in from start to end |
| * @param in |
| * @param start |
| * @param end |
| * @return The part of buffer |
| * @throws CharacterCodingException |
| */ |
| private String getBuffer(ByteBuffer in, int start, int end) throws CharacterCodingException { |
| in.rewind(); |
| in.limit(end); |
| in.position(start); |
| } |
| |
| return in.getString(decoder); |
| } |
| |
| |
| /** |
| * Gets the all lines. |
| * |
| * @param in |
| * the in |
| * @param start |
| * the start |
| * @param end |
| * the end |
| * |
| * @return the all lines |
| * |
| * @throws Exception |
| * the exception |
| */ |
| private List getAllLines(ByteBuffer in, int start, int end) throws Exception { |
| return getAllLines(getBuffer(in, start, end)); |
| } |
| |
| /** |
| * Gets the http messages. |
| * |
| * @param lines |
| * the lines |
| * @param currentHttpMessage |
| * the current http message |
| * @param session |
| * the session |
| * |
| * @return the http messages |
| * |
| * @throws Exception |
| * the exception |
| */ |
| /* |
| * private List getHttpMessages(List lines, HttpMessage currentHttpMessage, |
| * IoSession session) throws Exception { List result = new ArrayList(); |
| * HttpMessage message = currentHttpMessage; boolean isHeaderCompletelyRead |
| * = false; StringBuffer body = new StringBuffer(); for (int i = 0; i < |
| * lines.size(); i++) { String line = (String) lines.get(i); if ((i==0) && |
| * (session.getAttribute(INCOMPLETE_LINE) != null)) { line = |
| * session.getAttribute(INCOMPLETE_LINE) + line; |
| * session.removeAttribute(INCOMPLETE_LINE); } if (!"".equals(line)) { if |
| * (isFirstLineOfNewHTTPMessage(line, message)) { if (body.length() != 0) { |
| * message.setBody(body.toString()); result.add(message); |
| * |
| * // init for the next message body = new StringBuffer(); |
| * isHeaderCompletelyRead = false; } message = getHttpMessage(line, |
| * session); if (message == null) { break; } } else { if |
| * (!isHeaderCompletelyRead) { setHeader(message, line); } else { |
| * body.append(line); } } } else { if (!isHeaderCompletelyRead) { |
| * isHeaderCompletelyRead = true; } else if (i != lines.size()) { |
| * body.append(line); } else { message.setBody(body.toString()); |
| * result.add(message); |
| * |
| * // init for the next message body = new StringBuffer(); |
| * isHeaderCompletelyRead = false; } } } if (message != null) { |
| * message.setBody(body.toString()); result.add(message); } |
| * |
| * return result; } |
| */ |
| /** |
| * Split buffer in list of line |
| * |
| * @param buffer |
| * @return |
| */ |
| private List getAllLines(String buffer) { |
| List allLines = new ArrayList(); |
| |
| private HttpMessage getHttpMessage(List lines, |
| HttpMessage currentHttpMessage, IoSession session) throws Exception { |
| HttpMessage message = getHttpMessage((String) lines.get(0), session); |
| boolean isHeaderCompletelyRead = false; |
| StringBuffer body = new StringBuffer(); |
| if (message != null) { |
| for (int i = 1; i < lines.size(); i++) { |
| String line = (String) lines.get(i); |
| if (!Constant.EMPTY.equals(line)) { |
| if (!isHeaderCompletelyRead) { |
| setHeader(message, line); |
| } else { |
| body.append(line); |
| } |
| } else { |
| if (!isHeaderCompletelyRead) { |
| isHeaderCompletelyRead = true; |
| } else if (i != lines.size()) { |
| body.append(line); |
| } |
| } |
| } |
| message.setBody(body.toString()); |
| } |
| body = null; |
| return message; |
| } |
| String[] tabLines = buffer.split(CRLF, -1); |
| for (int i = 0; i < tabLines.length; i++) { |
| // Remove CR and LF if persist in line |
| String line = tabLines[i].replaceAll("\n", "").replaceAll("\r", ""); |
| allLines.add(line); |
| } |
| tabLines = null; |
| return allLines; |
| } |
| |
| /** |
| * Sets the header. |
| * |
| * @param httpMessage |
| * the http message |
| * @param line |
| * the line |
| * |
| * @throws Exception |
| * the exception |
| */ |
| private void setHeader(HttpMessage httpMessage, String line) |
| throws Exception { |
| String key = null; |
| String value = Constant.EMPTY; |
| String[] tokens = line.split(": "); |
| key = (String) tokens[0]; |
| if (tokens.length == 2) |
| value = tokens[1]; |
| if (key.equalsIgnoreCase(SET_COOKIE)) { |
| Cookie cookie = decodeCookie(value); |
| if (cookie != null) { |
| httpMessage.addCookie(cookie); |
| } |
| } else if (key.equalsIgnoreCase(HttpMessage.CONTENT_TYPE)) { |
| httpMessage.setContentType(value); |
| } else if (key.equalsIgnoreCase(HttpMessage.CONTENT_LENGTH)) { |
| httpMessage.setContentLength(Integer.parseInt(value)); |
| } else if (key.equalsIgnoreCase(TRANSFER_ENCODING) && value != null |
| && value.equalsIgnoreCase(CHUNKED)) { |
| httpMessage.setChunked(true); |
| } else if (key.equalsIgnoreCase(HttpMessage.CONNECTION) |
| && value != null |
| && value.equalsIgnoreCase(HttpMessage.CONNECTION_CLOSE)) { |
| httpMessage.setDecodeOnlyAfterCloseConnection(true); |
| } else { |
| httpMessage.getHeaders().put(key, value); |
| } |
| /** |
| * Get buffer part of buffer in from start to end |
| * |
| * @param in |
| * @param start |
| * @param end |
| * @return The part of buffer |
| * @throws CharacterCodingException |
| */ |
| private String getBuffer(ByteBuffer in, int start, int end) throws CharacterCodingException { |
| in.rewind(); |
| in.limit(end); |
| in.position(start); |
| if (LOGGER.isLoggable(BasicLevel.DEBUG)) { |
| // debug log for debug this stupid encoding system ! |
| LOGGER.log(BasicLevel.DEBUG, "getBuffer() start=" + start + " end=" + end + " in=" + in); |
| |
| } |
| String msg = ""; |
| for (int i = start; i < end; i++) { |
| msg += String.valueOf((char) in.get(i)); |
| } |
| LOGGER.log(BasicLevel.DEBUG, "getBuffer() start=" + start + " end=" + end + " msg=" + msg); |
| } |
| return in.getString(decoder); |
| } |
| |
| /** |
| * Decode body. |
| * |
| * @param in |
| * the in |
| * |
| * @return true, if message complete |
| * |
| * @throws Exception |
| * the exception |
| */ |
| /* |
| * public void decodeBody(BufferedReader reader, HttpMessage message, |
| * IoSession session) throws Exception { if (message instanceof |
| * HttpResponseMessage) { int code = ((HttpResponseMessage) |
| * message).getStatusCode(); if (code < 200 || code == 204 || code == 304) { |
| * message.setBody("status of msg " + code); |
| * session.removeAttribute(CURRENT_MESSAGE); } else { |
| * message.setBody(getContent(reader, session)); } } else { |
| * message.setBody(getContent(reader, session)); } } |
| */ |
| /** |
| * Gets the http messages. |
| * |
| * @param lines |
| * the lines |
| * @param currentHttpMessage |
| * the current http message |
| * @param session |
| * the session |
| * |
| * @return the http messages |
| * |
| * @throws Exception |
| * the exception |
| */ |
| /* |
| * private List getHttpMessages(List lines, HttpMessage currentHttpMessage, |
| * IoSession session) throws Exception { List result = new ArrayList(); |
| * HttpMessage message = currentHttpMessage; boolean isHeaderCompletelyRead = |
| * false; StringBuffer body = new StringBuffer(); for (int i = 0; i < |
| * lines.size(); i++) { String line = (String) lines.get(i); if ((i==0) && |
| * (session.getAttribute(INCOMPLETE_LINE) != null)) { line = |
| * session.getAttribute(INCOMPLETE_LINE) + line; |
| * session.removeAttribute(INCOMPLETE_LINE); } if (!"".equals(line)) { if |
| * (isFirstLineOfNewHTTPMessage(line, message)) { if (body.length() != 0) { |
| * message.setBody(body.toString()); result.add(message); |
| * |
| * // init for the next message body = new StringBuffer(); |
| * isHeaderCompletelyRead = false; } message = getHttpMessage(line, session); |
| * if (message == null) { break; } } else { if (!isHeaderCompletelyRead) { |
| * setHeader(message, line); } else { body.append(line); } } } else { if |
| * (!isHeaderCompletelyRead) { isHeaderCompletelyRead = true; } else if (i != |
| * lines.size()) { body.append(line); } else { |
| * message.setBody(body.toString()); result.add(message); |
| * |
| * // init for the next message body = new StringBuffer(); |
| * isHeaderCompletelyRead = false; } } } if (message != null) { |
| * message.setBody(body.toString()); result.add(message); } |
| * |
| * return result; } |
| */ |
| |
| /** |
| * Gets the content. |
| * |
| * @param reader |
| * the reader |
| * @param session |
| * the session |
| * |
| * @return the content |
| * |
| * @throws Exception |
| * the exception |
| */ |
| /* |
| * public String getContent(BufferedReader reader, IoSession session) throws |
| * Exception { StringBuffer result = new StringBuffer(); String line = |
| * reader.readLine(); boolean isAnotherMessagePresents = false; while (line |
| * != null) { if (isFirstLineOfNewHTTPMessage(line)) { |
| * session.removeAttribute(CURRENT_MESSAGE); |
| * session.setAttribute(CURRENT_MESSAGE, getHttpMessage(line)); |
| * isAnotherMessagePresents = true; break; } else { result.append(line); |
| * line = reader.readLine(); } } if (!isAnotherMessagePresents) |
| * session.removeAttribute(CURRENT_MESSAGE); return result.toString(); } |
| */ |
| private HttpMessage getHttpMessage(List lines, HttpMessage currentHttpMessage, IoSession session) throws Exception { |
| HttpMessage message = getHttpMessage((String) lines.get(0), session); |
| boolean isHeaderCompletelyRead = false; |
| StringBuffer body = new StringBuffer(); |
| if (message != null) { |
| for (int i = 1; i < lines.size(); i++) { |
| String line = (String) lines.get(i); |
| if (!Constant.EMPTY.equals(line)) { |
| if (!isHeaderCompletelyRead) { |
| setHeader(message, line); |
| } else { |
| body.append(line); |
| } |
| } else { |
| if (!isHeaderCompletelyRead) { |
| isHeaderCompletelyRead = true; |
| } else if (i != lines.size()) { |
| body.append(line); |
| } |
| } |
| } |
| message.setBody(body.toString()); |
| } |
| body = null; |
| return message; |
| } |
| |
| /** |
| * Message complete. |
| * |
| * @param in |
| * the in |
| * |
| * @return true, if successful |
| * |
| * @throws Exception |
| * the exception |
| */ |
| private boolean messageComplete(ByteBuffer in) throws Exception { |
| int last = in.remaining() - 1; |
| if (in.remaining() < 4) { |
| return false; |
| } |
| /** |
| * Sets the header. |
| * |
| * @param httpMessage |
| * the http message |
| * @param line |
| * the line |
| * |
| * @throws Exception |
| * the exception |
| */ |
| private void setHeader(HttpMessage httpMessage, String line) throws Exception { |
| String key = null; |
| String value = Constant.EMPTY; |
| String[] tokens = line.split(": "); |
| key = (String) tokens[0]; |
| if (tokens.length == 2) |
| value = tokens[1]; |
| if (key.equalsIgnoreCase(SET_COOKIE)) { |
| Cookie cookie = decodeCookie(value); |
| if (cookie != null) { |
| httpMessage.addCookie(cookie); |
| } |
| } else if (key.equalsIgnoreCase(HttpMessage.CONTENT_TYPE)) { |
| httpMessage.setContentType(value); |
| } else if (key.equalsIgnoreCase(HttpMessage.CONTENT_LENGTH)) { |
| httpMessage.setContentLength(Integer.parseInt(value)); |
| } else if (key.equalsIgnoreCase(TRANSFER_ENCODING) && value != null && value.equalsIgnoreCase(CHUNKED)) { |
| httpMessage.setChunked(true); |
| } else if (key.equalsIgnoreCase(HttpMessage.CONNECTION) && value != null |
| && value.equalsIgnoreCase(HttpMessage.CONNECTION_CLOSE)) { |
| httpMessage.setDecodeOnlyAfterCloseConnection(true); |
| } else { |
| httpMessage.getHeaders().put(key, value); |
| } |
| |
| // to speed up things we check if the Http request is a GET or POST |
| if (in.get(0) == (byte) 'G' && in.get(1) == (byte) 'E' |
| && in.get(2) == (byte) 'T') { |
| // Http GET request therefore the last 4 bytes should be 0x0D 0x0A |
| // 0x0D 0x0A |
| return in.get(last) == (byte) 0x0A |
| && in.get(last - 1) == (byte) 0x0D |
| && in.get(last - 2) == (byte) 0x0A |
| && in.get(last - 3) == (byte) 0x0D; |
| } else if (in.get(0) == (byte) 'P' && in.get(1) == (byte) 'O' |
| && in.get(2) == (byte) 'S' && in.get(3) == (byte) 'T') { |
| // Http POST request |
| // first the position of the 0x0D 0x0A 0x0D 0x0A bytes |
| int eoh = -1; |
| for (int i = last; i > 2; i--) { |
| if (in.get(i) == (byte) 0x0A && in.get(i - 1) == (byte) 0x0D |
| && in.get(i - 2) == (byte) 0x0A |
| && in.get(i - 3) == (byte) 0x0D) { |
| eoh = i + 1; |
| break; |
| } |
| } |
| if (eoh == -1) { |
| return false; |
| } |
| for (int i = 0; i < last; i++) { |
| boolean found = false; |
| for (int j = 0; j < CONTENT_LENGTH.length; j++) { |
| if (in.get(i + j) != CONTENT_LENGTH[j]) { |
| found = false; |
| break; |
| } |
| found = true; |
| } |
| if (found) { |
| // retrieve value from this position till next 0x0D 0x0A |
| StringBuilder contentLength = new StringBuilder(); |
| for (int j = i + CONTENT_LENGTH.length; j < last; j++) { |
| if (in.get(j) == 0x0D) { |
| break; |
| } |
| contentLength.append(new String( |
| new byte[] { in.get(j) })); |
| } |
| // if content-length worth of data has been received then |
| // the message is complete |
| return Integer.parseInt(contentLength.toString().trim()) |
| + eoh == in.remaining(); |
| } |
| } |
| } |
| } |
| |
| // the message is not complete and we need more data |
| return false; |
| } |
| /** |
| * Decode body. |
| * |
| * @param in |
| * the in |
| * |
| * @return true, if message complete |
| * |
| * @throws Exception |
| * the exception |
| */ |
| /* |
| * public void decodeBody(BufferedReader reader, HttpMessage message, |
| * IoSession session) throws Exception { if (message instanceof |
| * HttpResponseMessage) { int code = ((HttpResponseMessage) |
| * message).getStatusCode(); if (code < 200 || code == 204 || code == 304) { |
| * message.setBody("status of msg " + code); |
| * session.removeAttribute(CURRENT_MESSAGE); } else { |
| * message.setBody(getContent(reader, session)); } } else { |
| * message.setBody(getContent(reader, session)); } } |
| */ |
| |
| /** |
| * Exists at least one message complete. |
| * |
| * @param in |
| * the in |
| * |
| * @return true, if successful |
| * |
| * @throws Exception |
| * the exception |
| */ |
| private boolean ExistsAtLeastOneMessageComplete(ByteBuffer in) |
| throws Exception { |
| int last = in.remaining() - 1; |
| boolean foundStart = false; |
| boolean foundEnd = false; |
| if ((in.get(0) == HttpMessageEncoder.STX) |
| && (in.get(0) == HttpMessageEncoder.ETX)) { |
| foundStart = true; |
| } |
| for (int i = 0; i < last; i++) { |
| if (in.get(i) == HttpMessageEncoder.ETX) { |
| foundEnd = true; |
| break; |
| } |
| } |
| return (foundStart && foundEnd); |
| } |
| /** |
| * Gets the content. |
| * |
| * @param reader |
| * the reader |
| * @param session |
| * the session |
| * |
| * @return the content |
| * |
| * @throws Exception |
| * the exception |
| */ |
| /* |
| * public String getContent(BufferedReader reader, IoSession session) throws |
| * Exception { StringBuffer result = new StringBuffer(); String line = |
| * reader.readLine(); boolean isAnotherMessagePresents = false; while (line != |
| * null) { if (isFirstLineOfNewHTTPMessage(line)) { |
| * session.removeAttribute(CURRENT_MESSAGE); |
| * session.setAttribute(CURRENT_MESSAGE, getHttpMessage(line)); |
| * isAnotherMessagePresents = true; break; } else { result.append(line); line |
| * = reader.readLine(); } } if (!isAnotherMessagePresents) |
| * session.removeAttribute(CURRENT_MESSAGE); return result.toString(); } |
| */ |
| |
| /** |
| * Decode cookie. |
| * |
| * @param cookieStr |
| * the cookie str |
| * |
| * @return the cookie |
| * |
| * @throws Exception |
| * the exception |
| */ |
| public Cookie decodeCookie(String cookieStr) throws Exception { |
| /** |
| * Message complete. |
| * |
| * @param in |
| * the in |
| * |
| * @return true, if successful |
| * |
| * @throws Exception |
| * the exception |
| */ |
| private boolean messageComplete(ByteBuffer in) throws Exception { |
| int last = in.remaining() - 1; |
| if (in.remaining() < 4) { |
| return false; |
| } |
| |
| Cookie cookie = null; |
| // to speed up things we check if the Http request is a GET or POST |
| if (in.get(0) == (byte) 'G' && in.get(1) == (byte) 'E' && in.get(2) == (byte) 'T') { |
| // Http GET request therefore the last 4 bytes should be 0x0D 0x0A |
| // 0x0D 0x0A |
| return in.get(last) == (byte) 0x0A && in.get(last - 1) == (byte) 0x0D && in.get(last - 2) == (byte) 0x0A |
| && in.get(last - 3) == (byte) 0x0D; |
| } else if (in.get(0) == (byte) 'P' && in.get(1) == (byte) 'O' && in.get(2) == (byte) 'S' && in.get(3) == (byte) 'T') { |
| // Http POST request |
| // first the position of the 0x0D 0x0A 0x0D 0x0A bytes |
| int eoh = -1; |
| for (int i = last; i > 2; i--) { |
| if (in.get(i) == (byte) 0x0A && in.get(i - 1) == (byte) 0x0D && in.get(i - 2) == (byte) 0x0A |
| && in.get(i - 3) == (byte) 0x0D) { |
| eoh = i + 1; |
| break; |
| } |
| } |
| if (eoh == -1) { |
| return false; |
| } |
| for (int i = 0; i < last; i++) { |
| boolean found = false; |
| for (int j = 0; j < CONTENT_LENGTH.length; j++) { |
| if (in.get(i + j) != CONTENT_LENGTH[j]) { |
| found = false; |
| break; |
| } |
| found = true; |
| } |
| if (found) { |
| // retrieve value from this position till next 0x0D 0x0A |
| StringBuilder contentLength = new StringBuilder(); |
| for (int j = i + CONTENT_LENGTH.length; j < last; j++) { |
| if (in.get(j) == 0x0D) { |
| break; |
| } |
| contentLength.append(new String(new byte[] { in.get(j) })); |
| } |
| // if content-length worth of data has been received then |
| // the message is complete |
| return Integer.parseInt(contentLength.toString().trim()) + eoh == in.remaining(); |
| } |
| } |
| } |
| |
| String pairs[] = cookieStr.split(";"); |
| for (int i = 0; i < pairs.length; i++) { |
| String nameValue[] = pairs[i].trim().split("="); |
| String name = nameValue[0].trim(); |
| // the message is not complete and we need more data |
| return false; |
| } |
| |
| // First one is the cookie name/value pair |
| if (i == 0) { |
| cookie = new Cookie(name, nameValue[1].trim()); |
| continue; |
| } |
| /** |
| * Exists at least one message complete. |
| * |
| * @param in |
| * the in |
| * |
| * @return true, if successful |
| * |
| * @throws Exception |
| * the exception |
| */ |
| private boolean ExistsAtLeastOneMessageComplete(ByteBuffer in) throws Exception { |
| int last = in.remaining() - 1; |
| boolean foundStart = false; |
| boolean foundEnd = false; |
| if ((in.get(0) == HttpMessageEncoder.STX) && (in.get(0) == HttpMessageEncoder.ETX)) { |
| foundStart = true; |
| } |
| for (int i = 0; i < last; i++) { |
| if (in.get(i) == HttpMessageEncoder.ETX) { |
| foundEnd = true; |
| break; |
| } |
| } |
| return (foundStart && foundEnd); |
| } |
| |
| if (name.equalsIgnoreCase(COOKIE_COMMENT)) { |
| cookie.setComment(nameValue[1].trim()); |
| continue; |
| } |
| /** |
| * Decode cookie. |
| * |
| * @param cookieStr |
| * the cookie str |
| * |
| * @return the cookie |
| * |
| * @throws Exception |
| * the exception |
| */ |
| public Cookie decodeCookie(String cookieStr) throws Exception { |
| |
| if (name.equalsIgnoreCase(COOKIE_PATH)) { |
| cookie.setPath(nameValue[1].trim()); |
| } |
| Cookie cookie = null; |
| |
| if (name.equalsIgnoreCase(COOKIE_SECURE)) { |
| cookie.setSecure(true); |
| } |
| String pairs[] = cookieStr.split(";"); |
| for (int i = 0; i < pairs.length; i++) { |
| String nameValue[] = pairs[i].trim().split("="); |
| String name = nameValue[0].trim(); |
| |
| if (name.equalsIgnoreCase(COOKIE_VERSION)) { |
| cookie.setVersion(Integer.parseInt(nameValue[1])); |
| } |
| // First one is the cookie name/value pair |
| if (i == 0) { |
| cookie = new Cookie(name, nameValue[1].trim()); |
| continue; |
| } |
| |
| if (name.equalsIgnoreCase(COOKIE_MAX_AGE)) { |
| int age = Integer.parseInt(nameValue[1]); |
| cookie.setExpires(new Date(System.currentTimeMillis() + age |
| * 1000L)); |
| } |
| if (name.equalsIgnoreCase(COOKIE_COMMENT)) { |
| cookie.setComment(nameValue[1].trim()); |
| continue; |
| } |
| |
| if (name.equalsIgnoreCase(COOKIE_EXPIRES)) { |
| // TODO |
| // cookie.setExpires( DateUtil.parseDate( nameValue[1] ) ); |
| } |
| if (name.equalsIgnoreCase(COOKIE_PATH)) { |
| cookie.setPath(nameValue[1].trim()); |
| } |
| |
| if (name.equalsIgnoreCase(COOKIE_DOMAIN)) { |
| cookie.setDomain(nameValue[1]); |
| } |
| } |
| return cookie; |
| } |
| if (name.equalsIgnoreCase(COOKIE_SECURE)) { |
| cookie.setSecure(true); |
| } |
| |
| /** |
| * Gets the http message. |
| * |
| * @param firstLine |
| * the first line |
| * @param session |
| * the session |
| * |
| * @return the http message |
| * |
| * @throws Exception |
| * the exception |
| */ |
| private HttpMessage getHttpMessage(String firstLine, IoSession session) |
| throws Exception { |
| HttpMessage result = null; |
| if (firstLine != null) { |
| boolean isRequest = isMethodPresents(firstLine); |
| if (isRequest) { |
| if (!isHttpProtocolPresents(firstLine)) { |
| session.setAttribute(INCOMPLETE_LINE, firstLine); |
| } else { |
| result = new HttpRequestMessage(); |
| String[] url = firstLine.split(Constant.SPACE); |
| if (url.length < 3) { |
| return null; |
| } |
| ((HttpRequestMessage) result).setMethod(url[0] |
| .toUpperCase()); |
| ((HttpRequestMessage) result).setRequestLine(url[1]); |
| ((HttpRequestMessage) result).setHttpProtocol(url[2]); |
| } |
| } else { |
| // This is a response message |
| if (!isHttpProtocolPresents(firstLine)) { |
| session.setAttribute(INCOMPLETE_LINE, firstLine); |
| } else { |
| result = new HttpResponseMessage(); |
| ((HttpResponseMessage) result).setHttpProtocol(firstLine |
| .substring(0, 8)); |
| ((HttpResponseMessage) result).setStatusCode(Integer |
| .parseInt(firstLine.substring(9, 12))); |
| ((HttpResponseMessage) result).setStatusMessage(firstLine |
| .substring(13)); |
| } |
| } |
| if (name.equalsIgnoreCase(COOKIE_VERSION)) { |
| cookie.setVersion(Integer.parseInt(nameValue[1])); |
| } |
| |
| } |
| return result; |
| } |
| if (name.equalsIgnoreCase(COOKIE_MAX_AGE)) { |
| int age = Integer.parseInt(nameValue[1]); |
| cookie.setExpires(new Date(System.currentTimeMillis() + age * 1000L)); |
| } |
| |
| /** |
| * Checks if is http protocol presents. |
| * |
| * @param line |
| * the line |
| * |
| * @return true, if is http protocol presents |
| */ |
| private boolean isHttpProtocolPresents(String line) { |
| return (line.contains(HttpMessage.PROTOCOL_HTTP_1_1) || line |
| .contains(HttpMessage.PROTOCOL_HTTP_1_0)); |
| } |
| if (name.equalsIgnoreCase(COOKIE_EXPIRES)) { |
| // TODO |
| // cookie.setExpires( DateUtil.parseDate( nameValue[1] ) ); |
| } |
| |
| /** |
| * Checks if is method presents. |
| * |
| * @param line |
| * the line |
| * |
| * @return true, if is method presents |
| */ |
| private boolean isMethodPresents(String line) { |
| return (line.contains(HttpRequestMessage.GET_METHOD) || line |
| .contains(HttpRequestMessage.POST_METHOD)); |
| } |
| if (name.equalsIgnoreCase(COOKIE_DOMAIN)) { |
| cookie.setDomain(nameValue[1]); |
| } |
| } |
| return cookie; |
| } |
| |
| /** |
| * Gets the http message. |
| * |
| * @param firstLine |
| * the first line |
| * @param session |
| * the session |
| * |
| * @return the http message |
| * |
| * @throws Exception |
| * the exception |
| */ |
| private HttpMessage getHttpMessage(String firstLine, IoSession session) throws Exception { |
| HttpMessage result = null; |
| if (firstLine != null) { |
| boolean isRequest = isMethodPresents(firstLine); |
| if (isRequest) { |
| if (!isHttpProtocolPresents(firstLine)) { |
| session.setAttribute(INCOMPLETE_LINE, firstLine); |
| } else { |
| result = new HttpRequestMessage(); |
| String[] url = firstLine.split(Constant.SPACE); |
| if (url.length < 3) { |
| return null; |
| } |
| ((HttpRequestMessage) result).setMethod(url[0].toUpperCase()); |
| ((HttpRequestMessage) result).setRequestLine(url[1]); |
| ((HttpRequestMessage) result).setHttpProtocol(url[2]); |
| } |
| } else { |
| // This is a response message |
| if (!isHttpProtocolPresents(firstLine)) { |
| session.setAttribute(INCOMPLETE_LINE, firstLine); |
| } else { |
| result = new HttpResponseMessage(); |
| ((HttpResponseMessage) result).setHttpProtocol(firstLine.substring(0, 8)); |
| ((HttpResponseMessage) result).setStatusCode(Integer.parseInt(firstLine.substring(9, 12))); |
| ((HttpResponseMessage) result).setStatusMessage(firstLine.substring(13)); |
| } |
| } |
| |
| } |
| return result; |
| } |
| |
| /** |
| * Checks if is http protocol presents. |
| * |
| * @param line |
| * the line |
| * |
| * @return true, if is http protocol presents |
| */ |
| private boolean isHttpProtocolPresents(String line) { |
| return (line.contains(HttpMessage.PROTOCOL_HTTP_1_1) || line.contains(HttpMessage.PROTOCOL_HTTP_1_0)); |
| } |
| |
| /** |
| * Checks if is method presents. |
| * |
| * @param line |
| * the line |
| * |
| * @return true, if is method presents |
| */ |
| private boolean isMethodPresents(String line) { |
| return (line.contains(HttpRequestMessage.GET_METHOD) || line.contains(HttpRequestMessage.POST_METHOD)); |
| } |
| } |