net.lightbody.bmp.proxy.jetty.http.ajp.AJP13Packet.java Source code

Java tutorial

Introduction

Here is the source code for net.lightbody.bmp.proxy.jetty.http.ajp.AJP13Packet.java

Source

// ========================================================================
// $Id: AJP13Packet.java,v 1.24 2006/10/08 14:13:05 gregwilkins Exp $
// Copyright 2002-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at 
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================

package net.lightbody.bmp.proxy.jetty.http.ajp;

import net.lightbody.bmp.proxy.jetty.log.LogFactory;
import net.lightbody.bmp.proxy.jetty.util.ByteArrayISO8859Writer;
import net.lightbody.bmp.proxy.jetty.util.ByteArrayPool;
import net.lightbody.bmp.proxy.jetty.util.LogSupport;
import net.lightbody.bmp.proxy.jetty.util.StringUtil;
import org.apache.commons.logging.Log;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;

/* ------------------------------------------------------------ */
/**
 * 
 * @version $Id: AJP13Packet.java,v 1.24 2006/10/08 14:13:05 gregwilkins Exp $
 * @author Greg Wilkins (gregw)
 */
public abstract class AJP13Packet {
    private static Log log = LogFactory.getLog(AJP13Packet.class);

    /* ------------------------------------------------------------ */
    public static final int __MAX_BUF = 8192;
    public static final int __HDR_SIZE = 4;
    public static final int __DATA_HDR = 7;
    public static final int __MAX_DATA = __MAX_BUF - __DATA_HDR;

    public static final byte __FORWARD_REQUEST = 2, __SHUTDOWN = 7, __SEND_BODY_CHUNK = 3, __SEND_HEADERS = 4,
            __END_RESPONSE = 5, __GET_BODY_CHUNK = 6;

    public static final String[] __method = { "ERROR", "OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE",
            "PROPFIND", "PROPPATCH", "MKCOL", "COPY", "MOVE", "LOCK", "UNLOCK", "ACL", "REPORT", "VERSION-CONTROL",
            "CHECKIN", "CHECKOUT", "UNCHECKOUT", "SEARCH" };

    public String[] __header;

    protected HashMap __headerMap = new HashMap();

    /**
     * Abstract method to populate the header array and hash map.
     * 
     */
    abstract public void populateHeaders();

    /* ------------------------------------------------------------ */
    private byte[] _buf;
    private int _bytes;
    private int _pos;
    private ByteArrayISO8859Writer _byteWriter;
    private boolean _ownBuffer;

    /* ------------------------------------------------------------ */
    public AJP13Packet(byte[] buffer, int len) {
        populateHeaders();
        _buf = buffer;
        _ownBuffer = false;
        _bytes = len;
    }

    /* ------------------------------------------------------------ */
    public AJP13Packet(byte[] buffer) {
        populateHeaders();
        _buf = buffer;
        _ownBuffer = false;
    }

    /* ------------------------------------------------------------ */
    public AJP13Packet(int size) {
        populateHeaders();
        _buf = ByteArrayPool.getByteArray(size);
        _ownBuffer = true;
    }

    /* ------------------------------------------------------------ */
    public void prepare() {
        _bytes = 0;
        _pos = 0;
        addByte((byte) 'A');
        addByte((byte) 'B');
        addInt(0);
    }

    /* ------------------------------------------------------------ */
    public void destroy() {
        if (_ownBuffer)
            ByteArrayPool.returnByteArray(_buf);
        _buf = null;
        _byteWriter = null;
    }

    /* ------------------------------------------------------------ */
    public void reset() {
        _bytes = 0;
        _pos = 0;
    }

    /* ------------------------------------------------------------ */
    public byte[] getBuffer() {
        return _buf;
    }

    /* ------------------------------------------------------------ */
    public void resetData() {
        _bytes = __HDR_SIZE;
        _pos = 0;
    }

    /* ------------------------------------------------------------ */
    public int getMark() {
        return _bytes;
    }

