KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > snmp > SNMPObjectIdentifier


1 /*
2  * SNMP Package
3  *
4  * Copyright (C) 2004, Jonathan Sevy <jsevy@mcs.drexel.edu>
5  *
6  * This is free software. Redistribution and use in source and binary forms, with
7  * or without modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  * list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  * derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
23  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */

29
30
31 package snmp;
32
33 import java.util.*;
34 import java.io.*;
35
36 /**
37 * Class representing ASN.1 object identifiers. These are unbounded sequences (arrays) of
38 * natural numbers, written as dot-separated strings.
39 */

40
41 public class SNMPObjectIdentifier extends SNMPObject
42 {
43     private long[] digits; // array of longs
44

45     protected byte tag = SNMPBERCodec.SNMPOBJECTIDENTIFIER;
46     
47     /**
48     * Create a new empty object identifier (0-length array).
49     */

50     
51     public SNMPObjectIdentifier()
52     {
53         digits = new long[0];
54     }
55     
56     
57     
58     
59     /**
60     * Create a new object identifier from the supplied string of dot-separated nonegative
61     * decimal integer values.
62     * @throws SNMPBadValueException Indicates incorrectly-formatted string supplied.
63     */

64     
65     public SNMPObjectIdentifier(String JavaDoc digitString)
66         throws SNMPBadValueException
67     {
68         convertDigitString(digitString);
69     }
70     
71     
72     
73     
74     /**
75     * Create a new object identifier from the supplied array of nonegative
76     * integer values.
77     * @throws SNMPBadValueException Negative value(s) supplied.
78     */

79     
80     public SNMPObjectIdentifier(int[] digits)
81         throws SNMPBadValueException
82     {
83         long[] longDigits = new long[digits.length];
84         
85         for (int i = 0; i < digits.length; i++)
86         {
87             if (digits[i] < 0)
88                 throw new SNMPBadValueException("Negative value supplied for SNMPObjectIdentifier.");
89             
90             longDigits[i] = digits[i];
91         }
92                 
93         this.digits = longDigits;
94     }
95     
96     
97     
98     
99     /**
100     * Create a new object identifier from the supplied array of nonegative
101     * long values.
102     * @throws SNMPBadValueException Negative value(s) supplied.
103     */

104     
105     public SNMPObjectIdentifier(long[] digits)
106         throws SNMPBadValueException
107     {
108         
109         for (int i = 0; i < digits.length; i++)
110         {
111             if (digits[i] < 0)
112                 throw new SNMPBadValueException("Negative value supplied for SNMPObjectIdentifier.");
113         }
114                 
115         this.digits = digits;
116     }
117     
118     
119     
120     
121     /**
122     * Used to initialize from the BER encoding, as received in a response from
123     * an SNMP device responding to an SNMPGetRequest.
124     * @throws SNMPBadValueException Indicates an invalid BER encoding supplied. Shouldn't
125     * occur in normal operation, i.e., when valid responses are received from devices.
126     */

127     
128     protected SNMPObjectIdentifier(byte[] enc)
129         throws SNMPBadValueException
130     {
131         extractFromBEREncoding(enc);
132     }
133     
134     
135     
136     
137     /**
138     * Return array of integers corresponding to components of identifier.
139     */

140     
141     public Object JavaDoc getValue()
142     {
143         return digits;
144     }
145     
146     
147     
148     
149     
150     /**
151     * Used to set the value from an integer or long array containing the identifier components, or from
152     * a String containing a dot-separated sequence of nonegative values.
153     * @throws SNMPBadValueException Indicates an incorrect object type supplied, or negative array
154     * elements, or an incorrectly formatted String.
155     */

156     
157     public void setValue(Object JavaDoc digits)
158         throws SNMPBadValueException
159     {
160         if (digits instanceof long[])
161         {
162             for (int i = 0; i < ((long[])digits).length; i++)
163             {
164                 if (((long[])digits)[i] < 0)
165                     throw new SNMPBadValueException("Negative value supplied for SNMPObjectIdentifier.");
166             }
167             
168             this.digits = (long[])digits;
169         }
170         else if (digits instanceof int[])
171         {
172             long[] longDigits = new long[((int[])digits).length];
173         
174             for (int i = 0; i < ((int[])digits).length; i++)
175             {
176                 if (((int[])digits)[i] < 0)
177                     throw new SNMPBadValueException("Negative value supplied for SNMPObjectIdentifier.");
178                 
179                 longDigits[i] = ((int[])digits)[i];
180             }
181                 
182             this.digits = longDigits;
183         }
184         else if (digits instanceof String JavaDoc)
185         {
186             convertDigitString((String JavaDoc)digits);
187         }
188         else
189             throw new SNMPBadValueException(" Object Identifier: bad object supplied to set value ");
190     }
191     
192     
193     
194     
195     /**
196     * Return BER encoding for this object identifier.
197     */

198     
199     protected byte[] getBEREncoding()
200     {
201         ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
202         
203         byte type = SNMPBERCodec.SNMPOBJECTIDENTIFIER;
204             
205         // write contents of array of values
206
byte[] data = encodeArray();
207         
208         // calculate encoding for length of data
209
byte[] len = SNMPBERCodec.encodeLength(data.length);
210         
211         // encode T,L,V info
212
outBytes.write(type);
213         outBytes.write(len, 0, len.length);
214         outBytes.write(data, 0, data.length);
215         
216         return outBytes.toByteArray();
217     }
218     
219     
220     
221     private byte[] encodeArray()
222     {
223         ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
224         
225         int numElements = digits.length;
226         
227         // encode first two identifier digits as one byte, using the 40*x + y rule;
228
// of course, if only one element, just use 40*x; if none, do nothing
229
if (numElements >= 2)
230         {
231             outBytes.write((byte)(40*digits[0] + digits[1]));
232         }
233         else if (numElements ==1)
234         {
235             outBytes.write((byte)(40*digits[0]));
236         }
237         
238         
239         for (int i = 2; i < numElements; ++i)
240         {
241             byte[] nextBytes = encodeValue(digits[i]);
242             outBytes.write(nextBytes, 0, nextBytes.length);
243         }
244         
245         
246         return outBytes.toByteArray();
247     }
248     
249     
250     
251     private byte[] encodeValue(long v)
252     {
253         // see how many bytes are needed: each value uses just
254
// 7 bits of each byte, with high-order bit functioning as
255
// a continuation marker
256
int numBytes = 0;
257         long temp = v;
258         
259         do
260         {
261             ++numBytes;
262             temp = (long)Math.floor(temp / 128);
263         }
264         while (temp > 0);
265         
266         
267         byte[] enc = new byte[numBytes];
268         // encode lowest-order byte, without setting high bit
269
enc[numBytes-1] = (byte)(v % 128);
270         v = (long)Math.floor(v / 128);
271         
272         //.encode other bytes with high bit set
273
for (int i = numBytes-2; i >= 0; --i)
274         {
275             enc[i] = (byte)((v % 128) + 128);
276             v = (long)Math.floor(v / 128);
277         }
278         
279         return enc;
280     }
281     
282     
283     
284     private void convertDigitString(String JavaDoc digitString)
285         throws SNMPBadValueException
286     {
287         try
288         {
289             StringTokenizer st = new StringTokenizer(digitString, " .");
290             int size = 0;
291             
292             while (st.hasMoreTokens())
293             {
294                 // figure out how many values are in string
295
size++;
296                 st.nextToken();
297             }
298             
299             long[] returnDigits = new long[size];
300             
301             st = new StringTokenizer(digitString, " .");
302             
303             for (int i = 0; i < size; i++)
304             {
305                 returnDigits[i] = Long.parseLong(st.nextToken());
306                 if (returnDigits[i] < 0)
307                     throw new SNMPBadValueException(" Object Identifier: bad string supplied to set value ");
308             }
309             
310             digits = returnDigits;
311             
312         }
313         catch (NumberFormatException JavaDoc e)
314         {
315             throw new SNMPBadValueException(" Object Identifier: bad string supplied for object identifier value ");
316         }
317         
318         
319     }
320     
321     
322     
323     
324     private void extractFromBEREncoding(byte[] enc)
325         throws SNMPBadValueException
326     {
327         // note: masks must be ints; byte internal representation issue(?)
328
int bitTest = 0x80; // test for leading 1
329
int highBitMask = 0x7F; // mask out high bit for value
330

331         // first, compute number of "digits";
332
// will just be number of bytes with leading 0's
333
int numInts = 0;
334         for (int i = 0; i < enc.length; i++)
335         {
336             if ((enc[i] & bitTest) == 0) //high-order bit not set; count
337
numInts++;
338         }
339         
340         
341         if (numInts > 0)
342         {
343             // create new int array to hold digits; since first value is 40*x + y,
344
// need one extra entry in array to hold this.
345
digits = new long[numInts + 1];
346             
347             int currentByte = -1; // will be incremented to 0
348

349             long value = 0;
350             
351             // read in values 'til get leading 0 in byte
352
do
353             {
354                 currentByte++;
355                 value = value*128 + (enc[currentByte] & highBitMask);
356             }
357             while ((enc[currentByte] & bitTest) > 0); // implies high bit set!
358

359             // now handle 40a + b
360
digits[0] = (long)Math.floor(value / 40);
361             digits[1] = value % 40;
362             
363             // now read in rest!
364
for (int i = 2; i < numInts + 1; i++)
365             {
366                 // read in values 'til get leading 0 in byte
367
value = 0;
368                 do
369                 {
370                     currentByte++;
371                     value = value*128 + (enc[currentByte] & highBitMask);
372                 }
373                 while ((enc[currentByte] & bitTest) > 0);
374                 
375                 digits[i] = value;
376             }
377             
378         }
379         else
380         {
381             // no digits; create empty digit array
382
digits = new long[0];
383         }
384         
385     }
386     
387     
388     
389     
390     /*
391     public boolean equals(SNMPObjectIdentifier other)
392     {
393         long[] otherDigits = (long[])(other.getValue());
394         
395         boolean areEqual = true;
396         
397         if (digits.length != otherDigits.length)
398         {
399             areEqual = false;
400         }
401         else
402         {
403             for (int i = 0; i < digits.length; i++)
404             {
405                 if (digits[i] != otherDigits[i])
406                 {
407                     areEqual = false;
408                     break;
409                 }
410             }
411         }
412         
413         return areEqual;
414             
415     }
416     */

417     
418     
419     
420     
421     /**
422     * Checks the internal arrays for equality.
423     */

424     
425     public boolean equals(Object JavaDoc other)
426     {
427         // false if other is null
428
if (other == null)
429         {
430             return false;
431         }
432         
433         // check first to see that they're both of the same class
434
if (!this.getClass().equals(other.getClass()))
435         {
436             return false;
437         }
438         
439         SNMPObjectIdentifier otherSNMPObject = (SNMPObjectIdentifier)other;
440          
441         // see if their embedded arrays are equal
442
if (java.util.Arrays.equals((long[])this.getValue(),(long[])otherSNMPObject.getValue()))
443         {
444             return true;
445         }
446         else
447         {
448             return false;
449         }
450     }
451     
452     
453     
454     /**
455     * Generates a hash value so SNMP Object Identifiers can be used in Hashtables.
456     */

457     
458     public int hashCode()
459     {
460         int hash = 0;
461         
462         // generate a hashcode from the embedded array
463
for (int i = 0; i < digits.length; i++)
464         {
465             hash += (int)(digits[i] ^ (digits[i] >> 32));
466             hash += (hash << 10);
467             hash ^= (hash >> 6);
468         }
469         
470         hash += (hash << 3);
471         hash ^= (hash >> 11);
472         hash += (hash << 15);
473          
474         return hash;
475     }
476     
477     
478     
479     /**
480     * Return dot-separated sequence of decimal values.
481     */

482     
483     public String JavaDoc toString()
484     {
485         StringBuffer JavaDoc valueStringBuffer = new StringBuffer JavaDoc();
486         if (digits.length > 0)
487         {
488             valueStringBuffer.append(digits[0]);
489             
490             for (int i = 1; i < digits.length; ++i)
491             {
492                 valueStringBuffer.append(".");
493                 valueStringBuffer.append(digits[i]);
494             }
495         }
496         
497             
498         return valueStringBuffer.toString();
499     }
500     
501     
502     
503     
504 }
Popular Tags