You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by tr...@apache.org on 2006/10/17 08:08:46 UTC

svn commit: r464824 - in /directory: branches/mina/1.0/core/src/main/java/org/apache/mina/common/support/ branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/ branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/n...

Author: trustin
Date: Mon Oct 16 23:08:44 2006
New Revision: 464824

URL: http://svn.apache.org/viewvc?view=rev&rev=464824
Log:
Fixed issue: DIRMINA-273 Session created with non-existent service
Fixed issue: DIRMINA-283 Filter.sessionCreated/Filter.sessionOpened called AFTER Filter.filterWrite...
* Added AbstractIoFilterChain.CONNECT_FUTURE attribute key to store the connect future until the future becomes now.
* AbstractIoFilterChain.fireSessionOpened() and fireExceptionCaught() take care of finishing the ConnectFuture attached to sessions.
* Made sure the behavior of ConnectFuture and IoFilterChain is all identical for all transports


Added:
    directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/AbstractConnectorTest.java
    directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConnectorTest.java
    directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/socket/nio/SocketConnectorTest.java
    directory/trunks/mina/core/src/test/java/org/apache/mina/transport/AbstractConnectorTest.java   (with props)
    directory/trunks/mina/core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConnectorTest.java   (with props)
    directory/trunks/mina/core/src/test/java/org/apache/mina/transport/socket/nio/SocketConnectorTest.java   (with props)
Modified:
    directory/branches/mina/1.0/core/src/main/java/org/apache/mina/common/support/AbstractIoFilterChain.java
    directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketAcceptor.java
    directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketConnector.java
    directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketIoProcessor.java
    directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketSessionImpl.java
    directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/support/DatagramConnectorDelegate.java
    directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeConnector.java
    directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeFilterChain.java
    directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeSessionImpl.java
    directory/trunks/mina/core/src/main/java/org/apache/mina/common/support/AbstractIoFilterChain.java
    directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketAcceptor.java
    directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketConnector.java
    directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketIoProcessor.java
    directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketSessionImpl.java
    directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/support/DatagramConnectorDelegate.java
    directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeConnector.java
    directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeFilterChain.java
    directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeSessionImpl.java

Modified: directory/branches/mina/1.0/core/src/main/java/org/apache/mina/common/support/AbstractIoFilterChain.java
URL: http://svn.apache.org/viewvc/directory/branches/mina/1.0/core/src/main/java/org/apache/mina/common/support/AbstractIoFilterChain.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/branches/mina/1.0/core/src/main/java/org/apache/mina/common/support/AbstractIoFilterChain.java (original)
+++ directory/branches/mina/1.0/core/src/main/java/org/apache/mina/common/support/AbstractIoFilterChain.java Mon Oct 16 23:08:44 2006
@@ -26,6 +26,7 @@
 import java.util.Map;
 
 import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.ConnectFuture;
 import org.apache.mina.common.IdleStatus;
 import org.apache.mina.common.IoFilter;
 import org.apache.mina.common.IoFilterAdapter;
@@ -52,10 +53,17 @@
  */
 public abstract class AbstractIoFilterChain implements IoFilterChain
 {
-    private final IoSession session;
+    /**
+     * A session attribute that stores a {@link ConnectFuture} related with
+     * the {@link IoSession}.  {@link AbstractIoFilterChain} clears this
+     * attribute and notifies the future when {@link #fireSessionOpened(IoSession)}
+     * or {@link #fireExceptionCaught(IoSession, Throwable)} is invoked
+     */
+    public static final String CONNECT_FUTURE =
+        AbstractIoFilterChain.class.getName() + ".connectFuture";
 
+    private final IoSession session;
     private final Map name2entry = new HashMap();
-
     private final EntryImpl head;
     private final EntryImpl tail;
 
@@ -67,160 +75,11 @@
         }
 
         this.session = session;
-        head = new EntryImpl( null, null, "head", createHeadFilter() );
-        tail = new EntryImpl( head, null, "tail", createTailFilter() );
+        head = new EntryImpl( null, null, "head", new HeadFilter() );
+        tail = new EntryImpl( head, null, "tail", new TailFilter() );
         head.nextEntry = tail;
     }
 
