1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.river.discovery;
20
21 import java.io.IOException;
22 import java.net.InetAddress;
23 import java.net.InetSocketAddress;
24 import java.net.Socket;
25 import java.net.SocketException;
26 import java.net.SocketTimeoutException;
27 import java.net.UnknownHostException;
28 import net.jini.core.constraint.InvocationConstraints;
29
30
31
32
33
34
35
36 public abstract class MultiIPDiscovery {
37
38 public final static int DEFAULT_TIMEOUT = 60 * 1000;
39
40 public UnicastResponse getResponse(String scheme, String host, int port, InvocationConstraints constraints)
41 throws IOException, ClassNotFoundException
42 {
43 InetAddress addrs[] = null;
44 try {
45 addrs = InetAddress.getAllByName(host);
46 } catch (UnknownHostException uhe) {
47
48
49 }
50
51 DiscoveryConstraints dc = DiscoveryConstraints.process(constraints);
52 int pv = dc.chooseProtocolVersion();
53 Discovery disco;
54
55
56
57
58
59
60 if ("https".equals(scheme)){
61 disco = Discovery.getUnicastHttps(null);
62 } else {
63 switch (pv) {
64 case Discovery.PROTOCOL_VERSION_1:
65 disco = Discovery.getProtocol1();
66 break;
67 case Discovery.PROTOCOL_VERSION_2:
68 disco = Discovery.getProtocol2(null);
69 break;
70 default:
71 throw new AssertionError(pv);
72 }
73 }
74
75 long deadline = dc.getConnectionDeadline(Long.MAX_VALUE);
76 long connectionTimeout = getTimeout(deadline);
77
78 if (addrs == null) {
79 return getSingleResponse(host, connectionTimeout, port, dc, disco);
80 }
81
82 IOException ioEx = null;
83 SecurityException secEx = null;
84 ClassNotFoundException cnfEx = null;
85 for (int i = 0, l = addrs.length; i < l; i++) {
86 try {
87 return getSingleResponse(addrs[i].getHostAddress(),
88 connectionTimeout, port, dc, disco);
89 } catch (ClassNotFoundException ex) {
90 cnfEx = ex;
91 singleResponseException(ex, addrs[i], port);
92 } catch (IOException ex) {
93 ioEx = ex;
94 singleResponseException(ex, addrs[i], port);
95 } catch (SecurityException ex) {
96 secEx = ex;
97 singleResponseException(ex, addrs[i], port);
98 }
99
100 try {
101 connectionTimeout = getTimeout(deadline);
102 } catch (SocketTimeoutException ex) {
103 if (ioEx == null) {
104 ioEx = ex;
105 }
106
107 break;
108 }
109 }
110 if (cnfEx != null) {
111 throw cnfEx;
112 }
113 if (ioEx != null) {
114 throw ioEx;
115 }
116 assert (secEx != null);
117 throw secEx;
118 }
119
120 private long getTimeout(long deadline) throws SocketTimeoutException {
121 long now = System.currentTimeMillis();
122 if (now >= deadline) {
123 throw new SocketTimeoutException("timeout expired before"
124 + " connection attempted");
125 }
126 return deadline - now;
127 }
128
129 private UnicastResponse getSingleResponse(String host,
130 long connectionTimeout,
131 int port,
132 DiscoveryConstraints dc,
133 Discovery disco)
134 throws IOException, ClassNotFoundException
135 {
136 Socket s = new Socket();
137 boolean discoveryAttempted = false;
138 try {
139 if (connectionTimeout > Integer.MAX_VALUE) {
140 s.connect(new InetSocketAddress(host, port));
141 } else {
142 s.connect(new InetSocketAddress(host, port),
143 (int) connectionTimeout);
144 }
145 try {
146 s.setTcpNoDelay(true);
147 } catch (SocketException e) {
148
149 }
150 try {
151 s.setKeepAlive(true);
152 } catch (SocketException e) {
153
154 }
155 s.setSoTimeout(dc.getUnicastSocketTimeout(
156 getDefaultUnicastSocketTimeout()));
157 discoveryAttempted = true;
158 return performDiscovery(disco, dc, s);
159 } finally {
160 try {
161 s.close();
162 } catch (IOException e) {
163 if (discoveryAttempted) {
164 socketCloseException(e);
165 }
166 }
167 }
168 }
169
170
171
172
173
174
175 protected int getDefaultUnicastSocketTimeout() {
176 return DEFAULT_TIMEOUT;
177 }
178
179
180
181
182
183
184
185 protected void singleResponseException(Exception ex,
186 InetAddress addr,
187 int port)
188 {
189 }
190
191
192
193
194
195 protected void socketCloseException(IOException ex) {}
196
197
198
199
200
201 protected abstract UnicastResponse performDiscovery(Discovery disco,
202 DiscoveryConstraints dc,
203 Socket s)
204 throws IOException, ClassNotFoundException;
205
206 }