Source code: org/jnp/interfaces/TimedSocketFactory.java
1 /*
2 * JBoss, the OpenSource J2EE WebOS
3 *
4 * Distributable under LGPL license.
5 * See terms of license at gnu.org.
6 */
7 package org.jnp.interfaces;
8
9 import java.io.IOException;
10 import java.net.ConnectException;
11 import java.net.InetAddress;
12 import java.net.Socket;
13 import java.net.UnknownHostException;
14 import java.util.Hashtable;
15 import javax.net.SocketFactory;
16
17 /** A concrete implementation of the SocketFactory that supports a configurable
18 timeout for the initial socket connection as well as the SO_TIMEOUT used to
19 determine how long a read will block waiting for data.
20
21 @author Scott.Stark@jboss.org
22 @version $Revision: 1.2 $
23 */
24 public class TimedSocketFactory extends SocketFactory
25 {
26 public static final String JNP_TIMEOUT = "jnp.timeout";
27 public static final String JNP_SO_TIMEOUT = "jnp.sotimeout";
28
29 /** The connection timeout in milliseconds */
30 protected int timeout = 0;
31 /** The SO_TIMEOUT in milliseconds */
32 protected int soTimeout = 0;
33
34 /** Creates a new instance of TimedSocketFactory */
35 public TimedSocketFactory()
36 {
37 }
38 public TimedSocketFactory(Hashtable env)
39 {
40 String value = (String) env.get(JNP_TIMEOUT);
41 if( value != null )
42 timeout = Integer.parseInt(value);
43 value = (String) env.get(JNP_SO_TIMEOUT);
44 if( value != null )
45 soTimeout = Integer.parseInt(value);
46 }
47
48 public Socket createSocket(String host, int port) throws IOException, UnknownHostException
49 {
50 InetAddress hostAddr = InetAddress.getByName(host);
51 return this.createSocket(hostAddr, port, null, 0);
52 }
53 public Socket createSocket(InetAddress hostAddr, int port) throws IOException
54 {
55 return this.createSocket(hostAddr, port, null, 0);
56 }
57
58 public Socket createSocket(String host, int port, InetAddress localAddr, int localPort)
59 throws IOException, UnknownHostException
60 {
61 InetAddress hostAddr = InetAddress.getByName(host);
62 return this.createSocket(hostAddr, port, localAddr, localPort);
63 }
64 public Socket createSocket(InetAddress hostAddr, int port, InetAddress localAddr, int localPort)
65 throws IOException
66 {
67 Socket socket = null;
68 if( timeout <= 0 )
69 socket = new Socket(hostAddr, port, localAddr, localPort);
70 else
71 socket = createSocket(hostAddr, port, localAddr, localPort, timeout);
72
73 socket.setSoTimeout(soTimeout);
74 return socket;
75 }
76
77 protected Socket createSocket(InetAddress hostAddr, int port,
78 InetAddress localAddr, int localPort, int connectTimeout)
79 throws IOException
80 {
81 ConnectThread t = new ConnectThread();
82 Socket socket = t.createSocket(hostAddr, port, localAddr, localPort, connectTimeout);
83 return socket;
84 }
85
86 /** A subclass of Thread used to time the blocking connect operation
87 and notify the thread attempting the socket connect of a timeout.
88 */
89 class ConnectThread extends Thread
90 {
91 IOException ex;
92 InetAddress hostAddr;
93 InetAddress localAddr;
94 int port;
95 int localPort;
96 int connectTimeout;
97 Socket socket;
98
99 ConnectThread()
100 {
101 super("JNP ConnectThread");
102 super.setDaemon(true);
103 }
104
105 /** Perform the connection in a background thread and wait upto
106 connectTimeout milliseconds for it to complete before throwing
107 a ConnectionException
108 */
109 Socket createSocket(InetAddress hostAddr, int port,
110 InetAddress localAddr, int localPort, int connectTimeout)
111 throws IOException
112 {
113 this.hostAddr = hostAddr;
114 this.port = port;
115 this.localAddr = localAddr;
116 this.localPort = localPort;
117 this.connectTimeout = connectTimeout;
118
119 try
120 {
121 synchronized( this )
122 {
123 // Perform the socket connection in a background thread
124 this.start();
125 // Wait for upto connectTimeout milliseconds for the connection
126 this.wait(connectTimeout);
127 }
128 }
129 catch(InterruptedException e)
130 {
131 throw new ConnectException("Connect attempt timed out");
132 }
133
134 // See if the connect thread exited due to an exception
135 if( ex != null )
136 throw ex;
137 // If socket is null we timed out while waiting
138 if( socket == null )
139 throw new ConnectException("Connect attempt timed out");
140
141 return socket;
142 }
143
144 public void run()
145 {
146 try
147 {
148 socket = new Socket(hostAddr, port, localAddr, localPort);
149 synchronized( this )
150 {
151 this.notify();
152 }
153 }
154 catch(IOException e)
155 {
156 this.ex = e;
157 }
158 }
159 }
160 }