001: /*
002: * Copyright (C) The Spice Group. All rights reserved.
003: *
004: * This software is published under the terms of the Spice
005: * Software License version 1.1, a copy of which has been included
006: * with this distribution in the LICENSE.txt file.
007: */
008: package org.codehaus.spice.netserve.connection.handlers;
009:
010: import java.net.Socket;
011: import java.util.Map;
012: import java.util.Hashtable;
013: import java.util.Collection;
014: import org.codehaus.spice.netserve.connection.RequestHandler;
015: import org.codehaus.spice.threadpool.ThreadPool;
016: import org.codehaus.spice.threadpool.ThreadControl;
017:
018: /**
019: * A Handler that uses a thread from a pool for each different request.
020: *
021: * @author Peter Donald
022: * @version $Revision: 1.2 $ $Date: 2004/03/21 23:42:58 $
023: */
024: public class ThreadPerRequestHandler extends DelegatingRequestHandler {
025: /**
026: * A map of Socket->ThreadControl.
027: */
028: private final Map m_controlMap = new Hashtable();
029:
030: /**
031: * the thread pool that used to handle requests.
032: */
033: private final ThreadPool m_threadPool;
034:
035: /**
036: * Create handler.
037: *
038: * @param handler the underlying handler
039: * @param threadPool the thread pool to use to create handler threads
040: */
041: public ThreadPerRequestHandler(final RequestHandler handler,
042: final ThreadPool threadPool) {
043: super (handler);
044: if (null == threadPool) {
045: throw new NullPointerException("threadPool");
046: }
047: m_threadPool = threadPool;
048: }
049:
050: /**
051: * Execute each request in a separate thread.
052: *
053: * @param socket the socket to handle
054: */
055: public void handleConnection(final Socket socket) {
056: final Runnable runnable = createRunnable(socket);
057: final ThreadControl control = m_threadPool.execute(runnable);
058: m_controlMap.put(socket, control);
059: }
060:
061: /**
062: * Remove ThreadControl from list of active threads.
063: *
064: * @param socket the socket
065: */
066: protected void endConnection(Socket socket) {
067: m_controlMap.remove(socket);
068: super .endConnection(socket);
069: }
070:
071: /**
072: * Shutdown all requests including those executing in thread pool.
073: *
074: * @param timeout the timeout
075: */
076: public void shutdown(final long timeout) {
077: markAsShutdown();
078: final ThreadControl[] controls;
079: synchronized (m_controlMap) {
080: final Collection collection = m_controlMap.values();
081: controls = (ThreadControl[]) collection
082: .toArray(new ThreadControl[collection.size()]);
083: }
084: for (int i = 0; i < controls.length; i++) {
085: final ThreadControl control = controls[i];
086: if (!control.isFinished()) {
087: control.interrupt();
088: }
089: }
090: super .shutdown(timeout);
091: for (int i = 0; i < controls.length; i++) {
092: final ThreadControl control = controls[i];
093: if (!control.isFinished()) {
094: try {
095: control.join(timeout);
096: } catch (final InterruptedException ie) {
097: //Ignore
098: }
099: }
100: }
101: }
102: }
|