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 2005/12/06 04:04:08 UTC

svn commit: r354263 - in /directory/network/trunk/src: java/org/apache/mina/handler/ java/org/apache/mina/handler/chain/ java/org/apache/mina/handler/demux/ test/org/apache/mina/handler/ test/org/apache/mina/handler/demux/

Author: trustin
Date: Mon Dec  5 19:03:10 2005
New Revision: 354263

URL: http://svn.apache.org/viewcvs?rev=354263&view=rev
Log:
* Moved DemuxingIoHandler and its associates to handler.demux package for better organization
* Refactored handler.chain package to make it fit more tightly into MINA

Added:
    directory/network/trunk/src/java/org/apache/mina/handler/chain/ChainedIoHandler.java   (with props)
    directory/network/trunk/src/java/org/apache/mina/handler/chain/CommandChain.java   (with props)
    directory/network/trunk/src/java/org/apache/mina/handler/chain/package.html   (with props)
    directory/network/trunk/src/java/org/apache/mina/handler/demux/
    directory/network/trunk/src/java/org/apache/mina/handler/demux/DemuxingIoHandler.java
      - copied, changed from r354242, directory/network/trunk/src/java/org/apache/mina/handler/DemuxingIoHandler.java
    directory/network/trunk/src/java/org/apache/mina/handler/demux/MessageHandler.java
      - copied, changed from r354242, directory/network/trunk/src/java/org/apache/mina/handler/MessageHandler.java
    directory/network/trunk/src/java/org/apache/mina/handler/demux/UnknownMessageTypeException.java
      - copied, changed from r354242, directory/network/trunk/src/java/org/apache/mina/handler/UnknownMessageTypeException.java
    directory/network/trunk/src/java/org/apache/mina/handler/demux/package.html   (with props)
    directory/network/trunk/src/test/org/apache/mina/handler/demux/
    directory/network/trunk/src/test/org/apache/mina/handler/demux/DemuxingIoHandlerTest.java
      - copied, changed from r354242, directory/network/trunk/src/test/org/apache/mina/handler/DemuxingIoHandlerTest.java
Removed:
    directory/network/trunk/src/java/org/apache/mina/handler/DemuxingIoHandler.java
    directory/network/trunk/src/java/org/apache/mina/handler/MessageHandler.java
    directory/network/trunk/src/java/org/apache/mina/handler/UnknownMessageTypeException.java
    directory/network/trunk/src/java/org/apache/mina/handler/chain/Chain.java
    directory/network/trunk/src/java/org/apache/mina/handler/chain/Filter.java
    directory/network/trunk/src/test/org/apache/mina/handler/DemuxingIoHandlerTest.java
Modified:
    directory/network/trunk/src/java/org/apache/mina/handler/chain/Command.java

Added: directory/network/trunk/src/java/org/apache/mina/handler/chain/ChainedIoHandler.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/handler/chain/ChainedIoHandler.java?rev=354263&view=auto
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/handler/chain/ChainedIoHandler.java (added)
+++ directory/network/trunk/src/java/org/apache/mina/handler/chain/ChainedIoHandler.java Mon Dec  5 19:03:10 2005
@@ -0,0 +1,45 @@
+/*
+ *   Copyright 2005 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.mina.handler.chain;
+
+import org.apache.mina.common.IoHandlerAdapter;
+import org.apache.mina.common.IoSession;
+
+/**
+ * 
+ *
+ * @author The Apache Directory Project (dev@directory.apache.org)
+ * @version $Rev$, $Date$
+ */
+public class ChainedIoHandler extends IoHandlerAdapter
+{
+    private final Command command;
+
+    public ChainedIoHandler( Command command )
+    {
+        if( command == null )
+        {
+            throw new NullPointerException( "command" );
+        }
+        this.command = command;
+    }
+
+    public void messageReceived( IoSession session, Object message ) throws Exception
+    {
+        command.execute( null, session, message);
+    }
+}

Propchange: directory/network/trunk/src/java/org/apache/mina/handler/chain/ChainedIoHandler.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Modified: directory/network/trunk/src/java/org/apache/mina/handler/chain/Command.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/handler/chain/Command.java?rev=354263&r1=354262&r2=354263&view=diff
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/handler/chain/Command.java (original)
+++ directory/network/trunk/src/java/org/apache/mina/handler/chain/Command.java Mon Dec  5 19:03:10 2005
@@ -26,23 +26,14 @@
  * them to either complete the required processing or delegate further
  * processing to the next {@link Command} in the {@link Chain}.</p>
  *
