/* * 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 * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * 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 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. 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 2006 Sun Microsystems, Inc. */ package org.opends.server.core; import static org.opends.server.loggers.Debug.debugConstructor; import static org.opends.server.loggers.Debug.debugEnter; import static org.opends.server.messages.MessageHandler.getMessage; import static org.opends.server.messages.SchemaMessages.*; import java.util.HashSet; import java.util.InputMismatchException; import java.util.NoSuchElementException; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.opends.server.types.ResultCode; import org.opends.server.types.SearchFilter; import org.opends.server.util.StaticUtils; /** * A relative subtree specification. *
* Relative subtree specifications are very similar toRFC 3672 subtree * specifications with the only difference being that the specification * filter is not a set of refinements, but an LDAP search filter. *
* The string representation of a relative subtree specification is * defined by the following grammar: * *
* SubtreeSpecification = "{"
* [ sp ss-relative-base ]
* [ sep sp ss-specificExclusions ]
* [ sep sp ss-minimum ]
* [ sep sp ss-maximum ]
* [ sep sp ss-specificationFilter ]
* sp "}"
*
* ss-relative-base = "relativeBase" msp DistinguishedName
*
* ss-specificExclusions = "specificExclusions"
* msp SpecificExclusions
*
* ss-minimum = "minimum" msp BaseDistance
*
* ss-maximum = "maximum" msp BaseDistance
*
* ss-specificationFilter = "specificationFilter" msp Filter
*
* SpecificExclusions = "{"
* [ sp SpecificExclusion
* ( "," sp SpecificExclusion ) ]
* sp "}"
*
* SpecificExclusion = chopBefore / chopAfter
*
* chopBefore = "chopBefore" ":" LocalName
*
* chopAfter = "chopAfter" ":" LocalName
*
* Filter = dquote *SafeUTF8Character dquote
*
*/
public final class RelativeSubtreeSpecification extends
SimpleSubtreeSpecification {
// Fully qualified class name for debugging purposes.
private static final String CLASS_NAME = RelativeSubtreeSpecification.class
.getName();
// The root DN.
private DN rootDN;
// The optional relative base DN.
private DN relativeBaseDN;
// The optional search filter.
private SearchFilter filter;
/**
* Parses the string argument as a relative subtree specification.
*
* @param rootDN
* The DN of the subtree specification's base entry.
* @param s
* The string to be parsed.
* @return The relative subtree specification represented by the
* string argument.
* @throws DirectoryException
* If the string does not contain a parsable relative
* subtree specification.
*/
public static RelativeSubtreeSpecification valueOf(DN rootDN, String s)
throws DirectoryException {
assert debugEnter(CLASS_NAME, "valueOf");
// Default values.
DN relativeBaseDN = null;
int minimum = -1;
int maximum = -1;
HashSetnull if not
* specified).
* @param minimumDepth
* The minimum depth (<=0 means unlimited).
* @param maximumDepth
* The maximum depth (<0 means unlimited).
* @param chopBefore
* The set of chop before local names (relative to the base
* DN), or null if there are none.
* @param chopAfter
* The set of chop after local names (relative to the base
* DN), or null if there are none.
* @param filter
* The optional search filter (null if there
* is no filter).
*/
public RelativeSubtreeSpecification(DN rootDN, DN relativeBaseDN,
int minimumDepth, int maximumDepth, Iterablenull if none
* was specified.
*/
public DN getRelativeBaseDN() {
assert debugEnter(CLASS_NAME, "getRelativeBaseDN");
return relativeBaseDN;
}
/**
* Get the specification filter.
*
* @return Returns the search filter, or null if there
* is no filter.
*/
public SearchFilter getFilter() {
assert debugEnter(CLASS_NAME, "getFilter");
return filter;
}
/**
* {@inheritDoc}
*/
@Override
public boolean isWithinScope(Entry entry) {
assert debugEnter(CLASS_NAME, "isWithinScope");
if (isDNWithinScope(entry.getDN())) {
try {
return filter.matchesEntry(entry);
} catch (DirectoryException e) {
// TODO: need to decide what to do with the exception here. It's
// probably safe to ignore, but we could log it perhaps.
return false;
}
} else {
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public StringBuilder toString(StringBuilder builder) {
assert debugEnter(CLASS_NAME, "toString");
boolean isFirstElement = true;
// Output the optional base DN.
builder.append("{");
if (relativeBaseDN != null && !relativeBaseDN.isNullDN()) {
builder.append(" relativeBase ");
StaticUtils.toRFC3641StringValue(builder, relativeBaseDN.toString());
isFirstElement = false;
}
// Output the optional specific exclusions.
Iterable