com.subgraph.vega.ui.httpeditor.parser.ParserBase.java Source code

Java tutorial

Introduction

Here is the source code for com.subgraph.vega.ui.httpeditor.parser.ParserBase.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Subgraph.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Subgraph - initial API and implementation
 ******************************************************************************/
package com.subgraph.vega.ui.httpeditor.parser;

import org.apache.http.Header;
import org.apache.http.ParseException;
import org.apache.http.message.LineParser;
import org.apache.http.message.ParserCursor;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.CharArrayBuffer;

import com.subgraph.vega.api.http.requests.IHttpMessageBuilder;

public abstract class ParserBase {

    /**
     * Get the next line of characters from a CharArrayBuffer into another CharArrayBuffer. Treats LF and CRLF as valid
     * line delimiters. Treats the entire buffer as a line if no line delimiters are found.
     * 
     * @param src Source buffer to read line from.
     * @param srcCursor Parser cursor for src. Adjusted to discard line delimiters.
     * @param dst Destination buffer for characters from line. 
     * @return Number of characters in line minus line delimiters, or < 0 if none found.
     */
    protected int readLine(final CharArrayBuffer src, final ParserCursor srcCursor, final CharArrayBuffer dst) {
        if (srcCursor.atEnd()) {
            return -1;
        }

        int idxPos = srcCursor.getPos();
        int idxLf = src.indexOf(HTTP.LF, idxPos, srcCursor.getUpperBound());
        int idxEnd;

        if (idxLf > 0) {
            if (src.charAt(idxLf - 1) == HTTP.CR) {
                idxEnd = idxLf - 1;
            } else {
                idxEnd = idxLf;
            }
        } else {
            idxEnd = srcCursor.getUpperBound();
            idxLf = idxEnd - 1;
        }

        dst.append(src, idxPos, idxEnd - idxPos);
        srcCursor.updatePos(idxLf + 1);
        return idxEnd - idxPos;
    }

    /**
     * Get the next header line of characters from a CharArrayBuffer into another CharArrayBuffer. Treats LF and CRLF as
     * valid line delimiters. Treats the entire buffer as a line if no line delimiters are found. Supports folded header
     * field values as per the HTTP/1.1 specification.
     *    
     * @param src Source buffer to read line from.
     * @param srcCursor Parser cursor for src. Adjusted to discard line delimiters.
     * @param dst Destination buffer for characters from line. 
     * @return Number of characters in line minus line delimiters, or < 0 if none found.
     */
    protected int readLineHeader(final CharArrayBuffer src, final ParserCursor srcCursor,
            final CharArrayBuffer dst) {
        if (srcCursor.atEnd()) {
            return -1;
        }

        int idxPos = srcCursor.getPos();
        int chCnt = 0;
        int idxLf, idxEnd;

        do {
            idxLf = src.indexOf(HTTP.LF, idxPos, srcCursor.getUpperBound());

            if (idxLf > 0) {
                if (src.charAt(idxLf - 1) == HTTP.CR) {
                    idxEnd = idxLf - 1;
                } else {
                    idxEnd = idxLf;
                }
            } else {
                idxEnd = srcCursor.getUpperBound();
                idxLf = idxEnd - 1;
            }

            if (chCnt != 0) {
                while (idxPos < idxEnd && (src.charAt(idxPos) == HTTP.HT || src.charAt(idxPos) == HTTP.SP)) {
                    idxPos++;
                }
                if (idxPos != idxEnd) {
                    dst.append(' ');
                }
            }

            dst.append(src, idxPos, idxEnd - idxPos);
            chCnt += idxEnd - idxPos;
            idxPos = idxLf + 1;
            srcCursor.updatePos(idxPos);
        } while (idxPos < srcCursor.getUpperBound()
                && (src.charAt(idxPos) == HTTP.HT || src.charAt(idxPos) == HTTP.SP));

        return chCnt;
    }

    /**
     * Get the next word from a buffer containing a line.
     * 
     * @param lnBuf Buffer containing line.
     * @param lnCursor Parser cursor for lnBuf. Adjusted to one character after the word.
     * @return Next word, or null if none is found.
     */
    protected String nextWord(final CharArrayBuffer lnBuf, final ParserCursor lnCursor) {
        skipSpHt(lnBuf, lnCursor);
        int idxPos = lnCursor.getPos();
        int idxLineEnd = lnBuf.indexOf(' ', idxPos, lnCursor.getUpperBound());
        if (idxLineEnd < 0) {
            if (idxPos == lnCursor.getUpperBound()) {
                return null;
            }
            idxLineEnd = lnCursor.getUpperBound();
        }
        lnCursor.updatePos(idxLineEnd);
        return lnBuf.substringTrimmed(idxPos, idxLineEnd);
    }

    /**
     * Skip SP and HT characters in a line.   
     * 
     * @param lnBuf Buffer containing line.
     * @param lnCursor Parser cursor for lnBuf. Adjusted to one character after and SP and HT.
     */
    protected void skipSpHt(final CharArrayBuffer lnBuf, final ParserCursor lnCursor) {
        int idxTo = lnCursor.getUpperBound();
        int idxPos = lnCursor.getPos();
        while (idxPos < idxTo && (lnBuf.charAt(idxPos) == HTTP.SP || lnBuf.charAt(idxPos) == HTTP.HT)) {
            idxPos++;
        }
        lnCursor.updatePos(idxPos);
    }

    /**
     * Parse HTTP headers and add them to a IHttpMessageBuilder until a non-header line is encountered.
     * 
     * @param parser HC line parser.
     * @param builder IHttpMessageBuilder to add parsed headers to.
     * @param buf Buffer containing header data.
     * @param bufCursor Parser cursor for buf. Adjusted to one character past the end of headers and optional CRLF line.
     */
    protected void parseHeaders(final LineParser parser, final IHttpMessageBuilder builder,
            final CharArrayBuffer buf, final ParserCursor bufCursor) {
        final CharArrayBuffer lnBuf = new CharArrayBuffer(0);
        while (true) {
            lnBuf.clear();
            int idxPos = bufCursor.getPos();
            if (readLineHeader(buf, bufCursor, lnBuf) > 0) {
                try {
                    // REVISIT don't want an extra step
                    Header header = parser.parseHeader(lnBuf);
                    builder.addHeader(header.getName(), header.getValue());
                } catch (ParseException e) {
                    // for now we'll move the cursor back so the line gets treated as the start of the body
                    bufCursor.updatePos(idxPos);
                    return;
                }
            } else {
                break;
            }
        }
    }

}