
com.unboundid.ldap.sdk.ServerSetBlacklistManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of unboundid-ldapsdk Show documentation
Show all versions of unboundid-ldapsdk 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 Standard Edition of the LDAP SDK, which is a
complete, general-purpose library for communicating with LDAPv3 directory
servers.
/*
* Copyright 2019 Ping Identity Corporation
* All Rights Reserved.
*/
/*
* Copyright (C) 2019 Ping Identity Corporation
*
* 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.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.SocketFactory;
import com.unboundid.util.Debug;
import com.unboundid.util.Mutable;
import com.unboundid.util.ObjectPair;
import com.unboundid.util.StaticUtils;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;
import com.unboundid.util.Validator;
/**
* This class provides a mechanism for maintaining a blacklist of servers that
* have recently been found to be unacceptable for use by a server set. Server
* sets that use this class can temporarily avoid trying to access servers that
* may be experiencing problems.
*/
@Mutable()
@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
final class ServerSetBlacklistManager
{
// A reference to a timer that is used to periodically check the status of
// blacklisted servers.
private final AtomicReference timerReference;
// The bind request to use to authenticate newly created connections.
private final BindRequest bindRequest;
// The connection options to use when creating connections.
private final LDAPConnectionOptions connectionOptions;
// The length of time, in milliseconds, between checks to determine whether
// a server should be removed from the blacklist.
private final long checkIntervalMillis;
// A map of currently blacklisted servers.
private final Map,
LDAPConnectionPoolHealthCheck> blacklistedServers;
// The post-connect processor to use for newly created connections.
private final PostConnectProcessor postConnectProcessor;
// The socket factory to use when creating connections.
private final SocketFactory socketFactory;
// A string representation of the associated server set.
private final String serverSetString;
/**
* Creates a new server set blacklist manager with the provided information.
*
* @param serverSet The server set with which this blacklist
* manager is associated.
* @param socketFactory An optional socket factory to use when
* creating connections. If this is
* {@code null}, a default socket factory will
* be used.
* @param connectionOptions An optional set of connection options to use
* when creating connections. If this is
* {@code null}, a default set of connection
* options will be used.
* @param bindRequest An optional bind request to use to
* authenticate connections that are
* established. It may be {@code null} if no
* authentication should be performed.
* @param postConnectProcessor An optional post-connect processor that
* should be invoked for any connection that is
* established. It may be {@code null} if no
* post-connect processing should be performed.
* @param checkIntervalMillis The length of time, in milliseconds, between
* checks to determine whether a server should
* be removed from the blacklist.
*/
ServerSetBlacklistManager(final ServerSet serverSet,
final SocketFactory socketFactory,
final LDAPConnectionOptions connectionOptions,
final BindRequest bindRequest,
final PostConnectProcessor postConnectProcessor,
final long checkIntervalMillis)
{
Validator.ensureTrue((checkIntervalMillis > 0L),
"ServerSetBlacklistManager.checkIntervalMillis must be greater " +
"than zero.");
this.checkIntervalMillis = checkIntervalMillis;
serverSetString = serverSet.toString();
if (socketFactory == null)
{
this.socketFactory = SocketFactory.getDefault();
}
else
{
this.socketFactory = socketFactory;
}
if (connectionOptions == null)
{
this.connectionOptions = new LDAPConnectionOptions();
}
else
{
this.connectionOptions = connectionOptions;
}
this.bindRequest = bindRequest;
this.postConnectProcessor = postConnectProcessor;
blacklistedServers =
new ConcurrentHashMap<>(StaticUtils.computeMapCapacity(10));
timerReference = new AtomicReference<>();
}
/**
* Indicates whether the blacklist is currently empty.
*
* @return {@code true} if the blacklist is currently empty, or {@code false}
* if it contains at least one server.
*/
boolean isEmpty()
{
if (blacklistedServers.isEmpty())
{
return true;
}
else
{
ensureTimerIsRunning();
return false;
}
}
/**
* Retrieves the number of servers currently on the blacklist.
*
* @return The number of servers currently on the blacklist.
*/
int size()
{
if (blacklistedServers.isEmpty())
{
return 0;
}
else
{
ensureTimerIsRunning();
return blacklistedServers.size();
}
}
/**
* Retrieves a list of the servers currently on the blacklist.
*
* @return A list of the servers currently on the blacklist.
*/
Set> getBlacklistedServers()
{
if (! blacklistedServers.isEmpty())
{
ensureTimerIsRunning();
}
return new HashSet<>(blacklistedServers.keySet());
}
/**
* Indicates whether the specified server is currently on the blacklist.
*
* @param host The address of the server for which to make the
* determination. It must not be {@code null}.
* @param port The port of the server for which to make the determination.
* It must be between 1 and 65535, inclusive.
*
* @return {@code true} if the server is on the blacklist, or {@code false}
* if not.
*/
boolean isBlacklisted(final String host, final int port)
{
if (blacklistedServers.isEmpty())
{
return false;
}
else
{
ensureTimerIsRunning();
return blacklistedServers.containsKey(new ObjectPair<>(host, port));
}
}
/**
* Indicates whether the specified server is currently on the blacklist.
*
* @param hostPort An {@code ObjectPair} containing the address and port of
* the server for which to make the determination. It must
* not be {@code null}.
*
* @return {@code true} if the server is on the blacklist, or {@code false}
* if not.
*/
boolean isBlacklisted(final ObjectPair hostPort)
{
if (blacklistedServers.isEmpty())
{
return false;
}
else
{
ensureTimerIsRunning();
return blacklistedServers.containsKey(hostPort);
}
}
/**
* Adds the specified server to the blacklist.
*
* @param host The address of the server to be added. It must not be
* {@code null}.
* @param port The port of the server to be added. It must be
* between 1 and 65535, inclusive.
* @param healthCheck The health check to use for periodic checks to see if
* the server can be removed from the blacklist. It may
* be {@code null} if no health checking is required.
*/
void addToBlacklist(final String host, final int port,
final LDAPConnectionPoolHealthCheck healthCheck)
{
addToBlacklist(new ObjectPair<>(host, port), healthCheck);
}
/**
* Adds the specified server to the blacklist.
*
* @param hostPort An {@code ObjectPair} containing the address and port
* of the server to be added. It must not be
* {@code null}.
* @param healthCheck The health check to use for periodic checks to see if
* the server can be removed from the blacklist. It may
* be {@code null} if no health checking is required.
*/
void addToBlacklist(final ObjectPair hostPort,
final LDAPConnectionPoolHealthCheck healthCheck)
{
if (healthCheck == null)
{
blacklistedServers.put(hostPort, new LDAPConnectionPoolHealthCheck());
}
else
{
blacklistedServers.put(hostPort, healthCheck);
}
ensureTimerIsRunning();
}
/**
* Removes the specified server from the blacklist.
*
* @param host The address of the server to be removed. It must not be
* {@code null}.
* @param port The port of the server to be removed. It must be between 1
* and 65535, inclusive.
*/
void removeFromBlacklist(final String host, final int port)
{
removeFromBlacklist(new ObjectPair<>(host, port));
}
/**
* Removes the specified server from the blacklist.
*
* @param hostPort An {@code ObjectPair} containing the address and port of
* the server to be removed. It must not be {@code null}.
*/
void removeFromBlacklist(final ObjectPair hostPort)
{
blacklistedServers.remove(hostPort);
if (! blacklistedServers.isEmpty())
{
ensureTimerIsRunning();
}
}
/**
* Clears the blacklist.
*/
void clear()
{
blacklistedServers.clear();
}
/**
* Ensures that there is a timer to periodically check the status of
* blacklisted servers.
*/
private synchronized void ensureTimerIsRunning()
{
Timer timer = timerReference.get();
if (timer == null)
{
timer = new Timer(
"ServerSet Blacklist Manager Timer for " + serverSetString, true);
timerReference.set(timer);
timer.scheduleAtFixedRate(new ServerSetBlacklistManagerTimerTask(this),
checkIntervalMillis, checkIntervalMillis);
}
}
/**
* Checks all blacklisted servers to see if any of them should be removed from
* the blacklist. If there are no servers on the blacklist and the timer is
* running, then it will be shut down.
*/
void checkBlacklistedServers()
{
// Iterate through the blacklist and check each of the servers. If we find
// one that is acceptable, then remove it from the blacklist.
final Iterator,
LDAPConnectionPoolHealthCheck>> iterator =
blacklistedServers.entrySet().iterator();
while (iterator.hasNext())
{
final Map.Entry,
LDAPConnectionPoolHealthCheck> e = iterator.next();
final ObjectPair hostPort = e.getKey();
final LDAPConnectionPoolHealthCheck healthCheck = e.getValue();
try (LDAPConnection conn = new LDAPConnection(socketFactory,
connectionOptions, hostPort.getFirst(), hostPort.getSecond()))
{
ServerSet.doBindPostConnectAndHealthCheckProcessing(conn, bindRequest,
postConnectProcessor, healthCheck);
iterator.remove();
}
catch (final Exception ex)
{
Debug.debugException(ex);
}
}
// If the blacklist is empty, then cancel the timer, if there is one.
if (blacklistedServers.isEmpty())
{
synchronized (this)
{
if (blacklistedServers.isEmpty())
{
final Timer timer = timerReference.getAndSet(null);
if (timer != null)
{
timer.cancel();
timer.purge();
}
return;
}
}
}
}
/**
* Retrieves a string representation of this server set blacklist manager.
*
* @return A string representation of this server set blacklist manager.
*/
@Override()
public String toString()
{
final StringBuilder buffer = new StringBuilder();
toString(buffer);
return buffer.toString();
}
/**
* Appends a string representation of this server set blacklist manager to the
* provided buffer.
*
* @param buffer The buffer to which the information should be appended.
*/
void toString(final StringBuilder buffer)
{
buffer.append("ServerSetBlacklistManager(serverSet='");
buffer.append(serverSetString);
buffer.append("', blacklistedServers={");
final Iterator> iterator =
blacklistedServers.keySet().iterator();
while (iterator.hasNext())
{
final ObjectPair hostPort = iterator.next();
buffer.append('\'');
buffer.append(hostPort.getFirst());
buffer.append(':');
buffer.append(hostPort.getSecond());
buffer.append('\'');
if (iterator.hasNext())
{
buffer.append(',');
}
}
buffer.append("}, checkIntervalMillis=");
buffer.append(checkIntervalMillis);
buffer.append(')');
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy