View Javadoc

1   /*
2    * Copyright (C) The Spice Group. All rights reserved.
3    *
4    * This software is published under the terms of the Spice
5    * Software License version 1.1, a copy of which has been included
6    * with this distribution in the LICENSE.txt file.
7    */
8   package org.codehaus.spice.netserve.connection.impl;
9   
10  import java.io.IOException;
11  import java.io.InterruptedIOException;
12  import java.net.Socket;
13  
14  import org.codehaus.spice.netserve.connection.impl.AcceptorConfig;
15  import org.codehaus.spice.netserve.connection.impl.AcceptorMonitor;
16  
17  /***
18   * A helper class that manages acceptor for a single ServerSocket.
19   *
20   * @author Peter Donald
21   * @version $Revision: 1.2 $ $Date: 2004/03/21 23:42:59 $
22   */
23  class ConnectionAcceptor
24      implements Runnable
25  {
26      /***
27       * The configuration for acceptor.
28       */
29      private final AcceptorConfig m_config;
30  
31      /***
32       * The AcceptorMonitor for event notification.
33       */
34      private final AcceptorMonitor m_monitor;
35  
36      private boolean m_started;
37  
38      private boolean m_active;
39  
40      /***
41       * The thread in which the main accept loop is running.
42       * Setup at start of thread and set to null to shutdown
43       * acceptor.
44       */
45      private Thread m_thread;
46  
47      /***
48       * Create the acceptor.
49       *
50       * @param config the config for acceptor
51       * @param monitor the monitor
52       */
53      ConnectionAcceptor( final AcceptorConfig config,
54                          final AcceptorMonitor monitor )
55      {
56          if( null == config )
57          {
58              throw new NullPointerException( "config" );
59          }
60          if( null == monitor )
61          {
62              throw new NullPointerException( "monitor" );
63          }
64          m_config = config;
65          m_monitor = monitor;
66          m_monitor.acceptorCreated( m_config.getName(),
67                                     m_config.getServerSocket() );
68      }
69  
70      /***
71       * Return true if acceptor has started.
72       *
73       * @return true if acceptor has started.
74       */
75      synchronized boolean hasStarted()
76      {
77          return m_started;
78      }
79  
80      /***
81       * Shutdown the acceptor.
82       */
83      void close( final long timeout )
84      {
85          synchronized( this )
86          {
87              m_active = false;
88              m_monitor.acceptorClosing( m_config.getName(),
89                                         m_config.getServerSocket() );
90              m_thread.interrupt();
91              try
92              {
93                  wait( timeout );
94              }
95              catch( InterruptedException e )
96              {
97                  //ignore
98              }
99          }
100     }
101 
102     /***
103      * The main accept & handle loop for acceptor.
104      */
105     public void run()
106     {
107         //Setup thread to indicate that we are currently running
108         synchronized( this )
109         {
110             m_started = true;
111             m_active = true;
112             m_thread = Thread.currentThread();
113         }
114         while( isRunning() )
115         {
116             m_monitor.serverSocketListening( m_config.getName(),
117                                              m_config.getServerSocket() );
118             try
119             {
120                 final Socket socket = m_config.getServerSocket().accept();
121                 if( isRunning() )
122                 {
123                     m_config.getHandler().handleConnection( socket );
124                 }
125                 else
126                 {
127                     try
128                     {
129                         socket.close();
130                     }
131                     catch( final Exception e )
132                     {
133                         //Ignore
134                     }
135                 }
136             }
137             catch( final InterruptedIOException iioe )
138             {
139                 //Consume exception
140             }
141             catch( final IOException ioe )
142             {
143                 m_monitor.errorAcceptingConnection( m_config.getName(), ioe );
144             }
145         }
146 
147         shutdownServerSocket();
148         synchronized( this )
149         {
150             m_thread = null;
151             notifyAll();
152         }
153     }
154 
155     /***
156      * Utility method to shutdown serverSocket.
157      */
158     void shutdownServerSocket()
159     {
160         try
161         {
162             m_config.getServerSocket().close();
163         }
164         catch( final IOException ioe )
165         {
166             m_monitor.errorClosingServerSocket( m_config.getName(), ioe );
167         }
168     }
169 
170     /***
171      * Return true if the acceptor is currently running.
172      *
173      * @return true if the acceptor is currently running.
174      */
175     synchronized boolean isRunning()
176     {
177         return m_active;
178     }
179 }