package com.hwlcn.ldap.ldap.sdk; import java.net.Socket; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import javax.net.SocketFactory; import static com.hwlcn.ldap.ldap.sdk.LDAPMessages.*; import static com.hwlcn.ldap.util.Debug.*; import static com.hwlcn.ldap.util.StaticUtils.*; final class ConnectThread extends Thread { private final AtomicBoolean connected; private final AtomicBoolean started; private final AtomicReference<Socket> socket; private final AtomicReference<Thread> thread; private final AtomicReference<Throwable> exception; private final int port; private final SocketFactory socketFactory; private final String address; ConnectThread(final SocketFactory socketFactory, final String address, final int port) { super("Background connect thread for " + address + ':' + port); setDaemon(true); this.socketFactory = socketFactory; this.address = address; this.port = port; connected = new AtomicBoolean(false); started = new AtomicBoolean(false); socket = new AtomicReference<Socket>(); thread = new AtomicReference<Thread>(); exception = new AtomicReference<Throwable>(); } @Override() public void run() { thread.set(Thread.currentThread()); started.set(true); try { socket.set(socketFactory.createSocket(address, port)); connected.set(true); } catch (final Throwable t) { debugException(t); exception.set(t); } finally { thread.set(null); } } Socket getConnectedSocket(final long timeoutMillis) throws LDAPException { while (! started.get()) { Thread.yield(); } final Thread t = thread.get(); if (t != null) { try { t.join(timeoutMillis); } catch (Exception e) { debugException(e); } } if (connected.get()) { return socket.get(); } try { if (t != null) { t.interrupt(); } } catch (final Exception e) { debugException(e); } try { final Socket s = socket.get(); if (s != null) { s.close(); } } catch (final Exception e) { debugException(e); } final Throwable cause = exception.get(); if (cause == null) { throw new LDAPException(ResultCode.CONNECT_ERROR, ERR_CONNECT_THREAD_TIMEOUT.get(address, port, timeoutMillis)); } else { throw new LDAPException(ResultCode.CONNECT_ERROR, ERR_CONNECT_THREAD_EXCEPTION.get(address, port, getExceptionMessage(cause)), cause); } } }