directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From akaras...@apache.org
Subject svn commit: rev 30757 - in incubator/directory/snickers/trunk: . ber-codec/src/java/org/apache/snickers/ber ber-codec/src/test/org/apache/snickers/ber ldap-ber-provider ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/abandon ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/bind ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/search ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/abandon ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/bind ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/search xdocs/ber-codec
Date Tue, 27 Jul 2004 04:15:17 GMT
Author: akarasulu
Date: Mon Jul 26 21:15:16 2004
New Revision: 30757

Added:
   incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/TupleEventConsumer.java   (contents, props changed)
   incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/TupleEventProducer.java   (contents, props changed)
   incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/TupleTreeAnalyzer.java
      - copied, changed from rev 9765, incubator/directory/snickers/trunk/ber/src/java/org/apache/snickers/ber/TupleTreeAnalyzer.java
   incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/LdapResultEncoder.java
   incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/bind/BindRequestEncoder.java
   incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/bind/BindResponseEncoder.java
   incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/search/
   incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/search/SearchRequestEncoder.java
   incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/AbstractEncoderTest.java
   incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/bind/
   incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/bind/BindRequestEncoderTest.java
   incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/bind/BindResponseEncoderTest.java
   incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/search/
Modified:
   incubator/directory/snickers/trunk/   (props changed)
   incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/BEREncoder.java
   incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/Tuple.java
   incubator/directory/snickers/trunk/ber-codec/src/test/org/apache/snickers/ber/BEREncoderTest.java
   incubator/directory/snickers/trunk/ldap-ber-provider/   (props changed)
   incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/SnickersLdapEncoder.java
   incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/abandon/AbandonRequestEncoder.java
   incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/abandon/AbandonRequestEncoderTest.java
   incubator/directory/snickers/trunk/project.xml
   incubator/directory/snickers/trunk/xdocs/ber-codec/BEREncoderDesign.xml
Log:
Commit changes ...

 o resurrected and modified TupleTreeAnalyzer
 o altered tuple to support setter operations
 o added new event producer consumers for tuple events
 o added bind request and response handlers for the encoder
 o added generic ldap result handler
 o started search encoder
 



Modified: incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/BEREncoder.java
==============================================================================
--- incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/BEREncoder.java	(original)
+++ incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/BEREncoder.java	Mon Jul 26 21:15:16 2004
@@ -18,23 +18,30 @@
 
 
 import org.apache.commons.codec.stateful.AbstractStatefulEncoder;
-import org.apache.commons.codec.stateful.StatefulEncoder;
 
 import java.nio.ByteBuffer;
 
 
 /**
- * A BER TLV tuple encoder.  This encoder receives events via some BEREncoder
+ * A BER TLV tuple encoder.  This encoder receives events via a
+ * BEREncoderCallback.  Hence the callback is used to deliver events to this
+ * encoder or event consumer.  The product is announced via an regular encoder
+ * event.
+ *
+ * @note We tried the route of using a BEREncoderCallback here and well it was
+ * ugly the event consumer producer based mechanism was a much better more
+ * specific approach.  Plus it got confusing: we started confusing callbacks.
+ * There was a callback for getting event then another callback for producing
+ * them.  It got confusing fast.
  *
- * 
  * @author <a href="mailto:directory-dev@incubator.apache.org"> Apache Directory
  *         Project</a> $Rev$
  */
 public class BEREncoder extends AbstractStatefulEncoder