-    /**
-     * Override this method to create custom head of this filter chain.
-     */
-    protected IoFilter createHeadFilter()
-    {
-        return new IoFilterAdapter()
-        {
-            public void sessionCreated( NextFilter nextFilter, IoSession session )
-            {
-                nextFilter.sessionCreated( session );
-            }
-
-            public void sessionOpened( NextFilter nextFilter, IoSession session )
-            {
-                nextFilter.sessionOpened( session );
-            }
-
-            public void sessionClosed( NextFilter nextFilter, IoSession session )
-            {
-                nextFilter.sessionClosed( session );
-            }
-
-            public void sessionIdle( NextFilter nextFilter, IoSession session,
-                                    IdleStatus status )
-            {
-                nextFilter.sessionIdle( session, status );
-            }
-
-            public void exceptionCaught( NextFilter nextFilter,
-                                        IoSession session, Throwable cause )
-            {
-                nextFilter.exceptionCaught( session, cause );
-            }
-
-            public void messageReceived( NextFilter nextFilter, IoSession session,
-                                         Object message )
-            {
-                nextFilter.messageReceived( session, message );
-            }
-
-            public void messageSent( NextFilter nextFilter, IoSession session,
-                                     Object message )
-            {
-                nextFilter.messageSent( session, message );
-            }
-
-            public void filterWrite( NextFilter nextFilter, IoSession session,
-                                     WriteRequest writeRequest ) throws Exception
-            {
-                if( session.getTransportType().getEnvelopeType().isAssignableFrom( writeRequest.getMessage().getClass() ) )
-                {
-                    doWrite( session, writeRequest );
-                }
-                else
-                {
-                    throw new IllegalStateException(
-                            "Write requests must be transformed to " +
-                            session.getTransportType().getEnvelopeType() +
-                            ": " + writeRequest );
-                }
-            }
-
-            public void filterClose( NextFilter nextFilter, IoSession session ) throws Exception
-            {
-                doClose( session );
-            }
-        };
-    }
-
-    /**
-     * Override this method to create custom head of this filter chain.
-     */
-    protected IoFilter createTailFilter()
-    {
-        return new IoFilterAdapter()
-        {
-            public void sessionCreated( NextFilter nextFilter, IoSession session ) throws Exception
-            {
-                session.getHandler().sessionCreated( session );
-            }
-            public void sessionOpened( NextFilter nextFilter, IoSession session ) throws Exception
-            {
-                session.getHandler().sessionOpened( session );
-            }
-
-            public void sessionClosed( NextFilter nextFilter, IoSession session ) throws Exception
-            {
-                try
-                {
-                    session.getHandler().sessionClosed( session );
-                }
-                finally
-                {
-                    // Remove all filters.
-                    session.getFilterChain().clear();
-                }
-            }
-
-            public void sessionIdle( NextFilter nextFilter, IoSession session,
-                                    IdleStatus status ) throws Exception
-            {
-                session.getHandler().sessionIdle( session, status );
-            }
-
-            public void exceptionCaught( NextFilter nextFilter,
-                                        IoSession session, Throwable cause ) throws Exception
-            {
-                session.getHandler().exceptionCaught( session, cause );
-            }
-
-            public void messageReceived( NextFilter nextFilter, IoSession session,
-                                         Object message ) throws Exception
-            {
-                try
-                {
-                    session.getHandler().messageReceived( session, message );
-                }
-                finally
-                {
-                    ByteBufferUtil.releaseIfPossible( message );
-                }
-            }
-
-            public void messageSent( NextFilter nextFilter, IoSession session,
-                                     Object message ) throws Exception
-            {
-                try
-                {
-                    session.getHandler().messageSent( session, message );
-                }
-                finally
-                {
-                    ByteBufferUtil.releaseIfPossible( message );
-                }
-            }
-
-            public void filterWrite( NextFilter nextFilter,
-                                     IoSession session, WriteRequest writeRequest ) throws Exception
-            {
-                nextFilter.filterWrite( session, writeRequest );
-            }
-
-            public void filterClose( NextFilter nextFilter, IoSession session ) throws Exception
-            {
-                nextFilter.filterClose( session );
-            }
-        };
-    }
-
     public IoSession getSession()
     {
         return session;
@@ -539,8 +398,20 @@
 
     public void fireExceptionCaught( IoSession session, Throwable cause )
     {
-        Entry head = this.head;
-        callNextExceptionCaught(head, session, cause);
+        // Notify the related ConnectFuture
+        // if the session is created from SocketConnector.
+        ConnectFuture future = ( ConnectFuture ) session.removeAttribute( CONNECT_FUTURE );
+        if( future == null )
+        {
+            Entry head = this.head;
+            callNextExceptionCaught( head, session, cause );
+        }
+        else
+        {
+            // Please note that this place is not the only place that
+            // calls ConnectFuture.setException().
+            future.setException( cause );
+        }
     }
 
     private void callNextExceptionCaught( Entry entry,
@@ -710,6 +581,157 @@
     protected abstract void doWrite( IoSession session, WriteRequest writeRequest ) throws Exception;
 
     protected abstract void doClose( IoSession session ) throws Exception;
+
+    private class HeadFilter extends IoFilterAdapter
+    {
+        public void sessionCreated( NextFilter nextFilter, IoSession session )
+        {
+            nextFilter.sessionCreated( session );
+        }
+
+        public void sessionOpened( NextFilter nextFilter, IoSession session )
+        {
+            nextFilter.sessionOpened( session );
+        }
+
+        public void sessionClosed( NextFilter nextFilter, IoSession session )
+        {
+            nextFilter.sessionClosed( session );
+        }
+
+        public void sessionIdle( NextFilter nextFilter, IoSession session,
+                                IdleStatus status )
+        {
+            nextFilter.sessionIdle( session, status );
+        }
+
+        public void exceptionCaught( NextFilter nextFilter,
+                                    IoSession session, Throwable cause )
+        {
+            nextFilter.exceptionCaught( session, cause );
+        }
+
+        public void messageReceived( NextFilter nextFilter, IoSession session,
+                                     Object message )
+        {
+            nextFilter.messageReceived( session, message );
+        }
+
+        public void messageSent( NextFilter nextFilter, IoSession session,
+                                 Object message )
+        {
+            nextFilter.messageSent( session, message );
+        }
+
+        public void filterWrite( NextFilter nextFilter, IoSession session,
+                                 WriteRequest writeRequest ) throws Exception
+        {
+            if( session.getTransportType().getEnvelopeType().isAssignableFrom( writeRequest.getMessage().getClass() ) )
+            {
+                doWrite( session, writeRequest );
+            }
+            else
+            {
+                throw new IllegalStateException(
+                        "Write requests must be transformed to " +
+                        session.getTransportType().getEnvelopeType() +
+                        ": " + writeRequest );
+            }
+        }
+
+        public void filterClose( NextFilter nextFilter, IoSession session ) throws Exception
+        {
+            doClose( session );
+        }
+    }
+
+    private static class TailFilter extends IoFilterAdapter
+    {
+        public void sessionCreated( NextFilter nextFilter, IoSession session ) throws Exception
+        {
+            session.getHandler().sessionCreated( session );
+        }
+
+        public void sessionOpened( NextFilter nextFilter, IoSession session ) throws Exception
+        {
+            try
+            {
+                session.getHandler().sessionOpened( session );
+            }
+            finally
+            {
+                // Notify the related ConnectFuture
+                // if the session is created from SocketConnector.
+                ConnectFuture future = ( ConnectFuture ) session.removeAttribute( CONNECT_FUTURE );
+                if( future != null )
+                {
+                    future.setSession( session );
+                }
+            }
+        }
+
+        public void sessionClosed( NextFilter nextFilter, IoSession session ) throws Exception
+        {
+            try
+            {
+                session.getHandler().sessionClosed( session );
+            }
+            finally
+            {
+                // Remove all filters.
+                session.getFilterChain().clear();
+            }
+        }
+
+        public void sessionIdle( NextFilter nextFilter, IoSession session,
+                                IdleStatus status ) throws Exception
+        {
+            session.getHandler().sessionIdle( session, status );
+        }
+
+        public void exceptionCaught( NextFilter nextFilter,
+                                    IoSession session, Throwable cause ) throws Exception
+        {
+            session.getHandler().exceptionCaught( session, cause );
+        }
+
+        public void messageReceived( NextFilter nextFilter, IoSession session,
+                                     Object message ) throws Exception
+        {
+            try
+            {
+                session.getHandler().messageReceived( session, message );
+            }
+            finally
+            {
+                ByteBufferUtil.releaseIfPossible( message );
+            }
+        }
+
+        public void messageSent( NextFilter nextFilter, IoSession session,
+                                 Object message ) throws Exception
+        {
+            try
+            {
+                session.getHandler().messageSent( session, message );
+            }
+            finally
+            {
+                ByteBufferUtil.releaseIfPossible( message );
+            }
+        }
+
+        public void filterWrite( NextFilter nextFilter,
+                                 IoSession session, WriteRequest writeRequest ) throws Exception
+        {
+            nextFilter.filterWrite( session, writeRequest );
+        }
+
+        public void filterClose( NextFilter nextFilter, IoSession session ) throws Exception
+        {
+            nextFilter.filterClose( session );
+        }
+    }
 
     private class EntryImpl implements Entry
     {

Modified: directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketAcceptor.java
URL: http://svn.apache.org/viewvc/directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketAcceptor.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketAcceptor.java (original)
+++ directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketAcceptor.java Mon Oct 16 23:08:44 2006
@@ -343,13 +343,9 @@
                 try
                 {
                     RegistrationRequest req = ( RegistrationRequest ) key.attachment();
-                    SocketSessionImpl session = new SocketSessionImpl( SocketAcceptor.this,
-                                                                       nextProcessor(),
-                                                                       getListeners(),
-                                                                       req.config,
-                                                                       ch,
-                                                                       req.handler,
-                                                                       req.address );
+                    SocketSessionImpl session = new SocketSessionImpl(
+                            SocketAcceptor.this, nextProcessor(), getListeners(),
+                            req.config, ch, req.handler, req.address );
                     getFilterChainBuilder().buildFilterChain( session.getFilterChain() );
                     req.config.getFilterChainBuilder().buildFilterChain( session.getFilterChain() );
                     req.config.getThreadModel().buildFilterChain( session.getFilterChain() );

Modified: directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketConnector.java
URL: http://svn.apache.org/viewvc/directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketConnector.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketConnector.java (original)
+++ directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketConnector.java Mon Oct 16 23:08:44 2006
@@ -35,6 +35,7 @@
 import org.apache.mina.common.IoConnectorConfig;
 import org.apache.mina.common.IoHandler;
 import org.apache.mina.common.IoServiceConfig;
+import org.apache.mina.common.support.AbstractIoFilterChain;
 import org.apache.mina.common.support.BaseIoConnector;
 import org.apache.mina.common.support.DefaultConnectFuture;
 import org.apache.mina.util.Queue;
@@ -365,13 +366,9 @@
     private void newSession( SocketChannel ch, IoHandler handler, IoServiceConfig config, ConnectFuture connectFuture )
         throws IOException
     {
-        SocketSessionImpl session = new SocketSessionImpl( this,
-                                                           nextProcessor(),
-                                                           getListeners(),
-                                                           config,
-                                                           ch,
-                                                           handler,
-                                                           ch.socket().getRemoteSocketAddress() );
+        SocketSessionImpl session = new SocketSessionImpl(
+                this, nextProcessor(), getListeners(),
+                config, ch, handler, ch.socket().getRemoteSocketAddress() );
         try
         {
             getFilterChainBuilder().buildFilterChain( session.getFilterChain() );
@@ -382,8 +379,13 @@
         {
             throw ( IOException ) new IOException( "Failed to create a session." ).initCause( e );
         }
+        
+        // Set the ConnectFuture of the specified session, which will be
+        // removed and notified by AbstractIoFilterChain eventually.
+        session.setAttribute( AbstractIoFilterChain.CONNECT_FUTURE, connectFuture );
+
+        // Forward the remaining process to the SocketIoProcessor.
         session.getIoProcessor().addNew( session );
-        connectFuture.setSession( session );
     }
 
     private SocketIoProcessor nextProcessor()

Modified: directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketIoProcessor.java
URL: http://svn.apache.org/viewvc/directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketIoProcessor.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketIoProcessor.java (original)
+++ directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketIoProcessor.java Mon Oct 16 23:08:44 2006
@@ -160,25 +160,22 @@
                 break;
 
             SocketChannel ch = session.getChannel();
-            boolean registered;
-
             try
             {
                 ch.configureBlocking( false );
                 session.setSelectionKey( ch.register( selector,
                                                       SelectionKey.OP_READ,
                                                       session ) );
-                registered = true;
+
+                // AbstractIoFilterChain.CONNECT_FUTURE is cleared inside here
+                // in AbstractIoFilterChain.fireSessionOpened().
+                session.getServiceListeners().fireSessionCreated( session );
             }
             catch( IOException e )
             {
-                registered = false;
+                // Clear the AbstractIoFilterChain.CONNECT_FUTURE attribute
+                // and call ConnectFuture.setException().
                 session.getFilterChain().fireExceptionCaught( session, e );
-            }
-
-            if( registered )
-            {
-                session.getServiceListeners().fireSessionCreated( session );
             }
         }
     }

Modified: directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketSessionImpl.java
URL: http://svn.apache.org/viewvc/directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketSessionImpl.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketSessionImpl.java (original)
+++ directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/SocketSessionImpl.java Mon Oct 16 23:08:44 2006
@@ -149,7 +149,7 @@
     {
         this.key = key;
     }
-
+    
     public IoHandler getHandler()
     {
         return handler;

Modified: directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/support/DatagramConnectorDelegate.java
URL: http://svn.apache.org/viewvc/directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/support/DatagramConnectorDelegate.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/support/DatagramConnectorDelegate.java (original)
+++ directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/socket/nio/support/DatagramConnectorDelegate.java Mon Oct 16 23:08:44 2006
@@ -37,6 +37,7 @@
 import org.apache.mina.common.IoSession;
 import org.apache.mina.common.IoSessionRecycler;
 import org.apache.mina.common.IoFilter.WriteRequest;
+import org.apache.mina.common.support.AbstractIoFilterChain;
 import org.apache.mina.common.support.BaseIoConnector;
 import org.apache.mina.common.support.DefaultConnectFuture;
 import org.apache.mina.transport.socket.nio.DatagramConnectorConfig;
@@ -613,6 +614,9 @@
                     req.config,
                     req.channel, req.handler,
                     req.channel.socket().getRemoteSocketAddress() );
+            
+            // AbstractIoFilterChain will notify the connect future.
+            session.setAttribute( AbstractIoFilterChain.CONNECT_FUTURE, req );
 
             boolean success = false;
             try
@@ -625,21 +629,20 @@
                 }
                 else
                 {
+                    SelectionKey key = req.channel.register( selector,
+                            SelectionKey.OP_READ, session );
+
+                    session.setSelectionKey( key );
                     buildFilterChain( req, session );
+                    // The CONNECT_FUTURE attribute is cleared and notified here.
                     getListeners().fireSessionCreated( session );
                 }
-
-                SelectionKey key = req.channel.register( selector,
-                                                         SelectionKey.OP_READ, session );
-
-                session.setSelectionKey( key );
-
-                req.setSession( session );
                 success = true;
             }
             catch( Throwable t )
             {
-                req.setException( t );
+                // The CONNECT_FUTURE attribute is cleared and notified here.
+                session.getFilterChain().fireExceptionCaught( session, t );
             }
             finally
             {

Modified: directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeConnector.java
URL: http://svn.apache.org/viewvc/directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeConnector.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeConnector.java (original)
+++ directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeConnector.java Mon Oct 16 23:08:44 2006
@@ -23,14 +23,18 @@
 import java.net.SocketAddress;
 
 import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.common.ExceptionMonitor;
+import org.apache.mina.common.IoFilterChain;
 import org.apache.mina.common.IoHandler;
 import org.apache.mina.common.IoServiceConfig;
 import org.apache.mina.common.IoSessionConfig;
+import org.apache.mina.common.support.AbstractIoFilterChain;
 import org.apache.mina.common.support.BaseIoConnector;
 import org.apache.mina.common.support.BaseIoConnectorConfig;
 import org.apache.mina.common.support.BaseIoSessionConfig;
 import org.apache.mina.common.support.DefaultConnectFuture;
 import org.apache.mina.transport.vmpipe.support.VmPipe;
+import org.apache.mina.transport.vmpipe.support.VmPipeIdleStatusChecker;
 import org.apache.mina.transport.vmpipe.support.VmPipeSessionImpl;
 import org.apache.mina.util.AnonymousSocketAddress;
 
@@ -87,23 +91,53 @@
         }
 
         DefaultConnectFuture future = new DefaultConnectFuture();
+        VmPipeSessionImpl localSession =
+            new VmPipeSessionImpl(
+                    this,
+                    config,
+                    getListeners(),
+                    new Object(), // lock
+                    new AnonymousSocketAddress(),
+                    handler,
+                    entry );
+        
+        // initialize connector session
         try
         {
-            VmPipeSessionImpl session =
-                new VmPipeSessionImpl(
-                        this,
-                        config,
-                        getListeners(),
-                        new Object(), // lock
-                        new AnonymousSocketAddress(),
-                        handler,
-                        entry );
-            future.setSession( session );
+            IoFilterChain filterChain = localSession.getFilterChain();
+            this.getFilterChainBuilder().buildFilterChain( filterChain );
+            config.getFilterChainBuilder().buildFilterChain( filterChain );
+            config.getThreadModel().buildFilterChain( filterChain );
+
+            // The following sentences don't throw any exceptions.
+            localSession.setAttribute( AbstractIoFilterChain.CONNECT_FUTURE, future );
+            getListeners().fireSessionCreated( localSession );
+            VmPipeIdleStatusChecker.getInstance().addSession( localSession);
         }
-        catch( IOException e )
+        catch( Throwable t )
         {
-            future.setException( e );
+            future.setException( t );
         }
+        
+        // initialize acceptor session
+        VmPipeSessionImpl remoteSession = localSession.getRemoteSession();
+        try
+        {
+            IoFilterChain filterChain = remoteSession.getFilterChain();
+            entry.getAcceptor().getFilterChainBuilder().buildFilterChain( filterChain );
+            entry.getConfig().getFilterChainBuilder().buildFilterChain( filterChain );
+            entry.getConfig().getThreadModel().buildFilterChain( filterChain );
+            
+            // The following sentences don't throw any exceptions.
+            entry.getListeners().fireSessionCreated( remoteSession );
+            VmPipeIdleStatusChecker.getInstance().addSession( remoteSession );
+        }
+        catch( Throwable t )
+        {
+            ExceptionMonitor.getInstance().exceptionCaught( t );
+            remoteSession.close();
+        }
+
         return future;
     }
     

