Nathan,
Thanks. I'll apply it. Don't know how I left out the '/' in the config file I checked in. --Peter > -----Original Message----- > From: Nathan Carter [mailto:[EMAIL PROTECTED]] > Sent: Tuesday, October 08, 2002 3:05 PM > To: James Developers List > Subject: Re: cvs commit: jakarta- > james/src/java/org/apache/james/util/connection ServerConnection.java > SimpleConnectionManager.java SimpleConnectionManager.xinfo package.html > > Peter, > > Current HEAD compiles fine, but there's a parsing error at runtime due > to a couple of typos in src/conf/james-config.xml - here is the patch. > > Nathan Carter > > > [EMAIL PROTECTED] wrote: > > >pgoldstein 2002/10/07 00:16:46 > > > > Modified: src/conf james-assembly.xml james-config.xml > > Added: src/java/org/apache/james/util/connection > > ServerConnection.java > SimpleConnectionManager.java > > SimpleConnectionManager.xinfo package.html > > Log: > > Added the SimpleConnectionManager and supporting class > ServerConnection. > > > > Changed the configuration/assembly - > > i) Replaced tabs with spaces > > ii) Added comments > > iii) Removed AuthService references > > iv) Increased max number of threads in thread pool > > v) Changed ConnectionManager to default to > org.apache.james.util.connection.SimpleConnectionManager > > vi) Added commented authRequired element to NNTP server > > > > Revision Changes Path > > 1.12 +1 -6 jakarta-james/src/conf/james-assembly.xml > > > > Index: james-assembly.xml > > =================================================================== > > RCS file: /home/cvs/jakarta-james/src/conf/james-assembly.xml,v > > retrieving revision 1.11 > > retrieving revision 1.12 > > diff -u -r1.11 -r1.12 > > --- james-assembly.xml 2 Oct 2002 09:53:37 -0000 1.11 > > +++ james-assembly.xml 7 Oct 2002 07:16:46 -0000 1.12 > > @@ -99,11 +99,6 @@ > > > role="org.apache.james.nntpserver.repository.NNTPRepository"/> > > </block> > > > > - <!-- NNTP Authentication Service --> > > - <block name="nntpauth" > class="org.apache.james.nntpserver.AuthServiceImpl" > > > - <provide name="users-store" > role="org.apache.james.services.UsersStore"/> > > - </block> > > - > > <!-- NNTP Repository --> > > <block name="nntp-repository" > class="org.apache.james.nntpserver.repository.NNTPRepositoryImpl" /> > > > > @@ -142,7 +137,7 @@ > > > > <!-- The Connection Manager block --> > > <block name="connections" > > - > class="org.apache.avalon.cornerstone.blocks.connection.DefaultConnection Ma > nager" > > > + > class="org.apache.james.util.connection.SimpleConnectionManager" > > > <provide name="thread-manager" > > > role="org.apache.avalon.cornerstone.services.threads.ThreadManager" /> > > </block> > > > > > > > > 1.34 +92 -49 jakarta-james/src/conf/james-config.xml > > > > Index: james-config.xml > > =================================================================== > > RCS file: /home/cvs/jakarta-james/src/conf/james-config.xml,v > > retrieving revision 1.33 > > retrieving revision 1.34 > > diff -u -r1.33 -r1.34 > > --- james-config.xml 27 Sep 2002 16:31:06 -0000 1.33 > > +++ james-config.xml 7 Oct 2002 07:16:46 -0000 1.34 > > @@ -7,10 +7,10 @@ > > README! > > > > This configuration file is designed to run without alteration for > simple tests. > > -It assumes you have a DNS server on localhost and assigns a root > pasword of root. > > +It assumes you have a DNS server on localhost and assigns a root > password of root. > > > > In case the defaults do not suit you, the items you are most likely to > need to change > > -are preceeded by a CHECKME! or CONFIRM? comment in the left margin. > > +are preceded by a CHECKME! or CONFIRM? comment in the left margin. > > > > For production use you will probably need to make more extensive > changes, see > > http://jakarta.apache.org/james/configuration_v2_0.html > > @@ -30,16 +30,16 @@ > > If autodetectIP is not FALSE, James will also allow add the > IP address for each servername. > > The automatic IP detection is to support RFC 2821, Sec > 4.1.3, address literals. > > By default, the servername 'localhost' is specified. This > can be removed, if required. --> > > - <servernames autodetect="TRUE" autodetectIP="TRUE"> > > + <servernames autodetect="true" autodetectIP="true"> > > <!--<servername>To override autodetected server names > uncomment this. </servername> --> > > <servername>localhost</servername> > > - <!-- IMPORTANT if you are using fetchpop it is important to > include the --> > > - <!-- fetched domains here to prevent looping > --> > > + <!-- IMPORTANT if you are using fetchpop it is important to > include the --> > > + <!-- fetched domains here to prevent looping > --> > > </servernames> > > > > <!-- Set whether user names are case sensitive or case > insensitive --> > > <!-- Set whether to enable local aliases --> > > - <usernames ignoreCase="TRUE" enableAliases="TRUE" > enableForwarding="TRUE"/> > > + <usernames ignoreCase="true" enableAliases="true" > enableForwarding="true"/> > > > > <!-- The inbox repository is the location for users inboxes --> > > <!-- Default setting: file based repository - enter path ( use > "file:///" for absolute) --> > > @@ -62,22 +62,22 @@ > > <!-- fetched domains in the <servernames> section of the <James> > block --> > > <!-- above. fetchpop is disabled by default. > --> > > > > - <fetchpop enabled="false"> > > - <!-- you can have as many fetch tasks as you want to -- > > > > - <!-- but each must have a unique name to identify itself by -- > > > > - <fetch name="mydomain.com"> > > - <!-- host name or IP address --> > > - <host>mail.mydomain.com</host> > > - <!-- acount login username --> > > - <user>username</user> > > - <!-- account login password --> > > - <password>pass</password> > > - <!-- Interval to check this account in milliseconds, > 600000 is every ten minutes --> > > - <interval>600000</interval> > > - </fetch> > > - </fetchpop> > > - > > - > > + <fetchpop enabled="false"> > > + <!-- you can have as many fetch tasks as you want to -- > > > > + <!-- but each must have a unique name to identify itself by -- > > > > + <fetch name="mydomain.com"> > > + <!-- host name or IP address --> > > + <host>mail.mydomain.com</host> > > + <!-- acount login username --> > > + <user>username</user> > > + <!-- account login password --> > > + <password>pass</password> > > + <!-- Interval to check this account in milliseconds, > 600000 is every ten minutes --> > > + <interval>600000</interval> > > + </fetch> > > + </fetchpop> > > + > > + > > <!-- The James Spool Manager block --> > > <spoolmanager> > > <!-- number of spool threads --> > > @@ -119,7 +119,7 @@ > > <!-- Sample matching to kill a message (send to Null) --> > > <mailet match="RecipientIs=badboy@badhost" class="Null"/> > > > > - <!-- Send remaining mails to the transport processor for > either local or remote delivery --> > > + <!-- Send remaining mails to the transport processor for > either local or remote delivery --> > > <mailet match="All" class="ToProcessor"> > > <processor> transport </processor> > > </mailet> > > @@ -142,7 +142,7 @@ > > <!--<mailet match="All" class="NotifyPostmaster"/>--> > > </processor> > > > > - <!-- Processor CONFIGURATION SAMPLE: transport is a sample > custom processor for local or remote delivery --> > > + <!-- Processor CONFIGURATION SAMPLE: transport is a sample > custom processor for local or remote delivery --> > > <processor name="transport"> > > > > <!-- Is the recipient is for a local account, deliver it > locally --> > > @@ -153,7 +153,7 @@ > > <processor>error</processor> > > </mailet> > > > > - <!-- CHECKME! Anti-relay mailet: Add your network address > here, > > + <!-- CHECKME! Anti-relay mailet: Add your network address > here, > > e.g. "RemoteAddrNotInNetwork=127.0.0.1, abc.de.*, > 192.168.0.*"--> > > > > <!-- This matcher-mailet pair can prevent relaying... > > @@ -244,7 +244,7 @@ > > autodetect is TRUE, James will attempt to discover its > own name OR > > use 'localhost'. If autodetect is FALSE, James will use > the value > > given OR 'localhost' --> > > - <helloName autodetect="TRUE">myMailServer</helloName> > > + <helloName autodetect="true">myMailServer</helloName> > > <administrator_accounts> > > <!-- CHECKME! Change the default password! --> > > <!-- FILL ME!!!!!! You must provide a password for your > administrator accounts (cannot be blank) --> > > @@ -254,9 +254,9 @@ > > </handler> > > </remotemanager> > > > > - <!-- The POP3 server is enabled by default --> > > - <!-- Disabling blocks will stop them from listening, --> > > - <!-- but does not free as many resources as removing them would --> > > + <!-- The POP3 server is enabled by default --> > > + <!-- Disabling blocks will stop them from listening, --> > > + <!-- but does not free as many resources as removing them would -- > > > > <pop3server enabled="true"> > > <!-- port 995 is the well-known/IANA registered port for POP3S > ie over SSL/TLS --> > > <!-- port 100 is the well-known/IANA registered port for > Standard POP3 --> > > @@ -273,14 +273,14 @@ > > autodetect is TRUE, James will attempt to discover its > own name OR > > use 'localhost'. If autodetect is FALSE, James will use > the value > > given OR 'localhost' --> > > - <helloName autodetect="TRUE">myMailServer</helloName> > > + <helloName autodetect="true">myMailServer</helloName> > > <connectiontimeout>120000</connectiontimeout> > > </handler> > > </pop3server> > > > > - <!-- The SMTP server is enabled by default --> > > - <!-- Disabling blocks will stop them from listening, --> > > - <!-- but does not free as many resources as removing them would --> > > + <!-- The SMTP server is enabled by default --> > > + <!-- Disabling blocks will stop them from listening, --> > > + <!-- but does not free as many resources as removing them would -- > > > > <smtpserver enabled="true"> > > <port>25</port> > > > > @@ -295,7 +295,7 @@ > > autodetect is TRUE, James will attempt to discover its > own name OR > > use 'localhost'. If autodetect is FALSE, James will use > the value > > given OR 'localhost' --> > > - <helloName autodetect="TRUE">myMailServer</helloName> > > + <helloName autodetect="true">myMailServer</helloName> > > <connectiontimeout>360000</connectiontimeout> > > <!-- uncomment this if you want > > SMTP AUTH support. This is useful if you have users who > need to use > > @@ -313,9 +313,9 @@ > > </handler> > > </smtpserver> > > > > - <!-- The NNTP server is enabled by default --> > > - <!-- Disabling blocks will stop them from listening, --> > > - <!-- but does not free as many resources as removing them would --> > > + <!-- The NNTP server is enabled by default --> > > + <!-- Disabling blocks will stop them from listening, --> > > + <!-- but does not free as many resources as removing them would -- > > > > <nntpserver enabled="true"> > > <!-- port 563 is the well-known/IANA registered port for nntp > over SSL/TLS --> > > <!-- port 119 is the well-known/IANA registered port for > Standard nntp --> > > @@ -332,16 +332,13 @@ > > autodetect is TRUE, James will attempt to discover its own > name OR > > use 'localhost'. If autodetect is FALSE, James will use > the value > > given OR 'localhost' --> > > - <helloName autodetect="TRUE">myMailServer</helloName> > > + <helloName autodetect="true">myMailServer</helloName> > > <connectiontimeout>120000</connectiontimeout> > > + <!-- Set the authRequired value to true to enable > authenticated NNTP --> > > + <authRequired>false</authRequired> > > </handler> > > </nntpserver> > > > > - <nntpauth> > > - <!-- make this true, if you want only authenticated users to > access NNTP--> > > - <authRequired>false</authRequired> > > - </nntpauth> > > - > > <nntp-repository> > > <!-- make this true to disallow posting to all newsgroups--> > > <readOnly>false</readOnly> > > @@ -460,8 +457,8 @@ > > User repositories are required for the following purposes: > > - holding information about Users of the James mail server > > - holding lists of users for the listserv mailet > > - Currently, 2 different storage options are available: > > - - file-based storage using Java serialisation > > + Currently, two different storage options are available: > > + - file-based storage using Java serialization > > - database-backed storage > > (Use of database or file-system is defined on a "per-repository" > basis) > > Note: Two user repositories are required for default > configuration: > > @@ -533,8 +530,19 @@ > > </data-sources> > > </database-connections> > > > > - <!-- Configuration for Cornerstone Blocks only after here NOTHING > BELOW THIS SHOULD NEED CHANGING, > > - (unless you want secure sockets (TLS)) --> > > + <!-- Configuration for Cornerstone Services --> > > + <!-- --> > > + <!-- For a simple configuration, nothing beneath this line should > require --> > > + <!-- alteration. --> > > + <!-- --> > > + <!-- You will need to adjust the Socket Manager service > configuration if you want --> > > + <!-- to enable secure sockets (TLS) for any James service. > --> > > + <!-- --> > > + <!-- Complex or high volume configurations may require changes to > the parameters --> > > + <!-- in this section. Please read the James and Avalon > documentation before --> > > + <!-- attempting to adjust this section. --> > > + <!-- --> > > + > > <!-- The Storage block --> > > <objectstorage> > > <repositories> > > @@ -566,7 +574,42 @@ > > </repository> > > </repositories> > > </objectstorage> > > + <!-- The Connection Manager block --> > > + <!-- --> > > + <!-- The idle-timeout is the number of milliseconds that it will > take for idle --> > > + <!-- client connections managed by this connection manager to be > marked at timed out. --> > > + <!-- If no value is specified, the value defaults to 5 minutes, > 300000 milliseconds --> > > + <!-- A value of 0 means that client sockets will not timeout. --> > > + <!-- --> > > + <!-- The max-connections parameter specifies the maximum number of > client connections --> > > + <!-- that this connection manager will allow per managed server > socket. --> > > + <!-- If no value is specified, the value defaults to 30. --> > > + <!-- A value of 0 means that there is no limit imposed by the > connection manager, although --> > > + <!-- resource limitations imposed by other components (i.e. max # > of threads) may --> > > + <!-- serve to limit the number of open connections. --> > > + <!-- --> > > + <connections> > > + <idle-timeout>300000<idle-timeout> > > + <max-connections>30<max-connections> > > + </connections> > > <!-- The Socket Manager block --> > > + <!-- --> > > + <!-- The server-sockets element has a number of factory sub- > elements. --> > > + <!-- Each of the factory elements has a name and class attribute -- > > > > + <!-- The name attribute for each factory element must be unique. - > -> > > + <!-- The class attribute is the name of a class that implements the > --> > > + <!-- interface > org.apache.avalon.cornerstone.services.ServerSocketFactory --> > > + <!-- Specific factory elements may require some sub-elements. This > is --> > > + <!-- factory class dependent. --> > > + <!-- --> > > + <!-- The client-sockets element has a number of factory sub- > elements. --> > > + <!-- Each of the factory elements has a name and class attribute -- > > > > + <!-- The name attribute for each factory element must be unique. - > -> > > + <!-- The class attribute is the name of a class that implements the > --> > > + <!-- interface org.apache.avalon.cornerstone.services.SocketFactory > --> > > + <!-- Specific factory elements may require some sub-elements. This > is --> > > + <!-- factory class dependent. --> > > + <!-- --> > > <sockets> > > <server-sockets> > > <factory name="plain" > class="org.apache.avalon.cornerstone.blocks.sockets.DefaultServerSocketF ac > tory"/> > > @@ -592,7 +635,7 @@ > > <priority>5</priority> > > <!-- are threads daemon threads ? --> > > <is-daemon>false</is-daemon> > > - <max-threads>40</max-threads> > > + <max-threads>100</max-threads> > > <!-- these are ignored at the moment but will be fixed in > later revisions --> > > <min-threads>20</min-threads> > > <min-spare-threads>20</min-spare-threads> > > > > > > > > 1.1 jakarta- > james/src/java/org/apache/james/util/connection/ServerConnection.java > > > > Index: ServerConnection.java > > =================================================================== > > /* > > * Copyright (C) The Apache Software Foundation. All rights reserved. > > * > > * This software is published under the terms of the Apache Software > License > > * version 1.1, a copy of which has been included with this > distribution in > > * the LICENSE.txt file. > > */ > > package org.apache.james.util.connection; > > > > import java.io.IOException; > > import java.io.InterruptedIOException; > > import java.net.ServerSocket; > > import java.net.Socket; > > import java.net.SocketException; > > import java.util.ArrayList; > > import java.util.Iterator; > > import java.util.List; > > > > import > org.apache.avalon.cornerstone.services.connection.ConnectionHandler; > > import > org.apache.avalon.cornerstone.services.connection.ConnectionHandlerFacto ry > ; > > import org.apache.avalon.excalibur.thread.ThreadPool; > > import org.apache.avalon.framework.component.Component; > > import org.apache.avalon.framework.logger.AbstractLogEnabled; > > > > > > /** > > * Represents a single server socket managed by a connection manager. > > * The connection manager will spawn a single ServerConnection for each > > * server socket that the connection manager is managing. > > * > > * @author Andrei Ivanov > > * @author Peter M. Goldstein <[EMAIL PROTECTED]> > > */ > > public class ServerConnection extends AbstractLogEnabled > > implements Component, Runnable { > > > > /** > > * This is a hack to deal with the fact that there appears to be > > * no platform-independent way to break out of a ServerSocket > > * accept() call. On some platforms closing either the > ServerSocket > > * itself, or its associated InputStream, causes the accept > > * method to exit. Unfortunately, this behavior is not consistent > > * across platforms. The deal with this, we introduce a polling > > * loop of 20 seconds for the server socket. This introduces a > > * cost across platforms, but is necessary to maintain cross- > platform > > * functionality. > > */ > > private static int POLLING_INTERVAL = 20*1000; > > > > /** > > * The server socket which this connection is managing > > */ > > private ServerSocket serverSocket; > > > > /** > > * The connection handler factory that generates connection > > * handlers to manage client connections to this server socket > > */ > > private ConnectionHandlerFactory handlerFactory; > > > > /** > > * The thread pool used to spawn individual threads used to manage > each > > * client connection. > > */ > > private ThreadPool connThreadPool; > > > > /** > > * The timeout for client sockets spawned off this connection. > > */ > > private int socketTimeout; > > > > /** > > * The maximum number of open client connections that this server > > * connection will allow. > > */ > > private int maxOpenConn; > > > > /** > > * A collection of client connection runners. > > */ > > private final ArrayList clientConnectionRunners = new ArrayList(); > > > > /** > > * The current number of open client connections. > > */ > > private int openConnections = 0; > > > > /** > > * The thread used to manage this server connection. > > */ > > private Thread serverConnectionThread; > > > > /** > > * The sole constructor for a ServerConnection. > > * > > * @param serverSocket the ServerSocket associated with this > ServerConnection > > * @param handlerFactory the factory that generates > ConnectionHandlers for the client > > * connections spawned off this > ServerConnection > > * @param threadPool the ThreadPool used to obtain handler threads > > * @param timeout the client idle timeout for this > ServerConnection's client connections > > * @param maxOpenConn the maximum number of open client connections > allowed for this > > * ServerConnection > > */ > > public ServerConnection(ServerSocket serverSocket, > > ConnectionHandlerFactory handlerFactory, > > ThreadPool threadPool, > > int timeout, > > int maxOpenConn) { > > this.serverSocket = serverSocket; > > this.handlerFactory = handlerFactory; > > connThreadPool = threadPool; > > socketTimeout = timeout; > > this.maxOpenConn = maxOpenConn; > > } > > > > /** > > * The dispose operation is called by the owning ConnectionManager > > * at the end of its lifecycle. Cleans up the server connection, > forcing > > * everything to finish. > > */ > > public void dispose() { > > if (getLogger().isDebugEnabled()) { > > getLogger().debug("Disposing server connection..." + > this.toString()); > > } > > synchronized( this ) { > > if( null != serverConnectionThread ) { > > // Execution of this block means that the run() method > > // hasn't finished yet. So we interrupt the thread > > // to terminate run() and wait for the run() method > > // to finish. The notifyAll() at the end of run() will > > // wake this thread and allow dispose() to end. > > Thread thread = serverConnectionThread; > > serverConnectionThread = null; > > thread.interrupt(); > > try { > > serverSocket.close(); > > } catch (IOException ie) { > > // Ignored - we're doing this to break out of the > > // accept. This minimizes the time required to > > // shutdown the server. Unfortunately, this is > > // not guaranteed to work on all platforms. See > > // the comments for POLLING_INTERVAL > > } > > try { > > if (POLLING_INTERVAL > 0) { > > wait(2L*POLLING_INTERVAL); > > } else { > > wait(); > > } > > } catch (InterruptedException ie) { > > // Expected - just complete dispose() > > } > > } > > } > > > > getLogger().debug("Closed server connection - cleaning up > clients - " + this.toString()); > > > > synchronized (clientConnectionRunners) { > > Iterator runnerIterator = > clientConnectionRunners.iterator(); > > while( runnerIterator.hasNext() ) > > { > > ClientConnectionRunner runner = > (ClientConnectionRunner)runnerIterator.next(); > > runner.dispose(); > > runner = null; > > } > > clientConnectionRunners.clear(); > > openConnections = 0; > > } > > > > getLogger().debug("Cleaned up clients - " + this.toString()); > > > > } > > > > /** > > * Adds a ClientConnectionRunner to the set managed by this > ServerConnection object. > > * > > * @param clientConnectionRunner the ClientConnectionRunner to be > added > > */ > > private void addClientConnectionRunner(ClientConnectionRunner > clientConnectionRunner) { > > synchronized (clientConnectionRunners) { > > clientConnectionRunners.add(clientConnectionRunner); > > openConnections++; > > } > > } > > > > /** > > * Removes a ClientConnectionRunner from the set managed by this > ServerConnection object. > > * > > * @param clientConnectionRunner the ClientConnectionRunner to be > removed > > */ > > private void removeClientConnectionRunner(ClientConnectionRunner > clientConnectionRunner) { > > synchronized (clientConnectionRunners) { > > clientConnectionRunners.remove(clientConnectionRunner); > > openConnections--; > > } > > } > > > > /** > > * Provides the body for the thread of execution for a > ServerConnection. > > * Connections made to the server socket are passed to an > appropriate, > > * newly created, ClientConnectionRunner > > */ > > public void run() { > > serverConnectionThread = Thread.currentThread(); > > > > int ioExceptionCount = 0; > > try { > > serverSocket.setSoTimeout(POLLING_INTERVAL); > > } catch (SocketException se) { > > // Ignored - for the moment > > } > > while( null != serverConnectionThread && > !serverConnectionThread.isInterrupted() ) { > > try { > > Socket clientSocket = null; > > try { > > clientSocket = serverSocket.accept(); > > } catch( InterruptedIOException iioe ) { > > // This exception is expected upon ServerConnection > shutdown. > > // See the POLLING_INTERVAL comment > > continue; > > } catch( IOException se ) { > > if (ioExceptionCount > 0) { > > getLogger().error( "Fatal exception while > listening on server socket. Terminating connection.", se ); > > break; > > } else { > > continue; > > } > > } catch( SecurityException se ) { > > getLogger().error( "Fatal exception while listening > on server socket. Terminating connection.", se ); > > break; > > } > > ClientConnectionRunner runner = null; > > synchronized (clientConnectionRunners) { > > if ((maxOpenConn > 0) && (openConnections >= > maxOpenConn)) { > > if (getLogger().isWarnEnabled()) { > > getLogger().warn("Maximum number of open > connections exceeded - refusing connection. Current number of connections > is " + openConnections); > > } > > try { > > clientSocket.close(); > > } catch (IOException ignored) { > > // We ignore this exception, as we already > have an error condition. > > } > > continue; > > } else { > > clientSocket.setSoTimeout(socketTimeout); > > runner = > > new ClientConnectionRunner(clientSocket, > handlerFactory); > > } > > } > > setupLogger( runner ); > > connThreadPool.execute( runner ); > > } catch( IOException ioe ) { > > getLogger().error( "Exception accepting connection", > ioe ); > > } catch( Exception e ) { > > getLogger().error( "Exception executing client > connection runner: " + e.getMessage() ); > > } > > } > > synchronized( this ) { > > serverConnectionThread = null; > > notifyAll(); > > } > > } > > > > /** > > * An inner class to provide the actual body of the thread of > execution > > * that occurs upon a client connection. > > * > > * @author Andrei Ivanov > > * @author Peter M. Goldstein <[EMAIL PROTECTED]> > > */ > > class ClientConnectionRunner extends AbstractLogEnabled > > implements Runnable, Component { > > > > /** > > * The Socket that this client connection is using for > transport. > > */ > > private Socket clientSocket; > > > > /** > > * The thread of execution associated with this client > connection. > > */ > > private Thread clientSocketThread; > > > > /** > > * The ConnectionHandlerFactory that generates a > ConnectionHandler for > > * this client connection. > > */ > > private ConnectionHandlerFactory > clientConnectionHandlerFactory; > > > > /** > > * The constructor for a ClientConnectionRunner. > > * > > * @param socket the client socket associated with this > ClientConnectionRunner > > * @param handlerFactory the factory that generates > ConnectionHandlers for this > > * connection > > */ > > public ClientConnectionRunner(Socket socket, > > ConnectionHandlerFactory > handlerFactory) { > > clientSocket = socket; > > clientConnectionHandlerFactory = handlerFactory; > > } > > > > /** > > * The dispose operation that terminates the runner. Should > only be > > * called by the ServerConnection that owns the > ClientConnectionRunner > > */ > > public void dispose() { > > synchronized( this ) { > > if (null != clientSocketThread) { > > // Execution of this block means that the run() > method > > // hasn't finished yet. So we interrupt the thread > > // to terminate run() and wait for the run() method > > // to finish. The notifyAll() at the end of run() > will > > // wake this thread and allow dispose() to end. > > clientSocketThread.interrupt(); > > clientSocketThread = null; > > try { > > wait(); > > } catch (InterruptedException ie) { > > // Expected - return from the method > > } > > } > > } > > } > > > > /** > > * Provides the body for the thread of execution dealing with a > particular client > > * connection. An appropriate ConnectionHandler is created, > applied, executed, > > * and released. > > */ > > public void run() { > > ConnectionHandler handler = null; > > try { > > clientSocketThread = Thread.currentThread(); > > ServerConnection.this.addClientConnectionRunner(this); > > > > handler = > clientConnectionHandlerFactory.createConnectionHandler(); > > String connectionString = null; > > if( getLogger().isDebugEnabled() ) { > > connectionString = getConnectionString(); > > String message = "Starting " + connectionString; > > getLogger().debug( message ); > > } > > > > handler.handleConnection(clientSocket); > > > > if( getLogger().isDebugEnabled() ) { > > String message = "Ending " + connectionString; > > getLogger().debug( message ); > > } > > } catch( Exception e ) { > > getLogger().warn( "Error handling connection", e ); > > } finally { > > > > // Close the underlying socket > > try { > > clientSocket.close(); > > } catch( IOException ioe ) { > > getLogger().warn( "Error shutting down connection", > ioe ); > > } > > > > // Release the handler and kill the reference to the > handler factory > > if (handler != null) { > > > clientConnectionHandlerFactory.releaseConnectionHandler( handler ); > > handler = null; > > } > > clientConnectionHandlerFactory = null; > > > > // Remove this runner from the list of active > connections. > > > ServerConnection.this.removeClientConnectionRunner(this); > > > > // Null out the thread, notify other threads to > encourage > > // a context switch > > synchronized( this ) { > > clientSocketThread = null; > > notifyAll(); > > } > > } > > } > > > > /** > > * Helper method to return a formatted string with connection > transport information. > > * > > * @return a formatted string > > */ > > private String getConnectionString() { > > if (clientSocket == null) { > > return "invalid socket"; > > } > > StringBuffer connectionBuffer > > = new StringBuffer(256) > > .append("connection on ") > > > .append(clientSocket.getLocalAddress().getHostAddress().toString()) > > .append(":") > > .append(clientSocket.getLocalPort()) > > .append(" from ") > > > .append(clientSocket.getInetAddress().getHostAddress().toString()) > > .append(":") > > .append(clientSocket.getPort()); > > return connectionBuffer.toString(); > > } > > } > > } > > > > > > > > > > > > 1.1 jakarta- > james/src/java/org/apache/james/util/connection/SimpleConnectionManager. ja > va > > > > Index: SimpleConnectionManager.java > > =================================================================== > > /* > > * Copyright (C) The Apache Software Foundation. All rights reserved. > > * > > * This software is published under the terms of the Apache Software > License > > * version 1.1, a copy of which has been included with this > distribution in > > * the LICENSE file. > > */ > > package org.apache.james.util.connection; > > > > import java.net.ServerSocket; > > import java.util.HashMap; > > > > import org.apache.avalon.excalibur.thread.ThreadPool; > > > > import > org.apache.avalon.cornerstone.services.connection.ConnectionHandlerFacto ry > ; > > import > org.apache.avalon.cornerstone.services.connection.ConnectionManager; > > import org.apache.avalon.cornerstone.services.threads.ThreadManager; > > import org.apache.avalon.framework.component.ComponentException; > > import org.apache.avalon.framework.component.ComponentManager; > > import org.apache.avalon.framework.component.Composable; > > import org.apache.avalon.framework.configuration.Configurable; > > import org.apache.avalon.framework.configuration.Configuration; > > import > org.apache.avalon.framework.configuration.ConfigurationException; > > > > import org.apache.avalon.framework.activity.Disposable; > > import org.apache.avalon.framework.logger.AbstractLogEnabled; > > > > > > /** > > * An implementation of ConnectionManager that supports configurable > > * idle timeouts and a configurable value for the maximum number of > > * client connections to a particular port. > > * > > * @author Andrei Ivanov > > * @author Peter M. Goldstein <[EMAIL PROTECTED]> > > */ > > public class SimpleConnectionManager extends AbstractLogEnabled > > implements ConnectionManager, Composable, Configurable, Disposable > { > > > > /** > > * The default value for client socket idle timeouts. The > > * Java default is 0, meaning no timeout. That's dangerous > > * for a connection handler like this one, because it can > > * easily lead to consumption of network resources. So we > > * allow users to configure the system to allow no timeout, > > * but if no timeout is specified in the configuration, we > > * use a timeout of 5 minutes. > > */ > > private static final int DEFAULT_SOCKET_TIMEOUT = 5 * 60 * 1000; > > > > /** > > * The default value for the maximum number of allowed client > > * connections. > > */ > > private static final int DEFAULT_MAX_CONNECTIONS = 30; > > > > /** > > * The map of connection name / server connections managed by this > connection > > * manager. > > */ > > private final HashMap connectionMap = new HashMap(); > > > > /** > > * The idle timeout for the individual sockets spawed from the > server socket. > > */ > > protected int timeout = 0; > > > > /** > > * The maximum number of client connections allowed per server > connection. > > */ > > protected int maxOpenConn = 0; > > > > /** > > * The ThreadManager component that is used to provide a default > thread pool. > > */ > > private ThreadManager threadManager; > > > > /** > > * Whether the SimpleConnectionManager has been disposed. > > */ > > private volatile boolean disposed = false; > > > > /** > > * @see > org.apache.avalon.framework.configuration.Configurable#configure(Configu ra > tion) > > */ > > public void configure(final Configuration configuration) throws > ConfigurationException { > > timeout = configuration.getChild("idle- > timeout").getValueAsInteger(DEFAULT_SOCKET_TIMEOUT); > > maxOpenConn = configuration.getChild("max- > connections").getValueAsInteger(DEFAULT_MAX_CONNECTIONS); > > > > if (timeout < 0) { > > StringBuffer exceptionBuffer = > > new StringBuffer(128) > > .append("Specified socket timeout value of ") > > .append(timeout) > > .append(" is not a legal value."); > > throw new > ConfigurationException(exceptionBuffer.toString()); > > } > > > > if (maxOpenConn < 0) { > > StringBuffer exceptionBuffer = > > new StringBuffer(128) > > .append("Specified maximum number of open > connections of ") > > .append(maxOpenConn) > > .append(" is not a legal value."); > > throw new > ConfigurationException(exceptionBuffer.toString()); > > } > > > > if (getLogger().isDebugEnabled()) { > > getLogger().debug("Connection timeout is " > > + (timeout == 0 ? "unlimited" : > Long.toString(timeout))); > > getLogger().debug("The maximum number of simultaneously > open connections is " > > + (maxOpenConn == 0 ? "unlimited" : > Integer.toString(maxOpenConn))); > > } > > } > > > > /** > > * @see > org.apache.avalon.framework.component.Composable#compose(ComponentManage r) > > */ > > public void compose(ComponentManager componentManager) > > throws ComponentException { > > threadManager = (ThreadManager)componentManager.lookup( > ThreadManager.ROLE ); > > } > > > > /** > > * Disconnects all the underlying ServerConnections > > */ > > public void dispose() { > > disposed = true; > > if (getLogger().isDebugEnabled()) { > > getLogger().debug("Starting SimpleConnectionManager > dispose..."); > > } > > final String[] names = > (String[])connectionMap.keySet().toArray( new String[ 0 ] ); > > for( int i = 0; i < names.length; i++ ) { > > try { > > if (getLogger().isDebugEnabled()) { > > getLogger().debug("Disconnecting ServerConnection " > + names[i]); > > } > > disconnect( names[ i ], true); > > } catch( final Exception e ) { > > getLogger().warn( "Error disconnecting " + names[ i ], > e ); > > } > > } > > if (getLogger().isDebugEnabled()) { > > getLogger().debug("Finishing SimpleConnectionManager > dispose..."); > > } > > } > > > > /** > > * Start managing a connection. > > * Management involves accepting connections and farming them out > to threads > > * from pool to be handled. > > * > > * @param name the name of connection > > * @param socket the ServerSocket from which to > > * @param handlerFactory the factory from which to acquire handlers > > * @param threadPool the thread pool to use > > * @exception Exception if an error occurs > > */ > > public void connect( String name, > > ServerSocket socket, > > ConnectionHandlerFactory handlerFactory, > > ThreadPool threadPool ) > > throws Exception { > > > > if (disposed) { > > throw new IllegalStateException("Connection manager has > already been shutdown."); > > } > > if( null != connectionMap.get( name ) ) { > > throw new IllegalArgumentException( "Connection already > exists with name " + > > name ); > > } > > > > ServerConnection runner = new ServerConnection(socket, > handlerFactory, threadPool, timeout, maxOpenConn); > > setupLogger( runner ); > > connectionMap.put( name, runner ); > > threadPool.execute(runner); > > } > > > > /** > > * Start managing a connection. > > * This is similar to other connect method except that it uses > default thread pool. > > * > > * @param name the name of connection > > * @param socket the ServerSocket from which to > > * @param handlerFactory the factory from which to acquire handlers > > * @exception Exception if an error occurs > > */ > > public void connect( String name, > > ServerSocket socket, > > ConnectionHandlerFactory handlerFactory ) > > throws Exception > > { > > connect( name, socket, handlerFactory, > threadManager.getDefaultThreadPool() ); > > } > > > > > > /** > > * This shuts down all handlers and socket, waiting for each to > gracefully shutdown. > > * > > * @param name the name of connection > > * @exception Exception if an error occurs > > */ > > public void disconnect( final String name ) > > throws Exception { > > > > disconnect( name, false ); > > } > > > > /** > > * This shuts down a connection. > > * If tearDown is true then it will forcefully the connection and > try > > * to return as soon as possible. Otherwise it will behave the same > as > > * void disconnect( String name ); > > * > > * @param name the name of connection > > * @param tearDown if true will forcefully tear down all handlers > > * @exception Exception if an error occurs > > */ > > public void disconnect( final String name, final boolean tearDown ) > > throws Exception { > > > > ServerConnection connection = > (ServerConnection)connectionMap.remove( name ); > > if( null == connection ) { > > throw new IllegalArgumentException( "No such connection > with name " + > > name ); > > } > > > > // TODO: deal with tear down > > connection.dispose(); > > } > > > > } > > > > > > > > 1.1 jakarta- > james/src/java/org/apache/james/util/connection/SimpleConnectionManager. xi > nfo > > > > Index: SimpleConnectionManager.xinfo > > =================================================================== > > <?xml version="1.0"?> > > > > > > <blockinfo> > > > > <!-- section to describe block --> > > <block> > > <name>SimpleConnectionManager</name> > > <version>1.0</version> > > </block> > > > > <!-- services that are offered by this block --> > > <services> > > <service > name="org.apache.avalon.cornerstone.services.connection.ConnectionManage r" > /> > > </services> > > > > <!-- services that are required by this block --> > > <dependencies> > > <dependency> > > <service > name="org.apache.avalon.cornerstone.services.threads.ThreadManager"/> > > </dependency> > > </dependencies> > > > > </blockinfo> > > > > > > > > 1.1 jakarta- > james/src/java/org/apache/james/util/connection/package.html > > > > Index: package.html > > =================================================================== > > <body> > > <p>Provides classes that implement Avalon Cornerstone connection > services. It would be desirable to have these classes eventually moved to > Cornerstone.</p> > > </body> > > > > > > > > > >-- > >To unsubscribe, e-mail: <mailto:james-dev- > [EMAIL PROTECTED]> > >For additional commands, e-mail: <mailto:james-dev- > [EMAIL PROTECTED]> > > > > > > > > -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
