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.handlers;
9   
10  import java.net.Socket;
11  import java.util.Map;
12  import java.util.Hashtable;
13  import java.util.Collection;
14  import org.codehaus.spice.netserve.connection.RequestHandler;
15  import org.codehaus.spice.threadpool.ThreadPool;
16  import org.codehaus.spice.threadpool.ThreadControl;
17  
18  /***
19   * A Handler that uses a thread from a pool for each different request.
20   *
21   * @author Peter Donald
22   * @version $Revision: 1.2 $ $Date: 2004/03/21 23:42:58 $
23   */
24  public class ThreadPerRequestHandler
25      extends DelegatingRequestHandler
26  {
27      /***
28       * A map of Socket->ThreadControl.
29       */
30      private final Map m_controlMap = new Hashtable();
31  
32      /***
33       * the thread pool that used to handle requests.
34       */
35      private final ThreadPool m_threadPool;
36  
37      /***
38       * Create handler.
39       *
40       * @param handler the underlying handler
41       * @param threadPool the thread pool to use to create handler threads
42       */
43      public ThreadPerRequestHandler( final RequestHandler handler,
44                                      final ThreadPool threadPool )
45      {
46          super( handler );
47          if( null == threadPool )
48          {
49              throw new NullPointerException( "threadPool" );
50          }
51          m_threadPool = threadPool;
52      }
53  
54      /***
55       * Execute each request in a separate thread.
56       *
57       * @param socket the socket to handle
58       */
59      public void handleConnection( final Socket socket )
60      {
61          final Runnable runnable = createRunnable( socket );
62          final ThreadControl control = m_threadPool.execute( runnable );
63          m_controlMap.put( socket, control );
64      }
65  
66      /***
67       * Remove ThreadControl from list of active threads.
68       *
69       * @param socket the socket
70       */
71      protected void endConnection( Socket socket )
72      {
73          m_controlMap.remove( socket );
74          super.endConnection( socket );
75      }
76  
77      /***
78       * Shutdown all requests including those executing in thread pool.
79       *
80       * @param timeout the timeout
81       */
82      public void shutdown( final long timeout )
83      {
84          markAsShutdown();
85          final ThreadControl[] controls;
86          synchronized( m_controlMap )
87          {
88              final Collection collection = m_controlMap.values();
89              controls = (ThreadControl[])collection.
90                  toArray( new ThreadControl[ collection.size() ] );
91          }
92          for( int i = 0; i < controls.length; i++ )
93          {
94              final ThreadControl control = controls[ i ];
95              if( !control.isFinished() )
96              {
97                  control.interrupt();
98              }
99          }
100         super.shutdown( timeout );
101         for( int i = 0; i < controls.length; i++ )
102         {
103             final ThreadControl control = controls[ i ];
104             if( !control.isFinished() )
105             {
106                 try
107                 {
108                     control.join( timeout );
109                 }
110                 catch( final InterruptedException ie )
111                 {
112                     //Ignore
113                 }
114             }
115         }
116     }
117 }