You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by er...@apache.org on 2004/12/29 12:49:37 UTC

svn commit: r123630 - in incubator/directory/changepw/trunk: main/src/java/org main/src/java/org/apache main/src/java/org/apache/kerberos main/src/java/org/apache/kerberos/changepw main/src/java/org/apache/kerberos/changepw/server protocol/src/java/org protocol/src/java/org/apache protocol/src/java/org/apache/kerberos protocol/src/java/org/apache/kerberos/changepw protocol/src/java/org/apache/kerberos/changepw/protocol

Author: erodriguez
Date: Wed Dec 29 03:49:34 2004
New Revision: 123630

URL: http://svn.apache.org/viewcvs?view=rev&rev=123630
Log:
More cleanup of Change Password protocol SEDA frontend.
Added:
   incubator/directory/changepw/trunk/main/src/java/org/
   incubator/directory/changepw/trunk/main/src/java/org/apache/
   incubator/directory/changepw/trunk/main/src/java/org/apache/kerberos/
   incubator/directory/changepw/trunk/main/src/java/org/apache/kerberos/changepw/
   incubator/directory/changepw/trunk/main/src/java/org/apache/kerberos/changepw/server/
   incubator/directory/changepw/trunk/main/src/java/org/apache/kerberos/changepw/server/Main.java
   incubator/directory/changepw/trunk/protocol/src/java/org/
   incubator/directory/changepw/trunk/protocol/src/java/org/apache/
   incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/
   incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/
   incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/
   incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwTcpDecoder.java
   incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwTcpEncoder.java
   incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwTcpProvider.java
   incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwUdpDecoder.java
   incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwUdpEncoder.java
   incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwUdpProvider.java

