View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
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.log.Log;
30  import org.eclipse.jetty.util.log.Logger;
31  import org.eclipse.jetty.util.thread.Scheduler;
32  
33  
34  /* ------------------------------------------------------------ */
35  /** ByteArrayEndPoint.
36   *
37   */
38  public class ByteArrayEndPoint extends AbstractEndPoint
39  {
40      static final Logger LOG = Log.getLogger(ByteArrayEndPoint.class);
41      public final static InetSocketAddress NOIP=new InetSocketAddress(0);
42  
43      protected volatile ByteBuffer _in;
44      protected volatile ByteBuffer _out;
45      protected volatile boolean _ishut;
46      protected volatile boolean _oshut;
47      protected volatile boolean _closed;
48      protected volatile boolean _growOutput;
49  
50  
51      /* ------------------------------------------------------------ */
52      /**
53       *
54       */
55      public ByteArrayEndPoint()
56      {
57          this(null,0,null,null);
58      }
59  
60      /* ------------------------------------------------------------ */
61      /**
62       *
63       */
64      public ByteArrayEndPoint(byte[] input, int outputSize)
65      {
66          this(null,0,input!=null?BufferUtil.toBuffer(input):null,BufferUtil.allocate(outputSize));
67      }
68  
69      /* ------------------------------------------------------------ */
70      /**
71       *
72       */
73      public ByteArrayEndPoint(String input, int outputSize)
74      {
75          this(null,0,input!=null?BufferUtil.toBuffer(input):null,BufferUtil.allocate(outputSize));
76      }
77  
78      /* ------------------------------------------------------------ */
79      public ByteArrayEndPoint(Scheduler scheduler, long idleTimeoutMs)
80      {
81          this(scheduler,idleTimeoutMs,null,null);
82      }
83  
84      /* ------------------------------------------------------------ */
85      public ByteArrayEndPoint(Scheduler timer, long idleTimeoutMs, byte[] input, int outputSize)
86      {
87          this(timer,idleTimeoutMs,input!=null?BufferUtil.toBuffer(input):null,BufferUtil.allocate(outputSize));
88      }
89  
90      /* ------------------------------------------------------------ */
91      public ByteArrayEndPoint(Scheduler timer, long idleTimeoutMs, String input, int outputSize)
92      {
93          this(timer,idleTimeoutMs,input!=null?BufferUtil.toBuffer(input):null,BufferUtil.allocate(outputSize));
94      }
95  
96      /* ------------------------------------------------------------ */
97      public ByteArrayEndPoint(Scheduler timer, long idleTimeoutMs, ByteBuffer input, ByteBuffer output)
98      {
99          super(timer,NOIP,NOIP);
100         _in=input==null?BufferUtil.EMPTY_BUFFER:input;
101         _out=output==null?BufferUtil.allocate(1024):output;
102         setIdleTimeout(idleTimeoutMs);
103     }
104 
105 
106 
107 
108 
109     /* ------------------------------------------------------------ */
110     @Override
111     protected void onIncompleteFlush()
112     {
113         // Don't need to do anything here as takeOutput does the signalling.
114     }
115 
116     /* ------------------------------------------------------------ */
117     @Override
118     protected boolean needsFill() throws IOException
119     {
120         if (_closed)
121             throw new ClosedChannelException();
122         return _in == null || BufferUtil.hasContent(_in);
123     }
124 
125     /* ------------------------------------------------------------ */
126     /**
127      * @return Returns the in.
128      */
129     public ByteBuffer getIn()
130     {
131         return _in;
132     }
133 
134     /* ------------------------------------------------------------ */
135     /**
136      */
137     public void setInputEOF()
138     {
139         _in = null;
140     }
141 
142     /* ------------------------------------------------------------ */
143     /**
144      * @param in The in to set.
145      */
146     public void setInput(ByteBuffer in)
147     {
148         _in = in;
149         if (in == null || BufferUtil.hasContent(in))
150             getFillInterest().fillable();
151     }
152 
153     /* ------------------------------------------------------------ */
154     public void setInput(String s)
155     {
156         setInput(BufferUtil.toBuffer(s,StandardCharsets.UTF_8));
157     }
158 
159     /* ------------------------------------------------------------ */
160     public void setInput(String s,Charset charset)
161     {
162         setInput(BufferUtil.toBuffer(s,charset));
163     }
164 
165     /* ------------------------------------------------------------ */
166     /**
167      * @return Returns the out.
168      */
169     public ByteBuffer getOutput()
170     {
171         return _out;
172     }
173 
174     /* ------------------------------------------------------------ */
175     /**
176      * @return Returns the out.
177      */
178     public String getOutputString()
179     {
180         return getOutputString(StandardCharsets.UTF_8);
181     }
182 
183     /* ------------------------------------------------------------ */
184     /**
185      * @return Returns the out.
186      */
187     public String getOutputString(Charset charset)
188     {
189         return BufferUtil.toString(_out,charset);
190     }
191 
192     /* ------------------------------------------------------------ */
193     /**
194      * @return Returns the out.
195      */
196     public ByteBuffer takeOutput()
197     {
198         ByteBuffer b=_out;
199         _out=BufferUtil.allocate(b.capacity());
200         getWriteFlusher().completeWrite();
201         return b;
202     }
203 
204     /* ------------------------------------------------------------ */
205     /**
206      * @return Returns the out.
207      */
208     public String takeOutputString()
209     {
210         return takeOutputString(StandardCharsets.UTF_8);
211     }
212 
213     /* ------------------------------------------------------------ */
214     /**
215      * @return Returns the out.
216      */
217     public String takeOutputString(Charset charset)
218     {
219         ByteBuffer buffer=takeOutput();
220         return BufferUtil.toString(buffer,charset);
221     }
222 
223     /* ------------------------------------------------------------ */
224     /**
225      * @param out The out to set.
226      */
227     public void setOutput(ByteBuffer out)
228     {
229         _out = out;
230         getWriteFlusher().completeWrite();
231     }
232 
233     /* ------------------------------------------------------------ */
234     /*
235      * @see org.eclipse.io.EndPoint#isOpen()
236      */
237     @Override
238     public boolean isOpen()
239     {
240         return !_closed;
241     }
242 
243     /* ------------------------------------------------------------ */
244     /*
245      */
246     @Override
247     public boolean isInputShutdown()
248     {
249         return _ishut||_closed;
250     }
251 
252     /* ------------------------------------------------------------ */
253     /*
254      */
255     @Override
256     public boolean isOutputShutdown()
257     {
258         return _oshut||_closed;
259     }
260 
261     /* ------------------------------------------------------------ */
262     private void shutdownInput()
263     {
264         _ishut=true;
265         if (_oshut)
266             close();
267     }
268 
269     /* ------------------------------------------------------------ */
270     /*
271      * @see org.eclipse.io.EndPoint#shutdownOutput()
272      */
273     @Override
274     public void shutdownOutput()
275     {
276         _oshut=true;
277         if (_ishut)
278             close();
279     }
280 
281     /* ------------------------------------------------------------ */
282     /*
283      * @see org.eclipse.io.EndPoint#close()
284      */
285     @Override
286     public void close()
287     {
288         super.close();
289         _closed=true;
290     }
291 
292     /* ------------------------------------------------------------ */
293     /**
294      * @return <code>true</code> if there are bytes remaining to be read from the encoded input
295      */
296     public boolean hasMore()
297     {
298         return getOutput().position()>0;
299     }
300 
301     /* ------------------------------------------------------------ */
302     /*
303      * @see org.eclipse.io.EndPoint#fill(org.eclipse.io.Buffer)
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.append(buffer,_in);
315         if (filled>0)
316             notIdle();
317         return filled;
318     }
319 
320     /* ------------------------------------------------------------ */
321     /*
322      * @see org.eclipse.io.EndPoint#flush(org.eclipse.io.Buffer, org.eclipse.io.Buffer, org.eclipse.io.Buffer)
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.append(n,_out);
346                         _out=n;
347                     }
348                 }
349 
350                 if (BufferUtil.append(_out,b)>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      * @see org.eclipse.io.EndPoint#getConnection()
383      */
384     @Override
385     public Object getTransport()
386     {
387         return null;
388     }
389 
390     /* ------------------------------------------------------------ */
391     /**
392      * @return the growOutput
393      */
394     public boolean isGrowOutput()
395     {
396         return _growOutput;
397     }
398 
399     /* ------------------------------------------------------------ */
400     /**
401      * @param growOutput the growOutput to set
402      */
403     public void setGrowOutput(boolean growOutput)
404     {
405         _growOutput=growOutput;
406     }
407 
408 
409 }