1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.filter.buffer;
21
22 import java.io.BufferedOutputStream;
23 import java.util.concurrent.ConcurrentHashMap;
24
25 import org.apache.mina.core.buffer.IoBuffer;
26 import org.apache.mina.core.filterchain.IoFilter;
27 import org.apache.mina.core.filterchain.IoFilterAdapter;
28 import org.apache.mina.core.session.IoSession;
29 import org.apache.mina.core.write.DefaultWriteRequest;
30 import org.apache.mina.core.write.WriteRequest;
31 import org.apache.mina.filter.codec.ProtocolCodecFilter;
32 import org.apache.mina.util.LazyInitializedCacheMap;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public final class BufferedWriteFilter extends IoFilterAdapter {
51 private final Logger logger = LoggerFactory
52 .getLogger(BufferedWriteFilter.class);
53
54
55
56
57 public final static int DEFAULT_BUFFER_SIZE = 8192;
58
59
60
61
62 private int bufferSize = DEFAULT_BUFFER_SIZE;
63
64
65
66
67
68 private final LazyInitializedCacheMap<IoSession, IoBuffer> buffersMap;
69
70
71
72
73
74 public BufferedWriteFilter() {
75 this(DEFAULT_BUFFER_SIZE, null);
76 }
77
78
79
80
81
82
83
84 public BufferedWriteFilter(int bufferSize) {
85 this(bufferSize, null);
86 }
87
88
89
90
91
92
93
94
95
96 public BufferedWriteFilter(int bufferSize,
97 LazyInitializedCacheMap<IoSession, IoBuffer> buffersMap) {
98 super();
99 this.bufferSize = bufferSize;
100 if (buffersMap == null) {
101 this.buffersMap = new LazyInitializedCacheMap<IoSession, IoBuffer>();
102 } else {
103 this.buffersMap = buffersMap;
104 }
105 }
106
107
108
109
110 public int getBufferSize() {
111 return bufferSize;
112 }
113
114
115
116
117
118
119 public void setBufferSize(int bufferSize) {
120 this.bufferSize = bufferSize;
121 }
122
123
124
125
126
127
128
129 @Override
130 public void filterWrite(NextFilter nextFilter, IoSession session,
131 WriteRequest writeRequest) throws Exception {
132
133 Object data = writeRequest.getMessage();
134
135 if (data instanceof IoBuffer) {
136 write(session, (IoBuffer) data);
137 } else {
138 throw new IllegalArgumentException(
139 "This filter should only buffer IoBuffer objects");
140 }
141 }
142
143
144
145
146
147
148
149 private void write(IoSession session, IoBuffer data) {
150 IoBuffer dest = buffersMap.putIfAbsent(session,
151 new IoBufferLazyInitializer(bufferSize));
152
153 write(session, data, dest);
154 }
155
156
157
158
159
160
161
162
163
164
165
166 private void write(IoSession session, IoBuffer data, IoBuffer buf) {
167 try {
168 int len = data.remaining();
169 if (len >= buf.capacity()) {
170
171
172
173
174 NextFilter nextFilter = session.getFilterChain().getNextFilter(
175 this);
176 internalFlush(nextFilter, session, buf);
177 nextFilter.filterWrite(session, new DefaultWriteRequest(data));
178 return;
179 }
180 if (len > (buf.limit() - buf.position())) {
181 internalFlush(session.getFilterChain().getNextFilter(this),
182 session, buf);
183 }
184 synchronized (buf) {
185 buf.put(data);
186 }
187 } catch (Throwable e) {
188 session.getFilterChain().fireExceptionCaught(e);
189 }
190 }
191
192
193
194
195
196
197
198
199
200 private void internalFlush(NextFilter nextFilter, IoSession session,
201 IoBuffer buf) throws Exception {
202 IoBuffer tmp = null;
203 synchronized (buf) {
204 buf.flip();
205 tmp = buf.duplicate();
206 buf.clear();
207 }
208 logger.debug("Flushing buffer: {}", tmp);
209 nextFilter.filterWrite(session, new DefaultWriteRequest(tmp));
210 }
211
212
213
214
215
216
217 public void flush(IoSession session) {
218 try {
219 internalFlush(session.getFilterChain().getNextFilter(this),
220 session, buffersMap.get(session));
221 } catch (Throwable e) {
222 session.getFilterChain().fireExceptionCaught(e);
223 }
224 }
225
226
227
228
229
230
231
232 private void free(IoSession session) {
233 IoBuffer buf = buffersMap.remove(session);
234 if (buf != null) {
235 buf.free();
236 }
237 }
238
239
240
241
242 @Override
243 public void exceptionCaught(NextFilter nextFilter, IoSession session,
244 Throwable cause) throws Exception {
245 free(session);
246 }
247
248
249
250
251 @Override
252 public void sessionClosed(NextFilter nextFilter, IoSession session)
253 throws Exception {
254 free(session);
255 }
256 }