View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 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.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  /** ByteArrayEndPoint.
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         // Don't need to do anything here as takeOutput does the signalling.
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      * @return Returns the in.
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      * @param in The in to set.
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      * @return Returns the out.
169      */
170     public ByteBuffer getOutput()
171     {
172         return _out;
173     }
174 
175     /* ------------------------------------------------------------ */
176     /**
177      * @return Returns the out.
178      */
179     public String getOutputString()
180     {
181         return getOutputString(StandardCharsets.UTF_8);
182     }
183 
184     /* ------------------------------------------------------------ */
185     /**
186      * @return Returns the out.
187      */
188     public String getOutputString(Charset charset)
189     {
190         return BufferUtil.toString(_out,charset);
191     }
192 
193     /* ------------------------------------------------------------ */
194     /**
195      * @return Returns the out.
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      * @return Returns the out.
208      */
209     public String takeOutputString()
210     {
211         return takeOutputString(StandardCharsets.UTF_8);
212     }
213 
214     /* ------------------------------------------------------------ */
215     /**
216      * @return Returns the out.
217      */
218     public String takeOutputString(Charset charset)
219     {
220         ByteBuffer buffer=takeOutput();
221         return BufferUtil.toString(buffer,charset);
222     }
223 
224     /* ------------------------------------------------------------ */
225     /**
226      * @param out The out to set.
227      */
228     public void setOutput(ByteBuffer out)
229     {
230         _out = out;
231         getWriteFlusher().completeWrite();
232     }
233 
234     /* ------------------------------------------------------------ */
235     /*
236      * @see org.eclipse.io.EndPoint#isOpen()
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      * @see org.eclipse.io.EndPoint#shutdownOutput()
273      */
274     @Override
275     public void shutdownOutput()
276     {
277         _oshut=true;
278         if (_ishut)
279             close();
280     }
281 
282     /* ------------------------------------------------------------ */
283     /*
284      * @see org.eclipse.io.EndPoint#close()
285      */
286     @Override
287     public void close()
288     {
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.flipPutFlip(_in,buffer);
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.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      * @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 }