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: impl.create(true);
75: socket = new NIOSocket (impl, this);
76: configureBlocking(true);
77: }
78:
79: SocketChannelImpl (SelectorProvider provider,
80: NIOSocket socket)
81: throws IOException
82: {
83: super (provider);
84: this.impl = socket.getPlainSocketImpl();
85: this.socket = socket;
86: }
87:
88: public void finalizer()
89: {
90: if (isConnected())
91: {
92: try
93: {
94: close ();
95: }
96: catch (Exception e)
97: {
98: }
99: }
100: }
101:
102: PlainSocketImpl getPlainSocketImpl()
103: {
104: return impl;
105: }
106:
107: int getNativeFD()
108: {
109: return socket.getPlainSocketImpl().getNativeFD();
110: }
111:
112: protected void implCloseSelectableChannel () throws IOException
113: {
114: socket.close();
115: }
116:
117: protected void implConfigureBlocking (boolean blocking) throws IOException
118: {
119: socket.setSoTimeout (blocking ? 0 : NIOConstants.DEFAULT_TIMEOUT);
120: }
121:
122: public boolean connect (SocketAddress remote) throws IOException
123: {
124: if (!isOpen())
125: throw new ClosedChannelException();
126:
127: if (isConnected())
128: throw new AlreadyConnectedException();
129:
130: if (connectionPending)
131: throw new ConnectionPendingException();
132:
133: if (!(remote instanceof InetSocketAddress))
134: throw new UnsupportedAddressTypeException();
135:
136: if (((InetSocketAddress) remote).isUnresolved())
137: throw new UnresolvedAddressException();
138:
139: try
140: {
141: socket.getPlainSocketImpl().setInChannelOperation(true);
142:
143:
144:
145:
146: if (isBlocking())
147: {
148:
149: socket.connect (remote);
150: return true;
151: }
152:
153:
154: try
155: {
156: socket.connect (remote, NIOConstants.DEFAULT_TIMEOUT);
157: return true;
158: }
159: catch (SocketTimeoutException e)
160: {
161: connectionPending = true;
162: return false;
163: }
164: }
165: finally
166: {
167: socket.getPlainSocketImpl().setInChannelOperation(false);
168: }
169: }
170:
171: public boolean finishConnect ()
172: throws IOException
173: {
174: if (!isOpen())
175: throw new ClosedChannelException();
176:
177: if (!isConnected() && !connectionPending)
178: throw new NoConnectionPendingException();
179:
180: if (isConnected())
181: return true;
182:
183:
184:
185: Selector selector = provider().openSelector();
186: register(selector, SelectionKey.OP_CONNECT);
187:
188: if (isBlocking())
189: {
190: selector.select();
191: connectionPending = false;
192: return true;
193: }
194:
195: int ready = selector.selectNow();
196: if (ready == 1)
197: {
198: connectionPending = false;
199: return true;
200: }
201:
202: return false;
203: }
204:
205: public boolean isConnected ()
206: {
207: return socket.isConnected();
208: }
209:
210: public boolean isConnectionPending ()
211: {
212: return connectionPending;
213: }
214:
215: public Socket socket ()
216: {
217: return socket;
218: }
219:
220: public int read(ByteBuffer dst) throws IOException
221: {
222: if (!isConnected())
223: throw new NotYetConnectedException();
224:
225: byte[] data;
226: int offset = 0;
227: InputStream input = socket.getInputStream();
228: int available = input.available();
229: int len = dst.remaining();
230:
231: if ((! isBlocking()) && available == 0)
232: return 0;
233:
234: if (dst.hasArray())
235: {
236: offset = dst.arrayOffset() + dst.position();
237: data = dst.array();
238: }
239: else
240: {
241: data = new byte [len];
242: }
243:
244: int readBytes = 0;
245: boolean completed = false;
246:
247: try
248: {
249: begin();
250: socket.getPlainSocketImpl().setInChannelOperation(true);
251: readBytes = input.read (data, offset, len);
252: completed = true;
253: }
254: finally
255: {
256: end (completed);
257: socket.getPlainSocketImpl().setInChannelOperation(false);
258: }
259:
260: if (readBytes > 0)
261: if (dst.hasArray())
262: {
263: dst.position (dst.position() + readBytes);
264: }
265: else
266: {
267: dst.put (data, offset, readBytes);
268: }
269:
270: return readBytes;
271: }
272:
273: public long read (ByteBuffer[] dsts, int offset, int length)
274: throws IOException
275: {
276: if (!isConnected())
277: throw new NotYetConnectedException();
278:
279: if ((offset < 0)
280: || (offset > dsts.length)
281: || (length < 0)
282: || (length > (dsts.length - offset)))
283: throw new IndexOutOfBoundsException();
284:
285: long readBytes = 0;
286:
287: for (int index = offset; index < length; index++)
288: readBytes += read (dsts [index]);
289:
290: return readBytes;
291: }
292:
293: public int write (ByteBuffer src)
294: throws IOException
295: {
296: if (!isConnected())
297: throw new NotYetConnectedException();
298:
299: byte[] data;
300: int offset = 0;
301: int len = src.remaining();
302:
303: if (!src.hasArray())
304: {
305: data = new byte [len];
306: src.get (data, 0, len);
307: }
308: else
309: {
310: offset = src.arrayOffset() + src.position();
311: data = src.array();
312: }
313:
314: OutputStream output = socket.getOutputStream();
315: boolean completed = false;
316:
317: try
318: {
319: begin();
320: socket.getPlainSocketImpl().setInChannelOperation(true);
321: output.write (data, offset, len);
322: completed = true;
323: }
324: finally
325: {
326: end (completed);
327: socket.getPlainSocketImpl().setInChannelOperation(false);
328: }
329:
330: if (src.hasArray())
331: {
332: src.position (src.position() + len);
333: }
334:
335: return len;
336: }
337:
338: public long write (ByteBuffer[] srcs, int offset, int length)
339: throws IOException
340: {
341: if (!isConnected())
342: throw new NotYetConnectedException();
343:
344: if ((offset < 0)
345: || (offset > srcs.length)
346: || (length < 0)
347: || (length > (srcs.length - offset)))
348: throw new IndexOutOfBoundsException();
349:
350: long writtenBytes = 0;
351:
352: for (int index = offset; index < length; index++)
353: writtenBytes += write (srcs [index]);
354:
355: return writtenBytes;
356: }
357: }