OSDN Git Service

cda86e80723310d7a574ebf7e04433d595deafb3
[pf3gnuchains/gcc-fork.git] / libjava / gnu / java / nio / SocketChannelImpl.java
1 /* SocketChannelImpl.java -- 
2    Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package gnu.java.nio;
40
41 import gnu.java.net.PlainSocketImpl;
42
43 import java.io.IOException;
44 import java.io.InputStream;
45 import java.io.OutputStream;
46 import java.net.InetSocketAddress;
47 import java.net.Socket;
48 import java.net.SocketAddress;
49 import java.net.SocketTimeoutException;
50 import java.nio.ByteBuffer;
51 import java.nio.channels.AlreadyConnectedException;
52 import java.nio.channels.ClosedChannelException;
53 import java.nio.channels.ConnectionPendingException;
54 import java.nio.channels.NoConnectionPendingException;
55 import java.nio.channels.NotYetConnectedException;
56 import java.nio.channels.SelectionKey;
57 import java.nio.channels.Selector;
58 import java.nio.channels.SocketChannel;
59 import java.nio.channels.UnresolvedAddressException;
60 import java.nio.channels.UnsupportedAddressTypeException;
61 import java.nio.channels.spi.SelectorProvider;
62
63 public final class SocketChannelImpl extends SocketChannel
64 {
65   private PlainSocketImpl impl;
66   private NIOSocket socket;
67   private boolean connectionPending;
68
69   SocketChannelImpl (SelectorProvider provider)
70     throws IOException
71   {
72     super (provider);
73     impl = new PlainSocketImpl();
74     socket = new NIOSocket (impl, this);
75     configureBlocking(true);
76   }
77   
78   SocketChannelImpl (SelectorProvider provider,
79                      NIOSocket socket)
80     throws IOException
81   {
82     super (provider);
83     this.impl = socket.getPlainSocketImpl();
84     this.socket = socket;
85   }
86
87   public void finalizer()
88   {
89     if (isConnected())
90       {
91         try
92           {
93             close ();
94           }
95         catch (Exception e)
96           {
97           }
98       }
99   }
100
101   PlainSocketImpl getPlainSocketImpl()
102   {
103     return impl;
104   }
105
106   int getNativeFD()
107   {
108     return socket.getPlainSocketImpl().getNativeFD();
109   }
110
111   protected void implCloseSelectableChannel () throws IOException
112   {
113     socket.close();
114   }
115
116   protected void implConfigureBlocking (boolean blocking) throws IOException
117   {
118     socket.setSoTimeout (blocking ? 0 : NIOConstants.DEFAULT_TIMEOUT);
119   }   
120
121   public boolean connect (SocketAddress remote) throws IOException
122   {
123     if (!isOpen())
124       throw new ClosedChannelException();
125     
126     if (isConnected())
127       throw new AlreadyConnectedException();
128
129     if (connectionPending)
130       throw new ConnectionPendingException();
131
132     if (!(remote instanceof InetSocketAddress))
133       throw new UnsupportedAddressTypeException();
134
135     if (((InetSocketAddress) remote).isUnresolved())
136       throw new UnresolvedAddressException();
137     
138     try
139       {
140         socket.getPlainSocketImpl().setInChannelOperation(true);
141           // indicate that a channel is initiating the accept operation
142           // so that the socket ignores the fact that we might be in
143           // non-blocking mode.
144         
145         if (isBlocking())
146           {
147             // Do blocking connect.
148             socket.connect (remote);
149             return true;
150           }
151
152         // Do non-blocking connect.
153         try
154           {
155             socket.connect (remote, NIOConstants.DEFAULT_TIMEOUT);
156             return true;
157           }
158         catch (SocketTimeoutException e)
159           {
160             connectionPending = true;
161             return false;
162           }
163       }
164     finally
165       {
166         socket.getPlainSocketImpl().setInChannelOperation(false);
167       }
168   }
169     
170   public boolean finishConnect ()
171     throws IOException
172   {
173     if (!isOpen())
174       throw new ClosedChannelException();
175     
176     if (!isConnected() && !connectionPending)
177       throw new NoConnectionPendingException();
178     
179     if (isConnected())
180       return true;
181
182     // FIXME: Handle blocking/non-blocking mode.
183
184     Selector selector = provider().openSelector();
185     register(selector, SelectionKey.OP_CONNECT);
186
187     if (isBlocking())
188       {
189         selector.select(); // blocking until channel is connected.
190         connectionPending = false;
191         return true;
192       }
193
194     int ready = selector.selectNow(); // non-blocking
195     if (ready == 1)
196       {
197         connectionPending = false;
198         return true;
199       }
200
201     return false;
202   }
203
204   public boolean isConnected ()
205   {
206     return socket.isConnected();
207   }
208     
209   public boolean isConnectionPending ()
210   {
211     return connectionPending;
212   }
213     
214   public Socket socket ()
215   {
216     return socket;
217   }
218
219   public int read(ByteBuffer dst) throws IOException
220   {
221     if (!isConnected())
222       throw new NotYetConnectedException();
223     
224     byte[] data;
225     int offset = 0;
226     InputStream input = socket.getInputStream();
227     int available = input.available();
228     int len = dst.remaining();
229         
230     if ((! isBlocking()) && available == 0)
231       return 0;
232     
233     if (dst.hasArray())
234       {
235         offset = dst.arrayOffset() + dst.position();
236         data = dst.array();
237       }
238     else
239       {
240         data = new byte [len];
241       }
242
243     int readBytes = 0;
244     boolean completed = false;
245
246     try
247       {
248         begin();
249         socket.getPlainSocketImpl().setInChannelOperation(true);
250         readBytes = input.read (data, offset, len);
251         completed = true;
252       }
253     finally
254       {
255         end (completed);
256         socket.getPlainSocketImpl().setInChannelOperation(false);
257       }
258
259     if (readBytes > 0)
260       if (dst.hasArray())
261         {
262           dst.position (dst.position() + readBytes);
263         }
264       else
265         {
266           dst.put (data, offset, readBytes);
267         }
268
269     return readBytes;
270   }
271     
272   public long read (ByteBuffer[] dsts, int offset, int length)
273     throws IOException
274   {
275     if (!isConnected())
276       throw new NotYetConnectedException();
277     
278     if ((offset < 0)
279         || (offset > dsts.length)
280         || (length < 0)
281         || (length > (dsts.length - offset)))
282       throw new IndexOutOfBoundsException();
283       
284     long readBytes = 0;
285
286     for (int index = offset; index < length; index++)
287       readBytes += read (dsts [index]);
288
289     return readBytes;
290   }
291      
292   public int write (ByteBuffer src)
293     throws IOException
294   {
295     if (!isConnected())
296       throw new NotYetConnectedException();
297     
298     byte[] data;
299     int offset = 0;
300     int len = src.remaining();
301     
302     if (!src.hasArray())
303       {
304         data = new byte [len];
305         src.get (data, 0, len);
306       }
307     else
308       {
309         offset = src.arrayOffset() + src.position();
310         data = src.array();
311       }
312
313     OutputStream output = socket.getOutputStream();
314     boolean completed = false;
315
316     try
317       {
318         begin();
319         socket.getPlainSocketImpl().setInChannelOperation(true);
320         output.write (data, offset, len);
321         completed = true;
322       }
323     finally
324       {
325         end (completed);
326         socket.getPlainSocketImpl().setInChannelOperation(false);
327       }
328
329     if (src.hasArray())
330       {
331         src.position (src.position() + len);
332       }
333     
334     return len;
335   }
336
337   public long write (ByteBuffer[] srcs, int offset, int length)
338     throws IOException
339   {
340     if (!isConnected())
341       throw new NotYetConnectedException();
342     
343     if ((offset < 0)
344         || (offset > srcs.length)
345         || (length < 0)
346         || (length > (srcs.length - offset)))
347       throw new IndexOutOfBoundsException();
348       
349     long writtenBytes = 0;
350
351     for (int index = offset; index < length; index++)
352       writtenBytes += write (srcs [index]);
353
354     return writtenBytes;
355   }
356 }