1:
37:
38:
39: package ;
40:
41: import ;
42:
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
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:
142:
143:
144:
145: if (isBlocking())
146: {
147:
148: socket.connect (remote);
149: return true;
150: }
151:
152:
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:
183:
184: Selector selector = provider().openSelector();
185: register(selector, SelectionKey.OP_CONNECT);
186:
187: if (isBlocking())
188: {
189: selector.select();
190: connectionPending = false;
191: return true;
192: }
193:
194: int ready = selector.selectNow();
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: }