History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/jmx/snmp/BerDecoder.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/jmx/snmp/BerDecoder.java+757−0
@@ -0,0 +1,757 @@
1+/*
2+ * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+
27+package com.sun.jmx.snmp;
28+
29+
30+
31+
32+/**
33+ * The <CODE>BerDecoder</CODE> class is used for decoding
34+ * BER-encoded data.
35+ *
36+ * A <CODE>BerDecoder</CODE> needs to be set up with the byte string containing
37+ * the encoding. It maintains a current position in the byte string.
38+ *
39+ * Methods allows to fetch integer, string, OID, etc., from the current
40+ * position. After a fetch the current position is moved forward.
41+ *
42+ * A fetch throws a <CODE>BerException</CODE> if the encoding is not of the
43+ * expected type.
44+ *
45+ * <p><b>This API is a Sun Microsystems internal API and is subject
46+ * to change without notice.</b></p>
47+ *
48+ * @since 1.5
49+ */
50+
51+public class BerDecoder {
52+
53+ /**
54+ * Constructs a new decoder and attaches it to the specified byte string.
55+ *
56+ * @param b The byte string containing the encoded data.
57+ */
58+
59+ public BerDecoder(byte b[]) {
60+ bytes = b ;
61+ reset() ;
62+ }
63+
64+ public void reset() {
65+ next = 0 ;
66+ stackTop = 0 ;
67+ }
68+
69+ /**
70+ * Fetch an integer.
71+ *
72+ * @return The decoded integer.
73+ *
74+ * @exception BerException Current position does not point to an integer.
75+ */
76+
77+ public int fetchInteger() throws BerException {
78+ return fetchInteger(IntegerTag) ;
79+ }
80+
81+
82+ /**
83+ * Fetch an integer with the specified tag.
84+ *
85+ * @param tag The expected tag.
86+ *
87+ * @return The decoded integer.
88+ *
89+ * @exception BerException Current position does not point to an integer
90+ * or the tag is not the expected one.
91+ */
92+
93+ public int fetchInteger(int tag) throws BerException {
94+ int result = 0 ;
95+ final int backup = next ;
96+ try {
97+ if (fetchTag() != tag) {
98+ throw new BerException() ;
99+ }
100+ result = fetchIntegerValue() ;
101+ }
102+ catch(BerException e) {
103+ next = backup ;
104+ throw e ;
105+ }
106+
107+ return result ;
108+ }
109+
110+
111+
112+ /**
113+ * Fetch an integer and return a long value.
114+ *
115+ * @return The decoded integer.
116+ *
117+ * @exception BerException Current position does not point to an integer.
118+ */
119+
120+ public long fetchIntegerAsLong() throws BerException {
121+ return fetchIntegerAsLong(IntegerTag) ;
122+ }
123+
124+
125+ /**
126+ * Fetch an integer with the specified tag and return a long value.
127+ *
128+ * @param tag The expected tag.
129+ *
130+ * @return The decoded integer.
131+ *
132+ * @exception BerException Current position does not point to an integer
133+ * or the tag is not the expected one.
134+ */
135+
136+ public long fetchIntegerAsLong(int tag) throws BerException {
137+ long result = 0 ;
138+ final int backup = next ;
139+ try {
140+ if (fetchTag() != tag) {
141+ throw new BerException() ;
142+ }
143+ result = fetchIntegerValueAsLong() ;
144+ }
145+ catch(BerException e) {
146+ next = backup ;
147+ throw e ;
148+ }
149+
150+ return result ;
151+ }
152+
153+
154+
155+ /**
156+ * Fetch an octet string.
157+ *
158+ * @return The decoded string.
159+ *
160+ * @exception BerException Current position does not point to an octet string.
161+ */
162+
163+ public byte[] fetchOctetString() throws BerException {
164+ return fetchOctetString(OctetStringTag) ;
165+ }
166+
167+
168+ /**
169+ * Fetch an octet string with a specified tag.
170+ *
171+ * @param tag The expected tag.
172+ *
173+ * @return The decoded string.
174+ *
175+ * @exception BerException Current position does not point to an octet string
176+ * or the tag is not the expected one.
177+ */
178+
179+ public byte[] fetchOctetString(int tag) throws BerException {
180+ byte[] result = null ;
181+ final int backup = next ;
182+ try {
183+ if (fetchTag() != tag) {
184+ throw new BerException() ;
185+ }
186+ result = fetchStringValue() ;
187+ }
188+ catch(BerException e) {
189+ next = backup ;
190+ throw e ;
191+ }
192+
193+ return result ;
194+ }
195+
196+
197+ /**
198+ * Fetch an object identifier.
199+ *
200+ * @return The decoded object identifier as an array of long.
201+ */
202+
203+ public long[] fetchOid() throws BerException {
204+ return fetchOid(OidTag) ;
205+ }
206+
207+
208+ /**
209+ * Fetch an object identifier with a specified tag.
210+ *
211+ * @param tag The expected tag.
212+ *
213+ * @return The decoded object identifier as an array of long.
214+ *
215+ * @exception BerException Current position does not point to an oid
216+ * or the tag is not the expected one.
217+ */
218+
219+ public long[] fetchOid(int tag) throws BerException {
220+ long[] result = null ;
221+ final int backup = next ;
222+ try {
223+ if (fetchTag() != tag) {
224+ throw new BerException() ;
225+ }
226+ result = fetchOidValue() ;
227+ }
228+ catch(BerException e) {
229+ next = backup ;
230+ throw e ;
231+ }
232+
233+ return result ;
234+ }
235+
236+
237+ /**
238+ * Fetch a <CODE>NULL</CODE> value.
239+ *
240+ * @exception BerException Current position does not point to <CODE>NULL</CODE> value.
241+ */
242+
243+ public void fetchNull() throws BerException {
244+ fetchNull(NullTag) ;
245+ }
246+
247+
248+ /**
249+ * Fetch a <CODE>NULL</CODE> value with a specified tag.
250+ *
251+ * @param tag The expected tag.
252+ *
253+ * @exception BerException Current position does not point to
254+ * <CODE>NULL</CODE> value or the tag is not the expected one.
255+ */
256+
257+ public void fetchNull(int tag) throws BerException {
258+ final int backup = next ;
259+ try {
260+ if (fetchTag() != tag) {
261+ throw new BerException() ;
262+ }
263+ final int length = fetchLength();
264+ if (length != 0) throw new BerException();
265+ }
266+ catch(BerException e) {
267+ next = backup ;
268+ throw e ;
269+ }
270+ }
271+
272+
273+
274+ /**
275+ * Fetch an <CODE>ANY</CODE> value. In fact, this method does not decode anything
276+ * it simply returns the next TLV as an array of bytes.
277+ *
278+ * @return The TLV as a byte array.
279+ *
280+ * @exception BerException The next TLV is really badly encoded...
281+ */
282+
283+ public byte[] fetchAny() throws BerException {
284+ byte[] result = null ;
285+ final int backup = next ;
286+ try {
287+ final int tag = fetchTag() ;
288+ final int contentLength = fetchLength() ;
289+ if (contentLength < 0) throw new BerException() ;
290+ final int tlvLength = next + contentLength - backup ;
291+ if (contentLength > (bytes.length - next))
292+ throw new IndexOutOfBoundsException("Decoded length exceeds buffer");
293+ final byte[] data = new byte[tlvLength] ;
294+ java.lang.System.arraycopy(bytes,backup,data,0,tlvLength);
295+ // for (int i = 0 ; i < tlvLength ; i++) {
296+ // data[i] = bytes[backup + i] ;
297+ // }
298+ next = next + contentLength ;
299+ result = data;
300+ }
301+ catch(IndexOutOfBoundsException e) {
302+ next = backup ;
303+ throw new BerException() ;
304+ }
305+ // catch(Error e) {
306+ // debug("fetchAny: Error decoding BER: " + e);
307+ // throw e;
308+ // }
309+
310+ return result ;
311+ }
312+
313+
314+ /**
315+ * Fetch an <CODE>ANY</CODE> value with a specific tag.
316+ *
317+ * @param tag The expected tag.
318+ *
319+ * @return The TLV as a byte array.
320+ *
321+ * @exception BerException The next TLV is really badly encoded...
322+ */
323+
324+ public byte[] fetchAny(int tag) throws BerException {
325+ if (getTag() != tag) {
326+ throw new BerException() ;
327+ }
328+ return fetchAny() ;
329+ }
330+
331+
332+
333+ /**
334+ * Fetch a sequence header.
335+ * The decoder computes the end position of the sequence and push it
336+ * on its stack.
337+ *
338+ * @exception BerException Current position does not point to a sequence header.
339+ */
340+
341+ public void openSequence() throws BerException {
342+ openSequence(SequenceTag) ;
343+ }
344+
345+
346+ /**
347+ * Fetch a sequence header with a specific tag.
348+ *
349+ * @param tag The expected tag.
350+ *
351+ * @exception BerException Current position does not point to a sequence header
352+ * or the tag is not the expected one.
353+ */
354+
355+ public void openSequence(int tag) throws BerException {
356+ final int backup = next ;
357+ try {
358+ if (fetchTag() != tag) {
359+ throw new BerException() ;
360+ }
361+ final int l = fetchLength() ;
362+ if (l < 0) throw new BerException();
363+ if (l > (bytes.length - next)) throw new BerException();
364+ stackBuf[stackTop++] = next + l ;
365+ }
366+ catch(BerException e) {
367+ next = backup ;
368+ throw e ;
369+ }
370+ }
371+
372+
373+ /**
374+ * Close a sequence.
375+ * The decode pull the stack and verifies that the current position
376+ * matches with the calculated end of the sequence. If not it throws
377+ * an exception.
378+ *
379+ * @exception BerException The sequence is not expected to finish here.
380+ */
381+
382+ public void closeSequence() throws BerException {
383+ if (stackBuf[stackTop - 1] == next) {
384+ stackTop-- ;
385+ }
386+ else {
387+ throw new BerException() ;
388+ }
389+ }
390+
391+
392+ /**
393+ * Return <CODE>true</CODE> if the end of the current sequence is not reached.
394+ * When this method returns <CODE>false</CODE>, <CODE>closeSequence</CODE> can (and must) be
395+ * invoked.
396+ *
397+ * @return <CODE>true</CODE> if there is still some data in the sequence.
398+ */
399+
400+ public boolean cannotCloseSequence() {
401+ return (next < stackBuf[stackTop - 1]) ;
402+ }
403+
404+
405+ /**
406+ * Get the tag of the data at the current position.
407+ * Current position is unchanged.
408+ *
409+ * @return The next tag.
410+ */
411+
412+ public int getTag() throws BerException {
413+ int result = 0 ;
414+ final int backup = next ;
415+ try {
416+ result = fetchTag() ;
417+ }
418+ finally {
419+ next = backup ;
420+ }
421+
422+ return result ;
423+ }
424+
425+
426+
427+ public String toString() {
428+ final StringBuffer result = new StringBuffer(bytes.length * 2) ;
429+ for (int i = 0 ; i < bytes.length ; i++) {
430+ final int b = (bytes[i] > 0) ? bytes[i] : bytes[i] + 256 ;
431+ if (i == next) {
432+ result.append("(") ;
433+ }
434+ result.append(Character.forDigit(b / 16, 16)) ;
435+ result.append(Character.forDigit(b % 16, 16)) ;
436+ if (i == next) {
437+ result.append(")") ;
438+ }
439+ }
440+ if (bytes.length == next) {
441+ result.append("()") ;
442+ }
443+
444+ return new String(result) ;
445+ }
446+
447+
448+ //
449+ // Some standard tags
450+ //
451+ public final static int BooleanTag = 1 ;
452+ public final static int IntegerTag = 2 ;
453+ public final static int OctetStringTag = 4 ;
454+ public final static int NullTag = 5 ;
455+ public final static int OidTag = 6 ;
456+ public final static int SequenceTag = 0x30 ;
457+
458+
459+
460+
461+ ////////////////////////// PRIVATE ///////////////////////////////
462+
463+
464+
465+ /**
466+ * Fetch a tag and move the current position forward.
467+ *
468+ * @return The tag
469+ */
470+
471+ private final int fetchTag() throws BerException {
472+ int result = 0 ;
473+ final int backup = next ;
474+
475+ try {
476+ final byte b0 = bytes[next++] ;
477+ result = (b0 >= 0) ? b0 : b0 + 256 ;
478+ if ((result & 31) == 31) {
479+ while ((bytes[next] & 128) != 0) {
480+ result = result << 7 ;
481+ result = result | (bytes[next++] & 127);
482+ }
483+ }
484+ }
485+ catch(IndexOutOfBoundsException e) {
486+ next = backup ;
487+ throw new BerException() ;
488+ }
489+
490+ return result ;
491+ }
492+
493+
494+ /**
495+ * Fetch a length and move the current position forward.
496+ *
497+ * @return The length
498+ */
499+
500+ private final int fetchLength() throws BerException {
501+ int result = 0 ;
502+ final int backup = next ;
503+
504+ try {
505+ final byte b0 = bytes[next++] ;
506+ if (b0 >= 0) {
507+ result = b0 ;
508+ }
509+ else {
510+ for (int c = 128 + b0 ; c > 0 ; c--) {
511+ final byte bX = bytes[next++] ;
512+ result = result << 8 ;
513+ result = result | ((bX >= 0) ? bX : bX+256) ;
514+ }
515+ }
516+ }
517+ catch(IndexOutOfBoundsException e) {
518+ next = backup ;
519+ throw new BerException() ;
520+ }
521+
522+ return result ;
523+ }
524+
525+
526+ /**
527+ * Fetch an integer value and move the current position forward.
528+ *
529+ * @return The integer
530+ */
531+
532+ private int fetchIntegerValue() throws BerException {
533+ int result = 0 ;
534+ final int backup = next ;
535+
536+ try {
537+ final int length = fetchLength() ;
538+ if (length <= 0) throw new BerException() ;
539+ if (length > (bytes.length - next)) throw
540+ new IndexOutOfBoundsException("Decoded length exceeds buffer");
541+ final int end = next + length ;
542+ result = bytes[next++] ;
543+ while (next < end) {
544+ final byte b = bytes[next++] ;
545+ if (b < 0) {
546+ result = (result << 8) | (256 + b) ;
547+ }
548+ else {
549+ result = (result << 8) | b ;
550+ }
551+ }
552+ }
553+ catch(BerException e) {
554+ next = backup ;
555+ throw e ;
556+ }
557+ catch(IndexOutOfBoundsException e) {
558+ next = backup ;
559+ throw new BerException() ;
560+ }
561+ catch(ArithmeticException e) {
562+ next = backup ;
563+ throw new BerException() ;
564+ }
565+ return result ;
566+ }
567+
568+
569+ /**
570+ * Fetch an integer value and return a long value.
571+ * FIX ME: someday we could have only on fetchIntegerValue() which always
572+ * returns a long value.
573+ *
574+ * @return The integer
575+ */
576+
577+ private final long fetchIntegerValueAsLong() throws BerException {
578+ long result = 0 ;
579+ final int backup = next ;
580+
581+ try {
582+ final int length = fetchLength() ;
583+ if (length <= 0) throw new BerException() ;
584+ if (length > (bytes.length - next)) throw
585+ new IndexOutOfBoundsException("Decoded length exceeds buffer");
586+
587+ final int end = next + length ;
588+ result = bytes[next++] ;
589+ while (next < end) {
590+ final byte b = bytes[next++] ;
591+ if (b < 0) {
592+ result = (result << 8) | (256 + b) ;
593+ }
594+ else {
595+ result = (result << 8) | b ;
596+ }
597+ }
598+ }
599+ catch(BerException e) {
600+ next = backup ;
601+ throw e ;
602+ }
603+ catch(IndexOutOfBoundsException e) {
604+ next = backup ;
605+ throw new BerException() ;
606+ }
607+ catch(ArithmeticException e) {
608+ next = backup ;
609+ throw new BerException() ;
610+ }
611+ return result ;
612+ }
613+
614+
615+ /**
616+ * Fetch a byte string and move the current position forward.
617+ *
618+ * @return The byte string
619+ */
620+
621+ private byte[] fetchStringValue() throws BerException {
622+ byte[] result = null ;
623+ final int backup = next ;
624+
625+ try {
626+ final int length = fetchLength() ;
627+ if (length < 0) throw new BerException() ;
628+ if (length > (bytes.length - next))
629+ throw new IndexOutOfBoundsException("Decoded length exceeds buffer");
630+ final byte data[] = new byte[length] ;
631+ java.lang.System.arraycopy(bytes,next,data,0,length);
632+ next += length;
633+ // int i = 0 ;
634+ // while (i < length) {
635+ // result[i++] = bytes[next++] ;
636+ // }
637+ result = data;
638+ }
639+ catch(BerException e) {
640+ next = backup ;
641+ throw e ;
642+ }
643+ catch(IndexOutOfBoundsException e) {
644+ next = backup ;
645+ throw new BerException() ;
646+ }
647+ catch(ArithmeticException e) {
648+ next = backup ;
649+ throw new BerException() ;
650+ }
651+ // catch(Error e) {
652+ // debug("fetchStringValue: Error decoding BER: " + e);
653+ // throw e;
654+ // }
655+
656+ return result ;
657+ }
658+
659+
660+
661+ /**
662+ * Fetch an oid and move the current position forward.
663+ *
664+ * @return The oid
665+ */
666+
667+ private final long[] fetchOidValue() throws BerException {
668+ long[] result = null ;
669+ final int backup = next ;
670+
671+ try {
672+ final int length = fetchLength() ;
673+ if (length <= 0) throw new BerException() ;
674+ if (length > (bytes.length - next))
675+ throw new IndexOutOfBoundsException("Decoded length exceeds buffer");
676+ // Count how many bytes have their 8th bit to 0
677+ // -> this gives the number of components in the oid
678+ int subidCount = 2 ;
679+ for (int i = 1 ; i < length ; i++) {
680+ if ((bytes[next + i] & 0x80) == 0) {
681+ subidCount++ ;
682+ }
683+ }
684+ final int datalen = subidCount;
685+ final long[] data = new long[datalen];
686+ final byte b0 = bytes[next++] ;
687+
688+ // bugId 4641746
689+ // The 8th bit of the first byte should always be set to 0
690+ if (b0 < 0) throw new BerException();
691+
692+ // bugId 4641746
693+ // The first sub Id cannot be greater than 2
694+ final long lb0 = b0 / 40 ;
695+ if (lb0 > 2) throw new BerException();
696+
697+ final long lb1 = b0 % 40;
698+ data[0] = lb0 ;
699+ data[1] = lb1 ;
700+ int i = 2 ;
701+ while (i < datalen) {
702+ long subid = 0 ;
703+ byte b = bytes[next++] ;
704+ while ((b & 0x80) != 0) {
705+ subid = (subid << 7) | (b & 0x7f) ;
706+ // bugId 4654674
707+ if (subid < 0) throw new BerException();
708+ b = bytes[next++] ;
709+ }
710+ subid = (subid << 7) | b ;
711+ // bugId 4654674
712+ if (subid < 0) throw new BerException();
713+ data[i++] = subid ;
714+ }
715+ result = data;
716+ }
717+ catch(BerException e) {
718+ next = backup ;
719+ throw e ;
720+ }
721+ catch(IndexOutOfBoundsException e) {
722+ next = backup ;
723+ throw new BerException() ;
724+ }
725+ // catch(Error e) {
726+ // debug("fetchOidValue: Error decoding BER: " + e);
727+ // throw e;
728+ // }
729+
730+ return result ;
731+ }
732+
733+ // private static final void debug(String str) {
734+ // System.out.println(str);
735+ // }
736+
737+ //
738+ // This is the byte array containing the encoding.
739+ //
740+ private final byte bytes[];
741+
742+ //
743+ // This is the current location. It is the next byte
744+ // to be decoded. It's an index in bytes[].
745+ //
746+ private int next = 0 ;
747+
748+ //
749+ // This is the stack where end of sequences are kept.
750+ // A value is computed and pushed in it each time openSequence()
751+ // is invoked.
752+ // A value is pulled and checked each time closeSequence() is called.
753+ //
754+ private final int stackBuf[] = new int[200] ;
755+ private int stackTop = 0 ;
756+
757+}