001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *    https://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 *
019 */
020package org.apache.directory.api.asn1.ber;
021
022
023import java.nio.Buffer;
024import java.nio.ByteBuffer;
025
026import org.apache.directory.api.asn1.ber.grammar.Grammar;
027import org.apache.directory.api.asn1.ber.grammar.States;
028import org.apache.directory.api.asn1.ber.tlv.TLV;
029import org.apache.directory.api.asn1.ber.tlv.TLVStateEnum;
030
031
032/**
033 * This class is the abstract container used to store the current state of a PDU
034 * being decoded. It also stores the grammars used to decode the PDU, and all
035 * the informations needed to decode a PDU.
036 *
037 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
038 */
039public abstract class AbstractContainer implements Asn1Container
040{
041    /** All the possible grammars */
042    private Grammar<? extends Asn1Container> grammar;
043
044    /** The current state of the decoding */
045    private TLVStateEnum state;
046
047    /** The current transition */
048    private Enum<?> transition;
049
050    /** The current TLV */
051    private TLV tlv;
052
053    /** The parent TLV */
054    private TLV parentTLV;
055
056    /** The grammar end transition flag */
057    private boolean grammarEndAllowed;
058
059    /** A counter for the decoded bytes */
060    private int decodedBytes;
061
062    /** The maximum allowed size for a PDU. Default to MAX int value */
063    private int maxPDUSize = Integer.MAX_VALUE;
064
065    /** The incremental id used to tag TLVs */
066    private int id = 0;
067
068    /** The Stream being decoded */
069    private ByteBuffer stream;
070
071    /** A flag telling if the Value should be accumulated before being decoded
072     * for constructed types */
073    private boolean gathering = false;
074
075
076    /**
077     * Creates a new instance of AbstractContainer with a starting state.
078     *
079     */
080    protected AbstractContainer()
081    {
082        state = TLVStateEnum.TAG_STATE_START;
083    }
084
085
086    /**
087     * Creates a new instance of AbstractContainer with a starting state.
088     *
089     * @param stream the buffer containing the data to decode
090     */
091    protected AbstractContainer( ByteBuffer stream )
092    {
093        state = TLVStateEnum.TAG_STATE_START;
094        this.stream = stream;
095    }
096
097
098    /**
099     * {@inheritDoc}
100     */
101    @Override
102    public Grammar<? extends Asn1Container> getGrammar()
103    {
104        return grammar;
105    }
106
107
108    /**
109     * {@inheritDoc}
110     */
111    @Override
112    public void setGrammar( Grammar<? extends Asn1Container> grammar )
113    {
114        this.grammar = grammar;
115    }
116
117
118    /**
119     * {@inheritDoc}
120     */
121    @Override
122    public TLVStateEnum getState()
123    {
124        return state;
125    }
126
127
128    /**
129     * {@inheritDoc}
130     */
131    @Override
132    public void setState( TLVStateEnum state )
133    {
134        this.state = state;
135    }
136
137
138    /**
139     * {@inheritDoc}
140     */
141    @Override
142    public boolean isGrammarEndAllowed()
143    {
144        return grammarEndAllowed;
145    }
146
147
148    /**
149     * {@inheritDoc}
150     */
151    @Override
152    public void setGrammarEndAllowed( boolean grammarEndAllowed )
153    {
154        this.grammarEndAllowed = grammarEndAllowed;
155    }
156
157
158    /**
159     * {@inheritDoc}
160     */
161    @Override
162    public Enum<?> getTransition()
163    {
164        return transition;
165    }
166
167
168    /**
169     * {@inheritDoc}
170     */
171    @Override
172    public void setTransition( Enum<?> transition )
173    {
174        this.transition = transition;
175    }
176
177
178    /**
179     * {@inheritDoc}
180     */
181    @Override
182    public void setCurrentTLV( TLV currentTLV )
183    {
184        this.tlv = currentTLV;
185    }
186
187
188    /**
189     * {@inheritDoc}
190     */
191    @Override
192    public TLV getCurrentTLV()
193    {
194        return this.tlv;
195    }
196
197
198    /**
199     * {@inheritDoc}
200     */
201    @Override
202    public TLV getParentTLV()
203    {
204        return parentTLV;
205    }
206
207
208    /**
209     * {@inheritDoc}
210     */
211    @Override
212    public void setParentTLV( TLV parentTLV )
213    {
214        this.parentTLV = parentTLV;
215    }
216
217
218    /**
219     * Clean the container for the next usage.
220     */
221    public void clean()
222    {
223        tlv = null;
224        parentTLV = null;
225        transition = ( ( States ) transition ).getStartState();
226        state = TLVStateEnum.TAG_STATE_START;
227    }
228
229
230    /**
231     * {@inheritDoc}
232     */
233    @Override
234    public int getNewTlvId()
235    {
236        return id++;
237    }
238
239
240    /**
241     * {@inheritDoc}
242     */
243    @Override
244    public int getTlvId()
245    {
246        return tlv.getId();
247    }
248
249
250    /**
251     * {@inheritDoc}
252     */
253    @Override
254    public int getDecodedBytes()
255    {
256        return decodedBytes;
257    }
258
259
260    /**
261     * {@inheritDoc}
262     */
263    @Override
264    public void setDecodedBytes( int decodedBytes )
265    {
266        this.decodedBytes = decodedBytes;
267    }
268
269
270    /**
271     * {@inheritDoc}
272     */
273    @Override
274    public void incrementDecodedBytes( int nb )
275    {
276        decodedBytes += nb;
277    }
278
279
280    /**
281     * {@inheritDoc}
282     */
283    @Override
284    public int getMaxPDUSize()
285    {
286        return maxPDUSize;
287    }
288
289
290    /**
291     * {@inheritDoc}
292     */
293    @Override
294    public void setMaxPDUSize( int maxPDUSize )
295    {
296        if ( maxPDUSize > 0 )
297        {
298            this.maxPDUSize = maxPDUSize;
299        }
300        else
301        {
302            this.maxPDUSize = Integer.MAX_VALUE;
303        }
304    }
305
306
307    /**
308     * {@inheritDoc}
309     */
310    @Override
311    public ByteBuffer getStream()
312    {
313        return stream;
314    }
315
316
317    /**
318     * {@inheritDoc}
319     */
320    @Override
321    public void setStream( ByteBuffer stream )
322    {
323        this.stream = stream;
324    }
325
326
327    /**
328     * {@inheritDoc}
329     */
330    @Override
331    public void rewind()
332    {
333        int start = stream.position() - 1 - tlv.getLengthNbBytes();
334        ( ( Buffer ) stream ).position( start );
335    }
336
337
338    /**
339     * {@inheritDoc}
340     */
341    @Override
342    public void updateParent()
343    {
344        TLV parentTlv = tlv.getParent();
345
346        while ( ( parentTlv != null ) && ( parentTlv.getExpectedLength() == 0 ) )
347        {
348            parentTlv = parentTlv.getParent();
349        }
350
351        this.parentTLV = parentTlv;
352    }
353
354
355    /**
356     * {@inheritDoc}
357     */
358    @Override
359    public boolean isGathering()
360    {
361        return gathering;
362    }
363
364
365    /**
366     * {@inheritDoc}
367     */
368    @Override
369    public void setGathering( boolean gathering )
370    {
371        this.gathering = gathering;
372    }
373
374}