KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > snmp4j > smi > OID


1 /*_############################################################################
2   _##
3   _## SNMP4J - OID.java
4   _##
5   _## Copyright 2003-2007 Frank Fock and Jochen Katz (SNMP4J.org)
6   _##
7   _## Licensed under the Apache License, Version 2.0 (the "License");
8   _## you may not use this file except in compliance with the License.
9   _## You may obtain a copy of the License at
10   _##
11   _## http://www.apache.org/licenses/LICENSE-2.0
12   _##
13   _## Unless required by applicable law or agreed to in writing, software
14   _## distributed under the License is distributed on an "AS IS" BASIS,
15   _## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   _## See the License for the specific language governing permissions and
17   _## limitations under the License.
18   _##
19   _##########################################################################*/

20
21
22
23
24
25 package org.snmp4j.smi;
26
27 import java.io.*;
28 import java.util.*;
29 import org.snmp4j.asn1.BER;
30 import org.snmp4j.asn1.BERInputStream;
31
32 /**
33  * The Object Identifier Class.
34  *
35  * The Object Identifier (OID) class is the encapsulation of an
36  * SMI object identifier. The SMI object is a data identifier for a
37  * data element found in a Management Information Base (MIB), as
38  * defined by a MIB definition. The <code>OID</code> class allows definition and
39  * manipulation of object identifiers.
40  *
41  * @author Frank Fock
42  * @version 1.7
43  */

