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.impl;
009:
010: import java.io.IOException;
011: import java.io.InterruptedIOException;
012: import java.net.Socket;
013:
014: import org.codehaus.spice.netserve.connection.impl.AcceptorConfig;
015: import org.codehaus.spice.netserve.connection.impl.AcceptorMonitor;
016:
017: /**
018: * A helper class that manages acceptor for a single ServerSocket.
019: *
020: * @author Peter Donald
021: * @version $Revision: 1.2 $ $Date: 2004/03/21 23:42:59 $
022: */
023: class ConnectionAcceptor implements Runnable {
024: /**
025: * The configuration for acceptor.
026: */
027: private final AcceptorConfig m_config;
028:
029: /**
030: * The AcceptorMonitor for event notification.
031: */
032: private final AcceptorMonitor m_monitor;
033:
034: private boolean m_started;
035:
036: private boolean m_active;
037:
038: /**
039: * The thread in which the main accept loop is running.
040: * Setup at start of thread and set to null to shutdown
041: * acceptor.
042: */
043: private Thread m_thread;
044:
045: /**
046: * Create the acceptor.
047: *
048: * @param config the config for acceptor
049: * @param monitor the monitor
050: */
051: ConnectionAcceptor(final AcceptorConfig config,
052: final AcceptorMonitor monitor) {
053: if (null == config) {
054: throw new NullPointerException("config");
055: }
056: if (null == monitor) {
057: throw new NullPointerException("monitor");
058: }
059: m_config = config;
060: m_monitor = monitor;
061: m_monitor.acceptorCreated(m_config.getName(), m_config
062: .getServerSocket());
063: }
064:
065: /**
066: * Return true if acceptor has started.
067: *
068: * @return true if acceptor has started.
069: */
070: synchronized boolean hasStarted() {
071: return m_started;
072: }
073:
074: /**
075: * Shutdown the acceptor.
076: */
077: void close(final long timeout) {
078: synchronized (this ) {
079: m_active = false;
080: m_monitor.acceptorClosing(m_config.getName(), m_config
081: .getServerSocket());
082: m_thread.interrupt();
083: try {
084: wait(timeout);
085: } catch (InterruptedException e) {
086: //ignore
087: }
088: }
089: }
090:
091: /**
092: * The main accept & handle loop for acceptor.
093: */
094: public void run() {
095: //Setup thread to indicate that we are currently running
096: synchronized (this ) {
097: m_started = true;
098: m_active = true;
099: m_thread = Thread.currentThread();
100: }
101: while (isRunning()) {
102: m_monitor.serverSocketListening(m_config.getName(),
103: m_config.getServerSocket());
104: try {
105: final Socket socket = m_config.getServerSocket()
106: .accept();
107: if (isRunning()) {
108: m_config.getHandler().handleConnection(socket);
109: } else {
110: try {
111: socket.close();
112: } catch (final Exception e) {
113: //Ignore
114: }
115: }
116: } catch (final InterruptedIOException iioe) {
117: //Consume exception
118: } catch (final IOException ioe) {
119: m_monitor.errorAcceptingConnection(m_config.getName(),
120: ioe);
121: }
122: }
123:
124: shutdownServerSocket();
125: synchronized (this ) {
126: m_thread = null;
127: notifyAll();
128: }
129: }
130:
131: /**
132: * Utility method to shutdown serverSocket.
133: */
134: void shutdownServerSocket() {
135: try {
136: m_config.getServerSocket().close();
137: } catch (final IOException ioe) {
138: m_monitor.errorClosingServerSocket(m_config.getName(), ioe);
139: }
140: }
141:
142: /**
143: * Return true if the acceptor is currently running.
144: *
145: * @return true if the acceptor is currently running.
146: */
147: synchronized boolean isRunning() {
148: return m_active;
149: }
150: }
|