1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mortbay.io.nio;
17
18 import java.io.IOException;
19 import java.net.InetSocketAddress;
20 import java.net.Socket;
21 import java.nio.ByteBuffer;
22 import java.nio.channels.ByteChannel;
23 import java.nio.channels.GatheringByteChannel;
24 import java.nio.channels.SelectableChannel;
25 import java.nio.channels.SocketChannel;
26
27 import org.mortbay.io.Buffer;
28 import org.mortbay.io.EndPoint;
29 import org.mortbay.io.Portable;
30 import org.mortbay.log.Log;
31
32
33
34
35
36
37
38
39 public class ChannelEndPoint implements EndPoint
40 {
41 protected final ByteChannel _channel;
42 protected final ByteBuffer[] _gather2=new ByteBuffer[2];
43 protected final Socket _socket;
44 protected final InetSocketAddress _local;
45 protected final InetSocketAddress _remote;
46
47
48
49
50 public ChannelEndPoint(ByteChannel channel)
51 {
52 super();
53 this._channel = channel;
54 if (channel instanceof SocketChannel)
55 {
56 _socket=((SocketChannel)channel).socket();
57 _local=(InetSocketAddress)_socket.getLocalSocketAddress();
58 _remote=(InetSocketAddress)_socket.getRemoteSocketAddress();
59 }
60 else
61 {
62 _socket=null;
63 _local=null;
64 _remote=null;
65 }
66 }
67
68 public boolean isBlocking()
69 {
70 if (_channel instanceof SelectableChannel)
71 return ((SelectableChannel)_channel).isBlocking();
72 return true;
73 }
74
75 public boolean blockReadable(long millisecs) throws IOException
76 {
77 return true;
78 }
79
80 public boolean blockWritable(long millisecs) throws IOException
81 {
82 return true;
83 }
84
85
86
87
88 public boolean isOpen()
89 {
90 return _channel.isOpen();
91 }
92
93
94
95
96 public void close() throws IOException
97 {
98 if (_channel.isOpen())
99 {
100 try
101 {
102 if (_channel instanceof SocketChannel)
103 {
104
105 Socket socket= ((SocketChannel)_channel).socket();
106 if (!socket.isClosed() && !socket.isOutputShutdown())
107 socket.shutdownOutput();
108 }
109 }
110 catch(IOException e)
111 {
112 Log.ignore(e);
113 }
114 catch(UnsupportedOperationException e)
115 {
116 Log.ignore(e);
117 }
118 finally
119 {
120 _channel.close();
121 }
122 }
123 }
124
125
126
127
128 public int fill(Buffer buffer) throws IOException
129 {
130 Buffer buf = buffer.buffer();
131 int len=0;
132 if (buf instanceof NIOBuffer)
133 {
134 NIOBuffer nbuf = (NIOBuffer)buf;
135 ByteBuffer bbuf=nbuf.getByteBuffer();
136 synchronized(nbuf)
137 {
138 try
139 {
140 bbuf.position(buffer.putIndex());
141 len=_channel.read(bbuf);
142 if (len<0)
143 _channel.close();
144 }
145 finally
146 {
147 buffer.setPutIndex(bbuf.position());
148 bbuf.position(0);
149 }
150 }
151 }
152 else
153 {
154 throw new IOException("Not Implemented");
155 }
156
157 return len;
158 }
159
160
161
162
163 public int flush(Buffer buffer) throws IOException
164 {
165 Buffer buf = buffer.buffer();
166 int len=0;
167 if (buf instanceof NIOBuffer)
168 {
169 NIOBuffer nbuf = (NIOBuffer)buf;
170 ByteBuffer bbuf=nbuf.getByteBuffer();
171
172
173 synchronized(bbuf)
174 {
175 try
176 {
177 bbuf.position(buffer.getIndex());
178 bbuf.limit(buffer.putIndex());
179 len=_channel.write(bbuf);
180 }
181 finally
182 {
183 if (len>0)
184 buffer.skip(len);
185 bbuf.position(0);
186 bbuf.limit(bbuf.capacity());
187 }
188 }
189 }
190 else if (buffer.array()!=null)
191 {
192 ByteBuffer b = ByteBuffer.wrap(buffer.array(), buffer.getIndex(), buffer.length());
193 len=_channel.write(b);
194 if (len>0)
195 buffer.skip(len);
196 }
197 else
198 {
199 throw new IOException("Not Implemented");
200 }
201 return len;
202 }
203
204
205
206
207 public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException
208 {
209 int length=0;
210
211 Buffer buf0 = header==null?null:header.buffer();
212 Buffer buf1 = buffer==null?null:buffer.buffer();
213
214 if (_channel instanceof GatheringByteChannel &&
215 header!=null && header.length()!=0 && header instanceof NIOBuffer &&
216 buffer!=null && buffer.length()!=0 && buffer instanceof NIOBuffer)
217 {
218 NIOBuffer nbuf0 = (NIOBuffer)buf0;
219 ByteBuffer bbuf0=nbuf0.getByteBuffer();
220 NIOBuffer nbuf1 = (NIOBuffer)buf1;
221 ByteBuffer bbuf1=nbuf1.getByteBuffer();
222
223 synchronized(this)
224 {
225
226 synchronized(bbuf0)
227 {
228 synchronized(bbuf1)
229 {
230 try
231 {
232
233 bbuf0.position(header.getIndex());
234 bbuf0.limit(header.putIndex());
235 bbuf1.position(buffer.getIndex());
236 bbuf1.limit(buffer.putIndex());
237
238 _gather2[0]=bbuf0;
239 _gather2[1]=bbuf1;
240
241
242 length=(int)((GatheringByteChannel)_channel).write(_gather2);
243
244 int hl=header.length();
245 if (length>hl)
246 {
247 header.clear();
248 buffer.skip(length-hl);
249 }
250 else if (length>0)
251 {
252 header.skip(length);
253 }
254
255 }
256 finally
257 {
258
259 if (!header.isImmutable())
260 header.setGetIndex(bbuf0.position());
261 if (!buffer.isImmutable())
262 buffer.setGetIndex(bbuf1.position());
263
264 bbuf0.position(0);
265 bbuf1.position(0);
266 bbuf0.limit(bbuf0.capacity());
267 bbuf1.limit(bbuf1.capacity());
268 }
269 }
270 }
271 }
272 }
273 else
274 {
275 if (header!=null)
276 {
277 if (buffer!=null && buffer.length()>0 && header.space()>buffer.length())
278 {
279 header.put(buffer);
280 buffer.clear();
281 }
282 if (trailer!=null && trailer.length()>0 && header.space()>trailer.length())
283 {
284 header.put(trailer);
285 trailer.clear();
286 }
287 }
288
289
290 if (header!=null && header.length()>0)
291 length=flush(header);
292
293
294 if ((header==null || header.length()==0) &&
295 buffer!=null && buffer.length()>0)
296 length+=flush(buffer);
297
298
299 if ((header==null || header.length()==0) &&
300 (buffer==null || buffer.length()==0) &&
301 trailer!=null && trailer.length()>0)
302 length+=flush(trailer);
303 }
304
305 return length;
306 }
307
308
309
310
311 public ByteChannel getChannel()
312 {
313 return _channel;
314 }
315
316
317
318
319
320
321 public String getLocalAddr()
322 {
323 if (_socket==null)
324 return null;
325
326 if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
327 return Portable.ALL_INTERFACES;
328
329 return _local.getAddress().getHostAddress();
330 }
331
332
333
334
335
336 public String getLocalHost()
337 {
338 if (_socket==null)
339 return null;
340
341 if (_local==null || _local.getAddress()==null || _local.getAddress().isAnyLocalAddress())
342 return Portable.ALL_INTERFACES;
343
344 return _local.getAddress().getCanonicalHostName();
345 }
346
347
348
349
350
351 public int getLocalPort()
352 {
353 if (_socket==null)
354 return 0;
355 if (_local==null)
356 return -1;
357 return _local.getPort();
358 }
359
360
361
362
363
364 public String getRemoteAddr()
365 {
366 if (_socket==null)
367 return null;
368
369 if (_remote==null)
370 return null;
371 return _remote.getAddress().getHostAddress();
372 }
373
374
375
376
377
378 public String getRemoteHost()
379 {
380 if (_socket==null)
381 return null;
382
383 if (_remote==null)
384 return null;
385 return _remote.getAddress().getCanonicalHostName();
386 }
387
388
389
390
391
392 public int getRemotePort()
393 {
394 if (_socket==null)
395 return 0;
396
397 if (_remote==null)
398 return -1;
399 return _remote==null?-1:_remote.getPort();
400 }
401
402
403
404
405
406 public Object getTransport()
407 {
408 return _channel;
409 }
410
411
412 public void flush()
413 throws IOException
414 {
415 }
416
417
418 public boolean isBufferingInput()
419 {
420 return false;
421 }
422
423
424 public boolean isBufferingOutput()
425 {
426 return false;
427 }
428
429
430 public boolean isBufferred()
431 {
432 return false;
433 }
434 }