1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.core.service;
21
22 import java.util.Collections;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.ConcurrentMap;
27 import java.util.concurrent.CopyOnWriteArrayList;
28 import java.util.concurrent.atomic.AtomicBoolean;
29
30 import org.apache.mina.core.filterchain.IoFilterChain;
31 import org.apache.mina.core.future.IoFuture;
32 import org.apache.mina.core.future.IoFutureListener;
33 import org.apache.mina.core.session.IoSession;
34 import org.apache.mina.util.ExceptionMonitor;
35
36
37
38
39
40
41
42 public class IoServiceListenerSupport {
43
44 private final IoService service;
45
46
47 private final List<IoServiceListener> listeners = new CopyOnWriteArrayList<IoServiceListener>();
48
49
50 private final ConcurrentMap<Long, IoSession> managedSessions = new ConcurrentHashMap<Long, IoSession>();
51
52
53 private final Map<Long, IoSession> readOnlyManagedSessions = Collections.unmodifiableMap(managedSessions);
54
55 private final AtomicBoolean activated = new AtomicBoolean();
56
57
58 private volatile long activationTime;
59
60
61 private volatile int largestManagedSessionCount = 0;
62
63
64 private volatile long cumulativeManagedSessionCount = 0;
65
66
67
68
69
70
71 public IoServiceListenerSupport(IoService service) {
72 if (service == null) {
73 throw new IllegalArgumentException("service");
74 }
75
76 this.service = service;
77 }
78
79
80
81
82
83
84 public void add(IoServiceListener listener) {
85 if (listener != null) {
86 listeners.add(listener);
87 }
88 }
89
90
91
92
93
94
95 public void remove(IoServiceListener listener) {
96 if (listener != null) {
97 listeners.remove(listener);
98 }
99 }
100
101
102
103
104 public long getActivationTime() {
105 return activationTime;
106 }
107
108 public Map<Long, IoSession> getManagedSessions() {
109 return readOnlyManagedSessions;
110 }
111
112 public int getManagedSessionCount() {
113 return managedSessions.size();
114 }
115
116
117
118
119
120 public int getLargestManagedSessionCount() {
121 return largestManagedSessionCount;
122 }
123
124
125
126
127
128 public long getCumulativeManagedSessionCount() {
129 return cumulativeManagedSessionCount;
130 }
131
132
133
134
135 public boolean isActive() {
136 return activated.get();
137 }
138
139
140
141
142
143 public void fireServiceActivated() {
144 if (!activated.compareAndSet(false, true)) {
145
146 return;
147 }
148
149 activationTime = System.currentTimeMillis();
150
151
152 for (IoServiceListener listener : listeners) {
153 try {
154 listener.serviceActivated(service);
155 } catch (Throwable e) {
156 ExceptionMonitor.getInstance().exceptionCaught(e);
157 }
158 }
159 }
160
161
162
163
164
165 public void fireServiceDeactivated() {
166 if (!activated.compareAndSet(true, false)) {
167
168 return;
169 }
170
171
172 try {
173 for (IoServiceListener listener : listeners) {
174 try {
175 listener.serviceDeactivated(service);
176 } catch (Throwable e) {
177 ExceptionMonitor.getInstance().exceptionCaught(e);
178 }
179 }
180 } finally {
181 disconnectSessions();
182 }
183 }
184
185
186
187
188
189
190 public void fireSessionCreated(IoSession session) {
191 boolean firstSession = false;
192
193 if (session.getService() instanceof IoConnector) {
194 synchronized (managedSessions) {
195 firstSession = managedSessions.isEmpty();
196 }
197 }
198
199
200 if (managedSessions.putIfAbsent(session.getId(), session) != null) {
201 return;
202 }
203
204
205 if (firstSession) {
206 fireServiceActivated();
207 }
208
209
210 IoFilterChain filterChain = session.getFilterChain();
211 filterChain.fireSessionCreated();
212 filterChain.fireSessionOpened();
213
214 int managedSessionCount = managedSessions.size();
215
216 if (managedSessionCount > largestManagedSessionCount) {
217 largestManagedSessionCount = managedSessionCount;
218 }
219
220 cumulativeManagedSessionCount++;
221
222
223 for (IoServiceListener l : listeners) {
224 try {
225 l.sessionCreated(session);
226 } catch (Throwable e) {
227 ExceptionMonitor.getInstance().exceptionCaught(e);
228 }
229 }
230 }
231
232
233
234
235
236
237 public void fireSessionDestroyed(IoSession session) {
238
239 if (managedSessions.remove(session.getId()) == null) {
240 return;
241 }
242
243
244 session.getFilterChain().fireSessionClosed();
245
246
247 try {
248 for (IoServiceListener l : listeners) {
249 try {
250 l.sessionDestroyed(session);
251 } catch (Throwable e) {
252 ExceptionMonitor.getInstance().exceptionCaught(e);
253 }
254 }
255 } finally {
256
257 if (session.getService() instanceof IoConnector) {
258 boolean lastSession = false;
259
260 synchronized (managedSessions) {
261 lastSession = managedSessions.isEmpty();
262 }
263
264 if (lastSession) {
265 fireServiceDeactivated();
266 }
267 }
268 }
269 }
270
271
272
273
274
275
276 private void disconnectSessions() {
277 if (!(service instanceof IoAcceptor)) {
278
279 return;
280 }
281
282 if (!((IoAcceptor) service).isCloseOnDeactivation()) {
283 return;
284 }
285
286 Object lock = new Object();
287 IoFutureListener<IoFuture> listener = new LockNotifyingListener(lock);
288
289 for (IoSession s : managedSessions.values()) {
290 s.close(true).addListener(listener);
291 }
292
293 try {
294 synchronized (lock) {
295 while (!managedSessions.isEmpty()) {
296 lock.wait(500);
297 }
298 }
299 } catch (InterruptedException ie) {
300
301 }
302 }
303
304
305
306
307 private static class LockNotifyingListener implements IoFutureListener<IoFuture> {
308 private final Object lock;
309
310 public LockNotifyingListener(Object lock) {
311 this.lock = lock;
312 }
313
314 public void operationComplete(IoFuture future) {
315 synchronized (lock) {
316 lock.notifyAll();
317 }
318 }
319 }
320 }