- * <p>{@link Command} implementations should be designed in a thread-safe
- * manner, suitable for inclusion in multiple {@link Chain}s that might be
- * processed by different threads simultaneously.  In general, this implies
- * that {@link Command} classes should not maintain state information in
- * instance variables.  Instead, state information should be maintained via
- * suitable modifications to the attributes of the {@link Context} that is
- * passed to the <code>execute()</code> command.</p>
- *
  * <p>{@link Command} implementations typically retrieve and store state
- * information in the {@link Context} instance that is passed as a parameter
- * to the <code>execute()</code> method, using particular keys into the
- * <code>Map</code> that can be acquired via
- * <code>Context.getAttributes()</code>.  To improve interoperability of
- * {@link Command} implementations, a useful design pattern is to expose the
- * key values used as JavaBeans properties of the {@link Command}
- * implementation class itself.  For example, a {@link Command} that requires
- * an input and an output key might implement the following properties:</p>
+ * information in the {@link IoSession} that is passed as a parameter to
+ * the {@link #execute(NextCommand,IoSession,Object)} method, using custom
+ * session attributes.  To improve interoperability of {@link Command}
+ * implementations, a useful design pattern is to expose the key values
+ * used as JavaBeans properties of the {@link Command} implementation class
+ * itself.  For example, a {@link Command} that requires an input and an
+ * output key might implement the following properties:</p>
  *
  * <pre>
  *   private String inputKey = "input";
@@ -82,22 +73,24 @@
     /**
      * <p>Execute a unit of processing work to be performed.  This
      * {@link Command} may either complete the required processing
-     * and return <code>true</code>, or delegate remaining processing
-     * to the next {@link Command} in a {@link Chain} containing this
-     * {@link Command} by returning <code>false</code>
+     * and just return to stop the processing, or delegate remaining
+     * processing to the next {@link Command} in a {@link Chain}
+     * containing this {@link Command} by calling
+     * {@link NextCommand#execute(IoSession,Object)}.
      *
-     * @param context The {@link Context} to be processed by this
-     *  {@link Command}
+     * @param next an indirect referenct to the next {@link Command} that
+     *             provides a way to forward the request to the next {@link Command}.
+     * @param session the {@link IoSession} which is associated with 
+     *                this request
+     * @param message the message object of this request
      *
      * @exception Exception general purpose exception return
-     *  to indicate abnormal termination
-     * @exception IllegalArgumentException if <code>context</code>
-     *  is <code>null</code>
-     *
-     * @return <code>true</code> if the processing of this {@link Context}
-     *  has been completed, or <code>false</code> if the processing
-     *  of this {@link Context} should be delegated to a subsequent
-     *  {@link Command} in an enclosing {@link Chain}
+     *                      to indicate abnormal termination
      */
-    boolean execute( IoSession session ) throws Exception;
+    void execute( NextCommand next, IoSession session, Object message ) throws Exception;
+    
+    public interface NextCommand
+    {
+        void execute( IoSession session, Object message ) throws Exception;
+    }
 }