Modified: directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeFilterChain.java
URL: http://svn.apache.org/viewvc/directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeFilterChain.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeFilterChain.java (original)
+++ directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeFilterChain.java Mon Oct 16 23:08:44 2006
@@ -100,8 +100,8 @@
                     s.increaseWrittenWriteRequests();
     
                     s.getFilterChain().fireMessageSent( s, writeRequest );
-                    s.remoteSession.getFilterChain()
-                                .fireMessageReceived( s.remoteSession, messageCopy );
+                    s.getRemoteSession().getFilterChain()
+                                .fireMessageReceived( s.getRemoteSession(), messageCopy );
                 }
             }
             else 
@@ -119,7 +119,7 @@
             if( !session.getCloseFuture().isClosed() )
             {
                 s.getServiceListeners().fireSessionDestroyed( s );
-                s.remoteSession.close();
+                s.getRemoteSession().close();
             }
         }
     }

Modified: directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeSessionImpl.java
URL: http://svn.apache.org/viewvc/directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeSessionImpl.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeSessionImpl.java (original)
+++ directory/branches/mina/1.0/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeSessionImpl.java Mon Oct 16 23:08:44 2006
@@ -19,10 +19,8 @@
  */
 package org.apache.mina.transport.vmpipe.support;
 
