/* See LICENSE for licensing and NOTICE for copyright. */
package org.ldaptive.intermediate;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.ldaptive.LdapUtils;
import org.ldaptive.asn1.AbstractParseHandler;
import org.ldaptive.asn1.BooleanType;
import org.ldaptive.asn1.DERParser;
import org.ldaptive.asn1.DERPath;
import org.ldaptive.asn1.OctetStringType;
import org.ldaptive.asn1.UuidType;
import org.ldaptive.control.ResponseControl;
/**
* Intermediate response message for ldap content synchronization. See RFC 4533. Message is defined as:
*
* <pre>
syncInfoValue ::= CHOICE {
newcookie [0] syncCookie,
refreshDelete [1] SEQUENCE {
cookie syncCookie OPTIONAL,
refreshDone BOOLEAN DEFAULT TRUE
},
refreshPresent [2] SEQUENCE {
cookie syncCookie OPTIONAL,
refreshDone BOOLEAN DEFAULT TRUE
},
syncIdSet [3] SEQUENCE {
cookie syncCookie OPTIONAL,
refreshDeletes BOOLEAN DEFAULT FALSE,
syncUUIDs SET OF syncUUID
}
}
* </pre>
*
* @author Middleware Services
*/
public class SyncInfoMessage extends AbstractIntermediateResponse
{
/** OID of this response. */
public static final String OID = "1.3.6.1.4.1.4203.1.9.1.4";
/** hash value seed. */
private static final int HASH_CODE_SEED = 761;
/** Types of request modes. */
public enum Type {
/** new cookie. */
NEW_COOKIE,
/** refresh delete. */
REFRESH_DELETE,
/** refresh present. */
REFRESH_PRESENT,
/** sync id set. */
SYNC_ID_SET
}
/** message type. */
private Type messageType;
/** server generated cookie. */
private byte[] cookie;
/** refresh done. */
private boolean refreshDone = true;
/** refresh deletes. */
private boolean refreshDeletes;
/** entry uuids. */
private Set<UUID> entryUuids = new HashSet<>();
/** Default constructor. */
public SyncInfoMessage()
{
super(OID, null, -1);
}
/**
* Creates a new sync info message.
*
* @param responseControls for this message
* @param id message id
*/
public SyncInfoMessage(final ResponseControl[] responseControls, final int id)
{
super(OID, responseControls, id);
}
/**
* Returns the message type.
*
* @return message type
*/
public Type getMessageType()
{
return messageType;
}
/**
* Sets the message type.
*
* @param type message type
*/
public void setMessageType(final Type type)
{
messageType = type;
}
/**
* Returns the sync request cookie.
*
* @return sync request cookie
*/
public byte[] getCookie()
{
return cookie;
}
/**
* Sets the sync request cookie.
*
* @param value sync request cookie
*/
public void setCookie(final byte[] value)
{
cookie = value;
}
/**
* Returns whether refreshes are done.
*
* @return refresh done
*/
public boolean getRefreshDone()
{
return refreshDone;
}
/**
* Sets whether refreshes are done.
*
* @param b refresh done
*/
public void setRefreshDone(final boolean b)
{
refreshDone = b;
}
/**
* Returns whether to refresh deletes.
*
* @return whether to refresh deletes
*/
public boolean getRefreshDeletes()
{
return refreshDeletes;
}
/**
* Sets whether to refresh deletes.
*
* @param b whether to refresh deletes
*/
public void setRefreshDeletes(final boolean b)
{
refreshDeletes = b;
}
/**
* Returns the entry uuids.
*
* @return entry uuids
*/
public Set<UUID> getEntryUuids()
{
return entryUuids;
}
/**
* Sets the entry uuids.
*
* @param uuids entry uuids
*/
public void setEntryUuids(final Set<UUID> uuids)
{
entryUuids = uuids;
}
@Override
public void decode(final byte[] berValue)
{
final DERParser parser = new DERParser();
parser.registerHandler(NewCookieHandler.PATH, new NewCookieHandler(this));
parser.registerHandler(RefreshDeleteHandler.PATH, new RefreshDeleteHandler(this));
parser.registerHandler(RefreshDeleteCookieHandler.PATH, new RefreshDeleteCookieHandler(this));
parser.registerHandler(RefreshDeleteDoneHandler.PATH, new RefreshDeleteDoneHandler(this));
parser.registerHandler(RefreshPresentHandler.PATH, new RefreshPresentHandler(this));
parser.registerHandler(RefreshPresentCookieHandler.PATH, new RefreshPresentCookieHandler(this));
parser.registerHandler(RefreshPresentDoneHandler.PATH, new RefreshPresentDoneHandler(this));
parser.registerHandler(SyncIdSetHandler.PATH, new SyncIdSetHandler(this));
parser.registerHandler(SyncIdSetCookieHandler.PATH, new SyncIdSetCookieHandler(this));
parser.registerHandler(SyncIdSetDeletesHandler.PATH, new SyncIdSetDeletesHandler(this));
parser.registerHandler(SyncIdSetUuidsHandler.PATH, new SyncIdSetUuidsHandler(this));
parser.parse(ByteBuffer.wrap(berValue));
}
@Override
public boolean equals(final Object o)
{
if (o == this) {
return true;
}
if (o instanceof SyncInfoMessage) {
final SyncInfoMessage v = (SyncInfoMessage) o;
return LdapUtils.areEqual(getOID(), v.getOID()) &&
LdapUtils.areEqual(messageType, v.messageType) &&
LdapUtils.areEqual(cookie, v.cookie) &&
LdapUtils.areEqual(refreshDone, v.refreshDone) &&
LdapUtils.areEqual(refreshDeletes, v.refreshDeletes) &&
LdapUtils.areEqual(entryUuids, v.entryUuids) &&
LdapUtils.areEqual(getControls(), v.getControls()) &&
LdapUtils.areEqual(getMessageId(), v.getMessageId());
}
return false;
}
@Override
public int hashCode()
{
return
LdapUtils.computeHashCode(
HASH_CODE_SEED,
getOID(),
messageType,
cookie,
refreshDone,
refreshDeletes,
entryUuids,
getControls(),
getMessageId());
}
@Override
public String toString()
{
return
String.format(
"[%s@%d::messageType=%s, cookie=%s, refreshDone=%s, " +
"refreshDeletes=%s, entryUuids=%s, responseControls=%s, messageId=%s]",
getClass().getName(),
hashCode(),
messageType,
LdapUtils.base64Encode(cookie),
refreshDone,
refreshDeletes,
entryUuids,
Arrays.toString(getControls()),
getMessageId());
}
/** Parse handler implementation for new cookie. */
private static class NewCookieHandler extends AbstractParseHandler<SyncInfoMessage>
{
/** DER path to value. */
public static final DERPath PATH = new DERPath("/CTX(0)");
/**
* Creates a new cookie handler.
*
* @param message to configure
*/
NewCookieHandler(final SyncInfoMessage message)
{
super(message);
}
@Override
public void handle(final DERParser parser, final ByteBuffer encoded)
{
getObject().setMessageType(Type.NEW_COOKIE);
final byte[] cookie = OctetStringType.readBuffer(encoded);
if (cookie != null && cookie.length > 0) {
getObject().setCookie(cookie);
}
}
}
/** Parse handler implementation for refresh delete. */
private static class RefreshDeleteHandler extends AbstractParseHandler<SyncInfoMessage>
{
/** DER path to value. */
public static final DERPath PATH = new DERPath("/CTX(1)");
/**
* Creates a refresh delete handler.
*
* @param message to configure
*/
RefreshDeleteHandler(final SyncInfoMessage message)
{
super(message);
}
@Override
public void handle(final DERParser parser, final ByteBuffer encoded)
{
getObject().setMessageType(Type.REFRESH_DELETE);
}
}
/** Parse handler implementation for refresh delete cookie. */
private static class RefreshDeleteCookieHandler extends AbstractParseHandler<SyncInfoMessage>
{
/** DER path to value. */
public static final DERPath PATH = new DERPath("/CTX(1)/OCTSTR");
/**
* Creates a refresh delete cookie handler.
*
* @param message to configure
*/
RefreshDeleteCookieHandler(final SyncInfoMessage message)
{
super(message);
}
@Override
public void handle(final DERParser parser, final ByteBuffer encoded)
{
final byte[] cookie = OctetStringType.readBuffer(encoded);
if (cookie != null && cookie.length > 0) {
getObject().setCookie(cookie);
}
}
}
/** Parse handler implementation for refresh delete done. */
private static class RefreshDeleteDoneHandler extends AbstractParseHandler<SyncInfoMessage>
{
/** DER path to value. */
public static final DERPath PATH = new DERPath("/CTX(1)/BOOL");
/**
* Creates a refresh delete done handler.
*
* @param message to configure
*/
RefreshDeleteDoneHandler(final SyncInfoMessage message)
{
super(message);
}
@Override
public void handle(final DERParser parser, final ByteBuffer encoded)
{
getObject().setRefreshDone(BooleanType.decode(encoded));
}
}
/** Parse handler implementation for refresh present. */
private static class RefreshPresentHandler extends AbstractParseHandler<SyncInfoMessage>
{
/** DER path to value. */
public static final DERPath PATH = new DERPath("/CTX(2)");
/**
* Creates a refresh present handler.
*
* @param message to configure
*/
RefreshPresentHandler(final SyncInfoMessage message)
{
super(message);
}
@Override
public void handle(final DERParser parser, final ByteBuffer encoded)
{
getObject().setMessageType(Type.REFRESH_PRESENT);
}
}
/** Parse handler implementation for refresh present cookie. */
private static class RefreshPresentCookieHandler extends AbstractParseHandler<SyncInfoMessage>
{
/** DER path to value. */
public static final DERPath PATH = new DERPath("/CTX(2)/OCTSTR");
/**
* Creates a refresh present cookie handler.
*
* @param message to configure
*/
RefreshPresentCookieHandler(final SyncInfoMessage message)
{
super(message);
}
@Override
public void handle(final DERParser parser, final ByteBuffer encoded)
{
final byte[] cookie = OctetStringType.readBuffer(encoded);
if (cookie != null && cookie.length > 0) {
getObject().setCookie(cookie);
}
}
}
/** Parse handler implementation for refresh present done. */
private static class RefreshPresentDoneHandler extends AbstractParseHandler<SyncInfoMessage>
{
/** DER path to value. */
public static final DERPath PATH = new DERPath("/CTX(2)/BOOL");
/**
* Creates a refresh present done handler.
*
* @param message to configure
*/
RefreshPresentDoneHandler(final SyncInfoMessage message)
{
super(message);
}
@Override
public void handle(final DERParser parser, final ByteBuffer encoded)
{
getObject().setRefreshDone(BooleanType.decode(encoded));
}
}
/** Parse handler implementation for sync id set. */
private static class SyncIdSetHandler extends AbstractParseHandler<SyncInfoMessage>
{
/** DER path to value. */
public static final DERPath PATH = new DERPath("/CTX(3)");
/**
* Creates a sync id set handler.
*
* @param message to configure
*/
SyncIdSetHandler(final SyncInfoMessage message)
{
super(message);
}
@Override
public void handle(final DERParser parser, final ByteBuffer encoded)
{
getObject().setMessageType(Type.SYNC_ID_SET);
}
}
/** Parse handler implementation for sync id set cookie. */
private static class SyncIdSetCookieHandler extends AbstractParseHandler<SyncInfoMessage>
{
/** DER path to value. */
public static final DERPath PATH = new DERPath("/CTX(3)/OCTSTR");
/**
* Creates a sync id set cookie handler.
*
* @param message to configure
*/
SyncIdSetCookieHandler(final SyncInfoMessage message)
{
super(message);
}
@Override
public void handle(final DERParser parser, final ByteBuffer encoded)
{
final byte[] cookie = OctetStringType.readBuffer(encoded);
if (cookie != null && cookie.length > 0) {
getObject().setCookie(cookie);
}
}
}
/** Parse handler implementation for sync id set deletes. */
private static class SyncIdSetDeletesHandler extends AbstractParseHandler<SyncInfoMessage>
{
/** DER path to value. */
public static final DERPath PATH = new DERPath("/CTX(3)/BOOL");
/**
* Creates a sync id set deletes handler.
*
* @param message to configure
*/
SyncIdSetDeletesHandler(final SyncInfoMessage message)
{
super(message);
}
@Override
public void handle(final DERParser parser, final ByteBuffer encoded)
{
getObject().setRefreshDeletes(BooleanType.decode(encoded));
}
}
/** Parse handler implementation for sync id set uuids. */
private static class SyncIdSetUuidsHandler extends AbstractParseHandler<SyncInfoMessage>
{
/** DER path to value. */
public static final DERPath PATH = new DERPath("/CTX(3)/SET/OCTSTR");
/**
* Creates a sync id set uuids handler.
*
* @param message to configure
*/
SyncIdSetUuidsHandler(final SyncInfoMessage message)
{
super(message);
}
@Override
public void handle(final DERParser parser, final ByteBuffer encoded)
{
getObject().getEntryUuids().add(UuidType.decode(encoded));
}
}
}