Added: incubator/directory/changepw/trunk/main/src/java/org/apache/kerberos/changepw/server/Main.java
Url: http://svn.apache.org/viewcvs/incubator/directory/changepw/trunk/main/src/java/org/apache/kerberos/changepw/server/Main.java?view=auto&rev=123630
==============================================================================
--- (empty file)
+++ incubator/directory/changepw/trunk/main/src/java/org/apache/kerberos/changepw/server/Main.java	Wed Dec 29 03:49:34 2004
@@ -0,0 +1,200 @@
+/*
+ *   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.kerberos.changepw.server;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+import javax.naming.NamingException;
+import javax.naming.directory.InitialDirContext;
+
+import org.apache.eve.jndi.EnvKeys;
+import org.apache.kerberos.changepw.ChangePasswordDispatcher;
+import org.apache.kerberos.changepw.protocol.ChangepwTcpProvider;
+import org.apache.kerberos.changepw.protocol.ChangepwUdpProvider;
+import org.apache.kerberos.changepw.store.EmbeddedEveStore;
+import org.apache.kerberos.changepw.store.PasswordStore;
+import org.apache.kerberos.kdc.KdcConfiguration;
+import org.apache.kerberos.kdc.store.BootstrapStore;
+import org.apache.seda.DefaultFrontend;
+import org.apache.seda.DefaultFrontendFactory;
+import org.apache.seda.listener.ListenerConfig;
+import org.apache.seda.listener.TCPListenerConfig;
+import org.apache.seda.listener.UDPListenerConfig;
+import org.apache.seda.protocol.DefaultInetServicesDatabase;
+import org.apache.seda.protocol.InetServiceEntry;
+import org.apache.seda.protocol.ProtocolProvider;
+import org.apache.seda.protocol.TransportTypeEnum;
+
+/**
+ * Simple application wrapper around the Change Password core.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class Main
+{
+    private final KdcConfiguration config = new KdcConfiguration();
+    private final BootstrapStore bootstrap = new BootstrapStore( config );
+    private PasswordStore store;
+    private ChangePasswordDispatcher dispatcher;
+
+    /** the frontend used to contain the protocols */
+    protected DefaultFrontend fe = null;
+
+    /** the tcp protocol provider */
+    protected ProtocolProvider tcpProvider = null;
+
+    /** the udp protocol provider */
+    protected ProtocolProvider udpProvider = null;
+
+    /** the UDP listener configuration for the protocol */
+    protected ListenerConfig udpConfig;
+
+    /** the TCP listener configuration for the protocol */
+    protected ListenerConfig tcpConfig;
+
+    /** the server port number for the protocol */
+    protected int port;
+
+
+    public Main( Properties env )
+    {
+        store = new EmbeddedEveStore( env );
+
+        init();
+
+        try
+        {
+            dispatcher  = new ChangePasswordDispatcher( config, bootstrap, store );
+            tcpProvider = new ChangepwTcpProvider( dispatcher );
+            udpProvider = new ChangepwUdpProvider( dispatcher );
+            setup();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+
+    public static void main( String[] args )
+    {
+        long startTime = System.currentTimeMillis();
+
+        if ( args.length == 0 )
+        {
+            System.err.println( "Path to configuration file required!" );
+
+            System.exit( 1 );
+        }
+
+        File file = new File( args[0] );
+
+        if ( ! file.exists() )
+        {
+            System.err.println( "Config file '" + file.getAbsolutePath() + "' does not exist!" );
+
+            System.exit( 2 );
+        }
+
+        Properties env = new Properties();
+
+        try
+        {
+            env.load( new FileInputStream( file ) );
+        }
+        catch ( IOException e )
+        {
+            System.err.println( "Failed while loading config file '" + file.getAbsolutePath() + "'" );
+
+            System.exit( 3 );
+        }
+
+        new Main( env );
+
+        System.out.println( "Apache Change Password: started in "
+                + ( System.currentTimeMillis() - startTime )
+                + " milliseconds");
+
+        while ( true )
+        {
+            try
+            {
+                // this is a big time cludge for now to just play
+                Thread.sleep( 20000 );
+
+                try
+                {
+                    env.setProperty( EnvKeys.SYNC, "true" );
+                    new InitialDirContext( env );
+                }
+                catch ( NamingException e )
+                {
+                    e.printStackTrace();
+                }
+            }
+            catch ( InterruptedException e )
+            {
+                e.printStackTrace();
+            }
+        }
+    }
+
+
+    /**
+     * Instantiates the factory then gets a handle on the Frontend.
+     *
+     * @throws Exception due to create()
+     */
+    protected void setup() throws Exception
+    {
+        port = config.getDefaultPort();
+
+        fe = (DefaultFrontend) new DefaultFrontendFactory().create();
+
+        InetServiceEntry srvEntry;
+
+        srvEntry = new InetServiceEntry(tcpProvider.getName(), port, tcpProvider, TransportTypeEnum.TCP);
+        ((DefaultInetServicesDatabase) fe.getInetServicesDatabase()).addEntry(srvEntry);
+        tcpConfig = new TCPListenerConfig(srvEntry);
+        fe.getTCPListenerManager().bind(tcpConfig);
+
+        srvEntry = new InetServiceEntry(udpProvider.getName(), port, udpProvider, TransportTypeEnum.UDP);
+        ((DefaultInetServicesDatabase) fe.getInetServicesDatabase()).addEntry(srvEntry);
+        udpConfig = new UDPListenerConfig(srvEntry);
+        fe.getUDPListenerManager().bind(udpConfig);
+    }
+
+
+    private void init()
+    {
+        Runnable runnable = new Runnable()
+        {
+            public void run()
+            {
+                bootstrap.init();
+                store.init();
+            }
+        };
+        Thread storeInit = new Thread( runnable );
+        storeInit.start();
+    }
+}
+

Added: incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwTcpDecoder.java
Url: http://svn.apache.org/viewcvs/incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwTcpDecoder.java?view=auto&rev=123630
==============================================================================
--- (empty file)
+++ incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwTcpDecoder.java	Wed Dec 29 03:49:34 2004
@@ -0,0 +1,133 @@
+/*
+ *   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.kerberos.changepw.protocol;
+
+import java.nio.ByteBuffer;
+
+import org.apache.asn1.ber.TupleEncodingVisitor;
+import org.apache.asn1.ber.TupleNode;
+import org.apache.asn1.ber.TupleTreeDecoder;
+import org.apache.asn1.codec.DecoderException;
+import org.apache.asn1.codec.EncoderException;
+import org.apache.asn1.codec.stateful.AbstractStatefulDecoder;
+import org.apache.asn1.codec.stateful.DecoderCallback;
+import org.apache.asn1.codec.stateful.EncoderCallback;
+import org.apache.asn1.codec.stateful.StatefulDecoder;
+import org.apache.asn1.codec.stateful.StatefulEncoder;
+
+
+/**
+ * A decoder for Change Password TCP requests.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev: 56478 $
+ */
+public class ChangepwTcpDecoder extends AbstractStatefulDecoder
+{
+    TupleTreeDecoder treeDecoder = new TupleTreeDecoder();
+    TupleEncodingVisitor treeEncoder = new TupleEncodingVisitor();
+
+
+    public ChangepwTcpDecoder()
+    {
+        treeDecoder.setCallback( new TreeDecodedCallback() );
+        treeEncoder.setCallback( new TreeEncodedCallback() );
+    }
+
+
+    /**
+     * Returns a decoded Change Password PDU.  The codec is an identity
+     * operation.  Each decode call triggers a callback since we're presuming
+     * each chunk to be a valid PDU while streaming the request back.
+     *
+     * @param encoded the object to return which is a buffer
+     */
+    public void decode( Object encoded ) throws DecoderException
+    {
+    	ByteBuffer buf = ( ByteBuffer ) encoded;
+    	
+    	/**
+    	 * TCP requests are preceded by the length of the request as 4 octets in 
+    	 * network byte order.  We don't currently use the length, but need to
+    	 * strip it off prior to passing the PDU to the decoder.
+    	 */
+    	buf.getInt();
+    	
+        treeDecoder.decode( encoded );
+    }
+
+
+    /**
+     * Callback set for the TupleTreeDecoder to trigger event for the creation
+     * of a tupe tree.
+     */
+    class TreeDecodedCallback implements DecoderCallback
+    {
+        public void decodeOccurred( StatefulDecoder decoder, Object decoded )
+        {
+            TupleNode root = ( TupleNode ) decoded;
+
+            try
+            {
+                treeEncoder.encode( root );
+                treeEncoder.flush();
+            }
+            catch ( EncoderException e )
+            {
+                e.printStackTrace();
+            }
+        }
+    }
+
+
+    class TreeEncodedCallback implements EncoderCallback
+    {
+        public void encodeOccurred( StatefulEncoder encoder, Object encoded )
+        {
+            if ( encoded instanceof ByteBuffer )
+            {
+                ChangepwTcpDecoder.this.decodeOccurred( encoded );
+                return;
+            }
+
+
+            if ( encoded instanceof ByteBuffer[] )
+            {
+                int size = 0;
+                ByteBuffer[] buffers = ( ByteBuffer[] ) encoded;
+                for ( int ii = 0; ii < buffers.length; ii++ )
+                {
+                    size += buffers[ii].remaining();
+                }
+
+                ByteBuffer consolidated = ByteBuffer.wrap( new byte[size] );
+                for ( int ii = 0; ii < buffers.length; ii++ )
+                {
+                    consolidated.put( buffers[ii] );
+                }
+
+                ChangepwTcpDecoder.this.decodeOccurred( consolidated );
+                return;
+            }
+
+            throw new IllegalArgumentException( "expected a ByteBuffer or a " +
+                    "ByteBuffer[] but got back a " + encoded.getClass() );
+        }
+    }
+}
+

Added: incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwTcpEncoder.java
Url: http://svn.apache.org/viewcvs/incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwTcpEncoder.java?view=auto&rev=123630
==============================================================================
--- (empty file)
+++ incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwTcpEncoder.java	Wed Dec 29 03:49:34 2004
@@ -0,0 +1,44 @@
+/*
+ *   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.kerberos.changepw.protocol;
+
+import org.apache.asn1.codec.stateful.AbstractStatefulEncoder;
+
+
+/**
+ * An encoder for Change Password replies.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev: 56478 $
+ */
+public class ChangepwTcpEncoder extends AbstractStatefulEncoder
+{
+    /**
+     * Returns an encoded Change Password PDU.  The codec is an identity
+     * operation.  Each encode call triggers a callback since we're presuming
+     * each chunk to be a valid PDU while streaming the request back as the
+     * response.
+     *
+     * @param substrate the object to return which is a buffer
+     */
+    public void encode(Object substrate)
+    {
+        super.encodeOccurred(substrate);
+    }
+}
+

Added: incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwTcpProvider.java
Url: http://svn.apache.org/viewcvs/incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwTcpProvider.java?view=auto&rev=123630
==============================================================================
--- (empty file)
+++ incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwTcpProvider.java	Wed Dec 29 03:49:34 2004
@@ -0,0 +1,170 @@
+/*
+ *   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.kerberos.changepw.protocol;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.apache.asn1.codec.stateful.DecoderFactory;
+import org.apache.asn1.codec.stateful.EncoderFactory;
+import org.apache.asn1.codec.stateful.StatefulDecoder;
+import org.apache.asn1.codec.stateful.StatefulEncoder;
+import org.apache.kerberos.changepw.ChangePasswordDispatcher;
+import org.apache.ldap.common.util.NestableRuntimeException;
+import org.apache.seda.listener.ClientKey;
+import org.apache.seda.protocol.HandlerTypeEnum;
+import org.apache.seda.protocol.ProtocolProvider;
+import org.apache.seda.protocol.RequestHandler;
+import org.apache.seda.protocol.SingleReplyHandler;
+
+
+/**
+ * An Change Password protocol service provider for the SEDA framework.  The provider along
+ * with the SEDA framework implements an RFC 3244 compliant server.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev: 56478 $
+ */
+public final class ChangepwTcpProvider implements ProtocolProvider
+{
+    /** the authoritative service name of this internet protocol: 'changepw' */
+    public static final String NAME = "changepw";
+
+    /** changepw handler where request is return back as a response */
+    public final SingleReplyHandler handler = new ChangePasswordHandler();
+    /** the changepw dispatcher */
+    public final ChangePasswordDispatcher dispatcher;
+
+
+    public ChangepwTcpProvider( ChangePasswordDispatcher dispatcher )
+    {
+        this.dispatcher = dispatcher;
+    }
+
+
+    /**
+     * Gets the authoritative name for the service of this provider.
+     *
+     * @return the authoritative service name
+     */
+    public final String getName()
+    {
+        return NAME;
+    }
+
+    /**
+     * Gets a factory used to create a new StatefulDecoder for this service's
+     * protocol.
+     *
+     * @return a new StatefulDecoder for this service's protocol
+     */
+    public final DecoderFactory getDecoderFactory()
+    {
+        return new DecoderFactory()
+            {
+                /**
+                 * Creates a really simple factory for decoders that return back
+                 * their request in the same decode call, ie a 1:1 decode to callback.
+                 * The same decoder will be returned every time since no state is
+                 * ever stored by these decoders.
+                 *
+                 * @return a chunking state based decoder
+                 */
+                public StatefulDecoder createDecoder()
+                {
+                    return new ChangepwTcpDecoder();
+                }
+            };
+    }
+
+    /**
+     * Gets a factory used to create a new StatefulEncoder for this service's
+     * protocol.
+     *
+     * @return a new StatefulEncoder for this service's protocol
+     */
+    public EncoderFactory getEncoderFactory()
+    {
+        return new EncoderFactory()
+            {
+                /**
+                 * Creates a factory that always returns the same encoder which
+                 * never really maintains any state.  This encoder simply returns
+                 * the object to encode as is without affecting it in any way.
+                 *
+                 * @return a new chunking state based encoder
+                 */
+                public StatefulEncoder createEncoder()
+                {
+                    return new ChangepwTcpEncoder();
+                }
+            };
+    }
+
+    /**
+     * @param request the ByteBuffer containing the data to process
+     * @return the same ByteBuffer without any changes
+     */
+    public RequestHandler getHandler(ClientKey key, Object request)
+    {
+        return handler;
+    }
+
+
+    class ChangePasswordHandler implements SingleReplyHandler
+    {
+        public HandlerTypeEnum getHandlerType()
+        {
+            return HandlerTypeEnum.SINGLEREPLY;
+        }
+
+
+        public Object handle( ClientKey key, Object request )
+        {
+            /*
+             * We know this is really bad form: meaning the .array() usage.
+             * Basically this is designed for the current decoder which we know
+             * creates consolidated byte[]s of multiple buffers.  So .array()
+             * does return the entire pdu or the entire buffer and we know this
+             * is wrapped instead of direct.  This MUST change in the future!
+             */
+            byte[] pdu = ( ( ByteBuffer ) request ).array();
+            
+            try
+            {
+            	byte[] pduBytes = dispatcher.dispatch( pdu );
+            	
+            	int integerLength = 4;
+            	
+            	ByteBuffer buf = ByteBuffer.allocate( pduBytes.length + integerLength );
+            	buf.putInt( pduBytes.length );
+            	buf.put( pduBytes );
+            	buf.flip();
+            	
+                return buf;
+            }
+            catch( IOException e )
+            {
+                e.printStackTrace();
+                throw new NestableRuntimeException(
+                        "Dispatcher failed to process kerberos request!", e );
+            }
+        }
+    }
+}
+

Added: incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwUdpDecoder.java
Url: http://svn.apache.org/viewcvs/incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwUdpDecoder.java?view=auto&rev=123630
==============================================================================
--- (empty file)
+++ incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwUdpDecoder.java	Wed Dec 29 03:49:34 2004
@@ -0,0 +1,124 @@
+/*
+ *   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.kerberos.changepw.protocol;
+
+import java.nio.ByteBuffer;
+
+import org.apache.asn1.ber.TupleEncodingVisitor;
+import org.apache.asn1.ber.TupleNode;
+import org.apache.asn1.ber.TupleTreeDecoder;
+import org.apache.asn1.codec.DecoderException;
+import org.apache.asn1.codec.EncoderException;
+import org.apache.asn1.codec.stateful.AbstractStatefulDecoder;
+import org.apache.asn1.codec.stateful.DecoderCallback;
+import org.apache.asn1.codec.stateful.EncoderCallback;
+import org.apache.asn1.codec.stateful.StatefulDecoder;
+import org.apache.asn1.codec.stateful.StatefulEncoder;
+
+
+/**
+ * A decoder for Change Password requests.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev: 56478 $
+ */
+public class ChangepwUdpDecoder extends AbstractStatefulDecoder
+{
+    TupleTreeDecoder treeDecoder = new TupleTreeDecoder();
+    TupleEncodingVisitor treeEncoder = new TupleEncodingVisitor();
+
+
+    public ChangepwUdpDecoder()
+    {
+        treeDecoder.setCallback( new TreeDecodedCallback() );
+        treeEncoder.setCallback( new TreeEncodedCallback() );
+    }
+
+
+    /**
+     * Returns a decoded Change Password PDU.  The codec is an identity
+     * operation.  Each decode call triggers a callback since we're presuming
+     * each chunk to be a valid PDU while streaming the request back.
+     *
+     * @param encoded the object to return which is a buffer
+     */
+    public void decode( Object encoded ) throws DecoderException
+    {
+        treeDecoder.decode( encoded );
+    }
+
+
+    /**
+     * Callback set for the TupleTreeDecoder to trigger event for the creation
+     * of a tuple tree.
+     */
+    class TreeDecodedCallback implements DecoderCallback
+    {
+        public void decodeOccurred( StatefulDecoder decoder, Object decoded )
+        {
+            TupleNode root = ( TupleNode ) decoded;
+
+            try
+            {
+                treeEncoder.encode( root );
+                treeEncoder.flush();
+            }
+            catch ( EncoderException e )
+            {
+                e.printStackTrace();
+            }
+        }
+    }
+
+
+    class TreeEncodedCallback implements EncoderCallback
+    {
+        public void encodeOccurred( StatefulEncoder encoder, Object encoded )
+        {
+            if ( encoded instanceof ByteBuffer )
+            {
+                ChangepwUdpDecoder.this.decodeOccurred( encoded );
+                return;
+            }
+
+
+            if ( encoded instanceof ByteBuffer[] )
+            {
+                int size = 0;
+                ByteBuffer[] buffers = ( ByteBuffer[] ) encoded;
+                for ( int ii = 0; ii < buffers.length; ii++ )
+                {
+                    size += buffers[ii].remaining();
+                }
+
+                ByteBuffer consolidated = ByteBuffer.wrap( new byte[size] );
+                for ( int ii = 0; ii < buffers.length; ii++ )
+                {
+                    consolidated.put( buffers[ii] );
+                }
+
+                ChangepwUdpDecoder.this.decodeOccurred( consolidated );
+                return;
+            }
+
+            throw new IllegalArgumentException( "expected a ByteBuffer or a " +
+                    "ByteBuffer[] but got back a " + encoded.getClass() );
+        }
+    }
+}
+

Added: incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwUdpEncoder.java
Url: http://svn.apache.org/viewcvs/incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwUdpEncoder.java?view=auto&rev=123630
==============================================================================
--- (empty file)
+++ incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwUdpEncoder.java	Wed Dec 29 03:49:34 2004
@@ -0,0 +1,44 @@
+/*
+ *   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.kerberos.changepw.protocol;
+
+import org.apache.asn1.codec.stateful.AbstractStatefulEncoder;
+
+
+/**
+ * An encoder for Change Password replies.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev: 56478 $
+ */
+public class ChangepwUdpEncoder extends AbstractStatefulEncoder
+{
+    /**
+     * Returns an encoded ChangePassword PDU.  The codec is an identity
+     * operation.  Each encode call triggers a callback since we're presuming
+     * each chunk to be a valid PDU while streaming the request back as the
+     * response.
+     *
+     * @param substrate the object to return which is a buffer
+     */
+    public void encode(Object substrate)
+    {
+        super.encodeOccurred(substrate);
+    }
+}
+

Added: incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwUdpProvider.java
Url: http://svn.apache.org/viewcvs/incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwUdpProvider.java?view=auto&rev=123630
==============================================================================
--- (empty file)
+++ incubator/directory/changepw/trunk/protocol/src/java/org/apache/kerberos/changepw/protocol/ChangepwUdpProvider.java	Wed Dec 29 03:49:34 2004
@@ -0,0 +1,161 @@
+/*
+ *   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.kerberos.changepw.protocol;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.apache.kerberos.changepw.ChangePasswordDispatcher;
+import org.apache.ldap.common.util.NestableRuntimeException;
+import org.apache.seda.listener.ClientKey;
+import org.apache.seda.protocol.HandlerTypeEnum;
+import org.apache.seda.protocol.ProtocolProvider;
+import org.apache.seda.protocol.RequestHandler;
+import org.apache.seda.protocol.SingleReplyHandler;
+import org.apache.asn1.codec.stateful.DecoderFactory;
+import org.apache.asn1.codec.stateful.EncoderFactory;
+import org.apache.asn1.codec.stateful.StatefulDecoder;
+import org.apache.asn1.codec.stateful.StatefulEncoder;
+
+
+/**
+ * A Change Password protocol service provider for the SEDA framework.  The provider along
+ * with the SEDA framework implements an RFC 3244 compliant server.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org">Apache Directory Project</a>
+ * @version $Rev: 56478 $
+ */
+public final class ChangepwUdpProvider implements ProtocolProvider
+{
+    /** the authoritative service name of this internet protocol: 'changepw' */
+    public static final String NAME = "changepw";
+
+    /** changepw handler where request is return back as a response */
+    public final SingleReplyHandler handler = new ChangePasswordHandler();
+    /** the changepw dispatcher */
+    public final ChangePasswordDispatcher dispatcher;
+
+
+    public ChangepwUdpProvider( ChangePasswordDispatcher dispatcher )
+    {
+        this.dispatcher = dispatcher;
+    }
+
+
+    /**
+     * Gets the authoritative name for the service of this provider.
+     *
+     * @return the authoritative service name
+     */
+    public final String getName()
+    {
+        return NAME;
+    }
+
+    /**
+     * Gets a factory used to create a new StatefulDecoder for this service's
+     * protocol.
+     *
+     * @return a new StatefulDecoder for this service's protocol
+     */
+    public final DecoderFactory getDecoderFactory()
+    {
+        return new DecoderFactory()
+            {
+                /**
+                 * Creates a really simple factory for decoders that return back
+                 * their request in the same decode call, ie a 1:1 decode to callback.
+                 * The same decoder will be returned every time since no state is
+                 * ever stored by these decoders.
+                 *
+                 * @return a chunking state based decoder
+                 */
+                public StatefulDecoder createDecoder()
+                {
+                    return new ChangepwUdpDecoder();
+                }
+            };
+    }
+
+    /**
+     * Gets a factory used to create a new StatefulEncoder for this service's
+     * protocol.
+     *
+     * @return a new StatefulEncoder for this service's protocol
+     */
+    public EncoderFactory getEncoderFactory()
+    {
+        return new EncoderFactory()
+            {
+                /**
+                 * Creates a factory that always returns the same encoder which
+                 * never really maintains any state.  This encoder simply returns
+                 * the object to encode as is without affecting it in any way.
+                 *
+                 * @return a new chunking state based encoder
+                 */
+                public StatefulEncoder createEncoder()
+                {
+                    return new ChangepwUdpEncoder();
+                }
+            };
+    }
+
+    /**
+     * @param request the ByteBuffer containing the data to process
+     * @return the same ByteBuffer without any changes
+     */
+    public RequestHandler getHandler(ClientKey key, Object request)
+    {
+        return handler;
+    }
+
+
+    class ChangePasswordHandler implements SingleReplyHandler
+    {
+        public HandlerTypeEnum getHandlerType()
+        {
+            return HandlerTypeEnum.SINGLEREPLY;
+        }
+
+
+        public Object handle( ClientKey key, Object request )
+        {
+            /*
+             * We know this is really bad form: meaning the .array() usage.
+             * Basically this is designed for the current decoder which we know
+             * creates consolidated byte[]s of multiple buffers.  So .array()
+             * does return the entire pdu or the entire buffer and we know this
+             * is wrapped instead of direct.  This MUST change in the future!
+             */
+            byte[] pdu = ( ( ByteBuffer ) request ).array();
+
+            try
+            {
+                return ByteBuffer.wrap( dispatcher.dispatch( pdu ) );
+            }
+            catch( IOException e )
+            {
+                e.printStackTrace();
+                throw new NestableRuntimeException(
+                        "Dispatcher failed to process changepw request!", e );
+            }
+        }
+    }
+}
+