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.shared.asn1.ber; 021 022 023import java.nio.ByteBuffer; 024 025import org.apache.directory.shared.asn1.ber.grammar.Grammar; 026import org.apache.directory.shared.asn1.ber.grammar.States; 027import org.apache.directory.shared.asn1.ber.tlv.TLV; 028import org.apache.directory.shared.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 /** Store a stack of the current states used when switching grammars */ 044 protected int[] stateStack; 045 046 /** The current state of the decoding */ 047 private TLVStateEnum state; 048 049 /** The current transition */ 050 private Enum<?> transition; 051 052 /** The current TLV */ 053 private TLV tlv; 054 055 /** The parent TLV */ 056 private TLV parentTLV; 057 058 /** The grammar end transition flag */ 059 private boolean grammarEndAllowed; 060 061 /** A counter for the decoded bytes */ 062 protected int decodeBytes; 063 064 /** The maximum allowed size for a PDU. Default to MAX int value */ 065 private int maxPDUSize = Integer.MAX_VALUE; 066 067 /** The incremental id used to tag TLVs */ 068 private int id = 0; 069 070 /** The Stream being decoded */ 071 private ByteBuffer stream; 072 073 /** A flag telling if the Value should be accumulated before being decoded 074 * for constructed types */ 075 private boolean isGathering = false; 076 077 /** 078 * Creates a new instance of AbstractContainer with a starting state. 079 * 080 */ 081 protected AbstractContainer() 082 { 083 state = TLVStateEnum.TAG_STATE_START; 084 } 085 086 087 /** 088 * Creates a new instance of AbstractContainer with a starting state. 089 * 090 * @param stream the buffer containing the data to decode 091 */ 092 protected AbstractContainer( ByteBuffer stream ) 093 { 094 state = TLVStateEnum.TAG_STATE_START; 095 this.stream = stream; 096 } 097 098 099 /** 100 * Get the current grammar 101 * 102 * @return Returns the grammar used to decode a LdapMessage. 103 */ 104 public Grammar<?> getGrammar() 105 { 106 return grammar; 107 } 108 109 110 /** 111 * Get the current grammar state 112 * 113 * @return Returns the current grammar state 114 */ 115 public TLVStateEnum getState() 116 { 117 return state; 118 } 119 120 121 /** 122 * Set the new current state 123 * 124 * @param state The new state 125 */ 126 public void setState( TLVStateEnum state ) 127 { 128 this.state = state; 129 } 130 131 132 /** 133 * Check that we can have a end state after this transition 134 * 135 * @return true if this can be the last transition 136 */ 137 public boolean isGrammarEndAllowed() 138 { 139 return grammarEndAllowed; 140 } 141 142 143 /** 144 * Set the flag to allow a end transition 145 * 146 * @param grammarEndAllowed true or false, depending on the next transition 147 * being an end or not. 148 */ 149 public void setGrammarEndAllowed( boolean grammarEndAllowed ) 150 { 151 this.grammarEndAllowed = grammarEndAllowed; 152 } 153 154 155 /** 156 * Get the transition 157 * 158 * @return Returns the transition from the previous state to the new state 159 */ 160 public Enum<?> getTransition() 161 { 162 return transition; 163 } 164 165 166 /** 167 * Update the transition from a state to another 168 * 169 * @param transition The transition to set 170 */ 171 public void setTransition( Enum<?> transition ) 172 { 173 this.transition = transition; 174 } 175 176 177 /** 178 * Set the current TLV 179 * 180 * @param currentTLV The current TLV 181 */ 182 public void setCurrentTLV( TLV currentTLV ) 183 { 184 this.tlv = currentTLV; 185 } 186 187 188 /** 189 * Get the current TLV 190 * 191 * @return Returns the current TLV being decoded 192 */ 193 public TLV getCurrentTLV() 194 { 195 return this.tlv; 196 } 197 198 199 /** 200 * Get the parent TLV; 201 * 202 * @return Returns the parent TLV, if any. 203 */ 204 public TLV getParentTLV() 205 { 206 return parentTLV; 207 } 208 209 210 /** 211 * Set the parent TLV. 212 * 213 * @param parentTLV The parent TLV to set. 214 */ 215 public void setParentTLV( TLV parentTLV ) 216 { 217 this.parentTLV = parentTLV; 218 } 219 220 221 /** 222 * Clean the container for the next usage. 223 */ 224 public void clean() 225 { 226 tlv = null; 227 parentTLV = null; 228 transition = ( ( States ) transition ).getStartState(); 229 state = TLVStateEnum.TAG_STATE_START; 230 } 231 232 233 /** 234 * Return a new ID and increment the counter 235 * @return A new TLV id. 236 */ 237 public int getNewTlvId() 238 { 239 return id++; 240 } 241 242 243 /** 244 * @return The TLV Id 245 */ 246 public int getTlvId() 247 { 248 return tlv.getId(); 249 } 250 251 252 /** 253 * @return The number of decoded bytes for this message. This is used 254 * to control the PDU size and avoid PDU exceeding the maximum allowed 255 * size to break the server. 256 */ 257 public int getDecodeBytes() 258 { 259 return decodeBytes; 260 } 261 262 263 /** 264 * Increment the decodedBytes by the latest received buffer's size. 265 * @param nb The buffer size. 266 */ 267 public void incrementDecodeBytes( int nb ) 268 { 269 decodeBytes += nb; 270 } 271 272 273 /** 274 * @return The maximum PDU size. 275 */ 276 public int getMaxPDUSize() 277 { 278 return maxPDUSize; 279 } 280 281 282 /** 283 * Set the maximum PDU size. 284 * @param maxPDUSize The maximum PDU size (if negative or null, will be 285 * replaced by the max integer value) 286 */ 287 public void setMaxPDUSize( int maxPDUSize ) 288 { 289 if ( maxPDUSize > 0 ) 290 { 291 this.maxPDUSize = maxPDUSize; 292 } 293 else 294 { 295 this.maxPDUSize = Integer.MAX_VALUE; 296 } 297 } 298 299 300 /** 301 * {@inheritDoc} 302 */ 303 public ByteBuffer getStream() 304 { 305 return stream; 306 } 307 308 309 /** 310 * {@inheritDoc} 311 */ 312 public void setStream( ByteBuffer stream ) 313 { 314 this.stream = stream; 315 } 316 317 318 /** 319 * {@inheritDoc} 320 */ 321 public void rewind() 322 { 323 324 int start = stream.position() - 1 - tlv.getLengthNbBytes(); 325 stream.position( start ); 326 } 327 328 329 /** 330 * {@inheritDoc} 331 */ 332 public void updateParent() 333 { 334 TLV parentTlv = tlv.getParent(); 335 336 while ( ( parentTlv != null ) && ( parentTlv.getExpectedLength() == 0 ) ) 337 { 338 parentTlv = parentTlv.getParent(); 339 } 340 341 this.parentTLV = parentTlv; 342 } 343 344 345 /** 346 * {@inheritDoc} 347 */ 348 public boolean isGathering() 349 { 350 return isGathering; 351 } 352 353 354 /** 355 * {@inheritDoc} 356 */ 357 public void setGathering( boolean isGathering ) 358 { 359 this.isGathering = isGathering; 360 } 361 362}