    /* ------------------------------------------------------------ */
    public int getBufferSize() {
        return _buf.length;
    }

    /* ------------------------------------------------------------ */
    /**
     * @return Bytes of data remaining
     */
    public int unconsumedData() {
        return _bytes - _pos;
    }

    /* ------------------------------------------------------------ */
    /**
     * @return Bytes of capacity remaining
     */
    public int unconsumedCapacity() {
        return _buf.length - _bytes;
    }

    /* ------------------------------------------------------------ */
    public boolean read(InputStream in) throws IOException {
        _bytes = 0;
        _pos = 0;

        // read header
        do {
            int l = in.read(_buf, _bytes, __HDR_SIZE - _bytes);
            if (l < 0)
                return false;
            _bytes += l;
        } while (_bytes < __HDR_SIZE);

        // decode header
        int magic = getInt();
        if (magic != 0x1234)
            throw new IOException("Bad JSP13 rcv packet:" + magic + " " + this);
        int len = getInt();

        // check packet fits into the buffer
        int packetLength = __HDR_SIZE + len;
        if (packetLength > _buf.length)
            throw new IOException(
                    "AJP13 packet (" + packetLength + "bytes) too large for buffer (" + _buf.length + " bytes)");

        // read packet
        do {
            int l = in.read(_buf, _bytes, packetLength - _bytes);
            if (l < 0)
                return false;
            _bytes += l;
        } while (_bytes < packetLength);

        if (log.isTraceEnabled())
            log.trace("AJP13 rcv: " + this.toString(64));
        // System.err.println(Thread.currentThread()+" AJP13 rcv
        // "+this.toString());

        return true;
    }

    /* ------------------------------------------------------------ */
    public void write(OutputStream out) throws IOException {
        if (log.isTraceEnabled())
            log.trace("AJP13 snd: " + this.toString(64));
        // System.err.println(Thread.currentThread()+" AJP13 snd
        // "+this.toString());
        out.write(_buf, 0, _bytes);
    }

    /* ------------------------------------------------------------ */
    public byte getByte() {
        return _buf[_pos++];
    }

    /* ------------------------------------------------------------ */
    public int getBytes(byte[] buf, int offset, int length) {
        if (length > unconsumedData())
            length = unconsumedData();
        System.arraycopy(_buf, _pos, buf, offset, length);
        _pos += length;
        return length;
    }

    /* ------------------------------------------------------------ */
    public boolean getBoolean() {
        return _buf[_pos++] != 0;
    }

    /* ------------------------------------------------------------ */
    public int getInt() {
        int i = _buf[_pos++] & 0xFF;
        i = (i << 8) + (_buf[_pos++] & 0xFF);
        return i;
    }

    /* ------------------------------------------------------------ */
    public String getString() {
        int len = getInt();
        if (len == 0xFFFF)
            return null;
        try {
            String s = new String(_buf, _pos, len, StringUtil.__ISO_8859_1);
            _pos += len + 1;
            return s;
        } catch (IndexOutOfBoundsException e) {
            // Bad request!!!
            LogSupport.ignore(log, e);
            return null;
        } catch (UnsupportedEncodingException e) {
            log.fatal(e);
            System.exit(1);
            return null;
        }
    }

    /* ------------------------------------------------------------ */
    public String getMethod() {
        return __method[getByte()];
    }

    /* ------------------------------------------------------------ */
    public String getHeader() {
        if ((0xFF & _buf[_pos]) == 0xA0) {
            _pos++;

            return __header[_buf[_pos++]];
        }
        return getString();
    }

    /* ------------------------------------------------------------ */
    public void addByte(byte b) {
        _buf[_bytes++] = b;
    }

    /* ------------------------------------------------------------ */
    public int addBytes(byte[] buf, int offset, int length) {
        if (length > unconsumedCapacity())
            length = unconsumedCapacity();
        System.arraycopy(buf, offset, _buf, _bytes, length);
        _bytes += length;
        return length;
    }

