mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

ludovicp
30.59.2010 66680d3613957ad09437fc8b64885a0ad87f9e53
Extend RFC3672 subtreeSpecification to allow OpenDS specific RelativeSubtreeSpec and AbsoluteSubtreeSpec.
1 files added
10 files modified
675 ■■■■ changed files
opends/resource/config/config.ldif 16 ●●●●● patch | view | raw | blame | history
opends/src/messages/messages/schema.properties 6 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/SubtreeSpecification.java 26 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/AbsoluteSubtreeSpecification.java 17 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/RelativeSubtreeSpecification.java 17 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/SimpleSubtreeSpecification.java 19 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/SubentryManager.java 11 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/schema/SchemaConstants.java 96 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/schema/SubtreeSpecificationSyntax.java 320 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/types/SubEntry.java 65 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/core/SubentryManagerTestCase.java 82 ●●●●● patch | view | raw | blame | history
opends/resource/config/config.ldif
@@ -1982,13 +1982,6 @@
objectClass: ds-cfg-branch
cn: Syntaxes
dn: cn=Absolute Subtree Specification,cn=Syntaxes,cn=config
objectClass: top
objectClass: ds-cfg-attribute-syntax
cn: Absolute Subtree Specification
ds-cfg-java-class: org.opends.server.schema.AbsoluteSubtreeSpecificationSyntax
ds-cfg-enabled: true
dn: cn=Sun-defined Access Control Information,cn=Syntaxes,cn=config
objectClass: top
objectClass: ds-cfg-attribute-syntax
@@ -2252,13 +2245,6 @@
ds-cfg-java-class: org.opends.server.schema.ProtocolInformationSyntax
ds-cfg-enabled: true
dn: cn=Relative Subtree Specification,cn=Syntaxes,cn=config
objectClass: top
objectClass: ds-cfg-attribute-syntax
cn: Relative Subtree Specification
ds-cfg-java-class: org.opends.server.schema.RelativeSubtreeSpecificationSyntax
ds-cfg-enabled: true
dn: cn=Substring Assertion,cn=Syntaxes,cn=config
objectClass: top
objectClass: ds-cfg-attribute-syntax
@@ -2270,7 +2256,7 @@
objectClass: top
objectClass: ds-cfg-attribute-syntax
cn: Subtree Specification
ds-cfg-java-class: org.opends.server.schema.RFC3672SubtreeSpecificationSyntax
ds-cfg-java-class: org.opends.server.schema.SubtreeSpecificationSyntax
ds-cfg-enabled: true
dn: cn=Supported Algorithm,cn=Syntaxes,cn=config
opends/src/messages/messages/schema.properties
@@ -20,7 +20,7 @@
#
# CDDL HEADER END
#
#      Copyright 2006-2009 Sun Microsystems, Inc.
#      Copyright 2006-2010 Sun Microsystems, Inc.
@@ -881,6 +881,8 @@
SEVERE_WARN_ATTR_SYNTAX_ATTRTYPE_INVALID_SUPERIOR_USAGE_268=The definition \
 for attribute type %s is invalid because its attribute usage %s is not the \
 same as the usage for its superior type %s
MILD_ERR_ATTR_SYNTAX_SUBTREE_SPECIFICATION_INVALID_269=The provided \
 value "%s" could not be parsed as a valid subtree specification
SEVERE_WARN_ATTR_SYNTAX_ATTRTYPE_NONCOLLECTIVE_FROM_COLLECTIVE_270=The \
 definition for attribute type %s is invalid because it is not defined as a \
 collective type but the superior type %s is collective
@@ -1023,4 +1025,4 @@
  conflicting  value "%d" for m(Minute) specification
MILD_WARN_ATTR_DUPLICATE_HOUR_ASSERTION_FORMAT_316=The provided \
  value "%s" could not be parsed as a valid assertion value because there is  \
  conflicting  value "%d" for h(Hour) specification
  conflicting  value "%d" for h(Hour) specification
