SearchFilter.java revision f15e69d46eb0444e28427f49fb519ea476c7feae
/*
* 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
*
*
* Copyright 2006-2009 Sun Microsystems, Inc.
* Portions Copyright 2014-2015 ForgeRock AS
* Portions Copyright 2013-2014 Manuel Gaupp
*/
/**
* This class defines a data structure for storing and interacting
* with a search filter that may serve as criteria for locating
* entries in the Directory Server.
*/
mayInstantiate=true,
mayExtend=false,
mayInvoke=true)
public final class SearchFilter
{
private static SearchFilter objectClassPresent;
/** The attribute type for this filter. */
private final AttributeType attributeType;
/** The assertion value for this filter. */
private final ByteString assertionValue;
/** Indicates whether to match on DN attributes for extensible match filters. */
private final boolean dnAttributes;
/** The subInitial element for substring filters. */
private final ByteString subInitialElement;
/** The set of subAny components for substring filters. */
/** The subFinal element for substring filters. */
private final ByteString subFinalElement;
/** The search filter type for this filter. */
private final FilterType filterType;
/** The set of filter components for AND and OR filters. */
/** The not filter component for this search filter. */
private final SearchFilter notComponent;
/** The set of options for the attribute type in this filter. */
/** The matching rule ID for this search filter. */
private final String matchingRuleID;
/**
* Creates a new search filter with the provided information.
*
* @param filterType The filter type for this search
* filter.
* @param filterComponents The set of filter components for AND
* and OR filters.
* @param notComponent The filter component for NOT filters.
* @param attributeType The attribute type for this filter.
* @param attributeOptions The set of attribute options for the
* associated attribute type.
* @param assertionValue The assertion value for this filter.
* @param subInitialElement The subInitial element for substring
* filters.
* @param subAnyElements The subAny elements for substring
* filters.
* @param subFinalElement The subFinal element for substring
* filters.
* @param matchingRuleID The matching rule ID for this search
* filter.
* @param dnAttributes Indicates whether to match on DN
* attributes for extensible match
* filters.
*
* FIXME: this should be private.
*/
{
// This used to happen in getSubAnyElements, but we do it here
// so that we can make this.subAnyElements final.
if (subAnyElements == null) {
}
// This used to happen in getFilterComponents, but we do it here
// so that we can make this.filterComponents final.
if (filterComponents == null) {
}
this.filterType = filterType;
this.notComponent = notComponent;
this.attributeType = attributeType;
this.attributeOptions = attributeOptions;
this.assertionValue = assertionValue;
this.subInitialElement = subInitialElement;
this.subAnyElements = subAnyElements;
this.subFinalElement = subFinalElement;
this.matchingRuleID = matchingRuleID;
this.dnAttributes = dnAttributes;
}
/**
* Creates a new AND search filter with the provided information.
*
* @param filterComponents The set of filter components for the
* AND filter.
*
* @return The constructed search filter.
*/
{
false);
}
/**
* Creates a new OR search filter with the provided information.
*
* @param filterComponents The set of filter components for the OR
* filter.
*
* @return The constructed search filter.
*/
{
false);
}
/**
* Creates a new NOT search filter with the provided information.
*
* @param notComponent The filter component for this NOT filter.
*
* @return The constructed search filter.
*/
public static SearchFilter createNOTFilter(
{
false);
}
/**
* Creates a new equality search filter with the provided
* information.
*
* @param attributeType The attribute type for this equality
* filter.
* @param assertionValue The assertion value for this equality
* filter.
*
* @return The constructed search filter.
*/
public static SearchFilter createEqualityFilter(
{
}
/**
* Creates a new equality search filter with the provided
* information.
*
* @param attributeType The attribute type for this equality
* filter.
* @param attributeOptions The set of attribute options for this
* equality filter.
* @param assertionValue The assertion value for this equality
* filter.
*
* @return The constructed search filter.
*/
public static SearchFilter createEqualityFilter(
{
false);
}
/**
* Creates a new substring search filter with the provided
* information.
*
* @param attributeType The attribute type for this filter.
* @param subInitialElement The subInitial element for substring
* filters.
* @param subAnyElements The subAny elements for substring
* filters.
* @param subFinalElement The subFinal element for substring
* filters.
*
* @return The constructed search filter.
*/
public static SearchFilter
{
subFinalElement, null, false);
}
/**
* Creates a new substring search filter with the provided
* information.
*
* @param attributeType The attribute type for this filter.
* @param attributeOptions The set of attribute options for this
* search filter.
* @param subInitialElement The subInitial element for substring
* filters.
* @param subAnyElements The subAny elements for substring
* filters.
* @param subFinalElement The subFinal element for substring
* filters.
*
* @return The constructed search filter.
*/
public static SearchFilter
{
subFinalElement, null, false);
}
/**
* Creates a greater-or-equal search filter with the provided
* information.
*
* @param attributeType The attribute type for this
* greater-or-equal filter.
* @param assertionValue The assertion value for this
* greater-or-equal filter.
*
* @return The constructed search filter.
*/
public static SearchFilter createGreaterOrEqualFilter(
{
}
/**
* Creates a greater-or-equal search filter with the provided
* information.
*
* @param attributeType The attribute type for this
* greater-or-equal filter.
* @param attributeOptions The set of attribute options for this
* search filter.
* @param assertionValue The assertion value for this
* greater-or-equal filter.
*
* @return The constructed search filter.
*/
public static SearchFilter createGreaterOrEqualFilter(
{
false);
}
/**
* Creates a less-or-equal search filter with the provided
* information.
*
* @param attributeType The attribute type for this less-or-equal
* filter.
* @param assertionValue The assertion value for this
* less-or-equal filter.
*
* @return The constructed search filter.
*/
public static SearchFilter createLessOrEqualFilter(
{
}
/**
* Creates a less-or-equal search filter with the provided
* information.
*
* @param attributeType The attribute type for this
* less-or-equal filter.
* @param attributeOptions The set of attribute options for this
* search filter.
* @param assertionValue The assertion value for this
* less-or-equal filter.
*
* @return The constructed search filter.
*/
public static SearchFilter createLessOrEqualFilter(
{
false);
}
/**
* Creates a presence search filter with the provided information.
*
* @param attributeType The attribute type for this presence
* filter.
*
* @return The constructed search filter.
*/
public static SearchFilter createPresenceFilter(
{
}
/**
* Creates a presence search filter with the provided information.
*
* @param attributeType The attribute type for this presence
* filter.
* @param attributeOptions The attribute options for this presence
* filter.
*
* @return The constructed search filter.
*/
public static SearchFilter createPresenceFilter(
{
}
/**
* Creates an approximate search filter with the provided
* information.
*
* @param attributeType The attribute type for this approximate
* filter.
* @param assertionValue The assertion value for this approximate
* filter.
*
* @return The constructed search filter.
*/
public static SearchFilter createApproximateFilter(
{
}
/**
* Creates an approximate search filter with the provided
* information.
*
* @param attributeType The attribute type for this approximate
* filter.
* @param attributeOptions The attribute options for this
* approximate filter.
* @param assertionValue The assertion value for this
* approximate filter.
*
* @return The constructed search filter.
*/
public static SearchFilter createApproximateFilter(
{
false);
}
/**
* Creates an extensible matching filter with the provided
* information.
*
* @param attributeType The attribute type for this extensible
* match filter.
* @param assertionValue The assertion value for this extensible
* match filter.
* @param matchingRuleID The matching rule ID for this search
* filter.
* @param dnAttributes Indicates whether to match on DN
* attributes for extensible match filters.
*
* @return The constructed search filter.
*
* @throws DirectoryException If the provided information is not
* sufficient to create an extensible
* match filter.
*/
public static SearchFilter createExtensibleMatchFilter(
boolean dnAttributes)
throws DirectoryException
{
{
throw new DirectoryException(
}
}
/**
* Creates an extensible matching filter with the provided
* information.
*
* @param attributeType The attribute type for this extensible
* match filter.
* @param attributeOptions The set of attribute options for this
* extensible match filter.
* @param assertionValue The assertion value for this extensible
* match filter.
* @param matchingRuleID The matching rule ID for this search
* filter.
* @param dnAttributes Indicates whether to match on DN
* attributes for extensible match
* filters.
*
* @return The constructed search filter.
*
* @throws DirectoryException If the provided information is not
* sufficient to create an extensible
* match filter.
*/
public static SearchFilter createExtensibleMatchFilter(
boolean dnAttributes)
throws DirectoryException
{
{
throw new DirectoryException(
}
}
/**
* Decodes the provided filter string as a search filter.
*
* @param filterString The filter string to be decoded as a search
* filter.
*
* @return The search filter decoded from the provided string.
*
* @throws DirectoryException If a problem occurs while attempting
* to decode the provided string as a
* search filter.
*/
public static SearchFilter createFilterFromString(
throws DirectoryException
{
if (filterString == null)
{
throw new DirectoryException(
}
try
{
filterString.length());
}
catch (DirectoryException de)
{
throw de;
}
catch (Exception e)
{
logger.traceException(e);
}
}
/**
* Creates a new search filter from the specified portion of the
* provided string.
*
* @param filterString The string containing the filter
* information to be decoded.
* @param startPos The index of the first character in the
* string that is part of the search filter.
* @param endPos The index of the first character after the
* start position that is not part of the
* search filter.
*
* @return The decoded search filter.
*
* @throws DirectoryException If a problem occurs while attempting
* to decode the provided string as a
* search filter.
*/
private static SearchFilter createFilterFromString(
int endPos)
throws DirectoryException
{
// Make sure that the length is sufficient for a valid search
// filter.
if (length <= 0)
{
throw new DirectoryException(
}
// If the filter is surrounded by parentheses (which it should
// be), then strip them off.
{
{
startPos++;
endPos--;
}
else
{
message);
}
}
// Look at the first character. If it is a '&' then it is an AND
// search. If it is a '|' then it is an OR search. If it is a
// '!' then it is a NOT search.
if (c == '&')
{
}
else if (c == '|')
{
}
else if (c == '!')
{
}
// If we've gotten here, then it must be a simple filter. It must
// have an equal sign at some point, so find it.
int equalPos = -1;
{
{
equalPos = i;
break;
}
}
{
message);
}
// Look at the character immediately before the equal sign,
// because it may help determine the filter type.
int attrEndPos;
{
case '~':
break;
case '>':
break;
case '<':
break;
case ':':
default:
break;
}
// The part of the filter string before the equal sign should be
// the attribute type (with or without options). Decode it.
if (semicolonPos < 0)
{
{
}
}
else
{
for (int i=0; i < semicolonPos; i++)
{
}
while (nextPos > 0)
{
nextPos));
}
}
// Get the attribute value.
{
}
{
}
{
endPos);
}
else
{
boolean hasEscape = false;
for (byte valueByte : valueBytes)
{
{
hasEscape = true;
break;
}
}
if (hasEscape)
{
{
{
// The next two bytes must be the hex characters that
// comprise the binary value.
{
message);
}
byte byteValue = 0;
switch (valueBytes[++i])
{
case 0x30: // '0'
break;
case 0x31: // '1'
byteValue = (byte) 0x10;
break;
case 0x32: // '2'
byteValue = (byte) 0x20;
break;
case 0x33: // '3'
byteValue = (byte) 0x30;
break;
case 0x34: // '4'
byteValue = (byte) 0x40;
break;
case 0x35: // '5'
byteValue = (byte) 0x50;
break;
case 0x36: // '6'
byteValue = (byte) 0x60;
break;
case 0x37: // '7'
byteValue = (byte) 0x70;
break;
case 0x38: // '8'
byteValue = (byte) 0x80;
break;
case 0x39: // '9'
byteValue = (byte) 0x90;
break;
case 0x41: // 'A'
case 0x61: // 'a'
byteValue = (byte) 0xA0;
break;
case 0x42: // 'B'
case 0x62: // 'b'
byteValue = (byte) 0xB0;
break;
case 0x43: // 'C'
case 0x63: // 'c'
byteValue = (byte) 0xC0;
break;
case 0x44: // 'D'
case 0x64: // 'd'
byteValue = (byte) 0xD0;
break;
case 0x45: // 'E'
case 0x65: // 'e'
byteValue = (byte) 0xE0;
break;
case 0x46: // 'F'
case 0x66: // 'f'
byteValue = (byte) 0xF0;
break;
default:
throw new DirectoryException(
}
switch (valueBytes[++i])
{
case 0x30: // '0'
break;
case 0x31: // '1'
byteValue |= (byte) 0x01;
break;
case 0x32: // '2'
byteValue |= (byte) 0x02;
break;
case 0x33: // '3'
byteValue |= (byte) 0x03;
break;
case 0x34: // '4'
byteValue |= (byte) 0x04;
break;
case 0x35: // '5'
byteValue |= (byte) 0x05;
break;
case 0x36: // '6'
byteValue |= (byte) 0x06;
break;
case 0x37: // '7'
byteValue |= (byte) 0x07;
break;
case 0x38: // '8'
byteValue |= (byte) 0x08;
break;
case 0x39: // '9'
byteValue |= (byte) 0x09;
break;
case 0x41: // 'A'
case 0x61: // 'a'
byteValue |= (byte) 0x0A;
break;
case 0x42: // 'B'
case 0x62: // 'b'
byteValue |= (byte) 0x0B;
break;
case 0x43: // 'C'
case 0x63: // 'c'
byteValue |= (byte) 0x0C;
break;
case 0x44: // 'D'
case 0x64: // 'd'
byteValue |= (byte) 0x0D;
break;
case 0x45: // 'E'
case 0x65: // 'e'
byteValue |= (byte) 0x0E;
break;
case 0x46: // 'F'
case 0x66: // 'f'
byteValue |= (byte) 0x0F;
break;
default:
throw new DirectoryException(
}
}
else
{
}
}
}
else
{
}
}
}
/**
* Decodes a set of filters from the provided filter string within
* the indicated range.
*
* @param filterType The filter type for this compound filter.
* It must be an AND, OR or NOT filter.
* @param filterString The string containing the filter
* information to decode.
* @param startPos The position of the first character in the
* set of filters to decode.
* @param endPos The position of the first character after
* the end of the set of filters to decode.
*
* @return The decoded search filter.
*
* @throws DirectoryException If a problem occurs while attempting
* to decode the compound filter.
*/
private static SearchFilter decodeCompoundFilter(
int endPos)
throws DirectoryException
{
// Create a list to hold the returned components.
// If the end pos is equal to the start pos, then there are no components.
{
{
}
else
{
null, false);
}
}
// The first and last characters must be parentheses. If not,
// then that's an error.
{
throw new DirectoryException(
}
// Iterate through the characters in the value. Whenever an open
// parenthesis is found, locate the corresponding close
// parentheses.
int pendingOpens = 0;
int openPos = -1;
{
char c = filterString.charAt(i);
if (c == '(')
{
if (openPos < 0)
{
openPos = i;
}
pendingOpens++;
}
else if (c == ')')
{
pendingOpens--;
if (pendingOpens == 0)
{
openPos, i+1));
openPos = -1;
}
else if (pendingOpens < 0)
{
get(filterString, i);
message);
}
}
else if (pendingOpens <= 0)
{
message);
}
}
// At this point, we have parsed the entire set of filter
// components. The list of open parenthesis positions must be
// empty.
if (pendingOpens != 0)
{
throw new DirectoryException(
}
// We should have everything we need, so return the list.
{
{
message);
}
false);
}
else
{
null, false);
}
}
/**
* Decodes a substring search filter component based on the provided
* information.
*
* @param filterString The filter string containing the
* information to decode.
* @param attrType The attribute type for this substring
* filter component.
* @param options The set of attribute options for the
* associated attribute type.
* @param equalPos The location of the equal sign separating
* the attribute type from the value.
* @param endPos The position of the first character after
* the end of the substring value.
*
* @return The decoded search filter.
*
* @throws DirectoryException If a problem occurs while attempting
* to decode the substring filter.
*/
private static SearchFilter decodeSubstringFilter(
int endPos)
throws DirectoryException
{
// Get a binary representation of the value.
byte[] valueBytes =
// Find the locations of all the asterisks in the value. Also,
// check to see if there are any escaped values, since they will
// need special treatment.
boolean hasEscape = false;
{
{
asteriskPositions.add(i);
}
{
hasEscape = true;
}
}
// If there were no asterisks, then this isn't a substring filter.
if (asteriskPositions.isEmpty())
{
throw new DirectoryException(
}
else
{
// The rest of the processing will be only on the value bytes,
// so re-adjust the end position.
}
// If the value starts with an asterisk, then there is no
// subInitial component. Otherwise, parse out the subInitial.
if (firstPos == 0)
{
subInitial = null;
}
else
{
if (hasEscape)
{
for (int i=0; i < firstPos; i++)
{
if (valueBytes[i] == 0x5C)
{
// The next two bytes must be the hex characters that
// comprise the binary value.
{
message);
}
byte byteValue = 0;
switch (valueBytes[++i])
{
case 0x30: // '0'
break;
case 0x31: // '1'
byteValue = (byte) 0x10;
break;
case 0x32: // '2'
byteValue = (byte) 0x20;
break;
case 0x33: // '3'
byteValue = (byte) 0x30;
break;
case 0x34: // '4'
byteValue = (byte) 0x40;
break;
case 0x35: // '5'
byteValue = (byte) 0x50;
break;
case 0x36: // '6'
byteValue = (byte) 0x60;
break;
case 0x37: // '7'
byteValue = (byte) 0x70;
break;
case 0x38: // '8'
byteValue = (byte) 0x80;
break;
case 0x39: // '9'
byteValue = (byte) 0x90;
break;
case 0x41: // 'A'
case 0x61: // 'a'
byteValue = (byte) 0xA0;
break;
case 0x42: // 'B'
case 0x62: // 'b'
byteValue = (byte) 0xB0;
break;
case 0x43: // 'C'
case 0x63: // 'c'
byteValue = (byte) 0xC0;
break;
case 0x44: // 'D'
case 0x64: // 'd'
byteValue = (byte) 0xD0;
break;
case 0x45: // 'E'
case 0x65: // 'e'
byteValue = (byte) 0xE0;
break;
case 0x46: // 'F'
case 0x66: // 'f'
byteValue = (byte) 0xF0;
break;
default:
throw new DirectoryException(
}
switch (valueBytes[++i])
{
case 0x30: // '0'
break;
case 0x31: // '1'
byteValue |= (byte) 0x01;
break;
case 0x32: // '2'
byteValue |= (byte) 0x02;
break;
case 0x33: // '3'
byteValue |= (byte) 0x03;
break;
case 0x34: // '4'
byteValue |= (byte) 0x04;
break;
case 0x35: // '5'
byteValue |= (byte) 0x05;
break;
case 0x36: // '6'
byteValue |= (byte) 0x06;
break;
case 0x37: // '7'
byteValue |= (byte) 0x07;
break;
case 0x38: // '8'
byteValue |= (byte) 0x08;
break;
case 0x39: // '9'
byteValue |= (byte) 0x09;
break;
case 0x41: // 'A'
case 0x61: // 'a'
byteValue |= (byte) 0x0A;
break;
case 0x42: // 'B'
case 0x62: // 'b'
byteValue |= (byte) 0x0B;
break;
case 0x43: // 'C'
case 0x63: // 'c'
byteValue |= (byte) 0x0C;
break;
case 0x44: // 'D'
case 0x64: // 'd'
byteValue |= (byte) 0x0D;
break;
case 0x45: // 'E'
case 0x65: // 'e'
byteValue |= (byte) 0x0E;
break;
case 0x46: // 'F'
case 0x66: // 'f'
byteValue |= (byte) 0x0F;
break;
default:
throw new DirectoryException(
}
}
else
{
}
}
}
else
{
}
}
// Next, process through the rest of the asterisks to get the subAny values.
for (int asteriskPos : asteriskPositions)
{
if (hasEscape)
{
{
if (valueBytes[i] == 0x5C)
{
// The next two bytes must be the hex characters that
// comprise the binary value.
{
message);
}
byte byteValue = 0;
switch (valueBytes[++i])
{
case 0x30: // '0'
break;
case 0x31: // '1'
byteValue = (byte) 0x10;
break;
case 0x32: // '2'
byteValue = (byte) 0x20;
break;
case 0x33: // '3'
byteValue = (byte) 0x30;
break;
case 0x34: // '4'
byteValue = (byte) 0x40;
break;
case 0x35: // '5'
byteValue = (byte) 0x50;
break;
case 0x36: // '6'
byteValue = (byte) 0x60;
break;
case 0x37: // '7'
byteValue = (byte) 0x70;
break;
case 0x38: // '8'
byteValue = (byte) 0x80;
break;
case 0x39: // '9'
byteValue = (byte) 0x90;
break;
case 0x41: // 'A'
case 0x61: // 'a'
byteValue = (byte) 0xA0;
break;
case 0x42: // 'B'
case 0x62: // 'b'
byteValue = (byte) 0xB0;
break;
case 0x43: // 'C'
case 0x63: // 'c'
byteValue = (byte) 0xC0;
break;
case 0x44: // 'D'
case 0x64: // 'd'
byteValue = (byte) 0xD0;
break;
case 0x45: // 'E'
case 0x65: // 'e'
byteValue = (byte) 0xE0;
break;
case 0x46: // 'F'
case 0x66: // 'f'
byteValue = (byte) 0xF0;
break;
default:
throw new DirectoryException(
}
switch (valueBytes[++i])
{
case 0x30: // '0'
break;
case 0x31: // '1'
byteValue |= (byte) 0x01;
break;
case 0x32: // '2'
byteValue |= (byte) 0x02;
break;
case 0x33: // '3'
byteValue |= (byte) 0x03;
break;
case 0x34: // '4'
byteValue |= (byte) 0x04;
break;
case 0x35: // '5'
byteValue |= (byte) 0x05;
break;
case 0x36: // '6'
byteValue |= (byte) 0x06;
break;
case 0x37: // '7'
byteValue |= (byte) 0x07;
break;
case 0x38: // '8'
byteValue |= (byte) 0x08;
break;
case 0x39: // '9'
byteValue |= (byte) 0x09;
break;
case 0x41: // 'A'
case 0x61: // 'a'
byteValue |= (byte) 0x0A;
break;
case 0x42: // 'B'
case 0x62: // 'b'
byteValue |= (byte) 0x0B;
break;
case 0x43: // 'C'
case 0x63: // 'c'
byteValue |= (byte) 0x0C;
break;
case 0x44: // 'D'
case 0x64: // 'd'
byteValue |= (byte) 0x0D;
break;
case 0x45: // 'E'
case 0x65: // 'e'
byteValue |= (byte) 0x0E;
break;
case 0x46: // 'F'
case 0x66: // 'f'
byteValue |= (byte) 0x0F;
break;
default:
throw new DirectoryException(
}
}
else
{
}
}
}
else
{
}
}
// Finally, see if there is anything after the last asterisk,
// which would be the subFinal value.
{
}
else
{
if (hasEscape)
{
{
if (valueBytes[i] == 0x5C)
{
// The next two bytes must be the hex characters that
// comprise the binary value.
{
message);
}
byte byteValue = 0;
switch (valueBytes[++i])
{
case 0x30: // '0'
break;
case 0x31: // '1'
byteValue = (byte) 0x10;
break;
case 0x32: // '2'
byteValue = (byte) 0x20;
break;
case 0x33: // '3'
byteValue = (byte) 0x30;
break;
case 0x34: // '4'
byteValue = (byte) 0x40;
break;
case 0x35: // '5'
byteValue = (byte) 0x50;
break;
case 0x36: // '6'
byteValue = (byte) 0x60;
break;
case 0x37: // '7'
byteValue = (byte) 0x70;
break;
case 0x38: // '8'
byteValue = (byte) 0x80;
break;
case 0x39: // '9'
byteValue = (byte) 0x90;
break;
case 0x41: // 'A'
case 0x61: // 'a'
byteValue = (byte) 0xA0;
break;
case 0x42: // 'B'
case 0x62: // 'b'
byteValue = (byte) 0xB0;
break;
case 0x43: // 'C'
case 0x63: // 'c'
byteValue = (byte) 0xC0;
break;
case 0x44: // 'D'
case 0x64: // 'd'
byteValue = (byte) 0xD0;
break;
case 0x45: // 'E'
case 0x65: // 'e'
byteValue = (byte) 0xE0;
break;
case 0x46: // 'F'
case 0x66: // 'f'
byteValue = (byte) 0xF0;
break;
default:
throw new DirectoryException(
}
switch (valueBytes[++i])
{
case 0x30: // '0'
break;
case 0x31: // '1'
byteValue |= (byte) 0x01;
break;
case 0x32: // '2'
byteValue |= (byte) 0x02;
break;
case 0x33: // '3'
byteValue |= (byte) 0x03;
break;
case 0x34: // '4'
byteValue |= (byte) 0x04;
break;
case 0x35: // '5'
byteValue |= (byte) 0x05;
break;
case 0x36: // '6'
byteValue |= (byte) 0x06;
break;
case 0x37: // '7'
byteValue |= (byte) 0x07;
break;
case 0x38: // '8'
byteValue |= (byte) 0x08;
break;
case 0x39: // '9'
byteValue |= (byte) 0x09;
break;
case 0x41: // 'A'
case 0x61: // 'a'
byteValue |= (byte) 0x0A;
break;
case 0x42: // 'B'
case 0x62: // 'b'
byteValue |= (byte) 0x0B;
break;
case 0x43: // 'C'
case 0x63: // 'c'
byteValue |= (byte) 0x0C;
break;
case 0x44: // 'D'
case 0x64: // 'd'
byteValue |= (byte) 0x0D;
break;
case 0x45: // 'E'
case 0x65: // 'e'
byteValue |= (byte) 0x0E;
break;
case 0x46: // 'F'
case 0x66: // 'f'
byteValue |= (byte) 0x0F;
break;
default:
throw new DirectoryException(
}
}
else
{
}
}
}
else
{
}
}
}
/**
* Decodes an extensible match filter component based on the
* provided information.
*
* @param filterString The filter string containing the
* information to decode.
* @param startPos The position in the filter string of the
* first character in the extensible match
* filter.
* @param equalPos The position of the equal sign in the
* extensible match filter.
* @param endPos The position of the first character after
* the end of the extensible match filter.
*
* @return The decoded search filter.
*
* @throws DirectoryException If a problem occurs while attempting
* to decode the extensible match
* filter.
*/
private static SearchFilter decodeExtensibleMatchFilter(
throws DirectoryException
{
boolean dnAttributes = false;
// Look at the first character. If it is a colon, then it must be
// followed by either the string "dn" or the matching rule ID. If
// it is not, then it must be the attribute type.
{
// See if it starts with ":dn". Otherwise, it much be the
// matching rule
// ID.
{
dnAttributes = true;
}
else
{
}
}
else
{
if (colonPos < 0)
{
message);
}
if (semicolonPos <0)
{
{
}
}
else
{
for (int i=0; i < semicolonPos; i++)
{
}
while (nextPos > 0)
{
nextPos));
}
}
// Get the attribute type for the specified name.
// followed by the matching rule ID.
{
{
dnAttributes = true;
{
}
}
else
{
}
}
}
// Parse out the attribute value.
endPos));
boolean hasEscape = false;
for (byte valueByte : valueBytes)
{
if (valueByte == 0x5C)
{
hasEscape = true;
break;
}
}
if (hasEscape)
{
{
{
// The next two bytes must be the hex characters that
// comprise the binary value.
{
message);
}
byte byteValue = 0;
switch (valueBytes[++i])
{
case 0x30: // '0'
break;
case 0x31: // '1'
byteValue = (byte) 0x10;
break;
case 0x32: // '2'
byteValue = (byte) 0x20;
break;
case 0x33: // '3'
byteValue = (byte) 0x30;
break;
case 0x34: // '4'
byteValue = (byte) 0x40;
break;
case 0x35: // '5'
byteValue = (byte) 0x50;
break;
case 0x36: // '6'
byteValue = (byte) 0x60;
break;
case 0x37: // '7'
byteValue = (byte) 0x70;
break;
case 0x38: // '8'
byteValue = (byte) 0x80;
break;
case 0x39: // '9'
byteValue = (byte) 0x90;
break;
case 0x41: // 'A'
case 0x61: // 'a'
byteValue = (byte) 0xA0;
break;
case 0x42: // 'B'
case 0x62: // 'b'
byteValue = (byte) 0xB0;
break;
case 0x43: // 'C'
case 0x63: // 'c'
byteValue = (byte) 0xC0;
break;
case 0x44: // 'D'
case 0x64: // 'd'
byteValue = (byte) 0xD0;
break;
case 0x45: // 'E'
case 0x65: // 'e'
byteValue = (byte) 0xE0;
break;
case 0x46: // 'F'
case 0x66: // 'f'
byteValue = (byte) 0xF0;
break;
default:
message);
}
switch (valueBytes[++i])
{
case 0x30: // '0'
break;
case 0x31: // '1'
byteValue |= (byte) 0x01;
break;
case 0x32: // '2'
byteValue |= (byte) 0x02;
break;
case 0x33: // '3'
byteValue |= (byte) 0x03;
break;
case 0x34: // '4'
byteValue |= (byte) 0x04;
break;
case 0x35: // '5'
byteValue |= (byte) 0x05;
break;
case 0x36: // '6'
byteValue |= (byte) 0x06;
break;
case 0x37: // '7'
byteValue |= (byte) 0x07;
break;
case 0x38: // '8'
byteValue |= (byte) 0x08;
break;
case 0x39: // '9'
byteValue |= (byte) 0x09;
break;
case 0x41: // 'A'
case 0x61: // 'a'
byteValue |= (byte) 0x0A;
break;
case 0x42: // 'B'
case 0x62: // 'b'
byteValue |= (byte) 0x0B;
break;
case 0x43: // 'C'
case 0x63: // 'c'
byteValue |= (byte) 0x0C;
break;
case 0x44: // 'D'
case 0x64: // 'd'
byteValue |= (byte) 0x0D;
break;
case 0x45: // 'E'
case 0x65: // 'e'
byteValue |= (byte) 0x0E;
break;
case 0x46: // 'F'
case 0x66: // 'f'
byteValue |= (byte) 0x0F;
break;
default:
message);
}
}
else
{
}
}
}
else
{
}
// Make sure that the filter contains at least one of an attribute
// type or a matching rule ID. Also, construct the appropriate
// attribute value.
if (attributeType == null)
{
if (matchingRuleID == null)
{
}
{
}
}
}
{
if (attributeType == null)
{
}
return attributeType;
}
/**
* Retrieves the filter type for this search filter.
*
* @return The filter type for this search filter.
*/
public FilterType getFilterType()
{
return filterType;
}
/**
* Retrieves the set of filter components for this AND or OR filter.
* The returned list can be modified by the caller.
*
* @return The set of filter components for this AND or OR filter.
*/
{
return filterComponents;
}
/**
* Retrieves the filter component for this NOT filter.
*
* @return The filter component for this NOT filter, or
* <CODE>null</CODE> if this is not a NOT filter.
*/
public SearchFilter getNotComponent()
{
return notComponent;
}
/**
* Retrieves the attribute type for this filter.
*
* @return The attribute type for this filter, or <CODE>null</CODE>
* if there is none.
*/
public AttributeType getAttributeType()
{
return attributeType;
}
/**
* Retrieves the assertion value for this filter.
*
* @return The assertion value for this filter, or
* <CODE>null</CODE> if there is none.
*/
public ByteString getAssertionValue()
{
return assertionValue;
}
/**
* Retrieves the subInitial element for this substring filter.
*
* @return The subInitial element for this substring filter, or
* <CODE>null</CODE> if there is none.
*/
public ByteString getSubInitialElement()
{
return subInitialElement;
}
/**
* Retrieves the set of subAny elements for this substring filter.
* The returned list may be altered by the caller.
*
* @return The set of subAny elements for this substring filter.
*/
{
return subAnyElements;
}
/**
* Retrieves the subFinal element for this substring filter.
*
* @return The subFinal element for this substring filter.
*/
public ByteString getSubFinalElement()
{
return subFinalElement;
}
/**
* Retrieves the matching rule ID for this extensible matching
* filter.
*
* @return The matching rule ID for this extensible matching
* filter.
*/
public String getMatchingRuleID()
{
return matchingRuleID;
}
/**
* Retrieves the dnAttributes flag for this extensible matching
* filter.
*
* @return The dnAttributes flag for this extensible matching
* filter.
*/
public boolean getDNAttributes()
{
return dnAttributes;
}
/**
* Indicates whether this search filter matches the provided entry.
*
* @param entry The entry for which to make the determination.
*
* @return <CODE>true</CODE> if this search filter matches the
* provided entry, or <CODE>false</CODE> if it does not.
*
* @throws DirectoryException If a problem is encountered during
* processing.
*/
throws DirectoryException
{
switch (result)
{
case TRUE:
return true;
case FALSE:
case UNDEFINED:
return false;
default:
return false;
}
}
/**
* Indicates whether the this filter matches the provided entry.
*
* @param completeFilter The complete filter being checked, of
* which this filter may be a subset.
* @param entry The entry for which to make the
* determination.
* @param depth The current depth of the evaluation,
* which is used to prevent infinite
* recursion due to highly nested filters
* and eventually running out of stack
* space.
*
* @return <CODE>TRUE</CODE> if this filter matches the provided
* entry, <CODE>FALSE</CODE> if it does not, or
* <CODE>UNDEFINED</CODE> if the result is undefined.
*
* @throws DirectoryException If a problem is encountered during
* processing.
*/
private ConditionResult matchesEntryInternal(
throws DirectoryException
{
switch (filterType)
{
case AND:
case OR:
case NOT:
case EQUALITY:
case SUBSTRING:
case GREATER_OR_EQUAL:
case LESS_OR_EQUAL:
case PRESENT:
case APPROXIMATE_MATCH:
case EXTENSIBLE_MATCH:
default:
// This is an invalid filter type.
}
}
/**
* Indicates whether the this AND filter matches the provided entry.
*
* @param completeFilter The complete filter being checked, of
* which this filter may be a subset.
* @param entry The entry for which to make the
* determination.
* @param depth The current depth of the evaluation,
* which is used to prevent infinite
* recursion due to highly nested filters
* and eventually running out of stack
* space.
*
* @return <CODE>TRUE</CODE> if this filter matches the provided
* entry, <CODE>FALSE</CODE> if it does not, or
* <CODE>UNDEFINED</CODE> if the result is undefined.
*
* @throws DirectoryException If a problem is encountered during
* processing.
*/
throws DirectoryException
{
if (filterComponents == null)
{
// The set of subcomponents was null. This is not allowed.
}
else if (filterComponents.isEmpty())
{
// An AND filter with no elements like "(&)" is specified as
// "undefined" in RFC 2251, but is considered one of the
// always return true.
if (logger.isTraceEnabled())
{
"filter (&)");
}
return ConditionResult.TRUE;
}
else
{
// We will have to evaluate one or more subcomponents. In
// this case, first check our depth to make sure we're not
// nesting too deep.
if (depth >= MAX_NESTED_FILTER_DEPTH)
{
}
for (SearchFilter f : filterComponents)
{
switch (result)
{
case TRUE:
break;
case FALSE:
if (logger.isTraceEnabled())
{
"Returning FALSE for AND component %s in " +
"filter %s for entry %s",
}
return result;
case UNDEFINED:
if (logger.isTraceEnabled())
{
"Undefined result for AND component %s in filter " +
}
return result;
default:
}
}
// If we have gotten here, then all the components must have
// matched.
if (logger.isTraceEnabled())
{
"Returning TRUE for AND component %s in filter %s " +
}
return ConditionResult.TRUE;
}
}
/**
* Indicates whether the this OR filter matches the provided entry.
*
* @param completeFilter The complete filter being checked, of
* which this filter may be a subset.
* @param entry The entry for which to make the
* determination.
* @param depth The current depth of the evaluation,
* which is used to prevent infinite
* recursion due to highly nested filters
* and eventually running out of stack
* space.
*
* @return <CODE>TRUE</CODE> if this filter matches the provided
* entry, <CODE>FALSE</CODE> if it does not, or
* <CODE>UNDEFINED</CODE> if the result is undefined.
*
* @throws DirectoryException If a problem is encountered during
* processing.
*/
throws DirectoryException
{
if (filterComponents == null)
{
// The set of subcomponents was null. This is not allowed.
throw new DirectoryException(
message);
}
else if (filterComponents.isEmpty())
{
// An OR filter with no elements like "(|)" is specified as
// "undefined" in RFC 2251, but is considered one of the
// always return false.
if (logger.isTraceEnabled())
{
"filter (|)");
}
return ConditionResult.FALSE;
}
else
{
// We will have to evaluate one or more subcomponents. In
// this case, first check our depth to make sure we're not
// nesting too deep.
if (depth >= MAX_NESTED_FILTER_DEPTH)
{
throw new DirectoryException(
message);
}
for (SearchFilter f : filterComponents)
{
depth+1))
{
case TRUE:
if (logger.isTraceEnabled())
{
"Returning TRUE for OR component %s in filter " +
"%s for entry %s",
}
return ConditionResult.TRUE;
case FALSE:
break;
case UNDEFINED:
if (logger.isTraceEnabled())
{
"Undefined result for OR component %s in filter " +
"%s for entry %s",
}
break;
default:
throw new
message);
}
}
if (logger.isTraceEnabled())
{
"Returning %s for OR component %s in filter %s for " +
}
return result;
}
}
/**
* Indicates whether the this NOT filter matches the provided entry.
*
* @param completeFilter The complete filter being checked, of
* which this filter may be a subset.
* @param entry The entry for which to make the
* determination.
* @param depth The current depth of the evaluation,
* which is used to prevent infinite
* recursion due to highly nested filters
* and eventually running out of stack
* space.
*
* @return <CODE>TRUE</CODE> if this filter matches the provided
* entry, <CODE>FALSE</CODE> if it does not, or
* <CODE>UNDEFINED</CODE> if the result is undefined.
*
* @throws DirectoryException If a problem is encountered during
* processing.
*/
throws DirectoryException
{
if (notComponent == null)
{
// The NOT subcomponent was null. This is not allowed.
throw new DirectoryException(
message);
}
else
{
// The subcomponent for the NOT filter can be an AND, OR, or
// NOT filter that would require more nesting. Make sure
// that we don't go too deep.
if (depth >= MAX_NESTED_FILTER_DEPTH)
{
throw new DirectoryException(
message);
}
switch (result)
{
case TRUE:
if (logger.isTraceEnabled())
{
"Returning FALSE for NOT component %s in filter " +
"%s for entry %s",
}
return ConditionResult.FALSE;
case FALSE:
if (logger.isTraceEnabled())
{
"Returning TRUE for NOT component %s in filter " +
"%s for entry %s",
}
return ConditionResult.TRUE;
case UNDEFINED:
if (logger.isTraceEnabled())
{
"Undefined result for NOT component %s in filter " +
"%s for entry %s",
}
return ConditionResult.UNDEFINED;
default:
throw new
message);
}
}
}
/**
* Indicates whether the this equality filter matches the provided
* entry.
*
* @param completeFilter The complete filter being checked, of
* which this filter may be a subset.
* @param entry The entry for which to make the
* determination.
*
* @return <CODE>TRUE</CODE> if this filter matches the provided
* entry, <CODE>FALSE</CODE> if it does not, or
* <CODE>UNDEFINED</CODE> if the result is undefined.
*
* @throws DirectoryException If a problem is encountered during
* processing.
*/
throws DirectoryException
{
// Make sure that an attribute type has been defined.
if (attributeType == null)
{
}
// Make sure that an assertion value has been defined.
if (assertionValue == null)
{
}
// See if the entry has an attribute with the requested type.
{
if (logger.isTraceEnabled())
{
"Returning FALSE for equality component %s in " +
"filter %s because entry %s didn't have attribute " +
"type %s",
}
return ConditionResult.FALSE;
}
// Get the equality matching rule for the given attribute type
if (matchingRule == null)
{
if (logger.isTraceEnabled())
{
"Attribute type %s does not have an equality matching " +
"rule -- returning undefined.",
}
return ConditionResult.UNDEFINED;
}
// Iterate through all the attributes and see if we can find a match.
{
{
if (logger.isTraceEnabled())
{
"Returning TRUE for equality component %s in filter %s " +
}
return ConditionResult.TRUE;
}
{
}
}
if (logger.isTraceEnabled())
{
"Returning %s for equality component %s in filter %s " +
"because entry %s didn't have attribute type %s with value %s",
}
return result;
}
/**
* Indicates whether the this substring filter matches the provided
* entry.
*
* @param completeFilter The complete filter being checked, of
* which this filter may be a subset.
* @param entry The entry for which to make the
* determination.
*
* @return <CODE>TRUE</CODE> if this filter matches the provided
* entry, <CODE>FALSE</CODE> if it does not, or
* <CODE>UNDEFINED</CODE> if the result is undefined.
*
* @throws DirectoryException If a problem is encountered during
* processing.
*/
private ConditionResult processSubstring(
throws DirectoryException
{
// Make sure that an attribute type has been defined.
if (attributeType == null)
{
}
// Make sure that at least one substring element has been defined.
if (subInitialElement == null &&
subFinalElement == null &&
{
}
// See if the entry has an attribute with the requested type.
{
if (logger.isTraceEnabled())
{
"Returning FALSE for substring component %s in " +
"filter %s because entry %s didn't have attribute " +
"type %s",
}
return ConditionResult.FALSE;
}
// Iterate through all the attributes and see if we can find a
// match.
{
switch (a.matchesSubstring(subInitialElement,
{
case TRUE:
if (logger.isTraceEnabled())
{
"Returning TRUE for substring component %s in " +
"filter %s for entry %s",
}
return ConditionResult.TRUE;
case FALSE:
break;
case UNDEFINED:
if (logger.isTraceEnabled())
{
"Undefined result encountered for substring " +
"component %s in filter %s for entry %s",
}
break;
default:
}
}
if (logger.isTraceEnabled())
{
"Returning %s for substring component %s in filter " +
"%s for entry %s",
}
return result;
}
/**
* Indicates whether the this greater-or-equal filter matches the
* provided entry.
*
* @param completeFilter The complete filter being checked, of
* which this filter may be a subset.
* @param entry The entry for which to make the
* determination.
*
* @return <CODE>TRUE</CODE> if this filter matches the provided
* entry, <CODE>FALSE</CODE> if it does not, or
* <CODE>UNDEFINED</CODE> if the result is undefined.
*
* @throws DirectoryException If a problem is encountered during
* processing.
*/
private ConditionResult processGreaterOrEqual(
throws DirectoryException
{
// Make sure that an attribute type has been defined.
if (attributeType == null)
{
}
// Make sure that an assertion value has been defined.
if (assertionValue == null)
{
}
// See if the entry has an attribute with the requested type.
{
if (logger.isTraceEnabled())
{
"greater-or-equal component %s in filter %s " +
"because entry %s didn't have attribute type %s",
}
return ConditionResult.FALSE;
}
// Iterate through all the attributes and see if we can find a
// match.
{
switch (a.greaterThanOrEqualTo(assertionValue))
{
case TRUE:
if (logger.isTraceEnabled())
{
"Returning TRUE for greater-or-equal component " +
"%s in filter %s for entry %s",
}
return ConditionResult.TRUE;
case FALSE:
break;
case UNDEFINED:
if (logger.isTraceEnabled())
{
"Undefined result encountered for " +
"greater-or-equal component %s in filter %s " +
"for entry %s", this, completeFilter,
}
break;
default:
}
}
if (logger.isTraceEnabled())
{
"Returning %s for greater-or-equal component %s in " +
"filter %s for entry %s",
}
return result;
}
/**
* Indicates whether the this less-or-equal filter matches the
* provided entry.
*
* @param completeFilter The complete filter being checked, of
* which this filter may be a subset.
* @param entry The entry for which to make the
* determination.
*
* @return <CODE>TRUE</CODE> if this filter matches the provided
* entry, <CODE>FALSE</CODE> if it does not, or
* <CODE>UNDEFINED</CODE> if the result is undefined.
*
* @throws DirectoryException If a problem is encountered during
* processing.
*/
private ConditionResult processLessOrEqual(
throws DirectoryException
{
// Make sure that an attribute type has been defined.
if (attributeType == null)
{
}
// Make sure that an assertion value has been defined.
if (assertionValue == null)
{
}
// See if the entry has an attribute with the requested type.
{
if (logger.isTraceEnabled())
{
"Returning FALSE for less-or-equal component %s in " +
"filter %s because entry %s didn't have attribute " +
}
return ConditionResult.FALSE;
}
// Iterate through all the attributes and see if we can find a
// match.
{
switch (a.lessThanOrEqualTo(assertionValue))
{
case TRUE:
if (logger.isTraceEnabled())
{
"Returning TRUE for less-or-equal component %s " +
"in filter %s for entry %s",
}
return ConditionResult.TRUE;
case FALSE:
break;
case UNDEFINED:
if (logger.isTraceEnabled())
{
"Undefined result encountered for " +
"less-or-equal component %s in filter %s " +
"for entry %s",
}
break;
default:
}
}
if (logger.isTraceEnabled())
{
"Returning %s for less-or-equal component %s in " +
"filter %s for entry %s",
}
return result;
}
/**
* Indicates whether the this present filter matches the provided
* entry.
*
* @param completeFilter The complete filter being checked, of
* which this filter may be a subset.
* @param entry The entry for which to make the
* determination.
*
* @return <CODE>TRUE</CODE> if this filter matches the provided
* entry, <CODE>FALSE</CODE> if it does not, or
* <CODE>UNDEFINED</CODE> if the result is undefined.
*
* @throws DirectoryException If a problem is encountered during
* processing.
*/
throws DirectoryException
{
// Make sure that an attribute type has been defined.
if (attributeType == null)
{
}
// See if the entry has an attribute with the requested type.
// If so, then it's a match. If not, then it's not a match.
if (logger.isTraceEnabled())
{
"Returning %s for presence component %s in filter %s for entry %s",
}
return result;
}
/**
* Indicates whether the this approximate filter matches the
* provided entry.
*
* @param completeFilter The complete filter being checked, of
* which this filter may be a subset.
* @param entry The entry for which to make the
* determination.
*
* @return <CODE>TRUE</CODE> if this filter matches the provided
* entry, <CODE>FALSE</CODE> if it does not, or
* <CODE>UNDEFINED</CODE> if the result is undefined.
*
* @throws DirectoryException If a problem is encountered during
* processing.
*/
private ConditionResult processApproximate(
throws DirectoryException
{
// Make sure that an attribute type has been defined.
if (attributeType == null)
{
}
// Make sure that an assertion value has been defined.
if (assertionValue == null)
{
}
// See if the entry has an attribute with the requested type.
{
if (logger.isTraceEnabled())
{
"Returning FALSE for approximate component %s in " +
"filter %s because entry %s didn't have attribute " +
}
return ConditionResult.FALSE;
}
// Iterate through all the attributes and see if we can find a
// match.
{
switch (a.approximatelyEqualTo(assertionValue))
{
case TRUE:
if (logger.isTraceEnabled())
{
"Returning TRUE for approximate component %s in " +
"filter %s for entry %s",
}
return ConditionResult.TRUE;
case FALSE:
break;
case UNDEFINED:
if (logger.isTraceEnabled())
{
"Undefined result encountered for approximate " +
"component %s in filter %s for entry %s",
}
break;
default:
}
}
if (logger.isTraceEnabled())
{
"Returning %s for approximate component %s in filter " +
"%s for entry %s",
}
return result;
}
/**
* Indicates whether this extensibleMatch filter matches the
* provided entry.
*
* @param completeFilter The complete filter in which this
* extensibleMatch filter may be a
* subcomponent.
* @param entry The entry for which to make the
* determination.
*
* @return <CODE>TRUE</CODE> if this extensibleMatch filter matches
* the provided entry, <CODE>FALSE</CODE> if it does not, or
* <CODE>UNDEFINED</CODE> if the result cannot be
* determined.
*
* @throws DirectoryException If a problem occurs while evaluating
* this filter against the provided
* entry.
*/
private ConditionResult processExtensibleMatch(
throws DirectoryException
{
// We must have an assertion value for which to make the
// determination.
if (assertionValue == null)
{
message);
}
if (matchingRuleID != null)
{
if (matchingRule == null)
{
if (logger.isTraceEnabled())
{
"Unknown matching rule %s defined in extensibleMatch " +
"component of filter %s -- returning undefined.",
matchingRuleID, this);
}
return ConditionResult.UNDEFINED;
}
}
else
{
if (attributeType == null)
{
message);
}
else
{
if (matchingRule == null)
{
if (logger.isTraceEnabled())
{
"Attribute type %s does not have an equality matching " +
"rule -- returning undefined.",
}
return ConditionResult.UNDEFINED;
}
}
}
// If there is an attribute type, then check to see if there is a
// corresponding matching rule use for the matching rule and
// determine if it allows that attribute type.
if (attributeType != null)
{
{
if (logger.isTraceEnabled())
{
"Attribute type %s is not allowed for use with " +
"matching rule %s because of matching rule use " +
}
return ConditionResult.UNDEFINED;
}
}
// Normalize the assertion value using the matching rule.
try
{
}
catch (Exception e)
{
logger.traceException(e);
// We can't normalize the assertion value, so the result must be
// undefined.
return ConditionResult.UNDEFINED;
}
// If there is an attribute type, then we should only check for
// that attribute. Otherwise, we should check against all
// attributes in the entry.
if (attributeType == null)
{
{
{
for (ByteString v : a)
{
try
{
switch (r)
{
case TRUE:
return ConditionResult.TRUE;
case FALSE:
break;
case UNDEFINED:
break;
default:
throw new DirectoryException(
}
}
catch (Exception e)
{
logger.traceException(e);
// We couldn't normalize one of the values. If we don't
// find a definite match, then we should return
// undefined.
}
}
}
}
{
{
for (ByteString v : a)
{
try
{
switch (r)
{
case TRUE:
return ConditionResult.TRUE;
case FALSE:
break;
case UNDEFINED:
break;
default:
throw new DirectoryException(
}
}
catch (Exception e)
{
logger.traceException(e);
// We couldn't normalize one of the values. If we don't
// find a definite match, then we should return
// undefined.
}
}
}
}
for (ByteString v : a)
{
try
{
switch (r)
{
case TRUE:
return ConditionResult.TRUE;
case FALSE:
break;
case UNDEFINED:
break;
default:
message);
}
}
catch (Exception e)
{
logger.traceException(e);
// We couldn't normalize one of the values. If we don't
// find a definite match, then we should return undefined.
}
}
}
else
{
{
{
for (ByteString v : a)
{
try
{
switch (r)
{
case TRUE:
return ConditionResult.TRUE;
case FALSE:
break;
case UNDEFINED:
break;
default:
throw new DirectoryException(
}
}
catch (Exception e)
{
logger.traceException(e);
// We couldn't normalize one of the values. If we don't
// find a definite match, then we should return
// undefined.
}
}
}
}
}
// If we've gotten here, then we know that there is no definite
// match in the set of attributes. If we should check DN
// attributes, then do so.
if (dnAttributes)
{
{
for (int i=0; i < numAVAs; i++)
{
try
{
{
switch (r)
{
case TRUE:
return ConditionResult.TRUE;
case FALSE:
break;
case UNDEFINED:
break;
default:
throw new DirectoryException(
}
}
}
catch (Exception e)
{
logger.traceException(e);
// We couldn't normalize one of the values. If we don't
// find a definite match, then we should return undefined.
}
}
}
}
// If we've gotten here, then there is no definitive match, so
// we'll either return FALSE or UNDEFINED.
return result;
}
/**
* Indicates whether this search filter is equal to the provided
* object.
*
* @param o The object for which to make the determination.
*
* @return <CODE>true</CODE> if the provide object is equal to this
* search filter, or <CODE>false</CODE> if it is not.
*/
{
if (o == null)
{
return false;
}
if (o == this)
{
return true;
}
if (! (o instanceof SearchFilter))
{
return false;
}
SearchFilter f = (SearchFilter) o;
if (filterType != f.filterType)
{
return false;
}
switch (filterType)
{
case AND:
case OR:
return andOrEqual(f);
case NOT:
case EQUALITY:
return typeAndOptionsAndAssertionEqual(f);
case SUBSTRING:
return substringEqual(f);
case GREATER_OR_EQUAL:
return typeAndOptionsAndAssertionEqual(f);
case LESS_OR_EQUAL:
return typeAndOptionsAndAssertionEqual(f);
case PRESENT:
case APPROXIMATE_MATCH:
return typeAndOptionsAndAssertionEqual(f);
case EXTENSIBLE_MATCH:
return extensibleEqual(f);
default:
return false;
}
}
private boolean andOrEqual(SearchFilter f)
{
{
return false;
}
{
{
return false;
}
}
return true;
}
private boolean typeAndOptionsAndAssertionEqual(SearchFilter f)
{
}
{
{
return false;
}
{
return false;
}
{
return false;
}
if (!initialCheck)
{
return false;
}
if (!finalCheck)
{
return false;
}
if (!anyCheck)
{
return false;
}
if (subAnyElements != null)
{
{
{
return false;
}
}
}
return true;
}
private boolean extensibleEqual(SearchFilter f)
{
if (attributeType == null)
{
if (f.attributeType != null)
{
return false;
}
}
else
{
{
return false;
}
{
return false;
}
}
if (dnAttributes != f.dnAttributes)
{
return false;
}
if (matchingRuleID == null)
{
if (f.matchingRuleID != null)
{
return false;
}
}
else
{
{
return false;
}
}
if (assertionValue == null)
{
if (f.assertionValue != null)
{
return false;
}
}
else
{
if (matchingRuleID == null)
{
{
return false;
}
}
else
{
{
return false;
}
else
{
try
{
}
catch (Exception e)
{
return false;
}
}
}
}
return true;
}
/**
* Indicates whether the two provided sets of attribute options
* should be considered equal.
*
* @param options1 The first set of attribute options for which to
* make the determination.
* @param options2 The second set of attribute options for which
* to make the determination.
*
* @return {@code true} if the sets of attribute options are equal,
* or {@code false} if not.
*/
{
{
}
{
return false;
}
else
{
{
return false;
}
{
}
{
{
return false;
}
}
return lowerOptions.isEmpty();
}
}
/**
* Retrieves the hash code for this search filter.
*
* @return The hash code for this search filter.
*/
public int hashCode()
{
switch (filterType)
{
case AND:
case OR:
int hashCode = 0;
{
}
return hashCode;
case NOT:
return notComponent.hashCode();
case EQUALITY:
return typeAndAssertionHashCode();
case SUBSTRING:
return substringHashCode();
case GREATER_OR_EQUAL:
return typeAndAssertionHashCode();
case LESS_OR_EQUAL:
return typeAndAssertionHashCode();
case PRESENT:
return attributeType.hashCode();
case APPROXIMATE_MATCH:
return typeAndAssertionHashCode();
case EXTENSIBLE_MATCH:
return extensibleHashCode();
default:
return 1;
}
}
/** Returns the hash code for extensible filter. */
private int extensibleHashCode()
{
int hashCode = 0;
if (attributeType != null)
{
}
if (dnAttributes)
{
hashCode++;
}
if (matchingRuleID != null)
{
}
if (assertionValue != null)
{
}
return hashCode;
}
private int typeAndAssertionHashCode()
{
}
/** Returns hash code to use for substring filter. */
private int substringHashCode()
{
if (subInitialElement != null)
{
}
if (subAnyElements != null)
{
for (ByteString e : subAnyElements)
{
}
}
if (subFinalElement != null)
{
}
return hashCode;
}
/**
* Retrieves a string representation of this search filter.
*
* @return A string representation of this search filter.
*/
{
}
/**
* Appends a string representation of this search filter to the
* provided buffer.
*
* @param buffer The buffer to which the information should be
* appended.
*/
{
switch (filterType)
{
case AND:
for (SearchFilter f : filterComponents)
{
}
break;
case OR:
for (SearchFilter f : filterComponents)
{
}
break;
case NOT:
break;
case EQUALITY:
break;
case SUBSTRING:
if (subInitialElement != null)
{
}
{
for (ByteString s : subAnyElements)
{
}
}
if (subFinalElement != null)
{
}
break;
case GREATER_OR_EQUAL:
break;
case LESS_OR_EQUAL:
break;
case PRESENT:
break;
case APPROXIMATE_MATCH:
break;
case EXTENSIBLE_MATCH:
if (attributeType != null)
{
}
if (dnAttributes)
{
}
if (matchingRuleID != null)
{
}
break;
}
}
{
{
{
}
}
}
/**
* Appends a properly-cleaned version of the provided value to the
* given buffer so that it can be safely used in string
* representations of this search filter. The formatting changes
* that may be performed will be in compliance with the
* specification in RFC 2254.
*
* @param buffer The buffer to which the "safe" version of the
* value will be appended.
* @param value The value to be appended to the buffer.
*/
{
{
return;
}
// Get the binary representation of the value and iterate through
// it to see if there are any unsafe characters. If there are,
// then escape them and replace them with a two-digit hex
// equivalent.
byte b;
{
if (((b & 0x7F) != b) || // Not 7-bit clean
(b <= 0x1F) || // Below the printable character range
(b == 0x28) || // Open parenthesis
(b == 0x29) || // Close parenthesis
(b == 0x2A) || // Asterisk
(b == 0x5C) || // Backslash
(b == 0x7F)) // Delete character
{
}
else
{
}
}
}
/**
* Returns the {@code objectClass} presence filter {@code (objectClass=*)}.
*
* @return The {@code objectClass} presence filter {@code (objectClass=*)}.
*/
public static SearchFilter objectClassPresent()
{
if (objectClassPresent == null)
{
try
{
}
catch (DirectoryException canNeverHappen)
{
}
}
return objectClassPresent;
}
}