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