directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From akaras...@apache.org
Subject svn commit: rev 9495 - incubator/directory/snickers/branches/refactoring/ber/src/java/org/apache/snickers/ber
Date Mon, 15 Mar 2004 22:31:40 GMT
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</a>
  * @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:
      * <ul>
      * <li>id</li>
      * <li>isPrimitive</li>
@@ -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:
      * <ul>
      * <li>id</li>
      * <li>isPrimitive</li>

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:
+     * <ul>
+     * <li>id</li>
+     * <li>isPrimitive</li>
+     * <li>typeClass</li>
+     * </ul>
+     * 
+     * @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:
+     * <ul>
+     * <li>id</li>
+     * <li>isPrimitive</li>
+     * <li>typeClass</li>
+     * <li>length</li>
+     * </ul>
+     * 
+     * @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 <code>n1.equals(n2)</code> 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 <a href="mailto:directory-dev@incubator.apache.org">
- * Apache Directory Project</a>
- * @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 <a href="mailto:directory-dev@incubator.apache.org">
+ * Apache Directory Project</a>
+ * @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 <a href="mailto:directory-dev@incubator.apache.org">
- * Apache Directory Project</a>
- * @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 <a href="mailto:directory-dev@incubator.apache.org">
+ * Apache Directory Project</a>
+ * @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 <a href="mailto:directory-dev@incubator.apache.org">
- * Apache Directory Project</a>
- * @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 <a href="mailto:directory-dev@incubator.apache.org">
+ * Apache Directory Project</a>
+ * @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 <a href="mailto:directory-dev@incubator.apache.org">
  * Apache Directory Project</a>
@@ -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 <code>TreeNode</code> interface 
+     * would be <code>getParent()</code>.
+     * 
+     * @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 <code>TreeNode</code> interface would be <code>children</code> which
+     * returns an <code>Enumeration</code> instead of an <code>Iterator</code>.
+     *  
+     * @return an iterator over this node's children
+     */
     Iterator getChildren() ;
+    
+    /**
+     * Gets a tuple node at an index.  The analogous interface on <code>TreeNode
+     * </code> would be the <code>getChildAt</code> 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 <code>TreeNode<code> takes a <code>TreeNode</code> instead of a 
+     * <code>TupleNode</code>.
+     * 
+     * @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 
+     * <code>TreeNode.getChildCount()</code> as well.
+     * 
+     * @return the number of child nodes contained.
+     */
     int getChildCount() ;
+    
+    /**
+     * Gets the number of child nodes contained.  This is the same as in 
+     * <code>TreeNode.size()</code> as well.
+     * 
+     * @return the number of children
+     */
     int size() ;
+    
+    
+    /**
+     * Gets the Tuple this node represents.   This is the analogous to <code>
+     * TreeNode.getUserObject()</code>.
+     * 
+     * @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 <code>equals()</code>.
+     * 
+     * @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 <a href="mailto:directory-dev@incubator.apache.org">
  * Apache Directory Project</a>
@@ -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() ;

Mime
View raw message