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]>

Reply via email to