From directory-cvs-return-551-apmail-incubator-directory-cvs-archive=incubator.apache.org@incubator.apache.org Mon Mar 15 22:31:43 2004 Return-Path: Delivered-To: apmail-incubator-directory-cvs-archive@www.apache.org Received: (qmail 69535 invoked from network); 15 Mar 2004 22:31:42 -0000 Received: from daedalus.apache.org (HELO mail.apache.org) (208.185.179.12) by minotaur-2.apache.org with SMTP; 15 Mar 2004 22:31:42 -0000 Received: (qmail 9956 invoked by uid 500); 15 Mar 2004 22:31:29 -0000 Delivered-To: apmail-incubator-directory-cvs-archive@incubator.apache.org Received: (qmail 9912 invoked by uid 500); 15 Mar 2004 22:31:29 -0000 Mailing-List: contact directory-cvs-help@incubator.apache.org; run by ezmlm Precedence: bulk Reply-To: directory-dev@incubator.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list directory-cvs@incubator.apache.org Received: (qmail 9895 invoked from network); 15 Mar 2004 22:31:27 -0000 Received: from unknown (HELO minotaur.apache.org) (209.237.227.194) by daedalus.apache.org with SMTP; 15 Mar 2004 22:31:27 -0000 Received: (qmail 69466 invoked by uid 65534); 15 Mar 2004 22:31:40 -0000 Date: 15 Mar 2004 22:31:40 -0000 Message-ID: <20040315223140.69463.qmail@minotaur.apache.org> From: akarasulu@apache.org To: directory-cvs@incubator.apache.org Subject: svn commit: rev 9495 - incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N Author: akarasulu Date: Mon Mar 15 14:31:39 2004 New Revision: 9495 Modified: incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/AbstractDecoderTestCase.java incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/BERDecoder.java incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/BERDecoderCallback.java incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/BERDecoderMonitor.java incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/DefaultMutableTupleNode.java incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/Length.java (contents, props changed) incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/LengthDecoder.java (contents, props changed) incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/MutableTupleNode.java incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/Tag.java (contents, props changed) incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/TagDecoder.java incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/TupleNode.java incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/TupleTreeDecoder.java Log: o Basically broke down the BERDecoder into separate stateful decoders which are used by the BERDecoder when it switches its state from reading a tag, length and on to a value. The code is much easier to handle and several old bugs are no longer present. The decoder overall works like a champion. o Clover shows green all over and the code has been cleaned up along with internal documentation - javadocs. o Added equals comparison functionality to TLV TupleNodes. We're ready to merge back this code now to the main trunk. Modified: incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/AbstractDecoderTestCase.java ============================================================================== --- incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/AbstractDecoderTestCase.java (original) +++ incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/AbstractDecoderTestCase.java Mon Mar 15 14:31:39 2004 @@ -57,7 +57,7 @@ protected void setUp() throws Exception { super.setUp() ; - decoder = new BERDecoder() ; + decoder = new BERDecoder( 1024 ) ; decoder.setCallback( this ) ; decoder.setDecoderMonitor( this ) ; } @@ -277,6 +277,20 @@ decode( encoder.encode( msg ) ) ; return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ; + } + + + /** + * Convenience method used to encode a msg using the Snacc libraries for + * the time being. + * + * @param msg the message to encode + * @return a byte buffer with the encoded message + */ + public ByteBuffer encode( Message msg ) + { + MessageEncoder encoder = new MessageEncoder() ; + return ByteBuffer.wrap( encoder.encode( msg ) ) ; } Modified: incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/BERDecoder.java ============================================================================== --- incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/BERDecoder.java (original) +++ incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/BERDecoder.java Mon Mar 15 14:31:39 2004 @@ -21,13 +21,13 @@ import java.nio.ByteBuffer ; -import org.apache.commons.codec.binary.Binary ; +import org.apache.commons.lang.ArrayUtils ; + import org.apache.commons.codec.DecoderException ; import org.apache.commons.codec.stateful.DecoderMonitor ; import org.apache.commons.codec.stateful.DecoderCallback ; import org.apache.commons.codec.stateful.StatefulDecoder ; import org.apache.commons.codec.stateful.DecoderMonitorAdapter ; -import org.apache.commons.collections.primitives.ArrayByteList ; /** @@ -56,7 +56,7 @@ * Apache Directory Project * @version $Rev$ */ -public class BERDecoder implements StatefulDecoder +public class BERDecoder implements StatefulDecoder, DecoderCallback { public static final BERDecoderCallback DEFAULT_CALLBACK = new BERDecoderCallbackAdapter() ; @@ -71,21 +71,33 @@ /** the single TLV tuple used by this decoder */ private final Tuple tlv = new Tuple() ; - /** a byte buffer used to collect the arriving tag octets */ - private final ArrayByteList tagBuffer = new ArrayByteList( 10 ) ; - /** a byte buffer used to collect the arriving legth octets */ - private final ArrayByteList lengthBuffer = new ArrayByteList( 10 ) ; - + /** a decoder used to decode tag octets */ + private final TagDecoder tagDecoder = new TagDecoder() ; + /** a decoder used to decode length octets */ + private final LengthDecoder lengthDecoder = new LengthDecoder() ; + /** a place to store value data - this is reused */ + private final ByteBuffer buffer ; + /** stack of nested/constructed TLV tuples */ private final Stack tlvStack = new Stack() ; - /** the length of the length data */ - private int lengthOfLength = 0 ; - /** the state of this decoder */ private BERDecoderState state = BERDecoderState.getStartState() ; + /** + * Creates a stateful BER decoder which limits the tuple's value size. + * + * @param valueMax the maximum tuple value size handled by this decoder + */ + public BERDecoder( int valueMax ) + { + tagDecoder.setCallback( this ) ; + lengthDecoder.setCallback( this ) ; + buffer = ByteBuffer.allocate( valueMax ) ; + } + + // ------------------------------------------------------------------------ // StatefulDecoder Methods // ------------------------------------------------------------------------ @@ -133,10 +145,10 @@ switch( state.getValue() ) { case( BERDecoderState.TAG_VAL ): - decodeTag( buf ) ; + tagDecoder.decode( buf ) ; break ; case( BERDecoderState.LENGTH_VAL ): - decodeLength( buf ) ; + lengthDecoder.decode( buf ) ; break ; case( BERDecoderState.VALUE_VAL ): decodeValue( buf ) ; @@ -172,161 +184,6 @@ /** - * Extracts the TLV's tag portion from the buffer. - * - * @param buf the byte byffer containing BER encoded data - */ - private void decodeTag( ByteBuffer buf ) throws DecoderException - { - for ( tlv.index = 0; buf.hasRemaining(); tlv.index++ ) - { - byte octet = buf.get() ; - tagBuffer.add( octet ) ; - - if ( tagBuffer.size() == 1 ) - { - int id = Tag.SHORT_MASK & octet ; - tlv.isPrimitive = Tag.isPrimitive( octet ) ; - tlv.typeClass = TypeClass.getTypeClass( octet ) ; - - // continue to collect more octets if this is the long Tag form - if ( id == Tag.SHORT_MASK ) - { - continue ; - } - - // its the short form so we get the id, switch state & return - tlv.id = id ; - fireTagDecoded() ; - state = state.getNext( tlv.isPrimitive ) ; - - // we moved by one byte so we update stack indices by 1 - updateStack( 1 ) ; - return ; - } - - /* - * From here on we're dealing with the long form of the tag. The - * terminating octet for the long form uses a raised most - * significant bit to flag the end of the train of octets for the - * tag id. - */ - if ( ( octet & Binary.BIT_7 ) == 0 ) - { - tlv.id = Tag.getTagId( tagBuffer ) ; - fireTagDecoded() ; - state = state.getNext( tlv.isPrimitive ) ; - - // we moved by many bytes so we update stack accordingly - updateStack( tagBuffer.size() ) ; - return ; - } - } - } - - - /** - * Extracts the length portion from the buffer. - * - * @param buf the byte byffer containing BER encoded data - */ - private void decodeLength( ByteBuffer buf ) throws DecoderException - { - while ( buf.hasRemaining() ) - { - tlv.index++ ; - byte octet = buf.get() ; - lengthBuffer.add( octet ) ; - - if ( lengthBuffer.size() == 1 ) - { - lengthOfLength = octet & Tag.LONG_MASK ; - - // handle the short form of the length here - if ( ( octet & Binary.BIT_7 ) == 0 ) - { - lengthOfLength = 0 ; - tlv.length = octet ; - tlv.valueIndex = Length.UNDEFINED ; - - if ( tlv.isPrimitive ) - { - tlv.value = new byte[tlv.length] ; - fireLengthDecoded() ; - state = BERDecoderState.VALUE ; - // we moved by one byte so we update stack indices by 1 - updateStack( 1 ) ; - } - else - { - // We moved by one byte so we update stack indices by 1 - // need to do this here so we do not double update the - // current tuple after pushing it onto the stack. - updateStack( 1 ) ; - - tlvStack.push( tlv.clone() ) ; - fireLengthDecoded() ; - tlv.clear() ; - state = BERDecoderState.TAG ; - } - - handleIndefinateTerminator() ; - return ; - } - // the indefinate form of the length - else if ( lengthOfLength == 0 ) - { - lengthOfLength = Length.INDEFINATE ; - tlv.index = Length.INDEFINATE ; - tlv.length = Length.INDEFINATE ; - tlv.valueIndex = Length.UNDEFINED ; - fireLengthDecoded() ; - tlvStack.push( tlv.clone() ) ; - tlv.clear() ; - state = BERDecoderState.TAG ; - - // we moved by one byte so we update stack indices by 1 - updateStack( 1 ) ; - return ; - } - } - - /* - * if we have collected all the octets needed for computing the long - * form length so we need to calculate the length push it and return - */ - if ( lengthBuffer.size() == lengthOfLength + 1 ) - { - lengthOfLength = 0 ; - tlv.length = Length.getLength( lengthBuffer ) ; - tlv.valueIndex = Length.UNDEFINED ; - - if ( tlv.isPrimitive ) - { - tlv.value = new byte[tlv.length] ; - fireLengthDecoded() ; - state = BERDecoderState.VALUE ; - } - else - { - tlvStack.push( tlv.clone() ) ; - fireLengthDecoded() ; - tlv.clear() ; - state = BERDecoderState.TAG ; - } - - /* - * we moved by one byte + lengthOfLength so we update stack - * indices by lengthOfLength + 1 - */ - updateStack( lengthOfLength + 1 ) ; - return ; - } - } - } - - - /** * Extracts the value portion from the buffer for a primitive type. * * @param buf the byte byffer containing BER encoded data @@ -337,28 +194,6 @@ int offset = Length.UNDEFINED ; int needToRead = Length.UNDEFINED ; - if ( ! tlv.isPrimitive ) - { - IllegalStateException e = new IllegalStateException( - "should only be working with primitive tlv" ) ; - - if ( monitor == null ) - { - throw e ; - } - else - { - monitor.fatalError( this, e ) ; - } - - return ; - } - - if ( ! buf.hasRemaining() ) - { - return ; - } - /* * setup to start decoding the value */ @@ -381,7 +216,8 @@ { buf.get( value, offset, needToRead ) ; tlv.valueIndex = tlv.length ; - tlv.index += needToRead ; + tlv.index += tlv.length ; + fireDecodeOccurred( tlv ) ; updateStack( needToRead ) ; tlv.clear() ; @@ -403,11 +239,89 @@ int remaining = buf.remaining() ; buf.get( value, offset, remaining ) ; tlv.valueIndex += remaining ; + tlv.index +=remaining ; + updateStack( remaining ) ; } } + + /* (non-Javadoc) + * @see org.apache.commons.codec.stateful.DecoderCallback#decodeOccurred( + * org.apache.commons.codec.stateful.StatefulDecoder, java.lang.Object) + */ + public void decodeOccurred( StatefulDecoder decoder, Object decoded ) + { + if ( decoder == tagDecoder ) + { + Tag tag = ( Tag ) decoded ; + tlv.id = tag.getId() ; + tlv.isPrimitive = tag.isPrimitive() ; + tlv.typeClass = tag.getTypeClass() ; + tlv.index = tag.size() ; + + fireTagDecoded() ; + updateStack( tag.size() ) ; + state = state.getNext( tag.isPrimitive() ) ; + } + else if ( decoder == lengthDecoder ) + { + Length length = ( Length ) decoded ; + tlv.length = length.getLength() ; + + if ( tlv.length == Length.INDEFINATE ) + { + tlv.index = Length.INDEFINATE ; + tlv.valueIndex = Length.INDEFINATE ; + } + else + { + tlv.index += length.size() ; + } + + fireLengthDecoded() ; + updateStack( length.size() ) ; + + + + if ( ! tlv.isPrimitive ) + { + if ( tlv.isIndefinate() || tlv.length > 0 ) + { + tlvStack.push( tlv.clone() ) ; + } + else + { + state = BERDecoderState.VALUE ; + fireDecodeOccurred( tlv ) ; + } + + state = BERDecoderState.TAG ; + tlv.clear() ; + } + else if ( tlv.isIndefinateTerminator() ) + { + return ; + } + else if ( tlv.length > 0 ) + { + tlv.value = new byte[tlv.length] ; + state = BERDecoderState.VALUE ; + } + else + { + tlv.value = ArrayUtils.EMPTY_BYTE_ARRAY ; + state = BERDecoderState.VALUE ; + } + } + else + { + throw new IllegalArgumentException( "unrecognized decoder" ) ; + } + } + + // ------------------------------------------------------------------------ // private utility methods // ------------------------------------------------------------------------ @@ -431,10 +345,8 @@ if ( monitor != null && monitor instanceof BERDecoderMonitor ) { BERDecoderMonitor berMonitor = ( BERDecoderMonitor ) monitor ; - berMonitor.tagDecoded( tlv, tagBuffer.toArray() ) ; + //berMonitor.tagDecoded( tlv, tagDecoder.getOctets() ) ; } - - tagBuffer.clear() ; } @@ -456,10 +368,8 @@ if ( monitor != null && monitor instanceof BERDecoderMonitor ) { BERDecoderMonitor berMonitor = ( BERDecoderMonitor ) monitor ; - berMonitor.lengthDecoded( tlv, lengthBuffer.toArray() ) ; + //berMonitor.lengthDecoded( tlv, lengthBuffer.toArray() ) ; } - - lengthBuffer.clear() ; } @@ -491,6 +401,11 @@ for ( int ii = 0; ii < tlvStack.size(); ii++ ) { Tuple t = ( Tuple ) tlvStack.get( ii ) ; + + if ( t.isIndefinate() ) + { + continue ; + } t.index += increment ; @@ -510,74 +425,33 @@ do { Tuple top = ( Tuple ) tlvStack.peek() ; - - if ( top.isIndefinate() ) + + if ( top.isIndefinate() && tlv.isIndefinateTerminator() ) + { + tlvStack.pop() ; + state = BERDecoderState.VALUE ; + fireDecodeOccurred( top ) ; + state = BERDecoderState.TAG ; + } + else if ( top.isIndefinate() ) { break ; } - if ( top.valueIndex >= top.length ) + else if ( top.valueIndex >= top.length ) { tlvStack.pop() ; + state = BERDecoderState.VALUE ; fireDecodeOccurred( top ) ; + state = BERDecoderState.TAG ; } else { break ; } + } while( tlvStack.size() > 0 ) ; } - - - private void handleIndefinateTerminator() - { - /* - * Check for a INDEFINATE length TLV when tlv is primitive with - * zero length and a type class of UNIVERSAL which is reserved - * for use by encoding rules. - */ - if ( tlv.id == 0 && tlv.length == 0 && - tlv.typeClass == TypeClass.UNIVERSAL ) - { - String msg = "expected indefinate length TLV on the stack" ; - if ( tlvStack.isEmpty() ) - { - IllegalStateException e = new IllegalStateException( - msg + " but the stack is empty" ) ; - - if ( monitor != null ) - { - monitor.fatalError( this, e ) ; - } - - throw e ; - } - - Tuple top = ( Tuple ) tlvStack.peek() ; - if ( top.length != Length.INDEFINATE ) - { - IllegalStateException e = new IllegalStateException( - msg + " but TLV on top has a definate length" ) ; - - if ( monitor == null ) - { - throw e ; - } - else - { - monitor.fatalError( this, e ) ; - } - - return ; - } - - tlvStack.pop() ; - fireDecodeOccurred( top ) ; - tlv.clear() ; - state = BERDecoderState.TAG ; - } - } - // ------------------------------------------------------------------------ // Methods used for testing Modified: incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/BERDecoderCallback.java ============================================================================== --- incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/BERDecoderCallback.java (original) +++ incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/BERDecoderCallback.java Mon Mar 15 14:31:39 2004 @@ -30,8 +30,8 @@ public interface BERDecoderCallback extends DecoderCallback { /** - * A tag was decoded. The following tag properties of the TLV tuple are - * valid at this point: + * Method used to receive notification that a tag was decoded. The + * following tag properties of the TLV tuple are valid at this point: *
    *
  • id
  • *
  • isPrimitive
  • @@ -43,8 +43,8 @@ void tagDecoded( Tuple tlv ) ; /** - * A tag was decoded. The following tag properties of the TLV tuple are - * valid at this point: + * Method used to receive notification that a length was decoded. The + * following properties of the TLV tuple are valid at this point: *
      *
    • id
    • *
    • isPrimitive
    • Modified: incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/BERDecoderMonitor.java ============================================================================== --- incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/BERDecoderMonitor.java (original) +++ incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/BERDecoderMonitor.java Mon Mar 15 14:31:39 2004 @@ -30,6 +30,32 @@ */ public interface BERDecoderMonitor extends DecoderMonitor { + /** + * Method used to receive notification that a tag was decoded. The + * following tag properties of the TLV tuple are valid at this point: + *
        + *
      • id
      • + *
      • isPrimitive
      • + *
      • typeClass
      • + *
      + * + * @param tlv the TLV tuple + * @param tagData the tag data collected + */ void tagDecoded( Tuple tlv, byte[] tagData ) ; + + /** + * Method used to receive notification that a length was decoded. The + * following properties of the TLV tuple are valid at this point: + *
        + *
      • id
      • + *
      • isPrimitive
      • + *
      • typeClass
      • + *
      • length
      • + *
      + * + * @param tlv the TLV tuple + * @param lengthData the length data collected + */ void lengthDecoded( Tuple tlv, byte[] lengthData ) ; } Modified: incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/DefaultMutableTupleNode.java ============================================================================== --- incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/DefaultMutableTupleNode.java (original) +++ incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/DefaultMutableTupleNode.java Mon Mar 15 14:31:39 2004 @@ -40,8 +40,11 @@ public class DefaultMutableTupleNode implements MutableTupleNode, MutableTreeNode { + /** this node's tuple user object */ private Tuple tuple ; + /** a list of this node's children */ private ArrayList children = new ArrayList() ; + /** this node's parent node */ private DefaultMutableTupleNode parent ; @@ -72,8 +75,37 @@ { children.add( index, child ) ; } + + + /** + * Adds a child node to the front of the child list. + * + * @param child the child to add to the front + */ + public void addFront( DefaultMutableTupleNode child ) + { + if ( children.isEmpty() ) + { + children.add( child ) ; + } + else + { + children.add( 0, child ) ; + } + } + /** + * Adds a child node to the end of the child list. + * + * @param child the child to add to the end + */ + public void addLast( DefaultMutableTupleNode child ) + { + children.add( child ) ; + } + + /* (non-Javadoc) * @see org.apache.snickers.ber.MutableTupleNode#remove(int) */ @@ -438,5 +470,70 @@ public void setUserObject( Object object ) { tuple = ( Tuple ) object ; + } + + + // ------------------------------------------------------------------------ + // java.lang.Object overrides & overloads + // ------------------------------------------------------------------------ + + + /** + * Checks to see if this node and its children equal another exactly. + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals( Object obj ) + { + if ( obj instanceof DefaultMutableTupleNode ) + { + return equals( this, ( DefaultMutableTupleNode ) obj ) ; + } + + return false ; + } + + + /** + * Checks to see if two nodes equal one another. The nodes must be exactly + * the same even in terms of the order of their children and the children + * of their descendants. + * + * @param n1 the first node + * @param n2 the second node + * @return true if n1.equals(n2) exactly otherwise false + */ + public static boolean equals( DefaultMutableTupleNode n1, + DefaultMutableTupleNode n2 ) + { + if ( n1 == n2 ) + { + return true ; + } + + if ( ! n1.getTuple().equals( n2.getTuple() ) ) + { + return false ; + } + + if ( n1.getChildCount() != n2.getChildCount() ) + { + return false ; + } + + DefaultMutableTupleNode n1Child = null ; + DefaultMutableTupleNode n2Child = null ; + for ( int ii = 0; ii < n1.getChildCount() ; ii++ ) + { + n1Child = ( DefaultMutableTupleNode ) n1.getChildAt( ii ) ; + n2Child = ( DefaultMutableTupleNode ) n2.getChildAt( ii ) ; + + if ( ! equals( n1Child, n2Child ) ) + { + return false ; + } + } + + return true ; } } Modified: incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/Length.java ============================================================================== --- incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/Length.java (original) +++ incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/Length.java Mon Mar 15 14:31:39 2004 @@ -1,193 +1,204 @@ -/* - * Copyright 2004 The Apache Software Foundation - * - * Licensed 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.snickers.ber ; - - -import org.apache.commons.codec.DecoderException ; -import org.apache.commons.collections.primitives.ArrayByteList ; - - -/** - * The length component of a BER TLV Tuple. - * - * @author - * Apache Directory Project - * @version $Rev$ - */ -public class Length -{ - /** used to mark length as indefinate */ - public static final int INDEFINATE = -2 ; - /** used to mark length as undefined */ - public static final int UNDEFINED = -1 ; - /** the end long form terminate bit flag mask */ - public static final int END_MASK = 0x80 ; - - /** the value for this tlv length */ - private int value = UNDEFINED ; - /** the number of octets needed to complete this length component */ - private int numOctets = UNDEFINED ; - /** whether or not this length has been fixated */ - private boolean isFixated = false ; - /** a byte buffer used to collect the arriving length octets */ - private final ArrayByteList buf = new ArrayByteList( 10 ) ; - - - - /** - * Checks to see if the length has been fixated. - * - * @return true if it is fixated, false if not - */ - public boolean isFixated() - { - return isFixated ; - } - - - /** - * Clears this tag's data of all bytes and values calculated so all is as it - * was when this instance was created. - */ - void clear() - { - isFixated = false ; - value = 0 ; - numOctets = 1 ; - buf.clear() ; - } - - - /** - * Fixates the data within this Length calculating all the derived - * properties from the existing set of octets. While fixated octets - * cannot be added. - * - * @throws DecoderException if this Length is invalid - */ - void fixate() throws DecoderException - { - value = getLength( buf ) ; - isFixated = true ; - } - - - /** - * Adds an octet to this Length component and as a side effect fixates the - * Length component if all the required length data has arrived. - * - * @param octet the 8 bit byte to add - */ - void add( byte octet ) throws DecoderException - { - if ( isFixated ) - { - throw new IllegalStateException( "data added to fixated length" ) ; - } - - buf.add( octet ) ; - - if ( buf.size() == 1 ) - { - // if its the long form - if ( END_MASK == ( octet & END_MASK ) && ( octet & 0x7F ) > 0 ) - { - // capture number of octets we need to compute length - numOctets = octet & 0x7F ; - } - else - { - fixate() ; - } - } - - /* - * if we have collected all the octets needed for computing the long - * form length so we need to calculate the length and just fixate - */ - else if ( buf.size() >= numOctets + 1 ) - { - fixate() ; - } - } - - - /** - * Gets a copy of the octets composing this Length component. - * - * @return the octets representing this Length component - */ - public byte[] getOctets() - { - return buf.toArray() ; - } - - - /** - * Gets the number of octets currently in this Length component. - * - * @return the number of octets currently within this Length component - */ - public int size() - { - return buf.size() ; - } - - - /** - * Decodes the length of a value for a tlv using the Length field bytes. - * - * @param octets the length field bytes in the TLV - * @return the length of the TLV - * @throws DecoderException if the precision cannot hold the number - */ - public static int getLength( ArrayByteList octets ) throws DecoderException - { - if ( octets.size() >= 6 ) - { - /* - * If this exception is ever thrown which is highly unlikely, then - * we need to switch to another data type to return because after - * 5 bytes the int can no longer hold the number. - */ - throw new DecoderException( "Length number is too large." ) ; - } - - // if we are using the short form then just return the first octet - if ( ( octets.get( 0 ) & END_MASK ) == 0 ) - { - return octets.get( 0 ) ; - } - // using the indefinate form - else if ( ( octets.get( 0 ) & 0x7F ) == 0 ) - { - return INDEFINATE ; - } - - // using the long form so we calculate the length from all octets - int length = 0 ; - - // calculate tag value w/ long tag format - for( int ii = 1 ; ii < octets.size(); ii++ ) - { - int shift = ( ii - 1 ) * 8 ; - length |= ( 0xFF & ( int ) octets.get( ii ) ) << shift ; - } - - return length ; - } -} +/* + * Copyright 2004 The Apache Software Foundation + * + * Licensed 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.snickers.ber ; + + +import org.apache.commons.codec.DecoderException ; +import org.apache.commons.collections.primitives.ArrayByteList ; + + +/** + * The length component of a BER TLV Tuple. + * + * @author + * Apache Directory Project + * @version $Rev$ + */ +public class Length +{ + /** used to mark length as indefinate */ + public static final int INDEFINATE = -2 ; + /** used to mark length as undefined */ + public static final int UNDEFINED = -1 ; + /** the end long form terminate bit flag mask */ + public static final int END_MASK = 0x80 ; + + /** the value for this tlv length */ + private int value = UNDEFINED ; + /** the number of octets needed to complete this length component */ + private int numOctets = UNDEFINED ; + /** whether or not this length has been fixated */ + private boolean isFixated = false ; + /** a byte buffer used to collect the arriving length octets */ + private final ArrayByteList buf = new ArrayByteList( 10 ) ; + + + + /** + * Checks to see if the length has been fixated. + * + * @return true if it is fixated, false if not + */ + public boolean isFixated() + { + return isFixated ; + } + + + /** + * Clears this tag's data of all bytes and values calculated so all is as it + * was when this instance was created. + */ + void clear() + { + isFixated = false ; + value = 0 ; + numOctets = 1 ; + buf.clear() ; + } + + + /** + * Fixates the data within this Length calculating all the derived + * properties from the existing set of octets. While fixated octets + * cannot be added. + * + * @throws DecoderException if this Length is invalid + */ + void fixate() throws DecoderException + { + value = getLength( buf ) ; + isFixated = true ; + } + + + /** + * Adds an octet to this Length component and as a side effect fixates the + * Length component if all the required length data has arrived. + * + * @param octet the 8 bit byte to add + */ + void add( byte octet ) throws DecoderException + { + if ( isFixated ) + { + throw new IllegalStateException( "data added to fixated length" ) ; + } + + buf.add( octet ) ; + + if ( buf.size() == 1 ) + { + // if its the long form + if ( END_MASK == ( octet & END_MASK ) && ( octet & 0x7F ) > 0 ) + { + // capture number of octets we need to compute length + numOctets = octet & 0x7F ; + } + else + { + fixate() ; + } + } + + /* + * if we have collected all the octets needed for computing the long + * form length so we need to calculate the length and just fixate + */ + else if ( buf.size() >= numOctets + 1 ) + { + fixate() ; + } + } + + + /** + * Gets the length of the value. + * + * @return the length of the value + */ + public int getLength() + { + return value ; + } + + + /** + * Gets a copy of the octets composing this Length component. + * + * @return the octets representing this Length component + */ + public byte[] getOctets() + { + return buf.toArray() ; + } + + + /** + * Gets the number of octets currently in this Length component. + * + * @return the number of octets currently within this Length component + */ + public int size() + { + return buf.size() ; + } + + + /** + * Decodes the length of a value for a tlv using the Length field bytes. + * + * @param octets the length field bytes in the TLV + * @return the length of the TLV + * @throws DecoderException if the precision cannot hold the number + */ + public static int getLength( ArrayByteList octets ) throws DecoderException + { + if ( octets.size() >= 6 ) + { + /* + * If this exception is ever thrown which is highly unlikely, then + * we need to switch to another data type to return because after + * 5 bytes the int can no longer hold the number. + */ + throw new DecoderException( "Length number is too large." ) ; + } + + // if we are using the short form then just return the first octet + if ( ( octets.get( 0 ) & END_MASK ) == 0 ) + { + return octets.get( 0 ) ; + } + // using the indefinate form + else if ( ( octets.get( 0 ) & 0x7F ) == 0 ) + { + return INDEFINATE ; + } + + // using the long form so we calculate the length from all octets + int length = 0 ; + + // calculate tag value w/ long tag format + for( int ii = 1 ; ii < octets.size(); ii++ ) + { + int shift = ( ii - 1 ) * 8 ; + length |= ( 0xFF & ( int ) octets.get( ii ) ) << shift ; + } + + return length ; + } +} Modified: incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/LengthDecoder.java ============================================================================== --- incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/LengthDecoder.java (original) +++ incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/LengthDecoder.java Mon Mar 15 14:31:39 2004 @@ -1,62 +1,63 @@ -/* - * Copyright 2004 The Apache Software Foundation - * - * Licensed 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.snickers.ber ; - - -import java.nio.ByteBuffer ; - -import org.apache.commons.codec.DecoderException ; -import org.apache.commons.codec.stateful.AbstractStatefulDecoder ; - - -/** - * A BER TLV Length component decoder. This decoder delivers a Length instance - * to its callback. For efficiency the same Length object is reused. Callback - * implementations should not copy the handle to the Length object delivered but - * should copy the data if they need it over the long term. - * - * @author - * Apache Directory Project - * @version $Rev: 9470 $ - */ -public class LengthDecoder extends AbstractStatefulDecoder -{ - /** the Length component decoded from a BER TLV Tuple */ - private final Length length = new Length() ; - - - /* (non-Javadoc) - * @see org.apache.commons.codec.stateful.StatefulDecoder#decode( - * java.lang.Object) - */ - public void decode( Object encoded ) throws DecoderException - { - ByteBuffer buf = ( ByteBuffer ) encoded ; - - while ( buf.hasRemaining() ) - { - byte octet = buf.get() ; - length.add( octet ) ; - - if ( length.isFixated() ) - { - decodeOccurred( length ) ; - length.clear() ; - } - } - } -} +/* + * Copyright 2004 The Apache Software Foundation + * + * Licensed 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.snickers.ber ; + + +import java.nio.ByteBuffer ; + +import org.apache.commons.codec.DecoderException ; +import org.apache.commons.codec.stateful.AbstractStatefulDecoder ; + + +/** + * A BER TLV Length component decoder. This decoder delivers a Length instance + * to its callback. For efficiency the same Length object is reused. Callback + * implementations should not copy the handle to the Length object delivered but + * should copy the data if they need it over the long term. + * + * @author + * Apache Directory Project + * @version $Rev$ + */ +public class LengthDecoder extends AbstractStatefulDecoder +{ + /** the Length component decoded from a BER TLV Tuple */ + private final Length length = new Length() ; + + + /* (non-Javadoc) + * @see org.apache.commons.codec.stateful.StatefulDecoder#decode( + * java.lang.Object) + */ + public void decode( Object encoded ) throws DecoderException + { + ByteBuffer buf = ( ByteBuffer ) encoded ; + + while ( buf.hasRemaining() ) + { + byte octet = buf.get() ; + length.add( octet ) ; + + if ( length.isFixated() ) + { + decodeOccurred( length ) ; + length.clear() ; + return ; + } + } + } +} Modified: incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/MutableTupleNode.java ============================================================================== --- incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/MutableTupleNode.java (original) +++ incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/MutableTupleNode.java Mon Mar 15 14:31:39 2004 @@ -29,22 +29,22 @@ /** * Adds child to the receiver at index. * - * @param child - * @param index + * @param child the child to add + * @param index the index at which to insert the child */ void insert( MutableTupleNode child, int index ) ; /** * Removes the child at index from the receiver. * - * @param index + * @param index the index at which to remove the child */ void remove( int index ) ; /** * Removes node from the receiver. * - * @param node + * @param node the node to remove */ void remove( MutableTupleNode node ) ; @@ -56,14 +56,14 @@ /** * Sets the parent of the receiver to newParent. * - * @param newParent + * @param newParent the new parent to set */ void setParent( MutableTupleNode newParent ) ; /** * Resets the Tuple of the receiver object. * - * @param t + * @param t the tuple to set for this node */ void setTuple( Tuple t ) ; Modified: incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/Tag.java ============================================================================== --- incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/Tag.java (original) +++ incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/Tag.java Mon Mar 15 14:31:39 2004 @@ -1,296 +1,296 @@ -/* - * Copyright 2004 The Apache Software Foundation - * - * Licensed 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.snickers.ber ; - - -import org.apache.commons.codec.DecoderException ; -import org.apache.commons.collections.primitives.ArrayByteList ; - - -/** - * The Tag component of a BER TLV Tuple. - * - * @author - * Apache Directory Project - * @version $Rev$ - */ -public class Tag -{ - /** tag mask for the primitive/constructed bit - 0010 0000 - 0x20 */ - private static final int PRIMITIVE_MASK = 0x20; - /** tag mask for the short tag format - 0001 1111 - 0x1F */ - public static final int SHORT_MASK = 0x1F ; - /** tag mask for the long tag format - 0111 1111 - 0x7F */ - public static final int LONG_MASK = 0x7F ; - - /** tag id */ - private int id = 0 ; - /** whether or not this tag represents a primitive type */ - private boolean isPrimitive = true ; - /** whether or not this tag has been fixated */ - private boolean isFixated = false ; - /** the type class of this tag */ - private TypeClass typeClass = TypeClass.APPLICATION ; - /** a byte buffer used to collect the arriving tag octets */ - private final ArrayByteList buf = new ArrayByteList( 10 ) ; - - - /** - * Clears this tag's data of all bytes and values calculated so all is as it - * was when this instance was created. - */ - void clear() - { - id = 0 ; - isFixated = false ; - isPrimitive = true ; - typeClass = TypeClass.APPLICATION ; - buf.clear() ; - } - - - /** - * Fixates the data within this Tag calculating all the derived - * properties from the existing set of octets. While fixated octets - * cannot be added. - * - * @throws DecoderException if this Tag is invalid - */ - void fixate() throws DecoderException - { - isFixated = true ; - id = Tag.getTagId( buf ) ; - isPrimitive = isPrimitive( buf.get( 0 ) ) ; - typeClass = TypeClass.getTypeClass( buf.get( 0 ) ) ; - } - - - /** - * Adds an octet to this Tag and as a size effect may fixate the Tag if - * all the expected data has arrived. - * - * @param octet the 8 bit byte to add - */ - void add( byte octet ) throws DecoderException - { - if ( isFixated ) - { - throw new IllegalStateException( "data added to fixated tag" ) ; - } - - buf.add( octet ) ; - - if ( buf.size() == 1 ) - { - // its the short form so we just fixate - if ( ( 0x1F & octet ) != 0x1F ) - { - fixate() ; - } - } - - /* - * From here on we're dealing with the long form of the tag. The - * terminating octet for the long form uses a 0 for the most - * significant bit to flag the end of the train of octets for the - * tag id. - */ - else if ( ( octet & 0x80 ) == 0 ) - { - fixate() ; - } - } - - - /** - * Gets a copy of the octets composing this Tag. - * - * @return the octets representing this Tag - */ - public byte[] getOctets() - { - return buf.toArray() ; - } - - - /** - * Gets the number of octets in this Tag. - * - * @return the number of octets within this Tag - */ - public int size() - { - return buf.size() ; - } - - - /** - * Gets the id. - * - * @return the id - */ - public int getId() - { - return id ; - } - - - /** - * Checks to see if the tag represented by this Tag is primitive or - * constructed. - * - * @return true if it is primitive, false if it is constructed - */ - public boolean isPrimitive() - { - return isPrimitive ; - } - - - /** - * Checks to see if the tag has been fixated. - * - * @return true if it is fixated, false if not - */ - public boolean isFixated() - { - return isFixated ; - } - - - /** - * Gets the type class for this Tag. - * - * @return the typeClass for this Tag - */ - public TypeClass getTypeClass() - { - return typeClass ; - } - - - /** - * Gets the tag id of a TLV from the tag octets. - * - * @param octets the set of octets needed to determine the tag value - * (a.k.a identifier octets) - * @return the tag id - * @throws DecoderException if the id cannot be determined due to - * type limitations of this method's return type. - */ - public final static int getTagId( byte[] octets ) - throws DecoderException - { - if ( octets.length > 6 ) - { - /* - * If this exception is ever thrown which is highly unlikely, then - * we need to switch to another data type to return because after - * 5 bytes the int can no longer hold the number. - */ - throw new DecoderException( "Tag number is too large." ) ; - } - - int id = octets[0] & SHORT_MASK ; - - // if bits are not all 1's then return the value which is less than 31 - if ( id != SHORT_MASK && octets.length == 1 ) - { - return id ; - } - - // clear the id now - id = 0 ; - - // calculate tag value w/ long tag format - for( int ii = 1 ; ii < octets.length; ii++ ) - { - int shift = ( ii - 1 ) * 7 ; - id |= ( octets[ii] & LONG_MASK ) << shift ; - } - - return id ; - } - - - /** - * Gets the tag id of a TLV from the tag octets. - * - * @param octets the set of octets needed to determine the tag value - * (a.k.a identifier octets) - * @return the tag id - * @throws DecoderException if the id cannot be determined due to - * type limitations of this method's return type. - */ - public final static int getTagId( ArrayByteList octets ) - throws DecoderException - { - if ( octets.size() > 6 ) - { - /* - * If this exception is ever thrown which is highly unlikely, then - * we need to switch to another data type to return because after - * 5 bytes the int can no longer hold the number. - */ - throw new DecoderException( "Tag number is too large." ) ; - } - - int id = octets.get( 0 ) & SHORT_MASK ; - - // if bits are not all 1's then return the value which is less than 31 - if ( id != SHORT_MASK && octets.size() == 1 ) - { - return id ; - } - - // clear the id now - id = 0 ; - - // calculate tag value w/ long tag format - for( int ii = 1 ; ii < octets.size(); ii++ ) - { - int shift = ( ii - 1 ) * 7 ; - id |= ( octets.get( ii ) & LONG_MASK ) << shift ; - } - - return id ; - } - - - /** - * Checks to see if the tag is a primitive. - * - * @param octet the first octet of the tag - * @return true if this tag is of the simple type, false if constructed - */ - public final static boolean isPrimitive( int octet ) - { - return ( octet & PRIMITIVE_MASK ) == 0 ; - } - - - /** - * Checks to see if the tag is constructed. - * - * @param octet the first octet of the tag - * @return true if constructed, false if primitive - */ - public final static boolean isConstructed( int octet ) - { - return ( octet & PRIMITIVE_MASK ) == PRIMITIVE_MASK ; - } -} +/* + * Copyright 2004 The Apache Software Foundation + * + * Licensed 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.snickers.ber ; + + +import org.apache.commons.codec.DecoderException ; +import org.apache.commons.collections.primitives.ArrayByteList ; + + +/** + * The Tag component of a BER TLV Tuple. + * + * @author + * Apache Directory Project + * @version $Rev$ + */ +public class Tag +{ + /** tag mask for the primitive/constructed bit - 0010 0000 - 0x20 */ + private static final int PRIMITIVE_MASK = 0x20; + /** tag mask for the short tag format - 0001 1111 - 0x1F */ + public static final int SHORT_MASK = 0x1F ; + /** tag mask for the long tag format - 0111 1111 - 0x7F */ + public static final int LONG_MASK = 0x7F ; + + /** tag id */ + private int id = 0 ; + /** whether or not this tag represents a primitive type */ + private boolean isPrimitive = true ; + /** whether or not this tag has been fixated */ + private boolean isFixated = false ; + /** the type class of this tag */ + private TypeClass typeClass = TypeClass.APPLICATION ; + /** a byte buffer used to collect the arriving tag octets */ + private final ArrayByteList buf = new ArrayByteList( 10 ) ; + + + /** + * Clears this tag's data of all bytes and values calculated so all is as it + * was when this instance was created. + */ + void clear() + { + id = 0 ; + isFixated = false ; + isPrimitive = true ; + typeClass = TypeClass.APPLICATION ; + buf.clear() ; + } + + + /** + * Fixates the data within this Tag calculating all the derived + * properties from the existing set of octets. While fixated octets + * cannot be added. + * + * @throws DecoderException if this Tag is invalid + */ + void fixate() throws DecoderException + { + isFixated = true ; + id = Tag.getTagId( buf ) ; + isPrimitive = isPrimitive( buf.get( 0 ) ) ; + typeClass = TypeClass.getTypeClass( buf.get( 0 ) ) ; + } + + + /** + * Adds an octet to this Tag and as a size effect may fixate the Tag if + * all the expected data has arrived. + * + * @param octet the 8 bit byte to add + */ + void add( byte octet ) throws DecoderException + { + if ( isFixated ) + { + throw new IllegalStateException( "data added to fixated tag" ) ; + } + + buf.add( octet ) ; + + if ( buf.size() == 1 ) + { + // its the short form so we just fixate + if ( ( 0x1F & octet ) != 0x1F ) + { + fixate() ; + } + } + + /* + * From here on we're dealing with the long form of the tag. The + * terminating octet for the long form uses a 0 for the most + * significant bit to flag the end of the train of octets for the + * tag id. + */ + else if ( ( octet & 0x80 ) == 0 ) + { + fixate() ; + } + } + + + /** + * Gets a copy of the octets composing this Tag. + * + * @return the octets representing this Tag + */ + public byte[] getOctets() + { + return buf.toArray() ; + } + + + /** + * Gets the number of octets in this Tag. + * + * @return the number of octets within this Tag + */ + public int size() + { + return buf.size() ; + } + + + /** + * Gets the id. + * + * @return the id + */ + public int getId() + { + return id ; + } + + + /** + * Checks to see if the tag represented by this Tag is primitive or + * constructed. + * + * @return true if it is primitive, false if it is constructed + */ + public boolean isPrimitive() + { + return isPrimitive ; + } + + + /** + * Checks to see if the tag has been fixated. + * + * @return true if it is fixated, false if not + */ + public boolean isFixated() + { + return isFixated ; + } + + + /** + * Gets the type class for this Tag. + * + * @return the typeClass for this Tag + */ + public TypeClass getTypeClass() + { + return typeClass ; + } + + + /** + * Gets the tag id of a TLV from the tag octets. + * + * @param octets the set of octets needed to determine the tag value + * (a.k.a identifier octets) + * @return the tag id + * @throws DecoderException if the id cannot be determined due to + * type limitations of this method's return type. + */ + public final static int getTagId( byte[] octets ) + throws DecoderException + { + if ( octets.length > 6 ) + { + /* + * If this exception is ever thrown which is highly unlikely, then + * we need to switch to another data type to return because after + * 5 bytes the int can no longer hold the number. + */ + throw new DecoderException( "Tag number is too large." ) ; + } + + int id = octets[0] & SHORT_MASK ; + + // if bits are not all 1's then return the value which is less than 31 + if ( id != SHORT_MASK && octets.length == 1 ) + { + return id ; + } + + // clear the id now + id = 0 ; + + // calculate tag value w/ long tag format + for( int ii = 1 ; ii < octets.length; ii++ ) + { + int shift = ( ii - 1 ) * 7 ; + id |= ( octets[ii] & LONG_MASK ) << shift ; + } + + return id ; + } + + + /** + * Gets the tag id of a TLV from the tag octets. + * + * @param octets the set of octets needed to determine the tag value + * (a.k.a identifier octets) + * @return the tag id + * @throws DecoderException if the id cannot be determined due to + * type limitations of this method's return type. + */ + public final static int getTagId( ArrayByteList octets ) + throws DecoderException + { + if ( octets.size() > 6 ) + { + /* + * If this exception is ever thrown which is highly unlikely, then + * we need to switch to another data type to return because after + * 5 bytes the int can no longer hold the number. + */ + throw new DecoderException( "Tag number is too large." ) ; + } + + int id = octets.get( 0 ) & SHORT_MASK ; + + // if bits are not all 1's then return the value which is less than 31 + if ( id != SHORT_MASK && octets.size() == 1 ) + { + return id ; + } + + // clear the id now + id = 0 ; + + // calculate tag value w/ long tag format + for( int ii = 1 ; ii < octets.size(); ii++ ) + { + int shift = ( ii - 1 ) * 7 ; + id |= ( octets.get( ii ) & LONG_MASK ) << shift ; + } + + return id ; + } + + + /** + * Checks to see if the tag is a primitive. + * + * @param octet the first octet of the tag + * @return true if this tag is of the simple type, false if constructed + */ + public final static boolean isPrimitive( int octet ) + { + return ( octet & PRIMITIVE_MASK ) == 0 ; + } + + + /** + * Checks to see if the tag is constructed. + * + * @param octet the first octet of the tag + * @return true if constructed, false if primitive + */ + public final static boolean isConstructed( int octet ) + { + return ( octet & PRIMITIVE_MASK ) == PRIMITIVE_MASK ; + } +} Modified: incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/TagDecoder.java ============================================================================== --- incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/TagDecoder.java (original) +++ incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/TagDecoder.java Mon Mar 15 14:31:39 2004 @@ -56,6 +56,7 @@ { decodeOccurred( tag ) ; tag.clear() ; + return ; } } } Modified: incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/TupleNode.java ============================================================================== --- incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/TupleNode.java (original) +++ incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/TupleNode.java Mon Mar 15 14:31:39 2004 @@ -22,7 +22,7 @@ /** - * A TLV Tuple tree node. + * A TLV Tuple tree node modeled in the likeness of a TreeNode. * * @author * Apache Directory Project @@ -30,12 +30,83 @@ */ public interface TupleNode { + /** + * Gets the parent tuple node to this node or null if a parent does not + * exist. The analogous method on the TreeNode interface + * would be getParent(). + * + * @return the parent node or null if one does not exist + */ TupleNode getParentTupleNode() ; + + /** + * Gets an iterator over this node's children. The analogous interface on + * the TreeNode interface would be children which + * returns an Enumeration instead of an Iterator. + * + * @return an iterator over this node's children + */ Iterator getChildren() ; + + /** + * Gets a tuple node at an index. The analogous interface on TreeNode + * would be the getChildAt method. + * + * @param index the index of the child to get + * @return the child node at the specified index + */ TupleNode getChildTupleNodeAt( int index ) ; + + /** + * Gets the index of a child if the child node if it exists. The analog + * within TreeNode takes a TreeNode instead of a + * TupleNode. + * + * @param node the child node to get the index for + * @return the index of the child node or -1 if the node does not exist + */ int getIndex( TupleNode node ) ; + + /** + * Gets the number of child nodes contained. This is the same as in + * TreeNode.getChildCount() as well. + * + * @return the number of child nodes contained. + */ int getChildCount() ; + + /** + * Gets the number of child nodes contained. This is the same as in + * TreeNode.size() as well. + * + * @return the number of children + */ int size() ; + + + /** + * Gets the Tuple this node represents. This is the analogous to + * TreeNode.getUserObject(). + * + * @return the tuple this node represents or null if one has not been + * assigned + */ Tuple getTuple() ; + + /** + * Recursively encodes the tree rooted at this node. + * + * @param buf the buffer populated with the BER encoded tlv tree contents + */ void encode( ByteBuffer buf ) ; + + /** + * Checks to see if two trees are equal. Note that the order of children + * within the tree as well as the tuples and their contents make a + * difference to equals(). + * + * @param obj the object to compare this node to + * @return true if the obj and this node are exact replicas of one another + */ + boolean equals( Object obj ) ; } Modified: incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/TupleTreeDecoder.java ============================================================================== --- incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/TupleTreeDecoder.java (original) +++ incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber/TupleTreeDecoder.java Mon Mar 15 14:31:39 2004 @@ -17,19 +17,21 @@ package org.apache.snickers.ber ; -import java.nio.ByteBuffer; import java.util.Stack ; +import java.nio.ByteBuffer ; import org.apache.commons.codec.DecoderException ; -import org.apache.commons.codec.stateful.CallbackHistory; import org.apache.commons.codec.stateful.DecoderMonitor ; +import org.apache.commons.codec.stateful.CallbackHistory ; import org.apache.commons.codec.stateful.DecoderCallback ; import org.apache.commons.codec.stateful.StatefulDecoder ; import org.apache.commons.codec.stateful.DecoderMonitorAdapter ; /** - * Builds a TLV tree from the TLV stream emitted from the decoder. + * Builds a TLV tree from the TLV stream emitted from the decoder. The decoded + * objects delivered to this StatefulDecoder's DecoderCallback are + * DefaultMutableTupleNodes. * * @author * Apache Directory Project @@ -37,12 +39,19 @@ */ public class TupleTreeDecoder implements StatefulDecoder { + /** a stack of nested constructed tuples used to track state */ Stack stack = new Stack() ; - BERDecoder decoder = new BERDecoder() ; + /** the underlying BER data stream to TLV stream decoder */ + BERDecoder decoder = new BERDecoder( 1024 ) ; + /** the callback to use for this StatefulDecoder */ DecoderCallback cb = null ; + /** the monitor to use for this StatefulDecoder */ DecoderMonitor monitor = new DecoderMonitorAdapter() ; + /** + * Creates a simple BER byte stream to TLV Tuple tree decoder. + */ public TupleTreeDecoder() { BERDecoderCallback berCallback = new BERDecoderCallback() @@ -53,8 +62,8 @@ { if ( ! tlv.isPrimitive ) { - MutableTupleNode child = null ; - MutableTupleNode parent = null ; + DefaultMutableTupleNode child = null ; + DefaultMutableTupleNode parent = null ; Tuple cloned = ( Tuple ) tlv.clone() ; if ( stack.isEmpty() ) @@ -63,18 +72,10 @@ return ; } - parent = ( MutableTupleNode ) stack.peek() ; + parent = ( DefaultMutableTupleNode ) stack.peek() ; child = new DefaultMutableTupleNode( cloned ) ; - child.setParent( parent ) ; - - int index = parent.getChildCount() - 1 ; - - if ( index < 0 ) - { - index = 0 ; - } - - parent.insert( child, index ) ; + child.setParent( ( MutableTupleNode ) parent ) ; + parent.addLast( child ) ; stack.push( child ) ; } } @@ -91,10 +92,16 @@ } - public void handleTuple( Tuple t ) + /** + * Handles a tuple recieved from the underlying BER byte stream decoder. + * + * @param t the tuple to handle + */ + private void handleTuple( Tuple t ) { System.out.println( t.id ) ; - MutableTupleNode node = null ; + DefaultMutableTupleNode node = null ; + DefaultMutableTupleNode parent = null ; if ( t.isPrimitive ) { @@ -102,22 +109,15 @@ if ( ! stack.isEmpty() ) { - MutableTupleNode parent = ( MutableTupleNode ) stack.peek() ; - node.setParent( parent ) ; - int index = parent.getChildCount() - 1 ; - - if ( index < 0 ) - { - index = 0 ; - } - - parent.insert( node, index ) ; + parent = ( DefaultMutableTupleNode ) stack.peek() ; + node.setParent( ( MutableTupleNode ) parent ) ; + parent.addLast( node ) ; } return ; } - node = ( MutableTupleNode ) stack.pop() ; + node = ( DefaultMutableTupleNode ) stack.pop() ; if ( cb != null && stack.isEmpty() ) { @@ -136,6 +136,15 @@ } + /** + * Decodes a BER byte buffer into a tree of TLV tuples. + * + * @param buf the buffer to decode + * @return the TLV tuple node with children if applicable + * @throws DecoderException if there is a problem decoding the data + * @throws java.util.NoSuchElementException if there is not enough data + * to properly decode a complete TLV tree + */ public static TupleNode treeDecode( ByteBuffer buf ) throws DecoderException { TupleTreeDecoder decoder = new TupleTreeDecoder() ;