org.ldaptive.provider.jldap.JLdapConnection Maven / Gradle / Ivy
/* See LICENSE for licensing and NOTICE for copyright. */
package org.ldaptive.provider.jldap;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import com.novell.ldap.LDAPConnection;
import com.novell.ldap.LDAPConstraints;
import com.novell.ldap.LDAPControl;
import com.novell.ldap.LDAPEntry;
import com.novell.ldap.LDAPException;
import com.novell.ldap.LDAPExtendedOperation;
import com.novell.ldap.LDAPExtendedResponse;
import com.novell.ldap.LDAPIntermediateResponse;
import com.novell.ldap.LDAPMessage;
import com.novell.ldap.LDAPMessageQueue;
import com.novell.ldap.LDAPResponse;
import com.novell.ldap.LDAPResponseQueue;
import com.novell.ldap.LDAPSearchConstraints;
import com.novell.ldap.LDAPSearchQueue;
import com.novell.ldap.LDAPSearchResult;
import com.novell.ldap.LDAPSearchResultReference;
import com.novell.ldap.LDAPUnsolicitedNotificationListener;
import com.novell.security.sasl.RealmCallback;
import com.novell.security.sasl.RealmChoiceCallback;
import org.ldaptive.AddRequest;
import org.ldaptive.BindRequest;
import org.ldaptive.CompareRequest;
import org.ldaptive.DeleteRequest;
import org.ldaptive.DerefAliases;
import org.ldaptive.LdapException;
import org.ldaptive.ModifyDnRequest;
import org.ldaptive.ModifyRequest;
import org.ldaptive.Request;
import org.ldaptive.Response;
import org.ldaptive.ResultCode;
import org.ldaptive.SearchEntry;
import org.ldaptive.SearchReference;
import org.ldaptive.SearchRequest;
import org.ldaptive.SearchScope;
import org.ldaptive.async.AsyncRequest;
import org.ldaptive.control.RequestControl;
import org.ldaptive.control.ResponseControl;
import org.ldaptive.extended.ExtendedRequest;
import org.ldaptive.extended.ExtendedResponse;
import org.ldaptive.extended.ExtendedResponseFactory;
import org.ldaptive.extended.UnsolicitedNotificationListener;
import org.ldaptive.intermediate.IntermediateResponseFactory;
import org.ldaptive.provider.ProviderConnection;
import org.ldaptive.provider.ProviderUtils;
import org.ldaptive.provider.SearchItem;
import org.ldaptive.provider.SearchIterator;
import org.ldaptive.provider.SearchListener;
import org.ldaptive.sasl.SaslConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* JLDAP provider implementation of ldap operations.
*
* @author Middleware Services
*/
public class JLdapConnection implements ProviderConnection
{
/** Logger for this class. */
protected final Logger logger = LoggerFactory.getLogger(getClass());
/** Ldap connection. */
private LDAPConnection connection;
/** Provider configuration. */
private final JLdapProviderConfig config;
/** Receives unsolicited notifications. */
private final AggregateUnsolicitedNotificationListener notificationListener =
new AggregateUnsolicitedNotificationListener();
/**
* Creates a new jldap connection.
*
* @param conn ldap connection
* @param pc provider configuration
*/
public JLdapConnection(final LDAPConnection conn, final JLdapProviderConfig pc)
{
connection = conn;
config = pc;
connection.addUnsolicitedNotificationListener(notificationListener);
}
/**
* Returns the underlying ldap connection.
*
* @return ldap connection
*/
public LDAPConnection getLDAPConnection()
{
return connection;
}
@Override
public void close(final RequestControl[] controls)
throws LdapException
{
try {
if (connection != null) {
connection.disconnect(getLDAPConstraints(controls));
}
} catch (LDAPException e) {
throw new LdapException(e, ResultCode.valueOf(e.getResultCode()));
} finally {
connection = null;
}
}
@Override
public Response bind(final BindRequest request)
throws LdapException
{
final Response response;
if (request.getSaslConfig() != null) {
response = saslBind(request);
} else if (request.getDn() == null && request.getCredential() == null) {
response = anonymousBind(request);
} else {
response = simpleBind(request);
}
return response;
}
/**
* Performs an anonymous bind.
*
* @param request to bind with
*
* @return bind response
*
* @throws LdapException if an error occurs
*/
protected Response anonymousBind(final BindRequest request)
throws LdapException
{
Response response = null;
try {
final LDAPResponseQueue queue = connection.bind(
LDAPConnection.LDAP_V3,
null,
null,
null,
getLDAPConstraints(request));
final LDAPResponse lr = (LDAPResponse) queue.getResponse();
response = createResponse(request, null, lr);
} catch (LDAPException e) {
processLDAPException(e);
}
return response;
}
/**
* Performs a simple bind.
*
* @param request to bind with
*
* @return bind response
*
* @throws LdapException if an error occurs
*/
protected Response simpleBind(final BindRequest request)
throws LdapException
{
Response response = null;
try {
final LDAPResponseQueue queue = connection.bind(
LDAPConnection.LDAP_V3,
request.getDn(),
request.getCredential().getBytes(),
null,
getLDAPConstraints(request));
final LDAPResponse lr = (LDAPResponse) queue.getResponse();
response = createResponse(request, null, lr);
} catch (LDAPException e) {
processLDAPException(e);
}
return response;
}
/**
* Performs a sasl bind.
*
* @param request to bind with
*
* @return bind response
*
* @throws LdapException if an error occurs
*/
protected Response saslBind(final BindRequest request)
throws LdapException
{
try {
final SaslConfig sc = request.getSaslConfig();
switch (sc.getMechanism()) {
case EXTERNAL:
throw new UnsupportedOperationException("SASL External not supported");
/* current implementation appears to be broken
* see http://tinyurl.com/7ojdzlz
* connection.bind(
* (String) null,
* sc.getAuthorizationId(),
* new String[] {"EXTERNAL"},
* null,
* (Object) null);
* break;
*/
case DIGEST_MD5:
connection.bind(
null,
request.getDn(),
new String[] {"DIGEST-MD5"},
null,
new SaslCallbackHandler(null, request.getCredential() != null ? request.getCredential().getString() : null));
break;
case CRAM_MD5:
throw new UnsupportedOperationException("CRAM-MD5 not supported");
case GSSAPI:
throw new UnsupportedOperationException("GSSAPI not supported");
default:
throw new IllegalArgumentException("Unknown SASL authentication mechanism: " + sc.getMechanism());
}
} catch (LDAPException e) {
processLDAPException(e);
}
return new Response<>(null, ResultCode.SUCCESS);
}
@Override
public Response add(final AddRequest request)
throws LdapException
{
Response response = null;
try {
final JLdapUtils bu = new JLdapUtils();
final LDAPResponseQueue queue = connection.add(
new LDAPEntry(request.getDn(), bu.fromLdapAttributes(request.getLdapAttributes())),
null,
getLDAPConstraints(request));
final LDAPResponse lr = (LDAPResponse) queue.getResponse();
response = createResponse(request, null, lr);
} catch (LDAPException e) {
processLDAPException(e);
}
return response;
}
@Override
public Response compare(final CompareRequest request)
throws LdapException
{
Response response = null;
try {
final JLdapUtils bu = new JLdapUtils();
final LDAPResponseQueue queue = connection.compare(
request.getDn(),
bu.fromLdapAttribute(request.getAttribute()),
null,
getLDAPConstraints(request));
final LDAPResponse lr = (LDAPResponse) queue.getResponse();
response = createResponse(request, lr.getResultCode() == ResultCode.COMPARE_TRUE.value(), lr);
} catch (LDAPException e) {
processLDAPException(e);
}
return response;
}
@Override
public Response delete(final DeleteRequest request)
throws LdapException
{
Response response = null;
try {
final LDAPResponseQueue queue = connection.delete(request.getDn(), null, getLDAPConstraints(request));
final LDAPResponse lr = (LDAPResponse) queue.getResponse();
response = createResponse(request, null, lr);
} catch (LDAPException e) {
processLDAPException(e);
}
return response;
}
@Override
public Response modify(final ModifyRequest request)
throws LdapException
{
Response response = null;
try {
final JLdapUtils bu = new JLdapUtils();
final LDAPResponseQueue queue = connection.modify(
request.getDn(),
bu.fromAttributeModification(request.getAttributeModifications()),
null,
getLDAPConstraints(request));
final LDAPResponse lr = (LDAPResponse) queue.getResponse();
response = createResponse(request, null, lr);
} catch (LDAPException e) {
processLDAPException(e);
}
return response;
}
@Override
public Response modifyDn(final ModifyDnRequest request)
throws LdapException
{
Response response = null;
try {
final String[] dn = request.getNewDn().split(",", 2);
final LDAPResponseQueue queue = connection.rename(
request.getDn(),
dn[0],
dn[1],
request.getDeleteOldRDn(),
null,
getLDAPConstraints(request));
final LDAPResponse lr = (LDAPResponse) queue.getResponse();
response = createResponse(request, null, lr);
} catch (LDAPException e) {
processLDAPException(e);
}
return response;
}
@Override
public SearchIterator search(final SearchRequest request)
throws LdapException
{
final JLdapSearchIterator i = new JLdapSearchIterator(request);
i.initialize();
return i;
}
@Override
public void searchAsync(final SearchRequest request, final SearchListener listener)
throws LdapException
{
final JLdapAsyncSearchListener l = new JLdapAsyncSearchListener(request, listener);
l.initialize();
}
@Override
public void abandon(final int messageId, final RequestControl[] controls)
throws LdapException
{
try {
connection.abandon(messageId, getLDAPConstraints(controls));
} catch (LDAPException e) {
processLDAPException(e);
}
}
@Override
public Response> extendedOperation(final ExtendedRequest request)
throws LdapException
{
Response> response = null;
try {
final LDAPExtendedResponse ldapExtRes = connection.extendedOperation(
new LDAPExtendedOperation(request.getOID(), request.encode()),
getLDAPConstraints(request));
final ExtendedResponse> extRes = ExtendedResponseFactory.createExtendedResponse(
request.getOID(),
ldapExtRes.getID(),
ldapExtRes.getValue());
response = createResponse(request, extRes.getValue(), ldapExtRes);
} catch (LDAPException e) {
processLDAPException(e);
}
return response;
}
@Override
public void addUnsolicitedNotificationListener(final UnsolicitedNotificationListener listener)
{
notificationListener.addUnsolicitedNotificationListener(listener);
}
@Override
public void removeUnsolicitedNotificationListener(final UnsolicitedNotificationListener listener)
{
notificationListener.removeUnsolicitedNotificationListener(listener);
}
/**
* Returns an ldap constraints object configured with the supplied request.
*
* @param request request containing configuration to create constraints
*
* @return ldap constraints
*/
protected LDAPConstraints getLDAPConstraints(final Request request)
{
LDAPConstraints constraints = connection.getConstraints();
if (constraints == null) {
constraints = new LDAPConstraints();
}
if (request.getControls() != null) {
constraints.setControls(config.getControlProcessor().processRequestControls(request.getControls()));
}
return constraints;
}
/**
* Returns an ldap constraints object configured with the supplied controls.
*
* @param controls to sets in the constraints
*
* @return ldap constraints
*/
protected LDAPConstraints getLDAPConstraints(final RequestControl[] controls)
{
LDAPConstraints constraints = connection.getConstraints();
if (constraints == null) {
constraints = new LDAPConstraints();
}
if (controls != null) {
constraints.setControls(config.getControlProcessor().processRequestControls(controls));
}
return constraints;
}
/**
* Determines if the supplied response should result in an operation retry.
*
* @param request that produced the exception
* @param ldapResponse provider response
*
* @throws LdapException wrapping the ldap exception
*/
protected void throwOperationException(final Request request, final LDAPResponse ldapResponse)
throws LdapException
{
ProviderUtils.throwOperationException(
config.getOperationExceptionResultCodes(),
String.format("Ldap returned result code: %s", ldapResponse.getResultCode()),
ldapResponse.getResultCode(),
ldapResponse.getMatchedDN(),
config.getControlProcessor().processResponseControls(ldapResponse.getControls()),
ldapResponse.getReferrals(),
false);
}
/**
* Creates an operation response with the supplied response data.
*
* @param type of response
* @param request containing controls
* @param result of the operation
* @param ldapResponse provider response
*
* @return operation response
*/
protected Response createResponse(final Request request, final T result, final LDAPResponse ldapResponse)
{
return
new Response<>(
result,
ResultCode.valueOf(ldapResponse.getResultCode()),
ldapResponse.getErrorMessage(),
ldapResponse.getMatchedDN(),
config.getControlProcessor().processResponseControls(ldapResponse.getControls()),
ldapResponse.getReferrals(),
ldapResponse.getMessageID());
}
/**
* Determines if the supplied ldap exception should result in an operation retry.
*
* @param e that was produced
*
* @throws LdapException wrapping the ldap exception
*/
protected void processLDAPException(final LDAPException e)
throws LdapException
{
ProviderUtils.throwOperationException(
config.getOperationExceptionResultCodes(),
e,
e.getResultCode(),
e.getMatchedDN(),
null,
null,
true);
}
/** Callback handler used by SASL mechanisms. */
private static class SaslCallbackHandler implements CallbackHandler
{
/** user name. */
private final String user;
/** password. */
private final char[] pass;
/**
* Creates a new bind callback handler.
*
* @param u username to bind with
* @param p password to bind with
*/
SaslCallbackHandler(final String u, final String p)
{
user = u;
if (p != null) {
pass = p.toCharArray();
} else {
pass = null;
}
}
@Override
public void handle(final Callback[] callbacks)
throws IOException, UnsupportedCallbackException
{
for (Callback cb : callbacks) {
if (cb instanceof NameCallback) {
// if user is null, the authzId will be used as it's the default name
((NameCallback) cb).setName(user != null ? user : ((NameCallback) cb).getDefaultName());
} else if (cb instanceof PasswordCallback) {
((PasswordCallback) cb).setPassword(pass);
} else if (cb instanceof RealmCallback) {
((RealmCallback) cb).setText(((RealmCallback) cb).getDefaultText());
} else if (cb instanceof RealmChoiceCallback) {
((RealmChoiceCallback) cb).setSelectedIndex(0);
}
}
}
}
/** Search iterator for JLdap search results. */
protected class JLdapSearchIterator extends AbstractJLdapSearch implements SearchIterator
{
/** Response data. */
private Response response;
/** Ldap search result iterator. */
private SearchResultIterator resultIterator;
/**
* Creates a new jldap search iterator.
*
* @param sr search request
*/
public JLdapSearchIterator(final SearchRequest sr)
{
super(sr);
}
/**
* Initializes this jldap search iterator.
*
* @throws LdapException if an error occurs
*/
public void initialize()
throws LdapException
{
try {
resultIterator = new SearchResultIterator(search(connection, request));
} catch (LDAPException e) {
processLDAPException(e);
}
}
@Override
public boolean hasNext()
throws LdapException
{
if (resultIterator == null || response != null) {
return false;
}
boolean more = false;
try {
more = resultIterator.hasNext();
if (!more) {
final LDAPResponse res = resultIterator.getResponse();
logger.trace("reading search response: {}", res);
throwOperationException(request, res);
response = createResponse(request, null, res);
}
} catch (LDAPException e) {
final ResultCode rc = ignoreSearchException(config.getSearchIgnoreResultCodes(), e);
if (rc == null) {
processLDAPException(e);
}
response = new Response<>(null, rc, e.getLDAPErrorMessage(), null, null, null, -1);
}
return more;
}
@Override
public SearchItem next()
throws LdapException
{
final SearchItem si;
final LDAPMessage message = resultIterator.next();
if (message instanceof LDAPSearchResult) {
si = processLDAPSearchResult((LDAPSearchResult) message);
} else if (message instanceof LDAPSearchResultReference) {
si = processLDAPSearchResultReference((LDAPSearchResultReference) message);
} else if (message instanceof LDAPIntermediateResponse) {
si = processLDAPIntermediateResponse((LDAPIntermediateResponse) message);
} else {
throw new IllegalStateException("Unknown message: " + message);
}
return si;
}
@Override
public Response getResponse()
{
return response;
}
@Override
public void close()
throws LdapException {}
}
/** Async search listener for JLdap search results. */
protected class JLdapAsyncSearchListener extends AbstractJLdapSearch
{
/** Search result listener. */
private final SearchListener listener;
/**
* Creates a new jldap async search listener.
*
* @param sr search request
* @param sl search listener
*/
public JLdapAsyncSearchListener(final SearchRequest sr, final SearchListener sl)
{
super(sr);
listener = sl;
}
/**
* Initializes this jldap search listener.
*
* @throws LdapException if an error occurs
*/
public void initialize()
throws LdapException
{
try {
search(connection, request);
} catch (LDAPException e) {
processLDAPException(e);
}
}
/**
* Executes an ldap search.
*
* @param conn to search with
* @param sr to read properties from
*
* @return ldap search queue
*
* @throws LDAPException if an error occurs
*/
protected LDAPSearchQueue search(final LDAPConnection conn, final SearchRequest sr)
throws LDAPException
{
final SearchResultIterator i = new SearchResultIterator(super.search(conn, sr));
listener.asyncRequestReceived(new JLdapAsyncRequest(i.getLDAPSearchQueue()));
while (i.hasNext()) {
final LDAPMessage message = i.next();
if (message instanceof LDAPSearchResult) {
listener.searchItemReceived(processLDAPSearchResult((LDAPSearchResult) message));
} else if (message instanceof LDAPSearchResultReference) {
listener.searchItemReceived(processLDAPSearchResultReference((LDAPSearchResultReference) message));
} else if (message instanceof LDAPIntermediateResponse) {
listener.searchItemReceived(processLDAPIntermediateResponse((LDAPIntermediateResponse) message));
} else {
throw new IllegalStateException("Unknown message: " + message);
}
}
final Response response = createResponse(request, null, i.getResponse());
listener.responseReceived(response);
return null;
}
}
/** Common search functionality for jldap iterators and listeners. */
protected abstract class AbstractJLdapSearch
{
/** Search request. */
protected final SearchRequest request;
/** Utility class. */
protected final JLdapUtils util;
/**
* Creates a new abstract jldap search.
*
* @param sr search request
*/
public AbstractJLdapSearch(final SearchRequest sr)
{
request = sr;
util = new JLdapUtils(request.getSortBehavior());
util.setBinaryAttributes(request.getBinaryAttributes());
}
/**
* Executes an ldap search.
*
* @param conn to search with
* @param sr to read properties from
*
* @return ldap search queue
*
* @throws LDAPException if an error occurs
*/
protected LDAPSearchQueue search(final LDAPConnection conn, final SearchRequest sr)
throws LDAPException
{
final LDAPSearchConstraints constraints = getLDAPSearchConstraints(sr);
final LDAPControl[] lc = config.getControlProcessor().processRequestControls(sr.getControls());
if (lc != null) {
constraints.setControls(lc);
}
return
conn.search(
sr.getBaseDn(),
getSearchScope(sr.getSearchScope()),
sr.getSearchFilter() != null ? sr.getSearchFilter().format() : null,
sr.getReturnAttributes(),
sr.getTypesOnly(),
null,
constraints);
}
/**
* Returns the jldap integer constant for the supplied search scope.
*
* @param ss search scope
*
* @return integer constant
*/
protected int getSearchScope(final SearchScope ss)
{
int scope = -1;
if (ss == SearchScope.OBJECT) {
scope = LDAPConnection.SCOPE_BASE;
} else if (ss == SearchScope.ONELEVEL) {
scope = LDAPConnection.SCOPE_ONE;
} else if (ss == SearchScope.SUBTREE) {
scope = LDAPConnection.SCOPE_SUB;
}
return scope;
}
/**
* Returns an ldap search constraints object configured with the supplied search request.
*
* @param sr search request containing configuration to create search constraints
*
* @return ldap search constraints
*/
protected LDAPSearchConstraints getLDAPSearchConstraints(final SearchRequest sr)
{
LDAPSearchConstraints constraints = connection.getSearchConstraints();
if (constraints == null) {
constraints = new LDAPSearchConstraints();
}
constraints.setServerTimeLimit((int) sr.getTimeLimit().getSeconds());
constraints.setMaxResults(Long.valueOf(sr.getSizeLimit()).intValue());
if (sr.getDerefAliases() != null) {
if (sr.getDerefAliases() == DerefAliases.ALWAYS) {
constraints.setDereference(LDAPSearchConstraints.DEREF_ALWAYS);
} else if (sr.getDerefAliases() == DerefAliases.FINDING) {
constraints.setDereference(LDAPSearchConstraints.DEREF_FINDING);
} else if (sr.getDerefAliases() == DerefAliases.NEVER) {
constraints.setDereference(LDAPSearchConstraints.DEREF_NEVER);
} else if (sr.getDerefAliases() == DerefAliases.SEARCHING) {
constraints.setDereference(LDAPSearchConstraints.DEREF_SEARCHING);
}
}
return constraints;
}
/**
* Determines whether the supplied ldap exception should be ignored.
*
* @param ignoreResultCodes to match against the exception
* @param e ldap exception to match
*
* @return result code that should be ignored or null
*/
protected ResultCode ignoreSearchException(final ResultCode[] ignoreResultCodes, final LDAPException e)
{
ResultCode ignore = null;
if (ignoreResultCodes != null && ignoreResultCodes.length > 0) {
for (ResultCode rc : ignoreResultCodes) {
if (e.getResultCode() == rc.value()) {
logger.debug("Ignoring ldap exception", e);
ignore = rc;
break;
}
}
}
return ignore;
}
/**
* Processes the response controls on the supplied result and returns a corresponding search item.
*
* @param res to process
*
* @return search item
*/
protected SearchItem processLDAPSearchResult(final LDAPSearchResult res)
{
logger.trace("reading search result: {}", res);
ResponseControl[] respControls = null;
if (res.getControls() != null && res.getControls().length > 0) {
respControls = config.getControlProcessor().processResponseControls(res.getControls());
}
final SearchEntry se = util.toSearchEntry(res.getEntry(), respControls, res.getMessageID());
return new SearchItem(se);
}
/**
* Processes the response controls on the supplied reference and returns a corresponding search item.
*
* @param ref to process
*
* @return search item
*/
protected SearchItem processLDAPSearchResultReference(final LDAPSearchResultReference ref)
{
logger.trace("reading search reference: {}", ref);
ResponseControl[] respControls = null;
if (ref.getControls() != null && ref.getControls().length > 0) {
respControls = config.getControlProcessor().processResponseControls(ref.getControls());
}
final SearchReference sr = new SearchReference(ref.getMessageID(), respControls, ref.getReferrals());
return new SearchItem(sr);
}
/**
* Processes the response controls on the supplied response and returns a corresponding search item.
*
* @param res to process
*
* @return search item
*/
protected SearchItem processLDAPIntermediateResponse(final LDAPIntermediateResponse res)
{
logger.trace("reading intermediate response: {}", res);
ResponseControl[] respControls = null;
if (res.getControls() != null && res.getControls().length > 0) {
respControls = config.getControlProcessor().processResponseControls(res.getControls());
}
final org.ldaptive.intermediate.IntermediateResponse ir = IntermediateResponseFactory.createIntermediateResponse(
res.getID(),
res.getValue(),
respControls,
res.getMessageID());
return new SearchItem(ir);
}
}
/** Iterates over an ldap search queue. */
protected static class SearchResultIterator
{
/** Queue to iterate over. */
private final LDAPSearchQueue queue;
/** Last response message received from the queue. */
private LDAPMessage message;
/** Response available after all messages have been received. */
private LDAPResponse response;
/**
* Create a new ldap result iterator.
*
* @param q ldap search queue
*/
public SearchResultIterator(final LDAPSearchQueue q)
{
queue = q;
}
/**
* Returns the search queue used by this iterator.
*
* @return ldap search queue
*/
public LDAPSearchQueue getLDAPSearchQueue()
{
return queue;
}
/**
* Returns whether the queue has another message to read.
*
* @return whether the queue has another message to read
*
* @throws LDAPException if an error occurs reading the response
*/
public boolean hasNext()
throws LDAPException
{
if (response != null) {
return false;
}
boolean more = false;
message = queue.getResponse();
if (message != null) {
if (message instanceof LDAPSearchResult) {
more = true;
} else if (message instanceof LDAPSearchResultReference) {
more = true;
} else if (message instanceof LDAPIntermediateResponse) {
more = true;
} else {
response = (LDAPResponse) message;
}
}
return more;
}
/**
* Returns the next message in the queue.
*
* @return ldap message
*/
public LDAPMessage next()
{
return message;
}
/**
* Returns the search response. Available after all messages have been read from the queue.
*
* @return ldap search response
*/
public LDAPResponse getResponse()
{
return response;
}
}
/** Async request to invoke abandons. */
protected class JLdapAsyncRequest implements AsyncRequest
{
/** Message queue. */
private final LDAPMessageQueue messageQueue;
/**
* Creates a new JLDAP async request.
*
* @param queue from an async operation
*/
public JLdapAsyncRequest(final LDAPMessageQueue queue)
{
messageQueue = queue;
}
@Override
public int getMessageId()
{
final int[] ids = messageQueue.getMessageIDs();
if (ids == null || ids.length == 0) {
return -1;
}
return ids[ids.length - 1];
}
@Override
public void abandon()
throws LdapException
{
try {
LDAPConstraints constraints = connection.getConstraints();
if (constraints == null) {
constraints = new LDAPConstraints();
}
connection.abandon(messageQueue, constraints);
} catch (LDAPException e) {
processLDAPException(e);
}
}
@Override
public void abandon(final RequestControl[] controls)
throws LdapException
{
try {
LDAPConstraints constraints = connection.getConstraints();
if (constraints == null) {
constraints = new LDAPConstraints();
}
if (controls != null) {
constraints.setControls(config.getControlProcessor().processRequestControls(controls));
}
connection.abandon(messageQueue, constraints);
} catch (LDAPException e) {
processLDAPException(e);
}
}
}
/** Allows the use of multiple unsolicited notification handlers per connection. */
protected class AggregateUnsolicitedNotificationListener implements LDAPUnsolicitedNotificationListener
{
/** Listeners to receive unsolicited notifications. */
private final List listeners = new ArrayList<>();
/**
* Adds an unsolicited notification listener to this handler.
*
* @param listener to receive unsolicited notifications
*/
public void addUnsolicitedNotificationListener(final UnsolicitedNotificationListener listener)
{
synchronized (listeners) {
listeners.add(listener);
}
}
/**
* Removes an unsolicited notification listener from this handler.
*
* @param listener to stop receiving unsolicited notifications
*/
public void removeUnsolicitedNotificationListener(final UnsolicitedNotificationListener listener)
{
synchronized (listeners) {
listeners.remove(listener);
}
}
@Override
public void messageReceived(final LDAPExtendedResponse extendedResponse)
{
logger.debug("Unsolicited notification received: {}", extendedResponse);
synchronized (listeners) {
final Response response = createResponse(null, null, extendedResponse);
for (UnsolicitedNotificationListener listener : listeners) {
listener.notificationReceived(extendedResponse.getID(), response);
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy