KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > internal > verifier > BERProcessor


1 /*******************************************************************************
2  * Copyright (c) 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.osgi.internal.verifier;
13
14 import java.math.BigInteger JavaDoc;
15
16 /**
17  * This is a simple class that processes BER structures. This class
18  * uses BER processing as outlined in X.690.
19  */

20 public class BERProcessor {
21     /**
22      * This is the buffer that contains the BER structures that are being interrogated.
23      */

24     byte buffer[];
25     /**
26      * The offset into <code>buffer</code> to the start of the structure being interrogated.
27      * If the offset is -1 that means that we have read the last structure.
28      */

29     int offset;
30     /**
31      * The last valid offset in <code>buffer</code>.
32      */

33     int lastOffset;
34     /**
35      * The offset into <code>buffer</code> to the start of the content of the structure
36      * being interrogated.
37      */

38     int contentOffset;
39     /**
40      * The length of the content of the structure being interrogated.
41      */

42     int contentLength;
43     /**
44      * The offset into <code>buffer</code> of the end of the structure being interrogated.
45      */

46     int endOffset;
47     /**
48      * The class of the tag of the current structure.
49      */

50     int classOfTag;
51     static final int UNIVERSAL_TAGCLASS = 0;
52     static final int APPLICATION_TAGCLASS = 1;
53     static final int CONTEXTSPECIFIC_TAGCLASS = 2;
54     static final int PRIVATE_TAGCLASS = 3;
55
56     static final byte BOOLTAG = 1;
57     static final byte INTTAG = 2;
58     static final byte OIDTAG = 6;
59     static final byte SEQTAG = 16;
60     static final byte SETTAG = 17;
61     static final byte NULLTAG = 5;
62
63     /**
64      * Tagnames used in toString()
65      */

66     static final String JavaDoc tagNames[] = {"<null>", "boolean", "int", "bitstring", "octetstring", "null", "objid", "objdesc", "external", "real", "enum", "pdv", "utf8", "relobjid", "resv", "resv", "sequence", "set", "char string"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ //$NON-NLS-11$ //$NON-NLS-12$ //$NON-NLS-13$ //$NON-NLS-14$ //$NON-NLS-15$ //$NON-NLS-16$ //$NON-NLS-17$ //$NON-NLS-18$ //$NON-NLS-19$
67

68     /**
69      * True if this is a structure for a constructed encoding.
70      */

71     public boolean constructed;
72     /**
73      * The tag type. Note that X.690 specifies encodings for tags with values greater than 31,
74      * but currently this class does not handle these kinds of tags.
75      */

76     public byte tag;
77
78     /**
79      * Constructs a BERProcessor to operate on the passed buffer. The first structure in the
80      * buffer will be processed before this method returns.
81      *
82      * @param buffer the buffer containing the BER structures.
83      * @param offset the offset into <code>buffer</code> to the start of the first structure.
84      * @param len the length of the BER structure.
85      */

86     public BERProcessor(byte buffer[], int offset, int len) {
87         this.buffer = buffer;
88         this.offset = offset;
89         lastOffset = len + offset;
90         processStructure();
91     }
92
93     /**
94      * Parse the structure found at the current <code>offset</code> into <code>buffer</code>.
95      * Most methods, constructor, and stepinto, will call this method automatically. If
96      * <code>offset</code> is modified outside of those methods, this method will need to
97      * be invoked.
98      */

99     public void processStructure() {
100         // Don't process if we are at the end
101
if (offset == -1)
102             return;
103         endOffset = offset;
104         // section 8.1.2.2
105
classOfTag = (buffer[offset] & 0xff) >> 6;
106         // section 8.1.2.5
107
constructed = (buffer[offset] & 0x20) != 0;
108         // section 8.1.2.3
109
byte tagNumber = (byte) (buffer[offset] & 0x1f);
110         if (tagNumber < 32) {
111             tag = tagNumber;
112             endOffset = offset + 1;
113         } else {
114             throw new IllegalArgumentException JavaDoc("Can't handle tags > 32"); //$NON-NLS-1$
115
}
116         if ((buffer[endOffset] & 0x80) == 0) {
117             // section 8.1.3.4 (doing the short form of the length)
118
contentLength = buffer[endOffset];
119             endOffset++;
120         } else {
121             // section 8.1.3.5 (doing the long form of the length)
122
int octetCount = buffer[endOffset] & 0x7f;
123             if (octetCount > 3)
124                 throw new ArrayIndexOutOfBoundsException JavaDoc("ContentLength octet count too large: " + octetCount); //$NON-NLS-1$
125
contentLength = 0;
126             endOffset++;
127             for (int i = 0; i < octetCount; i++) {
128                 contentLength <<= 8;
129                 contentLength |= buffer[endOffset] & 0xff;
130                 endOffset++;
131             }
132             // section 8.1.3.6 (doing the indefinite form
133
if (octetCount == 0)
134                 contentLength = -1;
135         }
136         contentOffset = endOffset;
137         if (contentLength != -1)
138             endOffset += contentLength;
139         if (endOffset > lastOffset)
140             throw new ArrayIndexOutOfBoundsException JavaDoc(endOffset + " > " + lastOffset); //$NON-NLS-1$
141
}
142
143     /**
144      * Returns a String representation of the current BER structure.
145      * @return a String representation of the current BER structure.
146      * @see java.lang.Object#toString()
147      */

148     public String JavaDoc toString() {
149         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
150         switch (classOfTag) {
151             case UNIVERSAL_TAGCLASS :
152                 sb.append('U');
153                 break;
154             case APPLICATION_TAGCLASS :
155                 sb.append('A');
156                 break;
157             case CONTEXTSPECIFIC_TAGCLASS :
158                 sb.append('C');
159                 break;
160             case PRIVATE_TAGCLASS :
161                 sb.append('P');
162                 break;
163         }
164         sb.append(constructed ? 'C' : 'P');
165         sb.append(" tag=" + tag); //$NON-NLS-1$
166
if (tag < tagNames.length) {
167             sb.append("(" + tagNames[tag] + ")"); //$NON-NLS-1$ //$NON-NLS-2$
168
}
169         sb.append(" len="); //$NON-NLS-1$
170
sb.append(contentLength);
171         switch (tag) {
172             case INTTAG :
173                 sb.append(" value=" + getIntValue()); //$NON-NLS-1$
174
break;
175             case OIDTAG :
176                 sb.append(" value="); //$NON-NLS-1$
177
int oid[] = getObjId();
178                 for (int i = 0; i < oid.length; i++) {
179                     if (i > 0)
180                         sb.append('.');
181                     sb.append(oid[i]);
182                 }
183         }
184         if (tag == 12 || (tag >= 18 && tag <= 22) || (tag >= 25 && tag <= 30)) {
185             sb.append(" value="); //$NON-NLS-1$
186
sb.append(getString());
187         }
188         return sb.toString();
189     }
190
191     /**
192      * Returns a BERProcessor for the content of the current structure.
193      */

194     public BERProcessor stepInto() {
195         return new BERProcessor(buffer, contentOffset, contentLength);
196     }
197
198     public void stepOver() {
199         offset = endOffset;
200         if (endOffset >= lastOffset) {
201             offset = -1;
202             return;
203         }
204         processStructure();
205     }
206
207     public boolean endOfSequence() {
208         return offset == -1;
209     }
210
211     /**
212      * Gets the content from the current structure as a String.
213      * @return the content from the current structure as a String.
214      */

215     public String JavaDoc getString() {
216         return new String JavaDoc(buffer, contentOffset, contentLength);
217     }
218
219     /**
220      * Gets the content from the current structure as an int.
221      * @return the content from the current structure as an int.
222      */

223     public BigInteger JavaDoc getIntValue() {
224         return new BigInteger JavaDoc(getBytes());
225     }
226
227     /**
228      * Gets the content from the current structure as an object id (int[]).
229      * @return the content from the current structure as an object id (int[]).
230      */

231     public int[] getObjId() {
232         // First count the ids
233
int count = 0;
234         for (int i = 0; i < contentLength; i++) {
235             // section 8.19.2
236
if ((buffer[contentOffset + i] & 0x80) == 0)
237                 count++;
238         }
239         count++; // section 8.19.3
240
int oid[] = new int[count];
241         int index = 0;
242         int currentValue = 0;
243         for (int i = 0; i < contentLength; i++) {
244             currentValue <<= 7;
245             currentValue |= buffer[contentOffset + i] & 0x7f;
246             // section 8.19.2
247
if ((buffer[contentOffset + i] & 0x80) == 0) {
248                 if (index == 0) {
249                     // section 8.19.4 special processing
250
oid[index++] = currentValue / 40;
251                     oid[index++] = currentValue % 40;
252                 } else {
253                     oid[index++] = currentValue;
254                 }
255                 currentValue = 0;
256             }
257         }
258         return oid;
259     }
260
261     /**
262      * Get a copy of the bytes in the content of the current structure.
263      * @return a copy of the bytes in the content of the current structure.
264      */

265     public byte[] getBytes() {
266         byte v[] = new byte[contentLength];
267         System.arraycopy(buffer, contentOffset, v, 0, contentLength);
268         return v;
269     }
270
271 }
272
Popular Tags