* Usually this method is expected to read just the very first line or * the very first valid from the data stream and based on the input generate * an appropriate instance of {@link HttpMessage}. * * @param buffer the session input buffer. * @return HTTP message based on the input from the session buffer. * @throws IOException in case of an I/O error. * @throws HttpException in case of HTTP protocol violation. * * @since 5.0 */ protected abstract T createMessage(CharArrayBuffer buffer) throws IOException, HttpException; /** * Subclasses must override this method to generate an appropriate exception * in case of unexpected connection termination by the peer endpoint. * * @since 5.0 */ protected abstract IOException createConnectionClosedException(); @Override public T parse(final SessionInputBuffer buffer, final InputStream inputStream) throws IOException, HttpException { Args.notNull(buffer, "Session input buffer"); Args.notNull(inputStream, "Input stream"); final int st = this.state; switch (st) { case HEAD_LINE: for (int n = 0; n < this.h1Config.getMaxEmptyLineCount(); n++) { this.headLine.clear(); final int i = buffer.readLine(this.headLine, inputStream); if (i == -1) { throw createConnectionClosedException(); } if (this.headLine.length() > 0) { this.message = createMessage(this.headLine); if (this.message != null) { break; } } } if (this.message == null) { throw new MessageConstraintException("Maximum empty line limit exceeded"); } this.state = HEADERS; //$FALL-THROUGH$ case HEADERS: final Header[] headers = AbstractMessageParser.parseHeaders( buffer, inputStream, this.h1Config.getMaxHeaderCount(), this.h1Config.getMaxLineLength(), this.lineParser, this.headerLines); this.message.setHeaders(headers); final T result = this.message; this.message = null; this.headerLines.clear(); this.state = HEAD_LINE; return result; default: throw new IllegalStateException("Inconsistent parser state"); } } }