44 public class OID extends AbstractVariable implements AssignableFromString {
45
46   private static final long serialVersionUID = 7521667239352941172L;
47
48   public static final int MAX_OID_LEN = 128;
49   public static final int MAX_SUBID_VALUE = 0xFFFFFFFF;
50
51   private int[] value = new int[0];
52
53   /**
54    * Constructs a zero length OID.
55    */

56   public OID() {
57   }
58
59   /**
60    * Constructs an <code>OID</code> from a dotted String.
61    * @param oid
62    * a dotted OID String, for example "1.3.6.1.2.2.1.0"
63    */

64   public OID(String JavaDoc oid) {
65     value = parseDottedString(oid);
66   }
67
68   /**
69    * Constructs an <code>OID</code> from an array of integer values.
70    * @param rawOID
71    * an array of <code>int</code> values. The array
72    * is copied. Later changes to <code>rawOID</code> will therefore not
73    * affect the OID's value.
74    */

75   public OID(int[] rawOID) {
76     this(rawOID, 0, rawOID.length);
77   }
78
79   /**
80    * Constructs an <code>OID</code> from two arrays of integer values where
81    * the first represents the OID prefix (i.e., the object class ID) and
82    * the second one represents the OID suffix (i.e., the instance identifier).
83    * @param prefixOID
84    * an array of <code>int</code> values. The array
85    * is copied. Later changes to <code>prefixOID</code> will therefore not
86    * affect the OID's value.
87    * @param suffixOID
88    * an array of <code>int</code> values which will be appended to the
89    * <code>prefixOID</code> OID. The array is copied. Later changes to
90    * <code>suffixOID</code> will therefore not affect the OID's value.
91    * @since 1.8
92    */

93   public OID(int[] prefixOID, int[] suffixOID) {
94     this.value = new int[prefixOID.length+suffixOID.length];
95     System.arraycopy(prefixOID, 0, value, 0, prefixOID.length);
96     System.arraycopy(suffixOID, 0, value, prefixOID.length, suffixOID.length);
97   }
98
99   /**
100    * Constructs an <code>OID</code> from an array of integer values.
101    * @param rawOID
102    * an array of <code>int</code> values. The array
103    * is copied. Later changes to <code>rawOID</code> will therefore not
104    * affect the OID's value.
105    * @param offset
106    * the zero based offset into the <code>rawOID</code> that points to the
107    * first sub-identifier of the new OID.
108    * @param length
109    * the length of the new OID, where <code>offset + length</code> must be
110    * less or equal the length of <code>rawOID</code>. Otherwise an
111    * <code>IndexOutOfBoundsException</code> is thrown.
112    */

113   public OID(int[] rawOID, int offset, int length) {
114     setValue(rawOID, offset, length);
115   }
116
117   /**
118    * Copy constructor.
119    * @param other OID
120    */

121   public OID(OID other) {
122     this(other.getValue());
123   }
124
125   private static int[] parseDottedString(String JavaDoc oid) {
126     StringTokenizer st = new StringTokenizer(oid, ".");
127     int size = st.countTokens();
128     int[] value = new int[size];
129     size = 0;
130     while (st.hasMoreTokens()) {
131       value[size++] = (int)Long.parseLong(st.nextToken());
132     }
133     return value;
134   }
135
136
137   public final int getSyntax() {
138     return SMIConstants.SYNTAX_OBJECT_IDENTIFIER;
139   }
140
141   public int hashCode() {
142     int hash = 0;
143     for (int i=0; i<value.length; i++) {
144       hash += value[i]*31^((value.length-1)-i);
145     }
146     return hash;
147   }
148
149   public final boolean equals(Object JavaDoc o) {
150     if (o instanceof OID) {
151       OID other = (OID)o;
152       if (other.value.length != value.length) {
153         return false;
154       }
155       for (int i=0; i<value.length; i++) {
156         if (value[i] != other.value[i]) {
157           return false;
158         }
159       }
160       return true;
161     }
162     return false;
163   }
164
165   /**
166    * Returns a copy of this OID where sub-identifiers have been set to zero
167    * for all n-th sub-identifier where the n-th bit of mask is zero.
168    * @param mask
169    * a mask where the n-th bit corresponds to the n-th sub-identifier.
170    * @return
171    * the masked OID.
172    * @since 1.5
173    */

174   public OID mask(OctetString mask) {
175     int[] masked = new int[value.length];
176     System.arraycopy(value, 0, masked, 0, value.length);
177     for (int i=0; (i<mask.length()*8) && (i<masked.length); i++) {
178       byte b = (byte) (0x80 >> (i%8));
179       if ((mask.get(i/8) & b) == 0) {
180         masked[i] = 0;
181       }
182     }
183     return new OID(masked);
184   }
185
186   public final int compareTo(Object JavaDoc o) {
187     if (o instanceof OID) {
188       OID other = (OID)o;
189       int min = Math.min(value.length, other.value.length);
190       int result = leftMostCompare(min, other);
191       if (result == 0) {
192         return (value.length - other.value.length);
193       }
194       return result;
195     }
196     throw new ClassCastException JavaDoc(o.getClass().getName());
197   }
198
199   public String JavaDoc toString() {
200     StringBuffer JavaDoc buf = new StringBuffer JavaDoc(10*value.length);
201     for (int i=0; i<value.length; i++) {
202       if (i != 0) {
203         buf.append('.');
204       }
205       buf.append((value[i] & 0xFFFFFFFFL));
206     }
207     return buf.toString();
208   }
209
210   /**
211    * Returns the content of the as a byte array. This method can be used
212    * to convert an index value to an <code>OctetString</code> or
213    * <code>IpAddress</code> instance.
214    *
215    * @return
216    * the sub-identifies of this <code>OID</code> as a byte array. Each
217    * sub-identifier value is masked with 0xFF to form a byte value.
218    * @since 1.2
219    */

220   public byte[] toByteArray() {
221     byte[] b = new byte[value.length];
222     for (int i=0; i<value.length; i++) {
223       b[i] = (byte) (value[i] & 0xFF);
224     }
225     return b;
226   }
227
228   public void encodeBER(OutputStream outputStream) throws java.io.IOException JavaDoc {
229     BER.encodeOID(outputStream, BER.OID, value);
230   }
231
232   public int getBERLength() {
233     int length = 1; // for first 2 subids
234

235     for (int i = 2; i < value.length; i++)
236     {
237       long v = value[i] & 0xFFFFFFFFL;
238
239       if (v < 0x80) { // 7 bits long subid
240
length += 1;
241       }
242       else if (v < 0x4000) { // 14 bits long subid
243
length += 2;
244       }
245       else if (v < 0x200000) { // 21 bits long subid
246
length += 3;
247       }
248       else if (v < 0x10000000) { // 28 bits long subid
249
length += 4;
250       }
251       else { // 32 bits long subid
252
length += 5;
253       }
254     }
255     return length + BER.getBERLengthOfLength(length) + 1;
256   }
257
258   public void decodeBER(BERInputStream inputStream) throws java.io.IOException JavaDoc {
259     BER.MutableByte type = new BER.MutableByte();
260     int[] v = BER.decodeOID(inputStream, type);
261     if (type.getValue() != BER.OID) {
262       throw new IOException("Wrong type encountered when decoding OID: "+
263                             type.getValue());
264     }
265     setValue(v);
266   }
267
268   public void setValue(String JavaDoc value) {
269     this.value = parseDottedString(value);
270   }
271
272   /**
273    * Sets the value from an array of integer values.
274    *
275    * @param value
276    * The new value
277    * @throws IllegalArgumentException
278    * if value == null.
279    */

280   public final void setValue(int[] value) {
281     if (value == null) {
282       throw new IllegalArgumentException JavaDoc("OID value must not be set to null");
283     }
284     this.value = value;
285   }
286
287   private void setValue(int[] rawOID, int offset, int length) {
288     value = new int[length];
289     System.arraycopy(rawOID, offset, value, 0, length);
290   }
291
292   /**
293    * Gets all sub-identifiers as an int array.
294    *
295    * @return int arry of all sub-identifiers
296    */

297   public final int[] getValue() {
298     return value;
299   }
300
301   /**
302    * Gets the sub-identifier value at the specified position.
303    * @param index
304    * a zero-based index into the <code>OID</code>.
305    * @throws ArrayIndexOutOfBoundsException
306    * if the index is out of range (index < 0 || index >= size()).
307    * @return
308    * the sub-indentifier value at <code>index</code>. NOTE: The returned
309    * value may be negative if the sub-identifier value is greater than
310    * <code>2^31</code>.
311    */

312   public final int get(int index) {
313     return value[index];
314   }
315
316   /**
317    * Gets the unsigned sub-identifier value at the specified position.
318    * @param index int
319    * @return
320    * the sub-indentifier value at <code>index</code> as an unsigned long
321    * value.
322    */

323   public final long getUnsigned(int index) {
324     return value[index] & 0xFFFFFFFFL;
325   }
326
327   /**
328    * Sets the sub-identifier at the specified position.
329    * @param index
330    * a zero-based index into the <code>OID</code>.
331    * @param value
332    * a 32bit unsigned integer value.
333    * @throws ArrayIndexOutOfBoundsException
334    * if the index is out of range (index < 0 || index >= size()).
335    */

336   public final void set(int index, int value) {
337     this.value[index] = value;
338   }
339
340   /**
341    * Appends a dotted String OID to this <code>OID</code>.
342    * @param oid
343    * a dotted String with numerical sub-identifiers.
344    */

345   public final void append(String JavaDoc oid) {
346     OID suffix = new OID(oid);
347     append(suffix);
348   }
349
350   /**
351    * Appends an <code>OID</code> to this OID.
352    * @param oid
353    * an <code>OID</code> instance.
354    */

355   public final void append(OID oid) {
356     int[] newValue = new int[value.length+oid.value.length];
357     System.arraycopy(value, 0, newValue, 0, value.length);
358     System.arraycopy(oid.value, 0, newValue, value.length, oid.value.length);
359     value = newValue;
360   }
361
362   /**
363    * Appends a sub-identifier to this OID.
364    * @param subID
365    * an integer value.
366    */

367   public final void append(int subID) {
368     int[] newValue = new int[value.length+1];
369     System.arraycopy(value, 0, newValue, 0, value.length);
370     newValue[value.length] = subID;
371     value = newValue;
372   }
373
374   /**
375    * Appends an unsigned long sub-identifier value to this OID.
376    * @param subID
377    * an unsigned long value less or equal to 2^32-1.
378    * @since 1.2
379    */

380   public final void appendUnsigned(long subID) {
381     append((int)(subID & 0xFFFFFFFFL));
382   }
383
384   /**
385    * Checks whether this <code>OID</code> can be BER encoded.
386    * @return
387    * <code>true</code> if size() >= 2 and size() <= 128 and if the first
388    * two sub-identifiers are less than 3 and 40 respectively.
389    */

390   public boolean isValid() {
391     return ((size() >= 2) && (size() <= 128) &&
392             ((value[0] & 0xFFFFFFFFL) <= 2l) &&
393             ((value[1] & 0xFFFFFFFFL) < 40l));
394   }
395
396   /**
397    * Returns the number of sub-identifiers in this <code>OID</code>.
398    * @return
399    * an integer value between 0 and 128.
400    */

401   public final int size() {
402     return value.length;
403   }
404
405   /**
406    * Compares the n leftmost sub-identifiers with the given <code>OID</code>
407    * in left-to-right direction.
408    * @param n
409    * the number of sub-identifiers to compare.
410    * @param other
411    * an <code>OID</code> to compare with this <code>OID</code>.
412    * @return
413    * <UL>
414    * <LI>0 if the first <code>n</code> sub-identifiers are the same.
415    * <LI>&lt;0 if the first <code>n</code> sub-identifiers of this
416    * <code>OID</code> are lexicographic less than those of the comparand.
417    * <LI>&gt;0 if the first <code>n</code> sub-identifiers of this
418    * <code>OID</code> are lexicographic greater than those of the comparand.
419    * </UL>
420    */

421   public int leftMostCompare(int n, OID other) {
422     for (int i=0; i<n; i++) {
423       if (value[i] == other.value[i]) {
424         continue;
425       }
426       else if ((value[i] & 0xFFFFFFFFL) <
427                (other.value[i] & 0xFFFFFFFFL)) {
428         return -1;
429       }
430       else {
431         return 1;
432       }
433     }
434     return 0;
435   }
436
437   /**
438    * Compares the n rightmost sub-identifiers in direction right-to-left
439    * with those of the given <code>OID</code>.
440    * @param n
441    * the number of sub-identifiers to compare.
442    * @param other
443    * an <code>OID</code> to compare with this <code>OID</code>.
444    * @return
445    * <UL>
446    * <LI>0 if the first <code>n</code> sub-identifiers are the same.
447    * <LI>&lt;0 if the first <code>n</code> sub-identifiers of this
448    * <code>OID</code> are lexicographic less than those of the comparand.
449    * <LI>&gt;0 if the first <code>n</code> sub-identifiers of this
450    * <code>OID</code> are lexicographic greater than those of the comparand.
451    * </UL>
452    */

453   public int rightMostCompare(int n, OID other) {
454     int cursorA = value.length-1;
455     int cursorB = other.value.length-1;
456     for (int i=n-1; i>=0; i--,cursorA--,cursorB--) {
457       if (value[cursorA] == other.value[cursorB]) {
458         continue;
459       }
460       else if (value[cursorA] < other.value[cursorB]) {
461         return -1;
462       }
463       else {
464         return 1;
465       }
466     }
467     return 0;
468   }
469
470   /**
471    * Check if the OID starts with the given OID.
472    *
473    * @param other
474    * the OID to compare to
475    * @return
476    * false if the sub-identifiers do not match.
477    */

478   public boolean startsWith(OID other) {
479     if (other.value.length > value.length) {
480       return false;
481     }
482     int min = Math.min(value.length, other.value.length);
483     return (leftMostCompare(min, other) == 0);
484   }
485
486   public Object JavaDoc clone() {
487     return new OID(value);
488   }
489
490   /**
491    * Returns the last sub-identifier as an integer value. If this OID is
492    * empty (i.e. has no sub-identifiers) then a
493    * <code>NoSuchElementException</code> is thrown
494    * @return
495    * the value of the last sub-identifier of this OID as an integer value.
496    * Sub-identifier values greater than 2^31-1 will be returned as negative
497    * values!
498    * @since 1.2
499    */

500   public final int last() {
501     if (value.length > 0) {
502       return value[value.length-1];
503     }
504     throw new NoSuchElementException();
505   }
506
507   /**
508    * Returns the last sub-identifier as an unsigned long value. If this OID is
509    * empty (i.e. has no sub-identifiers) then a
510    * <code>NoSuchElementException</code> is thrown
511    * @return
512    * the value of the last sub-identifier of this OID as an unsigned long.
513    * @since 1.2
514    */

515   public final long lastUnsigned() {
516     if (value.length > 0) {
517       return value[value.length-1] & 0xFFFFFFFFL;
518     }
519     throw new NoSuchElementException();
520   }
521
522   /**
523    * Removes the last sub-identifier (if available) from this <code>OID</code>
524    * and returns it.
525    * @return
526    * the last sub-identifier or -1 if there is no sub-identifier left in
527    * this <code>OID</code>.
528    */

529   public int removeLast() {
530     if (value.length == 0) {
531       return -1;
532     }
533     int[] newValue = new int[value.length-1];
534     System.arraycopy(value, 0, newValue, 0, value.length-1);
535     int retValue = value[value.length-1];
536     value = newValue;
537     return retValue;
538   }
539
540   /**
541    * Remove the n rightmost subidentifiers from this OID.
542    * @param n
543    * the number of subidentifiers to remove. If <code>n</code> is zero or
544    * negative then this OID will not be changed. If <code>n</code> is greater
545    * than {@link #size()} all subidentifiers will be removed from this OID.
546    */

547   public void trim(int n) {
548     if (n > 0) {
549       if (n > value.length) {
550         n = value.length;
551       }
552       int[] newValue = new int[value.length-n];
553       System.arraycopy(value, 0, newValue, 0, value.length-n);
554       value = newValue;
555     }
556   }
557
558   public int toInt() {
559     throw new UnsupportedOperationException JavaDoc();
560   }
561
562   public long toLong() {
563     throw new UnsupportedOperationException JavaDoc();
564   }
565
566   public final OID toSubIndex(boolean impliedLength) {
567     if (impliedLength) {
568       return new OID(value);
569     }
570     OID subIndex = new OID(new int[] { size() });
571     subIndex.append(this);
572     return subIndex;
573   }
574
575   public final void fromSubIndex(OID subIndex, boolean impliedLength) {
576     int offset = 1;
577     if (impliedLength) {
578       offset = 0;
579     }
580     setValue(subIndex.getValue(), offset, subIndex.size()-offset);
581   }
582
583   /**
584    * Returns the successor OID for this OID.
585    * @return
586    * an OID clone of this OID with a zero sub-identifier appended.
587    * @since 1.7
588    */

589   public final OID successor() {
590     if (value.length == MAX_OID_LEN) {
591       for (int i=MAX_OID_LEN-1; i>=0; i--) {
592         if (value[i] != MAX_SUBID_VALUE) {
593           int[] succ = new int[i+1];
594           System.arraycopy(value, 0, succ, 0, i+1);
595           succ[i]++;
596           return new OID(succ);
597         }
598       }
599       return new OID();
600     }
601     else {
602       int[] succ = new int[value.length + 1];
603       System.arraycopy(value, 0, succ, 0, value.length);
604       succ[value.length] = 0;
605       return new OID(succ);
606     }
607   }
608
609   /**
610    * Returns the predecessor OID for this OID.
611    * @return
612    * if this OID ends on 0, then a {@link #MAX_OID_LEN}
613    * sub-identifier OID is returned where each sub-ID for index greater
614    * or equal to {@link #size()} is set to {@link #MAX_SUBID_VALUE}.
615    * @since 1.7
616    */

617   public final OID predecessor() {
618     if (last() != 0) {
619       int[] pval = new int[MAX_OID_LEN];
620       System.arraycopy(value, 0, pval, 0, value.length);
621       Arrays.fill(pval, value.length, pval.length, MAX_SUBID_VALUE);
622       OID pred = new OID(pval);
623       pred.set(size()-1, last()-1);
624       return pred;
625     }
626     else {
627       OID pred = new OID(this);
628       pred.removeLast();
629       return pred;
630     }
631   }
632
633   /**
634    * Returns the next following OID with the same or lesser size (length).
635    * @return OID
636    * the next OID on the same or upper level or a clone of this OID, if
637    * it has a zero length or is 2^32-1.
638    * @since 1.7
639    */

640   public final OID nextPeer() {
641     OID next = new OID(this);
642     if ((next.size() > 0) && (last() != MAX_SUBID_VALUE)) {
643       next.set(next.size()-1, last()+1);
644     }
645     else if (next.size() > 1) {
646       next.trim(1);
647       next = nextPeer();
648     }
649     return next;
650   }
651
652   /**
653    * Returns the greater of the two OID values.
654    * @param a
655    * an OID.
656    * @param b
657    * an OID.
658    * @return
659    * <code>a</code> if a &gt;= b, <code>b</code> otherwise.
660    * @since 1.7
661    */

662   public static final OID max(OID a, OID b) {
663     if (a.compareTo(b) >= 0) {
664       return a;
665     }
666     return b;
667   }
668
669   /**
670    * Returns the lesser of the two OID values.
671    * @param a
672    * an OID.
673    * @param b
674    * an OID.
675    * @return
676    * <code>a</code> if a &lt;= b, <code>b</code> otherwise.
677    * @since 1.7
678    */

679   public static final OID min(OID a, OID b) {
680     if (a.compareTo(b) <= 0) {
681       return a;
682     }
683     return b;
684   }
685
686 }
687
688
Popular Tags