]> WPIA git - gigi.git/blob - lib/jetty/org/eclipse/jetty/io/ChannelEndPoint.java
Importing upstream Jetty jetty-9.2.1.v20140609
[gigi.git] / lib / jetty / org / eclipse / jetty / io / ChannelEndPoint.java
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.net.Socket;
24 import java.nio.ByteBuffer;
25 import java.nio.channels.ByteChannel;
26 import java.nio.channels.GatheringByteChannel;
27 import java.nio.channels.SocketChannel;
28
29 import org.eclipse.jetty.util.BufferUtil;
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  * Channel End Point.
36  * <p>Holds the channel and socket for an NIO endpoint.
37  */
38 public class ChannelEndPoint extends AbstractEndPoint
39 {
40     private static final Logger LOG = Log.getLogger(ChannelEndPoint.class);
41
42     private final ByteChannel _channel;
43     private final Socket _socket;
44     private volatile boolean _ishut;
45     private volatile boolean _oshut;
46
47     public ChannelEndPoint(Scheduler scheduler,SocketChannel channel)
48     {
49         super(scheduler,
50             (InetSocketAddress)channel.socket().getLocalSocketAddress(),
51             (InetSocketAddress)channel.socket().getRemoteSocketAddress());
52         _channel = channel;
53         _socket=channel.socket();
54     }
55
56     @Override
57     public boolean isOpen()
58     {
59         return _channel.isOpen();
60     }
61
62     protected void shutdownInput()
63     {
64         LOG.debug("ishut {}", this);
65         _ishut=true;
66         if (_oshut)
67             close();
68     }
69
70     @Override
71     public void shutdownOutput()
72     {
73         LOG.debug("oshut {}", this);
74         _oshut = true;
75         if (_channel.isOpen())
76         {
77             try
78             {
79                 if (!_socket.isOutputShutdown())
80                     _socket.shutdownOutput();
81             }
82             catch (IOException e)
83             {
84                 LOG.debug(e);
85             }
86             finally
87             {
88                 if (_ishut)
89                 {
90                     close();
91                 }
92             }
93         }
94     }
95
96     @Override
97     public boolean isOutputShutdown()
98     {
99         return _oshut || !_channel.isOpen() || _socket.isOutputShutdown();
100     }
101
102     @Override
103     public boolean isInputShutdown()
104     {
105         return _ishut || !_channel.isOpen() || _socket.isInputShutdown();
106     }
107
108     @Override
109     public void close()
110     {
111         super.close();
112         LOG.debug("close {}", this);
113         try
114         {
115             _channel.close();
116         }
117         catch (IOException e)
118         {
119             LOG.debug(e);
120         }
121         finally
122         {
123             _ishut=true;
124             _oshut=true;
125         }
126     }
127
128     @Override
129     public int fill(ByteBuffer buffer) throws IOException
130     {
131         if (_ishut)
132             return -1;
133
134         int pos=BufferUtil.flipToFill(buffer);
135         try
136         {
137             int filled = _channel.read(buffer);
138             if (LOG.isDebugEnabled()) // Avoid boxing of variable 'filled'
139                 LOG.debug("filled {} {}", filled, this);
140
141             if (filled>0)
142                 notIdle();
143             else if (filled==-1)
144                 shutdownInput();
145
146             return filled;
147         }
148         catch(IOException e)
149         {
150             LOG.debug(e);
151             shutdownInput();
152             return -1;
153         }
154         finally
155         {
156             BufferUtil.flipToFlush(buffer,pos);
157         }
158     }
159
160     @Override
161     public boolean flush(ByteBuffer... buffers) throws IOException
162     {
163         int flushed=0;
164         try
165         {
166             if (buffers.length==1)
167                 flushed=_channel.write(buffers[0]);
168             else if (buffers.length>1 && _channel instanceof GatheringByteChannel)
169                 flushed= (int)((GatheringByteChannel)_channel).write(buffers,0,buffers.length);
170             else
171             {
172                 for (ByteBuffer b : buffers)
173                 {
174                     if (b.hasRemaining())
175                     {
176                         int l=_channel.write(b);
177                         if (l>0)
178                             flushed+=l;
179                         if (b.hasRemaining())
180                             break;
181                     }
182                 }
183             }
184             if (LOG.isDebugEnabled())
185                 LOG.debug("flushed {} {}", flushed, this);
186         }
187         catch (IOException e)
188         {
189             throw new EofException(e);
190         }
191
192         if (flushed>0)
193             notIdle();
194
195         for (ByteBuffer b : buffers)
196             if (!BufferUtil.isEmpty(b))
197                 return false;
198
199         return true;
200     }
201
202     public ByteChannel getChannel()
203     {
204         return _channel;
205     }
206
207     @Override
208     public Object getTransport()
209     {
210         return _channel;
211     }
212
213     public Socket getSocket()
214     {
215         return _socket;
216     }
217
218     @Override
219     protected void onIncompleteFlush()
220     {
221         throw new UnsupportedOperationException();
222     }
223
224     @Override
225     protected boolean needsFill() throws IOException
226     {
227         throw new UnsupportedOperationException();
228     }
229 }