EntityTagVirtualAttributeProvider.java revision ea1068c292e9b341af6d6b563cd8988a96be20a9
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Portions Copyright 2012-2015 ForgeRock AS.
*/
/**
* This class implements a virtual attribute provider which ensures that all
* entries contain an "entity tag" or "Etag" as defined in section 3.11 of RFC
* 2616.
* <p>
* The entity tag may be used by clients, in conjunction with the assertion
* control, for optimistic concurrency control, as a way to help prevent
* simultaneous updates of an entry from conflicting with each other.
*/
public final class EntityTagVirtualAttributeProvider extends
VirtualAttributeProvider<EntityTagVirtualAttributeCfg> implements
{
new Comparator<Attribute>()
{
/**
* {@inheritDoc}
*/
{
}
};
// Current configuration.
private volatile EntityTagVirtualAttributeCfg config;
/**
* Default constructor invoked by reflection.
*/
public EntityTagVirtualAttributeProvider()
{
// Initialization performed by initializeVirtualAttributeProvider.
}
/**
* {@inheritDoc}
*/
{
this.config = configuration;
return new ConfigChangeResult();
}
/**
* {@inheritDoc}
*/
{
// ETags cannot be used in approximate matching.
return ConditionResult.UNDEFINED;
}
/**
* {@inheritDoc}
*/
public void finalizeVirtualAttributeProvider()
{
}
/**
* {@inheritDoc}
*/
{
// Save reference to current configuration in case it changes.
// Determine which checksum algorithm to use.
final Checksum checksummer;
switch (cfg.getChecksumAlgorithm())
{
case CRC_32:
checksummer = new CRC32();
break;
default: // ADLER_32
checksummer = new Adler32();
break;
}
}
/**
* {@inheritDoc}
*/
{
// ETags cannot be used in ordering matching.
return ConditionResult.UNDEFINED;
}
/**
* {@inheritDoc}
*/
{
// ETag is always present.
return true;
}
/**
* {@inheritDoc}
*/
public void initializeVirtualAttributeProvider(
{
this.config = configuration;
}
/**
* {@inheritDoc}
*/
public boolean isConfigurationChangeAcceptable(
{
// The new configuration should always be acceptable.
return true;
}
/**
* {@inheritDoc}
*/
public boolean isMultiValued()
{
// ETag is always single-valued.
return false;
}
/**
* {@inheritDoc}
*/
final SearchOperation searchOperation,
final boolean isPreIndexed)
{
// ETags cannot be searched since there is no way to determine which entry
// is associated with a particular ETag.
return false;
}
/**
* {@inheritDoc}
*/
{
// ETags cannot be used in ordering matching.
return ConditionResult.UNDEFINED;
}
/**
* {@inheritDoc}
*/
{
// ETags cannot be used in substring matching.
return ConditionResult.UNDEFINED;
}
/**
* {@inheritDoc}
*/
final SearchOperation searchOperation)
{
.getAttributeType().getNameOrOID());
}
{
// Object class may be null.
{
return;
}
// Ignore other virtual attributes include this one.
{
return;
}
// Ignore excluded attributes.
{
return;
}
// Checksum the attribute description.
// Checksum the attribute values. The value order may vary between
// replicas so we need to make sure that we always process them in the
// same order. Note that we don't need to normalize the values since we want
// to detect any kind of updates even if they are not semantically
// significant. In any case, normalization can be expensive and should be
// avoided if possible.
switch (size)
{
case 0:
// It's surprising to have an empty attribute, but if we do then there's
// nothing to do.
break;
case 1:
// Avoid sorting single valued attributes.
break;
default:
// Multi-valued attributes need sorting.
int i = 0;
{
}
{
}
break;
}
}
{
// Checksum the object classes since these are not included in the entry's
// attributes.
// The attribute order may vary between replicas so we need to make sure
// that we always process them in the same order.
{
}
// Convert the checksum value to a hex string.
final byte[] bytes = new byte[16];
int j = 15;
for (int i = 7; i >= 0; i--)
{
final byte b = (byte) (checksum & 0xFF);
final byte l = (byte) (b & 0x0F);
final byte h = (byte) ((b & 0xF0) >>> 4);
checksum >>>= 8;
}
}
{
for (int i = 0; i < size; i++)
{
}
}
}