/*
 * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


package com.sun.jmx.snmp;


The BerEncoder class is used for encoding data using BER. A BerEncoder needs to be set up with a byte buffer. The encoded data are stored in this byte buffer.

NOTE : the buffer is filled from end to start. This means the caller needs to encode its data in the reverse order.

This API is a Sun Microsystems internal API and is subject to change without notice.

Since:1.5
/** * The <CODE>BerEncoder</CODE> class is used for encoding data using BER. * * A <CODE>BerEncoder</CODE> needs to be set up with a byte buffer. The encoded * data are stored in this byte buffer. * <P> * NOTE : the buffer is filled from end to start. This means the caller * needs to encode its data in the reverse order. * * * <p><b>This API is a Sun Microsystems internal API and is subject * to change without notice.</b></p> * * @since 1.5 */
public class BerEncoder {
Constructs a new encoder and attaches it to the specified byte string.
Params:
  • b – The byte string containing the encoded data.
/** * Constructs a new encoder and attaches it to the specified byte string. * * @param b The byte string containing the encoded data. */
public BerEncoder(byte b[]) { bytes = b ; start = b.length ; stackTop = 0 ; }
Trim the encoding data and returns the length of the encoding. The encoder does backward encoding : so the bytes buffer is filled from end to start. The encoded data must be shift before the buffer can be used. This is the purpose of the trim method. After a call to the trim method, the encoder is reinitialized and putXXX overwrite any existing encoded data.
Returns:The length of the encoded data.
/** * Trim the encoding data and returns the length of the encoding. * * The encoder does backward encoding : so the bytes buffer is * filled from end to start. The encoded data must be shift before * the buffer can be used. This is the purpose of the <CODE>trim</CODE> method. * * After a call to the <CODE>trim</CODE> method, the encoder is reinitialized and <CODE>putXXX</CODE> * overwrite any existing encoded data. * * @return The length of the encoded data. */
public int trim() { final int result = bytes.length - start ; // for (int i = start ; i < bytes.length ; i++) { // bytes[i-start] = bytes[i] ; // } if (result > 0) java.lang.System.arraycopy(bytes,start,bytes,0,result); start = bytes.length ; stackTop = 0 ; return result ; }
Put an integer.
Params:
  • v – The integer to encode.
/** * Put an integer. * * @param v The integer to encode. */
public void putInteger(int v) { putInteger(v, IntegerTag) ; }
Put an integer with the specified tag.
Params:
  • v – The integer to encode.
  • tag – The tag to encode.
/** * Put an integer with the specified tag. * * @param v The integer to encode. * @param tag The tag to encode. */
public void putInteger(int v, int tag) { putIntegerValue(v) ; putTag(tag) ; }
Put an integer expressed as a long.
Params:
  • v – The long to encode.
/** * Put an integer expressed as a long. * * @param v The long to encode. */
public void putInteger(long v) { putInteger(v, IntegerTag) ; }
Put an integer expressed as a long with the specified tag.
Params:
  • v – The long to encode
  • tag – The tag to encode.
/** * Put an integer expressed as a long with the specified tag. * * @param v The long to encode * @param tag The tag to encode. */
public void putInteger(long v, int tag) { putIntegerValue(v) ; putTag(tag) ; }
Put an octet string.
Params:
  • s – The bytes to encode
/** * Put an octet string. * * @param s The bytes to encode */
public void putOctetString(byte[] s) { putOctetString(s, OctetStringTag) ; }
Put an octet string with a specified tag.
Params:
  • s – The bytes to encode
  • tag – The tag to encode.
/** * Put an octet string with a specified tag. * * @param s The bytes to encode * @param tag The tag to encode. */
public void putOctetString(byte[] s, int tag) { putStringValue(s) ; putTag(tag) ; }
Put an object identifier.
Params:
  • s – The oid to encode.
/** * Put an object identifier. * * @param s The oid to encode. */
public void putOid(long[] s) { putOid(s, OidTag) ; }
Put an object identifier with a specified tag.
Params:
  • s – The integer to encode.
  • tag – The tag to encode.
/** * Put an object identifier with a specified tag. * * @param s The integer to encode. * @param tag The tag to encode. */
public void putOid(long[] s, int tag) { putOidValue(s) ; putTag(tag) ; }
Put a NULL value.
/** * Put a <CODE>NULL</CODE> value. */
public void putNull() { putNull(NullTag) ; }
Put a NULL value with a specified tag.
Params:
  • tag – The tag to encode.
/** * Put a <CODE>NULL</CODE> value with a specified tag. * * @param tag The tag to encode. */
public void putNull(int tag) { putLength(0) ; putTag(tag) ; }
Put an ANY value. In fact, this method does not encode anything. It simply copies the specified bytes into the encoding.
Params:
  • s – The encoding of the ANY value.
/** * Put an <CODE>ANY</CODE> value. In fact, this method does not encode anything. * It simply copies the specified bytes into the encoding. * * @param s The encoding of the <CODE>ANY</CODE> value. */
public void putAny(byte[] s) { putAny(s, s.length) ; }
Put an ANY value. Only the first byteCount are considered.
Params:
  • s – The encoding of the ANY value.
  • byteCount – The number of bytes of the encoding.
/** * Put an <CODE>ANY</CODE> value. Only the first <CODE>byteCount</CODE> are considered. * * @param s The encoding of the <CODE>ANY</CODE> value. * @param byteCount The number of bytes of the encoding. */
public void putAny(byte[] s, int byteCount) { java.lang.System.arraycopy(s,0,bytes,start-byteCount,byteCount); start -= byteCount; // for (int i = byteCount - 1 ; i >= 0 ; i--) { // bytes[--start] = s[i] ; // } }
Open a sequence. The encoder push the current position on its stack.
/** * Open a sequence. * The encoder push the current position on its stack. */
public void openSequence() { stackBuf[stackTop++] = start ; }
Close a sequence. The decode pull the stack to know the end of the current sequence.
/** * Close a sequence. * The decode pull the stack to know the end of the current sequence. */
public void closeSequence() { closeSequence(SequenceTag) ; }
Close a sequence with the specified tag.
/** * Close a sequence with the specified tag. */
public void closeSequence(int tag) { final int end = stackBuf[--stackTop] ; putLength(end - start) ; putTag(tag) ; } // // Some standard tags // public final static int BooleanTag = 1 ; public final static int IntegerTag = 2 ; public final static int OctetStringTag = 4 ; public final static int NullTag = 5 ; public final static int OidTag = 6 ; public final static int SequenceTag = 0x30 ; ////////////////////////// PROTECTED ///////////////////////////////
Put a tag and move the current position backward.
Params:
  • tag – The tag to encode.
/** * Put a tag and move the current position backward. * * @param tag The tag to encode. */
protected final void putTag(int tag) { if (tag < 256) { bytes[--start] = (byte)tag ; } else { while (tag != 0) { bytes[--start] = (byte)(tag & 127) ; tag = tag << 7 ; } } }
Put a length and move the current position backward.
Params:
  • length – The length to encode.
/** * Put a length and move the current position backward. * * @param length The length to encode. */
protected final void putLength(final int length) { if (length < 0) { throw new IllegalArgumentException() ; } else if (length < 128) { bytes[--start] = (byte)length ; } else if (length < 256) { bytes[--start] = (byte)length ; bytes[--start] = (byte)0x81 ; } else if (length < 65536) { bytes[--start] = (byte)(length) ; bytes[--start] = (byte)(length >> 8) ; bytes[--start] = (byte)0x82 ; } else if (length < 16777126) { bytes[--start] = (byte)(length) ; bytes[--start] = (byte)(length >> 8) ; bytes[--start] = (byte)(length >> 16) ; bytes[--start] = (byte)0x83 ; } else { bytes[--start] = (byte)(length) ; bytes[--start] = (byte)(length >> 8) ; bytes[--start] = (byte)(length >> 16) ; bytes[--start] = (byte)(length >> 24) ; bytes[--start] = (byte)0x84 ; } }
Put an integer value and move the current position backward.
Params:
  • v – The integer to encode.
/** * Put an integer value and move the current position backward. * * @param v The integer to encode. */
protected final void putIntegerValue(int v) { final int end = start ; int mask = 0x7f800000 ; int byteNeeded = 4 ; if (v < 0) { while (((mask & v) == mask) && (byteNeeded > 1)) { mask = mask >> 8 ; byteNeeded-- ; } } else { while (((mask & v) == 0) && (byteNeeded > 1)) { mask = mask >> 8 ; byteNeeded-- ; } } for (int i = 0 ; i < byteNeeded ; i++) { bytes[--start] = (byte)v ; v = v >> 8 ; } putLength(end - start) ; }
Put an integer value expressed as a long.
Params:
  • v – The integer to encode.
/** * Put an integer value expressed as a long. * * @param v The integer to encode. */
protected final void putIntegerValue(long v) { final int end = start ; long mask = 0x7f80000000000000L ; int byteNeeded = 8 ; if (v < 0) { while (((mask & v) == mask) && (byteNeeded > 1)) { mask = mask >> 8 ; byteNeeded-- ; } } else { while (((mask & v) == 0) && (byteNeeded > 1)) { mask = mask >> 8 ; byteNeeded-- ; } } for (int i = 0 ; i < byteNeeded ; i++) { bytes[--start] = (byte)v ; v = v >> 8 ; } putLength(end - start) ; }
Put a byte string and move the current position backward.
Params:
  • s – The byte string to encode.
/** * Put a byte string and move the current position backward. * * @param s The byte string to encode. */
protected final void putStringValue(byte[] s) { final int datalen = s.length; java.lang.System.arraycopy(s,0,bytes,start-datalen,datalen); start -= datalen; // for (int i = s.length - 1 ; i >= 0 ; i--) { // bytes[--start] = s[i] ; // } putLength(datalen) ; }
Put an oid and move the current position backward.
Params:
  • s – The oid to encode.
/** * Put an oid and move the current position backward. * * @param s The oid to encode. */
protected final void putOidValue(final long[] s) { final int end = start ; final int slength = s.length; // bugId 4641746: 0, 1, and 2 are legal values. if ((slength < 2) || (s[0] > 2) || (s[1] >= 40)) { throw new IllegalArgumentException() ; } for (int i = slength - 1 ; i >= 2 ; i--) { long c = s[i] ; if (c < 0) { throw new IllegalArgumentException() ; } else if (c < 128) { bytes[--start] = (byte)c ; } else { bytes[--start] = (byte)(c & 127) ; c = c >> 7 ; while (c != 0) { bytes[--start] = (byte)(c | 128) ; c = c >> 7 ; } } } bytes[--start] = (byte)(s[0] * 40 + s[1]) ; putLength(end - start) ; } // // This is the byte array containing the encoding. // protected final byte bytes[]; // // This is the index of the first byte of the encoding. // It is initialized to <CODE>bytes.length</CODE> and decrease each time // an value is put in the encoder. // protected int start = -1 ; // // This is the stack where end of sequences are kept. // A value is computed and pushed in it each time the <CODE>openSequence</CODE> method // is invoked. // A value is pulled and checked each time the <CODE>closeSequence</CODE> method is called. // protected final int stackBuf[] = new int[200] ; protected int stackTop = 0 ; }