-import java.io.IOException;
 import java.net.SocketAddress;
 
-import org.apache.mina.common.ExceptionMonitor;
 import org.apache.mina.common.IoFilterChain;
 import org.apache.mina.common.IoHandler;
 import org.apache.mina.common.IoService;
@@ -54,7 +52,7 @@
     private final SocketAddress serviceAddress;
     private final IoHandler handler;
     private final VmPipeFilterChain filterChain;
-    final VmPipeSessionImpl remoteSession;
+    private final VmPipeSessionImpl remoteSession;
     final Object lock;
     final Queue pendingDataQueue;
 
@@ -64,7 +62,7 @@
     public VmPipeSessionImpl(
             IoService service, IoServiceConfig serviceConfig,
             IoServiceListenerSupport serviceListeners, Object lock, SocketAddress localAddress,
-            IoHandler handler, VmPipe remoteEntry ) throws IOException
+            IoHandler handler, VmPipe remoteEntry )
     {
         this.service = service;
         this.serviceConfig = serviceConfig;
@@ -77,27 +75,12 @@
         this.pendingDataQueue = new Queue();
 
         remoteSession = new VmPipeSessionImpl( this, remoteEntry );
-        
-        // initialize connector session
-        try
-        {
-            service.getFilterChainBuilder().buildFilterChain( filterChain );
-            serviceConfig.getFilterChainBuilder().buildFilterChain( filterChain );
-            serviceConfig.getThreadModel().buildFilterChain( filterChain );
-            serviceListeners.fireSessionCreated( this );
-        }
-        catch( Throwable t )
-        {
-            throw ( IOException ) new IOException( "Failed to create a connector session." ).initCause( t );
-        }
-
-        VmPipeIdleStatusChecker.getInstance().addSession( this );
     }
 
     /**
      * Constructor for server-side session.
      */
-    private VmPipeSessionImpl( VmPipeSessionImpl remoteSession, VmPipe entry ) throws IOException
+    private VmPipeSessionImpl( VmPipeSessionImpl remoteSession, VmPipe entry )
     {
         this.service = entry.getAcceptor();
         this.serviceConfig = entry.getConfig();
@@ -109,24 +92,6 @@
         this.filterChain = new VmPipeFilterChain( this );
         this.remoteSession = remoteSession;
         this.pendingDataQueue = new Queue();
-
-        // initialize acceptor session
-        try
-        {
-            entry.getAcceptor().getFilterChainBuilder().buildFilterChain( this.getFilterChain() );
-            entry.getConfig().getFilterChainBuilder().buildFilterChain( this.getFilterChain() );
-            entry.getConfig().getThreadModel().buildFilterChain( this.getFilterChain() );
-            serviceListeners.fireSessionCreated( this );
-        }
-        catch( Throwable t )
-        {
-            ExceptionMonitor.getInstance().exceptionCaught( t );
-            IOException e = new IOException( "Failed to initialize acceptor session." );
-            e.initCause( t );
-            throw e;
-        }
-        
-        VmPipeIdleStatusChecker.getInstance().addSession( this );
     }
     
     public IoService getService()
@@ -152,6 +117,11 @@
     public IoFilterChain getFilterChain()
     {
         return filterChain;
+    }
+    
+    public VmPipeSessionImpl getRemoteSession()
+    {
+        return remoteSession;
     }
 
     public IoHandler getHandler()

Added: directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/AbstractConnectorTest.java
URL: http://svn.apache.org/viewvc/directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/AbstractConnectorTest.java?view=auto&rev=464824
==============================================================================
--- directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/AbstractConnectorTest.java (added)
+++ directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/AbstractConnectorTest.java Mon Oct 16 23:08:44 2006
@@ -0,0 +1,126 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.mina.transport;
+
+import java.net.InetSocketAddress;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.common.IoHandlerAdapter;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.RuntimeIOException;
+import org.apache.mina.util.AvailablePortFinder;
+
+/**
+ * Tests a generic {@link IoConnector}.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev$, $Date$ 
+ */
+public abstract class AbstractConnectorTest extends TestCase {
+
+    protected abstract IoAcceptor createAcceptor();
+    protected abstract IoConnector createConnector();
+    
+    public void testConnectFutureSuccessTiming() throws Exception
+    {
+        int port = AvailablePortFinder.getNextAvailable( 1025 );
+        IoAcceptor acceptor = createAcceptor();
+        acceptor.bind( new InetSocketAddress( port ), new IoHandlerAdapter() );
+        
+        try
+        {
+            final StringBuffer buf = new StringBuffer();
+            IoConnector connector = createConnector();
+            ConnectFuture future = connector.connect(
+                    new InetSocketAddress( "localhost", port ),
+                    new IoHandlerAdapter()
+                    {
+                        public void sessionCreated( IoSession session )
+                        {
+                            buf.append( "1" );
+                        }
+                        
+                        public void sessionOpened( IoSession session )
+                        {
+                            buf.append( "2" );
+                        }
+                        
+                        public void exceptionCaught( IoSession session, Throwable cause )
+                        {
+                            buf.append( "X" );
+                        }
+                    });
+            
+            future.join();
+            buf.append("3");
+            future.getSession().close();
+            Assert.assertEquals( "123", buf.toString() );
+        }
+        finally
+        {
+            acceptor.unbind( new InetSocketAddress( port ) );
+        }
+    }
+
+    public void testConnectFutureFailureTiming() throws Exception
+    {
+        int port = AvailablePortFinder.getNextAvailable( 1025 );
+        final StringBuffer buf = new StringBuffer();
+
+        IoConnector connector = createConnector();
+        ConnectFuture future = connector.connect(
+                new InetSocketAddress( "localhost", port ),
+                new IoHandlerAdapter()
+                {
+                    public void sessionCreated( IoSession session )
+                    {
+                        buf.append( "X" );
+                    }
+                    
+                    public void sessionOpened( IoSession session )
+                    {
+                        buf.append( "Y" );
+                    }
+                    
+                    public void exceptionCaught( IoSession session, Throwable cause )
+                    {
+                        buf.append( "Z" );
+                    }
+                });
+        
+        future.join();
+        buf.append("1");
+        try
+        {
+            future.getSession().close();
+            fail();
+        }
+        catch( RuntimeIOException e )
+        {
+            // OK.
+        }
+        Assert.assertEquals( "1", buf.toString() );
+    }
+}

Added: directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConnectorTest.java
URL: http://svn.apache.org/viewvc/directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConnectorTest.java?view=auto&rev=464824
==============================================================================
--- directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConnectorTest.java (added)
+++ directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConnectorTest.java Mon Oct 16 23:08:44 2006
@@ -0,0 +1,51 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.mina.transport.socket.nio;
+
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.transport.AbstractConnectorTest;
+
+/**
+ * Tests {@link DatagramConnector}.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev$, $Date$ 
+ */
+public class DatagramConnectorTest extends AbstractConnectorTest {
+
+    protected IoAcceptor createAcceptor()
+    {
+        return new DatagramAcceptor();
+    }
+
+    protected IoConnector createConnector()
+    {
+        return new DatagramConnector();
+    }
+
+    public void testConnectFutureFailureTiming() throws Exception
+    {
+        // Skip the test; Datagram connection can be made even if there's no
+        // server at the endpoint.
+    }
+    
+    
+}

