1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.transport.vmpipe.support;
21
22 import java.util.Queue;
23 import java.util.concurrent.ConcurrentLinkedQueue;
24
25 import org.apache.mina.common.ByteBuffer;
26 import org.apache.mina.common.IdleStatus;
27 import org.apache.mina.common.IoSession;
28 import org.apache.mina.common.IoFilter.WriteRequest;
29 import org.apache.mina.common.support.AbstractIoFilterChain;
30
31
32
33
34
35 public class VmPipeFilterChain extends AbstractIoFilterChain {
36
37 private final Queue<Event> eventQueue = new ConcurrentLinkedQueue<Event>();
38
39 private boolean flushEnabled;
40
41 public VmPipeFilterChain(IoSession session) {
42 super(session);
43 }
44
45 public void start() {
46 flushEnabled = true;
47 flushEvents();
48 }
49
50 private void pushEvent(Event e) {
51 eventQueue.offer(e);
52 if (flushEnabled) {
53 flushEvents();
54 }
55 }
56
57 private void flushEvents() {
58 Event e;
59 while ((e = eventQueue.poll()) != null) {
60 fireEvent(e);
61 }
62 }
63
64 private void fireEvent(Event e) {
65 IoSession session = getSession();
66 EventType type = e.getType();
67 Object data = e.getData();
68
69 if (type == EventType.RECEIVED) {
70 VmPipeSessionImpl s = (VmPipeSessionImpl) session;
71 synchronized (s.lock) {
72 if (!s.getTrafficMask().isReadable()) {
73 s.pendingDataQueue.offer(data);
74 } else {
75 int byteCount = 1;
76 if (data instanceof ByteBuffer) {
77 byteCount = ((ByteBuffer) data).remaining();
78 }
79
80 s.increaseReadBytes(byteCount);
81
82 super.fireMessageReceived(s, data);
83 }
84 }
85 } else if (type == EventType.WRITE) {
86 super.fireFilterWrite(session, (WriteRequest) data);
87 } else if (type == EventType.SENT) {
88 super.fireMessageSent(session, (WriteRequest) data);
89 } else if (type == EventType.EXCEPTION) {
90 super.fireExceptionCaught(session, (Throwable) data);
91 } else if (type == EventType.IDLE) {
92 super.fireSessionIdle(session, (IdleStatus) data);
93 } else if (type == EventType.OPENED) {
94 super.fireSessionOpened(session);
95 } else if (type == EventType.CREATED) {
96 super.fireSessionCreated(session);
97 } else if (type == EventType.CLOSED) {
98 super.fireSessionClosed(session);
99 } else if (type == EventType.CLOSE) {
100 super.fireFilterClose(session);
101 }
102 }
103
104 @Override
105 public void fireFilterClose(IoSession session) {
106 pushEvent(new Event(EventType.CLOSE, null));
107 }
108
109 @Override
110 public void fireFilterWrite(IoSession session, WriteRequest writeRequest) {
111 pushEvent(new Event(EventType.WRITE, writeRequest));
112 }
113
114 @Override
115 public void fireExceptionCaught(IoSession session, Throwable cause) {
116 pushEvent(new Event(EventType.EXCEPTION, cause));
117 }
118
119 @Override
120 public void fireMessageSent(IoSession session, WriteRequest request) {
121 pushEvent(new Event(EventType.SENT, request));
122 }
123
124 @Override
125 public void fireSessionClosed(IoSession session) {
126 pushEvent(new Event(EventType.CLOSED, null));
127 }
128
129 @Override
130 public void fireSessionCreated(IoSession session) {
131 pushEvent(new Event(EventType.CREATED, null));
132 }
133
134 @Override
135 public void fireSessionIdle(IoSession session, IdleStatus status) {
136 pushEvent(new Event(EventType.IDLE, status));
137 }
138
139 @Override
140 public void fireSessionOpened(IoSession session) {
141 pushEvent(new Event(EventType.OPENED, null));
142 }
143
144 @Override
145 public void fireMessageReceived(IoSession session, Object message) {
146 pushEvent(new Event(EventType.RECEIVED, message));
147 }
148
149 @Override
150 protected void doWrite(IoSession session, WriteRequest writeRequest) {
151 VmPipeSessionImpl s = (VmPipeSessionImpl) session;
152 synchronized (s.lock) {
153 if (s.isConnected()) {
154
155 if (!s.getTrafficMask().isWritable()) {
156 s.pendingDataQueue.offer(writeRequest);
157 } else {
158 Object message = writeRequest.getMessage();
159
160 int byteCount = 1;
161 Object messageCopy = message;
162 if (message instanceof ByteBuffer) {
163 ByteBuffer rb = (ByteBuffer) message;
164 rb.mark();
165 byteCount = rb.remaining();
166 ByteBuffer wb = ByteBuffer.allocate(rb.remaining());
167 wb.put(rb);
168 wb.flip();
169 rb.reset();
170 messageCopy = wb;
171 }
172
173 s.increaseWrittenBytes(byteCount);
174 s.increaseWrittenMessages();
175
176 s.getRemoteSession().getFilterChain().fireMessageReceived(
177 s.getRemoteSession(), messageCopy);
178 s.getFilterChain().fireMessageSent(s, writeRequest);
179 }
180 } else {
181 writeRequest.getFuture().setWritten(false);
182 }
183 }
184 }
185
186 @Override
187 protected void doClose(IoSession session) {
188 VmPipeSessionImpl s = (VmPipeSessionImpl) session;
189 synchronized (s.lock) {
190 if (!session.getCloseFuture().isClosed()) {
191 s.getServiceListeners().fireSessionDestroyed(s);
192 s.getRemoteSession().close();
193 }
194 }
195 }
196
197
198 private static class EventType {
199 public static final EventType CREATED = new EventType("CREATED");
200
201 public static final EventType OPENED = new EventType("OPENED");
202
203 public static final EventType CLOSED = new EventType("CLOSED");
204
205 public static final EventType RECEIVED = new EventType("RECEIVED");
206
207 public static final EventType SENT = new EventType("SENT");
208
209 public static final EventType IDLE = new EventType("IDLE");
210
211 public static final EventType EXCEPTION = new EventType("EXCEPTION");
212
213 public static final EventType WRITE = new EventType("WRITE");
214
215 public static final EventType CLOSE = new EventType("CLOSE");
216
217 private final String value;
218
219 private EventType(String value) {
220 this.value = value;
221 }
222
223 public String toString() {
224 return value;
225 }
226 }
227
228 private static class Event {
229 private final EventType type;
230
231 private final Object data;
232
233 public Event(EventType type, Object data) {
234 this.type = type;
235 this.data = data;
236 }
237
238 public Object getData() {
239 return data;
240 }
241
242 public EventType getType() {
243 return type;
244 }
245 }
246 }