|
Java example source code file (BerEncoder.java)
This example Java source code file (BerEncoder.java) is included in the alvinalexander.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
Learn more about this Java project at its project page.
The BerEncoder.java Java example source code
/*
* 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 <CODE>BerEncoder class is used for encoding data using BER.
*
* A <CODE>BerEncoder 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>This API is a Sun Microsystems internal API and is subject
* to change without notice.</b>
*
* @since 1.5
*/
public class BerEncoder {
/**
* 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 <CODE>trim method.
*
* After a call to the <CODE>trim method, the encoder is reinitialized and putXXX
* 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.
*
* @param v The integer to encode.
*/
public void putInteger(int v) {
putInteger(v, IntegerTag) ;
}
/**
* 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.
*
* @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.
*
* @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.
*
* @param s The bytes to encode
*/
public void putOctetString(byte[] s) {
putOctetString(s, OctetStringTag) ;
}
/**
* 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.
*
* @param s The oid to encode.
*/
public void putOid(long[] s) {
putOid(s, OidTag) ;
}
/**
* 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 <CODE>NULL value.
*/
public void putNull() {
putNull(NullTag) ;
}
/**
* Put a <CODE>NULL value with a specified tag.
*
* @param tag The tag to encode.
*/
public void putNull(int tag) {
putLength(0) ;
putTag(tag) ;
}
/**
* Put an <CODE>ANY 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 value.
*/
public void putAny(byte[] s) {
putAny(s, s.length) ;
}
/**
* Put an <CODE>ANY value. Only the first byteCount are considered.
*
* @param s The encoding of the <CODE>ANY 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.
*/
public void openSequence() {
stackBuf[stackTop++] = start ;
}
/**
* 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.
*/
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.
*
* @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.
*
* @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.
*
* @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.
*
* @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.
*
* @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.
*
* @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 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 method
// is invoked.
// A value is pulled and checked each time the <CODE>closeSequence method is called.
//
protected final int stackBuf[] = new int[200] ;
protected int stackTop = 0 ;
}
Other Java examples (source code examples)
Here is a short list of links related to this Java BerEncoder.java source code file:
|