KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jmx > snmp > BerEncoder


1 /*
2  * @(#)file BerEncoder.java
3  * @(#)author Sun Microsystems, Inc.
4  * @(#)version 4.16
5  * @(#)date 08/02/09
6  *
7  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
8  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
9  *
10  */

11
12
13 package com.sun.jmx.snmp;
14
15
16 /**
17  * The <CODE>BerEncoder</CODE> class is used for encoding data using BER.
18  *
19  * A <CODE>BerEncoder</CODE> needs to be set up with a byte buffer. The encoded
20  * data are stored in this byte buffer.
21  * <P>
22  * NOTE : the buffer is filled from end to start. This means the caller
23  * needs to encode its data in the reverse order.
24  *
25  *
26  * <p><b>This API is a Sun Microsystems internal API and is subject
27  * to change without notice.</b></p>
28  * @version 4.16 12/19/03
29  * @author Sun Microsystems, Inc
30  *
31  * @since 1.5
32  */

33
34 public class BerEncoder {
35
36   /**
37   * Constructs a new encoder and attaches it to the specified byte string.
38   *
39   * @param b The byte string containing the encoded data.
40   */

41
42   public BerEncoder(byte b[]) {
43     bytes = b ;
44     start = b.length ;
45     stackTop = 0 ;
46   }
47
48
49   /**
50   * Trim the encoding data and returns the length of the encoding.
51   *
52   * The encoder does backward encoding : so the bytes buffer is
53   * filled from end to start. The encoded data must be shift before
54   * the buffer can be used. This is the purpose of the <CODE>trim</CODE> method.
55   *
56   * After a call to the <CODE>trim</CODE> method, the encoder is reinitialized and <CODE>putXXX</CODE>
57   * overwrite any existing encoded data.
58   *
59   * @return The length of the encoded data.
60   */

61
62   public int trim() {
63     final int result = bytes.length - start ;
64
65     // for (int i = start ; i < bytes.length ; i++) {
66
// bytes[i-start] = bytes[i] ;
67
// }
68
if (result > 0)
69     java.lang.System.arraycopy(bytes,start,bytes,0,result);
70
71     start = bytes.length ;
72     stackTop = 0 ;
73     
74     return result ;
75   }
76   
77   /**
78   * Put an integer.
79   *
80   * @param v The integer to encode.
81   */

82
83   public void putInteger(int v) {
84     putInteger(v, IntegerTag) ;
85   }
86
87
88   /**
89   * Put an integer with the specified tag.
90   *
91   * @param v The integer to encode.
92   * @param tag The tag to encode.
93   */

94
95   public void putInteger(int v, int tag) {
96     putIntegerValue(v) ;
97     putTag(tag) ;
98   }
99
100
101
102   /**
103   * Put an integer expressed as a long.
104   *
105   * @param v The long to encode.
106   */

107
108   public void putInteger(long v) {
109     putInteger(v, IntegerTag) ;
110   }
111
112
113   /**
114   * Put an integer expressed as a long with the specified tag.
115   *
116   * @param v The long to encode
117   * @param tag The tag to encode.
118   */

119
120   public void putInteger(long v, int tag) {
121     putIntegerValue(v) ;
122     putTag(tag) ;
123   }
124
125
126
127   /**
128   * Put an octet string.
129   *
130   * @param s The bytes to encode
131   */

132
133   public void putOctetString(byte[] s) {
134     putOctetString(s, OctetStringTag) ;
135   }
136   
137
138   /**
139   * Put an octet string with a specified tag.
140   *
141   * @param s The bytes to encode
142   * @param tag The tag to encode.
143   */

144
145   public void putOctetString(byte[] s, int tag) {
146     putStringValue(s) ;
147     putTag(tag) ;
148   }
149
150
151   /**
152   * Put an object identifier.
153   *
154   * @param s The oid to encode.
155   */

156
157   public void putOid(long[] s) {
158     putOid(s, OidTag) ;
159   }
160   
161
162   /**
163   * Put an object identifier with a specified tag.
164   *
165   * @param s The integer to encode.
166   * @param tag The tag to encode.
167   */

168
169   public void putOid(long[] s, int tag) {
170     putOidValue(s) ;
171     putTag(tag) ;
172   }
173
174
175   /**
176   * Put a <CODE>NULL</CODE> value.
177   */

178
179   public void putNull() {
180     putNull(NullTag) ;
181   }
182
183
184   /**
185   * Put a <CODE>NULL</CODE> value with a specified tag.
186   *
187   * @param tag The tag to encode.
188   */

189
190   public void putNull(int tag) {
191     putLength(0) ;
192     putTag(tag) ;
193   }
194   
195   
196
197   /**
198   * Put an <CODE>ANY</CODE> value. In fact, this method does not encode anything.
199   * It simply copies the specified bytes into the encoding.
200   *
201   * @param s The encoding of the <CODE>ANY</CODE> value.
202   */

203
204   public void putAny(byte[] s) {
205     putAny(s, s.length) ;
206   }
207
208
209   /**
210   * Put an <CODE>ANY</CODE> value. Only the first <CODE>byteCount</CODE> are considered.
211   *
212   * @param s The encoding of the <CODE>ANY</CODE> value.
213   * @param byteCount The number of bytes of the encoding.
214   */

215
216   public void putAny(byte[] s, int byteCount) {
217       java.lang.System.arraycopy(s,0,bytes,start-byteCount,byteCount);
218       start -= byteCount;
219       // for (int i = byteCount - 1 ; i >= 0 ; i--) {
220
// bytes[--start] = s[i] ;
221
// }
222
}
223
224
225   /**
226   * Open a sequence.
227   * The encoder push the current position on its stack.
228   */

229
230   public void openSequence() {
231     stackBuf[stackTop++] = start ;
232   }
233
234
235   /**
236   * Close a sequence.
237   * The decode pull the stack to know the end of the current sequence.
238   */

239
240   public void closeSequence() {
241     closeSequence(SequenceTag) ;
242   }
243   
244   
245   /**
246   * Close a sequence with the specified tag.
247   */

248
249   public void closeSequence(int tag) {
250     final int end = stackBuf[--stackTop] ;
251     putLength(end - start) ;
252     putTag(tag) ;
253   }
254
255
256   //
257
// Some standard tags
258
//
259
public final static int BooleanTag = 1 ;
260   public final static int IntegerTag = 2 ;
261   public final static int OctetStringTag = 4 ;
262   public final static int NullTag = 5 ;
263   public final static int OidTag = 6 ;
264   public final static int SequenceTag = 0x30 ;
265
266
267
268
269   ////////////////////////// PROTECTED ///////////////////////////////
270

271
272
273   /**
274   * Put a tag and move the current position backward.
275   *
276   * @param tag The tag to encode.
277   */

278
279   protected final void putTag(int tag) {
280     if (tag < 256) {
281       bytes[--start] = (byte)tag ;
282     }
283     else {
284       while (tag != 0) {
285         bytes[--start] = (byte)(tag & 127) ;
286         tag = tag << 7 ;
287       }
288     }
289   }
290
291
292   /**
293   * Put a length and move the current position backward.
294   *
295   * @param length The length to encode.
296   */

297
298   protected final void putLength(final int length) {
299     if (length < 0) {
300       throw new IllegalArgumentException JavaDoc() ;
301     }
302     else if (length < 128) {
303       bytes[--start] = (byte)length ;
304     }
305     else if (length < 256) {
306       bytes[--start] = (byte)length ;
307       bytes[--start] = (byte)0x81 ;
308     }
309     else if (length < 65536) {
310       bytes[--start] = (byte)(length) ;
311       bytes[--start] = (byte)(length >> 8) ;
312       bytes[--start] = (byte)0x82 ;
313     }
314     else if (length < 16777126) {
315       bytes[--start] = (byte)(length) ;
316       bytes[--start] = (byte)(length >> 8) ;
317       bytes[--start] = (byte)(length >> 16) ;
318       bytes[--start] = (byte)0x83 ;
319     }
320     else {
321       bytes[--start] = (byte)(length) ;
322       bytes[--start] = (byte)(length >> 8) ;
323       bytes[--start] = (byte)(length >> 16) ;
324       bytes[--start] = (byte)(length >> 24) ;
325       bytes[--start] = (byte)0x84 ;
326     }
327   }
328   
329
330   /**
331   * Put an integer value and move the current position backward.
332   *
333   * @param v The integer to encode.
334   */

335
336   protected final void putIntegerValue(int v) {
337     final int end = start ;
338     int mask = 0x7f800000 ;
339     int byteNeeded = 4 ;
340     if (v < 0) {
341       while (((mask & v) == mask) && (byteNeeded > 1)) {
342         mask = mask >> 8 ;
343         byteNeeded-- ;
344       }
345     }
346     else {
347       while (((mask & v) == 0) && (byteNeeded > 1)) {
348         mask = mask >> 8 ;
349         byteNeeded-- ;
350       }
351     }
352     for (int i = 0 ; i < byteNeeded ; i++) {
353       bytes[--start] = (byte)v ;
354       v = v >> 8 ;
355     }
356     putLength(end - start) ;
357   }
358   
359   
360   /**
361   * Put an integer value expressed as a long.
362   *
363   * @param v The integer to encode.
364   */

365
366   protected final void putIntegerValue(long v) {
367     final int end = start ;
368     long mask = 0x7f80000000000000L ;
369     int byteNeeded = 8 ;
370     if (v < 0) {
371       while (((mask & v) == mask) && (byteNeeded > 1)) {
372         mask = mask >> 8 ;
373         byteNeeded-- ;
374       }
375     }
376     else {
377       while (((mask & v) == 0) && (byteNeeded > 1)) {
378         mask = mask >> 8 ;
379         byteNeeded-- ;
380       }
381     }
382     for (int i = 0 ; i < byteNeeded ; i++) {
383       bytes[--start] = (byte)v ;
384       v = v >> 8 ;
385     }
386     putLength(end - start) ;
387   }
388   
389   
390   /**
391   * Put a byte string and move the current position backward.
392   *
393   * @param s The byte string to encode.
394   */

395
396   protected final void putStringValue(byte[] s) {
397       final int datalen = s.length;
398       java.lang.System.arraycopy(s,0,bytes,start-datalen,datalen);
399       start -= datalen;
400       // for (int i = s.length - 1 ; i >= 0 ; i--) {
401
// bytes[--start] = s[i] ;
402
// }
403
putLength(datalen) ;
404   }
405
406
407
408   /**
409   * Put an oid and move the current position backward.
410   *
411   * @param s The oid to encode.
412   */

413
414   protected final void putOidValue(final long[] s) {
415       final int end = start ;
416       final int slength = s.length;
417
418       // bugId 4641746: 0, 1, and 2 are legal values.
419
if ((slength < 2) || (s[0] > 2) || (s[1] >= 40)) {
420       throw new IllegalArgumentException JavaDoc() ;
421       }
422       for (int i = slength - 1 ; i >= 2 ; i--) {
423       long c = s[i] ;
424       if (c < 0) {
425           throw new IllegalArgumentException JavaDoc() ;
426       }
427       else if (c < 128) {
428           bytes[--start] = (byte)c ;
429       }
430       else {
431           bytes[--start] = (byte)(c & 127) ;
432           c = c >> 7 ;
433           while (c != 0) {
434           bytes[--start] = (byte)(c | 128) ;
435           c = c >> 7 ;
436           }
437       }
438       }
439       bytes[--start] = (byte)(s[0] * 40 + s[1]) ;
440       putLength(end - start) ;
441   }
442   
443
444   //
445
// This is the byte array containing the encoding.
446
//
447
protected final byte bytes[];
448   
449   //
450
// This is the index of the first byte of the encoding.
451
// It is initialized to <CODE>bytes.length</CODE> and decrease each time
452
// an value is put in the encoder.
453
//
454
protected int start = -1 ;
455   
456   //
457
// This is the stack where end of sequences are kept.
458
// A value is computed and pushed in it each time the <CODE>openSequence</CODE> method
459
// is invoked.
460
// A value is pulled and checked each time the <CODE>closeSequence</CODE> method is called.
461
//
462
protected final int stackBuf[] = new int[200] ;
463   protected int stackTop = 0 ;
464   
465 }
466
467
468
Popular Tags