📄 snmpobjectidentifier.java
字号:
/*
* SNMP Package
*
* Copyright (C) 2004, Jonathan Sevy <jsevy@mcs.drexel.edu>
*
* This is free software. Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package snmp;
import java.util.*;
import java.io.*;
/**
* Class representing ASN.1 object identifiers. These are unbounded sequences (arrays) of
* natural numbers, written as dot-separated strings.
*/
public class SNMPObjectIdentifier extends SNMPObject
{
private long[] digits; // array of longs
protected byte tag = SNMPBERCodec.SNMPOBJECTIDENTIFIER;
/**
* Create a new empty object identifier (0-length array).
*/
public SNMPObjectIdentifier()
{
digits = new long[0];
}
/**
* Create a new object identifier from the supplied string of dot-separated nonegative
* decimal integer values.
* @throws SNMPBadValueException Indicates incorrectly-formatted string supplied.
*/
public SNMPObjectIdentifier(String digitString)
throws SNMPBadValueException
{
convertDigitString(digitString);
}
/**
* Create a new object identifier from the supplied array of nonegative
* integer values.
* @throws SNMPBadValueException Negative value(s) supplied.
*/
public SNMPObjectIdentifier(int[] digits)
throws SNMPBadValueException
{
long[] longDigits = new long[digits.length];
for (int i = 0; i < digits.length; i++)
{
if (digits[i] < 0)
throw new SNMPBadValueException("Negative value supplied for SNMPObjectIdentifier.");
longDigits[i] = digits[i];
}
this.digits = longDigits;
}
/**
* Create a new object identifier from the supplied array of nonegative
* long values.
* @throws SNMPBadValueException Negative value(s) supplied.
*/
public SNMPObjectIdentifier(long[] digits)
throws SNMPBadValueException
{
for (int i = 0; i < digits.length; i++)
{
if (digits[i] < 0)
throw new SNMPBadValueException("Negative value supplied for SNMPObjectIdentifier.");
}
this.digits = digits;
}
/**
* Used to initialize from the BER encoding, as received in a response from
* an SNMP device responding to an SNMPGetRequest.
* @throws SNMPBadValueException Indicates an invalid BER encoding supplied. Shouldn't
* occur in normal operation, i.e., when valid responses are received from devices.
*/
protected SNMPObjectIdentifier(byte[] enc)
throws SNMPBadValueException
{
extractFromBEREncoding(enc);
}
/**
* Return array of integers corresponding to components of identifier.
*/
public Object getValue()
{
return digits;
}
/**
* Used to set the value from an integer or long array containing the identifier components, or from
* a String containing a dot-separated sequence of nonegative values.
* @throws SNMPBadValueException Indicates an incorrect object type supplied, or negative array
* elements, or an incorrectly formatted String.
*/
public void setValue(Object digits)
throws SNMPBadValueException
{
if (digits instanceof long[])
{
for (int i = 0; i < ((long[])digits).length; i++)
{
if (((long[])digits)[i] < 0)
throw new SNMPBadValueException("Negative value supplied for SNMPObjectIdentifier.");
}
this.digits = (long[])digits;
}
else if (digits instanceof int[])
{
long[] longDigits = new long[((int[])digits).length];
for (int i = 0; i < ((int[])digits).length; i++)
{
if (((int[])digits)[i] < 0)
throw new SNMPBadValueException("Negative value supplied for SNMPObjectIdentifier.");
longDigits[i] = ((int[])digits)[i];
}
this.digits = longDigits;
}
else if (digits instanceof String)
{
convertDigitString((String)digits);
}
else
throw new SNMPBadValueException(" Object Identifier: bad object supplied to set value ");
}
/**
* Return BER encoding for this object identifier.
*/
protected byte[] getBEREncoding()
{
ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
byte type = SNMPBERCodec.SNMPOBJECTIDENTIFIER;
// write contents of array of values
byte[] data = encodeArray();
// calculate encoding for length of data
byte[] len = SNMPBERCodec.encodeLength(data.length);
// encode T,L,V info
outBytes.write(type);
outBytes.write(len, 0, len.length);
outBytes.write(data, 0, data.length);
return outBytes.toByteArray();
}
private byte[] encodeArray()
{
ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
int numElements = digits.length;
// encode first two identifier digits as one byte, using the 40*x + y rule;
// of course, if only one element, just use 40*x; if none, do nothing
if (numElements >= 2)
{
outBytes.write((byte)(40*digits[0] + digits[1]));
}
else if (numElements ==1)
{
outBytes.write((byte)(40*digits[0]));
}
for (int i = 2; i < numElements; ++i)
{
byte[] nextBytes = encodeValue(digits[i]);
outBytes.write(nextBytes, 0, nextBytes.length);
}
return outBytes.toByteArray();
}
private byte[] encodeValue(long v)
{
// see how many bytes are needed: each value uses just
// 7 bits of each byte, with high-order bit functioning as
// a continuation marker
int numBytes = 0;
long temp = v;
do
{
++numBytes;
temp = (long)Math.floor(temp / 128);
}
while (temp > 0);
byte[] enc = new byte[numBytes];
// encode lowest-order byte, without setting high bit
enc[numBytes-1] = (byte)(v % 128);
v = (long)Math.floor(v / 128);
//.encode other bytes with high bit set
for (int i = numBytes-2; i >= 0; --i)
{
enc[i] = (byte)((v % 128) + 128);
v = (long)Math.floor(v / 128);
}
return enc;
}
private void convertDigitString(String digitString)
throws SNMPBadValueException
{
try
{
StringTokenizer st = new StringTokenizer(digitString, " .");
int size = 0;
while (st.hasMoreTokens())
{
// figure out how many values are in string
size++;
st.nextToken();
}
long[] returnDigits = new long[size];
st = new StringTokenizer(digitString, " .");
for (int i = 0; i < size; i++)
{
returnDigits[i] = Long.parseLong(st.nextToken());
if (returnDigits[i] < 0)
throw new SNMPBadValueException(" Object Identifier: bad string supplied to set value ");
}
digits = returnDigits;
}
catch (NumberFormatException e)
{
throw new SNMPBadValueException(" Object Identifier: bad string supplied for object identifier value ");
}
}
private void extractFromBEREncoding(byte[] enc)
throws SNMPBadValueException
{
// note: masks must be ints; byte internal representation issue(?)
int bitTest = 0x80; // test for leading 1
int highBitMask = 0x7F; // mask out high bit for value
// first, compute number of "digits";
// will just be number of bytes with leading 0's
int numInts = 0;
for (int i = 0; i < enc.length; i++)
{
if ((enc[i] & bitTest) == 0) //high-order bit not set; count
numInts++;
}
if (numInts > 0)
{
// create new int array to hold digits; since first value is 40*x + y,
// need one extra entry in array to hold this.
digits = new long[numInts + 1];
int currentByte = -1; // will be incremented to 0
long value = 0;
// read in values 'til get leading 0 in byte
do
{
currentByte++;
value = value*128 + (enc[currentByte] & highBitMask);
}
while ((enc[currentByte] & bitTest) > 0); // implies high bit set!
// now handle 40a + b
digits[0] = (long)Math.floor(value / 40);
digits[1] = value % 40;
// now read in rest!
for (int i = 2; i < numInts + 1; i++)
{
// read in values 'til get leading 0 in byte
value = 0;
do
{
currentByte++;
value = value*128 + (enc[currentByte] & highBitMask);
}
while ((enc[currentByte] & bitTest) > 0);
digits[i] = value;
}
}
else
{
// no digits; create empty digit array
digits = new long[0];
}
}
/*
public boolean equals(SNMPObjectIdentifier other)
{
long[] otherDigits = (long[])(other.getValue());
boolean areEqual = true;
if (digits.length != otherDigits.length)
{
areEqual = false;
}
else
{
for (int i = 0; i < digits.length; i++)
{
if (digits[i] != otherDigits[i])
{
areEqual = false;
break;
}
}
}
return areEqual;
}
*/
/**
* Checks the internal arrays for equality.
*/
public boolean equals(Object other)
{
// false if other is null
if (other == null)
{
return false;
}
// check first to see that they're both of the same class
if (!this.getClass().equals(other.getClass()))
{
return false;
}
SNMPObjectIdentifier otherSNMPObject = (SNMPObjectIdentifier)other;
// see if their embedded arrays are equal
if (java.util.Arrays.equals((long[])this.getValue(),(long[])otherSNMPObject.getValue()))
{
return true;
}
else
{
return false;
}
}
/**
* Generates a hash value so SNMP Object Identifiers can be used in Hashtables.
*/
public int hashCode()
{
int hash = 0;
// generate a hashcode from the embedded array
for (int i = 0; i < digits.length; i++)
{
hash += (int)(digits[i] ^ (digits[i] >> 32));
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
/**
* Return dot-separated sequence of decimal values.
*/
public String toString()
{
StringBuffer valueStringBuffer = new StringBuffer();
if (digits.length > 0)
{
valueStringBuffer.append(digits[0]);
for (int i = 1; i < digits.length; ++i)
{
valueStringBuffer.append(".");
valueStringBuffer.append(digits[i]);
}
}
return valueStringBuffer.toString();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -