/* * * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ // Copyright (c) 1995-96 by Cisco Systems, Inc. package com.sun.jmx.snmp; // java imports // import java.util.StringTokenizer; import java.util.NoSuchElementException; // sun imports import sun.misc.JavaAWTAccess; import sun.misc.SharedSecrets; /** * Represents an SNMP Object Identifier (OID). * *
This API is a Sun Microsystems internal API and is subject * to change without notice.
*/ public class SnmpOid extends SnmpValue { // CONSTRUCTORS //------------- /** * Constructs a newSnmpOid
with no components.
*/
public SnmpOid() {
components = new long[15] ;
componentCount = 0 ;
}
/**
* Constructs a new SnmpOid
from the specified component array.
* @param oidComponents The initialization component array.
*/
public SnmpOid(long[] oidComponents) {
components = oidComponents.clone() ;
componentCount = components.length ;
}
/**
* Constructs a new SnmpOid
containing one component with the
* specified value.
* @param id The initialization component value.
*/
public SnmpOid(long id) {
components = new long[1] ;
components[0] = id ;
componentCount = components.length ;
}
/**
* Constructs a new SnmpOid
containing four components
* with the specified values.
* @param id1 The first component value.
* @param id2 The second component values.
* @param id3 The third component values.
* @param id4 The fourth component values.
*/
public SnmpOid(long id1, long id2, long id3, long id4) {
components = new long[4] ;
components[0] = id1 ;
components[1] = id2 ;
components[2] = id3 ;
components[3] = id4 ;
componentCount = components.length ;
}
/**
* Constructs a new SnmpOid
from a dot-formatted String
or a MIB variable
* name. It generates an exception if the variable name cannot be resolved, or
* if the dot-formatted String
has an invalid subidentifier.
* This constructor helps build an OID object with a String
like .1.2.3.4 or 1.2.3.4
* or ifInOctets
or ifInOctets
.0.
* @param s String
or MIB variable of the form .1.2.3 or 1.2.3 or ifInOctets
.
* @exception IllegalArgumentException The subidentifier is neither a numeric String
* nor a String
of the MIB database.
*/
public SnmpOid(String s) throws IllegalArgumentException {
String dotString = s ;
if (s.startsWith(".") == false) {
try {
dotString = resolveVarName(s);
} catch(SnmpStatusException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
StringTokenizer st = new StringTokenizer(dotString, ".", false) ;
componentCount= st.countTokens();
// Now extract the ids
//
if (componentCount == 0) {
components = new long[15] ;
} else {
components = new long[componentCount] ;
try {
for (int i = 0 ; i < componentCount ; i++) {
try {
components[i] = Long.parseLong(st.nextToken()) ;
}
catch(NoSuchElementException e) {}
}
}
catch(NumberFormatException e) {
throw new IllegalArgumentException(s) ;
}
}
}
// PUBLIC METHODS
//---------------
/**
* Gets the number of components in this OID.
* @return The number of components.
*/
public int getLength() {
return componentCount ;
}
/**
* Returns a copy of the components array of this SnmpOid
.
* @return The copy of the components array.
*/
public long[] longValue() {
long[] result = new long[componentCount] ;
System.arraycopy(components,0,result,0,componentCount);
return result ;
}
/**
* Returns the components array of this SnmpOid
.
* If duplicate
is true, a copy is returned.
* Otherwise, a reference to the internal array is returned,
* in which case the caller shall not modify this array.
* This method is provided to optimize processing in those cases
* where the caller needs only to read the components array.
*
* @param duplicate Indicates whether a copy or a reference must
* be returned:
* true
if a copy must be returned,false
if a reference on the internal data
* can be returned.components
array. The first element is at
* position 0
.
*
* @param pos The position at which the OID arc should be peeked.
*
* @return The OID arc found at the requested position.
*
* @exception SnmpStatusException No OID arc was found at the requested
* position.
*/
public final long getOidArc(int pos) throws SnmpStatusException {
try {
return components[pos];
} catch(Exception e) {
throw new SnmpStatusException(SnmpStatusException.noAccess);
}
}
/**
* Converts the OID value to its Long
form.
* @return The Long
representation of the value.
*/
public Long toLong() {
if (componentCount != 1) {
throw new IllegalArgumentException() ;
}
return new Long(components[0]) ;
}
/**
* Converts the OID value to its Integer
form.
* @return The Integer
representation of the value.
*/
public Integer toInteger() {
if ((componentCount != 1) || (components[0] > Integer.MAX_VALUE)) {
throw new IllegalArgumentException() ;
}
return new Integer((int)components[0]) ;
}
/**
* Converts the OID value to its String
form.
* @return The String
representation of the value.
*/
public String toString() {
String result = "" ;
if (componentCount >= 1) {
for (int i = 0 ; i < componentCount - 1 ; i++) {
result = result + components[i] + "." ;
}
result = result + components[componentCount - 1] ;
}
return result ;
}
/**
* Converts the OID value to its Boolean
form.
* @return The Boolean
representation of the value.
*/
public Boolean toBoolean() {
if ((componentCount != 1) && (components[0] != 1) && (components[0] != 2)) {
throw new IllegalArgumentException() ;
}
return Boolean.valueOf(components[0] == 1) ;
}
/**
* Converts the OID value to its array of Bytes
form.
* @return The array of Bytes
representation of the value.
*/
public Byte[] toByte() {
Byte[] result = new Byte[componentCount] ;
for (int i =0 ; i < componentCount ; i++) {
if (components[0] > 255) {
throw new IllegalArgumentException() ;
}
result[i] = new Byte((byte)components[i]) ;
}
return result ;
}
/**
* Converts the OID value to its SnmpOid
form.
* @return The OID representation of the value.
*/
public SnmpOid toOid() {
long[] ids = new long[componentCount] ;
for (int i = 0 ; i < componentCount ; i++) {
ids[i] = components[i] ;
}
return new SnmpOid(ids) ;
}
/**
* Extracts the OID from an index OID and returns its
* value converted as an SnmpOid
.
* @param index The index array.
* @param start The position in the index array.
* @return The OID representing the OID value.
* @exception SnmpStatusException There is no OID value
* available at the start position.
*/
public static SnmpOid toOid(long[] index, int start) throws SnmpStatusException {
try {
if (index[start] > Integer.MAX_VALUE) {
throw new SnmpStatusException(SnmpStatusException.noSuchName) ;
}
int idCount = (int)index[start++] ;
long[] ids = new long[idCount] ;
for (int i = 0 ; i < idCount ; i++) {
ids[i] = index[start + i] ;
}
return new SnmpOid(ids) ;
}
catch(IndexOutOfBoundsException e) {
throw new SnmpStatusException(SnmpStatusException.noSuchName) ;
}
}
/**
* Scans an index OID, skips the OID value and returns the position
* of the next value.
* @param index The index array.
* @param start The position in the index array.
* @return The position of the next value.
* @exception SnmpStatusException There is no OID value
* available at the start position.
*/
public static int nextOid(long[] index, int start) throws SnmpStatusException {
try {
if (index[start] > Integer.MAX_VALUE) {
throw new SnmpStatusException(SnmpStatusException.noSuchName) ;
}
int idCount = (int)index[start++] ;
start += idCount ;
if (start <= index.length) {
return start ;
}
else {
throw new SnmpStatusException(SnmpStatusException.noSuchName) ;
}
}
catch(IndexOutOfBoundsException e) {
throw new SnmpStatusException(SnmpStatusException.noSuchName) ;
}
}
/**
* Appends an SnmpOid
representing an SnmpOid
to another OID.
* @param source An OID representing an SnmpOid
value.
* @param dest Where source should be appended.
*/
public static void appendToOid(SnmpOid source, SnmpOid dest) {
dest.append(source.getLength()) ;
dest.append(source) ;
}
/**
* Performs a clone action. This provides a workaround for the
* SnmpValue
interface.
* @return The SnmpValue clone.
*/
final synchronized public SnmpValue duplicate() {
return (SnmpValue)clone() ;
}
/**
* Clones the SnmpOid
object, making a copy of its data.
* @return The object clone.
*/
public Object clone() {
try {
SnmpOid obj = (SnmpOid)super.clone() ;
obj.components = new long[this.componentCount] ;
System.arraycopy(this.components, 0, obj.components, 0,
this.componentCount) ;
return obj ;
} catch (CloneNotSupportedException e) {
throw new InternalError() ; // should never happen. VM bug.
}
}
/**
* Inserts a subid at the beginning of this SnmpOid
.
* @param id The long subid to insert.
*/
public void insert(long id) {
enlargeIfNeeded(1) ;
for (int i = componentCount - 1 ; i >= 0 ; i--) {
components[i + 1] = components[i] ;
}
components[0] = id ;
componentCount++ ;
}
/**
* Inserts a subid at the beginning of this SnmpOid
.
* @param id The integer subid to insert.
*/
public void insert(int id) {
insert((long)id) ;
}
/**
* Appends the specified SnmpOid
to the end of this SnmpOid
.
* @param oid The OID to append.
*/
public void append(SnmpOid oid) {
enlargeIfNeeded(oid.componentCount) ;
for (int i = 0 ; i < oid.componentCount ; i++) {
components[componentCount + i] = oid.components[i] ;
}
componentCount += oid.componentCount ;
}
/**
* Appends the specified long to the end of this SnmpOid
.
* @param id The long to append.
*/
public void append(long id) {
enlargeIfNeeded(1) ;
components[componentCount] = id ;
componentCount++ ;
}
/**
* Adds the specified dot-formatted OID String
to the end of this SnmpOid
.
* The subidentifiers can be expressed as a dot-formatted String
or a
* MIB variable name.
* @param s Variable name of the form .1.2.3 or 1.2.3 or
* ifInOctets
.
* @exception SnmpStatusException An error occurred while accessing a MIB node.
*/
public void addToOid(String s) throws SnmpStatusException {
SnmpOid suffix= new SnmpOid(s);
this.append(suffix);
}
/**
* Adds the specified array of longs to the end of this SnmpOid
.
* @param oid An array of longs.
* @exception SnmpStatusException An error occurred while accessing a MIB node.
*/
public void addToOid(long []oid) throws SnmpStatusException {
SnmpOid suffix= new SnmpOid(oid);
this.append(suffix);
}
/**
* Checks the validity of the OID.
* @return true
if the OID is valid, false
otherwise.
*/
public boolean isValid() {
return ((componentCount >= 2) &&
((0 <= components[0]) && (components[0] < 3)) &&
((0 <= components[1]) && (components[1] < 40))) ;
}
/**
* Checks whether the specified Object
is equal to this SnmpOid
.
* @param o The Object
to be compared.
* @return true
if o
is an SnmpOid
instance and equal to this, false
otherwise.
*/
public boolean equals(Object o) {
boolean result = false ;
if (o instanceof SnmpOid) {
SnmpOid oid = (SnmpOid)o ;
if (oid.componentCount == componentCount) {
int i = 0 ;
long[] objoid = oid.components;
while ((i < componentCount) && (components[i] == objoid[i]))
i++ ;
result = (i == componentCount) ;
}
}
return result ;
}
/**
* The hashCode is computed from the OID components.
* @return a hashCode for this SnmpOid.
**/
public int hashCode() {
long acc=0;
for (int i=0;iSnmpOid
.
* A value smaller than 0 if this SnmpOid
is lexicographically smaller than other
.
* A value larger than 0 if this SnmpOid
is lexicographically larger than other
.
*/
public int compareTo(SnmpOid other) {
int result = 0 ;
int i = 0 ;
int cmplen = Math.min(componentCount, other.componentCount) ;
long[] otheroid = other.components;
for (i = 0; i < cmplen; i++) {
if (components[i] != otheroid[i]) {
break ;
}
}
if ((i == componentCount) && (i == other.componentCount)) {
result = 0 ;
}
else if (i == componentCount) {
result = -1 ;
}
else if (i == other.componentCount) {
result = 1 ;
}
else {
result = (components[i] < otheroid[i]) ? -1 : 1 ;
}
return result ;
}
/**
* Resolves a MIB variable String
with the MIB database.
* @param s The variable name to resolve.
* @exception SnmpStatusException If the variable is not found in the MIB database.
*/
public String resolveVarName(String s) throws SnmpStatusException {
int index = s.indexOf('.') ;
// First handle the case where oid is expressed as 1.2.3.4
//
try {
return handleLong(s, index);
} catch(NumberFormatException e) {}
SnmpOidTable table = getSnmpOidTable();
// if we are here, it means we have something to resolve..
//
if (table == null)
throw new SnmpStatusException(SnmpStatusException.noSuchName);
// Ok assume there is a variable name to resolve ...
//
if (index <= 0) {
SnmpOidRecord rec = table.resolveVarName(s);
return rec.getOid();
} else {
SnmpOidRecord rec = table.resolveVarName(s.substring(0, index));
return (rec.getOid()+ s.substring(index));
}
}
/**
* Returns a textual description of the type object.
* @return ASN.1 textual description.
*/
public String getTypeName() {
return name ;
}
/**
* Returns the MIB table used for resolving MIB variable names.
* @return The MIB table.
*/
public static SnmpOidTable getSnmpOidTable() {
JavaAWTAccess awtAccess = SharedSecrets.getJavaAWTAccess();
if (awtAccess == null) {
return meta;
} else {
return (SnmpOidTable) awtAccess.get(SnmpOidTable.class);
}
}
/**
* Sets the MIB table to use for resolving MIB variable names.
* If no mib table is available, the class will not be able to resolve
* names contained in the Object Identifier.
* @param db The MIB table to use.
*/
public static void setSnmpOidTable(SnmpOidTable db) {
JavaAWTAccess awtAccess = SharedSecrets.getJavaAWTAccess();
if (awtAccess == null) {
meta = db;
} else {
if (db == null) {
awtAccess.remove(SnmpOidTable.class);
} else {
awtAccess.put(SnmpOidTable.class, db);
}
}
}
/**
* Converts an OID index converted string back to a DisplayString
*
**/
public String toOctetString() {
return new String(tobyte()) ;
}
// PRIVATE METHODS
//------------------
/**
* convert the components array into a byte array
**/
private byte[] tobyte() {
byte[] result = new byte[componentCount] ;
for (int i =0 ; i < componentCount ; i++) {
if (components[0] > 255) {
throw new IllegalArgumentException() ;
}
result[i] = (byte)components[i] ;
}
return result ;
}
/**
* Checks if there is enough space in the components
* array to insert n new subids. If not, it increases the size of
* the array.
* In fact it reallocates a new array and copy the old one into the new one.
* @param n The number of subids to insert.
*/
private void enlargeIfNeeded(int n) {
int neededSize = components.length ;
while (componentCount + n > neededSize) {
neededSize = neededSize * 2 ;
}
if (neededSize > components.length) {
long[] newComponents = new long[neededSize] ;
for (int i = 0 ; i < components.length ; i++) {
newComponents[i] = components[i] ;
}
components = newComponents ;
}
}
// PRIVATE METHODS
//----------------
private String handleLong(String oid, int index) throws NumberFormatException, SnmpStatusException {
String str;
if (index >0) {
str= oid.substring(0, index);
} else {
str= oid ;
}
// just parse the element.
//
Long.parseLong(str);
return oid;
}
// VARIABLES
//----------
/**
* The components' array.
* @serial
*/
protected long components[] = null ;
/**
* The length of the components' array.
* @serial
*/
protected int componentCount = 0 ;
/**
* The name of the type.
*/
final static String name = "Object Identifier";
/**
* Reference to a mib table. If no mib table is available,
* the class will not be able to resolve names contained in the Object Identifier.
*/
private static SnmpOidTable meta= null;
/**
* Ensure serialization compatibility with version 4.1 FCS
*
*/
static final long serialVersionUID = 8956237235607885096L;
}