/* See LICENSE for licensing and NOTICE for copyright. */
package org.ldaptive.control;
import java.nio.ByteBuffer;
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;
/**
* Response control for ldap content synchronization. See RFC 4533. Control is defined as:
*
* <pre>
syncDoneValue ::= SEQUENCE {
cookie syncCookie OPTIONAL,
refreshDeletes BOOLEAN DEFAULT FALSE
}
* </pre>
*
* @author Middleware Services
*/
public class SyncDoneControl extends AbstractControl implements ResponseControl
{
/** OID of this control. */
public static final String OID = "1.3.6.1.4.1.4203.1.9.1.3";
/** hash code seed. */
private static final int HASH_CODE_SEED = 757;
/** server generated cookie. */
private byte[] cookie;
/** refresh deletes. */
private boolean refreshDeletes;
/** Default constructor. */
public SyncDoneControl()
{
super(OID);
}
/**
* Creates a new sync done control.
*
* @param critical whether this control is critical
*/
public SyncDoneControl(final boolean critical)
{
super(OID, critical);
}
/**
* Creates a new sync done control.
*
* @param value sync done cookie
*/
public SyncDoneControl(final byte[] value)
{
super(OID);
setCookie(value);
}
/**
* Creates a new sync done control.
*
* @param value sync done cookie
* @param critical whether this control is critical
*/
public SyncDoneControl(final byte[] value, final boolean critical)
{
super(OID, critical);
setCookie(value);
}
/**
* Creates a new sync done control.
*
* @param value sync done cookie
* @param refresh whether to refresh deletes
* @param critical whether this control is critical
*/
public SyncDoneControl(final byte[] value, final boolean refresh, final boolean critical)
{
super(OID, critical);
setCookie(value);
setRefreshDeletes(refresh);
}
/**
* Returns the sync done cookie.
*
* @return sync done cookie
*/
public byte[] getCookie()
{
return cookie;
}
/**
* Sets the sync done cookie.
*
* @param value sync done cookie
*/
public void setCookie(final byte[] value)
{
cookie = value;
}
/**
* Returns whether to refresh deletes.
*
* @return refresh deletes
*/
public boolean getRefreshDeletes()
{
return refreshDeletes;
}
/**
* Sets whether to refresh deletes.
*
* @param b refresh deletes
*/
public void setRefreshDeletes(final boolean b)
{
refreshDeletes = b;
}
@Override
public boolean equals(final Object o)
{
if (o == this) {
return true;
}
if (o instanceof SyncDoneControl && super.equals(o)) {
final SyncDoneControl v = (SyncDoneControl) o;
return LdapUtils.areEqual(cookie, v.cookie) &&
LdapUtils.areEqual(refreshDeletes, v.refreshDeletes);
}
return false;
}
@Override
public int hashCode()
{
return LdapUtils.computeHashCode(HASH_CODE_SEED, getOID(), getCriticality(), cookie, refreshDeletes);
}
@Override
public String toString()
{
return
String.format(
"[%s@%d::criticality=%s, cookie=%s, refreshDeletes=%s]",
getClass().getName(),
hashCode(),
getCriticality(),
LdapUtils.base64Encode(cookie),
refreshDeletes);
}
@Override
public void decode(final byte[] berValue)
{
logger.trace("decoding control: {}", LdapUtils.base64Encode(berValue));
final DERParser parser = new DERParser();
parser.registerHandler(CookieHandler.PATH, new CookieHandler(this));
parser.registerHandler(RefreshDeletesHandler.PATH, new RefreshDeletesHandler(this));
parser.parse(ByteBuffer.wrap(berValue));
}
/** Parse handler implementation for the cookie. */
private static class CookieHandler extends AbstractParseHandler<SyncDoneControl>
{
/** DER path to cookie value. */
public static final DERPath PATH = new DERPath("/SEQ/OCTSTR");
/**
* Creates a new cookie handler.
*
* @param control to configure
*/
CookieHandler(final SyncDoneControl control)
{
super(control);
}
@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 the refresh deletes flag. */
private static class RefreshDeletesHandler extends AbstractParseHandler<SyncDoneControl>
{
/** DER path to the boolean. */
public static final DERPath PATH = new DERPath("/SEQ/BOOL");
/**
* Creates a new refresh deletes handler.
*
* @param control to configure
*/
RefreshDeletesHandler(final SyncDoneControl control)
{
super(control);
}
@Override
public void handle(final DERParser parser, final ByteBuffer encoded)
{
getObject().setRefreshDeletes(BooleanType.decode(encoded));
}
}
}