1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.io;
20
21 import java.io.IOException;
22 import java.net.InetSocketAddress;
23 import java.nio.ByteBuffer;
24 import java.nio.channels.ClosedChannelException;
25 import java.nio.charset.Charset;
26 import java.nio.charset.StandardCharsets;
27
28 import org.eclipse.jetty.util.BufferUtil;
29 import org.eclipse.jetty.util.StringUtil;
30 import org.eclipse.jetty.util.log.Log;
31 import org.eclipse.jetty.util.log.Logger;
32 import org.eclipse.jetty.util.thread.Scheduler;
33
34
35
36
37
38
39 public class ByteArrayEndPoint extends AbstractEndPoint
40 {
41 static final Logger LOG = Log.getLogger(ByteArrayEndPoint.class);
42 public final static InetSocketAddress NOIP=new InetSocketAddress(0);
43
44 protected ByteBuffer _in;
45 protected ByteBuffer _out;
46 protected boolean _ishut;
47 protected boolean _oshut;
48 protected boolean _closed;
49 protected boolean _growOutput;
50
51
52
53
54
55
56 public ByteArrayEndPoint()
57 {
58 this(null,0,null,null);
59 }
60
61
62
63
64
65 public ByteArrayEndPoint(byte[] input, int outputSize)
66 {
67 this(null,0,input!=null?BufferUtil.toBuffer(input):null,BufferUtil.allocate(outputSize));
68 }
69
70
71
72
73
74 public ByteArrayEndPoint(String input, int outputSize)
75 {
76 this(null,0,input!=null?BufferUtil.toBuffer(input):null,BufferUtil.allocate(outputSize));
77 }
78
79
80 public ByteArrayEndPoint(Scheduler scheduler, long idleTimeoutMs)
81 {
82 this(scheduler,idleTimeoutMs,null,null);
83 }
84
85
86 public ByteArrayEndPoint(Scheduler timer, long idleTimeoutMs, byte[] input, int outputSize)
87 {
88 this(timer,idleTimeoutMs,input!=null?BufferUtil.toBuffer(input):null,BufferUtil.allocate(outputSize));
89 }
90
91
92 public ByteArrayEndPoint(Scheduler timer, long idleTimeoutMs, String input, int outputSize)
93 {
94 this(timer,idleTimeoutMs,input!=null?BufferUtil.toBuffer(input):null,BufferUtil.allocate(outputSize));
95 }
96
97
98 public ByteArrayEndPoint(Scheduler timer, long idleTimeoutMs, ByteBuffer input, ByteBuffer output)
99 {
100 super(timer,NOIP,NOIP);
101 _in=input==null?BufferUtil.EMPTY_BUFFER:input;
102 _out=output==null?BufferUtil.allocate(1024):output;
103 setIdleTimeout(idleTimeoutMs);
104 }
105
106
107
108
109
110
111 @Override
112 protected void onIncompleteFlush()
113 {
114
115 }
116
117
118 @Override
119 protected boolean needsFill() throws IOException
120 {
121 if (_closed)
122 throw new ClosedChannelException();
123 return _in == null || BufferUtil.hasContent(_in);
124 }
125
126
127
128
129
130 public ByteBuffer getIn()
131 {
132 return _in;
133 }
134
135
136
137
138 public void setInputEOF()
139 {
140 _in = null;
141 }
142
143
144
145
146
147 public void setInput(ByteBuffer in)
148 {
149 _in = in;
150 if (in == null || BufferUtil.hasContent(in))
151 getFillInterest().fillable();
152 }
153
154
155 public void setInput(String s)
156 {
157 setInput(BufferUtil.toBuffer(s,StandardCharsets.UTF_8));
158 }
159
160
161 public void setInput(String s,Charset charset)
162 {
163 setInput(BufferUtil.toBuffer(s,charset));
164 }
165
166
167
168
169
170 public ByteBuffer getOutput()
171 {
172 return _out;
173 }
174
175
176
177
178
179 public String getOutputString()
180 {
181 return getOutputString(StandardCharsets.UTF_8);
182 }
183
184
185
186
187
188 public String getOutputString(Charset charset)
189 {
190 return BufferUtil.toString(_out,charset);
191 }
192
193
194
195
196
197 public ByteBuffer takeOutput()
198 {
199 ByteBuffer b=_out;
200 _out=BufferUtil.allocate(b.capacity());
201 getWriteFlusher().completeWrite();
202 return b;
203 }
204
205
206
207
208
209 public String takeOutputString()
210 {
211 return takeOutputString(StandardCharsets.UTF_8);
212 }
213
214
215
216
217
218 public String takeOutputString(Charset charset)
219 {
220 ByteBuffer buffer=takeOutput();
221 return BufferUtil.toString(buffer,charset);
222 }
223
224
225
226
227
228 public void setOutput(ByteBuffer out)
229 {
230 _out = out;
231 getWriteFlusher().completeWrite();
232 }
233
234
235
236
237
238 @Override
239 public boolean isOpen()
240 {
241 return !_closed;
242 }
243
244
245
246
247 @Override
248 public boolean isInputShutdown()
249 {
250 return _ishut||_closed;
251 }
252
253
254
255
256 @Override
257 public boolean isOutputShutdown()
258 {
259 return _oshut||_closed;
260 }
261
262
263 private void shutdownInput()
264 {
265 _ishut=true;
266 if (_oshut)
267 close();
268 }
269
270
271
272
273
274 @Override
275 public void shutdownOutput()
276 {
277 _oshut=true;
278 if (_ishut)
279 close();
280 }
281
282
283
284
285
286 @Override
287 public void close()
288 {
289 _closed=true;
290 }
291
292
293
294
295
296 public boolean hasMore()
297 {
298 return getOutput().position()>0;
299 }
300
301
302
303
304
305 @Override
306 public int fill(ByteBuffer buffer) throws IOException
307 {
308 if (_closed)
309 throw new EofException("CLOSED");
310 if (_in==null)
311 shutdownInput();
312 if (_ishut)
313 return -1;
314 int filled=BufferUtil.flipPutFlip(_in,buffer);
315 if (filled>0)
316 notIdle();
317 return filled;
318 }
319
320
321
322
323
324 @Override
325 public boolean flush(ByteBuffer... buffers) throws IOException
326 {
327 if (_closed)
328 throw new IOException("CLOSED");
329 if (_oshut)
330 throw new IOException("OSHUT");
331
332 boolean flushed=true;
333 boolean idle=true;
334
335 for (ByteBuffer b : buffers)
336 {
337 if (BufferUtil.hasContent(b))
338 {
339 if (_growOutput && b.remaining()>BufferUtil.space(_out))
340 {
341 BufferUtil.compact(_out);
342 if (b.remaining()>BufferUtil.space(_out))
343 {
344 ByteBuffer n = BufferUtil.allocate(_out.capacity()+b.remaining()*2);
345 BufferUtil.flipPutFlip(_out,n);
346 _out=n;
347 }
348 }
349
350 if (BufferUtil.flipPutFlip(b,_out)>0)
351 idle=false;
352
353 if (BufferUtil.hasContent(b))
354 {
355 flushed=false;
356 break;
357 }
358 }
359 }
360 if (!idle)
361 notIdle();
362 return flushed;
363 }
364
365
366
367
368
369 public void reset()
370 {
371 getFillInterest().onClose();
372 getWriteFlusher().onClose();
373 _ishut=false;
374 _oshut=false;
375 _closed=false;
376 _in=null;
377 BufferUtil.clear(_out);
378 }
379
380
381
382
383
384 @Override
385 public Object getTransport()
386 {
387 return null;
388 }
389
390
391
392
393
394 public boolean isGrowOutput()
395 {
396 return _growOutput;
397 }
398
399
400
401
402
403 public void setGrowOutput(boolean growOutput)
404 {
405 _growOutput=growOutput;
406 }
407
408
409 }