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