Added: directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/socket/nio/SocketConnectorTest.java
URL: http://svn.apache.org/viewvc/directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/socket/nio/SocketConnectorTest.java?view=auto&rev=464824
==============================================================================
--- directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/socket/nio/SocketConnectorTest.java (added)
+++ directory/branches/mina/1.0/core/src/test/java/org/apache/mina/transport/socket/nio/SocketConnectorTest.java Mon Oct 16 23:08:44 2006
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.mina.transport.socket.nio;
+
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.transport.AbstractConnectorTest;
+
+/**
+ * Tests {@link SocketConnector}.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev$, $Date$ 
+ */
+public class SocketConnectorTest extends AbstractConnectorTest {
+
+    protected IoAcceptor createAcceptor()
+    {
+        return new SocketAcceptor();
+    }
+
+    protected IoConnector createConnector()
+    {
+        return new SocketConnector();
+    }
+}

Modified: directory/trunks/mina/core/src/main/java/org/apache/mina/common/support/AbstractIoFilterChain.java
URL: http://svn.apache.org/viewvc/directory/trunks/mina/core/src/main/java/org/apache/mina/common/support/AbstractIoFilterChain.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/trunks/mina/core/src/main/java/org/apache/mina/common/support/AbstractIoFilterChain.java (original)
+++ directory/trunks/mina/core/src/main/java/org/apache/mina/common/support/AbstractIoFilterChain.java Mon Oct 16 23:08:44 2006
@@ -26,6 +26,7 @@
 import java.util.Map;
 
 import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.ConnectFuture;
 import org.apache.mina.common.IdleStatus;
 import org.apache.mina.common.IoFilter;
 import org.apache.mina.common.IoFilterAdapter;
@@ -52,10 +53,17 @@
  */
 public abstract class AbstractIoFilterChain implements IoFilterChain
 {
-    private final IoSession session;
+    /**
+     * A session attribute that stores a {@link ConnectFuture} related with
+     * the {@link IoSession}.  {@link AbstractIoFilterChain} clears this
+     * attribute and notifies the future when {@link #fireSessionOpened(IoSession)}
+     * or {@link #fireExceptionCaught(IoSession, Throwable)} is invoked
+     */
+    public static final String CONNECT_FUTURE =
+        AbstractIoFilterChain.class.getName() + ".connectFuture";
 
+    private final IoSession session;
     private final Map name2entry = new HashMap();
-
     private final EntryImpl head;
     private final EntryImpl tail;
 
@@ -67,160 +75,11 @@
         }
 
         this.session = session;
-        head = new EntryImpl( null, null, "head", createHeadFilter() );
-        tail = new EntryImpl( head, null, "tail", createTailFilter() );
+        head = new EntryImpl( null, null, "head", new HeadFilter() );
+        tail = new EntryImpl( head, null, "tail", new TailFilter() );
         head.nextEntry = tail;
     }
 
