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