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    protected 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    protected int decodeBytes;
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 isGathering = 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    @SuppressWarnings("rawtypes")
101    public Grammar getGrammar()
102    {
103        return grammar;
104    }
105
106
107    /**
108     * {@inheritDoc}
109     */
110    public TLVStateEnum getState()
111    {
112        return state;
113    }
114
115
116    /**
117     * {@inheritDoc}
118     */
119    public void setState( TLVStateEnum state )
120    {
121        this.state = state;
122    }
123
124
125    /**
126     * {@inheritDoc}
127     */
128    public boolean isGrammarEndAllowed()
129    {
130        return grammarEndAllowed;
131    }
132
133
134    /**
135     * {@inheritDoc}
136     */
137    public void setGrammarEndAllowed( boolean grammarEndAllowed )
138    {
139        this.grammarEndAllowed = grammarEndAllowed;
140    }
141
142
143    /**
144     * {@inheritDoc}
145     */
146    public Enum<?> getTransition()
147    {
148        return transition;
149    }
150
151
152    /**
153     * {@inheritDoc}
154     */
155    public void setTransition( Enum<?> transition )
156    {
157        this.transition = transition;
158    }
159
160
161    /**
162     * {@inheritDoc}
163     */
164    public void setCurrentTLV( TLV currentTLV )
165    {
166        this.tlv = currentTLV;
167    }
168
169
170    /**
171     * {@inheritDoc}
172     */
173    public TLV getCurrentTLV()
174    {
175        return this.tlv;
176    }
177
178
179    /**
180     * {@inheritDoc}
181     */
182    public TLV getParentTLV()
183    {
184        return parentTLV;
185    }
186
187
188    /**
189     * {@inheritDoc}
190     */
191    public void setParentTLV( TLV parentTLV )
192    {
193        this.parentTLV = parentTLV;
194    }
195
196
197    /**
198     * Clean the container for the next usage.
199     */
200    public void clean()
201    {
202        tlv = null;
203        parentTLV = null;
204        transition = ( ( States ) transition ).getStartState();
205        state = TLVStateEnum.TAG_STATE_START;
206    }
207
208
209    /**
210     * {@inheritDoc}
211     */
212    public int getNewTlvId()
213    {
214        return id++;
215    }
216
217
218    /**
219     * {@inheritDoc}
220     */
221    public int getTlvId()
222    {
223        return tlv.getId();
224    }
225
226
227    /**
228     * {@inheritDoc}
229     */
230    public int getDecodeBytes()
231    {
232        return decodeBytes;
233    }
234
235
236    /**
237     * {@inheritDoc}
238     */
239    public void incrementDecodeBytes( int nb )
240    {
241        decodeBytes += nb;
242    }
243
244
245    /**
246     * {@inheritDoc}
247     */
248    public int getMaxPDUSize()
249    {
250        return maxPDUSize;
251    }
252
253
254    /**
255     * {@inheritDoc}
256     */
257    public void setMaxPDUSize( int maxPDUSize )
258    {
259        if ( maxPDUSize > 0 )
260        {
261            this.maxPDUSize = maxPDUSize;
262        }
263        else
264        {
265            this.maxPDUSize = Integer.MAX_VALUE;
266        }
267    }
268
269
270    /**
271     * {@inheritDoc}
272     */
273    public ByteBuffer getStream()
274    {
275        return stream;
276    }
277
278
279    /**
280     * {@inheritDoc}
281     */
282    public void setStream( ByteBuffer stream )
283    {
284        this.stream = stream;
285    }
286
287
288    /**
289     * {@inheritDoc}
290     */
291    public void rewind()
292    {
293
294        int start = stream.position() - 1 - tlv.getLengthNbBytes();
295        stream.position( start );
296    }
297
298
299    /**
300     * {@inheritDoc}
301     */
302    public void updateParent()
303    {
304        TLV parentTlv = tlv.getParent();
305
306        while ( ( parentTlv != null ) && ( parentTlv.getExpectedLength() == 0 ) )
307        {
308            parentTlv = parentTlv.getParent();
309        }
310
311        this.parentTLV = parentTlv;
312    }
313
314
315    /**
316     * {@inheritDoc}
317     */
318    public boolean isGathering()
319    {
320        return isGathering;
321    }
322
323
324    /**
325     * {@inheritDoc}
326     */
327    public void setGathering( boolean isGathering )
328    {
329        this.isGathering = isGathering;
330    }
331
332}