opends/src/server/org/opends/server/api/SubtreeSpecification.java
@@ -22,12 +22,13 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.api;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
@@ -53,6 +54,16 @@
  /**
   * Get the absolute base DN of the subtree specification.
   *
   * @return Returns the absolute base DN of the subtree
   *         specification.
   */
  public abstract DN getBaseDN();
  /**
   * Determine if an entry is within the scope of the subtree
   * specification.
   *
@@ -66,6 +77,19 @@
  /**
   * Determine if the specified DN is within the scope of the subtree
   * specification.
   *
   * @param dn  The distinguished name.
   * @return Returns <code>true</code> if the DN is within the scope
   *         of the subtree specification, or <code>false</code>
   *         otherwise.
   */
  public abstract boolean isDNWithinScope(DN dn);
  /**
   * Indicates whether the provided object is logically equal to this
   * subtree specification object.
   *
opends/src/server/org/opends/server/core/AbsoluteSubtreeSpecification.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.core;
import org.opends.messages.Message;
@@ -278,13 +278,16 @@
  public boolean isWithinScope(Entry entry) {
    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;
      if (filter != null) {
        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;
        }
      }
      return true;
    } else {
      return false;
    }
opends/src/server/org/opends/server/core/RelativeSubtreeSpecification.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.core;
import org.opends.messages.Message;
@@ -287,13 +287,16 @@
  public boolean isWithinScope(Entry entry) {
    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;
      if (filter != null) {
        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;
        }
      }
      return true;
    } else {
      return false;
    }
opends/src/server/org/opends/server/core/SimpleSubtreeSpecification.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.core;
@@ -404,16 +404,9 @@
  }
  /**
   * Determine if the specified DN is within the scope of the subtree
   * specification.
   *
   * @param dn
   *          The distringuished name.
   * @return Returns <code>true</code> if the DN is within the scope
   *         of the subtree specification, or <code>false</code>
   *         otherwise.
   * {@inheritDoc}
   */
  protected final boolean isDNWithinScope(DN dn) {
  public final boolean isDNWithinScope(DN dn) {
    if (!dn.isDescendantOf(baseDN)) {
      return false;
@@ -460,11 +453,9 @@
  }
  /**
   * Get the absolute base DN of the subtree specification.
   *
   * @return Returns the absolute base DN of the subtree specification.
   * {@inheritDoc}
   */
  protected final DN getBaseDN() {
  public final DN getBaseDN() {
    return baseDN;
  }
opends/src/server/org/opends/server/core/SubentryManager.java
@@ -28,6 +28,7 @@
import org.opends.server.api.SubtreeSpecification;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -206,7 +207,7 @@
  private void addSubEntry(Entry entry) throws DirectoryException
  {
    SubEntry subEntry = new SubEntry(entry);
    RFC3672SubtreeSpecification subSpec =
    SubtreeSpecification subSpec =
            subEntry.getSubTreeSpecification();
    DN subDN = subSpec.getBaseDN();
    List<SubEntry> subList = null;
@@ -488,7 +489,7 @@
        {
          for (SubEntry subEntry : subList)
          {
            RFC3672SubtreeSpecification subSpec =
            SubtreeSpecification subSpec =
                    subEntry.getSubTreeSpecification();
            if (subSpec.isDNWithinScope(dn))
            {
@@ -534,7 +535,7 @@
        {
          for (SubEntry subEntry : subList)
          {
            RFC3672SubtreeSpecification subSpec =
            SubtreeSpecification subSpec =
                    subEntry.getSubTreeSpecification();
            if (subSpec.isWithinScope(entry))
            {
@@ -580,7 +581,7 @@
        {
          for (SubEntry subEntry : subList)
          {
            RFC3672SubtreeSpecification subSpec =
            SubtreeSpecification subSpec =
                    subEntry.getSubTreeSpecification();
            if (subSpec.isDNWithinScope(dn))
            {
@@ -626,7 +627,7 @@
        {
          for (SubEntry subEntry : subList)
          {
            RFC3672SubtreeSpecification subSpec =
            SubtreeSpecification subSpec =
                    subEntry.getSubTreeSpecification();
            if (subSpec.isWithinScope(entry))
            {
opends/src/server/org/opends/server/schema/SchemaConstants.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2009 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.schema;
@@ -801,30 +801,6 @@
  /**
   * The OID for the absolute subtree specification attribute syntax.
   */
  public static final String SYNTAX_ABSOLUTE_SUBTREE_SPECIFICATION_OID =
       OID_OPENDS_SERVER_ATTRIBUTE_SYNTAX_BASE + ".3";
  /**
   * The description for the absolute subtree specification attribute syntax.
   */
  public static final String SYNTAX_ABSOLUTE_SUBTREE_SPECIFICATION_DESCRIPTION =
    "Absolute Subtree Specification";
  /**
   * The name for the absolute subtree specification attribute syntax.
   */
  public static final String SYNTAX_ABSOLUTE_SUBTREE_SPECIFICATION_NAME =
    "ds-absolute-subtree-specification";
   /**
    * The OID for the aci attribute syntax.
    */
@@ -1668,26 +1644,26 @@
  /**
   * The OID for the relative subtree specification attribute syntax.
   * The OID for the subtree specification attribute syntax.
   */
  public static final String SYNTAX_RELATIVE_SUBTREE_SPECIFICATION_OID =
       OID_OPENDS_SERVER_ATTRIBUTE_SYNTAX_BASE + ".2";
  public static final String SYNTAX_SUBTREE_SPECIFICATION_OID =
    "1.3.6.1.4.1.1466.115.121.1.45";
  /**
   * The description for the relative subtree specification attribute syntax.
   * The description for the subtree specification attribute syntax.
   */
  public static final String SYNTAX_RELATIVE_SUBTREE_SPECIFICATION_DESCRIPTION =
    "Relative Subtree Specification";
  public static final String SYNTAX_SUBTREE_SPECIFICATION_DESCRIPTION =
    "Subtree Specification";
  /**
   * The name for the relative subtree specification attribute syntax.
   * The name for the subtree specification attribute syntax.
   */
  public static final String SYNTAX_RELATIVE_SUBTREE_SPECIFICATION_NAME =
    "ds-relative-subtree-specification";
  public static final String SYNTAX_SUBTREE_SPECIFICATION_NAME =
    "SubtreeSpecification";
@@ -1695,7 +1671,7 @@
   * The OID for the RFC3672 subtree specification attribute syntax.
   */
  public static final String SYNTAX_RFC3672_SUBTREE_SPECIFICATION_OID =
    "1.3.6.1.4.1.1466.115.121.1.45";
    SYNTAX_SUBTREE_SPECIFICATION_OID;
@@ -1711,7 +1687,55 @@
   * The name for the RFC3672 subtree specification attribute syntax.
   */
  public static final String SYNTAX_RFC3672_SUBTREE_SPECIFICATION_NAME =
    "SubtreeSpecification";
    SYNTAX_SUBTREE_SPECIFICATION_NAME;
  /**
   * The OID for the absolute subtree specification attribute syntax.
   */
  public static final String SYNTAX_ABSOLUTE_SUBTREE_SPECIFICATION_OID =
       SYNTAX_SUBTREE_SPECIFICATION_OID;
  /**
   * The description for the absolute subtree specification attribute syntax.
   */
  public static final String SYNTAX_ABSOLUTE_SUBTREE_SPECIFICATION_DESCRIPTION =
    "Absolute Subtree Specification";
  /**
   * The name for the absolute subtree specification attribute syntax.
   */
  public static final String SYNTAX_ABSOLUTE_SUBTREE_SPECIFICATION_NAME =
    SYNTAX_SUBTREE_SPECIFICATION_NAME;
  /**
   * The OID for the relative subtree specification attribute syntax.
   */
  public static final String SYNTAX_RELATIVE_SUBTREE_SPECIFICATION_OID =
       SYNTAX_SUBTREE_SPECIFICATION_OID;
  /**
   * The description for the relative subtree specification attribute syntax.
   */
  public static final String SYNTAX_RELATIVE_SUBTREE_SPECIFICATION_DESCRIPTION =
    "Relative Subtree Specification";
  /**
   * The name for the relative subtree specification attribute syntax.
   */
  public static final String SYNTAX_RELATIVE_SUBTREE_SPECIFICATION_NAME =
    SYNTAX_SUBTREE_SPECIFICATION_NAME;
opends/src/server/org/opends/server/schema/SubtreeSpecificationSyntax.java
New file
@@ -0,0 +1,320 @@
/*
 * 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
 *
 *
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.schema;
import org.opends.messages.Message;
import static org.opends.server.loggers.debug.DebugLogger.*;
import org.opends.server.loggers.debug.DebugTracer;
import static org.opends.server.loggers.ErrorLogger.logError;
import static org.opends.messages.SchemaMessages.*;
import org.opends.messages.MessageBuilder;
import static org.opends.server.schema.SchemaConstants.*;
import org.opends.server.admin.std.server.AttributeSyntaxCfg;
import org.opends.server.api.ApproximateMatchingRule;
import org.opends.server.api.AttributeSyntax;
import org.opends.server.api.AttributeValueDecoder;
import org.opends.server.api.EqualityMatchingRule;
import org.opends.server.api.OrderingMatchingRule;
import org.opends.server.api.SubstringMatchingRule;
import org.opends.server.api.SubtreeSpecification;
import org.opends.server.config.ConfigException;
import org.opends.server.core.AbsoluteSubtreeSpecification;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.RFC3672SubtreeSpecification;
import org.opends.server.core.RelativeSubtreeSpecification;
import org.opends.server.types.*;
/**
 * This class defines the subtree specification attribute syntax,
 * which is used to specify the scope of sub-entries (RFC 3672).
 */
public final class SubtreeSpecificationSyntax
       extends AttributeSyntax<AttributeSyntaxCfg>
{
  /**
   * The tracer object for the debug logger.
   */
  private static final DebugTracer TRACER = getTracer();
  // The default equality matching rule for this syntax.
  private EqualityMatchingRule defaultEqualityMatchingRule;
  // The default ordering matching rule for this syntax.
  private OrderingMatchingRule defaultOrderingMatchingRule;
  // The default substring matching rule for this syntax.
  private SubstringMatchingRule defaultSubstringMatchingRule;
  /**
   * Create a new attribute value decoder with the specified root DN.
   *
   * @param rootDN
   *          The root DN for all decoded subtree specifications.
   * @return The attribute value decoder.
   */
  public static AttributeValueDecoder<SubtreeSpecification>
      createAttributeValueDecoder(DN rootDN) {
    return new Decoder(rootDN);
  }
  /**
   * Internal class implementing an attribute value decoder.
   */
  private static class Decoder implements
      AttributeValueDecoder<SubtreeSpecification> {
    // The root DN for all decoded relative subtree specifications.
    private DN rootDN;
    /**
     * Create a new decoder with the specified root DN.
     *
     * @param rootDN
     *          The root DN for all decoded relative subtree
     *          specifications.
     */
    public Decoder(DN rootDN) {
      this.rootDN = rootDN;
    }
    /**
     * {@inheritDoc}
     */
    public SubtreeSpecification decode(AttributeValue value)
        throws DirectoryException {
      // Try parsing the value with every subtree spec known.
      SubtreeSpecification subTreeSpec = null;
      String specString = value.toString();
      try {
        subTreeSpec = RFC3672SubtreeSpecification.valueOf(
                rootDN, specString);
        return subTreeSpec;
      } catch (DirectoryException de) {}
      try {
        subTreeSpec = RelativeSubtreeSpecification.valueOf(
                rootDN, specString);
        return subTreeSpec;
      } catch (DirectoryException de) {}
      try {
        subTreeSpec = AbsoluteSubtreeSpecification.valueOf(
                specString);
        return subTreeSpec;
      } catch (DirectoryException de) {}
      if (subTreeSpec == null) {
        Message message =
          ERR_ATTR_SYNTAX_SUBTREE_SPECIFICATION_INVALID.get(
            specString);
        throw new DirectoryException(
                ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
      }
      return subTreeSpec;
    }
  }
  /**
   * Creates a new instance of this syntax. Note that the only thing
   * that should be done here is to invoke the default constructor for
   * the superclass. All initialization should be performed in the
   * <CODE>initializeSyntax</CODE> method.
   */
  public SubtreeSpecificationSyntax() {
    // No implementation required.
  }
  /**
   * {@inheritDoc}
   */
  public void initializeSyntax(AttributeSyntaxCfg configuration)
      throws ConfigException {
    defaultEqualityMatchingRule = DirectoryServer
        .getEqualityMatchingRule(EMR_OCTET_STRING_OID);
    if (defaultEqualityMatchingRule == null) {
      logError(ERR_ATTR_SYNTAX_UNKNOWN_EQUALITY_MATCHING_RULE.get(
          EMR_OCTET_STRING_OID, SYNTAX_SUBTREE_SPECIFICATION_NAME));
    }
    defaultOrderingMatchingRule = DirectoryServer
        .getOrderingMatchingRule(OMR_OCTET_STRING_OID);
    if (defaultOrderingMatchingRule == null) {
      logError(ERR_ATTR_SYNTAX_UNKNOWN_ORDERING_MATCHING_RULE.get(
          OMR_OCTET_STRING_OID, SYNTAX_SUBTREE_SPECIFICATION_NAME));
    }
    defaultSubstringMatchingRule = DirectoryServer
        .getSubstringMatchingRule(SMR_OCTET_STRING_OID);
    if (defaultSubstringMatchingRule == null) {
      logError(ERR_ATTR_SYNTAX_UNKNOWN_SUBSTRING_MATCHING_RULE.get(
          SMR_OCTET_STRING_OID, SYNTAX_SUBTREE_SPECIFICATION_NAME));
    }
  }
  /**
   * Retrieves the common name for this attribute syntax.
   *
   * @return The common name for this attribute syntax.
   */
  public String getSyntaxName() {
    return SYNTAX_SUBTREE_SPECIFICATION_NAME;
  }
  /**
   * Retrieves the OID for this attribute syntax.
   *
   * @return The OID for this attribute syntax.
   */
  public String getOID() {
    return SYNTAX_SUBTREE_SPECIFICATION_OID;
  }
  /**
   * Retrieves a description for this attribute syntax.
   *
   * @return A description for this attribute syntax.
   */
  public String getDescription() {
    return SYNTAX_SUBTREE_SPECIFICATION_DESCRIPTION;
  }
  /**
   * Retrieves the default equality matching rule that will be used for
   * attributes with this syntax.
   *
   * @return The default equality matching rule that will be used for
   *         attributes with this syntax, or <CODE>null</CODE> if
   *         equality matches will not be allowed for this type by
   *         default.
   */
  public EqualityMatchingRule getEqualityMatchingRule() {
    return defaultEqualityMatchingRule;
  }
  /**
   * Retrieves the default ordering matching rule that will be used for
   * attributes with this syntax.
   *
   * @return The default ordering matching rule that will be used for
   *         attributes with this syntax, or <CODE>null</CODE> if
   *         ordering matches will not be allowed for this type by
   *         default.
   */
  public OrderingMatchingRule getOrderingMatchingRule() {
    return defaultOrderingMatchingRule;
  }
  /**
   * Retrieves the default substring matching rule that will be used for
   * attributes with this syntax.
   *
   * @return The default substring matching rule that will be used for
   *         attributes with this syntax, or <CODE>null</CODE> if
   *         substring matches will not be allowed for this type by
   *         default.
   */
  public SubstringMatchingRule getSubstringMatchingRule() {
    return defaultSubstringMatchingRule;
  }
  /**
   * Retrieves the default approximate matching rule that will be used
   * for attributes with this syntax.
   *
   * @return The default approximate matching rule that will be used for
   *         attributes with this syntax, or <CODE>null</CODE> if
   *         approximate matches will not be allowed for this type by
   *         default.
   */
  public ApproximateMatchingRule getApproximateMatchingRule() {
    // There is no approximate matching rule by default.
    return null;
  }
  /**
   * Indicates whether the provided value is acceptable for use in an
   * attribute with this syntax. If it is not, then the reason may be
   * appended to the provided buffer.
   *
   * @param value
   *          The value for which to make the determination.
   * @param invalidReason
   *          The buffer to which the invalid reason should be appended.
   * @return <CODE>true</CODE> if the provided value is acceptable for
   *         use with this syntax, or <CODE>false</CODE> if not.
   */
  public boolean valueIsAcceptable(ByteSequence value,
                                   MessageBuilder invalidReason) {
    // Use the subtree specification code to make this determination.
    // Try parsing the value with every subtree spec known.
    SubtreeSpecification subTreeSpec = null;
    String specString = value.toString();
    try {
      subTreeSpec = RFC3672SubtreeSpecification.valueOf(
              DN.nullDN(), specString);
      return true;
    } catch (DirectoryException de) {}
    try {
      subTreeSpec = RelativeSubtreeSpecification.valueOf(
              DN.nullDN(), specString);
      return true;
    } catch (DirectoryException de) {}
    try {
      subTreeSpec = AbsoluteSubtreeSpecification.valueOf(
              specString);
      return true;
    } catch (DirectoryException de) {}
    if (subTreeSpec == null) {
      Message message =
        ERR_ATTR_SYNTAX_SUBTREE_SPECIFICATION_INVALID.get(
          specString);
      invalidReason.append(message);
    }
    return false;
  }
 /**
   * {@inheritDoc}
   */
  public boolean isBinary()
  {
    return false;
  }
}
opends/src/server/org/opends/server/types/SubEntry.java
@@ -27,6 +27,10 @@
package org.opends.server.types;
import org.opends.messages.Message;
import org.opends.server.core.AbsoluteSubtreeSpecification;
import org.opends.server.core.RelativeSubtreeSpecification;
import org.opends.server.api.SubtreeSpecification;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;
@@ -37,6 +41,7 @@
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.messages.SchemaMessages.*;
/**
 * This class represents RFC 3672 subentries and RFC 3671
@@ -113,7 +118,7 @@
  private Entry entry;
  // Subtree specification.
  private RFC3672SubtreeSpecification subTreeSpec;
  private SubtreeSpecification subTreeSpec;
  // Collective subentry flag.
  private boolean isCollective = false;
@@ -138,6 +143,8 @@
    // Process subtree specification.
    this.subTreeSpec = null;
    String specString = null;
    boolean isValidSpec = true;
    AttributeType specAttrType = DirectoryServer.getAttributeType(
            ATTR_SUBTREE_SPEC_LC, true);
    List<Attribute> specAttrList =
@@ -148,8 +155,46 @@
      {
        for (AttributeValue value : attr)
        {
          this.subTreeSpec = RFC3672SubtreeSpecification.valueOf(
                  entry.getDN().getParent(), value.toString());
          // Try parsing the value with every subtree spec known.
          specString = value.toString();
          try
          {
            this.subTreeSpec = RFC3672SubtreeSpecification.valueOf(
                    entry.getDN().getParent(), specString);
            isValidSpec = true;
          }
          catch (DirectoryException de)
          {
            isValidSpec = false;
          }
          if (this.subTreeSpec != null)
          {
            break;
          }
          try
          {
            this.subTreeSpec = RelativeSubtreeSpecification.valueOf(
                    entry.getDN().getParent(), specString);
            isValidSpec = true;
          }
          catch (DirectoryException de)
          {
            isValidSpec = false;
          }
          if (this.subTreeSpec != null)
          {
            break;
          }
          try
          {
            this.subTreeSpec = AbsoluteSubtreeSpecification.valueOf(
                    specString);
            isValidSpec = true;
          }
          catch (DirectoryException de)
          {
            isValidSpec = false;
          }
          break;
        }
        if (this.subTreeSpec != null)
@@ -158,6 +203,18 @@
        }
      }
    }
    // Check that the subtree spec is flaged as valid. If it is not
    // that means all parsers have failed and it is ivalid syntax.
    if (!isValidSpec)
    {
      Message message =
        ERR_ATTR_SYNTAX_SUBTREE_SPECIFICATION_INVALID.get(
          specString);
      throw new DirectoryException(
              ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
    }
    // Subentry has to to have a subtree specification.
    if (this.subTreeSpec == null)
    {
@@ -258,7 +315,7 @@
   * Getter for subentry subtree specification.
   * @return subtree specification for this subentry.
   */
  public RFC3672SubtreeSpecification getSubTreeSpecification()
  public SubtreeSpecification getSubTreeSpecification()
  {
    return this.subTreeSpec;
  }
opends/tests/unit-tests-testng/src/server/org/opends/server/core/SubentryManagerTestCase.java
@@ -27,6 +27,7 @@
package org.opends.server.core;
import org.opends.server.api.SubtreeSpecification;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
@@ -449,6 +450,87 @@
          DN.decode("uid=rogasawara," + OLDBASE + "," + SUFFIX)).isEmpty());
  }
  @Test
  public void testExtendedSubtreeSpecification() throws Exception
  {
    // This one should have been added during test setup so just
    // do a quick check here to make sure it is available there.
    assertNotNull(DirectoryServer.getEntry(ldapSubentry.getDN()));
    // RFC3672 Spec test subentry.
    List<SubEntry> rfc3672SubList =
            DirectoryServer.getSubentryManager().getSubentries();
    for (SubEntry subentry : rfc3672SubList)
    {
      if (subentry.getDN().equals(ldapSubentry.getDN()))
      {
        SubtreeSpecification spec = subentry.getSubTreeSpecification();
        assertTrue(spec instanceof RFC3672SubtreeSpecification);
      }
    }
    InternalClientConnection connection =
         InternalClientConnection.getRootConnection();
    // Add Relative Spec test subentry.
    Entry relativeSubentry = TestCaseUtils.makeEntry(
         "dn: cn=Relative Subentry," + SUFFIX,
         "objectClass: top",
         "objectclass: subentry",
         "subtreeSpecification: {relativeBase \"ou=Test SubEntry Manager\"}",
         "cn: Subentry");
    AddOperation addOperation =
         connection.processAdd(relativeSubentry.getDN(),
                               relativeSubentry.getObjectClasses(),
                               relativeSubentry.getUserAttributes(),
                               relativeSubentry.getOperationalAttributes());
    assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
    assertNotNull(DirectoryServer.getEntry(relativeSubentry.getDN()));
    List<SubEntry> relativeSubList =
            DirectoryServer.getSubentryManager().getSubentries();
    for (SubEntry subentry : relativeSubList)
    {
      if (subentry.getDN().equals(relativeSubentry.getDN()))
      {
        SubtreeSpecification spec = subentry.getSubTreeSpecification();
        assertTrue(spec instanceof RelativeSubtreeSpecification);
      }
    }
    // Remove Relative Spec test subentry.
    TestCaseUtils.deleteEntry(relativeSubentry.getDN());
    // Add Absolute Spec test subentry.
    Entry absoluteSubentry = TestCaseUtils.makeEntry(
         "dn: cn=Absolute Subentry," + SUFFIX,
         "objectClass: top",
         "objectclass: subentry",
         "subtreeSpecification: {absoluteBase \"ou=Test SubEntry Manager\"}",
         "cn: Subentry");
    addOperation =
         connection.processAdd(absoluteSubentry.getDN(),
                               absoluteSubentry.getObjectClasses(),
                               absoluteSubentry.getUserAttributes(),
                               absoluteSubentry.getOperationalAttributes());
    assertEquals(addOperation.getResultCode(), ResultCode.SUCCESS);
    assertNotNull(DirectoryServer.getEntry(absoluteSubentry.getDN()));
    List<SubEntry> absoluteSubList =
            DirectoryServer.getSubentryManager().getSubentries();
    for (SubEntry subentry : absoluteSubList)
    {
      if (subentry.getDN().equals(absoluteSubentry.getDN()))
      {
        SubtreeSpecification spec = subentry.getSubTreeSpecification();
        assertTrue(spec instanceof AbsoluteSubtreeSpecification);
      }
    }
    // Remove Absolute Spec test subentry.
    TestCaseUtils.deleteEntry(absoluteSubentry.getDN());
  }
  private void addTestEntries() throws Exception
  {
    InternalClientConnection connection =