+        implements TupleEventConsumer
 {
     private static final int DEFAULT_BUFSZ = 32;
     private ByteBuffer buf = null;
-    private BEREncoderCallback berCb;
 
 
     /**
@@ -54,7 +61,6 @@
     public BEREncoder( int bufSz )
     {
         buf = ByteBuffer.allocateDirect( bufSz );
-        berCb = new Callback();
     }
 
 
@@ -76,132 +82,108 @@
     }
 
 
-    /**
-     * Gets the BEREncoderCallback used to send BER TLV Tuple events to this
-     * encoder.   This is separate from the traditional encoder callback used
-     * to emit encode events.
-     *
-     * @return the encoder's BER TLV event callback
+    /*
+     * The idea here is to see if we can encode the tag bytes into the
+     * remaining bytes of the buffer.  If we can then great we do so.
+     * If we cannot then we have to flush out the full buffer with an
+     * encodeOccurred Event.  This signals the production of encoded data
+     * and free's up the buffer to have the tag bytes writen to it.
      */
-    public BEREncoderCallback getBERCallback()
+    public void tag( Tuple tlv )
     {
-        return berCb;
+        if ( buf.remaining() >= tlv.getTagLength() )
+        {
+            tlv.setTag( buf, tlv.getTagLength() );
+        }
+        else
+        {
+            buf.flip();
+            encodeOccurred( buf );
+            buf.clear();
+            tlv.setTag( buf, tlv.getTagLength() );
+        }
     }
 
 
-    /**
-     * Specific callback interface used to send TLV tuple events to this
-     * encoder.  Uses the buffer in this encoder to lay down tag and length
-     * pairs yet passing through chunked values.  A downstream encoder can
-     * consolidate these buffers and flush them to a stream.
-     */
-    class Callback implements BEREncoderCallback
-    {
-        /*
-         * The idea here is to see if we can encode the tag bytes into the
-         * remaining bytes of the buffer.  If we can then great we do so.
-         * If we cannot then we have to flush out the full buffer with an
-         * encodeOccurred Event.  This signals the production of encoded data
-         * and free's up the buffer to have the tag bytes writen to it.
-         */
-        public void tagEncoded( Tuple tlv )
+    /*
+     * Again we have the same dynamic where we no encode the lenght bytes
+     * into the remaining bytes of the buffer.  If we can then great we do
+     * so.  If we cannot then we have to flush out the full buffer with an
+     * encodeOccurred Event.  This signals the production of encoded data
+     * and free's up the buffer to have the length bytes writen to it.
+     */
+    public void length( Tuple tlv )
+    {
+        if ( buf.remaining() >= tlv.getLengthLength() )
         {
-            if ( buf.remaining() >= tlv.getTagLength() )
-            {
-                tlv.setTag( buf, tlv.getTagLength() );
-            }
-            else
-            {
-                buf.flip();
-                BEREncoder.this.encodeOccurred( buf );
-                buf.clear();
-                tlv.setTag( buf, tlv.getTagLength() );
-            }
+            tlv.setLength( buf, tlv.getLengthLength() );
         }
-
-
-        /*
-         * Again we have the same dynamic where we no encode the lenght bytes
-         * into the remaining bytes of the buffer.  If we can then great we do
-         * so.  If we cannot then we have to flush out the full buffer with an
-         * encodeOccurred Event.  This signals the production of encoded data
-         * and free's up the buffer to have the length bytes writen to it.
-         */
-        public void lengthEncoded( Tuple tlv )
+        else
         {
-            if ( buf.remaining() >= tlv.getLengthLength() )
-            {
-                tlv.setLength( buf, tlv.getLengthLength() );
-            }
-            else
-            {
-                buf.flip();
-                BEREncoder.this.encodeOccurred( buf );
-                buf.clear();
-                tlv.setLength( buf, tlv.getLengthLength() );
-            }
+            buf.flip();
+            encodeOccurred( buf );
+            buf.clear();
+            tlv.setLength( buf, tlv.getLengthLength() );
         }
+    }
 
 
-        /*
-         * Here the situation is a little different.  The values are already
-         * chunked so there is no need to copy them into a buffer.  We are
-         * best off passing through this buffer to consumers with an encode but
-         * before we do that we need to check if the present buffer contains
-         * any material that must go out the door first.  Doing this prevents
-         * us from mangling the order of bytes to send.  So if our buf contains
-         * any bytes from previous operations laying down the tag and length
-         * then we must flush it out.  Then we can flush out this chunk.
-         */
-        public void partialValueEncoded( Tuple tlv )
+    /*
+     * Here the situation is a little different.  The values are already
+     * chunked so there is no need to copy them into a buffer.  We are
+     * best off passing through this buffer to consumers with an encode but
+     * before we do that we need to check if the present buffer contains
+     * any material that must go out the door first.  Doing this prevents
+     * us from mangling the order of bytes to send.  So if our buf contains
+     * any bytes from previous operations laying down the tag and length
+     * then we must flush it out.  Then we can flush out this chunk.
+     */
+    public void chunkedValue( Tuple tlv, ByteBuffer chunk )
+    {
+        if ( buf.position() > 0 )
         {
-            if ( buf.position() > 0 )
-            {
-                buf.flip();
-                BEREncoder.this.encodeOccurred( buf );
-                buf.clear();
-            }
-
-            BEREncoder.this.encodeOccurred( tlv.getLastValueChunk() );
+            buf.flip();
+            BEREncoder.this.encodeOccurred( buf );
+            buf.clear();
         }
 
+        encodeOccurred( tlv.getLastValueChunk() );
+    }
 
-        /*
-         * Keep in mind this method signals the end of a Tuple.  It is called
-         * upstream from us by a higher level encoder that generates tuple
-         * streams from objects.  This method simply returns if the object is
-         * a primitive Tuple because all value processing has already occurred
-         * for that tuple.  If on the otherhand the tuple is constructed and of
-         * the indefinate form need to write the termination sequence (two
-         * zeros) down into the stream.  We attempt to do this into the buffer.
-         * If the buffer is full we flush is with an encodeOccurred() event.
-         * Then we write the termination sequence into the buffer and flush
-         * the buffer with an encodeOccurred Event.
-         */
-        public void encodeOccurred( StatefulEncoder encoder, Object encoded )
-        {
-            Tuple tlv = ( Tuple ) encoded;
 
-            if ( tlv.isPrimitive() )
-            {
-                return;
-            }
+    /*
+     * Keep in mind this method signals the end of a Tuple.  It is called
+     * upstream from us by a higher level encoder that generates tuple
+     * streams from objects.  This method simply returns if the object is
+     * a primitive Tuple because all value processing has already occurred
+     * for that tuple.  If on the otherhand the tuple is constructed and of
+     * the indefinate form need to write the termination sequence (two
+     * zeros) down into the stream.  We attempt to do this into the buffer.
+     * If the buffer is full we flush is with an encodeOccurred() event.
+     * Then we write the termination sequence into the buffer and flush
+     * the buffer with an encodeOccurred Event.
+     */
+    public void finish( Tuple tlv )
+    {
+        if ( tlv.isPrimitive() )
+        {
+            return;
+        }
 
-            if ( tlv.isIndefinate() )
+        if ( tlv.isIndefinate() )
+        {
+            if ( buf.remaining() < 2 )
             {
-                if ( buf.remaining() < 2 )
-                {
-                    buf.flip();
-                    BEREncoder.this.encodeOccurred( buf );
-                    buf.clear();
-                }
-
-                buf.put( (byte) 0 );
-                buf.put( (byte) 0 );
                 buf.flip();
-                BEREncoder.this.encodeOccurred( buf );
+                encodeOccurred( buf );
                 buf.clear();
             }
+
+            buf.put( (byte) 0 );
+            buf.put( (byte) 0 );
+            buf.flip();
+            encodeOccurred( buf );
+            buf.clear();
         }
     }
 }

Modified: incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/Tuple.java
==============================================================================
--- incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/Tuple.java	(original)
+++ incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/Tuple.java	Mon Jul 26 21:15:16 2004
@@ -540,28 +540,30 @@
      */
     public void setTag( ByteBuffer octets, int tagLength )
     {
+        int ii = octets.position();
         octets.put( ( byte ) typeClass.getValue() ) ;
         
         if ( ! isPrimitive )
         {
-            octets.put( 0, ( byte ) ( octets.get( 0 ) | BIT_5 ) ) ;
+            octets.put( ii, ( byte ) ( octets.get( ii ) | BIT_5 ) ) ;
         }
         
         if ( tagLength == 1 )
         {
-            octets.put( 0, ( byte ) ( octets.get( 0 ) | id ) ) ;
+            octets.put( ii, ( byte ) ( octets.get( ii ) | id ) ) ;
             return ;
         }
         
-        octets.put( 0, ( byte ) ( octets.get( 0 ) | Tag.SHORT_MASK ) ) ;
+        octets.put( ii, ( byte ) ( octets.get( ii ) | Tag.SHORT_MASK ) ) ;
         
         if ( tagLength >= 2 )
         {
+            ii++;
             octets.put( ( byte ) ( ( int ) 0x7f & id ) ) ;
             
             if ( tagLength > 2 )
             {
-                octets.put( 1, ( byte ) ( octets.get( 1 ) | BIT_7 ) ) ;
+                octets.put( ii, ( byte ) ( octets.get( ii ) | BIT_7 ) ) ;
             }
         }
         else
@@ -579,11 +581,12 @@
          */
         if ( tagLength >= 3 )
         {
+            ii++;
             octets.put( ( byte ) ( ( ( int ) 0x3f80 & id ) >> 7 ) ) ;
             
             if ( tagLength > 3 )
             {
-                octets.put( 2, ( byte ) ( octets.get( 2 ) | BIT_7 ) ) ;
+                octets.put( ii, ( byte ) ( octets.get( ii ) | BIT_7 ) ) ;
             }
         }
         else
@@ -601,11 +604,12 @@
          */
         if ( tagLength >= 4 )
         {
+            ii++;
             octets.put( ( byte ) ( ( ( int ) 0x1fc000 & id ) >> 14 ) ) ;
             
             if ( tagLength > 4 )
             {
-                octets.put( 3, ( byte ) ( octets.get( 3 ) | BIT_7 ) ) ;
+                octets.put( ii, ( byte ) ( octets.get( ii ) | BIT_7 ) ) ;
             }
         }
         else
@@ -623,11 +627,12 @@
          */
         if ( tagLength >= 5 )
         {
+            ii++;
             octets.put( ( byte ) ( ( ( int ) 0x0fe00000 & id ) >> 21 ) ) ;
             
             if ( tagLength > 5 )
             {
-                octets.put( 4, ( byte ) ( octets.get( 4 ) | BIT_7 ) ) ;
+                octets.put( ii, ( byte ) ( octets.get( ii ) | BIT_7 ) ) ;
             }
         }
         else

Added: incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/TupleEventConsumer.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/TupleEventConsumer.java	Mon Jul 26 21:15:16 2004
@@ -0,0 +1,34 @@
+/*
+ *   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;
+
+
+/**
+ * Experimental shared interface for both Tuple event producers and consumers.
+ * 
+ * @author <a href="mailto:directory-dev@incubator.apache.org"> Apache Directory
+ *         Project</a> $Rev$
+ */
+public interface TupleEventConsumer
+{
+    public void tag( Tuple tlv );
+    public void length( Tuple tlv );
+    public void chunkedValue( Tuple tlv, ByteBuffer chunk );
+    public void finish( Tuple tlv );
+}

Added: incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/TupleEventProducer.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/TupleEventProducer.java	Mon Jul 26 21:15:16 2004
@@ -0,0 +1,29 @@
+/*
+ *   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;
+
+
+/**
+ * Document me.
+ * 
+ * @author <a href="mailto:directory-dev@incubator.apache.org"> Apache Directory
+ *         Project</a> $Rev$
+ */
+public interface TupleEventProducer
+{
+    public void attach( TupleEventConsumer consumer );
+}

Copied: incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/TupleTreeAnalyzer.java (from rev 9765, incubator/directory/snickers/trunk/ber/src/java/org/apache/snickers/ber/TupleTreeAnalyzer.java)
==============================================================================
--- incubator/directory/snickers/trunk/ber/src/java/org/apache/snickers/ber/TupleTreeAnalyzer.java	(original)
+++ incubator/directory/snickers/trunk/ber-codec/src/java/org/apache/snickers/ber/TupleTreeAnalyzer.java	Mon Jul 26 21:15:16 2004
@@ -17,6 +17,12 @@
 package org.apache.snickers.ber ;
 
 
+import org.apache.commons.codec.stateful.CallbackHistory;
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.collections.IteratorUtils;
+import org.apache.snickers.ber.primitives.UniversalTag;
+
 import javax.swing.JMenu ;
 import javax.swing.JTree ;
 import javax.swing.JFrame ;
@@ -29,7 +35,11 @@
 import javax.swing.JSplitPane ;
 import javax.swing.JScrollPane ;
 import javax.swing.JFileChooser ;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.event.TreeSelectionEvent;
 import javax.swing.tree.DefaultTreeModel ;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
 
 import java.awt.Toolkit ;
 import java.awt.Dimension ;
@@ -37,6 +47,9 @@
 import java.awt.event.ActionEvent ;
 import java.awt.event.WindowEvent ;
 import java.awt.event.ActionListener ;
+import java.nio.ByteBuffer;
+import java.util.Enumeration;
+import java.io.*;
 
 
 /**
@@ -46,10 +59,30 @@
  * Apache Directory Project</a>
  * @version $Rev$
  */
-public class TupleTreeAnalyzer extends JFrame 
+public class TupleTreeAnalyzer extends JFrame implements TreeSelectionListener
 {
-    DefaultMutableTupleNode root = null ;
-    
+    private BorderLayout layout = new BorderLayout();
+    private JLabel statusBar = new JLabel("Ready");
+    private JSplitPane jSplitPane1 = new JSplitPane();
+    private JScrollPane jScrollPane1 = new JScrollPane();
+    private JPanel jPanel1 = new JPanel();
+    private JTree jTree1 = new JTree();
+    private JPanel jPanel2 = new JPanel();
+    private JPanel jPanel5 = new JPanel();
+    private JPanel jPanel3 = new JPanel();
+    private JPanel jPanel4 = new JPanel();
+    private JLabel jLabel1 = new JLabel();
+    private JLabel jLabel3 = new JLabel();
+    private JLabel jLabel2 = new JLabel();
+    private JScrollPane jScrollPane2 = new JScrollPane();
+    private JTextArea jTextArea1 = new JTextArea();
+    private JTextField jTextField1 = new JTextField();
+    private JTextField jTextField3 = new JTextField();
+    private JTextField jTextField2 = new JTextField();
+
+    private DefaultMutableTupleNode root = null ;
+
+
     /** Creates new form JFrame */
     public TupleTreeAnalyzer( DefaultMutableTupleNode root ) 
     {
@@ -59,7 +92,27 @@
         pack() ;
     }
 
-    /** This method is called from within 
+
+    public TupleTreeAnalyzer( byte[] encoded ) throws DecoderException
+    {
+        this( ByteBuffer.wrap( encoded ) );
+    }
+
+
+    public TupleTreeAnalyzer( ByteBuffer encoded ) throws DecoderException
+    {
+        TupleTreeDecoder decoder = new TupleTreeDecoder();
+        CallbackHistory history = new CallbackHistory();
+        decoder.setCallback( history );
+        decoder.decode( encoded );
+        root = ( DefaultMutableTupleNode ) history.getMostRecent();
+
+        initGUI();
+        pack();
+    }
+
+
+    /** This method is called from within
      * the constructor to initialize the form. */
     private void initGUI() {
 
@@ -104,7 +157,7 @@
                 public void actionPerformed(java.awt.event.ActionEvent e) {
                     int returnVal = fc.showOpenDialog(TupleTreeAnalyzer.this);
                     if (returnVal == javax.swing.JFileChooser.APPROVE_OPTION) {
-                        java.io.File file = fc.getSelectedFile();
+                        //java.io.File file = fc.getSelectedFile();
                         // Write your code here what to do with selected file
                     } else {
                         // Write your code here what to do if user has canceled
@@ -120,7 +173,7 @@
                 public void actionPerformed(java.awt.event.ActionEvent e) {
                     int returnVal = fc.showSaveDialog(TupleTreeAnalyzer.this);
                     if (returnVal == JFileChooser.APPROVE_OPTION) {
-                        java.io.File file = fc.getSelectedFile();
+                        //java.io.File file = fc.getSelectedFile();
                         // Write your code here what to do with selected file
                     } else {
 // Write your code here what to do if user has canceled Save dialog
@@ -155,8 +208,8 @@
         jPanel5.add(jLabel3);
         jPanel5.add(jTextField3);
         jTextField3.setText("");
-        jTextField3.setMinimumSize(new java.awt.Dimension(104, 25));
-        jTextField3.setPreferredSize(new java.awt.Dimension(104, 25));
+        jTextField3.setMinimumSize(new java.awt.Dimension(184, 25));
+        jTextField3.setPreferredSize(new java.awt.Dimension(184, 25));
         jSplitPane1.setLastDividerLocation(50);
         jSplitPane1.setDividerLocation(180);
         jSplitPane1.add(jScrollPane1, javax.swing.JSplitPane.LEFT);
@@ -212,12 +265,12 @@
         jTextArea1.setText("");
         jScrollPane2.getViewport().add(jTextArea1);
         jTextField1.setText("");
-        jTextField1.setMinimumSize(new java.awt.Dimension(104, 25));
-        jTextField1.setPreferredSize(new java.awt.Dimension(104, 25));
+        jTextField1.setMinimumSize(new java.awt.Dimension(164, 25));
+        jTextField1.setPreferredSize(new java.awt.Dimension(164, 25));
         jTextField1.setEditable(true);
         jTextField2.setText("");
-        jTextField2.setPreferredSize(new java.awt.Dimension(104,25));
-        jTextField2.setMinimumSize(new java.awt.Dimension(104,25));
+        jTextField2.setPreferredSize(new java.awt.Dimension(164,25));
+        jTextField2.setMinimumSize(new java.awt.Dimension(164,25));
         jTextField2.setEditable(true);
         jScrollPane2.setVerticalScrollBarPolicy(
                 javax.swing.JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
@@ -225,11 +278,15 @@
                 javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
         jScrollPane2.setBorder(null);
         
-        jTree1.setModel( new DefaultTreeModel( root ) ) ;
+        jTree1.setModel( new DefaultTreeModel(
+                new TupleTreeNodeAdapter( root ) ) );
+        jTree1.getSelectionModel().addTreeSelectionListener( this );
     }
 
     /** Exit the Application */
-    private void exitForm(WindowEvent evt) {
+    private void exitForm(WindowEvent evt)
+    {
+        System.out.println("Closing window: " + evt.getWindow().getName());
         System.exit(0);
     }
 
@@ -248,22 +305,188 @@
         setVisible(true);
     }
 
-    private BorderLayout layout = new BorderLayout();
-    private JLabel statusBar = new JLabel("Ready");
-    private JSplitPane jSplitPane1 = new JSplitPane();
-    private JScrollPane jScrollPane1 = new JScrollPane();
-    private JPanel jPanel1 = new JPanel();
-    private JTree jTree1 = new JTree();
-    private JPanel jPanel2 = new JPanel();
-    private JPanel jPanel5 = new JPanel();
-    private JPanel jPanel3 = new JPanel();
-    private JPanel jPanel4 = new JPanel();
-    private JLabel jLabel1 = new JLabel();
-    private JLabel jLabel3 = new JLabel();
-    private JLabel jLabel2 = new JLabel();
-    private JScrollPane jScrollPane2 = new JScrollPane();
-    private JTextArea jTextArea1 = new JTextArea();
-    private JTextField jTextField1 = new JTextField();
-    private JTextField jTextField3 = new JTextField();
-    private JTextField jTextField2 = new JTextField();
+
+    public void valueChanged( TreeSelectionEvent e )
+    {
+        TreePath path = e.getPath();
+        TupleTreeNodeAdapter node = ( TupleTreeNodeAdapter )
+                path.getLastPathComponent();
+        TupleNode tn = node.getTupleNode();
+        Tuple tuple = tn.getTuple();
+
+        TypeClass type = TypeClass.getTypeClass( tuple.getRawTag() >> 24 );
+        jTextField3.setText( type.getName() );
+
+
+        if ( tuple.getLength() == Length.INDEFINATE )
+        {
+            jTextField2.setText( "INDEFINATE" );
+        }
+        else
+        {
+            jTextField2.setText( Integer.toString( tuple.getLength() ) );
+        }
+
+        if ( type.equals( TypeClass.UNIVERSAL ) )
+        {
+            UniversalTag tag = UniversalTag.getUniversalTag( tuple.getRawTag() );
+            jTextField1.setText( tag.getName() );
+        }
+        else
+        {
+            jTextField1.setText( Integer.toString( tuple.getId() ) );
+        }
+
+        if ( tuple.isPrimitive() )
+        {
+            ByteBuffer buf = ( ByteBuffer ) tuple.getLastValueChunk().rewind();
+            byte[] bites = new byte[buf.remaining()];
+            buf.get( bites );
+            jTextArea1.setText( new String( Hex.encodeHex( bites ) ) );
+            jTextArea1.setToolTipText( "String: " + new String( bites ) );
+        }
+        else
+        {
+            jTextArea1.setText( "N/A" );
+            jTextArea1.setToolTipText( null );
+        }
+    }
+
+
+    class TupleTreeNodeAdapter implements TreeNode
+    {
+        DefaultMutableTupleNode node;
+
+
+        TupleTreeNodeAdapter( DefaultMutableTupleNode node )
+        {
+            this.node = node;
+        }
+
+
+        public int getChildCount()
+        {
+            return node.getChildCount();
+        }
+
+        public boolean getAllowsChildren()
+        {
+            return !node.getTuple().isPrimitive();
+        }
+
+        public boolean isLeaf()
+        {
+            return node.getChildCount() == 0;
+        }
+
+        public Enumeration children()
+        {
+            return IteratorUtils.asEnumeration( node.getChildren() );
+        }
+
+        public TreeNode getParent()
+        {
+            return new TupleTreeNodeAdapter( ( DefaultMutableTupleNode )
+                    node.getParentTupleNode() );
+        }
+
+        public TreeNode getChildAt( int childIndex )
+        {
+            return new TupleTreeNodeAdapter( ( DefaultMutableTupleNode )
+                    node.getChildTupleNodeAt( childIndex ) );
+        }
+
+        public int getIndex( TreeNode node )
+        {
+            DefaultMutableTupleNode tn =
+                    ( ( TupleTreeNodeAdapter ) node ).getTupleNode();
+            return this.node.getIndex( tn );
+        }
+
+        DefaultMutableTupleNode getTupleNode()
+        {
+            return node;
+        }
+
+        public String toString()
+        {
+            StringBuffer buf = new StringBuffer();
+            Tuple tuple = node.getTuple();
+            TypeClass type =
+                    TypeClass.getTypeClass( node.getTuple().getRawTag() >> 24 );
+            int id = Tag.getTagId( tuple.getRawTag() );
+
+            buf.append( "[" ).append( type.getName() ).append( "][" )
+                    .append( id ).append( "]" ).append( "[" )
+                    .append( tuple.getLength() ).append( "]" );
+
+            return buf.toString();
+        }
+
+    }
+
+
+    public static void main( String [] args )
+    {
+        JFileChooser fc = new JFileChooser( "." );
+        fc.setFileFilter( new javax.swing.filechooser.FileFilter()
+        {
+            public boolean accept( File f )
+            {
+                return f.isDirectory() || f.getName().endsWith( ".ber" );
+            }
+
+            public String getDescription()
+            {
+                return "BER encoded data files";
+            }
+        }
+        );
+        fc.showOpenDialog( null );
+        File file = fc.getSelectedFile();
+
+        if ( file == null )
+        {
+            System.exit( 0 );
+        }
+
+        FileInputStream in = null;
+
+        try
+        {
+            in = new FileInputStream( file );
+        }
+        catch ( FileNotFoundException e )
+        {
+            e.printStackTrace();
+            System.exit( -1 );
+        }
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        try
+        {
+            int ch = -1;
+            while( ( ch = in.read() ) != -1 )
+            {
+                out.write( ch );
+            }
+        }
+        catch ( IOException e )
+        {
+            e.printStackTrace();
+            System.exit( -1 );
+        }
+
+        TupleTreeAnalyzer analyzer;
+        try
+        {
+            analyzer = new TupleTreeAnalyzer( out.toByteArray() );
+            analyzer.startup();
+        }
+        catch ( DecoderException e )
+        {
+            e.printStackTrace();
+            System.exit( -1 );
+        }
+    }
 }

Modified: incubator/directory/snickers/trunk/ber-codec/src/test/org/apache/snickers/ber/BEREncoderTest.java
==============================================================================
--- incubator/directory/snickers/trunk/ber-codec/src/test/org/apache/snickers/ber/BEREncoderTest.java	(original)
+++ incubator/directory/snickers/trunk/ber-codec/src/test/org/apache/snickers/ber/BEREncoderTest.java	Mon Jul 26 21:15:16 2004
@@ -64,67 +64,210 @@
     }
 
 
+
+    /**
+     * Produces a primitive tuple and pumps it through the encoder while
+     * listening to the output of the encoder collecting the output bytes into
+     * one buffer.  Then the collected data is compared with the expected
+     * encoded data.
+     */
     public void testPrimitives()
     {
+        // prepare tlv and generate an integer tag event
         Tuple tlv = new Tuple();
         tlv.setTag( UniversalTag.INTEGER );
-        encoder.getBERCallback().tagEncoded( tlv );
+        encoder.tag( tlv );
 
+        // generate a length event
         tlv.setLength( 1 );
-        encoder.getBERCallback().lengthEncoded( tlv );
+        encoder.length( tlv );
+
+        // generate a value event
+        byte[] value = new byte[] { (byte) 10 };
+        ByteBuffer chunk = ByteBuffer.wrap( value );
+        tlv.setLastValueChunk( chunk );
+        encoder.chunkedValue( tlv, chunk );
 
-        tlv.setLastValueChunk( ByteBuffer.wrap( new byte[] { (byte) 10 }) );
-        encoder.getBERCallback().partialValueEncoded( tlv );
-        encoder.getBERCallback().encodeOccurred( encoder, tlv );
+        // not really necessary but here for completeness
+        encoder.finish( tlv );
 
+        // generate the expected encoded bytes
         ArrayList list = new ArrayList();
-        list.add( ByteBuffer.wrap( new byte[] { (byte) 10 } ) );
+        list.add( ByteBuffer.wrap( value ) );
         ByteBuffer buf = tlv.toEncodedBuffer( list );
-
         byte[] correctBytes = new byte[buf.remaining()];
         buf.get( correctBytes );
 
+        // gather the collected encoded bytes
         collector.flip();
         byte[] encodedBytes = new byte[collector.remaining()];
         collector.get( encodedBytes );
 
+        // compare the two
         assertTrue( ArrayUtils.isEquals( correctBytes, encodedBytes ) );
     }
 
 
-    public void testConstructedDefinateLength()
+    /**
+     * Produces the tlv events for constructed TLV of definate length.
+     */
+    public void testConstructedDefinateLength1()
     {
+        // prepare top level TLV of sequence with length of 3
         Tuple top = new Tuple();
-        top.setTag( UniversalTag.SEQUENCE_SEQUENCE_OF );
-        encoder.getBERCallback().tagEncoded( top );
+        top.setTag( UniversalTag.SEQUENCE_SEQUENCE_OF, false );
+        encoder.tag( top );
         top.setLength( 3 );
-        encoder.getBERCallback().lengthEncoded( top );
+        encoder.length( top );
 
+        // prepare single nested child tlv
         Tuple tlv = new Tuple();
         tlv.setTag( UniversalTag.INTEGER );
-        encoder.getBERCallback().tagEncoded( tlv );
+        encoder.tag( tlv );
+        tlv.setLength( 1 );
+        encoder.length( tlv );
+        byte[] value = new byte[] { (byte) 10 };
+        ByteBuffer chunk = ByteBuffer.wrap( value );
+        tlv.setLastValueChunk( chunk );
+        encoder.chunkedValue( tlv, chunk );
+        encoder.finish( tlv );
+        encoder.finish( top );
+
+        // prepare the expected correct sequence of encoded bytes
+        ArrayList list = new ArrayList();
+        ByteBuffer all = ByteBuffer.wrap( new byte[64] ) ;
+        all.put( top.toEncodedBuffer( list ) );
+        list.add( ByteBuffer.wrap( value ) );
+        all.put( tlv.toEncodedBuffer( list ) );
+        all.flip();
+        byte[] correctBytes = new byte[all.remaining()];
+        all.get( correctBytes );
+
+        // gather the collected encoded bytes
+        collector.flip();
+        byte[] encodedBytes = new byte[collector.remaining()];
+        collector.get( encodedBytes );
+
+        // compare correct with encoded
+        assertTrue( ArrayUtils.isEquals( correctBytes, encodedBytes ) );
+    }
+
+
+    /**
+     * Produces the tlv events for constructed TLV of definate length.
+     */
+    public void testConstructedDefinateLength2()
+    {
+        // prepare top level TLV of sequence with length of 3
+        Tuple top = new Tuple();
+        top.setTag( UniversalTag.SEQUENCE_SEQUENCE_OF, false );
+        encoder.tag( top );
+        top.setLength( 8 );
+        encoder.length( top );
+
+        // prepare the expected correct sequence of encoded bytes
+        ArrayList list = new ArrayList();
+        ByteBuffer all = ByteBuffer.wrap( new byte[64] ) ;
+        all.put( top.toEncodedBuffer( list ) );
 
+        // prepare single nested child tlv
+        Tuple tlv = new Tuple();
+        tlv.setTag( UniversalTag.INTEGER );
+        encoder.tag( tlv );
         tlv.setLength( 1 );
-        encoder.getBERCallback().lengthEncoded( tlv );
+        encoder.length( tlv );
+        byte[] value = new byte[] { (byte) 10 };
+        ByteBuffer chunk = ByteBuffer.wrap( value );
+        tlv.setLastValueChunk( chunk );
+        encoder.chunkedValue( tlv, chunk );
+        encoder.finish( tlv );
+        list.add( ByteBuffer.wrap( value ) );
+        all.put( tlv.toEncodedBuffer( list ) );
+
+        tlv.setTag( UniversalTag.INTEGER );
+        encoder.tag( tlv );
+        tlv.setLength( 3 );
+        encoder.length( tlv );
+        value = new byte[] { (byte) 2, 7, 12 };
+        chunk = ByteBuffer.wrap( value );
+        tlv.setLastValueChunk( chunk );
+        encoder.chunkedValue( tlv, chunk );
+        encoder.finish( tlv );
+        encoder.finish( top );
+        list.add( ByteBuffer.wrap( value ) );
+        all.put( tlv.toEncodedBuffer( list ) );
+
+        // prepare the correct buffers
+        all.flip();
+        byte[] correctBytes = new byte[all.remaining()];
+        all.get( correctBytes );
+
+        // gather the collected encoded bytes
+        collector.flip();
+        byte[] encodedBytes = new byte[collector.remaining()];
+        collector.get( encodedBytes );
 
-        tlv.setLastValueChunk( ByteBuffer.wrap( new byte[] { (byte) 10 }) );
-        encoder.getBERCallback().partialValueEncoded( tlv );
+        // compare correct with encoded
+        assertTrue( ArrayUtils.isEquals( correctBytes, encodedBytes ) );
+    }
 
-        encoder.getBERCallback().encodeOccurred( encoder, top );
 
+    /**
+     * Produces the tlv events for constructed TLV of definate length.
+     */
+    public void testConstructedInDefinateLength()
+    {
+        // prepare top level TLV of sequence with length of 3
+        Tuple top = new Tuple();
+        top.setTag( UniversalTag.SEQUENCE_SEQUENCE_OF, false );
+        encoder.tag( top );
+        top.setLength( Length.INDEFINATE );
+        encoder.length( top );
+
+        // prepare the expected correct sequence of encoded bytes
         ArrayList list = new ArrayList();
         ByteBuffer all = ByteBuffer.wrap( new byte[64] ) ;
         all.put( top.toEncodedBuffer( list ) );
 
-        list.add( tlv.getLastValueChunk() );
+        // prepare single nested child tlv
+        Tuple tlv = new Tuple();
+        tlv.setTag( UniversalTag.INTEGER );
+        encoder.tag( tlv );
+        tlv.setLength( 1 );
+        encoder.length( tlv );
+        byte[] value = new byte[] { (byte) 10 };
+        ByteBuffer chunk = ByteBuffer.wrap( value );
+        tlv.setLastValueChunk( chunk );
+        encoder.chunkedValue( tlv, chunk );
+        encoder.finish( tlv );
+        list.add( ByteBuffer.wrap( value ) );
+        all.put( tlv.toEncodedBuffer( list ) );
+
+        tlv.setTag( UniversalTag.INTEGER );
+        encoder.tag( tlv );
+        tlv.setLength( 3 );
+        encoder.length( tlv );
+        value = new byte[] { (byte) 2, 7, 12 };
+        chunk = ByteBuffer.wrap( value );
+        tlv.setLastValueChunk( chunk );
+        encoder.chunkedValue( tlv, chunk );
+        encoder.finish( tlv );
+        encoder.finish( top );
+        list.add( ByteBuffer.wrap( value ) );
         all.put( tlv.toEncodedBuffer( list ) );
+        all.put( (byte) 0 ).put( (byte) 0 );
 
+        // prepare the correct buffers
+        all.flip();
         byte[] correctBytes = new byte[all.remaining()];
         all.get( correctBytes );
 
+        // gather the collected encoded bytes
+        collector.flip();
         byte[] encodedBytes = new byte[collector.remaining()];
         collector.get( encodedBytes );
 
-        //assertTrue( ArrayUtils.isEquals( correctBytes, encodedBytes ) );
+        // compare correct with encoded
+        assertTrue( ArrayUtils.isEquals( correctBytes, encodedBytes ) );
     }
 }

Added: incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/LdapResultEncoder.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/LdapResultEncoder.java	Mon Jul 26 21:15:16 2004
@@ -0,0 +1,108 @@
+/*
+ *   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.ldap.encoder;
+
+import org.apache.snickers.ber.TupleEventProducer;
+import org.apache.snickers.ber.TupleEventConsumer;
+import org.apache.snickers.ber.Tuple;
+import org.apache.snickers.ber.Length;
+import org.apache.snickers.ber.primitives.UniversalTag;
+import org.apache.snickers.ber.primitives.PrimitiveUtils;
+import org.apache.snickers.ldap.LdapTag;
+import org.apache.ldap.common.message.LdapResult;
+
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+
+
+/**
+ * Encodes the elements of an LdapResult into some top level tuple.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org"> Apache Directory
+ *         Project</a> $Rev$
+ */
+public class LdapResultEncoder implements TupleEventProducer
+{
+    TupleEventConsumer consumer = null;
+    Tuple tmp = new Tuple();
+
+
+    public void attach( TupleEventConsumer consumer )
+    {
+        this.consumer = consumer;
+    }
+
+
+    public void encode( LdapResult result )
+    {
+        // Encode the result code
+        tmp.setTag( UniversalTag.ENUMERATED, true );
+        ByteBuffer chunk = ByteBuffer.wrap( PrimitiveUtils
+                .encodeInt( result.getResultCode().getValue() ) ) ;
+        consumer.tag( tmp );
+        tmp.setLength( 1 );
+        consumer.length( tmp );
+        tmp.setLastValueChunk( chunk );
+        consumer.chunkedValue( tmp, chunk );
+        consumer.finish( tmp );
+
+        // Encode the matchedDN
+        tmp.setTag( UniversalTag.OCTET_STRING, true );
+        chunk = ByteBuffer.wrap( result.getMatchedDn().getBytes() );
+        consumer.tag( tmp );
+        tmp.setLength( chunk.remaining() );
+        consumer.length( tmp );
+        tmp.setLastValueChunk( chunk );
+        consumer.chunkedValue( tmp, chunk );
+        consumer.finish( tmp );
+
+        // Encode the errorMsg
+        tmp.setTag( UniversalTag.OCTET_STRING, true );
+        chunk = ByteBuffer.wrap( result.getErrorMessage().getBytes() );
+        consumer.tag( tmp );
+        tmp.setLength( chunk.remaining() );
+        consumer.length( tmp );
+        tmp.setLastValueChunk( chunk );
+        consumer.chunkedValue( tmp, chunk );
+        consumer.finish( tmp );
+
+        if ( result.getReferral() != null &&
+                result.getReferral().getLdapUrls().size() > 0 )
+        {
+            Tuple referrals = new Tuple();
+            referrals.setTag( LdapTag.REFERRAL_TAG, false );
+            consumer.tag( referrals );
+            referrals.setLength( Length.INDEFINATE );
+            consumer.length( referrals );
+
+            Iterator list = result.getReferral().getLdapUrls().iterator();
+            while( list.hasNext() )
+            {
+                tmp.setTag( UniversalTag.OCTET_STRING, true );
+                consumer.tag( tmp );
+                chunk = ByteBuffer.wrap( ( (String) list.next() ).getBytes() );
+                tmp.setLength( chunk.remaining() );
+                consumer.length( tmp );
+                tmp.setLastValueChunk( chunk );
+                consumer.chunkedValue( tmp, chunk );
+                consumer.finish( tmp );
+            }
+
+            consumer.finish( referrals );
+        }
+    }
+}

Modified: incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/SnickersLdapEncoder.java
==============================================================================
--- incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/SnickersLdapEncoder.java	(original)
+++ incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/SnickersLdapEncoder.java	Mon Jul 26 21:15:16 2004
@@ -18,33 +18,67 @@
 
 
 import org.apache.commons.codec.EncoderException;
-import org.apache.commons.codec.stateful.AbstractStatefulEncoder;
 import org.apache.commons.codec.stateful.StatefulEncoder;
+import org.apache.commons.codec.stateful.EncoderCallback;
+import org.apache.commons.codec.stateful.EncoderMonitor;
 import org.apache.ldap.common.message.Message;
 import org.apache.ldap.common.message.MessageTypeEnum;
+import org.apache.ldap.common.message.AbandonRequest;
 import org.apache.snickers.ldap.encoder.abandon.AbandonRequestEncoder;
+import org.apache.snickers.ber.BEREncoder;
 
-import java.util.HashMap;
 
 
 /**
- * A Snickers based LDAP message encoder.  The generated events via the callback
+ * A Snickers based LDAP message producer.  The generated events via the callback
  * are TLV tuples.
  *
  * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
  * @version $Rev$
  */
-public class SnickersLdapEncoder extends AbstractStatefulEncoder
+public class SnickersLdapEncoder implements StatefulEncoder
 {
-    private HashMap encoderMap = new HashMap();
+    AbandonRequestEncoder abandonReqEncoder = new AbandonRequestEncoder();
+    EncoderMonitor monitor;
+    BEREncoder encoder = new BEREncoder();
 
-    public SnickersLdapEncoder()
-    {
-        StatefulEncoder encoder = new AbandonRequestEncoder() ;
-    }
 
     public void encode( Object obj ) throws EncoderException
     {
         Message msg = ( Message ) obj;
+
+
+        switch( msg.getType().getValue() )
+        {
+            case( MessageTypeEnum.ABANDONREQUEST_VAL ):
+                abandonReqEncoder.attach( encoder );
+                abandonReqEncoder.encode( ( AbandonRequest ) obj );
+                break;
+            default:
+                IllegalArgumentException e = new IllegalArgumentException(
+                        "Cannot encode " + obj ) ;
+                monitor.error( this, e );
+                throw e;
+        }
+    }
+
+
+    public void setCallback( EncoderCallback cb )
+    {
+        encoder.setCallback( cb );
+
+        if ( monitor == null )
+        {
+            monitor.callbackSet( this, null, cb );
+            return;
+        }
+    }
+
+
+
+    public void setEncoderMonitor( EncoderMonitor monitor )
+    {
+        this.monitor = monitor;
+        this.encoder.setEncoderMonitor( monitor );
     }
 }

Modified: incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/abandon/AbandonRequestEncoder.java
==============================================================================
--- incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/abandon/AbandonRequestEncoder.java	(original)
+++ incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/abandon/AbandonRequestEncoder.java	Mon Jul 26 21:15:16 2004
@@ -18,11 +18,7 @@
 
 
 import org.apache.commons.codec.EncoderException;
-import org.apache.commons.codec.stateful.AbstractStatefulEncoder;
-import org.apache.snickers.ber.Tuple;
-import org.apache.snickers.ber.Tag;
-import org.apache.snickers.ber.TypeClass;
-import org.apache.snickers.ber.Length;
+import org.apache.snickers.ber.*;
 import org.apache.snickers.ber.primitives.PrimitiveUtils;
 import org.apache.snickers.ber.primitives.UniversalTag;
 import org.apache.snickers.ldap.LdapTag;
@@ -38,28 +34,52 @@
  *         Project</a>
  * @version $Rev$
  */
-public class AbandonRequestEncoder extends AbstractStatefulEncoder
+public class AbandonRequestEncoder implements TupleEventProducer
 {
-    Tuple tlv = new Tuple();
+    private TupleEventConsumer consumer = null;
+    private Tuple top = new Tuple();
+    private Tuple msgId = new Tuple();
+    private Tuple abandonId = new Tuple();
 
-    public void encode( Object obj ) throws EncoderException
+
+    public AbandonRequestEncoder()
     {
-        AbandonRequest req = ( AbandonRequest ) obj;
+        top.setTag( UniversalTag.SEQUENCE_SEQUENCE_OF, false );
+        msgId.setTag( UniversalTag.INTEGER );
+        abandonId.setTag( LdapTag.ABANDON_REQUEST );
+    }
+
 
-        tlv.setTag( UniversalTag.SEQUENCE_SEQUENCE_OF, false );
-        tlv.setLength( Length.INDEFINATE );
-        super.encodeOccurred( tlv );
+    public void encode( AbandonRequest req ) throws EncoderException
+    {
+        consumer.tag( top );
+        top.setLength( Length.INDEFINATE );
+        consumer.length( top );
 
         byte[] encoded = PrimitiveUtils.encodeInt( req.getMessageId() );
-        tlv.setTag( UniversalTag.INTEGER, true );
-        tlv.setLength( encoded.length );
-        tlv.setLastValueChunk( ByteBuffer.wrap( encoded ) );
-        super.encodeOccurred( tlv );
+        consumer.tag( msgId );
+        msgId.setLength( encoded.length );
+        consumer.length( msgId );
+        ByteBuffer chunk = ByteBuffer.wrap( encoded );
+        msgId.setLastValueChunk( chunk );
+        consumer.chunkedValue( msgId, chunk );
+        consumer.finish( msgId );
 
         encoded = PrimitiveUtils.encodeInt( req.getAbandoned() );
-        tlv.setTag( LdapTag.ABANDON_REQUEST );
-        tlv.setLength( encoded.length );
-        tlv.setLastValueChunk( ByteBuffer.wrap( encoded ) );
-        super.encodeOccurred( tlv );
+        consumer.tag( abandonId );
+        abandonId.setLength( encoded.length );
+        consumer.length( abandonId );
+        chunk = ByteBuffer.wrap( encoded );
+        abandonId.setLastValueChunk( chunk );
+        consumer.chunkedValue( abandonId, chunk );
+        consumer.finish( abandonId );
+        consumer.finish( top );
+    }
+
+
+
+    public void attach( TupleEventConsumer consumer )
+    {
+        this.consumer = consumer;
     }
 }

Added: incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/bind/BindRequestEncoder.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/bind/BindRequestEncoder.java	Mon Jul 26 21:15:16 2004
@@ -0,0 +1,131 @@
+/*
+ *   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.ldap.encoder.bind;
+
+
+import org.apache.snickers.ber.TupleEventProducer;
+import org.apache.snickers.ber.TupleEventConsumer;
+import org.apache.snickers.ber.Tuple;
+import org.apache.snickers.ber.Length;
+import org.apache.snickers.ber.primitives.UniversalTag;
+import org.apache.snickers.ber.primitives.PrimitiveUtils;
+import org.apache.snickers.ber.primitives.ContextSpecificTag;
+import org.apache.snickers.ldap.LdapTag;
+import org.apache.ldap.common.message.AbandonRequest;
+import org.apache.ldap.common.message.BindRequest;
+import org.apache.commons.codec.EncoderException;
+import org.apache.commons.lang.NotImplementedException;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * A bind request encoder which transforms LDAP BindRequest stubs into Tuple
+ * events.
+ *
+ * @warning only simple binds have been implemented
+ * @todo implement SASL binds
+ * @author <a href="mailto:directory-dev@incubator.apache.org"> Apache Directory
+ *         Project</a> $Rev$
+ */
+public class BindRequestEncoder implements TupleEventProducer
+{
+    private TupleEventConsumer consumer = null;
+    private Tuple top = new Tuple();
+    private Tuple tmp = new Tuple();
+    private Tuple bind = new Tuple();
+
+
+    public void attach( TupleEventConsumer consumer )
+    {
+        this.consumer = consumer;
+    }
+
+
+    public BindRequestEncoder()
+    {
+        top.setTag( UniversalTag.SEQUENCE_SEQUENCE_OF, false );
+        tmp.setTag( UniversalTag.INTEGER );
+        bind.setTag( LdapTag.BIND_REQUEST, false );
+    }
+
+
+    public void encode( BindRequest req ) throws EncoderException
+    {
+        consumer.tag( top );
+        top.setLength( Length.INDEFINATE );
+        consumer.length( top );
+
+        byte[] encoded = PrimitiveUtils.encodeInt( req.getMessageId() );
+        consumer.tag( tmp );
+        tmp.setLength( encoded.length );
+        consumer.length( tmp );
+        ByteBuffer chunk = ByteBuffer.wrap( encoded );
+        tmp.setLastValueChunk( chunk );
+        consumer.chunkedValue( tmp, chunk );
+        consumer.finish( tmp );
+
+
+        // Start working the bind request structure here
+
+        consumer.tag( bind );
+        bind.setLength( Length.INDEFINATE );
+        consumer.length( bind );
+
+        // encode and send the primitive int for the LDAP bind version
+        byte[] version = PrimitiveUtils.encodeInt( req.isVersion3() ? 3 : 2 );
+        chunk = ByteBuffer.wrap( version ) ;
+        tmp.setTag( UniversalTag.INTEGER, true );
+        consumer.tag( tmp );
+        tmp.setLength( 1 );
+        consumer.length( tmp );
+        tmp.setLastValueChunk( chunk );
+        consumer.chunkedValue( tmp, chunk );
+        consumer.finish( tmp );
+
+
+        // encode and send the primitive LDAPDN for the Bind [as] name
+        chunk = ByteBuffer.wrap( req.getName().getBytes() );
+        tmp.setTag( UniversalTag.OCTET_STRING );
+        consumer.tag( tmp );
+        tmp.setLength( chunk.remaining() );
+        consumer.length( tmp );
+        tmp.setLastValueChunk( chunk );
+        consumer.chunkedValue( tmp, chunk );
+        consumer.finish( tmp );
+
+
+        if ( req.isSimple() )
+        {
+            tmp.setTag( LdapTag.CONTEXT_SPECIFIC_TAG_0, true );
+            consumer.tag( tmp );
+            chunk = ByteBuffer.wrap( req.getCredentials() );
+            tmp.setLength( chunk.remaining() );
+            consumer.length( tmp );
+            tmp.setLastValueChunk( chunk );
+            consumer.chunkedValue( tmp, chunk );
+            consumer.finish( tmp );
+
+            consumer.finish( bind );
+            consumer.finish( top );
+            return;
+        }
+
+
+        throw new NotImplementedException( "SASL binds not implemented" );
+    }
+}

Added: incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/bind/BindResponseEncoder.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/bind/BindResponseEncoder.java	Mon Jul 26 21:15:16 2004
@@ -0,0 +1,102 @@
+/*
+ *   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.ldap.encoder.bind;
+
+
+import org.apache.snickers.ber.TupleEventProducer;
+import org.apache.snickers.ber.TupleEventConsumer;
+import org.apache.snickers.ber.Tuple;
+import org.apache.snickers.ber.Length;
+import org.apache.snickers.ber.primitives.UniversalTag;
+import org.apache.snickers.ber.primitives.PrimitiveUtils;
+import org.apache.snickers.ldap.LdapTag;
+import org.apache.snickers.ldap.encoder.LdapResultEncoder;
+import org.apache.ldap.common.message.BindResponse;
+import org.apache.ldap.common.message.LdapResult;
+import org.apache.commons.codec.EncoderException;
+import org.apache.commons.lang.NotImplementedException;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * A bind response encoder which transforms LDAP BindResponse stubs into Tuple
+ * events.
+ *
+ * @warning only simple binds have been implemented
+ * @todo implement SASL binds
+ * @author <a href="mailto:directory-dev@incubator.apache.org"> Apache Directory
+ *         Project</a> $Rev$
+ */
+public class BindResponseEncoder implements TupleEventProducer
+{
+    private TupleEventConsumer consumer = null;
+    private LdapResultEncoder resultEncoder = new LdapResultEncoder();
+    private Tuple top = new Tuple();
+    private Tuple tmp = new Tuple();
+    private Tuple bind = new Tuple();
+
+
+    public void attach( TupleEventConsumer consumer )
+    {
+        this.consumer = consumer;
+        resultEncoder.attach( consumer );
+    }
+
+
+    public BindResponseEncoder()
+    {
+        top.setTag( UniversalTag.SEQUENCE_SEQUENCE_OF, false );
+        tmp.setTag( UniversalTag.INTEGER );
+        bind.setTag( LdapTag.BIND_RESPONSE, false );
+    }
+
+
+    public void encode( BindResponse resp ) throws EncoderException
+    {
+        consumer.tag( top );
+        top.setLength( Length.INDEFINATE );
+        consumer.length( top );
+
+        byte[] encoded = PrimitiveUtils.encodeInt( resp.getMessageId() );
+        consumer.tag( tmp );
+        tmp.setLength( encoded.length );
+        consumer.length( tmp );
+        ByteBuffer chunk = ByteBuffer.wrap( encoded );
+        tmp.setLastValueChunk( chunk );
+        consumer.chunkedValue( tmp, chunk );
+        consumer.finish( tmp );
+
+
+        // Start working the bind request structure here
+        consumer.tag( bind );
+        bind.setLength( Length.INDEFINATE );
+        consumer.length( bind );
+
+        // Encode the result code
+        LdapResult result = resp.getLdapResult();
+        resultEncoder.encode( result );
+
+        if ( resp.getServerSaslCreds() != null )
+        {
+            throw new NotImplementedException( "SASL binds not implemented" ) ;
+        }
+
+        consumer.finish( bind );
+        consumer.finish( top );
+    }
+}

Added: incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/search/SearchRequestEncoder.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/trunk/ldap-ber-provider/src/java/org/apache/snickers/ldap/encoder/search/SearchRequestEncoder.java	Mon Jul 26 21:15:16 2004
@@ -0,0 +1,84 @@
+/*
+ *   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.ldap.encoder.search;
+
+
+import org.apache.snickers.ber.TupleEventProducer;
+import org.apache.snickers.ber.TupleEventConsumer;
+import org.apache.snickers.ber.Tuple;
+import org.apache.snickers.ber.Length;
+import org.apache.snickers.ber.primitives.UniversalTag;
+import org.apache.snickers.ber.primitives.PrimitiveUtils;
+import org.apache.snickers.ldap.LdapTag;
+import org.apache.ldap.common.message.SearchRequest;
+import org.apache.commons.codec.EncoderException;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * A search request encoder which transforms LDAP SearchRequest stubs into Tuple
+ * events.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org"> Apache Directory
+ *         Project</a> $Rev$
+ */
+public class SearchRequestEncoder implements TupleEventProducer
+{
+    private TupleEventConsumer consumer = null;
+    private Tuple top = new Tuple();
+    private Tuple tmp = new Tuple();
+    private Tuple search = new Tuple();
+
+
+    public void attach( TupleEventConsumer consumer )
+    {
+        this.consumer = consumer;
+    }
+
+
+    public SearchRequestEncoder()
+    {
+        top.setTag( UniversalTag.SEQUENCE_SEQUENCE_OF, false );
+        tmp.setTag( UniversalTag.INTEGER );
+        search.setTag( LdapTag.SEARCH_REQUEST, false );
+    }
+
+
+    public void encode( SearchRequest req ) throws EncoderException
+    {
+        consumer.tag( top );
+        top.setLength( Length.INDEFINATE );
+        consumer.length( top );
+
+        byte[] encoded = PrimitiveUtils.encodeInt( req.getMessageId() );
+        consumer.tag( tmp );
+        tmp.setLength( encoded.length );
+        consumer.length( tmp );
+        ByteBuffer chunk = ByteBuffer.wrap( encoded );
+        tmp.setLastValueChunk( chunk );
+        consumer.chunkedValue( tmp, chunk );
+        consumer.finish( tmp );
+
+
+        // Start working the bind request structure here
+
+        consumer.tag( search );
+        search.setLength( Length.INDEFINATE );
+        consumer.length( search );
+    }
+}

Added: incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/AbstractEncoderTest.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/AbstractEncoderTest.java	Mon Jul 26 21:15:16 2004
@@ -0,0 +1,90 @@
+/*
+ *   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.ldap.encoder;
+
+import junit.framework.TestCase;
+import org.apache.snickers.ber.BEREncoder;
+import org.apache.snickers.ber.TupleEventProducer;
+import org.apache.snickers.ldap.BufferUtils;
+import org.apache.ldap.common.message.*;
+import org.apache.commons.codec.stateful.EncoderCallback;
+import org.apache.commons.codec.stateful.StatefulEncoder;
+
+import java.nio.ByteBuffer;
+import java.io.ByteArrayInputStream;
+
+
+/**
+ * Base class for Encoders that are tuple event producers.
+ * 
+ * @author <a href="mailto:directory-dev@incubator.apache.org"> Apache Directory
+ *         Project</a> $Rev$
+ */
+public abstract class AbstractEncoderTest extends TestCase
+        implements EncoderCallback
+{
+    protected TupleEventProducer producer = null;
+    BEREncoder encoder = null;
+    protected ByteBuffer collector = null;
+    private final int bufsz;
+
+
+    public AbstractEncoderTest( String string, int bufsz )
+    {
+        super( string );
+        this.bufsz = bufsz;
+    }
+
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        producer = getProducer();
+        encoder = new BEREncoder();
+        encoder.setCallback( this );
+        producer.attach( encoder );
+        collector = ByteBuffer.wrap( new byte[bufsz] );
+    }
+
+
+    protected abstract TupleEventProducer getProducer();
+
+
+    protected void tearDown() throws Exception
+    {
+        super.tearDown();
+        producer = null;
+        encoder = null;
+        collector = null;
+    }
+
+
+    public void encodeOccurred( StatefulEncoder encoder, Object encoded )
+    {
+        ByteBuffer chunk = ( ByteBuffer ) encoded;
+        collector.put( chunk );
+    }
+
+
+    public static Message decodeEncoded( ByteBuffer encoded )
+    {
+        MessageDecoder decoder = new MessageDecoder();
+        byte[] encodedBytes = BufferUtils.getArray( encoded );
+        ByteArrayInputStream in = new ByteArrayInputStream( encodedBytes );
+        return ( Message ) decoder.decode( null, in );
+    }
+}

Modified: incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/abandon/AbandonRequestEncoderTest.java
==============================================================================
--- incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/abandon/AbandonRequestEncoderTest.java	(original)
+++ incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/abandon/AbandonRequestEncoderTest.java	Mon Jul 26 21:15:16 2004
@@ -16,86 +16,43 @@
  */
 package org.apache.snickers.ldap.encoder.abandon;
 
-import junit.framework.TestCase;
-import org.apache.commons.codec.stateful.EncoderCallback;
-import org.apache.commons.codec.stateful.StatefulEncoder;
-import org.apache.commons.codec.stateful.DecoderCallback;
-import org.apache.commons.codec.stateful.StatefulDecoder;
-import org.apache.snickers.ber.Tuple;
-import org.apache.snickers.ldap.BufferUtils;
+import org.apache.snickers.ber.TupleEventProducer;
+import org.apache.snickers.ldap.encoder.AbstractEncoderTest;
 import org.apache.ldap.common.message.AbandonRequestImpl;
-import org.apache.ldap.common.message.MessageDecoder;
 import org.apache.ldap.common.message.AbandonRequest;
 
-import java.util.ArrayList;
-import java.nio.ByteBuffer;
-import java.io.ByteArrayInputStream;
 
 /**
- * Document me.
+ * Tests to see if we can encode an AbandonRequest using the
+ * AbandonRequestEncoder.
  * 
  * @author <a href="mailto:directory-dev@incubator.apache.org"> Apache Directory
  *         Project</a> $Rev$
  */
-public class AbandonRequestEncoderTest extends TestCase
-        implements EncoderCallback, DecoderCallback
+public class AbandonRequestEncoderTest extends AbstractEncoderTest
 {
-    AbandonRequestEncoder encoder = null;
-    Tuple tlv = null;
-
-
-    protected void setUp() throws Exception
-    {
-        super.setUp();
-        encoder = new AbandonRequestEncoder();
-        encoder.setCallback( this );
-    }
-
-
-    protected void tearDown() throws Exception
+    public AbandonRequestEncoderTest()
     {
-        super.tearDown();
-        encoder = null;
+        super( "AbandonRequestEncoderTest", 32 );
     }
 
 
-    /**
-     * Callback to deliver a fully encoded object.
-     *
-     * @param encoder the stateful encoder driving the callback
-     * @param encoded the object that was encoded
-     */
-    public void encodeOccurred( StatefulEncoder encoder, Object encoded )
+    protected TupleEventProducer getProducer()
     {
-        tlv = ( Tuple ) encoded;
+        return new AbandonRequestEncoder();
     }
 
 
-    /**
-     * Callback to deliver a fully decoded object.
-     *
-     * @param decoder the stateful decoder driving the callback
-     * @param decoded the object that was decoded
-     */
-    public void decodeOccurred( StatefulDecoder decoder, Object decoded )
+    public void testEncode() throws Exception
     {
-    }
+        AbandonRequestImpl req = new AbandonRequestImpl( 5 );
+        req.setAbandoned( 23 );
+        ( ( AbandonRequestEncoder ) producer ).encode( req );
 
+        AbandonRequest decodedReq;
+        decodedReq = ( AbandonRequest ) decodeEncoded( collector );
 
-    public void testEncode() throws Exception
-    {
-//        AbandonRequestImpl req = new AbandonRequestImpl( 5 );
-//        req.setAbandoned( 23 );
-//        encoder.encode( req );
-//
-//        ArrayList valueChuncks = new ArrayList() ;
-//        valueChuncks.add( tlv.getLastValueChunk() );
-//        ByteBuffer encoded = tlv.toEncodedBuffer( valueChuncks );
-//        MessageDecoder decoder = new MessageDecoder();
-//
-//        byte[] encodedBytes = BufferUtils.getArray( encoded );
-//        ByteArrayInputStream in = new ByteArrayInputStream( encodedBytes );
-//
-//        AbandonRequest decodedReq = ( AbandonRequest ) decoder.decode(null,in);
+        assertEquals( req.getMessageId(), decodedReq.getMessageId() );
+        assertEquals( req.getAbandoned(), decodedReq.getAbandoned() );
     }
 }

Added: incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/bind/BindRequestEncoderTest.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/bind/BindRequestEncoderTest.java	Mon Jul 26 21:15:16 2004
@@ -0,0 +1,68 @@
+/*
+ *   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.ldap.encoder.bind;
+
+import org.apache.snickers.ber.TupleEventProducer;
+import org.apache.snickers.ldap.encoder.AbstractEncoderTest;
+import org.apache.ldap.common.message.BindRequestImpl;
+import org.apache.ldap.common.message.BindRequest;
+import org.apache.commons.lang.ArrayUtils;
+
+
+/**
+ * Tests to see if we can encode an AbandonRequest using the
+ * AbandonRequestEncoder.
+ * 
+ * @author <a href="mailto:directory-dev@incubator.apache.org"> Apache Directory
+ *         Project</a> $Rev$
+ */
+public class BindRequestEncoderTest extends AbstractEncoderTest
+{
+    private static final String LDAPDN = "ou=People,dc=example,dc=com";
+    private static final byte[] CREDS = "passwd".getBytes();
+
+
+    public BindRequestEncoderTest()
+    {
+        super( "BindRequestEncoderTest", 128 );
+    }
+
+
+    protected TupleEventProducer getProducer()
+    {
+        return new BindRequestEncoder();
+    }
+
+
+    public void testEncode() throws Exception
+    {
+        BindRequestImpl req = new BindRequestImpl( 5 );
+        req.setVersion3( true );
+        req.setSimple( true );
+        req.setName( LDAPDN );
+        req.setCredentials( CREDS );
+        ( ( BindRequestEncoder ) producer ).encode( req );
+
+        BindRequest decodedReq = ( BindRequest ) decodeEncoded( collector );
+        assertEquals( req.getMessageId(), decodedReq.getMessageId() );
+        assertEquals( req.getVersion3(), decodedReq.getVersion3() );
+        assertEquals( req.getSimple(), decodedReq.getSimple() );
+        assertEquals( req.getName(), decodedReq.getName() );
+        assertTrue( ArrayUtils.isEquals( req.getCredentials(),
+                decodedReq.getCredentials() ) );
+    }
+}

Added: incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/bind/BindResponseEncoderTest.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/trunk/ldap-ber-provider/src/test/org/apache/snickers/ldap/encoder/bind/BindResponseEncoderTest.java	Mon Jul 26 21:15:16 2004
@@ -0,0 +1,103 @@
+/*
+ *   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.ldap.encoder.bind;
+
+import org.apache.snickers.ber.TupleEventProducer;
+import org.apache.snickers.ldap.encoder.AbstractEncoderTest;
+import org.apache.ldap.common.message.*;
+import org.apache.ldap.common.berlib.snacc.ldap_v3.LDAPResultEnum;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.codec.binary.Hex;
+
+import java.util.TreeSet;
+import java.util.Iterator;
+import java.io.FileOutputStream;
+import java.io.File;
+
+
+/**
+ * Tests to see if we can encode an AbandonRequest using the
+ * AbandonRequestEncoder.
+ * 
+ * @author <a href="mailto:directory-dev@incubator.apache.org"> Apache Directory
+ *         Project</a> $Rev$
+ */
+public class BindResponseEncoderTest extends AbstractEncoderTest
+{
+    private static final String LDAPDN = "dc=com";
+
+    public BindResponseEncoderTest()
+    {
+        super( "BindResponseEncoderTest", 128 );
+    }
+
+
+    protected TupleEventProducer getProducer()
+    {
+        return new BindResponseEncoder();
+    }
+
+
+    public void testEncode() throws Exception
+    {
+        BindResponseImpl resp = new BindResponseImpl( 5 );
+        LdapResultImpl result = new LdapResultImpl( resp ) ;
+        resp.setLdapResult( result );
+        result.setResultCode( ResultCodeEnum.SUCCESS );
+        result.setMatchedDn( LDAPDN );
+        result.setErrorMessage( "" );
+        result.setReferral( new ReferralImpl( result ) );
+        result.getReferral().addLdapUrl( "ldap://onehost:389" );
+        result.getReferral().addLdapUrl( "ldap://twohost:389" );
+        result.getReferral().addLdapUrl( "ldap://threehost:389" );
+        ( ( BindResponseEncoder ) producer ).encode( resp );
+
+        MessageEncoder snaccEncoder = new MessageEncoder();
+        byte[] snaccEncoded = snaccEncoder.encode( resp );
+        File cwd = new File( "." );
+        FileOutputStream out = new FileOutputStream( new File(cwd,
+                "BindResponseEncoderTestSnacc.ber" ) );
+        out.write( snaccEncoded );
+
+        collector.flip();
+        byte[] snickersEncoded = new byte[collector.remaining()];
+        collector.get( snickersEncoded );
+        collector.rewind();
+        out = new FileOutputStream( new File(cwd,
+                "BindResponseEncoderTestSnickers.ber" ) );
+        out.write( snickersEncoded );
+
+        BindResponse decodedResp = ( BindResponse ) decodeEncoded( collector );
+        assertEquals( resp.getMessageId(), decodedResp.getMessageId() );
+        LdapResult decodedResult = decodedResp.getLdapResult();
+        assertEquals( result.getErrorMessage(),
+                decodedResult.getErrorMessage() );
+        assertEquals( result.getMatchedDn(), decodedResult.getMatchedDn() );
+        assertEquals( result.getResultCode(), decodedResult.getResultCode() );
+        assertEquals( result.getErrorMessage(),
+                decodedResult.getErrorMessage() );
+
+        assertEquals( result.getReferral().getLdapUrls().size(),
+                decodedResult.getReferral().getLdapUrls().size() );
+        assertTrue( decodedResult.getReferral().getLdapUrls().contains(
+            "ldap://onehost:389" ) );
+        assertTrue( decodedResult.getReferral().getLdapUrls().contains(
+            "ldap://twohost:389" ) );
+        assertTrue( decodedResult.getReferral().getLdapUrls().contains(
+            "ldap://threehost:389" ) );
+    }
+}

Modified: incubator/directory/snickers/trunk/project.xml
==============================================================================
--- incubator/directory/snickers/trunk/project.xml	(original)
+++ incubator/directory/snickers/trunk/project.xml	Mon Jul 26 21:15:16 2004
@@ -160,6 +160,7 @@
               
         <excludes>
             <exclude>**/testutils/*</exclude>
+            <exclude>**/Abstract*</exclude>
         </excludes>
         
         <resources>

Modified: incubator/directory/snickers/trunk/xdocs/ber-codec/BEREncoderDesign.xml
==============================================================================
--- incubator/directory/snickers/trunk/xdocs/ber-codec/BEREncoderDesign.xml	(original)
+++ incubator/directory/snickers/trunk/xdocs/ber-codec/BEREncoderDesign.xml	Mon Jul 26 21:15:16 2004
@@ -13,17 +13,27 @@
 
       <subsection name="Layering Encoders">
         <p>
-          It is a good idea to delegate different levels of functionality to
-          different encoders to divide the responsibilities of each encoder.
-          In many respects we are thinking about stacking multiple BER encoders
-          and multiplexing them as well.
+          It might be a good idea to separate encoder functionality into
+          separate encoder layers.  This way we can isolation operations to
+          divide the responsibilities of each encoder keeping each encoder
+          simple.  We are talking about stacking multiple encoders on top of
+          each other.
         </p>
 
         <p>
-          It might be a good idea to suppose that a TLV event stream is being
-          encoded into a byte buffer.  This then would be the lowest level of
-          BER encoding.  This approach where a low level TLV tuple encoder is
-          used has several benefits:
+          The most primitive teir could be an encoder concerned with writing
+          chunks out to a channel.  On top of that may reside another encoder
+          that converts TLV Tuple Tag, Length and Value events into a stream
+          of chunked buffers.  High level encoders can be designed to take
+          stub instances as and input to produce a stream of TLV tuple events.
+          These events are then pipped into the low level Tuple event encoder,
+          then written out as chunks to a channel.  We really will not be
+          concerned with where the chunks go the event producer consumer
+          pipeline is the primary concern for us.
+        </p>
+
+        <p>
+          There are several benefits to this approach.  Here's a few of them:
         </p>
 
         <ul>
@@ -32,7 +42,7 @@
           </li>
           <li>
             event streams generated by low level decoders can be piped
-            directly into low level encoders for testing
+            directly into low level encoders for round trip testing
           </li>
           <li>
             low level tuple encoder can be very efficient and fast because of
@@ -52,11 +62,14 @@
             aspects where other stacked encoders built upon it do not have to
             be concerned with this
           </li>
+          <li>
+            Stub specific code does not mix with generic tuple processing code.
+          </li>
         </ul>
 
         <p>
           This low level TLV Tuple event stream encoder will need to receive
-          TLV events somehow.  The encoder hence must implement some kind of
+          TLV events somehow.  The encoder hence smust implement some kind of
           callback.  The fact that it is a callback makes it receive the
           substrate this way rather than through the conventional encode()
           pathway.  What then happens to the idea of an encode() method that

Mime
View raw message