| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| package org.apache.directory.shared.asn1.ber; |
| |
| |
| import java.nio.ByteBuffer; |
| |
| import org.apache.directory.shared.asn1.ber.grammar.Grammar; |
| import org.apache.directory.shared.asn1.ber.grammar.States; |
| import org.apache.directory.shared.asn1.ber.tlv.TLV; |
| import org.apache.directory.shared.asn1.ber.tlv.TLVStateEnum; |
| |
| |
| /** |
| * This class is the abstract container used to store the current state of a PDU |
| * being decoded. It also stores the grammars used to decode the PDU, and all |
| * the informations needed to decode a PDU. |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| */ |
| public abstract class AbstractContainer implements Asn1Container |
| { |
| /** All the possible grammars */ |
| protected Grammar<?> grammar; |
| |
| /** Store a stack of the current states used when switching grammars */ |
| protected int[] stateStack; |
| |
| /** The current state of the decoding */ |
| private TLVStateEnum state; |
| |
| /** The current transition */ |
| private Enum<?> transition; |
| |
| /** The current TLV */ |
| private TLV tlv; |
| |
| /** The parent TLV */ |
| private TLV parentTLV; |
| |
| /** The grammar end transition flag */ |
| private boolean grammarEndAllowed; |
| |
| /** A counter for the decoded bytes */ |
| protected int decodeBytes; |
| |
| /** The maximum allowed size for a PDU. Default to MAX int value */ |
| private int maxPDUSize = Integer.MAX_VALUE; |
| |
| /** The incremental id used to tag TLVs */ |
| private int id = 0; |
| |
| /** The Stream being decoded */ |
| private ByteBuffer stream; |
| |
| /** A flag telling if the Value should be accumulated before being decoded |
| * for constructed types */ |
| private boolean isGathering = false; |
| |
| /** |
| * Creates a new instance of AbstractContainer with a starting state. |
| * |
| */ |
| protected AbstractContainer() |
| { |
| state = TLVStateEnum.TAG_STATE_START; |
| } |
| |
| |
| /** |
| * Creates a new instance of AbstractContainer with a starting state. |
| * |
| * @param stream the buffer containing the data to decode |
| */ |
| protected AbstractContainer( ByteBuffer stream ) |
| { |
| state = TLVStateEnum.TAG_STATE_START; |
| this.stream = stream; |
| } |
| |
| |
| /** |
| * Get the current grammar |
| * |
| * @return Returns the grammar used to decode a LdapMessage. |
| */ |
| public Grammar<?> getGrammar() |
| { |
| return grammar; |
| } |
| |
| |
| /** |
| * Get the current grammar state |
| * |
| * @return Returns the current grammar state |
| */ |
| public TLVStateEnum getState() |
| { |
| return state; |
| } |
| |
| |
| /** |
| * Set the new current state |
| * |
| * @param state The new state |
| */ |
| public void setState( TLVStateEnum state ) |
| { |
| this.state = state; |
| } |
| |
| |
| /** |
| * Check that we can have a end state after this transition |
| * |
| * @return true if this can be the last transition |
| */ |
| public boolean isGrammarEndAllowed() |
| { |
| return grammarEndAllowed; |
| } |
| |
| |
| /** |
| * Set the flag to allow a end transition |
| * |
| * @param grammarEndAllowed true or false, depending on the next transition |
| * being an end or not. |
| */ |
| public void setGrammarEndAllowed( boolean grammarEndAllowed ) |
| { |
| this.grammarEndAllowed = grammarEndAllowed; |
| } |
| |
| |
| /** |
| * Get the transition |
| * |
| * @return Returns the transition from the previous state to the new state |
| */ |
| public Enum<?> getTransition() |
| { |
| return transition; |
| } |
| |
| |
| /** |
| * Update the transition from a state to another |
| * |
| * @param transition The transition to set |
| */ |
| public void setTransition( Enum<?> transition ) |
| { |
| this.transition = transition; |
| } |
| |
| |
| /** |
| * Set the current TLV |
| * |
| * @param currentTLV The current TLV |
| */ |
| public void setCurrentTLV( TLV currentTLV ) |
| { |
| this.tlv = currentTLV; |
| } |
| |
| |
| /** |
| * Get the current TLV |
| * |
| * @return Returns the current TLV being decoded |
| */ |
| public TLV getCurrentTLV() |
| { |
| return this.tlv; |
| } |
| |
| |
| /** |
| * Get the parent TLV; |
| * |
| * @return Returns the parent TLV, if any. |
| */ |
| public TLV getParentTLV() |
| { |
| return parentTLV; |
| } |
| |
| |
| /** |
| * Set the parent TLV. |
| * |
| * @param parentTLV The parent TLV to set. |
| */ |
| public void setParentTLV( TLV parentTLV ) |
| { |
| this.parentTLV = parentTLV; |
| } |
| |
| |
| /** |
| * Clean the container for the next usage. |
| */ |
| public void clean() |
| { |
| tlv = null; |
| parentTLV = null; |
| transition = ( ( States ) transition ).getStartState(); |
| state = TLVStateEnum.TAG_STATE_START; |
| } |
| |
| |
| /** |
| * Return a new ID and increment the counter |
| * @return A new TLV id. |
| */ |
| public int getNewTlvId() |
| { |
| return id++; |
| } |
| |
| |
| /** |
| * @return The TLV Id |
| */ |
| public int getTlvId() |
| { |
| return tlv.getId(); |
| } |
| |
| |
| /** |
| * @return The number of decoded bytes for this message. This is used |
| * to control the PDU size and avoid PDU exceeding the maximum allowed |
| * size to break the server. |
| */ |
| public int getDecodeBytes() |
| { |
| return decodeBytes; |
| } |
| |
| |
| /** |
| * Increment the decodedBytes by the latest received buffer's size. |
| * @param nb The buffer size. |
| */ |
| public void incrementDecodeBytes( int nb ) |
| { |
| decodeBytes += nb; |
| } |
| |
| |
| /** |
| * @return The maximum PDU size. |
| */ |
| public int getMaxPDUSize() |
| { |
| return maxPDUSize; |
| } |
| |
| |
| /** |
| * Set the maximum PDU size. |
| * @param maxPDUSize The maximum PDU size (if negative or null, will be |
| * replaced by the max integer value) |
| */ |
| public void setMaxPDUSize( int maxPDUSize ) |
| { |
| if ( maxPDUSize > 0 ) |
| { |
| this.maxPDUSize = maxPDUSize; |
| } |
| else |
| { |
| this.maxPDUSize = Integer.MAX_VALUE; |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public ByteBuffer getStream() |
| { |
| return stream; |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void setStream( ByteBuffer stream ) |
| { |
| this.stream = stream; |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void rewind() |
| { |
| |
| int start = stream.position() - 1 - tlv.getLengthNbBytes(); |
| stream.position( start ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void updateParent() |
| { |
| TLV parentTlv = tlv.getParent(); |
| |
| while ( ( parentTlv != null ) && ( parentTlv.getExpectedLength() == 0 ) ) |
| { |
| parentTlv = parentTlv.getParent(); |
| } |
| |
| this.parentTLV = parentTlv; |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public boolean isGathering() |
| { |
| return isGathering; |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void setGathering( boolean isGathering ) |
| { |
| this.isGathering = isGathering; |
| } |
| |
| } |