-    /**
-     * Override this method to create custom head of this filter chain.
-     */
-    protected IoFilter createHeadFilter()
-    {
-        return new IoFilterAdapter()
-        {
-            public void sessionCreated( NextFilter nextFilter, IoSession session )
-            {
-                nextFilter.sessionCreated( session );
-            }
-
-            public void sessionOpened( NextFilter nextFilter, IoSession session )
-            {
-                nextFilter.sessionOpened( session );
-            }
-
-            public void sessionClosed( NextFilter nextFilter, IoSession session )
-            {
-                nextFilter.sessionClosed( session );
-            }
-
-            public void sessionIdle( NextFilter nextFilter, IoSession session,
-                                    IdleStatus status )
-            {
-                nextFilter.sessionIdle( session, status );
-            }
-
-            public void exceptionCaught( NextFilter nextFilter,
-                                        IoSession session, Throwable cause )
-            {
-                nextFilter.exceptionCaught( session, cause );
-            }
-
-            public void messageReceived( NextFilter nextFilter, IoSession session,
-                                         Object message )
-            {
-                nextFilter.messageReceived( session, message );
-            }
-
-            public void messageSent( NextFilter nextFilter, IoSession session,
-                                     Object message )
-            {
-                nextFilter.messageSent( session, message );
-            }
-
-            public void filterWrite( NextFilter nextFilter, IoSession session,
-                                     WriteRequest writeRequest ) throws Exception
-            {
-                if( session.getTransportType().getEnvelopeType().isAssignableFrom( writeRequest.getMessage().getClass() ) )
-                {
-                    doWrite( session, writeRequest );
-                }
-                else
-                {
-                    throw new IllegalStateException(
-                            "Write requests must be transformed to " +
-                            session.getTransportType().getEnvelopeType() +
-                            ": " + writeRequest );
-                }
-            }
-
-            public void filterClose( NextFilter nextFilter, IoSession session ) throws Exception
-            {
-                doClose( session );
-            }
-        };
-    }
-
-    /**
-     * Override this method to create custom head of this filter chain.
-     */
-    protected IoFilter createTailFilter()
-    {
-        return new IoFilterAdapter()
-        {
-            public void sessionCreated( NextFilter nextFilter, IoSession session ) throws Exception
-            {
-                session.getHandler().sessionCreated( session );
-            }
-            public void sessionOpened( NextFilter nextFilter, IoSession session ) throws Exception
-            {
-                session.getHandler().sessionOpened( session );
-            }
-
-            public void sessionClosed( NextFilter nextFilter, IoSession session ) throws Exception
-            {
-                try
-                {
-                    session.getHandler().sessionClosed( session );
-                }
-                finally
-                {
-                    // Remove all filters.
-                    session.getFilterChain().clear();
-                }
-            }
-
-            public void sessionIdle( NextFilter nextFilter, IoSession session,
-                                    IdleStatus status ) throws Exception
-            {
-                session.getHandler().sessionIdle( session, status );
-            }
-
-            public void exceptionCaught( NextFilter nextFilter,
-                                        IoSession session, Throwable cause ) throws Exception
-            {
-                session.getHandler().exceptionCaught( session, cause );
-            }
-
-            public void messageReceived( NextFilter nextFilter, IoSession session,
-                                         Object message ) throws Exception
-            {
-                try
-                {
-                    session.getHandler().messageReceived( session, message );
-                }
-                finally
-                {
-                    ByteBufferUtil.releaseIfPossible( message );
-                }
-            }
-
-            public void messageSent( NextFilter nextFilter, IoSession session,
-                                     Object message ) throws Exception
-            {
-                try
-                {
-                    session.getHandler().messageSent( session, message );
-                }
-                finally
-                {
-                    ByteBufferUtil.releaseIfPossible( message );
-                }
-            }
-
-            public void filterWrite( NextFilter nextFilter,
-                                     IoSession session, WriteRequest writeRequest ) throws Exception
-            {
-                nextFilter.filterWrite( session, writeRequest );
-            }
-
-            public void filterClose( NextFilter nextFilter, IoSession session ) throws Exception
-            {
-                nextFilter.filterClose( session );
-            }
-        };
-    }
-
     public IoSession getSession()
     {
         return session;
@@ -539,8 +398,20 @@
 
     public void fireExceptionCaught( IoSession session, Throwable cause )
     {
-        Entry head = this.head;
-        callNextExceptionCaught(head, session, cause);
+        // Notify the related ConnectFuture
+        // if the session is created from SocketConnector.
+        ConnectFuture future = ( ConnectFuture ) session.removeAttribute( CONNECT_FUTURE );
+        if( future == null )
+        {
+            Entry head = this.head;
+            callNextExceptionCaught( head, session, cause );
+        }
+        else
+        {
+            // Please note that this place is not the only place that
+            // calls ConnectFuture.setException().
+            future.setException( cause );
+        }
     }
 
     private void callNextExceptionCaught( Entry entry,
@@ -710,6 +581,157 @@
     protected abstract void doWrite( IoSession session, WriteRequest writeRequest ) throws Exception;
 
     protected abstract void doClose( IoSession session ) throws Exception;
+
+    private class HeadFilter extends IoFilterAdapter
+    {
+        public void sessionCreated( NextFilter nextFilter, IoSession session )
+        {
+            nextFilter.sessionCreated( session );
+        }
+
+        public void sessionOpened( NextFilter nextFilter, IoSession session )
+        {
+            nextFilter.sessionOpened( session );
+        }
+
+        public void sessionClosed( NextFilter nextFilter, IoSession session )
+        {
+            nextFilter.sessionClosed( session );
+        }
+
+        public void sessionIdle( NextFilter nextFilter, IoSession session,
+                                IdleStatus status )
+        {
+            nextFilter.sessionIdle( session, status );
+        }
+
+        public void exceptionCaught( NextFilter nextFilter,
+                                    IoSession session, Throwable cause )
+        {
+            nextFilter.exceptionCaught( session, cause );
+        }
+
+        public void messageReceived( NextFilter nextFilter, IoSession session,
+                                     Object message )
+        {
+            nextFilter.messageReceived( session, message );
+        }
+
+        public void messageSent( NextFilter nextFilter, IoSession session,
+                                 Object message )
+        {
+            nextFilter.messageSent( session, message );
+        }
+
+        public void filterWrite( NextFilter nextFilter, IoSession session,
+                                 WriteRequest writeRequest ) throws Exception
+        {
+            if( session.getTransportType().getEnvelopeType().isAssignableFrom( writeRequest.getMessage().getClass() ) )
+            {
+                doWrite( session, writeRequest );
+            }
+            else
+            {
+                throw new IllegalStateException(
+                        "Write requests must be transformed to " +
+                        session.getTransportType().getEnvelopeType() +
+                        ": " + writeRequest );
+            }
+        }
+
+        public void filterClose( NextFilter nextFilter, IoSession session ) throws Exception
+        {
+            doClose( session );
+        }
+    }
+
+    private static class TailFilter extends IoFilterAdapter
+    {
+        public void sessionCreated( NextFilter nextFilter, IoSession session ) throws Exception
+        {
+            session.getHandler().sessionCreated( session );
+        }
+
+        public void sessionOpened( NextFilter nextFilter, IoSession session ) throws Exception
+        {
+            try
+            {
+                session.getHandler().sessionOpened( session );
+            }
+            finally
+            {
+                // Notify the related ConnectFuture
+                // if the session is created from SocketConnector.
+                ConnectFuture future = ( ConnectFuture ) session.removeAttribute( CONNECT_FUTURE );
+                if( future != null )
+                {
+                    future.setSession( session );
+                }
+            }
+        }
+
+        public void sessionClosed( NextFilter nextFilter, IoSession session ) throws Exception
+        {
+            try
+            {
+                session.getHandler().sessionClosed( session );
+            }
+            finally
+            {
+                // Remove all filters.
+                session.getFilterChain().clear();
+            }
+        }
+
+        public void sessionIdle( NextFilter nextFilter, IoSession session,
+                                IdleStatus status ) throws Exception
+        {
+            session.getHandler().sessionIdle( session, status );
+        }
+
+        public void exceptionCaught( NextFilter nextFilter,
+                                    IoSession session, Throwable cause ) throws Exception
+        {
+            session.getHandler().exceptionCaught( session, cause );
+        }
+
+        public void messageReceived( NextFilter nextFilter, IoSession session,
+                                     Object message ) throws Exception
+        {
+            try
+            {
+                session.getHandler().messageReceived( session, message );
+            }
+            finally
+            {
+                ByteBufferUtil.releaseIfPossible( message );
+            }
+        }
+
+        public void messageSent( NextFilter nextFilter, IoSession session,
+                                 Object message ) throws Exception
+        {
+            try
+            {
+                session.getHandler().messageSent( session, message );
+            }
+            finally
+            {
+                ByteBufferUtil.releaseIfPossible( message );
+            }
+        }
+
+        public void filterWrite( NextFilter nextFilter,
+                                 IoSession session, WriteRequest writeRequest ) throws Exception
+        {
+            nextFilter.filterWrite( session, writeRequest );
+        }
+
+        public void filterClose( NextFilter nextFilter, IoSession session ) throws Exception
+        {
+            nextFilter.filterClose( session );
+        }
+    }
 
     private class EntryImpl implements Entry
     {

Modified: directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketAcceptor.java
URL: http://svn.apache.org/viewvc/directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketAcceptor.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketAcceptor.java (original)
+++ directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketAcceptor.java Mon Oct 16 23:08:44 2006
@@ -343,13 +343,9 @@
                 try
                 {
                     RegistrationRequest req = ( RegistrationRequest ) key.attachment();
-                    SocketSessionImpl session = new SocketSessionImpl( SocketAcceptor.this,
-                                                                       nextProcessor(),
-                                                                       getListeners(),
-                                                                       req.config,
-                                                                       ch,
-                                                                       req.handler,
-                                                                       req.address );
+                    SocketSessionImpl session = new SocketSessionImpl(
+                            SocketAcceptor.this, nextProcessor(), getListeners(),
+                            req.config, ch, req.handler, req.address );
                     getFilterChainBuilder().buildFilterChain( session.getFilterChain() );
                     req.config.getFilterChainBuilder().buildFilterChain( session.getFilterChain() );
                     req.config.getThreadModel().buildFilterChain( session.getFilterChain() );

Modified: directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketConnector.java
URL: http://svn.apache.org/viewvc/directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketConnector.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketConnector.java (original)
+++ directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketConnector.java Mon Oct 16 23:08:44 2006
@@ -35,6 +35,7 @@
 import org.apache.mina.common.IoConnectorConfig;
 import org.apache.mina.common.IoHandler;
 import org.apache.mina.common.IoServiceConfig;
+import org.apache.mina.common.support.AbstractIoFilterChain;
 import org.apache.mina.common.support.BaseIoConnector;
 import org.apache.mina.common.support.DefaultConnectFuture;
 import org.apache.mina.util.Queue;
@@ -365,13 +366,9 @@
     private void newSession( SocketChannel ch, IoHandler handler, IoServiceConfig config, ConnectFuture connectFuture )
         throws IOException
     {
-        SocketSessionImpl session = new SocketSessionImpl( this,
-                                                           nextProcessor(),
-                                                           getListeners(),
-                                                           config,
-                                                           ch,
-                                                           handler,
-                                                           ch.socket().getRemoteSocketAddress() );
+        SocketSessionImpl session = new SocketSessionImpl(
+                this, nextProcessor(), getListeners(),
+                config, ch, handler, ch.socket().getRemoteSocketAddress() );
         try
         {
             getFilterChainBuilder().buildFilterChain( session.getFilterChain() );
@@ -382,8 +379,13 @@
         {
             throw ( IOException ) new IOException( "Failed to create a session." ).initCause( e );
         }
+        
+        // Set the ConnectFuture of the specified session, which will be
+        // removed and notified by AbstractIoFilterChain eventually.
+        session.setAttribute( AbstractIoFilterChain.CONNECT_FUTURE, connectFuture );
+
+        // Forward the remaining process to the SocketIoProcessor.
         session.getIoProcessor().addNew( session );
-        connectFuture.setSession( session );
     }
 
     private SocketIoProcessor nextProcessor()

Modified: directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketIoProcessor.java
URL: http://svn.apache.org/viewvc/directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketIoProcessor.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketIoProcessor.java (original)
+++ directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketIoProcessor.java Mon Oct 16 23:08:44 2006
@@ -160,25 +160,22 @@
                 break;
 
             SocketChannel ch = session.getChannel();
-            boolean registered;
-
             try
             {
                 ch.configureBlocking( false );
                 session.setSelectionKey( ch.register( selector,
                                                       SelectionKey.OP_READ,
                                                       session ) );
-                registered = true;
+
+                // AbstractIoFilterChain.CONNECT_FUTURE is cleared inside here
+                // in AbstractIoFilterChain.fireSessionOpened().
+                session.getServiceListeners().fireSessionCreated( session );
             }
             catch( IOException e )
             {
-                registered = false;
+                // Clear the AbstractIoFilterChain.CONNECT_FUTURE attribute
+                // and call ConnectFuture.setException().
                 session.getFilterChain().fireExceptionCaught( session, e );
-            }
-
-            if( registered )
-            {
-                session.getServiceListeners().fireSessionCreated( session );
             }
         }
     }

Modified: directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketSessionImpl.java
URL: http://svn.apache.org/viewvc/directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketSessionImpl.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketSessionImpl.java (original)
+++ directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/SocketSessionImpl.java Mon Oct 16 23:08:44 2006
@@ -149,7 +149,7 @@
     {
         this.key = key;
     }
-
+    
     public IoHandler getHandler()
     {
         return handler;

Modified: directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/support/DatagramConnectorDelegate.java
URL: http://svn.apache.org/viewvc/directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/support/DatagramConnectorDelegate.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/support/DatagramConnectorDelegate.java (original)
+++ directory/trunks/mina/core/src/main/java/org/apache/mina/transport/socket/nio/support/DatagramConnectorDelegate.java Mon Oct 16 23:08:44 2006
@@ -37,6 +37,7 @@
 import org.apache.mina.common.IoSession;
 import org.apache.mina.common.IoSessionRecycler;
 import org.apache.mina.common.IoFilter.WriteRequest;
+import org.apache.mina.common.support.AbstractIoFilterChain;
 import org.apache.mina.common.support.BaseIoConnector;
 import org.apache.mina.common.support.DefaultConnectFuture;
 import org.apache.mina.transport.socket.nio.DatagramConnectorConfig;
@@ -613,6 +614,9 @@
                     req.config,
                     req.channel, req.handler,
                     req.channel.socket().getRemoteSocketAddress() );
+            
+            // AbstractIoFilterChain will notify the connect future.
+            session.setAttribute( AbstractIoFilterChain.CONNECT_FUTURE, req );
 
             boolean success = false;
             try
@@ -625,21 +629,20 @@
                 }
                 else
                 {
+                    SelectionKey key = req.channel.register( selector,
+                            SelectionKey.OP_READ, session );
+
+                    session.setSelectionKey( key );
                     buildFilterChain( req, session );
+                    // The CONNECT_FUTURE attribute is cleared and notified here.
                     getListeners().fireSessionCreated( session );
                 }
-
-                SelectionKey key = req.channel.register( selector,
-                                                         SelectionKey.OP_READ, session );
-
-                session.setSelectionKey( key );
-
-                req.setSession( session );
                 success = true;
             }
             catch( Throwable t )
             {
-                req.setException( t );
+                // The CONNECT_FUTURE attribute is cleared and notified here.
+                session.getFilterChain().fireExceptionCaught( session, t );
             }
             finally
             {

Modified: directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeConnector.java
URL: http://svn.apache.org/viewvc/directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeConnector.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeConnector.java (original)
+++ directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/VmPipeConnector.java Mon Oct 16 23:08:44 2006
@@ -23,14 +23,18 @@
 import java.net.SocketAddress;
 
 import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.common.ExceptionMonitor;
+import org.apache.mina.common.IoFilterChain;
 import org.apache.mina.common.IoHandler;
 import org.apache.mina.common.IoServiceConfig;
 import org.apache.mina.common.IoSessionConfig;
+import org.apache.mina.common.support.AbstractIoFilterChain;
 import org.apache.mina.common.support.BaseIoConnector;
 import org.apache.mina.common.support.BaseIoConnectorConfig;
 import org.apache.mina.common.support.BaseIoSessionConfig;
 import org.apache.mina.common.support.DefaultConnectFuture;
 import org.apache.mina.transport.vmpipe.support.VmPipe;
+import org.apache.mina.transport.vmpipe.support.VmPipeIdleStatusChecker;
 import org.apache.mina.transport.vmpipe.support.VmPipeSessionImpl;
 import org.apache.mina.util.AnonymousSocketAddress;
 
@@ -87,23 +91,53 @@
         }
 
         DefaultConnectFuture future = new DefaultConnectFuture();
+        VmPipeSessionImpl localSession =
+            new VmPipeSessionImpl(
+                    this,
+                    config,
+                    getListeners(),
+                    new Object(), // lock
+                    new AnonymousSocketAddress(),
+                    handler,
+                    entry );
+        
+        // initialize connector session
         try
         {
-            VmPipeSessionImpl session =
-                new VmPipeSessionImpl(
-                        this,
-                        config,
-                        getListeners(),
-                        new Object(), // lock
-                        new AnonymousSocketAddress(),
-                        handler,
-                        entry );
-            future.setSession( session );
+            IoFilterChain filterChain = localSession.getFilterChain();
+            this.getFilterChainBuilder().buildFilterChain( filterChain );
+            config.getFilterChainBuilder().buildFilterChain( filterChain );
+            config.getThreadModel().buildFilterChain( filterChain );
+
+            // The following sentences don't throw any exceptions.
+            localSession.setAttribute( AbstractIoFilterChain.CONNECT_FUTURE, future );
+            getListeners().fireSessionCreated( localSession );
+            VmPipeIdleStatusChecker.getInstance().addSession( localSession);
         }
-        catch( IOException e )
+        catch( Throwable t )
         {
-            future.setException( e );
+            future.setException( t );
         }
+        
+        // initialize acceptor session
+        VmPipeSessionImpl remoteSession = localSession.getRemoteSession();
+        try
+        {
+            IoFilterChain filterChain = remoteSession.getFilterChain();
+            entry.getAcceptor().getFilterChainBuilder().buildFilterChain( filterChain );
+            entry.getConfig().getFilterChainBuilder().buildFilterChain( filterChain );
+            entry.getConfig().getThreadModel().buildFilterChain( filterChain );
+            
+            // The following sentences don't throw any exceptions.
+            entry.getListeners().fireSessionCreated( remoteSession );
+            VmPipeIdleStatusChecker.getInstance().addSession( remoteSession );
+        }
+        catch( Throwable t )
+        {
+            ExceptionMonitor.getInstance().exceptionCaught( t );
+            remoteSession.close();
+        }
+
         return future;
     }
     

