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
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 fireServiceDeactivated() {
142 if (!activated.compareAndSet(true, false)) {
143 return;
144 }
145
146 try {
147 for (IoServiceListener l : listeners) {
148 try {
149 l.serviceDeactivated(service);
150 } catch (Throwable e) {
151 ExceptionMonitor.getInstance().exceptionCaught(e);
152 }
153 }
154 } finally {
155 disconnectSessions();
156 }
157 }
158
159
160
161
162 public void fireSessionCreated(IoSession session) {
163 boolean firstSession = false;
164 if (session.getService() instanceof IoConnector) {
165 synchronized (managedSessions) {
166 firstSession = managedSessions.isEmpty();
167 }
168 }
169
170
171 if (managedSessions.putIfAbsent(Long.valueOf(session.getId()), session) != null) {
172 return;
173 }
174
175
176 if (firstSession) {
177 fireServiceActivated();
178 }
179
180
181 IoFilterChain filterChain = session.getFilterChain();
182 filterChain.fireSessionCreated();
183 filterChain.fireSessionOpened();
184
185 int managedSessionCount = managedSessions.size();
186 if (managedSessionCount > largestManagedSessionCount) {
187 largestManagedSessionCount = managedSessionCount;
188 }
189 cumulativeManagedSessionCount ++;
190
191
192 for (IoServiceListener l : listeners) {
193 try {
194 l.sessionCreated(session);
195 } catch (Throwable e) {
196 ExceptionMonitor.getInstance().exceptionCaught(e);
197 }
198 }
199 }
200
201
202
203
204 public void fireSessionDestroyed(IoSession session) {
205
206 if (managedSessions.remove(Long.valueOf(session.getId())) == null) {
207 return;
208 }
209
210
211 session.getFilterChain().fireSessionClosed();
212
213
214 try {
215 for (IoServiceListener l : listeners) {
216 try {
217 l.sessionDestroyed(session);
218 } catch (Throwable e) {
219 ExceptionMonitor.getInstance().exceptionCaught(e);
220 }
221 }
222 } finally {
223
224 if (session.getService() instanceof IoConnector) {
225 boolean lastSession = false;
226 synchronized (managedSessions) {
227 lastSession = managedSessions.isEmpty();
228 }
229 if (lastSession) {
230 fireServiceDeactivated();
231 }
232 }
233 }
234 }
235
236 private void disconnectSessions() {
237 if (!(service instanceof IoAcceptor)) {
238 return;
239 }
240
241 if (!((IoAcceptor) service).isCloseOnDeactivation()) {
242 return;
243 }
244
245 Object lock = new Object();
246 IoFutureListener<IoFuture> listener = new LockNotifyingListener(lock);
247
248 for (IoSession s : managedSessions.values()) {
249 s.close(true).addListener(listener);
250 }
251
252 try {
253 synchronized (lock) {
254 while (!managedSessions.isEmpty()) {
255 lock.wait(500);
256 }
257 }
258 } catch (InterruptedException ie) {
259
260 }
261 }
262
263 private static class LockNotifyingListener implements IoFutureListener<IoFuture> {
264 private final Object lock;
265
266 public LockNotifyingListener(Object lock) {
267 this.lock = lock;
268 }
269
270 public void operationComplete(IoFuture future) {
271 synchronized (lock) {
272 lock.notifyAll();
273 }
274 }
275 }
276 }