cvs commit: spice/components/netserve/src/test/org/jcomponent/netserve/sockets/impl SocketTestCase.java
[email protected] Wed, 19 Nov 2003 18:25:07 -0600
| Newsgroups | gmane.comp.java.spice.cvs |
|---|---|
| Message-ID | <[email protected]> |
mauro 2003/11/19 18:25:07
Modified: components/netserve project.xml
components/netserve/xdocs index.xml
Added: components/netserve/src/java/org/codehaus/spice/netserve/sockets/impl
DefaultSocketFactory.java
DefaultServerSocketFactory.java
DefaultServerSocketFactory.xinfo
DefaultSocketFactory.xinfo
components/netserve/src/java/org/codehaus/spice/netserve/connection/impl
DNAAcceptorManager.java PicoAcceptorManager.java
AcceptorMonitor.java AcceptorManager-schema.xml
DefaultAcceptorManager.java
AbstractLoggingAcceptorMonitor.java
DNAAcceptorMonitor.java AcceptorConfig.java
NullAcceptorMonitor.java ConnectionAcceptor.java
components/netserve/src/test/org/codehaus/spice/netserve/connection/impl
AcceptorConfigTestCase.java
DNAAcceptorMonitorTestCase.java
DNAAcceptorManagerTestCase.java
PicoAcceptorManagerTestCase.java
ClosingSocketConnectionHandler.java
RecordingAcceptorMonitor.java
MockSocketConnectionHandler.java
ExceptOnCloseServerSocket.java
ExceptOnAcceptServerSocket.java
ConnectionAcceptorTestCase.java
BlockingServerSocket.java
DefaultAcceptorManagerTestCase.java
components/netserve/src/test/org/codehaus/spice/netserve/connection/handlers
RequestHandlerTestCase.java MockRequestHandler.java
ExceptingRequestHandler.java
DelegatingRequestHandlerTestCase.java
ManagedRequestHandlerTestCase.java
MockThreadPool.java
ThreadPerRequestHandlerTestCase.java
ExceptionOnCloseSocket.java
DelayingRequestHandler.java
MockManagedRequestHandler.java
MockThreadControl.java RequestManager.java
components/netserve/src/java/org/codehaus/spice/netserve/connection/handlers
ThreadPerRequestHandler.java
DelegatingRequestHandler.java
AbstractRequestHandler.java
ManagedRequestHandler.java
components/netserve/src/java/org/codehaus/spice/netserve/connection
RequestHandler.java SocketAcceptorManager.java
components/netserve/src/java/org/codehaus/spice/netserve/sockets
ServerSocketFactory.java SocketFactory.java
components/netserve/src/test/org/codehaus/spice/netserve/sockets/impl
SocketTestCase.java
Removed: components/netserve/src/test/org/jcomponent/netserve/connection/impl
DefaultAcceptorManagerTestCase.java
PicoAcceptorManagerTestCase.java
MockSocketConnectionHandler.java
RecordingAcceptorMonitor.java
ConnectionAcceptorTestCase.java
AcceptorConfigTestCase.java
ClosingSocketConnectionHandler.java
BlockingServerSocket.java
ExceptOnCloseServerSocket.java
DNAAcceptorMonitorTestCase.java
DNAAcceptorManagerTestCase.java
ExceptOnAcceptServerSocket.java
components/netserve/src/java/org/jcomponent/netserve/connection
RequestHandler.java SocketAcceptorManager.java
components/netserve/src/java/org/jcomponent/netserve/connection/impl
PicoAcceptorManager.java AcceptorManager-schema.xml
DNAAcceptorManager.java DNAAcceptorMonitor.java
ConnectionAcceptor.java AcceptorConfig.java
AbstractLoggingAcceptorMonitor.java
AcceptorMonitor.java NullAcceptorMonitor.java
DefaultAcceptorManager.java
components/netserve/src/test/org/jcomponent/netserve/connection/handlers
MockThreadPool.java
ManagedRequestHandlerTestCase.java
DelegatingRequestHandlerTestCase.java
MockRequestHandler.java DelayingRequestHandler.java
ThreadPerRequestHandlerTestCase.java
RequestHandlerTestCase.java
MockManagedRequestHandler.java
ExceptingRequestHandler.java MockThreadControl.java
RequestManager.java ExceptionOnCloseSocket.java
components/netserve/src/java/org/jcomponent/netserve/sockets
SocketFactory.java ServerSocketFactory.java
components/netserve/src/java/org/jcomponent/netserve/sockets/impl
DefaultServerSocketFactory.xinfo
DefaultSocketFactory.java
DefaultServerSocketFactory.java
DefaultSocketFactory.xinfo
components/netserve/src/java/org/jcomponent/netserve/connection/handlers
AbstractRequestHandler.java
DelegatingRequestHandler.java
ThreadPerRequestHandler.java
ManagedRequestHandler.java
components/netserve/src/test/org/jcomponent/netserve/sockets/impl
SocketTestCase.java
Log:
Renamed org.jcomponent -> org.codehaus.spice
Revision Changes Path
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/sockets/impl/DefaultSocketFactory.java
Index: DefaultSocketFactory.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.sockets.impl;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import org.codehaus.spice.netserve.sockets.SocketFactory;
/**
* A SocketFactory that creates vanilla sockets.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:04 $
* @dna.component
* @dna.service type="SocketFactory"
*/
public class DefaultSocketFactory
implements SocketFactory
{
/**
* Create a socket that connects to specified remote address.
*
* @param address the remote address
* @param port the remote port
* @return the socket connected to remote address
* @throws IOException if unable to create socket
*/
public Socket createSocket( final InetAddress address, final int port )
throws IOException
{
return new Socket( address, port );
}
/**
* Create a socket that connects to specified remote address and
* originates from specified local address.
*
* @param address the remote address
* @param port the remote port
* @param localAddress the local address
* @param localPort the local port
* @return the socket connected to remote address
* @throws IOException if unable to create socket
*/
public Socket createSocket( final InetAddress address,
final int port,
final InetAddress localAddress,
final int localPort )
throws IOException
{
return new Socket( address, port, localAddress, localPort );
}
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/sockets/impl/DefaultServerSocketFactory.java
Index: DefaultServerSocketFactory.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.sockets.impl;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import org.codehaus.spice.netserve.sockets.ServerSocketFactory;
/**
* Factory implementation for vanilla TCP sockets.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:04 $
* @dna.component
* @dna.service type="ServerSocketFactory"
*/
public class DefaultServerSocketFactory
implements ServerSocketFactory
{
/**
* Creates a socket on specified port.
*
* @param port the port (0 indicates any available port)
* @return the created ServerSocket
* @throws IOException if unable to create socket
*/
public ServerSocket createServerSocket( final int port )
throws IOException
{
return new ServerSocket( port );
}
/**
* Creates a socket on specified port with a specified backlog.
*
* @param port the port (0 indicates any available port)
* @param backlog the backlog
* @return the created ServerSocket
* @throws IOException if unable to create socket
*/
public ServerSocket createServerSocket( int port, int backlog )
throws IOException
{
return new ServerSocket( port, backlog );
}
/**
* Creates a socket on a particular network interface on specified port
* with a specified backlog.
*
* @param port the port (0 indicates any available port)
* @param backlog the backlog
* @param address the network interface to bind to.
* @return the created ServerSocket
* @throws IOException if unable to create socket
*/
public ServerSocket createServerSocket( int port, int backlog, InetAddress address )
throws IOException
{
return new ServerSocket( port, backlog, address );
}
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/sockets/impl/DefaultServerSocketFactory.xinfo
Index: DefaultServerSocketFactory.xinfo
===================================================================
<?xml version="1.0"?>
<!DOCTYPE blockinfo PUBLIC "-//PHOENIX/Block Info DTD Version 1.0//EN"
"http://jakarta.apache.org/avalon/dtds/phoenix/blockinfo_1_0.dtd">
<blockinfo>
<block>
<version>1.0</version>
</block>
<services>
<service name="org.codehaus.spice.netserve.sockets.ServerSocketFactory"/>
</services>
</blockinfo>
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/sockets/impl/DefaultSocketFactory.xinfo
Index: DefaultSocketFactory.xinfo
===================================================================
<?xml version="1.0"?>
<!DOCTYPE blockinfo PUBLIC "-//PHOENIX/Block Info DTD Version 1.0//EN"
"http://jakarta.apache.org/avalon/dtds/phoenix/blockinfo_1_0.dtd">
<blockinfo>
<block>
<version>1.0</version>
</block>
<services>
<service name="org.codehaus.spice.netserve.sockets.SocketFactory"/>
</services>
</blockinfo>
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/impl/DNAAcceptorManager.java
Index: DNAAcceptorManager.java
===================================================================
package org.codehaus.spice.netserve.connection.impl;
import org.jcontainer.dna.Configuration;
import org.jcontainer.dna.ConfigurationException;
import org.jcontainer.dna.Active;
import org.jcontainer.dna.Configurable;
import org.jcontainer.dna.LogEnabled;
import org.jcontainer.dna.Logger;
import org.codehaus.spice.netserve.connection.impl.DefaultAcceptorManager;
/**
* A DNA compliant implementation of AcceptorManager.
*
* <p>The component takes a single configuration parameter;
* "shutdownTimeout". This specifies the amount of time to wait
* while waiting for connections to shutdown gracefully. A
* sample configuration follows;</p>
* <pre>
* <!-- wait 200ms for connections to gracefully shutdown -->
* <shutdownTimeout>200</shutdownTimeout>
* </pre>
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
* @dna.component
* @dna.service type="org.codehaus.spice.netserve.connection.SocketAcceptorManager"
* @see org.codehaus.spice.netserve.connection.impl.DefaultAcceptorManager
*/
public class DNAAcceptorManager
extends DefaultAcceptorManager
implements LogEnabled, Configurable, Active
{
/**
* @dna.logger
*/
public void enableLogging( final Logger logger )
{
setMonitor( new DNAAcceptorMonitor( logger ) );
}
/**
* @dna.configuration type="http://relaxng.org/ns/structure/1.0"
* location="AcceptorManager-schema.xml"
*/
public void configure( final Configuration configuration )
throws ConfigurationException
{
setShutdownTimeout( configuration.getChild( "shutdownTimeout" ).getValueAsInteger( 0 ) );
}
/**
* Nothing to do to initial AcceptorManager.
*/
public void initialize()
throws Exception
{
}
/**
* Shutdown all connections.
*/
public void dispose()
{
shutdownAcceptors();
}
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/impl/PicoAcceptorManager.java
Index: PicoAcceptorManager.java
===================================================================
package org.codehaus.spice.netserve.connection.impl;
import org.codehaus.spice.netserve.connection.impl.AcceptorMonitor;
import org.codehaus.spice.netserve.connection.impl.DefaultAcceptorManager;
/**
* A Pico compliant implementation of AcceptorManager.
*/
public class PicoAcceptorManager
extends DefaultAcceptorManager
{
/**
* Create instance with default timeout and monitor.
*/
public PicoAcceptorManager()
{
}
/**
* Create instance with default monitor.
*
* @param shutdownTimeout the timeout
*/
public PicoAcceptorManager( final int shutdownTimeout )
{
setShutdownTimeout( shutdownTimeout );
}
/**
* Create instance with default timeout.
*
* @param monitor the monitor
*/
public PicoAcceptorManager( final AcceptorMonitor monitor )
{
setMonitor( monitor );
}
/**
* Create instance specifying both timeout and monitor.
*
* @param shutdownTimeout the timeout
* @param monitor the monitor
*/
public PicoAcceptorManager( final int shutdownTimeout,
final AcceptorMonitor monitor )
{
setShutdownTimeout( shutdownTimeout );
setMonitor( monitor );
}
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/impl/AcceptorMonitor.java
Index: AcceptorMonitor.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.impl;
import java.io.IOException;
import java.net.ServerSocket;
/**
* Monitor used to monitor events in the AcceptorManager.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
public interface AcceptorMonitor
{
/**
* Aceptor create with name for specified socket.
*
* @param name the acceptor name
* @param serverSocket the socket
*/
void acceptorCreated( String name, ServerSocket serverSocket );
/**
* About to close down acceptor and stop listening for
* connections.
*
* @param name the acceptor name
* @param serverSocket the socket
*/
void acceptorClosing( String name, ServerSocket serverSocket );
/**
* Listening for connection attempts in acceptor.
*
* @param name the acceptor name
* @param serverSocket the socket
*/
void serverSocketListening( String name, ServerSocket serverSocket );
/**
* There was an error accepting client connections.
*
* @param name the name of acceptor
* @param ioe the exception
*/
void errorAcceptingConnection( String name, IOException ioe );
/**
* There was an error closing server socket.
*
* @param name the name of acceptor
* @param ioe the exception
*/
void errorClosingServerSocket( String name, IOException ioe );
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/impl/AcceptorManager-schema.xml
Index: AcceptorManager-schema.xml
===================================================================
<?xml version="1.0"?>
<element
name="root"
xmlns="http://relaxng.org/ns/structure/1.0"
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<interleave>
<element name="shutdownTimeout"><data type="integer"/></element>
</interleave>
</element>
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/impl/DefaultAcceptorManager.java
Index: DefaultAcceptorManager.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.impl;
import java.net.ServerSocket;
import java.util.Hashtable;
import java.util.Map;
import org.codehaus.spice.netserve.connection.RequestHandler;
import org.codehaus.spice.netserve.connection.SocketAcceptorManager;
import org.codehaus.spice.netserve.connection.impl.AcceptorConfig;
import org.codehaus.spice.netserve.connection.impl.AcceptorMonitor;
import org.codehaus.spice.netserve.connection.impl.ConnectionAcceptor;
/**
* Default implementation of SocketAcceptorManager that uses
* a thread per acceptor approach.
*
* <p>Note that on some OS/JVM combinations <tt>soTimeout</tt> must
* be set to non-0 value or else the ServerSocket will never get out
* of accept() system call and we wont be able to shutdown the server
* socket properly. However it can introduce performance problems if
* constantly timing out. </p>
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @author <a href="mailto:mauro.talevi at aquilonia.org">Mauro Talevi</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
public class DefaultAcceptorManager
implements SocketAcceptorManager
{
/**
* The map of name->acceptor.
*/
private final Map m_acceptors = new Hashtable();
/**
* The monitor that receives notifications of Connection events
*/
private AcceptorMonitor m_monitor = NullAcceptorMonitor.MONITOR;
/**
* Value that we are to set SO_TIMEOUT to if the user
* has not already set the timeout. Defaults to 1000 (1s timeout).
*/
private int m_soTimeout = 1000;
/**
* Set to the number of milliseconds that we will wait
* for a connection to shutdown gracefully. Defaults to 0
* which indicates indefinite wait.
*/
private int m_shutdownTimeout;
/**
* Set the AcceptorMonitor that receives events when changes occur.
*
* @param monitor the AcceptorMonitor that receives events when
* changes occur.
*/
public void setMonitor( final AcceptorMonitor monitor )
{
m_monitor = monitor;
}
/**
* Set the value that we are to set SO_TIMEOUT to if the user
* has not already set the timeout. Defaults to 1000 (1s timeout).
*
* @param soTimeout the timeout value
*/
public void setSoTimeout( final int soTimeout )
{
m_soTimeout = soTimeout;
}
/**
* Set timeout for shutting down handlers.
* The timeout defaults to 0 which means wait indefinetly.
*
* @param shutdownTimeout the timeout
*/
public void setShutdownTimeout( final int shutdownTimeout )
{
m_shutdownTimeout = shutdownTimeout;
}
/**
* Return the shutdownTimeout.
*
* @return the shutdownTimeout
*/
protected int getShutdownTimeout()
{
return m_shutdownTimeout;
}
/**
* Dispose the ConnectionManager which involves shutting down all
* the connected acceptors.
*/
public void shutdownAcceptors()
{
final String[] names;
synchronized( m_acceptors )
{
names = (String[])m_acceptors.keySet().toArray( new String[ 0 ] );
}
for( int i = 0; i < names.length; i++ )
{
disconnect( names[ i ] );
}
}
/**
* Start accepting connections from a socket and passing connections
* to specified handler.
*
* @param name the name of connection. This serves as a key used to
* shutdown acceptor.
* @param socket the ServerSocket from which connections are accepted
* @throws java.lang.Exception if unable to initiate connection management. This could
* be due to the key already being used for another acceptor,
* the serversocket being closed, the handler being null etc.
*/
public void connect( final String name,
final ServerSocket socket,
final RequestHandler handler )
throws Exception
{
if( null == name )
{
throw new NullPointerException( "name" );
}
if( null == socket )
{
throw new NullPointerException( "socket" );
}
if( null == handler )
{
throw new NullPointerException( "handler" );
}
if( 0 == socket.getSoTimeout() )
{
socket.setSoTimeout( m_soTimeout );
}
final ConnectionAcceptor acceptor;
synchronized( m_acceptors )
{
if( isConnected( name ) )
{
final String message =
"Connection already exists with name " + name;
throw new IllegalArgumentException( message );
}
final AcceptorConfig config = new AcceptorConfig( name, socket, handler );
acceptor = new ConnectionAcceptor( config, getMonitor() );
m_acceptors.put( name, acceptor );
}
final Thread thread =
new Thread( acceptor, "Acceptor[" + name + "]" );
thread.start();
while( !acceptor.hasStarted() )
{
Thread.sleep( 5 );
}
}
/**
* Return true if acceptor with specified name exists.
*
* @param name the name
* @return true if acceptor with specified name exists.
*/
public boolean isConnected( final String name )
{
return m_acceptors.containsKey( name );
}
/**
* This shuts down the acceptor and the associated ServerSocket.
*
* @param name the name of connection
* @throws java.lang.IllegalArgumentException if no connection with specified name
*/
public void disconnect( final String name )
{
final ConnectionAcceptor acceptor =
(ConnectionAcceptor)m_acceptors.remove( name );
if( null == acceptor )
{
final String message = "No connection with name " + name;
throw new IllegalArgumentException( message );
}
acceptor.close( getShutdownTimeout() );
}
/**
* Return the monitor used by manager.
*
* @return the monitor used by manager.
*/
protected AcceptorMonitor getMonitor()
{
return m_monitor;
}
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/impl/AbstractLoggingAcceptorMonitor.java
Index: AbstractLoggingAcceptorMonitor.java
===================================================================
package org.codehaus.spice.netserve.connection.impl;
import java.io.IOException;
import java.net.ServerSocket;
/**
* An abstract monitor that writes out messages
* for acceptor events. Need to subclass and implement
* methods to write out log messages.
*/
public abstract class AbstractLoggingAcceptorMonitor
implements AcceptorMonitor
{
/**
* @see AcceptorMonitor#acceptorCreated
*/
public void acceptorCreated( final String name,
final ServerSocket serverSocket )
{
final String message =
"Creating Acceptor " + name + " on " +
serverSocket.getInetAddress().getHostAddress() + ":" +
serverSocket.getLocalPort() + ".";
info( message );
}
/**
* @see AcceptorMonitor#acceptorClosing
*/
public void acceptorClosing( final String name,
final ServerSocket serverSocket )
{
final String message = "Closing Acceptor " + name + ".";
info( message );
}
/**
* @see AcceptorMonitor#serverSocketListening
*/
public void serverSocketListening( final String name,
final ServerSocket serverSocket )
{
if ( isDebugEnabled() )
{
final String message =
"About to call accept() on ServerSocket '" + name + "'.";
debug( message );
}
}
/**
* @see AcceptorMonitor#errorAcceptingConnection
*/
public void errorAcceptingConnection( final String name,
final IOException ioe )
{
warn( "Error Accepting connection on " + name, ioe );
}
/**
* @see AcceptorMonitor#errorClosingServerSocket
*/
public void errorClosingServerSocket( final String name,
final IOException ioe )
{
warn( "Error Closing Server Socket " + name, ioe );
}
/**
* Return true if debug logging enabled.
*
* @return true if debug logging enabled.
*/
protected abstract boolean isDebugEnabled();
/**
* Write out debug message.
*
* @param message the message
*/
protected abstract void debug( String message );
/**
* Write out info message.
*
* @param message the message
*/
protected abstract void info( String message );
/**
* Write out warn message.
*
* @param message the message
* @param e the warnings cause
*/
protected abstract void warn( String message, Exception e );
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/impl/DNAAcceptorMonitor.java
Index: DNAAcceptorMonitor.java
===================================================================
package org.codehaus.spice.netserve.connection.impl;
import org.jcontainer.dna.Logger;
import org.codehaus.spice.netserve.connection.impl.AbstractLoggingAcceptorMonitor;
/**
* AcceptorMonitor that writes out messages to DNA Logger.
*/
public class DNAAcceptorMonitor
extends AbstractLoggingAcceptorMonitor
{
/**
* The associated DNA Logger.
*/
private final Logger m_logger;
/**
* Create AcceptorMonitor that writes to DNA Logger.
*
* @param logger the logger
*/
public DNAAcceptorMonitor( final Logger logger )
{
if ( null == logger )
{
throw new NullPointerException( "logger" );
}
m_logger = logger;
}
/**
* @see AbstractLoggingAcceptorMonitor#isDebugEnabled
*/
protected boolean isDebugEnabled()
{
return getLogger().isDebugEnabled();
}
/**
* @see AbstractLoggingAcceptorMonitor#debug
*/
protected void debug( final String message )
{
getLogger().debug( message );
}
/**
* @see AbstractLoggingAcceptorMonitor#info
*/
protected void info( final String message )
{
getLogger().info( message );
}
/**
* @see AbstractLoggingAcceptorMonitor#warn
*/
protected void warn( final String message,
final Exception e )
{
getLogger().warn( message, e );
}
/**
* Return the logger.
*
* @return the logger
*/
protected Logger getLogger()
{
return m_logger;
}
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/impl/AcceptorConfig.java
Index: AcceptorConfig.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.impl;
import java.net.ServerSocket;
import org.codehaus.spice.netserve.connection.RequestHandler;
/**
* A utility class that contains acceptor configuration.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class AcceptorConfig
{
/**
* The name of the connection.
*/
private final String m_name;
/**
* The ServerSocket that we are accepting connections from.
*/
private final ServerSocket m_serverSocket;
/**
* The ConnectionHandlerManager that we create ConnectionHandlers from.
*/
private final RequestHandler m_handler;
/**
* Create the acceptor.
*
* @param name the name that connection was registered using
* @param serverSocket the ServerSocket that used to accept connections
* @param handler the handler for new connections
*/
AcceptorConfig( final String name,
final ServerSocket serverSocket,
final RequestHandler handler )
{
if( null == name )
{
throw new NullPointerException( "name" );
}
if( null == serverSocket )
{
throw new NullPointerException( "serverSocket" );
}
if( null == handler )
{
throw new NullPointerException( "handler" );
}
m_name = name;
m_serverSocket = serverSocket;
m_handler = handler;
}
/**
* Return the name acceptor registered under.
*
* @return the name acceptor registered under.
*/
String getName()
{
return m_name;
}
/**
* Return the socket that connections accepted from.
*
* @return the socket that connections accepted from.
*/
ServerSocket getServerSocket()
{
return m_serverSocket;
}
/**
* Return the handler the connections are handled by.
*
* @return the handler the connections are handled by.
*/
RequestHandler getHandler()
{
return m_handler;
}
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/impl/NullAcceptorMonitor.java
Index: NullAcceptorMonitor.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.impl;
import java.io.IOException;
import java.net.ServerSocket;
import org.codehaus.spice.netserve.connection.impl.AcceptorMonitor;
/**
* A noop monitor.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
public class NullAcceptorMonitor
implements AcceptorMonitor
{
/**
* Add constant for instance of Null Monitor.
*/
public static final NullAcceptorMonitor MONITOR = new NullAcceptorMonitor();
/**
* @see AcceptorMonitor#acceptorCreated
*/
public void acceptorCreated( final String name,
final ServerSocket serverSocket )
{
}
/**
* @see AcceptorMonitor#acceptorClosing
*/
public void acceptorClosing( final String name,
final ServerSocket serverSocket )
{
}
/**
* @see AcceptorMonitor#serverSocketListening
*/
public void serverSocketListening( final String name,
final ServerSocket serverSocket )
{
}
/**
* @see AcceptorMonitor#errorAcceptingConnection
*/
public void errorAcceptingConnection( final String name,
final IOException ioe )
{
}
/**
* @see AcceptorMonitor#errorClosingServerSocket
*/
public void errorClosingServerSocket( final String name,
final IOException ioe )
{
}
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/impl/ConnectionAcceptor.java
Index: ConnectionAcceptor.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.impl;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.Socket;
import org.codehaus.spice.netserve.connection.impl.AcceptorConfig;
import org.codehaus.spice.netserve.connection.impl.AcceptorMonitor;
/**
* A helper class that manages acceptor for a single ServerSocket.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class ConnectionAcceptor
implements Runnable
{
/**
* The configuration for acceptor.
*/
private final AcceptorConfig m_config;
/**
* The AcceptorMonitor for event notification.
*/
private final AcceptorMonitor m_monitor;
private boolean m_started;
private boolean m_active;
/**
* The thread in which the main accept loop is running.
* Setup at start of thread and set to null to shutdown
* acceptor.
*/
private Thread m_thread;
/**
* Create the acceptor.
*
* @param config the config for acceptor
* @param monitor the monitor
*/
ConnectionAcceptor( final AcceptorConfig config,
final AcceptorMonitor monitor )
{
if( null == config )
{
throw new NullPointerException( "config" );
}
if( null == monitor )
{
throw new NullPointerException( "monitor" );
}
m_config = config;
m_monitor = monitor;
m_monitor.acceptorCreated( m_config.getName(),
m_config.getServerSocket() );
}
/**
* Return true if acceptor has started.
*
* @return true if acceptor has started.
*/
synchronized boolean hasStarted()
{
return m_started;
}
/**
* Shutdown the acceptor.
*/
void close( final long timeout )
{
synchronized( this )
{
m_active = false;
m_monitor.acceptorClosing( m_config.getName(),
m_config.getServerSocket() );
m_thread.interrupt();
try
{
wait( timeout );
}
catch( InterruptedException e )
{
//ignore
}
}
}
/**
* The main accept & handle loop for acceptor.
*/
public void run()
{
//Setup thread to indicate that we are currently running
synchronized( this )
{
m_started = true;
m_active = true;
m_thread = Thread.currentThread();
}
while( isRunning() )
{
m_monitor.serverSocketListening( m_config.getName(),
m_config.getServerSocket() );
try
{
final Socket socket = m_config.getServerSocket().accept();
if( isRunning() )
{
m_config.getHandler().handleConnection( socket );
}
else
{
try
{
socket.close();
}
catch( final Exception e )
{
//Ignore
}
}
}
catch( final InterruptedIOException iioe )
{
//Consume exception
}
catch( final IOException ioe )
{
m_monitor.errorAcceptingConnection( m_config.getName(), ioe );
}
}
shutdownServerSocket();
synchronized( this )
{
m_thread = null;
notifyAll();
}
}
/**
* Utility method to shutdown serverSocket.
*/
void shutdownServerSocket()
{
try
{
m_config.getServerSocket().close();
}
catch( final IOException ioe )
{
m_monitor.errorClosingServerSocket( m_config.getName(), ioe );
}
}
/**
* Return true if the acceptor is currently running.
*
* @return true if the acceptor is currently running.
*/
synchronized boolean isRunning()
{
return m_active;
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/impl/AcceptorConfigTestCase.java
Index: AcceptorConfigTestCase.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.impl;
import java.net.ServerSocket;
import junit.framework.TestCase;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
public class AcceptorConfigTestCase
extends TestCase
{
public void testCreation()
throws Exception
{
final String name = "name";
final ServerSocket serverSocket = new ServerSocket();
final MockSocketConnectionHandler handler = new MockSocketConnectionHandler();
final AcceptorConfig config =
new AcceptorConfig( name, serverSocket, handler );
assertEquals( "name", name, config.getName() );
assertEquals( "serverSocket", serverSocket, config.getServerSocket() );
assertEquals( "handler", handler, config.getHandler() );
}
public void testNullNameInCtor()
throws Exception
{
try
{
new AcceptorConfig( null,
new ServerSocket(),
new MockSocketConnectionHandler() );
}
catch ( final NullPointerException npe )
{
assertEquals( "npe.message", "name", npe.getMessage() );
return;
}
fail( "Expected to fail due to NPE for name" );
}
public void testNullServerSocketInCtor()
throws Exception
{
try
{
new AcceptorConfig( "name",
null,
new MockSocketConnectionHandler() );
}
catch ( final NullPointerException npe )
{
assertEquals( "npe.message", "serverSocket", npe.getMessage() );
return;
}
fail( "Expected to fail due to NPE for serverSocket" );
}
public void testNullHandlerInCtor()
throws Exception
{
try
{
new AcceptorConfig( "name",
new ServerSocket(),
null );
}
catch ( NullPointerException npe )
{
assertEquals( "npe.message", "handler", npe.getMessage() );
return;
}
fail( "Expected to fail due to NPE for handler" );
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/impl/DNAAcceptorMonitorTestCase.java
Index: DNAAcceptorMonitorTestCase.java
===================================================================
package org.codehaus.spice.netserve.connection.impl;
import java.net.ServerSocket;
import java.io.IOException;
import com.mockobjects.dynamic.C;
import com.mockobjects.dynamic.Mock;
import junit.framework.TestCase;
import org.jcontainer.dna.Logger;
public class DNAAcceptorMonitorTestCase
extends TestCase
{
public void testDNAAcceptorMonitor()
throws Exception
{
final Mock mockLogger = new Mock( Logger.class );
final String name = "MyName";
final ServerSocket serverSocket = new ServerSocket( 2023 );
final IOException ioe = new IOException();
final String acceptorCreatedMessage =
"Creating Acceptor " + name + " on " +
serverSocket.getInetAddress().getHostAddress() + ":" +
serverSocket.getLocalPort() + ".";
final String acceptorClosingMessage =
"Closing Acceptor " + name + ".";
final String serverSocketListening =
"About to call accept() on ServerSocket '" + name + "'.";
final String errorAcceptingConnectionMessage =
"Error Accepting connection on " + name;
final String errorClosingServerSocketMessage =
"Error Closing Server Socket " + name;
mockLogger.expect( "info", C.args( C.eq( acceptorCreatedMessage ) ) );
mockLogger.expect( "info", C.args( C.eq( acceptorClosingMessage ) ) );
mockLogger.expectAndReturn( "isDebugEnabled", C.NO_ARGS, false );
mockLogger.expectAndReturn( "isDebugEnabled", C.NO_ARGS, true );
mockLogger.expect( "debug", C.args( C.eq( serverSocketListening ) ) );
mockLogger.expect( "warn", C.args( C.eq( errorAcceptingConnectionMessage ), C.eq( ioe ) ) );
mockLogger.expect( "warn", C.args( C.eq( errorClosingServerSocketMessage ), C.eq( ioe ) ) );
final Logger logger = (Logger) mockLogger.proxy();
final AcceptorMonitor monitor = new DNAAcceptorMonitor( logger );
monitor.acceptorCreated( name, serverSocket );
monitor.acceptorClosing( name, serverSocket );
monitor.serverSocketListening( name, serverSocket );
monitor.serverSocketListening( name, serverSocket );
monitor.errorAcceptingConnection( name, ioe );
monitor.errorClosingServerSocket( name, ioe );
mockLogger.verify();
}
public void testDNAAcceptorMonitorPassedNullIntoCtor()
throws Exception
{
try
{
new DNAAcceptorMonitor( null );
}
catch ( final NullPointerException npe )
{
assertEquals( "npe.getMessage()", "logger", npe.getMessage() );
return;
}
fail( "Expected to fail due to npe in ctor" );
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/impl/DNAAcceptorManagerTestCase.java
Index: DNAAcceptorManagerTestCase.java
===================================================================
package org.codehaus.spice.netserve.connection.impl;
import junit.framework.TestCase;
import org.jcontainer.dna.impl.DefaultConfiguration;
import org.jcontainer.dna.impl.ConsoleLogger;
public class DNAAcceptorManagerTestCase
extends TestCase
{
public void testDNAAcceptorManager()
throws Exception
{
final DNAAcceptorManager manager = new DNAAcceptorManager();
final DefaultConfiguration root = new DefaultConfiguration( "root", "", "" );
final DefaultConfiguration configuration = new DefaultConfiguration( "shutdownTimeout", "", "" );
configuration.setValue( "22" );
root.addChild( configuration );
final ConsoleLogger logger = new ConsoleLogger( ConsoleLogger.LEVEL_NONE );
manager.enableLogging( logger );
final AcceptorMonitor monitor = manager.getMonitor();
assertTrue( "getMonitor() instanceof DNAAcceptorMonitor", monitor instanceof DNAAcceptorMonitor );
final DNAAcceptorMonitor dnaMonitor = (DNAAcceptorMonitor) monitor;
assertEquals( "logger", logger, dnaMonitor.getLogger() );
manager.configure( root );
assertEquals( "getShutdownTimeout()", 22, manager.getShutdownTimeout() );
manager.initialize();
manager.dispose();
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/impl/PicoAcceptorManagerTestCase.java
Index: PicoAcceptorManagerTestCase.java
===================================================================
package org.codehaus.spice.netserve.connection.impl;
import junit.framework.TestCase;
public class PicoAcceptorManagerTestCase
extends TestCase
{
public void testPicoAcceptorManagerWithMonitorAndShutdownSet()
throws Exception
{
final NullAcceptorMonitor monitor = new NullAcceptorMonitor();
final PicoAcceptorManager manager = new PicoAcceptorManager( 22, monitor );
assertEquals( "shutdownTimeout", 22, manager.getShutdownTimeout() );
assertEquals( "monitor", monitor, manager.getMonitor() );
}
public void testPicoAcceptorManagerWithShutdownSet()
throws Exception
{
final PicoAcceptorManager manager = new PicoAcceptorManager( 22 );
assertEquals( "shutdownTimeout", 22, manager.getShutdownTimeout() );
assertEquals( "monitor", NullAcceptorMonitor.MONITOR, manager.getMonitor() );
}
public void testPicoAcceptorManagerWithMonitorSet()
throws Exception
{
final NullAcceptorMonitor monitor = new NullAcceptorMonitor();
final PicoAcceptorManager manager = new PicoAcceptorManager( monitor );
assertEquals( "shutdownTimeout", 0, manager.getShutdownTimeout() );
assertEquals( "monitor", monitor, manager.getMonitor() );
}
public void testPicoAcceptorManagerWithDefaultCtor()
throws Exception
{
final PicoAcceptorManager manager = new PicoAcceptorManager();
assertEquals( "shutdownTimeout", 0, manager.getShutdownTimeout() );
assertEquals( "monitor", NullAcceptorMonitor.MONITOR, manager.getMonitor() );
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/impl/ClosingSocketConnectionHandler.java
Index: ClosingSocketConnectionHandler.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.impl;
import java.io.OutputStream;
import java.net.Socket;
import org.codehaus.spice.netserve.connection.handlers.AbstractRequestHandler;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class ClosingSocketConnectionHandler
extends AbstractRequestHandler
{
static final String MESSAGE = "Bye!";
protected void doPerformRequest( Socket socket )
throws Exception
{
final OutputStream outputStream = socket.getOutputStream();
outputStream.write( MESSAGE.getBytes() );
outputStream.flush();
outputStream.close();
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/impl/RecordingAcceptorMonitor.java
Index: RecordingAcceptorMonitor.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.impl;
import java.io.IOException;
import java.net.ServerSocket;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class RecordingAcceptorMonitor
extends NullAcceptorMonitor
{
private IOException m_errorClosingServerSocket;
private IOException m_errorAcceptingConnection;
private int m_listenCount;
public void serverSocketListening( String name, ServerSocket serverSocket )
{
m_listenCount++;
super.serverSocketListening( name, serverSocket );
}
public void errorAcceptingConnection( String name, IOException ioe )
{
m_errorAcceptingConnection = ioe;
super.errorAcceptingConnection( name, ioe );
}
public void errorClosingServerSocket( String name, IOException ioe )
{
m_errorClosingServerSocket = ioe;
super.errorClosingServerSocket( name, ioe );
}
IOException getErrorClosingServerSocket()
{
return m_errorClosingServerSocket;
}
IOException getErrorAcceptingConnection()
{
return m_errorAcceptingConnection;
}
int getListenCount()
{
return m_listenCount;
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/impl/MockSocketConnectionHandler.java
Index: MockSocketConnectionHandler.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.impl;
import java.net.Socket;
import org.codehaus.spice.netserve.connection.handlers.AbstractRequestHandler;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class MockSocketConnectionHandler
extends AbstractRequestHandler
{
private Socket m_socket;
protected void doPerformRequest( Socket socket )
throws Exception
{
m_socket = socket;
}
Socket getSocket()
{
return m_socket;
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/impl/ExceptOnCloseServerSocket.java
Index: ExceptOnCloseServerSocket.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.impl;
import java.io.IOException;
import java.net.ServerSocket;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class ExceptOnCloseServerSocket
extends ServerSocket
{
static final IOException EXCEPTION = new IOException( "No Close - ha ha!" );
public ExceptOnCloseServerSocket()
throws IOException
{
}
public void close() throws IOException
{
throw EXCEPTION;
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/impl/ExceptOnAcceptServerSocket.java
Index: ExceptOnAcceptServerSocket.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.impl;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class ExceptOnAcceptServerSocket
extends ServerSocket
{
static final IOException ERROR_EXCEPTION = new IOException( "No Accept - ha ha!" );
static final IOException INTERRUPTED_EXCEPTION = new InterruptedIOException( "No Interuptions!" );
private boolean m_interupt;
public ExceptOnAcceptServerSocket( final boolean interupt )
throws IOException
{
m_interupt = interupt;
}
public Socket accept() throws IOException
{
if ( m_interupt )
{
throw INTERRUPTED_EXCEPTION;
}
else
{
throw ERROR_EXCEPTION;
}
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/impl/ConnectionAcceptorTestCase.java
Index: ConnectionAcceptorTestCase.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.impl;
import java.net.ServerSocket;
import junit.framework.TestCase;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
public class ConnectionAcceptorTestCase
extends TestCase
{
public void testNullConfigInCtor()
throws Exception
{
try
{
new ConnectionAcceptor( null,
new NullAcceptorMonitor() );
}
catch ( final NullPointerException npe )
{
assertEquals( "npe.message", "config", npe.getMessage() );
return;
}
fail( "Expected to fail due to NPE for config" );
}
public void testNullMonitorInCtor()
throws Exception
{
try
{
new ConnectionAcceptor( new AcceptorConfig( "name",
new ServerSocket(),
new MockSocketConnectionHandler() ),
null );
}
catch ( NullPointerException npe )
{
assertEquals( "npe.message", "monitor", npe.getMessage() );
return;
}
fail( "Expected to fail due to NPE for monitor" );
}
public void testShutdownServerSocketCausesError()
throws Exception
{
final RecordingAcceptorMonitor monitor = new RecordingAcceptorMonitor();
final ConnectionAcceptor acceptor =
new ConnectionAcceptor( new AcceptorConfig( "name",
new ExceptOnCloseServerSocket(),
new MockSocketConnectionHandler() ),
monitor );
assertEquals( "errorClosingServerSocket pre-shutdownServerSocket()",
null,
monitor.getErrorClosingServerSocket() );
acceptor.shutdownServerSocket();
assertEquals( "errorClosingServerSocket post-shutdownServerSocket()",
ExceptOnCloseServerSocket.EXCEPTION,
monitor.getErrorClosingServerSocket() );
}
public void testShutdownServerSocket()
throws Exception
{
final RecordingAcceptorMonitor monitor = new RecordingAcceptorMonitor();
final ConnectionAcceptor acceptor =
new ConnectionAcceptor( new AcceptorConfig( "name",
new ServerSocket(),
new MockSocketConnectionHandler() ),
monitor );
assertEquals( "errorClosingServerSocket pre-shutdownServerSocket()",
null,
monitor.getErrorClosingServerSocket() );
acceptor.shutdownServerSocket();
assertEquals( "errorClosingServerSocket post-shutdownServerSocket()",
null,
monitor.getErrorClosingServerSocket() );
}
public void testExceptionOnAccept()
throws Exception
{
final RecordingAcceptorMonitor monitor = new RecordingAcceptorMonitor();
final ConnectionAcceptor acceptor =
new ConnectionAcceptor( new AcceptorConfig( "name",
new ExceptOnAcceptServerSocket( false ),
new MockSocketConnectionHandler() ),
monitor );
assertEquals( "getErrorAcceptingConnection pre-shutdownServerSocket()",
null,
monitor.getErrorAcceptingConnection() );
final Thread thread = startAcceptor( acceptor );
waitUntilStarted( acceptor );
waitUntilListening( monitor );
assertEquals( "getErrorAcceptingConnection post-shutdownServerSocket()",
ExceptOnAcceptServerSocket.ERROR_EXCEPTION,
monitor.getErrorAcceptingConnection() );
acceptor.close( 0 );
thread.join();
}
public void testInteruptOnAccept()
throws Exception
{
final RecordingAcceptorMonitor monitor = new RecordingAcceptorMonitor();
final ConnectionAcceptor acceptor =
new ConnectionAcceptor( new AcceptorConfig( "name",
new ExceptOnAcceptServerSocket( true ),
new MockSocketConnectionHandler() ),
monitor );
final Thread thread = startAcceptor( acceptor );
waitUntilStarted( acceptor );
waitUntilListening( monitor );
try
{
Thread.sleep( 30 );
}
catch ( final InterruptedException e )
{
}
assertTrue( "1 < monitor.getListenCount", 1 < monitor.getListenCount() );
acceptor.close( 0 );
thread.join();
}
public void _testNormalHandlerAccept()
throws Exception
{
final RecordingAcceptorMonitor monitor = new RecordingAcceptorMonitor();
final BlockingServerSocket serverSocket = new BlockingServerSocket();
final MockSocketConnectionHandler handler = new MockSocketConnectionHandler();
final ConnectionAcceptor acceptor =
new ConnectionAcceptor( new AcceptorConfig( "name",
serverSocket,
handler ),
monitor );
final Thread thread = startAcceptor( acceptor );
waitUntilStarted( acceptor );
waitUntilListening( monitor );
serverSocket.unlock();
try
{
Thread.sleep( 30 );
}
catch ( final InterruptedException e )
{
}
assertEquals( "handler.getSocket()",
BlockingServerSocket.SOCKET,
handler.getSocket() );
acceptor.close( 50 );
serverSocket.unlock();
thread.join();
}
public void testAcceptAfterClose()
throws Exception
{
final RecordingAcceptorMonitor monitor = new RecordingAcceptorMonitor();
final BlockingServerSocket serverSocket = new BlockingServerSocket();
final MockSocketConnectionHandler handler = new MockSocketConnectionHandler();
final ConnectionAcceptor acceptor =
new ConnectionAcceptor( new AcceptorConfig( "name",
serverSocket,
handler ),
monitor );
final Thread thread = startAcceptor( acceptor );
waitUntilStarted( acceptor );
waitUntilListening( monitor );
acceptor.close( 50 );
serverSocket.unlock();
waitUntilListening( monitor );
assertEquals( "handler.getSocket()",
null,
handler.getSocket() );
serverSocket.unlock();
thread.join();
}
private void waitUntilListening( final RecordingAcceptorMonitor monitor )
{
while ( 0 == monitor.getListenCount() )
{
try
{
Thread.sleep( 30 );
}
catch ( final InterruptedException e )
{
}
}
}
private Thread startAcceptor( final ConnectionAcceptor acceptor )
{
final Thread thread = new Thread( acceptor );
thread.start();
return thread;
}
private void waitUntilStarted( final ConnectionAcceptor acceptor )
{
while ( !acceptor.isRunning() )
{
try
{
Thread.sleep( 30 );
}
catch ( final InterruptedException e )
{
}
}
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/impl/BlockingServerSocket.java
Index: BlockingServerSocket.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.impl;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class BlockingServerSocket
extends ServerSocket
{
static final Socket SOCKET = new Socket();
private int m_lockCount;
private int m_acceptCount;
public BlockingServerSocket()
throws IOException
{
}
public Socket accept()
throws IOException
{
m_acceptCount++;
while ( true )
{
synchronized ( this )
{
if ( m_acceptCount <= m_lockCount )
{
break;
}
try
{
wait( 100 );
}
catch ( InterruptedException e )
{
}
notifyAll();
}
}
return SOCKET;
}
synchronized void unlock()
{
m_lockCount++;
notifyAll();
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/impl/DefaultAcceptorManagerTestCase.java
Index: DefaultAcceptorManagerTestCase.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.impl;
import java.net.Socket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.channels.ServerSocketChannel;
import java.util.Random;
import junit.framework.TestCase;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
public class DefaultAcceptorManagerTestCase
extends TestCase
{
public void testConnectAndDisconnectWithTimeoutNotSet()
throws Exception
{
final DefaultAcceptorManager manager = new DefaultAcceptorManager();
manager.setMonitor( NullAcceptorMonitor.MONITOR );
manager.setSoTimeout( 10 );
manager.setShutdownTimeout( 0 );
final String name = "name";
assertEquals( "isConnected pre connect", false, manager.isConnected( name ) );
final ExceptOnAcceptServerSocket socket = new ExceptOnAcceptServerSocket( true );
assertEquals( "socket.getSoTimeout pre connect", 0, socket.getSoTimeout() );
manager.connect( name,
socket,
new MockSocketConnectionHandler() );
assertEquals( "socket.getSoTimeout post connect", 10, socket.getSoTimeout() );
assertEquals( "isConnected pre disconnect", true, manager.isConnected( name ) );
manager.disconnect( name );
assertEquals( "isConnected post disconnect", false, manager.isConnected( name ) );
}
public void testShutdownAcceptors()
throws Exception
{
final DefaultAcceptorManager manager = new DefaultAcceptorManager();
manager.setMonitor( NullAcceptorMonitor.MONITOR );
manager.setSoTimeout( 10 );
final String name = "name";
assertEquals( "isConnected pre connect", false, manager.isConnected( name ) );
manager.connect( name,
new ExceptOnAcceptServerSocket( true ),
new MockSocketConnectionHandler() );
assertEquals( "isConnected pre shutdownAcceptors", true, manager.isConnected( name ) );
manager.shutdownAcceptors();
assertEquals( "isConnected post shutdownAcceptors", false, manager.isConnected( name ) );
}
public void testConnectAndDisconnectWithTimeoutSet()
throws Exception
{
final DefaultAcceptorManager manager = new DefaultAcceptorManager();
manager.setMonitor( NullAcceptorMonitor.MONITOR );
manager.setSoTimeout( 10 );
final String name = "name";
assertEquals( "isConnected pre connect", false, manager.isConnected( name ) );
final ExceptOnAcceptServerSocket socket = new ExceptOnAcceptServerSocket( true );
socket.setSoTimeout( 123 );
assertEquals( "socket.getSoTimeout pre connect", 123, socket.getSoTimeout() );
manager.connect( name,
socket,
new MockSocketConnectionHandler() );
assertEquals( "socket.getSoTimeout post connect", 123, socket.getSoTimeout() );
assertEquals( "isConnected pre disconnect", true, manager.isConnected( name ) );
manager.disconnect( name );
assertEquals( "isConnected post disconnect", false, manager.isConnected( name ) );
}
public void testConnectAndAcceptAndDisconnectWithTimeoutSet()
throws Exception
{
final DefaultAcceptorManager manager = new DefaultAcceptorManager();
final RecordingAcceptorMonitor monitor = new RecordingAcceptorMonitor();
manager.setMonitor( monitor );
manager.setSoTimeout( 10 );
final String name = "name";
assertEquals( "isConnected pre connect", false, manager.isConnected( name ) );
final ServerSocketChannel channel = ServerSocketChannel.open();
final ServerSocket serverSocket = channel.socket();
serverSocket.setReuseAddress( true );
final InetAddress localAddress = InetAddress.getLocalHost();
final Random random = new Random();
final int port = Math.abs( random.nextInt() % 5000 ) + 1024;
final InetSocketAddress address = new InetSocketAddress( localAddress, port );
serverSocket.bind( address );
while ( !serverSocket.isBound() )
{
System.out.print( "." );
Thread.yield();
}
final MockSocketConnectionHandler handler = new MockSocketConnectionHandler();
manager.connect( name, serverSocket, handler );
final Socket clientSocket = new Socket( localAddress, port );
System.out.print( "Socket Connecting" );
while ( !clientSocket.isConnected() )
{
System.out.print( "." );
Thread.yield();
}
System.out.println( " - Connected" );
clientSocket.close();
//Sleep to make sure accept goes through
Thread.sleep( 200 );
assertNotNull( "handler.socket", handler.getSocket() );
assertEquals( "isConnected pre disconnect", true, manager.isConnected( name ) );
manager.disconnect( name );
assertEquals( "isConnected post disconnect", false, manager.isConnected( name ) );
}
public void testDuplicateConnect()
throws Exception
{
final DefaultAcceptorManager manager = new DefaultAcceptorManager();
final String name = "name";
assertEquals( "isConnected pre connect", false, manager.isConnected( name ) );
final ExceptOnAcceptServerSocket socket = new ExceptOnAcceptServerSocket( true );
manager.connect( name,
socket,
new MockSocketConnectionHandler() );
assertEquals( "isConnected pre disconnect", true, manager.isConnected( name ) );
try
{
manager.connect( name,
new ExceptOnAcceptServerSocket( true ),
new MockSocketConnectionHandler() );
}
catch ( final IllegalArgumentException iae )
{
return;
}
finally
{
socket.close();
manager.shutdownAcceptors();
assertEquals( "isConnected post disconnect", false, manager.isConnected( name ) );
}
fail( "Expected to fail due to duplicate connect" );
}
public void testDisconnectNonExistent()
throws Exception
{
final DefaultAcceptorManager manager = new DefaultAcceptorManager();
try
{
manager.disconnect( "NonExistent" );
}
catch ( IllegalArgumentException iae )
{
return;
}
finally
{
manager.shutdownAcceptors();
}
fail( "Expected to fail to disconnect non existent acceptor" );
}
public void testConnectWithNullName()
throws Exception
{
final DefaultAcceptorManager manager = new DefaultAcceptorManager();
try
{
manager.connect( null,
new ExceptOnAcceptServerSocket( true ),
new MockSocketConnectionHandler() );
}
catch ( final NullPointerException npe )
{
assertEquals( "npe.message", "name", npe.getMessage() );
return;
}
finally
{
manager.shutdownAcceptors();
}
fail( "expected NPE due to null name in connect" );
}
public void testConnectWithNullSocket()
throws Exception
{
final DefaultAcceptorManager manager = new DefaultAcceptorManager();
try
{
manager.connect( "name",
null,
new MockSocketConnectionHandler() );
}
catch ( final NullPointerException npe )
{
assertEquals( "npe.message", "socket", npe.getMessage() );
return;
}
finally
{
manager.shutdownAcceptors();
}
fail( "expected NPE due to null socket in connect" );
}
public void testConnectWithNullHandler()
throws Exception
{
final DefaultAcceptorManager manager = new DefaultAcceptorManager();
try
{
manager.connect( "name",
new ExceptOnAcceptServerSocket( true ),
null );
}
catch ( final NullPointerException npe )
{
assertEquals( "npe.message", "handler", npe.getMessage() );
return;
}
finally
{
manager.shutdownAcceptors();
}
fail( "expected NPE due to null handler in connect" );
}
protected void setUp() throws Exception
{
System.out.print( "Test: " + getName() );
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/handlers/RequestHandlerTestCase.java
Index: RequestHandlerTestCase.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.handlers;
import junit.framework.TestCase;
import java.net.Socket;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
public class RequestHandlerTestCase
extends TestCase
{
public void testEndConnectionWithError()
throws Exception
{
final MockRequestHandler handler = new MockRequestHandler();
final ExceptionOnCloseSocket socket = new ExceptionOnCloseSocket();
handler.endConnection( socket );
assertEquals( "getErrorClosingConnectionSocket",
socket,
handler.getErrorClosingConnectionSocket() );
assertEquals( "getErrorClosingConnectionThrowable",
ExceptionOnCloseSocket.IO_EXCEPTION,
handler.getErrorClosingConnectionThrowable() );
}
public void testCreateRunnable()
throws Exception
{
final MockRequestHandler handler = new MockRequestHandler();
final Socket socket = new Socket();
final Runnable runnable = handler.createRunnable( socket );
runnable.run();
assertEquals( "getPerformRequestSocket",
socket,
handler.getPerformRequestSocket() );
}
public void testPerformRequestWithError()
throws Exception
{
final ExceptingRequestHandler handler = new ExceptingRequestHandler();
final Socket socket = new Socket();
handler.performRequest( socket );
assertEquals( "getPerformRequestSocket",
socket,
handler.getPerformRequestSocket() );
assertEquals( "getErrorHandlingConnectionSocket",
socket,
handler.getErrorHandlingConnectionSocket() );
assertEquals( "getErrorClosingConnectionThrowable",
ExceptingRequestHandler.EXCEPTION,
handler.getErrorHandlingConnectionThrowable() );
}
public void testShutdownWhileThreadStillGoingButInteruptible()
throws Exception
{
final DelayingRequestHandler handler = new DelayingRequestHandler( 2000, true );
final Socket socket = new Socket();
final Runnable runnable = new Runnable()
{
public void run()
{
handler.handleConnection( socket );
}
};
final Thread thread = new Thread( runnable );
thread.start();
Thread.sleep( 50 );
handler.shutdown( 50 );
assertEquals( "isShutdown", true, handler.isShutdown() );
assertEquals( "isExited", true, handler.isExited() );
assertEquals( "isExitDueToInterrupt", true, handler.isExitDueToInterrupt() );
}
public void testShutdownWhileThreadStillGoingAndNotInteruptible()
throws Exception
{
final DelayingRequestHandler handler =
new DelayingRequestHandler( 2000, false );
final Socket socket = new Socket();
final Runnable runnable = new Runnable()
{
public void run()
{
handler.handleConnection( socket );
}
};
final Thread thread = new Thread( runnable );
thread.start();
Thread.sleep( 50 );
handler.shutdown( 50 );
assertEquals( "isShutdown", true, handler.isShutdown() );
assertEquals( "isExited", false, handler.isExited() );
assertEquals( "isExitDueToInterrupt", false, handler.isExitDueToInterrupt() );
}
public void testShutdownWhileThreadStillGoingAndWaitIndefinetly()
throws Exception
{
final DelayingRequestHandler handler =
new DelayingRequestHandler( 200, false );
final Socket socket = new Socket();
final Runnable runnable = new Runnable()
{
public void run()
{
handler.handleConnection( socket );
}
};
final Thread thread = new Thread( runnable );
thread.start();
Thread.sleep( 50 );
handler.shutdown( 0 );
assertEquals( "isShutdown", true, handler.isShutdown() );
assertEquals( "isExited", true, handler.isExited() );
assertEquals( "isExitDueToInterrupt", false, handler.isExitDueToInterrupt() );
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/handlers/MockRequestHandler.java
Index: MockRequestHandler.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.handlers;
import java.net.Socket;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class MockRequestHandler
extends AbstractRequestHandler
{
private Socket m_performRequestSocket;
private Socket m_errorClosingConnectionSocket;
private Throwable m_errorClosingConnectionThrowable;
private Socket m_errorHandlingConnectionSocket;
private Throwable m_errorHandlingConnectionThrowable;
protected void doPerformRequest( Socket socket )
throws Exception
{
m_performRequestSocket = socket;
}
protected void errorClosingConnection( Socket socket,
Throwable t )
{
super.errorClosingConnection( socket, t );
m_errorClosingConnectionSocket = socket;
m_errorClosingConnectionThrowable = t;
}
protected void errorHandlingConnection( Socket socket,
Throwable t )
{
super.errorHandlingConnection( socket, t );
m_errorHandlingConnectionSocket = socket;
m_errorHandlingConnectionThrowable = t;
}
Socket getPerformRequestSocket()
{
return m_performRequestSocket;
}
Socket getErrorClosingConnectionSocket()
{
return m_errorClosingConnectionSocket;
}
Throwable getErrorClosingConnectionThrowable()
{
return m_errorClosingConnectionThrowable;
}
Socket getErrorHandlingConnectionSocket()
{
return m_errorHandlingConnectionSocket;
}
Throwable getErrorHandlingConnectionThrowable()
{
return m_errorHandlingConnectionThrowable;
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/handlers/ExceptingRequestHandler.java
Index: ExceptingRequestHandler.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.handlers;
import java.net.Socket;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class ExceptingRequestHandler
extends MockRequestHandler
{
static final Exception EXCEPTION = new Exception();
protected void doPerformRequest( Socket socket )
throws Exception
{
super.doPerformRequest(socket );
throw EXCEPTION;
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/handlers/DelegatingRequestHandlerTestCase.java
Index: DelegatingRequestHandlerTestCase.java
===================================================================
package org.codehaus.spice.netserve.connection.handlers;
import java.net.Socket;
import com.mockobjects.dynamic.C;
import com.mockobjects.dynamic.Mock;
import junit.framework.TestCase;
import org.codehaus.spice.netserve.connection.RequestHandler;
public class DelegatingRequestHandlerTestCase
extends TestCase
{
public void testNullPassedIntoCtor()
throws Exception
{
try
{
new DelegatingRequestHandler( null );
}
catch ( final NullPointerException npe )
{
assertEquals( "npe.getMessage()", "handler", npe.getMessage() );
return;
}
}
public void testDelegateHandlerInvoked()
throws Exception
{
final Mock mockHandler = new Mock( RequestHandler.class );
final Socket socket = new Socket();
final Long timeout = new Long( 23 );
mockHandler.expect( "handleConnection", C.args( C.eq( socket ) ) );
mockHandler.expect( "shutdown", C.args( C.eq( timeout ) ) );
final RequestHandler handler = (RequestHandler) mockHandler.proxy();
final DelegatingRequestHandler delegatingHandler =
new DelegatingRequestHandler( handler );
delegatingHandler.handleConnection( socket );
delegatingHandler.shutdown( 23 );
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/handlers/ManagedRequestHandlerTestCase.java
Index: ManagedRequestHandlerTestCase.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.handlers;
import com.mockobjects.dynamic.C;
import com.mockobjects.dynamic.Mock;
import java.net.Socket;
import junit.framework.TestCase;
import org.codehaus.spice.netserve.connection.RequestHandler;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
public class ManagedRequestHandlerTestCase
extends TestCase
{
public void testManagedRequestHandler()
throws Exception
{
final Mock mockHandler = new Mock( RequestHandler.class );
final Socket socket = new Socket();
mockHandler.expect( "handleConnection", C.args( C.eq( socket ) ) );
final RequestHandler handler = (RequestHandler)mockHandler.proxy();
final Mock mockManager = new Mock( RequestManager.class );
mockManager.expectAndReturn( "aquireHandler",
C.args( C.isA( Socket.class ) ),
handler );
mockManager.expect( "releaseHandler",
C.args( C.eq( handler ) ) );
final RequestManager manager = (RequestManager)mockManager.proxy();
final MockManagedRequestHandler managedHandler =
new MockManagedRequestHandler( manager );
managedHandler.handleConnection( socket );
mockManager.verify();
mockHandler.verify();
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/handlers/MockThreadPool.java
Index: MockThreadPool.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.handlers;
import org.codehaus.spice.threadpool.ThreadPool;
import org.codehaus.spice.threadpool.ThreadControl;
import org.codehaus.spice.threadpool.Executable;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class MockThreadPool
implements ThreadPool
{
public ThreadControl execute( Runnable work )
{
final Thread thread = new Thread( work );
thread.start();
return new MockThreadControl( thread );
}
public ThreadControl execute( Executable work )
{
return null;
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/handlers/ThreadPerRequestHandlerTestCase.java
Index: ThreadPerRequestHandlerTestCase.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.handlers;
import junit.framework.TestCase;
import com.mockobjects.dynamic.Mock;
import com.mockobjects.dynamic.C;
import org.codehaus.spice.netserve.connection.RequestHandler;
import org.codehaus.spice.threadpool.ThreadPool;
import org.codehaus.spice.threadpool.ThreadControl;
import java.net.Socket;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
public class ThreadPerRequestHandlerTestCase
extends TestCase
{
public void testNullThreadPoolPassedToCtor()
throws Exception
{
final Mock mockHandler = new Mock( RequestHandler.class );
final RequestHandler handler = (RequestHandler)mockHandler.proxy();
try
{
new ThreadPerRequestHandler( handler, null );
}
catch( final NullPointerException npe )
{
assertEquals( "npe.getMessage()", "threadPool", npe.getMessage() );
return;
}
fail( "Expected to fail due to null ThreadPool passed into Ctor" );
}
public void testThreadPoolInvoked()
throws Exception
{
final Mock mockControl = new Mock( ThreadControl.class );
final ThreadControl control = (ThreadControl)mockControl.proxy();
final Mock mockHandler = new Mock( RequestHandler.class );
final RequestHandler handler = (RequestHandler)mockHandler.proxy();
final Mock mockPool = new Mock( ThreadPool.class );
mockPool.expectAndReturn( "execute", C.args( C.isA( Runnable.class ) ), control );
final ThreadPool threadPool = (ThreadPool)mockPool.proxy();
final ThreadPerRequestHandler requestHandler =
new ThreadPerRequestHandler( handler, threadPool );
requestHandler.handleConnection( new Socket() );
mockHandler.verify();
mockPool.verify();
mockControl.verify();
}
public void testShutdownWhileThreadStillGoingButInteruptible()
throws Exception
{
final DelayingRequestHandler handler =
new DelayingRequestHandler( 2000, true );
final ThreadPerRequestHandler requestHandler =
new ThreadPerRequestHandler( handler, new MockThreadPool() );
requestHandler.handleConnection( new Socket() );
Thread.sleep( 50 );
requestHandler.shutdown( 50 );
assertEquals( "isShutdown", true, handler.isShutdown() );
assertEquals( "isExited", true, handler.isExited() );
assertEquals( "isExitDueToInterrupt", true, handler.isExitDueToInterrupt() );
}
public void testShutdownWhileThreadStillGoingAndNotInteruptible()
throws Exception
{
final DelayingRequestHandler handler =
new DelayingRequestHandler( 2000, false );
final ThreadPerRequestHandler requestHandler =
new ThreadPerRequestHandler( handler, new MockThreadPool() );
requestHandler.handleConnection( new Socket() );
Thread.sleep( 50 );
requestHandler.shutdown( 50 );
assertEquals( "isShutdown", true, handler.isShutdown() );
assertEquals( "isExited", false, handler.isExited() );
assertEquals( "isExitDueToInterrupt", false, handler.isExitDueToInterrupt() );
}
public void testShutdownWhileThreadStillGoingAndWaitIndefinetly()
throws Exception
{
final DelayingRequestHandler handler =
new DelayingRequestHandler( 200, false );
final ThreadPerRequestHandler requestHandler =
new ThreadPerRequestHandler( handler, new MockThreadPool() );
requestHandler.handleConnection( new Socket() );
Thread.sleep( 50 );
requestHandler.shutdown( 0 );
assertEquals( "isShutdown", true, handler.isShutdown() );
assertEquals( "isExited", true, handler.isExited() );
assertEquals( "isExitDueToInterrupt", false, handler.isExitDueToInterrupt() );
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/handlers/ExceptionOnCloseSocket.java
Index: ExceptionOnCloseSocket.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.handlers;
import java.net.Socket;
import java.io.IOException;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class ExceptionOnCloseSocket
extends Socket
{
static final IOException IO_EXCEPTION = new IOException();
public boolean isConnected()
{
return true;
}
public synchronized void close() throws IOException
{
throw IO_EXCEPTION;
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/handlers/DelayingRequestHandler.java
Index: DelayingRequestHandler.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.handlers;
import java.net.Socket;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class DelayingRequestHandler
extends AbstractRequestHandler
{
private final long m_delay;
private final boolean m_wakeupOnInterrupt;
private boolean m_exited;
private boolean m_exitDueToInterrupt;
DelayingRequestHandler( final long delay,
final boolean wakeupOnInterrupt )
{
m_delay = delay;
m_wakeupOnInterrupt = wakeupOnInterrupt;
}
protected void doPerformRequest( Socket socket )
throws Exception
{
final int code = System.identityHashCode( this );
final String prefix = "Handler(" + code + ") ";
System.out.println( prefix + "Started" );
final long then = System.currentTimeMillis() + m_delay;
while( System.currentTimeMillis() < then )
{
final long rest = then - System.currentTimeMillis();
System.out.println( prefix + "Sleeping for " + rest );
try
{
Thread.sleep( rest );
}
catch( InterruptedException e )
{
System.out.println( prefix + "Woken up" );
if( m_wakeupOnInterrupt )
{
m_exitDueToInterrupt = true;
break;
}
}
}
m_exited = true;
System.out.println( prefix + "Returning" );
}
boolean isExitDueToInterrupt()
{
return m_exitDueToInterrupt;
}
boolean isExited()
{
return m_exited;
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/handlers/MockManagedRequestHandler.java
Index: MockManagedRequestHandler.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.handlers;
import java.net.Socket;
import org.codehaus.spice.netserve.connection.RequestHandler;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class MockManagedRequestHandler
extends ManagedRequestHandler
{
private final RequestManager m_requestManager;
public MockManagedRequestHandler( RequestManager requestManager )
{
m_requestManager = requestManager;
}
protected RequestHandler aquireHandler( Socket socket )
{
return m_requestManager.aquireHandler( socket );
}
protected void releaseHandler( RequestHandler handler )
{
m_requestManager.releaseHandler( handler );
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/handlers/MockThreadControl.java
Index: MockThreadControl.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.handlers;
import org.codehaus.spice.threadpool.ThreadControl;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
class MockThreadControl
implements ThreadControl
{
private final Thread m_thread;
public MockThreadControl( Thread thread )
{
m_thread = thread;
}
public void join( long milliSeconds )
throws InterruptedException
{
m_thread.join( milliSeconds );
}
public void interrupt()
throws IllegalStateException, SecurityException
{
m_thread.interrupt();
}
public boolean isFinished()
{
return !m_thread.isAlive();
}
public Throwable getThrowable()
{
return null;
}
}
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/connection/handlers/RequestManager.java
Index: RequestManager.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.handlers;
import org.codehaus.spice.netserve.connection.RequestHandler;
import java.net.Socket;
/**
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:05 $
*/
public interface RequestManager
{
RequestHandler aquireHandler( Socket socket );
void releaseHandler( RequestHandler handler );
}
1.13 +5 -5 spice/components/netserve/project.xml
Index: project.xml
===================================================================
RCS file: /scm/cvs/spice/components/netserve/project.xml,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- project.xml 19 Nov 2003 17:38:34 -0000 1.12
+++ project.xml 20 Nov 2003 00:25:06 -0000 1.13
@@ -4,8 +4,8 @@
<name>Netserve</name>
<id>spice-netserve</id>
<gumpRepositoryId>components</gumpRepositoryId>
- <package>org.jcomponent.netserve</package>
- <currentVersion>0.7</currentVersion>
+ <package>org.codehaus.spice.netserve</package>
+ <currentVersion>1.0-b1</currentVersion>
<inceptionYear>1999</inceptionYear>
<shortDescription>Components useful for creating a Network Server.</shortDescription>
@@ -38,9 +38,9 @@
<version>1.0</version>
</dependency>
<dependency>
- <groupId>jcomponent</groupId>
- <artifactId>jcomponent-threadpool</artifactId>
- <version>1.0</version>
+ <groupId>spice</groupId>
+ <artifactId>spice-threadpool</artifactId>
+ <version>1.0-b1</version>
<properties>
<category>runtime</category>
</properties>
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/handlers/ThreadPerRequestHandler.java
Index: ThreadPerRequestHandler.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.handlers;
import java.net.Socket;
import java.util.Map;
import java.util.Hashtable;
import java.util.Collection;
import org.codehaus.spice.netserve.connection.RequestHandler;
import org.codehaus.spice.threadpool.ThreadPool;
import org.codehaus.spice.threadpool.ThreadControl;
/**
* A Handler that uses a thread from a pool for each different request.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:06 $
*/
public class ThreadPerRequestHandler
extends DelegatingRequestHandler
{
/**
* A map of Socket->ThreadControl.
*/
private final Map m_controlMap = new Hashtable();
/**
* the thread pool that used to handle requests.
*/
private final ThreadPool m_threadPool;
/**
* Create handler.
*
* @param handler the underlying handler
* @param threadPool the thread pool to use to create handler threads
*/
public ThreadPerRequestHandler( final RequestHandler handler,
final ThreadPool threadPool )
{
super( handler );
if( null == threadPool )
{
throw new NullPointerException( "threadPool" );
}
m_threadPool = threadPool;
}
/**
* Execute each request in a separate thread.
*
* @param socket the socket to handle
*/
public void handleConnection( final Socket socket )
{
final Runnable runnable = createRunnable( socket );
final ThreadControl control = m_threadPool.execute( runnable );
m_controlMap.put( socket, control );
}
/**
* Remove ThreadControl from list of active threads.
*
* @param socket the socket
*/
protected void endConnection( Socket socket )
{
m_controlMap.remove( socket );
super.endConnection( socket );
}
/**
* Shutdown all requests including those executing in thread pool.
*
* @param timeout the timeout
*/
public void shutdown( final long timeout )
{
markAsShutdown();
final ThreadControl[] controls;
synchronized( m_controlMap )
{
final Collection collection = m_controlMap.values();
controls = (ThreadControl[])collection.
toArray( new ThreadControl[ collection.size() ] );
}
for( int i = 0; i < controls.length; i++ )
{
final ThreadControl control = controls[ i ];
if( !control.isFinished() )
{
control.interrupt();
}
}
super.shutdown( timeout );
for( int i = 0; i < controls.length; i++ )
{
final ThreadControl control = controls[ i ];
if( !control.isFinished() )
{
try
{
control.join( timeout );
}
catch( final InterruptedException ie )
{
//Ignore
}
}
}
}
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/handlers/DelegatingRequestHandler.java
Index: DelegatingRequestHandler.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.handlers;
import java.net.Socket;
import org.codehaus.spice.netserve.connection.RequestHandler;
/**
* A simple handler that delegates to another handler.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:06 $
*/
public class DelegatingRequestHandler
extends AbstractRequestHandler
{
/**
* The underlying handler to delegate to.
*/
private final RequestHandler m_handler;
/**
* Create handler.
*
* @param handler the handler to delegate to
*/
public DelegatingRequestHandler( final RequestHandler handler )
{
if( null == handler )
{
throw new NullPointerException( "handler" );
}
m_handler = handler;
}
/**
* Delegate request to supplied handler.
*
* @param socket the socket
* @throws Exception on error
*/
protected void doPerformRequest( final Socket socket )
throws Exception
{
m_handler.handleConnection( socket );
}
/**
* @see AbstractRequestHandler#shutdown
*/
public void shutdown( final long timeout )
{
m_handler.shutdown( timeout );
super.shutdown( timeout );
}
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/handlers/AbstractRequestHandler.java
Index: AbstractRequestHandler.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection.handlers;
import java.io.IOException;
import java.net.Socket;
import java.util.HashSet;
import java.util.Set;
import org.codehaus.spice.netserve.connection.RequestHandler;
/**
* Abstract base class for request handlers.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:06 $
*/
public abstract class AbstractRequestHandler
implements RequestHandler
{
/**
* The set of active requests.
*/
private final Set m_activeRequests = new HashSet();
/**
* True if shutdown() has been called.
*/
private boolean m_shutdown;
/**
* Handle a connection.
*
* @param socket the socket
*/
public void handleConnection( Socket socket )
{
performRequest( socket );
}
/**
* @see RequestHandler#shutdown
*/
public void shutdown( final long timeout )
{
markAsShutdown();
final Thread[] threads;
synchronized( this )
{
threads = (Thread[])m_activeRequests.
toArray( new Thread[ m_activeRequests.size() ] );
}
for( int i = 0; i < threads.length; i++ )
{
final Thread thread = threads[ i ];
thread.interrupt();
}
final long now = System.currentTimeMillis();
final long then = now + timeout;
while( System.currentTimeMillis() < then || 0 == timeout )
{
synchronized( this )
{
if( 0 == m_activeRequests.size() )
{
return;
}
try
{
wait( timeout );
}
catch( final InterruptedException ie )
{
//Ignore
}
}
}
}
/**
* Mark request handler as shutdown.
*/
protected void markAsShutdown()
{
m_shutdown = true;
}
/**
* Return true if handler has been shutdown.
*
* @return true if handler has been shutdown.
*/
protected boolean isShutdown()
{
return m_shutdown;
}
/**
* Perform the request for socket by delegating to
* underlying handler.
*
* @param socket the socket to handle
*/
protected void performRequest( final Socket socket )
{
synchronized( this )
{
m_activeRequests.add( Thread.currentThread() );
}
setupThreadName( socket );
try
{
doPerformRequest( socket );
}
catch( final Throwable t )
{
errorHandlingConnection( socket, t );
}
finally
{
endConnection( socket );
synchronized( this )
{
m_activeRequests.remove( Thread.currentThread() );
notifyAll();
}
}
}
/**
* Method implemented to actually do the work.
*
* @param socket the socket
* @throws Exception if an error occurs
*/
protected abstract void doPerformRequest( Socket socket )
throws Exception;
/**
* Setup the name of the thread.
*
* @param socket the socket associated with request
*/
protected void setupThreadName( final Socket socket )
{
final String name = getThreadName( socket );
Thread.currentThread().setName( name );
}
/**
* End connection for socket.
*
* @param socket the socket
*/
protected void endConnection( final Socket socket )
{
if( socket.isConnected() )
{
try
{
socket.close();
}
catch( final IOException ioe )
{
errorClosingConnection( socket, ioe );
}
}
}
/**
* Create Runnable to perform the request.
*
* @param socket the socket to handle
* @return thee runnable
*/
protected Runnable createRunnable( final Socket socket )
{
return new Runnable()
{
public void run()
{
performRequest( socket );
}
};
}
/**
* Return the name should be set for current thread.
*
* @param socket the socket being handled in thread
* @return the thread name.
*/
protected String getThreadName( final Socket socket )
{
if( socket.isConnected() )
{
return "RequestHandler for " +
socket.getInetAddress().getHostAddress() + ":" +
socket.getPort();
}
else
{
return "RequestHandler for " + socket;
}
}
/**
* Notify handler of an error handling socket.
*
* @param socket the socket
* @param t the error
*/
protected void errorHandlingConnection( final Socket socket,
final Throwable t )
{
}
/**
* Notify handler of an error closing socket.
*
* @param socket the socket
* @param t the error
*/
protected void errorClosingConnection( final Socket socket,
final Throwable t )
{
errorHandlingConnection( socket, t );
}
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/handlers/ManagedRequestHandler.java
Index: ManagedRequestHandler.java
===================================================================
package org.codehaus.spice.netserve.connection.handlers;
import java.net.Socket;
import org.codehaus.spice.netserve.connection.RequestHandler;
/**
* A handler that allows user to handle ConnectionHandlers.
* Subclasses may pool or create transient handlers etc.
*/
public abstract class ManagedRequestHandler
extends AbstractRequestHandler
{
/**
* Actually handle the request.
* Assume that the caller will gracefully
* handle unexpected exceptions and shutdown
* the socket when this method returns.
*
* @param socket the socket
* @throws Exception if an erro roccurs
*/
protected void doPerformRequest( final Socket socket )
throws Exception
{
final RequestHandler handler = aquireHandler( socket );
try
{
handler.handleConnection( socket );
}
finally
{
releaseHandler( handler );
}
}
/**
* Retrieve the underlying handler.
*
* @param socket the socket
* @return the RequestHandler
*/
protected abstract RequestHandler aquireHandler( Socket socket );
/**
* Release the underlying handler.
*
* @param handler the handler
*/
protected abstract void releaseHandler( RequestHandler handler );
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/RequestHandler.java
Index: RequestHandler.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection;
import java.net.Socket;
/**
* Implement this interface to process incoming socket connections.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:06 $
*/
public interface RequestHandler
{
/**
* Processes connections as they occur.
*
* @param socket the socket
*/
void handleConnection( Socket socket );
/**
* Shutdown the handler and any requests currently being handled.
* The timeout specifies the time to wait while shutting
* down request handlers. A timeout of 0 indicates that
* should wait indefinetly.
*
* @param timeout the timeout
*/
void shutdown( long timeout );
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/connection/SocketAcceptorManager.java
Index: SocketAcceptorManager.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.connection;
import java.net.ServerSocket;
import org.codehaus.spice.netserve.connection.RequestHandler;
/**
* This service is used to manage network acceptors.
* The service takes a ServerSocket and RequestHandler and
* anytime a new connection is accepted the handler is called
* with the new socket connection.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:06 $
*/
public interface SocketAcceptorManager
{
/**
* Start accepting connections from a socket and passing connections
* to specified handler.
*
* @param name the name of connection. This serves as a key used to
* shutdown acceptor.
* @param socket the ServerSocket from which connections are accepted
* @throws java.lang.Exception if unable to initiate connection management. This could
* be due to the key already being used for another acceptor,
* the serversocket being closed, the handler being null etc.
*/
void connect( String name,
ServerSocket socket,
RequestHandler handler )
throws Exception;
/**
* This shuts down the named acceptor.
* NOTE: It is the responsibility of the caller to make
* sure that the ServerSocket has been closed.
*
* @param name the name of connection
* @throws java.lang.IllegalArgumentException if no connection with specified name
*/
void disconnect( String name );
/**
* Return true if acceptor with specified name exists.
*
* @param name the name
* @return true if acceptor with specified name exists.
*/
boolean isConnected( String name );
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/sockets/ServerSocketFactory.java
Index: ServerSocketFactory.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.sockets;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
/**
* Service used to create server sockets. The factory is used so that
* the exact socket type and underlying transport is abstracted. The
* sockets created could be proxied, SSL enabled, TLS enabled etc.
* However clients just care that they return sockets.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:06 $
*/
public interface ServerSocketFactory
{
/**
* Creates a socket on specified port.
*
* @param port the port (0 indicates any available port)
* @return the created ServerSocket
* @throws IOException if unable to create socket
*/
ServerSocket createServerSocket( int port )
throws IOException;
/**
* Creates a socket on specified port with a specified backlog.
*
* @param port the port (0 indicates any available port)
* @param backlog the backlog
* @return the created ServerSocket
* @throws IOException if unable to create socket
*/
ServerSocket createServerSocket( int port, int backlog )
throws IOException;
/**
* Creates a socket on a particular network interface on specified port
* with a specified backlog.
*
* @param port the port (0 indicates any available port)
* @param backlog the backlog
* @param address the network interface to bind to.
* @return the created ServerSocket
* @throws IOException if unable to create socket
*/
ServerSocket createServerSocket( int port, int backlog, InetAddress address )
throws IOException;
}
1.1 spice/components/netserve/src/java/org/codehaus/spice/netserve/sockets/SocketFactory.java
Index: SocketFactory.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.sockets;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
/**
* Service used to create client sockets. The factory is used so that
* the exact socket type and underlying transport is abstracted. The
* sockets created could be proxied, SSL enabled, TLS enabled etc.
* However clients just care that they return sockets.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:06 $
*/
public interface SocketFactory
{
/**
* Create a socket that connects to specified remote address.
*
* @param address the remote address
* @param port the remote port
* @return the socket connected to remote address
* @throws IOException if unable to create socket
*/
Socket createSocket( InetAddress address, int port )
throws IOException;
/**
* Create a socket that connects to specified remote address and
* originates from specified local address.
*
* @param address the remote address
* @param port the remote port
* @param localAddress the local address
* @param localPort the local port
* @return the socket connected to remote address
* @throws IOException if unable to create socket
*/
Socket createSocket( InetAddress address, int port,
InetAddress localAddress, int localPort )
throws IOException;
}
1.5 +9 -10 spice/components/netserve/xdocs/index.xml
Index: index.xml
===================================================================
RCS file: /scm/cvs/spice/components/netserve/xdocs/index.xml,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- index.xml 5 Nov 2003 08:47:56 -0000 1.4
+++ index.xml 20 Nov 2003 00:25:07 -0000 1.5
@@ -13,11 +13,10 @@
from ACE for both stream based and packet based connections,
etc.
</p>
- <p>
+ <p>
All Spice jars are held in the
- <a href="http://spice.sf.net/maven">http://spice.sf.net/maven</a>
- repository for Maven usage.
- </p>
+ <a href="http://dist.codehaus.org/spice">Codehaus Repository</a>.
+ </p>
</section>
<section name="Multi-Container support">
<p>
@@ -31,9 +30,9 @@
supports type-1 Inversion of Control (IoC).
</p>
<p>
- <a href="apidocs/org/jcomponent/netserve/connection/impl/AvalonConnectionManager.html">
+ <a href="apidocs/org/codehaus/spice/netserve/connection/impl/AvalonConnectionManager.html">
AvalonConnectionManager</a> provides an implementation of the
- <a href="apidocs/org/jcomponent/netserve/connection/ConnectionManager.html">
+ <a href="apidocs/org/codehaus/spice/netserve/connection/ConnectionManager.html">
ConnectionManager</a> interface which is Avalon-compatible.
</p>
</subsection>
@@ -43,9 +42,9 @@
supports type-1 Inversion of Control (IoC).
</p>
<p>
- <a href="apidocs/org/jcomponent/netserve/connection/impl/DNAConnectionManager.html">
+ <a href="apidocs/org/codehaus/spice/netserve/connection/impl/DNAConnectionManager.html">
DNAConnectionManager</a> provides an implementation of the
- <a href="apidocs/org/jcomponent/netserve/connection/ConnectionManager.html">
+ <a href="apidocs/org/codehaus/spice/netserve/connection/ConnectionManager.html">
ConnectionManager</a> interface which is DNA-compatible.
</p>
</subsection>
@@ -55,9 +54,9 @@
supports type-3 IoC.
</p>
<p>
- <a href="apidocs/org/jcomponent/netserve/connection/impl/PicoConnectionManager.html">
+ <a href="apidocs/org/codehaus/spice/netserve/connection/impl/PicoConnectionManager.html">
PicoConnectionManager</a> provides an implementation of the
- <a href="apidocs/org/jcomponent/netserve/connection/ConnectionManager.html">
+ <a href="apidocs/org/codehaus/spice/netserve/connection/ConnectionManager.html">
ConnectionManager</a> interface which is
<img src="http://www.picocontainer.org/images/pico-compatible.png" alt="Pico-compatible"/>.
</p>
1.1 spice/components/netserve/src/test/org/codehaus/spice/netserve/sockets/impl/SocketTestCase.java
Index: SocketTestCase.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.codehaus.spice.netserve.sockets.impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import junit.framework.TestCase;
import org.codehaus.spice.netserve.sockets.ServerSocketFactory;
import org.codehaus.spice.netserve.sockets.SocketFactory;
/**
* TestCase for {@link org.codehaus.spice.netserve.sockets.SocketFactory} and {@link org.codehaus.spice.netserve.sockets.ServerSocketFactory}.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:25:07 $
*/
public class SocketTestCase
extends TestCase
{
private static final int PORT = 1977;
private static final InetAddress HOST = getLocalHost();
private static final byte DATA = 23;
public SocketTestCase( final String name )
{
super( name );
}
public void testDefault()
throws Exception
{
final SocketFactory csf = new DefaultSocketFactory();
final ServerSocketFactory ssf = new DefaultServerSocketFactory();
doSocketPairTest( csf, ssf );
}
private void doSocketPairTest( final SocketFactory csf, final ServerSocketFactory ssf ) throws IOException
{
try
{
csf.createSocket( HOST, PORT );
final String message = "Should not be able to create " +
"client socket when server socket not initialized.";
fail( message );
}
catch( IOException e )
{
}
final ServerSocket ss1 = ssf.createServerSocket( PORT );
readWriteTestsOnSingleSocket( ss1, csf );
final ServerSocket ss2 = ssf.createServerSocket( PORT, 1 );
readWriteTestsOnSingleSocket( ss2, csf );
final ServerSocket ss3 = ssf.createServerSocket( PORT, 1, HOST );
readWriteTestsOnSingleSocket( ss3, csf );
}
private void readWriteTestsOnSingleSocket( final ServerSocket serverSocket,
final SocketFactory csf )
throws IOException
{
final Socket client = csf.createSocket( HOST, PORT );
final Socket server = serverSocket.accept();
pushPullData( "Testing single socket conn", client, server );
final Socket client2 = csf.createSocket( HOST, PORT, HOST, 0 );
final Socket server2 = serverSocket.accept();
pushPullData( "Testing single socket conn2", client2, server2 );
serverSocket.close();
}
private void pushPullData( final String prefix,
final Socket client,
final Socket server )
throws IOException
{
pushData( prefix + ": c2s", client, server );
pushData( prefix + ": s2c", server, client );
client.close();
server.close();
}
/**
* Push data from socket1 to socket2.
*/
private void pushData( final String prefix,
final Socket socket1,
final Socket socket2 ) throws IOException
{
final OutputStream cos = socket1.getOutputStream();
cos.write( DATA );
cos.flush();
final InputStream sis = socket2.getInputStream();
assertEquals( prefix + ": Write/read byte", DATA, sis.read() );
}
private static InetAddress getLocalHost()
{
try
{
return InetAddress.getLocalHost();
}
catch( UnknownHostException e )
{
throw new IllegalStateException( e.toString() );
}
}
}