001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2006-2008 Sun Microsystems, Inc.
025 *      Portions copyright 2012-2013 ForgeRock AS.
026 *      Portions Copyright 2014 Manuel Gaupp
027 */
028
029package org.forgerock.opendj.io;
030
031import java.io.Closeable;
032import java.io.IOException;
033
034import org.forgerock.opendj.ldap.ByteString;
035import org.forgerock.opendj.ldap.ByteStringBuilder;
036import org.forgerock.opendj.ldap.DecodeException;
037
038/**
039 * An interface for decoding ASN.1 elements from a data source.
040 * <p>
041 * Methods for creating {@link ASN1Reader}s are provided in the {@link ASN1}
042 * class.
043 */
044public interface ASN1Reader extends Closeable {
045
046    /**
047     * Closes this ASN.1 reader.
048     *
049     * @throws IOException
050     *             If an error occurs while closing.
051     */
052    void close() throws IOException;
053
054    /**
055     * Indicates whether or not the next element can be read without blocking.
056     *
057     * @return {@code true} if a complete element is available or {@code false}
058     *         otherwise.
059     * @throws DecodeException
060     *             If the available data was not valid ASN.1.
061     * @throws IOException
062     *             If an unexpected IO error occurred.
063     */
064    boolean elementAvailable() throws DecodeException, IOException;
065
066    /**
067     * Indicates whether or not the current stream, sequence, or set contains
068     * another element. Note that this method may return {@code true} even if a
069     * previous call to {@link #elementAvailable} returned {@code false},
070     * indicating that the current set or sequence contains another element but
071     * an attempt to read that element may block. This method will block if
072     * there is not enough data available to make the determination (typically
073     * only the next element's type is required).
074     *
075     * @return {@code true} if the current stream, sequence, or set contains
076     *         another element, or {@code false} if the end of the stream,
077     *         sequence, or set has been reached.
078     * @throws DecodeException
079     *             If the available data was not valid ASN.1.
080     * @throws IOException
081     *             If an unexpected IO error occurred.
082     */
083    boolean hasNextElement() throws DecodeException, IOException;
084
085    /**
086     * Returns the data length of the next element without actually reading it.
087     *
088     * @return The data length of the next element, or {@code -1} if the end of
089     *         the stream, sequence, or set has been reached.
090     * @throws DecodeException
091     *             If the available data was not valid ASN.1.
092     * @throws IOException
093     *             If an unexpected IO error occurred.
094     */
095    int peekLength() throws DecodeException, IOException;
096
097    /**
098     * Returns the type of the next element without actually reading it.
099     *
100     * @return The type of the next element, or {@code -1} if the end of the
101     *         stream, sequence, or set has been reached.
102     * @throws DecodeException
103     *             If the available data was not valid ASN.1.
104     * @throws IOException
105     *             If an unexpected IO error occurred.
106     */
107    byte peekType() throws DecodeException, IOException;
108
109    /**
110     * Reads the next element as a boolean having the Universal Boolean ASN.1
111     * type tag.
112     *
113     * @return The decoded boolean value.
114     * @throws DecodeException
115     *             If the element cannot be decoded as a boolean.
116     * @throws IOException
117     *             If an unexpected IO error occurred.
118     */
119    boolean readBoolean() throws DecodeException, IOException;
120
121    /**
122     * Reads the next element as a boolean having the provided type tag.
123     *
124     * @param type
125     *            The expected type tag of the element.
126     * @return The decoded boolean value.
127     * @throws DecodeException
128     *             If the element cannot be decoded as a boolean.
129     * @throws IOException
130     *             If an unexpected IO error occurred.
131     */
132    boolean readBoolean(byte type) throws DecodeException, IOException;
133
134    /**
135     * Finishes reading a sequence and discards any unread elements.
136     *
137     * @throws DecodeException
138     *             If an error occurs while advancing to the end of the
139     *             sequence.
140     * @throws IOException
141     *             If an unexpected IO error occurred.
142     * @throws IllegalStateException
143     *             If there is no sequence being read.
144     */
145    void readEndSequence() throws DecodeException, IOException;
146
147    /**
148     * Finishes reading an explicit tag and discards any unread elements.
149     *
150     * @throws DecodeException
151     *             If an error occurs while advancing to the end of the
152     *             explicit tag.
153     * @throws IOException
154     *             If an unexpected IO error occurred.
155     * @throws IllegalStateException
156     *             If there is no explicit tag being read.
157     */
158    void readEndExplicitTag() throws DecodeException, IOException;
159
160    /**
161     * Finishes reading a set and discards any unread elements.
162     *
163     * @throws DecodeException
164     *             If an error occurs while advancing to the end of the set.
165     * @throws IOException
166     *             If an unexpected IO error occurred.
167     * @throws IllegalStateException
168     *             If there is no set being read.
169     */
170    void readEndSet() throws DecodeException, IOException;
171
172    /**
173     * Reads the next element as an enumerated having the Universal Enumerated
174     * ASN.1 type tag.
175     *
176     * @return The decoded enumerated value.
177     * @throws DecodeException
178     *             If the element cannot be decoded as an enumerated value.
179     * @throws IOException
180     *             If an unexpected IO error occurred.
181     */
182    int readEnumerated() throws DecodeException, IOException;
183
184    /**
185     * Reads the next element as an enumerated having the provided type tag.
186     *
187     * @param type
188     *            The expected type tag of the element.
189     * @return The decoded enumerated value.
190     * @throws DecodeException
191     *             If the element cannot be decoded as an enumerated value.
192     * @throws IOException
193     *             If an unexpected IO error occurred.
194     */
195    int readEnumerated(byte type) throws DecodeException, IOException;
196
197    /**
198     * Reads the next element as an integer having the Universal Integer ASN.1
199     * type tag.
200     *
201     * @return The decoded integer value.
202     * @throws DecodeException
203     *             If the element cannot be decoded as an integer.
204     * @throws IOException
205     *             If an unexpected IO error occurred.
206     */
207    long readInteger() throws DecodeException, IOException;
208
209    /**
210     * Reads the next element as an integer having the provided type tag.
211     *
212     * @param type
213     *            The expected type tag of the element.
214     * @return The decoded integer value.
215     * @throws DecodeException
216     *             If the element cannot be decoded as an integer.
217     * @throws IOException
218     *             If an unexpected IO error occurred.
219     */
220    long readInteger(byte type) throws DecodeException, IOException;
221
222    /**
223     * Reads the next element as a null element having the Universal Null ASN.1
224     * type tag.
225     *
226     * @throws DecodeException
227     *             If the element cannot be decoded as a null element.
228     * @throws IOException
229     *             If an unexpected IO error occurred.
230     */
231    void readNull() throws DecodeException, IOException;
232
233    /**
234     * Reads the next element as a null element having the provided type tag.
235     *
236     * @param type
237     *            The expected type tag of the element.
238     * @throws DecodeException
239     *             If the element cannot be decoded as a null element.
240     * @throws IOException
241     *             If an unexpected IO error occurred.
242     */
243    void readNull(byte type) throws DecodeException, IOException;
244
245    /**
246     * Reads the next element as an octet string having the Universal Octet
247     * String ASN.1 type tag.
248     *
249     * @return The decoded octet string represented using a {@link ByteString}.
250     * @throws DecodeException
251     *             If the element cannot be decoded as an octet string.
252     * @throws IOException
253     *             If an unexpected IO error occurred.
254     */
255    ByteString readOctetString() throws DecodeException, IOException;
256
257    /**
258     * Reads the next element as an octet string having the provided type tag.
259     *
260     * @param type
261     *            The expected type tag of the element.
262     * @return The decoded octet string represented using a {@link ByteString}.
263     * @throws DecodeException
264     *             If the element cannot be decoded as an octet string.
265     * @throws IOException
266     *             If an unexpected IO error occurred.
267     */
268    ByteString readOctetString(byte type) throws DecodeException, IOException;
269
270    /**
271     * Reads the next element as an octet string having the provided type tag
272     * and appends it to the provided {@link ByteStringBuilder}.
273     *
274     * @param type
275     *            The expected type tag of the element.
276     * @param builder
277     *            The {@link ByteStringBuilder} to append the octet string to.
278     * @return A reference to {@code builder}.
279     * @throws DecodeException
280     *             If the element cannot be decoded as an octet string.
281     * @throws IOException
282     *             If an unexpected IO error occurred.
283     */
284    ByteStringBuilder readOctetString(byte type, ByteStringBuilder builder) throws DecodeException,
285            IOException;
286
287    /**
288     * Reads the next element as an octet string having the Universal Octet
289     * String ASN.1 type tag and appends it to the provided
290     * {@link ByteStringBuilder}.
291     *
292     * @param builder
293     *            The {@link ByteStringBuilder} to append the octet string to.
294     * @return A reference to {@code builder}.
295     * @throws DecodeException
296     *             If the element cannot be decoded as an octet string.
297     * @throws IOException
298     *             If an unexpected IO error occurred.
299     */
300    ByteStringBuilder readOctetString(ByteStringBuilder builder) throws DecodeException,
301            IOException;
302
303    /**
304     * Reads the next element as an octet string having the Universal Octet
305     * String ASN.1 type tag and decodes the value as a UTF-8 encoded string.
306     *
307     * @return The decoded octet string as a UTF-8 encoded string.
308     * @throws DecodeException
309     *             If the element cannot be decoded as an octet string.
310     * @throws IOException
311     *             If an unexpected IO error occurred.
312     */
313    String readOctetStringAsString() throws DecodeException, IOException;
314
315    /**
316     * Reads the next element as an octet string having the provided type tag
317     * and decodes the value as a UTF-8 encoded string.
318     *
319     * @param type
320     *            The expected type tag of the element.
321     * @return The decoded octet string as a UTF-8 encoded string.
322     * @throws DecodeException
323     *             If the element cannot be decoded as an octet string.
324     * @throws IOException
325     *             If an unexpected IO error occurred.
326     */
327    String readOctetStringAsString(byte type) throws DecodeException, IOException;
328
329    /**
330     * Reads the next element as a sequence having the Universal Sequence ASN.1
331     * type tag. All further reads will read the elements in the sequence until
332     * {@link #readEndSequence()} is called.
333     *
334     * @throws DecodeException
335     *             If the element cannot be decoded as a sequence.
336     * @throws IOException
337     *             If an unexpected IO error occurred.
338     */
339    void readStartSequence() throws DecodeException, IOException;
340
341    /**
342     * Reads the next element as an explicit ignoring the ASN.1 type tag. All
343     * further reads will read the elements in the explicit tag until
344     * {@link #readEndExplicitTag()} is called.
345     *
346     * @throws DecodeException
347     *             If the element cannot be decoded as an explicit tag.
348     * @throws IOException
349     *             If an unexpected IO error occurred.
350     */
351    void readStartExplicitTag() throws DecodeException, IOException;
352
353    /**
354     * Reads the next element as an explicit tag having the provided tag type.
355     * All further reads will read the elements in the explicit tag until
356     * {@link #readEndExplicitTag()} is called.
357     *
358     * @param type
359     *            The expected type tag of the element.
360     * @throws DecodeException
361     *             If the element cannot be decoded as an explicit tag.
362     * @throws IOException
363     *             If an unexpected IO error occurred.
364     */
365    void readStartExplicitTag(byte type) throws DecodeException, IOException;
366
367    /**
368     * Reads the next element as a sequence having the provided type tag. All
369     * further reads will read the elements in the sequence until
370     * {@link #readEndSequence()} is called.
371     *
372     * @param type
373     *            The expected type tag of the element.
374     * @throws DecodeException
375     *             If the element cannot be decoded as a sequence.
376     * @throws IOException
377     *             If an unexpected IO error occurred.
378     */
379    void readStartSequence(byte type) throws DecodeException, IOException;
380
381    /**
382     * Reads the next element as a set having the Universal Set ASN.1 type tag.
383     * All further reads will read the elements in the set until
384     * {@link #readEndSet()} is called.
385     *
386     * @throws DecodeException
387     *             If the element cannot be decoded as a set.
388     * @throws IOException
389     *             If an unexpected IO error occurred.
390     */
391    void readStartSet() throws DecodeException, IOException;
392
393    /**
394     * Reads the next element as a set having the provided type tag. All further
395     * reads will read the elements in the set until {@link #readEndSet()} is
396     * called.
397     *
398     * @param type
399     *            The expected type tag of the element.
400     * @throws DecodeException
401     *             If the element cannot be decoded as a set.
402     * @throws IOException
403     *             If an unexpected IO error occurred.
404     */
405    void readStartSet(byte type) throws DecodeException, IOException;
406
407    /**
408     * Skips the next element without decoding it.
409     *
410     * @return A reference to this ASN.1 reader.
411     * @throws DecodeException
412     *             If the next element could not be skipped.
413     * @throws IOException
414     *             If an unexpected IO error occurred.
415     */
416    ASN1Reader skipElement() throws DecodeException, IOException;
417
418    /**
419     * Skips the next element having the provided type tag without decoding it.
420     *
421     * @param type
422     *            The expected type tag of the element.
423     * @return A reference to this ASN.1 reader.
424     * @throws DecodeException
425     *             If the next element does not have the provided type tag.
426     * @throws IOException
427     *             If an unexpected IO error occurred.
428     */
429    ASN1Reader skipElement(byte type) throws DecodeException, IOException;
430}