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.io.IOException;
011: import java.net.Socket;
012: import java.util.HashSet;
013: import java.util.Set;
014: import org.codehaus.spice.netserve.connection.RequestHandler;
015:
016: /**
017: * Abstract base class for request handlers.
018: *
019: * @author Peter Donald
020: * @version $Revision: 1.2 $ $Date: 2004/03/21 23:42:58 $
021: */
022: public abstract class AbstractRequestHandler implements RequestHandler {
023: /**
024: * The set of active requests.
025: */
026: private final Set m_activeRequests = new HashSet();
027:
028: /**
029: * True if shutdown() has been called.
030: */
031: private boolean m_shutdown;
032:
033: /**
034: * Handle a connection.
035: *
036: * @param socket the socket
037: */
038: public void handleConnection(Socket socket) {
039: performRequest(socket);
040: }
041:
042: /**
043: * @see RequestHandler#shutdown
044: */
045: public void shutdown(final long timeout) {
046: markAsShutdown();
047: final Thread[] threads;
048: synchronized (this ) {
049: threads = (Thread[]) m_activeRequests
050: .toArray(new Thread[m_activeRequests.size()]);
051: }
052: for (int i = 0; i < threads.length; i++) {
053: final Thread thread = threads[i];
054: thread.interrupt();
055: }
056: final long now = System.currentTimeMillis();
057: final long then = now + timeout;
058:
059: while (System.currentTimeMillis() < then || 0 == timeout) {
060: synchronized (this ) {
061: if (0 == m_activeRequests.size()) {
062: return;
063: }
064: try {
065: wait(timeout);
066: } catch (final InterruptedException ie) {
067: //Ignore
068: }
069: }
070: }
071: }
072:
073: /**
074: * Mark request handler as shutdown.
075: */
076: protected void markAsShutdown() {
077: m_shutdown = true;
078: }
079:
080: /**
081: * Return true if handler has been shutdown.
082: *
083: * @return true if handler has been shutdown.
084: */
085: protected boolean isShutdown() {
086: return m_shutdown;
087: }
088:
089: /**
090: * Perform the request for socket by delegating to
091: * underlying handler.
092: *
093: * @param socket the socket to handle
094: */
095: protected void performRequest(final Socket socket) {
096: synchronized (this ) {
097: m_activeRequests.add(Thread.currentThread());
098: }
099: setupThreadName(socket);
100: try {
101: doPerformRequest(socket);
102: } catch (final Throwable t) {
103: errorHandlingConnection(socket, t);
104: } finally {
105: endConnection(socket);
106: synchronized (this ) {
107: m_activeRequests.remove(Thread.currentThread());
108: notifyAll();
109: }
110: }
111: }
112:
113: /**
114: * Method implemented to actually do the work.
115: *
116: * @param socket the socket
117: * @throws Exception if an error occurs
118: */
119: protected abstract void doPerformRequest(Socket socket)
120: throws Exception;
121:
122: /**
123: * Setup the name of the thread.
124: *
125: * @param socket the socket associated with request
126: */
127: protected void setupThreadName(final Socket socket) {
128: final String name = getThreadName(socket);
129: Thread.currentThread().setName(name);
130: }
131:
132: /**
133: * End connection for socket.
134: *
135: * @param socket the socket
136: */
137: protected void endConnection(final Socket socket) {
138: if (socket.isConnected()) {
139: try {
140: socket.close();
141: } catch (final IOException ioe) {
142: errorClosingConnection(socket, ioe);
143: }
144: }
145: }
146:
147: /**
148: * Create Runnable to perform the request.
149: *
150: * @param socket the socket to handle
151: * @return thee runnable
152: */
153: protected Runnable createRunnable(final Socket socket) {
154: return new Runnable() {
155: public void run() {
156: performRequest(socket);
157: }
158: };
159: }
160:
161: /**
162: * Return the name should be set for current thread.
163: *
164: * @param socket the socket being handled in thread
165: * @return the thread name.
166: */
167: protected String getThreadName(final Socket socket) {
168: if (socket.isConnected()) {
169: return "RequestHandler for "
170: + socket.getInetAddress().getHostAddress() + ":"
171: + socket.getPort();
172: } else {
173: return "RequestHandler for " + socket;
174: }
175: }
176:
177: /**
178: * Notify handler of an error handling socket.
179: *
180: * @param socket the socket
181: * @param t the error
182: */
183: protected void errorHandlingConnection(final Socket socket,
184: final Throwable t) {
185: }
186:
187: /**
188: * Notify handler of an error closing socket.
189: *
190: * @param socket the socket
191: * @param t the error
192: */
193: protected void errorClosingConnection(final Socket socket,
194: final Throwable t) {
195: errorHandlingConnection(socket, t);
196: }
197: }
|