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.DefaultConnectionManager" >
>  +         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.DefaultServerSocketFactory"/>
>  @@ -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.ConnectionHandlerFactory;
>  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.java
>  
>  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.ConnectionHandlerFactory;
>  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(Configuration)
>       */
>      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(ComponentManager)
>       */
>      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.xinfo
>  
>  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.ConnectionManager"/>
>    </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:[EMAIL PROTECTED]>
>For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
>
>
>  
>

Index: src/conf/james-config.xml
===================================================================
RCS file: /home/cvspublic/jakarta-james/src/conf/james-config.xml,v
retrieving revision 1.34
diff -u -r1.34 james-config.xml
--- src/conf/james-config.xml   7 Oct 2002 07:16:46 -0000       1.34
+++ src/conf/james-config.xml   8 Oct 2002 21:52:47 -0000
@@ -589,8 +589,8 @@
    <!-- serve to limit the number of open connections. -->
    <!-- -->
    <connections>
-      <idle-timeout>300000<idle-timeout>
-      <max-connections>30<max-connections>
+      <idle-timeout>300000</idle-timeout>
+      <max-connections>30</max-connections>
    </connections>
    <!-- The Socket Manager block -->
    <!-- -->

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to