    /* ------------------------------------------------------------ */
    public void addBoolean(boolean b) {
        _buf[_bytes++] = (byte) (b ? 1 : 0);
    }

    /* ------------------------------------------------------------ */
    public void addInt(int i) {
        _buf[_bytes++] = (byte) ((i >> 8) & 0xFF);
        _buf[_bytes++] = (byte) (i & 0xFF);
    }

    /* ------------------------------------------------------------ */
    public void setInt(int mark, int i) {
        _buf[mark] = (byte) ((i >> 8) & 0xFF);
        _buf[mark + 1] = (byte) (i & 0xFF);
    }

    /* ------------------------------------------------------------ */
    public void addString(String s) throws IOException {
        if (s == null) {
            addInt(0xFFFF);
            return;
        }

        if (_byteWriter == null)
            _byteWriter = new ByteArrayISO8859Writer(_buf);

        int p = _bytes + 2;
        _byteWriter.setLength(p);
        _byteWriter.write(s);
        int l = _byteWriter.size() - p;

        addInt(l);
        _bytes += l;
        _buf[_bytes++] = (byte) 0;
    }

    /* ------------------------------------------------------------ */
    public void addHeader(String s) throws IOException {
        Integer h = (Integer) __headerMap.get(s);
        if (h != null)
            addInt(h.intValue());
        else
            addString(s);
    }

    /* ------------------------------------------------------------ */
    public int getDataSize() {
        return _bytes - __HDR_SIZE;
    }

    /* ------------------------------------------------------------ */
    public void setDataSize() {
        setDataSize(_bytes - __HDR_SIZE);
    }

    /* ------------------------------------------------------------ */
    public void setDataSize(int s) {
        _bytes = s + __HDR_SIZE;

        if (_buf[4] == __SEND_BODY_CHUNK)
            s = s + 1;

        _buf[2] = (byte) ((s >> 8) & 0xFF);
        _buf[3] = (byte) (s & 0xFF);

        if (_buf[4] == __SEND_BODY_CHUNK) {
            s = s - 4;
            _buf[5] = (byte) ((s >> 8) & 0xFF);
            _buf[6] = (byte) (s & 0xFF);
        }
    }

    /* ------------------------------------------------------------ */
    public String toString() {
        return toString(-1);
    }

    /* ------------------------------------------------------------ */
    public String toString(int max) {
        StringBuffer b = new StringBuffer();
        StringBuffer a = new StringBuffer();

        b.append(_bytes);
        b.append('/');
        b.append(_buf.length);
        b.append('[');
        b.append(_pos);
        b.append("]: ");

        switch (_buf[__HDR_SIZE]) {
        case __FORWARD_REQUEST:
            b.append("FORWARD_REQUEST{:");
            break;
        case __SHUTDOWN:
            b.append("SHUTDOWN        :");
            break;
        case __SEND_BODY_CHUNK:
            b.append("SEND_BODY_CHUNK :");
            break;
        case __SEND_HEADERS:
            b.append("SEND_HEADERS  ( :");
            break;
        case __END_RESPONSE:
            b.append("END_RESPONSE  )}:");
            break;
        case __GET_BODY_CHUNK:
            b.append("GET_BODY_CHUNK  :");
            break;
        }

        if (max == 0)
            return b.toString();

        b.append("\n");

        for (int i = 0; i < _bytes; i++) {
            int d = _buf[i] & 0xFF;
            if (d < 16)
                b.append('0');
            b.append(Integer.toString(d, 16));

            char c = (char) d;

            if (Character.isLetterOrDigit(c))
                a.append(c);
            else
                a.append('.');

            if (i % 32 == 31 || i == (_bytes - 1)) {
                b.append(" : ");
                b.append(a.toString());
                a.setLength(0);
                b.append("\n");
                if (max > 0 && (i + 1) >= max)
                    break;
            } else
                b.append(",");
        }

        return b.toString();
    }
}