KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > server > ss > provider > ASClientSocketImpl


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23 package com.sun.enterprise.server.ss.provider;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.net.*;
27 import java.nio.*;
28 import java.nio.channels.*;
29 import java.util.*;
30
31 import java.util.logging.*;
32 import com.sun.enterprise.server.ss.spi.ASSocketFacadeUtils;
33 import com.sun.enterprise.server.ss.spi.ASSocketServiceFacade;
34 import com.sun.logging.LogDomains;
35
36 /**
37  * NIO based SocketImpl implementation used by java.net.Socket. The implementation
38  * is used always in the non-blocking mode.
39  */

40
41 class ASClientSocketImpl extends java.net.SocketImpl JavaDoc {
42     private static Logger logger = LogDomains.getLogger(LogDomains.CORE_LOGGER);
43
44     private SocketChannel sc;
45     private Socket sock;
46     private InputStream JavaDoc is;
47
48     public int available() throws IOException JavaDoc {
49         return 0;
50     }
51
52     /**
53      * Apart from closing the internal socket ant it's channel,
54      * we need to shutdown the output also. This is necessary because
55      * 1) A normal socket's InputStream will get an EOF, when its remote
56      * socket closes.
57      * 2) But in case of non blocking IO, if a selector is registered
58      * on the channel with OP_WRITE key, the output of the socket
59      * doesnt get shutdown immediately even when the socket/channel
60      * is closed. This could lead to its corrsponding InputStream
61      * longer to get closed.
62      * We explicitely shutdown to fix this problem.
63      *
64      * Note that, if a program, expects its output stream to be open
65      * for a few microseconds after the socket is closed and try to do
66      * some smart stuff, may not work correctly. But that is a very
67      * very very rare case.
68      */

69     public void close() throws IOException JavaDoc {
70         if (sock != null) {
71             try {
72                 sock.shutdownOutput();
73             } catch (Exception JavaDoc e) {
74                 if ( logger.isLoggable(Level.FINER) ) {
75                     logger.log(Level.FINER, "" + e.getMessage(), e);
76                 }
77             }
78             try {
79             sock.close();
80                 sc.close();
81             } catch (IOException JavaDoc ie) {
82                 if ( logger.isLoggable(Level.FINER) ) {
83                     logger.log(Level.FINER, "" + ie.getMessage(), ie);
84                 }
85                 //throw ie;
86
} catch (Error JavaDoc er) {
87                 if ( logger.isLoggable(Level.FINE) ) {
88                     logger.log(Level.FINE, "" + er.getMessage(), er);
89                 }
90                 // This ideally should not happen...
91
}
92             is = null;
93         }
94     }
95
96     public int getLocalPort() {
97         try {
98             return getClientSocket().getLocalPort();
99         } catch (IOException JavaDoc ie) {
100             if ( logger.isLoggable(Level.FINE) ) {
101                  logger.log(Level.FINE, "" + ie.getMessage(), ie);
102             }
103             // Typically this will never be executed.
104
return super.getLocalPort();
105         }
106     }
107
108     public int getPort() {
109         try {
110             return getClientSocket().getPort();
111         } catch (IOException JavaDoc ie) {
112             if ( logger.isLoggable(Level.FINE) ) {
113                  logger.log(Level.FINE, "" + ie.getMessage(), ie);
114             }
115             // Typically this will never be executed.
116
return super.getPort();
117         }
118     }
119
120     public void shutdownInput() throws IOException JavaDoc {
121         getClientSocket().shutdownInput();
122     }
123
124     public void shutdownOutput() throws IOException JavaDoc {
125         getClientSocket().shutdownOutput();
126     }
127
128     public boolean supportsUrgentData() {
129         return true;
130     }
131
132     public void sendUrgentData(int i) throws IOException JavaDoc {
133         getClientSocket().sendUrgentData(i);
134     }
135
136     public void listen(int i) throws IOException JavaDoc {
137     throw new UnsupportedOperationException JavaDoc(
138             "listen() not supported in ASClientSocketImpl");
139     }
140
141     public void create(boolean stream) throws IOException JavaDoc {
142     // No-op: stream is always true when called from Socket
143
}
144     
145     public java.io.InputStream JavaDoc getInputStream() throws IOException JavaDoc {
146         if (this.is == null) {
147             this.is = new ASInputStream(getClientSocketChannel(), getClientSocket());
148         }
149         return this.is;
150     }
151
152     public java.io.OutputStream JavaDoc getOutputStream() throws IOException JavaDoc {
153         return new ASOutputStream(getClientSocketChannel(), getClientSocket());
154     }
155
156     public void bind(java.net.InetAddress JavaDoc ia, int port) throws IOException JavaDoc {
157         InetSocketAddress isa = new InetSocketAddress(ia, port);
158         getClientSocket().bind(isa);
159     }
160
161     public void connect(java.lang.String JavaDoc host, int port) throws IOException JavaDoc {
162         InetSocketAddress isa = new InetSocketAddress(host, port);
163         if ( logger.isLoggable(Level.FINE) ) {
164             logger.fine("In ASClientSocketImpl.connect, host = "+host
165                              +" port = "+port);
166         }
167         connect(isa);
168     }
169
170     public void connect(java.net.InetAddress JavaDoc ia, int port) throws IOException JavaDoc {
171         InetSocketAddress isa = new InetSocketAddress(ia, port);
172         if ( logger.isLoggable(Level.FINE) ) {
173         logger.fine("In ASClientSocketImpl.connect, host = "+ia.getHostName()
174                                    +" port = "+port);
175         }
176         connect(isa);
177     }
178
179     private void connect(InetSocketAddress isa) throws IOException JavaDoc {
180         connect(isa,0);
181     }
182
183     public void connect(java.net.SocketAddress JavaDoc sa, int timeout) throws IOException JavaDoc {
184         if (sa == null || !(sa instanceof InetSocketAddress)) {
185             throw new IllegalArgumentException JavaDoc("unsupported address type");
186     }
187     
188         InetSocketAddress addr = (InetSocketAddress) sa;
189         if (addr.isUnresolved()) {
190             throw new UnknownHostException(addr.getHostName());
191     }
192         this.port = addr.getPort();
193         this.address = addr.getAddress();
194
195         // Check whether the socketservice is notified. If it is not, then
196
// this is the first connection to the service. This will trigger
197
// the startup. So, this connection should be serviced only after
198
// the completion of service startup.
199
boolean waitForStartupReqd = ! ASSocketFacadeUtils.getASSocketService().
200                                       socketServiceNotified(this.port);
201
202         SocketChannel ch = getClientSocketChannel();
203         boolean connected = ch.connect(sa);
204     if ( !connected ) {
205         waitForSelect(timeout);
206         if (ch.finishConnect() == false) {
207         throw new IOException JavaDoc("Connection timed out");
208         }
209     }
210
211     // Inform the ASSocketService about this socket, so that it can
212
// correctly block remote sockets while allowing local loopback sockets.
213
// Note: this needs to be called when NIO sockets are created too,
214
// for now we dont do it because the Windows NIO impl does not allow
215
// SocketChannel to be wrapped (it casts the SocketChannel to an
216
// internal class).
217
Socket connectedSocket = sc.socket();
218         if (waitForStartupReqd) {
219             ASSocketFacadeUtils.getASSocketService().
220             waitOnClientConnection(connectedSocket);
221         }
222     ASSocketFacadeUtils.getASSocketService().clientSocketConnected(
223                                                               sc.socket());
224     }
225
226     public void accept(java.net.SocketImpl JavaDoc si) throws IOException JavaDoc {
227     throw new UnsupportedOperationException JavaDoc(
228             "accept() not supported in ASClientSocketImpl");
229     }
230
231     public void setOption(int opt,java.lang.Object JavaDoc val) throws SocketException {
232     try {
233         switch (opt) {
234         case SO_LINGER:
235         if (val == null || (!(val instanceof Integer JavaDoc) && !(val instanceof Boolean JavaDoc)))
236             throw new SocketException("Bad parameter for option");
237         if (val instanceof Boolean JavaDoc) {
238             if ( ((Boolean JavaDoc)val).booleanValue() == true )
239             throw new SocketException("Bad parameter for option");
240             getClientSocket().setSoLinger( false, 0);
241         } else {
242             getClientSocket().setSoLinger( true, ((Integer JavaDoc) val).intValue());
243         }
244         break;
245         case SO_TIMEOUT:
246         if (val == null || (!(val instanceof Integer JavaDoc)))
247             throw new SocketException("Bad parameter for SO_TIMEOUT");
248         int tmp = ((Integer JavaDoc) val).intValue();
249         if (tmp < 0)
250             throw new IllegalArgumentException JavaDoc("timeout < 0");
251         //timeout = tmp;
252
getClientSocket().setSoTimeout( tmp );
253         break;
254         case IP_TOS:
255          if (val == null || !(val instanceof Integer JavaDoc)) {
256              throw new SocketException("bad argument for IP_TOS");
257          }
258          int trafficClass = ((Integer JavaDoc)val).intValue();
259          getClientSocket().setTrafficClass( trafficClass );
260          break;
261         case SO_BINDADDR:
262         throw new SocketException("Cannot re-bind socket");
263         case TCP_NODELAY:
264         if (val == null || !(val instanceof Boolean JavaDoc))
265             throw new SocketException("bad parameter for TCP_NODELAY");
266         
267         getClientSocket().setTcpNoDelay( ((Boolean JavaDoc)val).booleanValue() );
268         break;
269         case SO_SNDBUF:
270         if (val == null || !(val instanceof Integer JavaDoc) ||
271             !(((Integer JavaDoc)val).intValue() > 0)) {
272             throw new SocketException("bad parameter for SO_SNDBUF " );
273         }
274         getClientSocket().setSendBufferSize( ((Integer JavaDoc) val).intValue() );
275         break;
276         case SO_RCVBUF:
277         if (val == null || !(val instanceof Integer JavaDoc) ||
278             !(((Integer JavaDoc)val).intValue() > 0)) {
279             throw new SocketException("bad parameter for SO_SNDBUF " +
280                           "or SO_RCVBUF");
281         }
282         getClientSocket().setReceiveBufferSize( ((Integer JavaDoc) val).intValue() );
283         break;
284         case SO_KEEPALIVE:
285         if (val == null || !(val instanceof Boolean JavaDoc))
286             throw new SocketException("bad parameter for SO_KEEPALIVE");
287         getClientSocket().setKeepAlive( ((Boolean JavaDoc)val).booleanValue() );
288         break;
289         case SO_OOBINLINE:
290         if (val == null || !(val instanceof Boolean JavaDoc))
291             throw new SocketException("bad parameter for SO_OOBINLINE");
292         getClientSocket().setOOBInline( ((Boolean JavaDoc)val).booleanValue() );
293         break;
294         case SO_REUSEADDR:
295         if (val == null || !(val instanceof Boolean JavaDoc))
296             throw new SocketException("bad parameter for SO_REUSEADDR");
297         getClientSocket().setReuseAddress( ((Boolean JavaDoc)val).booleanValue() );
298         break;
299         default:
300         throw new SocketException("unrecognized TCP option: " + opt);
301         }
302
303     } catch ( IOException JavaDoc ioex ) {
304         if ( ioex instanceof SocketException )
305         throw ((SocketException)ioex);
306         else
307         throw (SocketException)(new SocketException()).initCause(ioex);
308     }
309     }
310
311     public Object JavaDoc getOption(int opt) throws SocketException {
312         switch (opt) {
313         case SO_LINGER:
314             return new Integer JavaDoc(sock.getSoLinger());
315         case SO_TIMEOUT:
316             return new Integer JavaDoc(sock.getSoTimeout());
317         case IP_TOS:
318              return new Integer JavaDoc(sock.getTrafficClass());
319         case SO_BINDADDR:
320         return sock.getInetAddress();
321         case TCP_NODELAY:
322             return new Boolean JavaDoc(sock.getTcpNoDelay());
323         case SO_SNDBUF:
324             return new Integer JavaDoc(sock.getSendBufferSize());
325         case SO_RCVBUF:
326             return new Integer JavaDoc(sock.getReceiveBufferSize());
327         case SO_KEEPALIVE:
328             return new Boolean JavaDoc(sock.getKeepAlive());
329         case SO_OOBINLINE:
330             return new Boolean JavaDoc(sock.getOOBInline());
331         case SO_REUSEADDR:
332             return new Boolean JavaDoc(sock.getReuseAddress());
333         default:
334             throw new SocketException("unrecognized TCP option: " + opt);
335         }
336     }
337
338     private Socket getClientSocket() throws IOException JavaDoc {
339     if ( sock == null ) {
340             createSocket();
341     }
342     return sock;
343     }
344
345     private SocketChannel getClientSocketChannel() throws IOException JavaDoc {
346     if ( sc == null ) {
347             createSocket();
348     }
349     return sc;
350     }
351
352     private void createSocket() throws IOException JavaDoc {
353     sc = SocketChannel.open();
354         sc.configureBlocking(false);
355     sock = sc.socket();
356     }
357
358
359     private void waitForSelect(long timeout) throws IOException JavaDoc {
360         Selector selector = Selector.open();
361         this.sc.register(selector, SelectionKey.OP_CONNECT);
362         
363         selectorblock:
364             while (true) {
365                 try {
366                     int n = selector.select(timeout);
367                     if (n==0 && this.sc.finishConnect()) {
368                         break;
369                     }
370                     Iterator it = selector.selectedKeys().iterator();
371                     while (it.hasNext()) {
372                         SelectionKey selKey = (SelectionKey)it.next();
373                         if (selKey.isValid() && selKey.isConnectable()) {
374                             it.remove();
375                             break selectorblock;
376                         }
377                     }
378                 } catch (Exception JavaDoc e) {
379                     throw (IOException JavaDoc) (new IOException JavaDoc()).initCause(e);
380                 }
381             }
382         try {
383             selector.close();
384         } catch (IOException JavaDoc ie) {
385             if ( logger.isLoggable(Level.FINE) ) {
386                 logger.log(Level.FINE, ie.getMessage(), ie);
387             }
388         }
389     }
390
391     // Called from ASServerSocketImpl
392
void setClientSocket(Socket s) throws IOException JavaDoc {
393     sock = s;
394     sc = sock.getChannel();
395         sc.configureBlocking(false);
396         localport = sock.getLocalPort();
397         port = sock.getPort();
398         address = sock.getInetAddress();
399     }
400
401     protected void finalize() throws Throwable JavaDoc {
402         try {
403             close();
404         } catch (Throwable JavaDoc t) {}
405     }
406     
407 }
408
409
Popular Tags