- /*
- * @(#)file SnmpOid.java
- * @(#)author Sun Microsystems, Inc.
- * @(#)version 4.22
- * @(#)date 04/09/15
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN 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;
-
- /**
- * Represents an SNMP Object Identifier (OID).
- *
- * <p><b>This API is a Sun Microsystems internal API and is subject
- * to change without notice.</b></p>
- * @version 4.22 12/19/03
- * @author Sun Microsystems, Inc
- * @author Cisco Systems, Inc.
- */
-
- public class SnmpOid extends SnmpValue {
-
- // CONSTRUCTORS
- //-------------
- /**
- * Constructs a new <CODE>SnmpOid</CODE> with no components.
- */
- public SnmpOid() {
- components = new long[15] ;
- componentCount = 0 ;
- }
-
- /**
- * Constructs a new <CODE>SnmpOid</CODE> from the specified component array.
- * @param oidComponents The initialization component array.
- */
- public SnmpOid(long[] oidComponents) {
- components = (long[])oidComponents.clone() ;
- componentCount = components.length ;
- }
-
- /**
- * Constructs a new <CODE>SnmpOid</CODE> 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 <CODE>SnmpOid</CODE> 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 <CODE>SnmpOid</CODE> from a dot-formatted <CODE>String</CODE> or a MIB variable
- * name. It generates an exception if the variable name cannot be resolved, or
- * if the dot-formatted <CODE>String</CODE> has an invalid subidentifier.
- * This constructor helps build an OID object with a <CODE>String</CODE> like .1.2.3.4 or 1.2.3.4
- * or <CODE>ifInOctets</CODE> or <CODE>ifInOctets</CODE>.0.
- * @param s <CODE>String</CODE> or MIB variable of the form .1.2.3 or 1.2.3 or <CODE>ifInOctets</CODE>.
- * @exception IllegalArgumentException The subidentifier is neither a numeric <CODE>String</CODE>
- * nor a <CODE>String</CODE> 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 <CODE>SnmpOid</CODE>.
- * @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 <CODE>SnmpOid</CODE>.
- * If <code>duplicate</code> is true, a copy is returned.
- * Otherwise, a reference to the internal array is returned,
- * in which case the caller <b>shall not</b> 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:
- * <li><code>true</code> if a copy must be returned,</li>
- * <li><code>false</code> if a reference on the internal data
- * can be returned.</li>
- * @return A copy of (or a reference on) the components array.
- */
- public final long[] longValue(boolean duplicate) {
- if (duplicate) return longValue();
- if (componentCount == components.length) return components ;
- components = longValue();
- componentCount = components.length;
- return components ;
- }
-
- /**
- * Returns the value of the OID arc found at the requested position
- * in the <CODE>components</CODE> array. The first element is at
- * position <code>0</code>.
- *
- * @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 <CODE>Long</CODE> form.
- * @return The <CODE>Long</CODE> representation of the value.
- */
- public Long toLong() {
- if (componentCount != 1) {
- throw new IllegalArgumentException() ;
- }
- return new Long(components[0]) ;
- }
-
- /**
- * Converts the OID value to its <CODE>Integer</CODE> form.
- * @return The <CODE>Integer</CODE> 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 <CODE>String</CODE> form.
- * @return The <CODE>String</CODE> 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 <CODE>Boolean</CODE> form.
- * @return The <CODE>Boolean</CODE> representation of the value.
- */
- public Boolean toBoolean() {
- if ((componentCount != 1) && (components[0] != 1) && (components[0] != 2)) {
- throw new IllegalArgumentException() ;
- }
- return new Boolean(components[0] == 1) ;
- }
-
- /**
- * Converts the OID value to its array of <CODE>Bytes</CODE> form.
- * @return The array of <CODE>Bytes</CODE> 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 <CODE>SnmpOid</CODE> 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 <CODE>SnmpOid</CODE>.
- * @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 <CODE>SnmpOid</CODE> representing an <CODE>SnmpOid</CODE> to another OID.
- * @param source An OID representing an <CODE>SnmpOid</CODE> 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
- * <CODE>SnmpValue</CODE> interface.
- * @return The SnmpValue clone.
- */
- final synchronized public SnmpValue duplicate() {
- return (SnmpValue)clone() ;
- }
-
- /**
- * Clones the <CODE>SnmpOid</CODE> 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 <CODE>SnmpOid</CODE>.
- * @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 <CODE>SnmpOid</CODE>.
- * @param id The integer subid to insert.
- */
- public void insert(int id) {
- insert((long)id) ;
- }
-
- /**
- * Appends the specified <CODE>SnmpOid</CODE> to the end of this <CODE>SnmpOid</CODE>.
- * @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 <CODE>SnmpOid</CODE>.
- * @param id The long to append.
- */
- public void append(long id) {
- enlargeIfNeeded(1) ;
- components[componentCount] = id ;
- componentCount++ ;
- }
-
- /**
- * Adds the specified dot-formatted OID <CODE>String</CODE> to the end of this <CODE>SnmpOid</CODE>.
- * The subidentifiers can be expressed as a dot-formatted <CODE>String</CODE> or a
- * MIB variable name.
- * @param s Variable name of the form .1.2.3 or 1.2.3 or
- * <CODE>ifInOctets</CODE>.
- * @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 <CODE>SnmpOid</CODE>.
- * @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 <CODE>true</CODE> if the OID is valid, <CODE>false</CODE> otherwise.
- */
- public boolean isValid() {
- return ((componentCount >= 2) &&
- ((0 <= components[0]) && (components[0] < 3)) &&
- ((0 <= components[1]) && (components[1] < 40))) ;
- }
-
- /**
- * Checks whether the specified <CODE>Object</CODE> is equal to this <CODE>SnmpOid</CODE>.
- * @param o The <CODE>Object</CODE> to be compared.
- * @return <CODE>true</CODE> if <CODE>o</CODE> is an <CODE>SnmpOid</CODE> instance and equal to this, <CODE>false</CODE> 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;i<componentCount;i++) {
- acc = acc*31+components[i];
- }
- return (int)acc;
- }
-
- /**
- * Compares two OIDs lexicographically.
- * @param other The OID to be compared.
- * @return
- * The value 0 if the parameter <CODE>other</CODE> is equal to this <CODE>SnmpOid</CODE>.
- * A value smaller than 0 if this <CODE>SnmpOid</CODE> is lexicographically smaller than <CODE>other</CODE>.
- * A value larger than 0 if this <CODE>SnmpOid</CODE> is lexicographically larger than <CODE>other</CODE>.
- */
- 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 <CODE>String</CODE> 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) {}
-
- // if we are here, it means we have something to resolve..
- //
- if (meta == null)
- throw new SnmpStatusException(SnmpStatusException.noSuchName);
-
- // Ok assume there is a variable name to resolve ...
- //
- if (index <= 0) {
- SnmpOidRecord rec = meta.resolveVarName(s);
- return rec.getOid();
-
- } else {
- SnmpOidRecord rec = meta.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() {
- return meta;
- }
-
- /**
- * 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) {
- meta = 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;
- }