KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > mina > common > support > IoServiceListenerSupport


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  *
19  */

20 package org.apache.mina.common.support;
21
22 import java.net.SocketAddress JavaDoc;
23 import java.util.Collections JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Set JavaDoc;
26 import java.util.concurrent.ConcurrentHashMap JavaDoc;
27 import java.util.concurrent.ConcurrentMap JavaDoc;
28 import java.util.concurrent.CopyOnWriteArrayList JavaDoc;
29 import java.util.concurrent.CopyOnWriteArraySet JavaDoc;
30 import java.util.concurrent.CountDownLatch JavaDoc;
31
32 import org.apache.mina.common.IoAcceptorConfig;
33 import org.apache.mina.common.IoConnector;
34 import org.apache.mina.common.IoFuture;
35 import org.apache.mina.common.IoFutureListener;
36 import org.apache.mina.common.IoHandler;
37 import org.apache.mina.common.IoService;
38 import org.apache.mina.common.IoServiceConfig;
39 import org.apache.mina.common.IoServiceListener;
40 import org.apache.mina.common.IoSession;
41 import org.apache.mina.common.RuntimeIOException;
42 import org.apache.mina.util.IdentityHashSet;
43
44 /**
45  * A helper which provides addition and removal of {@link IoServiceListener}s and firing
46  * events.
47  *
48  * @author The Apache Directory Project (mina-dev@directory.apache.org)
49  * @version $Rev: 555855 $, $Date: 2007-07-13 12:19:00 +0900 (금, 13 7월 2007) $
50  */

