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  
27  import org.eclipse.jetty.util.BufferUtil;
28  import org.eclipse.jetty.util.StringUtil;
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 ByteBuffer _in;
44      protected ByteBuffer _out;
45      protected boolean _ishut;
46      protected boolean _oshut;
47      protected boolean _closed;
48      protected 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,StringUtil.__UTF8_CHARSET));
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(StringUtil.__UTF8_CHARSET);
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(StringUtil.__UTF8_CHARSET);
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         _closed=true;
289     }
290 
291     /* ------------------------------------------------------------ */
292     /**
293      * @return <code>true</code> if there are bytes remaining to be read from the encoded input
294      */
295     public boolean hasMore()
296     {
297         return getOutput().position()>0;
298     }
299 
300     /* ------------------------------------------------------------ */
301     /*
302      * @see org.eclipse.io.EndPoint#fill(org.eclipse.io.Buffer)
303      */
304     @Override
305     public int fill(ByteBuffer buffer) throws IOException
306     {
307         if (_closed)
308             throw new EofException("CLOSED");
309         if (_in==null)
310             shutdownInput();
311         if (_ishut)
312             return -1;
313         int filled=BufferUtil.flipPutFlip(_in,buffer);
314         if (filled>0)
315             notIdle();
316         return filled;
317     }
318 
319     /* ------------------------------------------------------------ */
320     /*
321      * @see org.eclipse.io.EndPoint#flush(org.eclipse.io.Buffer, org.eclipse.io.Buffer, org.eclipse.io.Buffer)
322      */
323     @Override
324     public boolean flush(ByteBuffer... buffers) throws IOException
325     {
326         if (_closed)
327             throw new IOException("CLOSED");
328         if (_oshut)
329             throw new IOException("OSHUT");
330 
331         boolean flushed=true;
332         boolean idle=true;
333 
334         for (ByteBuffer b : buffers)
335         {
336             if (BufferUtil.hasContent(b))
337             {
338                 if (_growOutput && b.remaining()>BufferUtil.space(_out))
339                 {
340                     BufferUtil.compact(_out);
341                     if (b.remaining()>BufferUtil.space(_out))
342                     {
343                         ByteBuffer n = BufferUtil.allocate(_out.capacity()+b.remaining()*2);
344                         BufferUtil.flipPutFlip(_out,n);
345                         _out=n;
346                     }
347                 }
348 
349                 if (BufferUtil.flipPutFlip(b,_out)>0)
350                     idle=false;
351 
352                 if (BufferUtil.hasContent(b))
353                 {
354                     flushed=false;
355                     break;
356                 }
357             }
358         }
359         if (!idle)
360             notIdle();
361         return flushed;
362     }
363 
364     /* ------------------------------------------------------------ */
365     /**
366      *
367      */
368     public void reset()
369     {
370         getFillInterest().onClose();
371         getWriteFlusher().onClose();
372         _ishut=false;
373         _oshut=false;
374         _closed=false;
375         _in=null;
376         BufferUtil.clear(_out);
377     }
378 
379     /* ------------------------------------------------------------ */
380     /*
381      * @see org.eclipse.io.EndPoint#getConnection()
382      */
383     @Override
384     public Object getTransport()
385     {
386         return null;
387     }
388 
389     /* ------------------------------------------------------------ */
390     /**
391      * @return the growOutput
392      */
393     public boolean isGrowOutput()
394     {
395         return _growOutput;
396     }
397 
398     /* ------------------------------------------------------------ */
399     /**
400      * @param growOutput the growOutput to set
401      */
402     public void setGrowOutput(boolean growOutput)
403     {
404         _growOutput=growOutput;
405     }
406 
407 
408 }