*/
if (altFactoryList.size() == 0) {
return initialFactory.createSocket(host, port);
}
RMISocketFactory factory;
/*
* If we remember successfully connecting to this host before,
* use the same factory.
*/
factory = (RMISocketFactory) successTable.get(host);
if (factory != null) {
if (proxyLog.isLoggable(Log.BRIEF)) {
proxyLog.log(Log.BRIEF,
"previously successful factory found: " + factory);
}
return factory.createSocket(host, port);
}
/*
* Next, try a direct socket connection. Open socket in another
* thread and only wait for specified timeout, in case the socket
* would otherwise spend minutes trying an unreachable host.
*/
Socket initialSocket = null;
Socket fallbackSocket = null;
final AsyncConnector connector =
new AsyncConnector(initialFactory, host, port,
AccessController.getContext());
// connection must be attempted with
// this thread's access control context
IOException initialFailure = null;
try {
synchronized (connector) {
Thread t = (Thread)
java.security.AccessController.doPrivileged(
new NewThreadAction(connector, "AsyncConnector",
true));
t.start();
try {
long now = System.currentTimeMillis();
long deadline = now + connectTimeout;
do {
connector.wait(deadline - now);
initialSocket = checkConnector(connector);
if (initialSocket != null)
break;
now = System.currentTimeMillis();
} while (now < deadline);
} catch (InterruptedException e) {
throw new InterruptedIOException(
"interrupted while waiting for connector");
}
}
// assume no route to host (for now) if no connection yet
if (initialSocket == null)
throw new NoRouteToHostException(
"connect timed out: " + host);
proxyLog.log(Log.BRIEF, "direct socket connection successful");
return initialSocket;
} catch (UnknownHostException e) {
initialFailure = e;
} catch (NoRouteToHostException e) {
initialFailure = e;
} catch (SocketException e) {
if (eagerHttpFallback) {
initialFailure = e;
} else {
throw e;
}
} finally {
if (initialFailure != null) {
if (proxyLog.isLoggable(Log.BRIEF)) {
proxyLog.log(Log.BRIEF,
"direct socket connection failed: ", initialFailure);
}
// Finally, try any alternate connection mechanisms.
for (int i = 0; i < altFactoryList.size(); ++ i) {
factory = (RMISocketFactory) altFactoryList.elementAt(i);
try {
if (proxyLog.isLoggable(Log.BRIEF)) {
proxyLog.log(Log.BRIEF,
"trying with factory: " + factory);
}
// For HTTP connections, the output (POST request) must
// be sent before we verify a successful connection.
// So, sacrifice a socket for the sake of testing...
// The following sequence should verify a successful
// HTTP connection if no IOException is thrown.
Socket testSocket = factory.createSocket(host, port);
InputStream in = testSocket.getInputStream();
int b = in.read(); // probably -1 for EOF...
testSocket.close();
} catch (IOException ex) {
if (proxyLog.isLoggable(Log.BRIEF)) {
proxyLog.log(Log.BRIEF, "factory failed: ", ex);
}
continue;
}
proxyLog.log(Log.BRIEF, "factory succeeded");
// factory succeeded, open new socket for caller's use
try {
fallbackSocket = factory.createSocket(host, port);
} catch (IOException ex) { // if it fails 2nd time,
} // just give up
break;
}
}