Modified: directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeFilterChain.java
URL: http://svn.apache.org/viewvc/directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeFilterChain.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeFilterChain.java (original)
+++ directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeFilterChain.java Mon Oct 16 23:08:44 2006
@@ -100,8 +100,8 @@
                     s.increaseWrittenWriteRequests();
     
                     s.getFilterChain().fireMessageSent( s, writeRequest );
-                    s.remoteSession.getFilterChain()
-                                .fireMessageReceived( s.remoteSession, messageCopy );
+                    s.getRemoteSession().getFilterChain()
+                                .fireMessageReceived( s.getRemoteSession(), messageCopy );
                 }
             }
             else 
@@ -119,7 +119,7 @@
             if( !session.getCloseFuture().isClosed() )
             {
                 s.getServiceListeners().fireSessionDestroyed( s );
-                s.remoteSession.close();
+                s.getRemoteSession().close();
             }
         }
     }

Modified: directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeSessionImpl.java
URL: http://svn.apache.org/viewvc/directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeSessionImpl.java?view=diff&rev=464824&r1=464823&r2=464824
==============================================================================
--- directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeSessionImpl.java (original)
+++ directory/trunks/mina/core/src/main/java/org/apache/mina/transport/vmpipe/support/VmPipeSessionImpl.java Mon Oct 16 23:08:44 2006
@@ -19,10 +19,8 @@
  */
 package org.apache.mina.transport.vmpipe.support;
 
-import java.io.IOException;
 import java.net.SocketAddress;
 
-import org.apache.mina.common.ExceptionMonitor;
 import org.apache.mina.common.IoFilterChain;
 import org.apache.mina.common.IoHandler;
 import org.apache.mina.common.IoService;
@@ -54,7 +52,7 @@
     private final SocketAddress serviceAddress;
     private final IoHandler handler;
     private final VmPipeFilterChain filterChain;
-    final VmPipeSessionImpl remoteSession;
+    private final VmPipeSessionImpl remoteSession;
     final Object lock;
     final Queue pendingDataQueue;
 