Added: directory/network/trunk/src/java/org/apache/mina/handler/chain/CommandChain.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/handler/chain/CommandChain.java?rev=354263&view=auto
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/handler/chain/CommandChain.java (added)
+++ directory/network/trunk/src/java/org/apache/mina/handler/chain/CommandChain.java Mon Dec  5 19:03:10 2005
@@ -0,0 +1,375 @@
+/*
+ *   @(#) $Id$
+ *
+ *   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.mina.handler.chain;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.mina.common.IoSession;
+
+/**
+ * @author The Apache Directory Project
+ * @version $Rev$, $Date$
+ */
+public class CommandChain implements Command
+{
+    private static volatile int nextId = 0;
+    
+    private final int id = nextId++;
+    private final String NEXT_COMMAND = CommandChain.class.getName() + '.' + id + ".nextCommand";
+    private final Map name2entry = new HashMap();
+    
+    private final Entry head;
+    private final Entry tail;
+
+    protected CommandChain()
+    {
+        head = new Entry( null, null, "head", createHeadCommand() );
+        tail = new Entry( head, null, "tail", createTailCommand() );
+        head.nextEntry = tail;
+    }
+    
+    private Command createHeadCommand()
+    {
+        return new Command()
+        {
+            public void execute( NextCommand next, IoSession session, Object message ) throws Exception
+            {
+                next.execute(session, message);
+            }
+        };
+    }
+    
+    private Command createTailCommand()
+    {
+        return new Command()
+        {
+            public void execute( NextCommand next, IoSession session, Object message ) throws Exception
+            {
+                next = ( NextCommand ) session.getAttribute( NEXT_COMMAND );
+                if( next != null )
+                {
+                    next.execute( session, message );
+                }
+            }
+        };
+    }
+    
+    public Entry getEntry( String name )
+    {
+        Entry e = ( Entry ) name2entry.get( name );
+        if ( e == null )
+        {
+            return null;
+        }
+        return e;
+    }
+    
+    public Command get( String name )
+    {
+        Entry e = getEntry( name );
+        if( e == null )
+        {
+            return null;
+        }
+        
+        return e.getCommand();
+    }
+    
+    public NextCommand getNextCommand( String name )
+    {
+        Entry e = getEntry( name );
+        if( e == null )
+        {
+            return null;
+        }
+        
+        return e.getNextCommand();
+    }
+    
+    public synchronized void addFirst( String name,
+                                       Command command )
+    {
+        checkAddable( name );
+        register( head, name, command );
+    }
+
+    public synchronized void addLast( String name,
+                                      Command command )
+    {
+        checkAddable( name );
+        register( tail.prevEntry, name, command );
+    }
+
+    public synchronized void addBefore( String baseName,
+                                        String name,
+                                        Command command )
+    {
+        Entry baseEntry = checkOldName( baseName );
+        checkAddable( name );
+        register( baseEntry.prevEntry, name, command );
+    }
+
+    public synchronized void addAfter( String baseName,
+                                       String name,
+                                       Command command )
+    {
+        Entry baseEntry = checkOldName( baseName );
+        checkAddable( name );
+        register( baseEntry, name, command );
+    }
+
+    public synchronized Command remove( String name )
+    {
+        Entry entry = checkOldName( name );
+        deregister( entry );
+        return entry.getCommand();
+    }
+
+    public synchronized void clear() throws Exception
+    {
+        Iterator it = new ArrayList( name2entry.keySet() ).iterator();
+        while ( it.hasNext() )
+        {
+            this.remove( ( String ) it.next() );
+        }
+    }
+
+    private void register( Entry prevEntry, String name, Command command )
+    {
+        Entry newEntry = new Entry( prevEntry, prevEntry.nextEntry, name, command );
+        prevEntry.nextEntry.prevEntry = newEntry;
+        prevEntry.nextEntry = newEntry;
+
+        name2entry.put( name, newEntry );
+    }
+    
+    private void deregister( Entry entry )
+    {
+        Entry prevEntry = entry.prevEntry;
+        Entry nextEntry = entry.nextEntry;
+        prevEntry.nextEntry = nextEntry;
+        nextEntry.prevEntry = prevEntry;
+
+        name2entry.remove( entry.name );
+    }
+
+    /**
+     * Throws an exception when the specified filter name is not registered in this chain.
+     *
+     * @return An filter entry with the specified name.
+     */
+    private Entry checkOldName( String baseName )
+    {
+        Entry e = ( Entry ) name2entry.get( baseName );
+        if ( e == null )
+        {
+            throw new IllegalArgumentException( "Unknown filter name:" +
+                    baseName );
+        }
+        return e;
+    }
+
+
+    /**
+     * Checks the specified filter name is already taken and throws an exception if already taken.
+     */
+    private void checkAddable( String name )
+    {
+        if ( name2entry.containsKey( name ) )
+        {
+            throw new IllegalArgumentException( "Other filter is using the same name '" + name + "'" );
+        }
+    }
+
+    public void execute( NextCommand next, IoSession session, Object message ) throws Exception
+    {
+        if( next != null )
+        {
+            session.setAttribute( NEXT_COMMAND, next );
+        }
+
+        try
+        {
+            callNextCommand( head, session, message );
+        }
+        finally
+        {
+            session.removeAttribute( NEXT_COMMAND );
+        }
+    }
+    
+    private void callNextCommand( Entry entry, IoSession session, Object message ) throws Exception
+    {
+        entry.getCommand().execute( entry.getNextCommand(), session, message );
+    }
+    
+    public List getAll()
+    {
+        List list = new ArrayList();
+        Entry e = head.nextEntry;
+        while( e != tail )
+        {
+            list.add( e );
+            e = e.nextEntry;
+        }
+
+        return list;
+    }
+
+    public List getAllReversed()
+    {
+        List list = new ArrayList();
+        Entry e = tail.prevEntry;
+        while( e != head )
+        {
+            list.add( e );
+            e = e.prevEntry;
+        }
+        return list;
+    }
+    
+    public boolean contains( String name )
+    {
+        return getEntry( name ) != null;
+    }
+
+    public boolean contains( Command command )
+    {
+        Entry e = head.nextEntry;
+        while( e != tail )
+        {
+            if( e.getCommand() == command )
+            {
+                return true;
+            }
+            e = e.nextEntry;
+        }
+        return false;
+    }
+
+    public boolean contains( Class commandType )
+    {
+        Entry e = head.nextEntry;
+        while( e != tail )
+        {
+            if( commandType.isAssignableFrom( e.getCommand().getClass() ) )
+            {
+                return true;
+            }
+            e = e.nextEntry;
+        }
+        return false;
+    }
+
+    public String toString()
+    {
+        StringBuffer buf = new StringBuffer();
+        buf.append( "{ " );
+        
+        boolean empty = true;
+        
+        Entry e = head.nextEntry;
+        while( e != tail )
+        {
+            if( !empty )
+            {
+                buf.append( ", " );
+            }
+            else
+            {
+                empty = false;
+            }
+            
+            buf.append( '(' );
+            buf.append( e.getName() );
+            buf.append( ':' );
+            buf.append( e.getCommand() );
+            buf.append( ')' );
+
+            e = e.nextEntry;
+        }
+
+        if( empty )
+        {
+            buf.append( "empty" );
+        }
+        
+        buf.append( " }" );
+        
+        return buf.toString();
+    }
+
+    public class Entry
+    {
+        private Entry prevEntry;
+
+        private Entry nextEntry;
+
+        private final String name;
+        
+        private final Command command;
+
+        private final NextCommand nextCommand;
+        
+        private Entry( Entry prevEntry, Entry nextEntry,
+                       String name, Command command )
+        {
+            if( command == null )
+            {
+                throw new NullPointerException( "command" );
+            }
+            if( name == null )
+            {
+                throw new NullPointerException( "name" );
+            }
+            
+            this.prevEntry = prevEntry;
+            this.nextEntry = nextEntry;
+            this.name = name;
+            this.command = command;
+            this.nextCommand = new NextCommand()
+            {
+                public void execute( IoSession session, Object message ) throws Exception
+                {
+                    Entry nextEntry = Entry.this.nextEntry;
+                    callNextCommand( nextEntry, session, message );
+                }
+            };
+        }
+        
+        public String getName()
+        {
+            return name;
+        }
+        
+        public Command getCommand()
+        {
+            return command;
+        }
+        
+        public NextCommand getNextCommand()
+        {
+            return nextCommand;
+        }
+    }
+}

