001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.net.core;
006:
007: import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArraySet;
008:
009: import com.tc.logging.TCLogger;
010: import com.tc.logging.TCLogging;
011: import com.tc.net.TCSocketAddress;
012: import com.tc.net.core.event.TCConnectionEventListener;
013: import com.tc.net.core.event.TCListenerEvent;
014: import com.tc.net.core.event.TCListenerEventListener;
015: import com.tc.net.protocol.ProtocolAdaptorFactory;
016: import com.tc.net.protocol.TCProtocolAdaptor;
017: import com.tc.util.Assert;
018: import com.tc.util.TCTimeoutException;
019: import com.tc.util.concurrent.SetOnceFlag;
020: import com.tc.util.concurrent.TCExceptionResultException;
021: import com.tc.util.concurrent.TCFuture;
022:
023: import java.net.InetAddress;
024: import java.nio.channels.ServerSocketChannel;
025: import java.nio.channels.SocketChannel;
026: import java.util.Iterator;
027:
028: /**
029: * TCListener implementation
030: *
031: * @author teck
032: */
033: final class TCListenerJDK14 implements TCListener {
034: protected final static TCLogger logger = TCLogging
035: .getLogger(TCListener.class);
036:
037: private final ServerSocketChannel ssc;
038: private final TCCommJDK14 comm;
039: private final TCConnectionEventListener listener;
040: private final TCConnectionManagerJDK14 parent;
041: private final InetAddress addr;
042: private final int port;
043: private final TCSocketAddress sockAddr;
044: private final TCListenerEvent staticEvent;
045: private final SetOnceFlag closeEventFired = new SetOnceFlag();
046: private final SetOnceFlag stopPending = new SetOnceFlag();
047: private final SetOnceFlag stopped = new SetOnceFlag();
048: private final CopyOnWriteArraySet listeners = new CopyOnWriteArraySet();
049: private final ProtocolAdaptorFactory factory;
050:
051: TCListenerJDK14(ServerSocketChannel ssc,
052: ProtocolAdaptorFactory factory, TCCommJDK14 comm,
053: TCConnectionEventListener listener,
054: TCConnectionManagerJDK14 managerJDK14) {
055: this .addr = ssc.socket().getInetAddress();
056: this .port = ssc.socket().getLocalPort();
057: this .sockAddr = new TCSocketAddress(this .addr, this .port);
058: this .factory = factory;
059: this .staticEvent = new TCListenerEvent(this );
060: this .ssc = ssc;
061: this .comm = comm;
062: this .listener = listener;
063: this .parent = managerJDK14;
064: }
065:
066: protected void stopImpl(Runnable callback) {
067: comm.stopListener(ssc, callback);
068: }
069:
070: TCConnectionJDK14 createConnection(SocketChannel ch,
071: SocketParams params) {
072: TCProtocolAdaptor adaptor = getProtocolAdaptorFactory()
073: .getInstance();
074: TCConnectionJDK14 rv = new TCConnectionJDK14(listener, comm,
075: adaptor, ch, parent, params);
076: rv.finishConnect();
077: parent.newConnection(rv);
078: return rv;
079: }
080:
081: public final void stop() {
082: try {
083: stop(0);
084: } catch (Exception e) {
085: logger.error("unexpected exception", e);
086: }
087: }
088:
089: public final TCSocketAddress getBindSocketAddress() {
090: return sockAddr;
091: }
092:
093: public final void stop(long timeout) throws TCTimeoutException {
094: if (stopped.isSet()) {
095: logger.warn("listener already stopped");
096: return;
097: }
098:
099: if (stopPending.attemptSet()) {
100: final TCFuture future = new TCFuture();
101:
102: stopImpl(new Runnable() {
103: public void run() {
104: future.set("stop done");
105: }
106: });
107:
108: try {
109: future.get(timeout);
110: } catch (InterruptedException e) {
111: logger.warn("stop interrupted");
112: return;
113: } catch (TCExceptionResultException e) {
114: logger.error(e);
115: Assert.eval("exception result set in future", false);
116: return;
117: } finally {
118: fireCloseEvent();
119: stopped.set();
120: }
121: } else {
122: logger.warn("stop already requested");
123: }
124: }
125:
126: public final int getBindPort() {
127: return port;
128: }
129:
130: public final InetAddress getBindAddress() {
131: return addr;
132: }
133:
134: public final void addEventListener(TCListenerEventListener lsnr) {
135: if (lsnr == null) {
136: logger.warn("trying to add a null event listener");
137: return;
138: }
139:
140: listeners.add(lsnr);
141: }
142:
143: public final void removeEventListener(TCListenerEventListener lsnr) {
144: if (lsnr == null) {
145: logger.warn("trying to remove a null event listener");
146: return;
147: }
148:
149: listeners.remove(lsnr);
150: }
151:
152: public final boolean isStopped() {
153: return stopped.isSet();
154: }
155:
156: public final String toString() {
157: return getClass().getName() + " " + addr.getHostAddress() + ":"
158: + port;
159: }
160:
161: protected final void fireCloseEvent() {
162: if (closeEventFired.attemptSet()) {
163: for (final Iterator iter = listeners.iterator(); iter
164: .hasNext();) {
165: final TCListenerEventListener lsnr = (TCListenerEventListener) iter
166: .next();
167:
168: try {
169: lsnr.closeEvent(staticEvent);
170: } catch (Exception e) {
171: logger.error("exception in close event handler", e);
172: }
173: }
174: }
175: }
176:
177: final ProtocolAdaptorFactory getProtocolAdaptorFactory() {
178: return factory;
179: }
180: }
|