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 *    http://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.ByteBuffer;
024
025import org.apache.directory.api.asn1.ber.grammar.Grammar;
026import org.apache.directory.api.asn1.ber.grammar.States;
027import org.apache.directory.api.asn1.ber.tlv.TLV;
028import org.apache.directory.api.asn1.ber.tlv.TLVStateEnum;
029
030
031/**
032 * This class is the abstract container used to store the current state of a PDU
033 * being decoded. It also stores the grammars used to decode the PDU, and all
034 * the informations needed to decode a PDU.
035 *
036 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
037 */
038public abstract class AbstractContainer implements Asn1Container
039{
040    /** All the possible grammars */
041    private Grammar<?> grammar;
042
043    /** The current state of the decoding */
044    private TLVStateEnum state;
045
046    /** The current transition */
047    private Enum<?> transition;
048
049    /** The current TLV */
050    private TLV tlv;
051
052    /** The parent TLV */
053    private TLV parentTLV;
054
055    /** The grammar end transition flag */
056    private boolean grammarEndAllowed;
057
058    /** A counter for the decoded bytes */
059    private int decodedBytes;
060
061    /** The maximum allowed size for a PDU. Default to MAX int value */
062    private int maxPDUSize = Integer.MAX_VALUE;
063
064    /** The incremental id used to tag TLVs */
065    private int id = 0;
066
067    /** The Stream being decoded */
068    private ByteBuffer stream;
069
070    /** A flag telling if the Value should be accumulated before being decoded
071     * for constructed types */
072    private boolean gathering = false;
073
074
075    /**
076     * Creates a new instance of AbstractContainer with a starting state.
077     *
078     */
079    protected AbstractContainer()
080    {
081        state = TLVStateEnum.TAG_STATE_START;
082    }
083
084
085    /**
086     * Creates a new instance of AbstractContainer with a starting state.
087     *
088     * @param stream the buffer containing the data to decode
089     */
090    protected AbstractContainer( ByteBuffer stream )
091    {
092        state = TLVStateEnum.TAG_STATE_START;
093        this.stream = stream;
094    }
095
096
097    /**
098     * {@inheritDoc}
099     */
100    @Override
101    public Grammar<?> getGrammar()
102    {
103        return grammar;
104    }
105
106
107    /**
108     * {@inheritDoc}
109     */
110    @Override
111    public void setGrammar( Grammar<?> grammar )
112    {
113        this.grammar = grammar;
114    }
115
116
117    /**
118     * {@inheritDoc}
119     */
120    @Override
121    public TLVStateEnum getState()
122    {
123        return state;
124    }
125
126
127    /**
128     * {@inheritDoc}
129     */
130    @Override
131    public void setState( TLVStateEnum state )
132    {
133        this.state = state;
134    }
135
136
137    /**
138     * {@inheritDoc}
139     */
140    @Override
141    public boolean isGrammarEndAllowed()
142    {
143        return grammarEndAllowed;
144    }
145
146
147    /**
148     * {@inheritDoc}
149     */
150    @Override
151    public void setGrammarEndAllowed( boolean grammarEndAllowed )
152    {
153        this.grammarEndAllowed = grammarEndAllowed;
154    }
155
156
157    /**
158     * {@inheritDoc}
159     */
160    @Override
161    public Enum<?> getTransition()
162    {
163        return transition;
164    }
165
166
167    /**
168     * {@inheritDoc}
169     */
170    @Override
171    public void setTransition( Enum<?> transition )
172    {
173        this.transition = transition;
174    }
175
176
177    /**
178     * {@inheritDoc}
179     */
180    @Override
181    public void setCurrentTLV( TLV currentTLV )
182    {
183        this.tlv = currentTLV;
184    }
185
186
187    /**
188     * {@inheritDoc}
189     */
190    @Override
191    public TLV getCurrentTLV()
192    {
193        return this.tlv;
194    }
195
196
197    /**
198     * {@inheritDoc}
199     */
200    @Override
201    public TLV getParentTLV()
202    {
203        return parentTLV;
204    }
205
206
207    /**
208     * {@inheritDoc}
209     */
210    @Override
211    public void setParentTLV( TLV parentTLV )
212    {
213        this.parentTLV = parentTLV;
214    }
215
216
217    /**
218     * Clean the container for the next usage.
219     */
220    public void clean()
221    {
222        tlv = null;
223        parentTLV = null;
224        transition = ( ( States ) transition ).getStartState();
225        state = TLVStateEnum.TAG_STATE_START;
226    }
227
228
229    /**
230     * {@inheritDoc}
231     */
232    @Override
233    public int getNewTlvId()
234    {
235        return id++;
236    }
237
238
239    /**
240     * {@inheritDoc}
241     */
242    @Override
243    public int getTlvId()
244    {
245        return tlv.getId();
246    }
247
248
249    /**
250     * {@inheritDoc}
251     */
252    @Override
253    public int getDecodedBytes()
254    {
255        return decodedBytes;
256    }
257
258
259    /**
260     * {@inheritDoc}
261     */
262    @Override
263    public void setDecodedBytes( int decodedBytes )
264    {
265        this.decodedBytes = decodedBytes;
266    }
267
268
269    /**
270     * {@inheritDoc}
271     */
272    @Override
273    public void incrementDecodedBytes( int nb )
274    {
275        decodedBytes += nb;
276    }
277
278
279    /**
280     * {@inheritDoc}
281     */
282    @Override
283    public int getMaxPDUSize()
284    {
285        return maxPDUSize;
286    }
287
288
289    /**
290     * {@inheritDoc}
291     */
292    @Override
293    public void setMaxPDUSize( int maxPDUSize )
294    {
295        if ( maxPDUSize > 0 )
296        {
297            this.maxPDUSize = maxPDUSize;
298        }
299        else
300        {
301            this.maxPDUSize = Integer.MAX_VALUE;
302        }
303    }
304
305
306    /**
307     * {@inheritDoc}
308     */
309    @Override
310    public ByteBuffer getStream()
311    {
312        return stream;
313    }
314
315
316    /**
317     * {@inheritDoc}
318     */
319    @Override
320    public void setStream( ByteBuffer stream )
321    {
322        this.stream = stream;
323    }
324
325
326    /**
327     * {@inheritDoc}
328     */
329    @Override
330    public void rewind()
331    {
332
333        int start = stream.position() - 1 - tlv.getLengthNbBytes();
334        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}