Propchange: directory/network/trunk/src/java/org/apache/mina/handler/chain/CommandChain.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/trunk/src/java/org/apache/mina/handler/chain/package.html
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/handler/chain/package.html?rev=354263&view=auto
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/handler/chain/package.html (added)
+++ directory/network/trunk/src/java/org/apache/mina/handler/chain/package.html Mon Dec  5 19:03:10 2005
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body>
+A handler implementation that helps you implement hierarchical protocols
+using Chains of Responsibility pattern.
+</body>
+</html>

Propchange: directory/network/trunk/src/java/org/apache/mina/handler/chain/package.html
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Copied: directory/network/trunk/src/java/org/apache/mina/handler/demux/DemuxingIoHandler.java (from r354242, directory/network/trunk/src/java/org/apache/mina/handler/DemuxingIoHandler.java)
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/handler/demux/DemuxingIoHandler.java?p2=directory/network/trunk/src/java/org/apache/mina/handler/demux/DemuxingIoHandler.java&p1=directory/network/trunk/src/java/org/apache/mina/handler/DemuxingIoHandler.java&r1=354242&r2=354263&rev=354263&view=diff
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/handler/DemuxingIoHandler.java (original)
+++ directory/network/trunk/src/java/org/apache/mina/handler/demux/DemuxingIoHandler.java Mon Dec  5 19:03:10 2005
@@ -1,7 +1,7 @@
 /*
  * @(#) $Id$
  */
-package org.apache.mina.handler;
+package org.apache.mina.handler.demux;
 
 import java.util.Collections;
 import java.util.Hashtable;

Copied: directory/network/trunk/src/java/org/apache/mina/handler/demux/MessageHandler.java (from r354242, directory/network/trunk/src/java/org/apache/mina/handler/MessageHandler.java)
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/handler/demux/MessageHandler.java?p2=directory/network/trunk/src/java/org/apache/mina/handler/demux/MessageHandler.java&p1=directory/network/trunk/src/java/org/apache/mina/handler/MessageHandler.java&r1=354242&r2=354263&rev=354263&view=diff
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/handler/MessageHandler.java (original)
+++ directory/network/trunk/src/java/org/apache/mina/handler/demux/MessageHandler.java Mon Dec  5 19:03:10 2005
@@ -16,7 +16,7 @@
  *   limitations under the License.
  *
  */
-package org.apache.mina.handler;
+package org.apache.mina.handler.demux;
 
 import org.apache.mina.common.IoSession;
 

Copied: directory/network/trunk/src/java/org/apache/mina/handler/demux/UnknownMessageTypeException.java (from r354242, directory/network/trunk/src/java/org/apache/mina/handler/UnknownMessageTypeException.java)
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/handler/demux/UnknownMessageTypeException.java?p2=directory/network/trunk/src/java/org/apache/mina/handler/demux/UnknownMessageTypeException.java&p1=directory/network/trunk/src/java/org/apache/mina/handler/UnknownMessageTypeException.java&r1=354242&r2=354263&rev=354263&view=diff
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/handler/UnknownMessageTypeException.java (original)
+++ directory/network/trunk/src/java/org/apache/mina/handler/demux/UnknownMessageTypeException.java Mon Dec  5 19:03:10 2005
@@ -16,7 +16,7 @@
  *   limitations under the License.
  *
  */
-package org.apache.mina.handler;
+package org.apache.mina.handler.demux;
 
 
 /**

Added: directory/network/trunk/src/java/org/apache/mina/handler/demux/package.html
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/handler/demux/package.html?rev=354263&view=auto
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/handler/demux/package.html (added)
+++ directory/network/trunk/src/java/org/apache/mina/handler/demux/package.html Mon Dec  5 19:03:10 2005
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+</head>
+<body>
+A handler implementation that helps you implement complex protocols
+by splitting <tt>messageReceived</tt> handlers into multiple sub-handlers.
+</body>
+</html>

Propchange: directory/network/trunk/src/java/org/apache/mina/handler/demux/package.html
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Copied: directory/network/trunk/src/test/org/apache/mina/handler/demux/DemuxingIoHandlerTest.java (from r354242, directory/network/trunk/src/test/org/apache/mina/handler/DemuxingIoHandlerTest.java)
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/test/org/apache/mina/handler/demux/DemuxingIoHandlerTest.java?p2=directory/network/trunk/src/test/org/apache/mina/handler/demux/DemuxingIoHandlerTest.java&p1=directory/network/trunk/src/test/org/apache/mina/handler/DemuxingIoHandlerTest.java&r1=354242&r2=354263&rev=354263&view=diff
==============================================================================
--- directory/network/trunk/src/test/org/apache/mina/handler/DemuxingIoHandlerTest.java (original)
+++ directory/network/trunk/src/test/org/apache/mina/handler/demux/DemuxingIoHandlerTest.java Mon Dec  5 19:03:10 2005
@@ -16,15 +16,17 @@
  *   limitations under the License.
  *
  */
-package org.apache.mina.handler;
+package org.apache.mina.handler.demux;
 
 import junit.framework.TestCase;
 
 import org.apache.mina.common.IoSession;
+import org.apache.mina.handler.demux.DemuxingIoHandler;
+import org.apache.mina.handler.demux.MessageHandler;
 import org.easymock.MockControl;
 
 /**
- * Tests {@link org.apache.mina.handler.DemuxingIoHandler}.
+ * Tests {@link org.apache.mina.handler.demux.DemuxingIoHandler}.
  *
  * @author The Apache Directory Project (dev@directory.apache.org)
  * @version $Rev$, $Date$