51 public class IoServiceListenerSupport {
52     /**
53      * A list of {@link IoServiceListener}s.
54      */

55     private final List JavaDoc<IoServiceListener> listeners = new CopyOnWriteArrayList JavaDoc<IoServiceListener>();
56
57     /**
58      * Tracks managed <tt>serviceAddress</tt>es.
59      */

60     private final Set JavaDoc<SocketAddress JavaDoc> managedServiceAddresses = new CopyOnWriteArraySet JavaDoc<SocketAddress JavaDoc>();
61
62     /**
63      * Tracks managed sesssions with <tt>serviceAddress</tt> as a key.
64      */

65     private final ConcurrentMap JavaDoc<SocketAddress JavaDoc, Set JavaDoc<IoSession>> managedSessions = new ConcurrentHashMap JavaDoc<SocketAddress JavaDoc, Set JavaDoc<IoSession>>();
66
67     /**
68      * Creates a new instance.
69      */

70     public IoServiceListenerSupport() {
71     }
72
73     /**
74      * Adds a new listener.
75      */

76     public void add(IoServiceListener listener) {
77         listeners.add(listener);
78     }
79
80     /**
81      * Removes an existing listener.
82      */

83     public void remove(IoServiceListener listener) {
84         listeners.remove(listener);
85     }
86
87     public Set JavaDoc<SocketAddress JavaDoc> getManagedServiceAddresses() {
88         return Collections.unmodifiableSet(managedServiceAddresses);
89     }
90
91     public boolean isManaged(SocketAddress JavaDoc serviceAddress) {
92         return managedServiceAddresses.contains(serviceAddress);
93     }
94
95     public Set JavaDoc<IoSession> getManagedSessions(SocketAddress JavaDoc serviceAddress) {
96         Set JavaDoc<IoSession> sessions = managedSessions.get(serviceAddress);
97
98         if (null == sessions) {
99             return Collections.emptySet();
100         }
101
102         synchronized (sessions) {
103             return new IdentityHashSet<IoSession>(sessions);
104         }
105     }
106
107     /**
108      * Calls {@link IoServiceListener#serviceActivated(IoService, SocketAddress, IoHandler, IoServiceConfig)}
109      * for all registered listeners.
110      */

111     public void fireServiceActivated(IoService service,
112             SocketAddress JavaDoc serviceAddress, IoHandler handler,
113             IoServiceConfig config) {
114         if (!managedServiceAddresses.add(serviceAddress)) {
115             return;
116         }
117
118         for (IoServiceListener listener : listeners) {
119             listener.serviceActivated(service, serviceAddress, handler, config);
120         }
121     }
122
123     /**
124      * Calls {@link IoServiceListener#serviceDeactivated(IoService, SocketAddress, IoHandler, IoServiceConfig)}
125      * for all registered listeners.
126      */

127     public synchronized void fireServiceDeactivated(IoService service,
128             SocketAddress JavaDoc serviceAddress, IoHandler handler,
129             IoServiceConfig config) {
130         if (!managedServiceAddresses.remove(serviceAddress)) {
131             return;
132         }
133
134         try {
135             for (IoServiceListener listener : listeners) {
136                 listener.serviceDeactivated(service, serviceAddress, handler,
137                         config);
138             }
139         } finally {
140             disconnectSessions(serviceAddress, config);
141         }
142     }
143
144     /**
145      * Calls {@link IoServiceListener#sessionCreated(IoSession)} for all registered listeners.
146      */

147     public void fireSessionCreated(IoSession session) {
148         SocketAddress JavaDoc serviceAddress = session.getServiceAddress();
149
150         // Get the session set.
151
Set JavaDoc<IoSession> s = new IdentityHashSet<IoSession>();
152         Set JavaDoc<IoSession> sessions = managedSessions.putIfAbsent(serviceAddress,
153                 Collections.synchronizedSet(s));
154         boolean firstSession;
155
156         if (null == sessions) {
157             sessions = s;
158             firstSession = true;
159         } else {
160             firstSession = false;
161         }
162
163         // If already registered, ignore.
164
if (!sessions.add(session)) {
165             return;
166         }
167
168         // If the first connector session, fire a virtual service activation event.
169
if (session.getService() instanceof IoConnector && firstSession) {
170             fireServiceActivated(session.getService(), session
171                     .getServiceAddress(), session.getHandler(), session
172                     .getServiceConfig());
173         }
174
175         // Fire session events.
176
session.getFilterChain().fireSessionCreated(session);
177         session.getFilterChain().fireSessionOpened(session);
178
179         // Fire listener events.
180
for (IoServiceListener listener : listeners) {
181             listener.sessionCreated(session);
182         }
183     }
184
185     /**
186      * Calls {@link IoServiceListener#sessionDestroyed(IoSession)} for all registered listeners.
187      */

188     public void fireSessionDestroyed(IoSession session) {
189         SocketAddress JavaDoc serviceAddress = session.getServiceAddress();
190
191         // Get the session set.
192
Set JavaDoc<IoSession> sessions = managedSessions.get(serviceAddress);
193         // Ignore if unknown.
194
if (sessions == null) {
195             return;
196         }
197
198         sessions.remove(session);
199
200         boolean lastSession = false;
201
202         // Try to remove the remaining empty session set after removal.
203
if (sessions.isEmpty()) {
204             lastSession = managedSessions.remove(serviceAddress, sessions);
205         }
206
207         // Fire session events.
208
session.getFilterChain().fireSessionClosed(session);
209
210         // Fire listener events.
211
try {
212             for (IoServiceListener listener : listeners) {
213                 listener.sessionDestroyed(session);
214             }
215         } finally {
216             // Fire a virtual service deactivation event for the last session of the connector.
217
//TODO double-check that this is *STILL* the last session. May not be the case
218
if (session.getService() instanceof IoConnector && lastSession) {
219                 fireServiceDeactivated(session.getService(), session
220                         .getServiceAddress(), session.getHandler(), session
221                         .getServiceConfig());
222             }
223         }
224     }
225
226     private void disconnectSessions(SocketAddress JavaDoc serviceAddress,
227             IoServiceConfig config) {
228         if (!(config instanceof IoAcceptorConfig)) {
229             return;
230         }
231
232         if (!((IoAcceptorConfig) config).isDisconnectOnUnbind()) {
233             return;
234         }
235
236         Set JavaDoc<IoSession> sessions = getManagedSessions(serviceAddress);
237
238         if (sessions.isEmpty()) {
239             return;
240         }
241
242         final CountDownLatch JavaDoc latch = new CountDownLatch JavaDoc(sessions.size());
243
244         for (IoSession session : sessions) {
245             session.close().addListener(new IoFutureListener() {
246                 public void operationComplete(IoFuture future) {
247                     latch.countDown();
248                 }
249             });
250         }
251
252         try {
253             latch.await();
254         } catch (InterruptedException JavaDoc e) {
255             throw new RuntimeIOException(e);
256         }
257     }
258 }
259
Popular Tags