![JAR search and dependency download from the Maven repository](/logo.png)
com.unboundid.ldap.sdk.ConnectThread Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of unboundid-ldapsdk-commercial-edition Show documentation
Show all versions of unboundid-ldapsdk-commercial-edition Show documentation
The UnboundID LDAP SDK for Java is a fast, comprehensive, and easy-to-use
Java API for communicating with LDAP directory servers and performing
related tasks like reading and writing LDIF, encoding and decoding data
using base64 and ASN.1 BER, and performing secure communication. This
package contains the Commercial Edition of the LDAP SDK, which includes
all of the general-purpose functionality contained in the Standard
Edition, plus additional functionality specific to UnboundID server
products.
The newest version!
/*
* Copyright 2009-2017 UnboundID Corp.
* All Rights Reserved.
*/
/*
* Copyright (C) 2009-2017 UnboundID Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License (GPLv2 only)
* or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
package com.unboundid.ldap.sdk;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.SocketFactory;
import static com.unboundid.ldap.sdk.LDAPMessages.*;
import static com.unboundid.util.Debug.*;
import static com.unboundid.util.StaticUtils.*;
/**
* This class provides a thread that may be used to create an establish a
* socket using a provided socket factory with a specified timeout. This
* provides a more reliable mechanism for attempting to establish a connection
* with a timeout than using the {@code Socket.connect} method that takes a
* timeout because this method cannot be used with some socket factories (like
* SSL socket factories), and that method is also not reliable for hung servers
* which are listening for connections but are not responsive. The
* {@link #getConnectedSocket} method should be called immediately after
* starting the thread to wait for the connection to be established, or to fail
* if it cannot be successfully established within the given timeout period.
*/
final class ConnectThread
extends Thread
{
// Indicates whether the connection has been successfully established.
private final AtomicBoolean connected;
// The socket used for the connection.
private final AtomicReference socket;
// The thread being used to establish the connection.
private final AtomicReference thread;
// The exception caught while trying to establish the connection.
private final AtomicReference exception;
// A latch that will be used to indicate that the thread has actually started.
private final CountDownLatch startLatch;
// The maximum length of time in milliseconds that the connection attempt
// should be allowed to block.
private final int connectTimeoutMillis;
// The port to which the connection should be established.
private final int port;
// The socket factory that will be used to create the connection.
private final SocketFactory socketFactory;
// The address to which the connection should be established.
private final InetAddress address;
/**
* Creates a new instance of this connect thread with the provided
* information.
*
* @param socketFactory The socket factory to use to create the
* socket.
* @param address The address to which the connection should be
* established.
* @param port The port to which the connection should be
* established.
* @param connectTimeoutMillis The maximum length of time in milliseconds
* that the connection attempt should be allowed
* to block.
*/
ConnectThread(final SocketFactory socketFactory, final InetAddress address,
final int port, final int connectTimeoutMillis)
{
super("Background connect thread for " + address + ':' + port);
setDaemon(true);
this.socketFactory = socketFactory;
this.address = address;
this.port = port;
this.connectTimeoutMillis = connectTimeoutMillis;
connected = new AtomicBoolean(false);
socket = new AtomicReference();
thread = new AtomicReference();
exception = new AtomicReference();
startLatch = new CountDownLatch(1);
}
/**
* Attempts to establish the connection.
*/
@Override()
public void run()
{
thread.set(Thread.currentThread());
startLatch.countDown();
try
{
boolean connectNeeded;
Socket s;
try
{
s = socketFactory.createSocket();
connectNeeded = true;
}
catch (final Exception e)
{
debugException(e);
s = socketFactory.createSocket(address, port);
connectNeeded = false;
}
socket.set(s);
if (connectNeeded)
{
s.connect(new InetSocketAddress(address, port), connectTimeoutMillis);
}
connected.set(true);
}
catch (final Throwable t)
{
debugException(t);
exception.set(t);
}
finally
{
thread.set(null);
}
}
/**
* Gets the connection after it has been established. This should be called
* immediately after starting the thread.
*
* @return The socket that has been connected to the target server.
*
* @throws LDAPException If a problem occurs while attempting to establish
* the connection, or if it cannot be established
* within the specified time limit.
*/
Socket getConnectedSocket()
throws LDAPException
{
while (startLatch.getCount() > 0L)
{
try
{
startLatch.await();
break;
}
catch (final InterruptedException ie)
{
debugException(ie);
Thread.currentThread().interrupt();
throw new LDAPException(ResultCode.LOCAL_ERROR,
ERR_CONNECT_THREAD_INTERRUPTED.get(address.getHostAddress(), port,
getExceptionMessage(ie)),
ie);
}
}
final Thread t = thread.get();
if (t != null)
{
try
{
t.join(connectTimeoutMillis);
}
catch (final InterruptedException ie)
{
debugException(ie);
Thread.currentThread().interrupt();
throw new LDAPException(ResultCode.LOCAL_ERROR,
ERR_CONNECT_THREAD_INTERRUPTED.get(address.getHostAddress(), port,
getExceptionMessage(ie)),
ie);
}
}
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, connectTimeoutMillis));
}
else
{
throw new LDAPException(ResultCode.CONNECT_ERROR,
ERR_CONNECT_THREAD_EXCEPTION.get(address, port,
getExceptionMessage(cause)), cause);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy