berencoder.java

来自「opennms得相关源码 请大家看看」· Java 代码 · 共 1,296 行 · 第 1/3 页

JAVA
1,296
字号
//// This file is part of the OpenNMS(R) Application.//// OpenNMS(R) is Copyright (C) 2002-2003 The OpenNMS Group, Inc.  All rights reserved.// OpenNMS(R) is a derivative work, containing both original code, included code and modified// code that was published under the GNU General Public License. Copyrights for modified // and included code are below.//// OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.//// Copyright (C) 1999-2001 Oculan Corp.  All rights reserved.//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//// For more information contact://      OpenNMS Licensing       <license@opennms.org>//      http://www.opennms.org///      http://www.opennms.com///// Tab Size = 8//// BerEncoder.java,v 1.1.1.1 2001/11/11 17:27:23 ben Exp//package org.opennms.protocols.snmp.asn1;import java.math.BigInteger;/** * The BerEncoder class is used to implement the AsnEncoder interface for the * Basic Encoding Rules (BER). The encoding rules are used to encode and decode * SNMP values using BER. *  * @author <a href="http://www.opennms.org">OpenNMS </a> * @author <a href="mailto:weave@oculan.com">Brian Weaver </a> * @version 1.1.1.1 */public class BerEncoder implements AsnEncoder {    /**     * Defines the ASN.1 long length marker for the Basic Encoding Rule (BER)     */    private static final byte LONG_LENGTH = (byte) 0x80;    /**     * Defines the "high bit" that is the sign extension bit for a 8-bit signed     * value.     */    private static final byte HIGH_BIT = (byte) 0x80;    /**     * Defines the BER extension "value" that is used to mark an extension type.     */    private static final byte EXTENSION_ID = (byte) 0x1F;    /**     * Defines the BER constructor id     */    private static final byte CONSTRUCTOR = (byte) 0x20;    /**     * Converts a primitive byte to a primitive long using "unsigned" logic.     *      * @param b     *            The 8-bit value to convert     * @return Returns the 32-bit converted value     *      */    protected static int byteToInt(byte b) {        return (b < 0) ? 256 + (int) b : (int) b;    }    /**     * Converts a primitive byte to a primitive long. The byte is converted     * using "unsigned" logic     *      * @param b     *            The 8-bit value to convert     * @return Returns the 64-bit converted value     *      */    protected static long byteToLong(byte b) {        return (b < 0) ? 256 + (long) b : (long) b;    }    /**     * Used to determine if the ASN.1 type is a constructor.     *      * @param b     *            The ASN.1 type     *      * @return True if the ASN.1 type is a constructor, otherwise a false is     *         returned.     *      */    protected static boolean isConstructor(byte b) {        return ((b & CONSTRUCTOR) == CONSTRUCTOR);    }    /**     * Used to test if the ASN.1 type is an extension.     *      * @param b     *            The ASN.1 type.     *      * @return True if the ASN.1 type is an extension. False if the ASN.1 type     *         is not an extension.     *      */    protected static boolean isExtensionId(byte b) {        return ((b & EXTENSION_ID) == EXTENSION_ID);    }    /**     * Used to copy data from one buffer to another. The method has the     * flexability to allow the caller to specify an offset in each buffer and     * the total number of bytes to copy     *      * @param src     *            The source buffer     * @param srcOff     *            The offset of the first byte in the source buffer     * @param dest     *            The destination buffer     * @param destOff     *            The offset of the first byte in the destination buffer     * @param bytesToCopy     *            The number of bytes to copy     *      * @exception ArrayIndexOutOfBoundsException     *                Thrown if there is insufficent space in either array to     *                copy the data.     *      */    protected static void copy(byte[] src, int srcOff, byte[] dest, int destOff, int bytesToCopy) throws ArrayIndexOutOfBoundsException {        if ((dest.length - destOff) < bytesToCopy || (src.length - srcOff) < bytesToCopy)            throw new ArrayIndexOutOfBoundsException("Destination or source buffer is insufficent");        for (int x = bytesToCopy - 1; x >= 0; x--) {            dest[destOff + x] = src[srcOff + x];        }    }    /**     * Used to copy data from one buffer to another. The method has the     * flexability to allow the caller to specify an offset in each buffer and     * the total number of integers to copy     *      * @param src     *            The source buffer     * @param srcOff     *            The offset of the first integer in the source buffer     * @param dest     *            The destination buffer     * @param destOff     *            The offset of the first integer in the destination buffer     * @param intsToCopy     *            The number of integer elements to copy     *      * @exception ArrayIndexOutOfBoundsException     *                Thrown if there is insufficent space in either array to     *                copy the data.     *      */    protected static void copy(int[] src, int srcOff, int[] dest, int destOff, int intsToCopy) throws ArrayIndexOutOfBoundsException {        if ((dest.length - destOff) < intsToCopy || (src.length - srcOff) < intsToCopy)            throw new ArrayIndexOutOfBoundsException("Destination or source buffer is insufficent");        for (int x = intsToCopy - 1; x >= 0; x--) {            dest[destOff + x] = src[srcOff + x];        }    }    /**     * Rotates a give buffer area marked by begin, pivot, and end. The pivot     * marks the point where the bytes between [pivot..end) are moved to the     * position marked by begin. The bytes between [begin..pivot) are shifted     * such that begin is at [begin+(end-pivot)].     *      * @param buf     *            The buffer containing the data to rotate     * @param begin     *            The start of the rotation     * @param pivot     *            The pivot point for the rotation     * @param end     *            The end of the rotational buffer     *      * @exception ArrayIndexOutOfBoundsException     *                Thrown if an access exception occurs     *      */    protected static void rotate(byte[] buf, int begin, int pivot, int end) throws ArrayIndexOutOfBoundsException {        int dist = end - pivot;        byte[] hold = new byte[dist];        copy(buf, // source             pivot, // source offset             hold, // destination             0, // destination offset             dist); // length        //        // shift from end of buffer to front. This        // way we do not have to worry about data        // corruption        //        for (int x = (pivot - begin) - 1; x >= 0; x--) {            buf[begin + dist + x] = buf[begin + x]; // SHIFT!        }        copy(hold, // source             0, // source offset             buf, // destination             begin, // destination offset             dist); // length    }    /**     * Default constructor for the BER Encoder.     *      */    public BerEncoder() {        // default class constructor.        // Does nothing    }    /**     *      * The buildLength() method is used to encode an ASN.1 length into the     * specified byte buffer. The method is defined in the AsnEncoder interface.     *      * @param buf     *            The output buffer of encoded bytes.     * @param startOffset     *            The offset from the start of the buffer where the method     *            should start writing the encoded data.     * @param asnLength     *            The length to be encoded.     *      * @return Returns the new offset for the next encoding routine. If the     *         startOffset is subtracted from the return value then the length     *         of the encoded data can be determined.     *      * @exception AsnEncodingException     *                Thrown if an error occurs encoding the datatype.     */    public int buildLength(byte[] buf, int startOffset, int asnLength) throws AsnEncodingException {        if (asnLength <= 0x7f) {            //             // check the buffer length            //            if ((buf.length - startOffset) < 1)                throw new AsnEncodingException("Buffer overflow error");            buf[startOffset++] = (byte) (asnLength & 0x7f);        } else if (asnLength <= 0xff) {            //            // check the buffer length            //            if ((buf.length - startOffset) < 2)                throw new AsnEncodingException("Buffer overflow error");            buf[startOffset++] = (byte) (0x01 | LONG_LENGTH);            buf[startOffset++] = (byte) (asnLength & 0xff);        } else // 0xff < asnLength <= 0xffff        {            //            // check the buffer length            //            if ((buf.length - startOffset) < 3)                throw new AsnEncodingException("Buffer overflow error");            buf[startOffset++] = (byte) (0x02 | LONG_LENGTH);            buf[startOffset++] = (byte) ((asnLength >>> 8) & 0xff);            buf[startOffset++] = (byte) (asnLength & 0xff);        }        return startOffset;    }    /**     *      * The parseLength() method is used to decode an ASN.1 length from the     * specified buffer. The method is defined to support the AsnEncoder     * interface.     *      * @param buf     *            The input buffer     * @param startOffset     *            The offset to start decoding in the buffer     *      * @return Returns an Object array that contains the new offset and the     *         decoded length. The first object is an Integer object and     *         contains the new offset for the next object in buf. The second     *         object is an Integer and contains the actual decoded length.     *      * @exception AsnDecodingException     *                Thrown if an error occurs decoding the buffer.     */    public Object[] parseLength(byte[] buf, int startOffset) throws AsnDecodingException {        //        // check the buffer length        //        if ((buf.length - startOffset) < 1)            throw new AsnDecodingException("Buffer underflow error");        //        // 1) Integer w/new offset value        // 2) Integer w/recovered length        //        Object[] retVals = new Object[2];        //        // get the first byte and check it for        // the long length field        //        byte numBytes = buf[startOffset++];        if ((numBytes & LONG_LENGTH) == 0) {            //            // short definiate length encoding            //            numBytes = (byte) (numBytes & ~LONG_LENGTH);            retVals[1] = new Integer(byteToInt(numBytes));        } else {            //            // Long length encoding            //            numBytes = (byte) (numBytes & ~LONG_LENGTH);            if (numBytes == 1) {                if ((buf.length - startOffset) < 1)                    throw new AsnDecodingException("Buffer underflow error");                retVals[1] = new Integer(byteToInt(buf[startOffset++]));            } else if (numBytes == 2) {                if ((buf.length - startOffset) < 2)                    throw new AsnDecodingException("Buffer underflow error");                int val = byteToInt(buf[startOffset++]) << 8 | byteToInt(buf[startOffset++]);                retVals[1] = new Integer(val);            } else {                throw new AsnDecodingException("Invalid ASN.1 length");            }        }        //        // create the offset object        //        retVals[0] = new Integer(startOffset);        return retVals;    }    /**     *      * The buildHeader() method is used to encode an ASN.1 header into the     * specified byte buffer. The method is defined to support the AsnEncoder     * interface. This method is dependant on the buildLength() method.     *      * @param buf     *            The output buffer of encoded bytes.     * @param startOffset     *            The offset from the start of the buffer where the method     *            should start writing the encoded data.     * @param asnType     *            The ASN.1 type to place in the buffer     * @param asnLength     *            The length to be encoded.     *      * @return Returns the new offset for the next encoding routine. If     *         startOffset is subtracted from the return value then the length     *         of the encoded data can be determined.     *      * @exception AsnEncodingException     *                Thrown if an error occurs encoding the datatype.     *      */    public int buildHeader(byte[] buf, int startOffset, byte asnType, int asnLength) throws AsnEncodingException {        if ((buf.length - startOffset) < 1)            throw new AsnEncodingException("Buffer overflow error");        buf[startOffset++] = asnType;        return buildLength(buf, startOffset, asnLength);    }    /**     *      * The parseHeader() method is used to decode an ASN.1 header from the     * specified buffer. The method is defined to support the AsnEncoder     * interface. The method also calls the parseLength() method.     *      * @param buf     *            The input buffer     * @param startOffset     *            The offset to start decoding in the buffer     *      * @return Returns an Object array that contains the new offset, ASN.1 type,     *         and decoded length. The first object is an Integer object and     *         contains the new offset for the next object in buf. The second     *         object is a Byte object that represents the decoded ASN.1 Type.     *         The third object is an Integer and contains the actual decoded     *         length.     *      * @exception AsnDecodingException     *                Thrown if an error occurs decoding the buffer.     */    public Object[] parseHeader(byte[] buf, int startOffset) throws AsnDecodingException {        if ((buf.length - startOffset) < 1)            throw new AsnDecodingException("Insufficent buffer length");        //        // get the ASN.1 Type        //        byte asnType = buf[startOffset++];        if (isExtensionId(asnType))            throw new AsnDecodingException("Buffer underflow error");        //        // get the length        //        Object[] lenVals = parseLength(buf, startOffset);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?