@@ -64,7 +62,7 @@
     public VmPipeSessionImpl(
             IoService service, IoServiceConfig serviceConfig,
             IoServiceListenerSupport serviceListeners, Object lock, SocketAddress localAddress,
-            IoHandler handler, VmPipe remoteEntry ) throws IOException
+            IoHandler handler, VmPipe remoteEntry )
     {
         this.service = service;
         this.serviceConfig = serviceConfig;
@@ -77,27 +75,12 @@
         this.pendingDataQueue = new Queue();
 
         remoteSession = new VmPipeSessionImpl( this, remoteEntry );
-        
-        // initialize connector session
-        try
-        {
-            service.getFilterChainBuilder().buildFilterChain( filterChain );
-            serviceConfig.getFilterChainBuilder().buildFilterChain( filterChain );
-            serviceConfig.getThreadModel().buildFilterChain( filterChain );
-            serviceListeners.fireSessionCreated( this );
-        }
-        catch( Throwable t )
-        {
-            throw ( IOException ) new IOException( "Failed to create a connector session." ).initCause( t );
-        }
-
-        VmPipeIdleStatusChecker.getInstance().addSession( this );
     }
 
     /**
      * Constructor for server-side session.
      */
-    private VmPipeSessionImpl( VmPipeSessionImpl remoteSession, VmPipe entry ) throws IOException
+    private VmPipeSessionImpl( VmPipeSessionImpl remoteSession, VmPipe entry )
     {
         this.service = entry.getAcceptor();
         this.serviceConfig = entry.getConfig();
@@ -109,24 +92,6 @@
         this.filterChain = new VmPipeFilterChain( this );
         this.remoteSession = remoteSession;
         this.pendingDataQueue = new Queue();
-
-        // initialize acceptor session
-        try
-        {
-            entry.getAcceptor().getFilterChainBuilder().buildFilterChain( this.getFilterChain() );
-            entry.getConfig().getFilterChainBuilder().buildFilterChain( this.getFilterChain() );
-            entry.getConfig().getThreadModel().buildFilterChain( this.getFilterChain() );
-            serviceListeners.fireSessionCreated( this );
-        }
-        catch( Throwable t )
-        {
-            ExceptionMonitor.getInstance().exceptionCaught( t );
-            IOException e = new IOException( "Failed to initialize acceptor session." );
-            e.initCause( t );
-            throw e;
-        }
-        
-        VmPipeIdleStatusChecker.getInstance().addSession( this );
     }
     
     public IoService getService()
@@ -152,6 +117,11 @@
     public IoFilterChain getFilterChain()
     {
         return filterChain;
+    }
+    
+    public VmPipeSessionImpl getRemoteSession()
+    {
+        return remoteSession;
     }
 
     public IoHandler getHandler()

Added: directory/trunks/mina/core/src/test/java/org/apache/mina/transport/AbstractConnectorTest.java
URL: http://svn.apache.org/viewvc/directory/trunks/mina/core/src/test/java/org/apache/mina/transport/AbstractConnectorTest.java?view=auto&rev=464824
==============================================================================
--- directory/trunks/mina/core/src/test/java/org/apache/mina/transport/AbstractConnectorTest.java (added)
+++ directory/trunks/mina/core/src/test/java/org/apache/mina/transport/AbstractConnectorTest.java Mon Oct 16 23:08:44 2006
@@ -0,0 +1,126 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.mina.transport;
+
+import java.net.InetSocketAddress;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.common.IoHandlerAdapter;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.RuntimeIOException;
+import org.apache.mina.util.AvailablePortFinder;
+
+/**
+ * Tests a generic {@link IoConnector}.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev$, $Date$ 
+ */
+public abstract class AbstractConnectorTest extends TestCase {
+
+    protected abstract IoAcceptor createAcceptor();
+    protected abstract IoConnector createConnector();
+    
+    public void testConnectFutureSuccessTiming() throws Exception
+    {
+        int port = AvailablePortFinder.getNextAvailable( 1025 );
+        IoAcceptor acceptor = createAcceptor();
+        acceptor.bind( new InetSocketAddress( port ), new IoHandlerAdapter() );
+        
+        try
+        {
+            final StringBuffer buf = new StringBuffer();
+            IoConnector connector = createConnector();
+            ConnectFuture future = connector.connect(
+                    new InetSocketAddress( "localhost", port ),
+                    new IoHandlerAdapter()
+                    {
+                        public void sessionCreated( IoSession session )
+                        {
+                            buf.append( "1" );
+                        }
+                        
+                        public void sessionOpened( IoSession session )
+                        {
+                            buf.append( "2" );
+                        }
+                        
+                        public void exceptionCaught( IoSession session, Throwable cause )
+                        {
+                            buf.append( "X" );
+                        }
+                    });
+            
+            future.join();
+            buf.append("3");
+            future.getSession().close();
+            Assert.assertEquals( "123", buf.toString() );
+        }
+        finally
+        {
+            acceptor.unbind( new InetSocketAddress( port ) );
+        }
+    }
+
+    public void testConnectFutureFailureTiming() throws Exception
+    {
+        int port = AvailablePortFinder.getNextAvailable( 1025 );
+        final StringBuffer buf = new StringBuffer();
+
+        IoConnector connector = createConnector();
+        ConnectFuture future = connector.connect(
+                new InetSocketAddress( "localhost", port ),
+                new IoHandlerAdapter()
+                {
+                    public void sessionCreated( IoSession session )
+                    {
+                        buf.append( "X" );
+                    }
+                    
+                    public void sessionOpened( IoSession session )
+                    {
+                        buf.append( "Y" );
+                    }
+                    
+                    public void exceptionCaught( IoSession session, Throwable cause )
+                    {
+                        buf.append( "Z" );
+                    }
+                });
+        
+        future.join();
+        buf.append("1");
+        try
+        {
+            future.getSession().close();
+            fail();
+        }
+        catch( RuntimeIOException e )
+        {
+            // OK.
+        }
+        Assert.assertEquals( "1", buf.toString() );
+    }
+}

Propchange: directory/trunks/mina/core/src/test/java/org/apache/mina/transport/AbstractConnectorTest.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/trunks/mina/core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConnectorTest.java
URL: http://svn.apache.org/viewvc/directory/trunks/mina/core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConnectorTest.java?view=auto&rev=464824
==============================================================================
--- directory/trunks/mina/core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConnectorTest.java (added)
+++ directory/trunks/mina/core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConnectorTest.java Mon Oct 16 23:08:44 2006
@@ -0,0 +1,51 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.mina.transport.socket.nio;
+
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.transport.AbstractConnectorTest;
+
+/**
+ * Tests {@link DatagramConnector}.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev$, $Date$ 
+ */
+public class DatagramConnectorTest extends AbstractConnectorTest {
+
+    protected IoAcceptor createAcceptor()
+    {
+        return new DatagramAcceptor();
+    }
+
+    protected IoConnector createConnector()
+    {
+        return new DatagramConnector();
+    }
+
+    public void testConnectFutureFailureTiming() throws Exception
+    {
+        // Skip the test; Datagram connection can be made even if there's no
+        // server at the endpoint.
+    }
+    
+    
+}

Propchange: directory/trunks/mina/core/src/test/java/org/apache/mina/transport/socket/nio/DatagramConnectorTest.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/trunks/mina/core/src/test/java/org/apache/mina/transport/socket/nio/SocketConnectorTest.java
URL: http://svn.apache.org/viewvc/directory/trunks/mina/core/src/test/java/org/apache/mina/transport/socket/nio/SocketConnectorTest.java?view=auto&rev=464824
==============================================================================
--- directory/trunks/mina/core/src/test/java/org/apache/mina/transport/socket/nio/SocketConnectorTest.java (added)
+++ directory/trunks/mina/core/src/test/java/org/apache/mina/transport/socket/nio/SocketConnectorTest.java Mon Oct 16 23:08:44 2006
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.mina.transport.socket.nio;
+
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.common.IoConnector;
+import org.apache.mina.transport.AbstractConnectorTest;
+
+/**
+ * Tests {@link SocketConnector}.
+ *
+ * @author The Apache Directory Project (mina-dev@directory.apache.org)
+ * @version $Rev$, $Date$ 
+ */
+public class SocketConnectorTest extends AbstractConnectorTest {
+
+    protected IoAcceptor createAcceptor()
+    {
+        return new SocketAcceptor();
+    }
+
+    protected IoConnector createConnector()
+    {
+        return new SocketConnector();
+    }
+}

Propchange: directory/trunks/mina/core/src/test/java/org/apache/mina/transport/socket/nio/SocketConnectorTest.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision