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     */
020    package org.apache.directory.shared.asn1.ber;
021    
022    
023    import org.apache.directory.shared.asn1.ber.grammar.IGrammar;
024    import org.apache.directory.shared.asn1.ber.grammar.IStates;
025    import org.apache.directory.shared.asn1.ber.tlv.TLV;
026    import org.apache.directory.shared.asn1.ber.tlv.TLVStateEnum;
027    
028    
029    /**
030     * This class is the abstract container used to store the current state of a PDU
031     * being decoded. It also stores the grammars used to decode the PDU, and zll
032     * the informations needed to decode a PDU.
033     * 
034     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
035      * @version $Rev: 725712 $, $Date: 2008-12-11 16:32:04 +0100 (Thu, 11 Dec 2008) $
036    */
037    public class AbstractContainer implements IAsn1Container
038    {
039        // ~ Instance fields
040        // ----------------------------------------------------------------------------
041    
042        /** All the possible grammars */
043        protected IGrammar grammar;
044    
045        /** Store a stack of the current states used when switching grammars */
046        protected int[] stateStack;
047    
048        /** The current state of the decoding */
049        protected int state;
050    
051        /** The current transition */
052        protected int transition;
053    
054        /** The current TLV */
055        protected TLV tlv;
056    
057        /** Store the different states for debug purpose */
058        protected IStates states;
059    
060        /** The parent TLV */
061        protected TLV parentTLV;
062    
063        /** The grammar end transition flag */
064        protected boolean grammarEndAllowed;
065    
066        /** A counter for the decoded bytes */
067        protected int decodeBytes;
068    
069        /** The maximum allowed size for a PDU. Default to MAX int value */
070        protected int maxPDUSize = Integer.MAX_VALUE;
071    
072        /** The incremental id used to tag TLVs */
073        private int id = 0;
074        
075        // ~ Methods
076        // ------------------------------------------------------------------------------------
077    
078        /**
079         * Get the current grammar
080         * 
081         * @return Returns the grammar used to decode a LdapMessage.
082         */
083        public IGrammar getGrammar()
084        {
085            return grammar;
086        }
087    
088    
089        /**
090         * Get the current grammar state
091         * 
092         * @return Returns the current grammar state
093         */
094        public int getState()
095        {
096            return state;
097        }
098    
099    
100        /**
101         * Set the new current state
102         * 
103         * @param state The new state
104         */
105        public void setState( int state )
106        {
107            this.state = state;
108        }
109    
110    
111        /**
112         * Check that we can have a end state after this transition
113         * 
114         * @return true if this can be the last transition
115         */
116        public boolean isGrammarEndAllowed()
117        {
118            return grammarEndAllowed;
119        }
120    
121    
122        /**
123         * Set the flag to allow a end transition
124         * 
125         * @param grammarEndAllowed true or false, depending on the next transition
126         * being an end or not.
127         */
128        public void grammarEndAllowed( boolean grammarEndAllowed )
129        {
130            this.grammarEndAllowed = grammarEndAllowed;
131        }
132    
133    
134        /**
135         * Get the transition
136         * 
137         * @return Returns the transition from the previous state to the new state
138         */
139        public int getTransition()
140        {
141            return transition;
142        }
143    
144    
145        /**
146         * Update the transition from a state to another
147         * 
148         * @param transition The transition to set
149         */
150        public void setTransition( int transition )
151        {
152            this.transition = transition;
153        }
154    
155    
156        /**
157         * Set the current TLV
158         * 
159         * @param tlv The current TLV
160         */
161        public void setCurrentTLV( TLV tlv )
162        {
163            this.tlv = tlv;
164        }
165    
166    
167        /**
168         * Get the current TLV
169         * 
170         * @return Returns the current TLV being decoded
171         */
172        public TLV getCurrentTLV()
173        {
174            return this.tlv;
175        }
176    
177    
178        /**
179         * Get the states for this container's grammars
180         * 
181         * @return Returns the states.
182         */
183        public IStates getStates()
184        {
185            return states;
186        }
187    
188    
189        /**
190         * Get the parent TLV;
191         * 
192         * @return Returns the parent TLV, if any.
193         */
194        public TLV getParentTLV()
195        {
196            return parentTLV;
197        }
198    
199    
200        /**
201         * Set the parent TLV.
202         * 
203         * @param parentTLV The parent TLV to set.
204         */
205        public void setParentTLV( TLV parentTLV )
206        {
207            this.parentTLV = parentTLV;
208        }
209    
210    
211        /**
212         * Clean the container for the next usage.
213         */
214        public void clean()
215        {
216            tlv = null;
217            parentTLV = null;
218            transition = 0;
219            state = TLVStateEnum.TAG_STATE_START;
220        }
221        
222        /**
223         * Return a new ID and increment the counter
224         * @return A new TLV id. 
225         */
226        public int getNewTlvId()
227        {
228            return id++;
229        }
230    
231        /**
232         * @return The TLV Id
233         */
234        public int getTlvId()
235        {
236            return tlv.getId();
237        }
238    
239    
240        /**
241         * @return The number of decoded bytes for this message. This is used
242         * to control the PDU size and avoid PDU exceeding the maximum allowed
243         * size to break the server.
244         */
245        public int getDecodeBytes()
246        {
247            return decodeBytes;
248        }
249    
250    
251        /**
252         * Increment the decodedBytes by the latest received buffer's size.
253         * @param nb The buffer size.
254         */
255        public void incrementDecodeBytes( int nb )
256        {
257            decodeBytes += nb;
258        }
259        
260        
261        /**
262         * @return The maximum PDU size.
263         */
264        public int getMaxPDUSize()
265        {
266            return maxPDUSize;
267        }
268        
269        
270        /**
271         * Set the maximum PDU size.
272         * @param maxPDUSize The maximum PDU size (if negative or null, will be
273         * replaced by the max integer value)
274         */
275        public void setMaxPDUSize( int maxPDUSize )
276        {
277            if ( maxPDUSize > 0 )
278            {
279                this.maxPDUSize = maxPDUSize;
280            }
281            else
282            {
283                this.maxPDUSize = Integer.MAX_VALUE;
284            }
285        }
286    }