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

matthew_swift
27.50.2007 ace2bd4146fe55154c0d716f20d9cbff3a2297d3
Improvements to aggregation support and foundation work for expressing arbitrary constraints within components.

This change adds support for defining arbitrary conditions which can be used to test properties and their values. Conditions can be used within aggregations to define 1) when a referenced managed object needs enabling and 2) when it is enabled. For example, the LDAP connection handler requires that its key manager provider and trust manager provider are enabled when it is enable and when either SSL or StartTLS are enabled.

Conditions are also intended for use within the existing constraint/dependency support. For example, it should be possible to indicate that a property "min" is always less than or equal to a property "max", or that when "use-ssl" is set to true, any required SSL configuration related properties are also defined. This will be implemented in a subsequent change (this change just focuses on the work required to resolve issue 1449).

This change adds support for the following conditions:

* logical "not"
* logical "and"
* logical "or"
* logical "implies"
* contains - determines if a property contains a particular value
* is-present - determines if a property has any values (incl. defaults)

More will be added as required.
9 files added
26 files modified
2167 ■■■■ changed files
opends/resource/admin/admin.xsd 155 ●●●● patch | view | raw | blame | history
opends/resource/admin/conditions.xsl 96 ●●●●● patch | view | raw | blame | history
opends/resource/admin/metaMO.xsl 4 ●●●● patch | view | raw | blame | history
opends/resource/admin/property-types/aggregation.xsl 35 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/CramMD5SASLMechanismHandlerConfiguration.xml 8 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/DigestMD5SASLMechanismHandlerConfiguration.xml 8 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/ExternalSASLMechanismHandlerConfiguration.xml 8 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/GSSAPISASLMechanismHandlerConfiguration.xml 8 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml 4 ●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/JMXConnectionHandlerConfiguration.xml 37 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/LDAPConnectionHandlerConfiguration.xml 123 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/Package.xml 60 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/PasswordModifyExtendedOperationHandlerConfiguration.xml 8 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyConfiguration.xml 20 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyImportPluginConfiguration.xml 16 ●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/PlainSASLMechanismHandlerConfiguration.xml 8 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/admin.properties 3 ●●●● patch | view | raw | blame | history
opends/src/messages/messages/dsconfig.properties 3 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/AggregationPropertyDefinition.java 334 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/Configuration.java 13 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/condition/ANDCondition.java 112 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/condition/Condition.java 94 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/condition/Conditions.java 237 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/condition/ContainsValueCondition.java 197 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/condition/IsPresentCondition.java 104 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/condition/NOTCondition.java 97 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/condition/ORCondition.java 112 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/admin/condition/package-info.java 36 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/CreateSubCommandHandler.java 98 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/dsconfig/SetPropSubCommandHandler.java 106 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java 2 ●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java 2 ●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/AggregationTest.java 7 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/DomainFakeCfg.java 6 ●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ReplServerFakeConfiguration.java 6 ●●●● patch | view | raw | blame | history
opends/resource/admin/admin.xsd
@@ -1036,49 +1036,37 @@
        </xsd:annotation>
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="source-enabled-property-name"
              minOccurs="0" maxOccurs="unbounded">
              <xsd:annotation>
                <xsd:documentation>
                  The optional boolean "enabled" property in the
                  aggregating managed object. When this property is
                  true, the "target-enabled-property-name" in the
                  aggregated managed objects must also be true. The
                  "target-enabled-property-name" attribute must be
                  specified when this attribute is defined.
                </xsd:documentation>
              </xsd:annotation>
              <xsd:complexType>
                <xsd:attribute name="name" type="tns:name-type"
                  use="required">
                  <xsd:annotation>
                    <xsd:documentation>
                      The name of the source property.
                    </xsd:documentation>
                  </xsd:annotation>
                </xsd:attribute>
              </xsd:complexType>
            </xsd:element>
            <xsd:element name="target-enabled-property-name"
            <xsd:element name="target-needs-enabling-condition"
              minOccurs="0">
              <xsd:annotation>
                <xsd:documentation>
                  The optional boolean "enabled" property in the
                  aggregated managed objects. This property must not be
                  false while the aggregated managed object is
                  referenced. This attribute must be defined when the
                  "source-enabled-property-name" attribute is specified.
                  A condition which indicates whether or not referenced
                  managed objects must be enabled. The default behavior
                  is that all referenced managed objects must be
                  enabled.
                </xsd:documentation>
              </xsd:annotation>
              <xsd:complexType>
                <xsd:attribute name="name" type="tns:name-type"
                  use="required">
                <xsd:sequence>
                  <xsd:group ref="tns:condition-group" />
                </xsd:sequence>
              </xsd:complexType>
            </xsd:element>
            <xsd:element name="target-is-enabled-condition"
              minOccurs="0">
                  <xsd:annotation>
                    <xsd:documentation>
                      The name of the target property.
                  A condition which indicates whether or not referenced
                  managed objects are enabled. Managed objects are
                  assumed to be enabled by default.
                    </xsd:documentation>
                  </xsd:annotation>
                </xsd:attribute>
              <xsd:complexType>
                <xsd:sequence>
                  <xsd:sequence>
                    <xsd:group ref="tns:condition-group" />
                  </xsd:sequence>
                </xsd:sequence>
              </xsd:complexType>
            </xsd:element>
          </xsd:sequence>
@@ -1894,4 +1882,105 @@
      </xsd:attribute>
    </xsd:complexType>
  </xsd:element>
  <xsd:group name="condition-group">
    <xsd:choice>
      <xsd:element name="not">
        <xsd:annotation>
          <xsd:documentation>
            A condition which evaluates to true if the sub-condition is
            false, or false if the sub-condition is true.
          </xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
          <xsd:sequence>
            <xsd:group ref="tns:condition-group" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="and">
        <xsd:annotation>
          <xsd:documentation>
            A condition which evaluates to true if and only if all of
            its sub-conditions are true.
          </xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
          <xsd:sequence>
            <xsd:group ref="tns:condition-group" maxOccurs="unbounded" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="or">
        <xsd:annotation>
          <xsd:documentation>
            A condition which evaluates to false if and only if none of
            its sub-conditions are true.
          </xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
          <xsd:sequence>
            <xsd:group ref="tns:condition-group" maxOccurs="unbounded" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="implies">
        <xsd:annotation>
          <xsd:documentation>
            Creates a condition which evaluates to false if and only if
            the first sub-condition evaluates to true and the second
            sub-condition evaluates to false. This can be used to
            represent if-then relationships.
          </xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
          <xsd:sequence>
            <xsd:group ref="tns:condition-group" />
            <xsd:group ref="tns:condition-group" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="contains">
        <xsd:annotation>
          <xsd:documentation>
            A condition which evaluates to true if and only if a
            property contains a particular value.
          </xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
          <xsd:attribute name="property" type="tns:name-type"
            use="required">
            <xsd:annotation>
              <xsd:documentation>
                The name of the property to be tested.
              </xsd:documentation>
            </xsd:annotation>
          </xsd:attribute>
          <xsd:attribute name="value" type="xsd:string"
            use="required">
            <xsd:annotation>
              <xsd:documentation>The property value.</xsd:documentation>
            </xsd:annotation>
          </xsd:attribute>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="is-present">
        <xsd:annotation>
          <xsd:documentation>
            Creates a condition which evaluates to true if and only if a
            particular property has any values specified.
          </xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
          <xsd:attribute name="property" type="tns:name-type"
            use="required">
            <xsd:annotation>
              <xsd:documentation>
                The name of the property to be tested.
              </xsd:documentation>
            </xsd:annotation>
          </xsd:attribute>
        </xsd:complexType>
      </xsd:element>
    </xsd:choice>
  </xsd:group>
</xsd:schema>
opends/resource/admin/conditions.xsl
New file
@@ -0,0 +1,96 @@
<!--
  ! 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 2007 Sun Microsystems, Inc.
  ! -->
<xsl:stylesheet version="1.0" xmlns:adm="http://www.opends.org/admin"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!--
    Rules for compiling conditions from their XML definition.
  -->
  <!--
    and condition
  -->
  <xsl:template match="adm:and" mode="compile-condition">
    <xsl:value-of select="'Conditions.and('" />
    <xsl:for-each select="*">
      <xsl:apply-templates select="." mode="compile-condition" />
      <xsl:if test="position() != last()">
        <xsl:value-of select="', '" />
      </xsl:if>
    </xsl:for-each>
    <xsl:value-of select="')'" />
  </xsl:template>
  <!--
    or condition
  -->
  <xsl:template match="adm:or" mode="compile-condition">
    <xsl:value-of select="'Conditions.or('" />
    <xsl:for-each select="*">
      <xsl:apply-templates select="." mode="compile-condition" />
      <xsl:if test="position() != last()">
        <xsl:value-of select="', '" />
      </xsl:if>
    </xsl:for-each>
    <xsl:value-of select="')'" />
  </xsl:template>
  <!--
    not condition
  -->
  <xsl:template match="adm:not" mode="compile-condition">
    <xsl:value-of select="'Conditions.not('" />
    <xsl:apply-templates select="*[1]" mode="compile-condition" />
    <xsl:value-of select="')'" />
  </xsl:template>
  <!--
    implies condition
  -->
  <xsl:template match="adm:implies" mode="compile-condition">
    <xsl:value-of select="'Conditions.implies('" />
    <xsl:apply-templates select="*[1]" mode="compile-condition" />
    <xsl:value-of select="', '" />
    <xsl:apply-templates select="*[2]" mode="compile-condition" />
    <xsl:value-of select="')'" />
  </xsl:template>
  <!--
    contains condition
  -->
  <xsl:template match="adm:contains" mode="compile-condition">
    <xsl:value-of
      select="concat('Conditions.contains(&quot;', @property, '&quot;, &quot;', @value, '&quot;)')" />
  </xsl:template>
  <!--
    is-present condition
  -->
  <xsl:template match="adm:is-present" mode="compile-condition">
    <xsl:value-of
      select="concat('Conditions.isPresent(&quot;', @property, '&quot;)')" />
  </xsl:template>
</xsl:stylesheet>
opends/resource/admin/metaMO.xsl
@@ -580,7 +580,7 @@
                     '      return INSTANCE;&#xa;',
                     '    }&#xa;')" />
    <!--
      Property provider view.
      Server managed object getter.
    -->
    <xsl:text>&#xa;</xsl:text>
    <xsl:text>&#xa;</xsl:text>
@@ -589,7 +589,7 @@
      select="concat('    /**&#xa;',
                     '     * {@inheritDoc}&#xa;',
                     '     */&#xa;',
                     '    public PropertyProvider properties() {&#xa;',
                     '    public ServerManagedObject&lt;? extends ', $this-java-class,'Cfg&gt; managedObject() {&#xa;',
                     '      return impl;&#xa;',
                     '    }&#xa;')" />
    <!--
opends/resource/admin/property-types/aggregation.xsl
@@ -26,6 +26,7 @@
  ! -->
<xsl:stylesheet version="1.0" xmlns:adm="http://www.opends.org/admin"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:include href="../conditions.xsl" />
  <!-- 
    Templates for processing aggregation properties.
  -->
@@ -44,6 +45,12 @@
    <xsl:if test="../../@multi-valued = 'true'">
      <import>java.util.TreeSet</import>
    </xsl:if>
    <xsl:if test="adm:target-needs-enabling-condition">
      <import>org.opends.server.admin.condition.Conditions</import>
    </xsl:if>
    <xsl:if test="adm:target-is-enabled-condition">
      <import>org.opends.server.admin.condition.Conditions</import>
    </xsl:if>
    <import>
      org.opends.server.admin.AggregationPropertyDefinition
    </import>
@@ -79,30 +86,26 @@
          select="concat('No relation-name defined for aggregation property ', ../../@name)" />
      </xsl:message>
    </xsl:if>
    <xsl:if
      test="@source-enabled-property-name and not(@target-enabled-property-name)">
      <xsl:message terminate="yes">
        <xsl:value-of
          select="concat('source-enabled-property-name defined but target-enabled-property-name undefined in aggregation property ', ../../@name)" />
      </xsl:message>
    </xsl:if>
    <xsl:value-of
      select="concat('      builder.setParentPath(&quot;',
                     normalize-space(@parent-path), '&quot;);&#xa;')" />
    <xsl:value-of
      select="concat('      builder.setRelationDefinition(&quot;',
                     normalize-space(@relation-name), '&quot;);&#xa;')" />
    <xsl:for-each select="adm:source-enabled-property-name">
      <xsl:sort select="@name" />
    <xsl:if test="adm:target-needs-enabling-condition">
      <xsl:value-of
        select="concat('      builder.addSourceEnabledPropertyName(&quot;',
                       normalize-space(@name), '&quot;);&#xa;')" />
    </xsl:for-each>
    <xsl:if test="source-enabled-property-name"></xsl:if>
    <xsl:if test="adm:target-enabled-property-name">
        select="'      builder.setTargetNeedsEnablingCondition('" />
      <xsl:apply-templates
        select="adm:target-needs-enabling-condition/*"
        mode="compile-condition" />
      <xsl:value-of select="');&#xa;'" />
    </xsl:if>
    <xsl:if test="adm:target-is-enabled-condition">
      <xsl:value-of
        select="concat('      builder.setTargetEnabledPropertyName(&quot;',
                       normalize-space(adm:target-enabled-property-name/@name), '&quot;);&#xa;')" />
        select="'      builder.setTargetIsEnabledCondition('" />
      <xsl:apply-templates select="adm:target-is-enabled-condition/*"
        mode="compile-condition" />
      <xsl:value-of select="');&#xa;'" />
    </xsl:if>
  </xsl:template>
  <xsl:template match="adm:aggregation"
opends/src/admin/defn/org/opends/server/admin/std/CramMD5SASLMechanismHandlerConfiguration.xml
@@ -59,8 +59,12 @@
    <adm:syntax>
      <adm:aggregation relation-name="identity-mapper"
        parent-path="/">
        <adm:source-enabled-property-name name="enabled" />
        <adm:target-enabled-property-name name="enabled" />
        <adm:target-needs-enabling-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-needs-enabling-condition>
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
opends/src/admin/defn/org/opends/server/admin/std/DigestMD5SASLMechanismHandlerConfiguration.xml
@@ -87,8 +87,12 @@
    <adm:syntax>
      <adm:aggregation relation-name="identity-mapper"
        parent-path="/">
        <adm:source-enabled-property-name name="enabled" />
        <adm:target-enabled-property-name name="enabled" />
        <adm:target-needs-enabling-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-needs-enabling-condition>
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
opends/src/admin/defn/org/opends/server/admin/std/ExternalSASLMechanismHandlerConfiguration.xml
@@ -134,8 +134,12 @@
    <adm:syntax>
      <adm:aggregation relation-name="certificate-mapper"
        parent-path="/">
        <adm:source-enabled-property-name name="enabled" />
        <adm:target-enabled-property-name name="enabled" />
        <adm:target-needs-enabling-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-needs-enabling-condition>
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
opends/src/admin/defn/org/opends/server/admin/std/GSSAPISASLMechanismHandlerConfiguration.xml
@@ -173,8 +173,12 @@
    <adm:syntax>
      <adm:aggregation relation-name="identity-mapper"
        parent-path="/">
        <adm:source-enabled-property-name name="enabled" />
        <adm:target-enabled-property-name name="enabled" />
        <adm:target-needs-enabling-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-needs-enabling-condition>
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
@@ -335,7 +335,9 @@
    <adm:syntax>
      <adm:aggregation relation-name="identity-mapper"
        parent-path="/">
        <adm:target-enabled-property-name name="enabled" />
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
opends/src/admin/defn/org/opends/server/admin/std/JMXConnectionHandlerConfiguration.xml
@@ -54,5 +54,40 @@
  <adm:property-reference name="listen-port" />
  <adm:property-reference name="use-ssl" />
  <adm:property-reference name="ssl-cert-nickname" />
  <adm:property-reference name="key-manager-provider" />
  <adm:property name="key-manager-provider">
    <adm:synopsis>
      Specifies the name of the key manager that should be used
      with this <adm:user-friendly-name />.
    </adm:synopsis>
    <adm:requires-admin-action>
      <adm:none>
        <adm:synopsis>
          Changes to this property will take effect immediately, but
          only for subsequent attempts to access the key manager
          provider for associated client connections.
        </adm:synopsis>
      </adm:none>
    </adm:requires-admin-action>
    <adm:default-behavior>
      <adm:undefined />
    </adm:default-behavior>
    <adm:syntax>
      <adm:aggregation relation-name="key-manager-provider" parent-path="/">
        <adm:target-needs-enabling-condition>
          <adm:and>
            <adm:contains property="enabled" value="true" />
            <adm:contains property="use-ssl" value="true" />
          </adm:and>
        </adm:target-needs-enabling-condition>
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-key-manager-provider</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opends/src/admin/defn/org/opends/server/admin/std/LDAPConnectionHandlerConfiguration.xml
@@ -30,21 +30,18 @@
  package="org.opends.server.admin.std" extends="connection-handler"
  xmlns:adm="http://www.opends.org/admin"
  xmlns:ldap="http://www.opends.org/admin-ldap">
  <adm:synopsis>
    The
    <adm:user-friendly-name />
    is used to interact with clients using LDAP. In particular, it
    provides full support for LDAPv3 and limited support for LDAPv2.
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:name>ds-cfg-ldap-connection-handler</ldap:name>
      <ldap:superior>ds-cfg-connection-handler</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:property-override name="java-class">
    <adm:default-behavior>
      <adm:defined>
@@ -54,17 +51,93 @@
      </adm:defined>
    </adm:default-behavior>
  </adm:property-override>
  <adm:property-reference name="listen-port" />
  <adm:property-reference name="use-ssl" />
  <adm:property-reference name="ssl-cert-nickname" />
  <adm:property-reference name="key-manager-provider" />
  <adm:property-reference name="trust-manager-provider" />
  <adm:property name="key-manager-provider">
    <adm:synopsis>
      Specifies the name of the key manager that should be used with
      this
      <adm:user-friendly-name />
      .
    </adm:synopsis>
    <adm:requires-admin-action>
      <adm:none>
        <adm:synopsis>
          Changes to this property will take effect immediately, but
          only for subsequent attempts to access the key manager
          provider for associated client connections.
        </adm:synopsis>
      </adm:none>
    </adm:requires-admin-action>
    <adm:default-behavior>
      <adm:undefined />
    </adm:default-behavior>
    <adm:syntax>
      <adm:aggregation relation-name="key-manager-provider"
        parent-path="/">
        <adm:target-needs-enabling-condition>
          <adm:and>
            <adm:contains property="enabled" value="true" />
            <adm:or>
              <adm:contains property="use-ssl" value="true" />
              <adm:contains property="allow-start-tls" value="true" />
            </adm:or>
          </adm:and>
        </adm:target-needs-enabling-condition>
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-key-manager-provider</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="trust-manager-provider">
    <adm:synopsis>
      Specifies the name of the trust manager that should be used with
      this
      <adm:user-friendly-name />
      .
    </adm:synopsis>
    <adm:requires-admin-action>
      <adm:none>
        <adm:synopsis>
          Changes to this property will take effect immediately, but
          only for subsequent attempts to access the trust manager
          provider for associated client connections.
        </adm:synopsis>
      </adm:none>
    </adm:requires-admin-action>
    <adm:default-behavior>
      <adm:undefined />
    </adm:default-behavior>
    <adm:syntax>
      <adm:aggregation relation-name="trust-manager-provider"
        parent-path="/">
        <adm:target-needs-enabling-condition>
          <adm:and>
            <adm:contains property="enabled" value="true" />
            <adm:or>
              <adm:contains property="use-ssl" value="true" />
              <adm:contains property="allow-start-tls" value="true" />
            </adm:or>
          </adm:and>
        </adm:target-needs-enabling-condition>
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-trust-manager-provider</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="listen-address" multi-valued="true">
    <adm:synopsis>
      Specifies the address or set of addresses on which this
@@ -94,7 +167,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="allow-ldap-v2">
    <adm:synopsis>
      Indicates whether connections from LDAPv2 clients will be allowed.
@@ -120,7 +192,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="keep-stats">
    <adm:synopsis>
      Indicates whether the
@@ -147,7 +218,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="use-tcp-keep-alive">
    <adm:synopsis>
      Indicates whether the
@@ -178,7 +248,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="use-tcp-no-delay">
    <adm:synopsis>
      Indicates whether the
@@ -209,7 +278,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="allow-tcp-reuse-address">
    <adm:synopsis>
      Indicates whether the
@@ -241,7 +309,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="send-rejection-notice">
    <adm:synopsis>
      Indicates whether the
@@ -267,7 +334,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="max-request-size">
    <adm:synopsis>
      Specifies the size of the largest LDAP request message that will
@@ -296,7 +362,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="num-request-handlers">
    <adm:synopsis>
      Specifies the number of request handlers that will be used to read
@@ -329,7 +394,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="allow-start-tls">
    <adm:synopsis>
      Indicates whether clients will be allowed to use StartTLS.
@@ -358,7 +422,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="ssl-client-auth-policy">
    <adm:synopsis>
      Specifies the policy that the
@@ -407,7 +470,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="accept-backlog">
    <adm:synopsis>
      Specifies the maximum number of pending connection attempts that
@@ -441,7 +503,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="ssl-protocol" multi-valued="true">
    <adm:synopsis>
      Specifies the names of the SSL protocols that will be allowed for
@@ -473,7 +534,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="ssl-cipher-suite" multi-valued="true">
    <adm:synopsis>
      Specifies the names of the SSL cipher suites that will be allowed
@@ -505,19 +565,16 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="max-blocked-write-time-limit" mandatory="false">
    <adm:synopsis>
      Specifies the maximum length of time that attempts to write data to LDAP
      clients should be allowed to block.  If an attempt to write data to a
      client takes longer than this length of time, then the client connection
      will be terminated.
      Specifies the maximum length of time that attempts to write data
      to LDAP clients should be allowed to block. If an attempt to write
      data to a client takes longer than this length of time, then the
      client connection will be terminated.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          2 minutes
        </adm:value>
        <adm:value>2 minutes</adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
@@ -529,6 +586,4 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opends/src/admin/defn/org/opends/server/admin/std/Package.xml
@@ -227,36 +227,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="key-manager-provider">
    <adm:synopsis>
      Specifies the name of the key manager that should be used
      with this <adm:user-friendly-name />.
    </adm:synopsis>
    <adm:requires-admin-action>
      <adm:none>
        <adm:synopsis>
          Changes to this property will take effect immediately, but
          only for subsequent attempts to access the key manager
          provider for associated client connections.
        </adm:synopsis>
      </adm:none>
    </adm:requires-admin-action>
    <adm:default-behavior>
      <adm:undefined />
    </adm:default-behavior>
    <adm:syntax>
      <adm:aggregation relation-name="key-manager-provider" parent-path="/">
        <adm:source-enabled-property-name name="enabled" />
        <adm:source-enabled-property-name name="use-ssl" />
        <adm:target-enabled-property-name name="enabled" />
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-key-manager-provider</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="trust-store-pin">
    <adm:synopsis>
      Specifies the clear-text PIN needed to access the
@@ -374,36 +344,6 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="trust-manager-provider">
    <adm:synopsis>
      Specifies the name of the trust manager that should be used with
      this <adm:user-friendly-name />.
    </adm:synopsis>
    <adm:requires-admin-action>
      <adm:none>
        <adm:synopsis>
          Changes to this property will take effect immediately, but
          only for subsequent attempts to access the trust manager
          provider for associated client connections.
        </adm:synopsis>
      </adm:none>
    </adm:requires-admin-action>
    <adm:default-behavior>
      <adm:undefined />
    </adm:default-behavior>
    <adm:syntax>
      <adm:aggregation relation-name="trust-manager-provider" parent-path="/">
        <adm:source-enabled-property-name name="enabled" />
        <adm:source-enabled-property-name name="use-ssl" />
        <adm:target-enabled-property-name name="enabled" />
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-trust-manager-provider</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="include-filter" mandatory="false"
    multi-valued="true">
    <adm:synopsis>
opends/src/admin/defn/org/opends/server/admin/std/PasswordModifyExtendedOperationHandlerConfiguration.xml
@@ -77,8 +77,12 @@
    <adm:syntax>
      <adm:aggregation relation-name="identity-mapper"
        parent-path="/">
        <adm:source-enabled-property-name name="enabled" />
        <adm:target-enabled-property-name name="enabled" />
        <adm:target-needs-enabling-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-needs-enabling-condition>
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyConfiguration.xml
@@ -72,7 +72,9 @@
    <adm:syntax>
      <adm:aggregation relation-name="password-storage-scheme"
        parent-path="/">
        <adm:target-enabled-property-name name="enabled" />
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
@@ -98,7 +100,9 @@
    <adm:syntax>
      <adm:aggregation relation-name="password-storage-scheme"
        parent-path="/">
        <adm:target-enabled-property-name name="enabled" />
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
@@ -120,7 +124,9 @@
    <adm:syntax>
      <adm:aggregation relation-name="password-validator"
        parent-path="/">
        <adm:target-enabled-property-name name="enabled" />
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
@@ -143,7 +149,9 @@
      <adm:aggregation
        relation-name="account-status-notification-handler"
        parent-path="/">
        <adm:target-enabled-property-name name="enabled" />
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
@@ -319,7 +327,9 @@
    <adm:syntax>
      <adm:aggregation relation-name="password-generator"
        parent-path="/">
        <adm:target-enabled-property-name name="enabled" />
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
opends/src/admin/defn/org/opends/server/admin/std/PasswordPolicyImportPluginConfiguration.xml
@@ -86,8 +86,12 @@
    </adm:default-behavior>
    <adm:syntax>
      <adm:aggregation relation-name="password-storage-scheme" parent-path="/">
        <adm:source-enabled-property-name name="enabled" />
        <adm:target-enabled-property-name name="enabled" />
        <adm:target-needs-enabling-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-needs-enabling-condition>
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
@@ -118,8 +122,12 @@
    </adm:default-behavior>
    <adm:syntax>
      <adm:aggregation relation-name="password-storage-scheme" parent-path="/">
        <adm:source-enabled-property-name name="enabled" />
        <adm:target-enabled-property-name name="enabled" />
        <adm:target-needs-enabling-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-needs-enabling-condition>
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
opends/src/admin/defn/org/opends/server/admin/std/PlainSASLMechanismHandlerConfiguration.xml
@@ -59,8 +59,12 @@
    <adm:syntax>
      <adm:aggregation relation-name="identity-mapper"
        parent-path="/">
        <adm:source-enabled-property-name name="enabled" />
        <adm:target-enabled-property-name name="enabled" />
        <adm:target-needs-enabling-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-needs-enabling-condition>
        <adm:target-is-enabled-condition>
          <adm:contains property="enabled" value="true" />
        </adm:target-is-enabled-condition>
      </adm:aggregation>
    </adm:syntax>
    <adm:profile name="ldap">
opends/src/messages/messages/admin.properties
@@ -308,4 +308,5 @@
 disabled because it is referenced by the "%s" property in the %s called "%s"
SEVERE_ERR_CLIENT_REFINT_CANNOT_DISABLE_WITHOUT_NAME_133=This %s cannot be \
 disabled because it is referenced by the "%s" property in the %s
SEVERE_ERR_REFINT_UNABLE_TO_EVALUATE_TARGET_CONDITION_134=An error occurred \
 while attempting to determine if the %s in entry %s is enabled: %s
opends/src/messages/messages/dsconfig.properties
@@ -440,3 +440,6 @@
SEVERE_ERR_GET_HEADING_MODE_SINGLE_143=The %s could not be decoded due to the following reason:
SEVERE_ERR_GET_HEADING_MODE_PLURAL_144=The %s could not be decoded due to the following reasons:
INFO_EDITOR_OPTION_CREATE_A_NEW_COMPONENT_145=Create a new %s
INFO_DSCFG_PROMPT_EDIT_TO_ENABLE_146=The referenced %s \
 called "%s" must be enabled so that it can be used with this %s. Do \
 you want to edit its properties in order to enable it?
opends/src/server/org/opends/server/admin/AggregationPropertyDefinition.java
@@ -29,6 +29,7 @@
import static org.opends.messages.AdminMessages.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.util.Validator.*;
import java.util.Collection;
@@ -47,15 +48,21 @@
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagedObjectDecodingException;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.condition.Condition;
import org.opends.server.admin.condition.Conditions;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.server.ConfigurationDeleteListener;
import org.opends.server.admin.server.ServerConstraintHandler;
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.admin.server.ServerManagementContext;
import org.opends.server.config.ConfigException;
import org.opends.server.loggers.ErrorLogger;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.ResultCode;
import org.opends.server.util.StaticUtils;
@@ -126,16 +133,13 @@
    // contains the aggregated managed objects.
    private String rdName = null;
    // The optional names of boolean "enabled" properties in this
    // managed object. When all of the properties are true, the
    // enabled property in the aggregated managed object must also be
    // true.
    private List<String> sourceEnabledPropertyNames = new LinkedList<String>();
    // The condition which is used to determine if a referenced
    // managed object is enabled.
    private Condition targetIsEnabledCondition = Conditions.TRUE;
    // The optional name of a boolean "enabled" property in the
    // aggregated managed object. This property must not be false
    // while the aggregated managed object is referenced.
    private String targetEnabledPropertyName = null;
    // The condition which is used to determine whether or not
    // referenced managed objects need to be enabled.
    private Condition targetNeedsEnablingCondition = Conditions.TRUE;
@@ -148,27 +152,6 @@
    /**
     * Registers a boolean "enabled" property in this managed object.
     * When all the registered properties are true, the enabled
     * property in the aggregated managed object must also be true.
     * <p>
     * By default no source properties are defined which indicates
     * that the target property must always be true. When there is one
     * or more source properties defined, a target property must also
     * be defined.
     *
     * @param sourceEnabledPropertyName
     *          The optional boolean "enabled" property in this
     *          managed object.
     */
    public final void addSourceEnabledPropertyName(
        String sourceEnabledPropertyName) {
      this.sourceEnabledPropertyNames.add(sourceEnabledPropertyName);
    }
    /**
     * Sets the name of the managed object which is the parent of the
     * aggregated managed objects.
     * <p>
@@ -204,20 +187,31 @@
    /**
     * Sets the optional boolean "enabled" property in the aggregated
     * managed object. This property must not be false while the
     * aggregated managed object is referenced.
     * <p>
     * By default no target property is defined. It must be defined,
     * if the source property is defined.
     * Sets the condition which is used to determine if a referenced
     * managed object is enabled. By default referenced managed
     * objects are assumed to always be enabled.
     *
     * @param targetEnabledPropertyName
     *          The optional boolean "enabled" property in the
     *          aggregated managed object.
     * @param condition
     *          The condition which is used to determine if a
     *          referenced managed object is enabled.
     */
    public final void setTargetEnabledPropertyName(
        String targetEnabledPropertyName) {
      this.targetEnabledPropertyName = targetEnabledPropertyName;
    public final void setTargetIsEnabledCondition(Condition condition) {
      this.targetIsEnabledCondition = condition;
    }
    /**
     * Sets the condition which is used to determine whether or not
     * referenced managed objects need to be enabled. By default
     * referenced managed objects must always be enabled.
     *
     * @param condition
     *          The condition which is used to determine whether or
     *          not referenced managed objects need to be enabled.
     */
    public final void setTargetNeedsEnablingCondition(Condition condition) {
      this.targetNeedsEnablingCondition = condition;
    }
@@ -240,18 +234,9 @@
        throw new IllegalStateException("Relation definition undefined");
      }
      // Make sure that if a source property is specified then a
      // target property is also specified.
      if (!sourceEnabledPropertyNames.isEmpty()
          && targetEnabledPropertyName == null) {
        throw new IllegalStateException(
            "One or more source properties defined but "
                + "target property is undefined");
      }
      return new AggregationPropertyDefinition<C, S>(d, propertyName, options,
          adminAction, defaultBehavior, parentPathString, rdName,
          sourceEnabledPropertyNames, targetEnabledPropertyName);
          targetNeedsEnablingCondition, targetIsEnabledCondition);
    }
  }
@@ -287,18 +272,20 @@
     * {@inheritDoc}
     */
    public ConfigChangeResult applyConfigurationChange(S configuration) {
      PropertyProvider provider = configuration.properties();
      Collection<Boolean> values = provider
          .getPropertyValues(getTargetEnabledPropertyDefinition());
      if (values.iterator().next() == false) {
        // This should not happen - the
        // isConfigurationChangeAcceptable() call-back should have
      ServerManagedObject<?> mo = configuration.managedObject();
      try {
        if (targetIsEnabledCondition.evaluate(mo)) {
          return new ConfigChangeResult(ResultCode.SUCCESS, false);
        }
      } catch (ConfigException e) {
        // This should not happen - ignore it and throw an exception
        // anyway below.
      }
      // This should not happen - the previous call-back should have
        // trapped this.
        throw new IllegalStateException("Attempting to disable a referenced "
            + configuration.definition().getUserFriendlyName());
      } else {
        return new ConfigChangeResult(ResultCode.SUCCESS, false);
      }
    }
@@ -310,14 +297,27 @@
        List<Message> unacceptableReasons) {
      // Always prevent the referenced component from being
      // disabled.
      PropertyProvider provider = configuration.properties();
      Collection<Boolean> values = provider
          .getPropertyValues(getTargetEnabledPropertyDefinition());
      if (values.iterator().next() == false) {
      ServerManagedObject<?> mo = configuration.managedObject();
      try {
        if (!targetIsEnabledCondition.evaluate(mo)) {
          unacceptableReasons.add(message);
          return false;
        } else {
          return true;
        }
      } catch (ConfigException e) {
        // The condition could not be evaluated.
        if (debugEnabled()) {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
        Message message = ERR_REFINT_UNABLE_TO_EVALUATE_TARGET_CONDITION.get(mo
            .getManagedObjectDefinition().getUserFriendlyName(), String
            .valueOf(configuration.dn()), StaticUtils.getExceptionMessage(e));
        ErrorLogger.logError(message);
        unacceptableReasons.add(message);
        return false;
      }
      return true;
    }
@@ -407,15 +407,14 @@
      SortedSet<String> names = managedObject
          .getPropertyValues(AggregationPropertyDefinition.this);
      ServerManagementContext context = ServerManagementContext.getInstance();
      BooleanPropertyDefinition tpd = getTargetEnabledPropertyDefinition();
      List<BooleanPropertyDefinition> spdlist =
        getSourceEnabledPropertyDefinitions();
      Message thisUFN = managedObject.getManagedObjectDefinition()
          .getUserFriendlyName();
      String thisDN = managedObject.getDN().toString();
      Message thatUFN = getRelationDefinition().getUserFriendlyName();
      boolean isUsable = true;
      boolean needsEnabling = targetNeedsEnablingCondition
          .evaluate(managedObject);
      for (String name : names) {
        ManagedObjectPath<C, S> path = getChildPath(name);
        String thatDN = path.toDN().toString();
@@ -425,30 +424,11 @@
              getName(), thisUFN, thisDN, thatUFN, thatDN);
          unacceptableReasons.add(msg);
          isUsable = false;
        } else if (tpd != null) {
          // Check that the referenced component is enabled.
        } else if (needsEnabling) {
          // Check that the referenced component is enabled if
          // required.
          ServerManagedObject<? extends S> ref = context.getManagedObject(path);
          if (!spdlist.isEmpty()) {
            // Target must be enabled but only if the source
            // properties are enabled.
            boolean isRequired = true;
            for (BooleanPropertyDefinition spd : spdlist) {
              if (!managedObject.getPropertyValue(spd)) {
                isRequired = false;
                break;
              }
            }
            if (isRequired && !ref.getPropertyValue(tpd)) {
              Message msg = ERR_SERVER_REFINT_SOURCE_ENABLED_TARGET_DISABLED
                  .get(name, getName(), thisUFN, thisDN, thatUFN, thatDN);
              unacceptableReasons.add(msg);
              isUsable = false;
            }
          } else {
            // Target must always be enabled.
            if (!ref.getPropertyValue(tpd)) {
          if (!targetIsEnabledCondition.evaluate(ref)) {
              Message msg = ERR_SERVER_REFINT_TARGET_DISABLED.get(name,
                  getName(), thisUFN, thisDN, thatUFN, thatDN);
              unacceptableReasons.add(msg);
@@ -456,7 +436,6 @@
            }
          }
        }
      }
      return isUsable;
    }
@@ -478,9 +457,6 @@
      // Add change and delete listeners against all referenced
      // components.
      BooleanPropertyDefinition tpd = getTargetEnabledPropertyDefinition();
      List<BooleanPropertyDefinition> spdlist =
        getSourceEnabledPropertyDefinitions();
      Message thisUFN = managedObject.getManagedObjectDefinition()
          .getUserFriendlyName();
      String thisDN = managedObject.getDN().toString();
@@ -488,18 +464,8 @@
      // Referenced managed objects will only need a change listener
      // if they have can be disabled.
      boolean needsChangeListeners;
      if (tpd != null) {
        needsChangeListeners = true;
        for (BooleanPropertyDefinition spd : spdlist) {
          if (!managedObject.getPropertyValue(spd)) {
            needsChangeListeners = false;
            break;
          }
        }
      } else {
        needsChangeListeners = false;
      }
      boolean needsChangeListeners = targetNeedsEnablingCondition
          .evaluate(managedObject);
      // Delete listeners need to be registered against the parent
      // entry of the referenced components.
@@ -611,18 +577,12 @@
        throws AuthorizationException, CommunicationException {
      // If all of this managed object's "enabled" properties are true
      // then any referenced managed objects must also be enabled.
      boolean needsEnabling = true;
      for (BooleanPropertyDefinition spd :
        getSourceEnabledPropertyDefinitions()) {
        if (!managedObject.getPropertyValue(spd)) {
          needsEnabling = false;
        }
      }
      boolean needsEnabling = targetNeedsEnablingCondition.evaluate(context,
          managedObject);
      // Check the referenced managed objects exist and, if required,
      // are enabled.
      boolean isAcceptable = true;
      BooleanPropertyDefinition tpd = getTargetEnabledPropertyDefinition();
      Message ufn = getRelationDefinition().getUserFriendlyName();
      for (String name : managedObject
          .getPropertyValues(AggregationPropertyDefinition.this)) {
@@ -653,8 +613,8 @@
        }
        // Make sure the reference managed object is enabled.
        if (tpd != null && needsEnabling) {
          if (!ref.getPropertyValue(tpd)) {
        if (needsEnabling) {
          if (!targetIsEnabledCondition.evaluate(context, ref)) {
            Message msg = ERR_CLIENT_REFINT_TARGET_DISABLED.get(ufn, name,
                getName());
            unacceptableReasons.add(msg);
@@ -849,15 +809,7 @@
        throws AuthorizationException, CommunicationException {
      // If the modified managed object is disabled and there are some
      // active references then refuse the change.
      BooleanPropertyDefinition tpd = getTargetEnabledPropertyDefinition();
      // The referenced managed object cannot be disabled: always ok.
      if (tpd == null) {
        return true;
      }
      // The referenced managed object is enabled: always ok.
      if (managedObject.getPropertyValue(tpd)) {
      if (targetIsEnabledCondition.evaluate(context, managedObject)) {
        return true;
      }
@@ -866,16 +818,7 @@
      boolean isAcceptable = true;
      for (ManagedObject<?> mo : findReferences(context, managedObject
          .getManagedObjectPath().getName())) {
        boolean needsEnabling = true;
        for (BooleanPropertyDefinition spd :
          getSourceEnabledPropertyDefinitions()) {
          if (!mo.getPropertyValue(spd)) {
            needsEnabling = false;
            break;
          }
        }
        if (needsEnabling) {
        if (targetNeedsEnablingCondition.evaluate(context, mo)) {
          String name = mo.getManagedObjectPath().getName();
          if (name == null) {
            Message msg = ERR_CLIENT_REFINT_CANNOT_DISABLE_WITHOUT_NAME.get(
@@ -910,6 +853,11 @@
    }
  }
  /**
   * The tracer object for the debug logger.
   */
  private static final DebugTracer TRACER = getTracer();
  /**
@@ -937,14 +885,14 @@
  // The active server-side referential integrity change listeners
  // associated with this property.
  private final Map<DN, List<ReferentialIntegrityChangeListener>>
    changeListeners =
      new HashMap<DN, List<ReferentialIntegrityChangeListener>>();
    changeListeners = new HashMap<DN,
      List<ReferentialIntegrityChangeListener>>();
  // The active server-side referential integrity delete listeners
  // associated with this property.
  private final Map<DN, List<ReferentialIntegrityDeleteListener>>
    deleteListeners =
      new HashMap<DN, List<ReferentialIntegrityDeleteListener>>();
    deleteListeners = new HashMap<DN,
      List<ReferentialIntegrityDeleteListener>>();
  // The name of the managed object which is the parent of the
  // aggregated managed objects.
@@ -962,22 +910,13 @@
  // aggregated managed objects.
  private InstantiableRelationDefinition<C, S> relationDefinition;
  // The decoded source property definitions.
  private List<BooleanPropertyDefinition> sourceEnabledProperties;
  // The condition which is used to determine if a referenced managed
  // object is enabled.
  private final Condition targetIsEnabledCondition;
  // The optional names of boolean "enabled" properties in this
  // managed object. When all of the properties are true or if there
  // are none defined, the enabled property in the aggregated managed
  // object must also be true.
  private final List<String> sourceEnabledPropertyNames;
  // The decoded target property definition.
  private BooleanPropertyDefinition targetEnabledProperty;
  // The optional name of a boolean "enabled" property in the
  // aggregated managed object. This property must not be false
  // while the aggregated managed object is referenced.
  private final String targetEnabledPropertyName;
  // The condition which is used to determine whether or not
  // referenced managed objects need to be enabled.
  private final Condition targetNeedsEnablingCondition;
@@ -986,14 +925,14 @@
      AbstractManagedObjectDefinition<?, ?> d, String propertyName,
      EnumSet<PropertyOption> options, AdministratorAction adminAction,
      DefaultBehaviorProvider<String> defaultBehavior, String parentPathString,
      String rdName, List<String> sourceEnabledPropertyNames,
      String targetEnabledPropertyName) {
      String rdName, Condition targetNeedsEnablingCondition,
      Condition targetIsEnabledCondition) {
    super(d, String.class, propertyName, options, adminAction, defaultBehavior);
    this.parentPathString = parentPathString;
    this.rdName = rdName;
    this.sourceEnabledPropertyNames = sourceEnabledPropertyNames;
    this.targetEnabledPropertyName = targetEnabledPropertyName;
    this.targetNeedsEnablingCondition = targetNeedsEnablingCondition;
    this.targetIsEnabledCondition = targetIsEnabledCondition;
  }
@@ -1115,32 +1054,27 @@
  /**
   * Gets the optional boolean "enabled" properties in this managed
   * object. When these properties are all true or if there are no
   * properties, the enabled property in the aggregated managed object
   * must also be true.
   * Gets the condition which is used to determine if a referenced
   * managed object is enabled.
   *
   * @return Returns the optional boolean "enabled" properties in this
   *         managed object, which may be empty.
   * @return Returns the condition which is used to determine if a
   *         referenced managed object is enabled.
   */
  public final List<BooleanPropertyDefinition>
      getSourceEnabledPropertyDefinitions() {
    return sourceEnabledProperties;
  public final Condition getTargetIsEnabledCondition() {
    return targetIsEnabledCondition;
  }
  /**
   * Gets the optional boolean "enabled" property in the aggregated
   * managed object. This property must not be false while the
   * aggregated managed object is referenced.
   * Gets the condition which is used to determine whether or not
   * referenced managed objects need to be enabled.
   *
   * @return Returns the optional boolean "enabled" property in the
   *         aggregated managed object, or <code>null</code> if none
   *         is defined.
   * @return Returns the condition which is used to determine whether
   *         or not referenced managed objects need to be enabled.
   */
  public final BooleanPropertyDefinition getTargetEnabledPropertyDefinition() {
    return targetEnabledProperty;
  public final Condition getTargetNeedsEnablingCondition() {
    return targetNeedsEnablingCondition;
  }
@@ -1175,22 +1109,11 @@
    builder.append(" relationDefinition=");
    builder.append(relationDefinition.getName());
    builder.append(" sourceEnabledPropertyName=[");
    boolean isFirst = true;
    for (String name : sourceEnabledPropertyNames) {
      if (!isFirst) {
        builder.append(", ");
      } else {
        isFirst = false;
      }
      builder.append(name);
    }
    builder.append(']');
    builder.append(" targetNeedsEnablingCondition=");
    builder.append(String.valueOf(targetNeedsEnablingCondition));
    if (targetEnabledPropertyName != null) {
      builder.append(" targetEnabledPropertyName=");
      builder.append(targetEnabledPropertyName);
    }
    builder.append(" targetIsEnabledCondition=");
    builder.append(String.valueOf(targetIsEnabledCondition));
  }
@@ -1224,28 +1147,9 @@
    RelationDefinition<?, ?> rd = parent.getRelationDefinition(rdName);
    relationDefinition = (InstantiableRelationDefinition<C, S>) rd;
    // Now decode the property definitions.
    AbstractManagedObjectDefinition<?, ?> d = getManagedObjectDefinition();
    sourceEnabledProperties = new LinkedList<BooleanPropertyDefinition>();
    for (String name : sourceEnabledPropertyNames) {
      PropertyDefinition<?> pd = d.getPropertyDefinition(name);
      // Runtime cast is required to workaround a
      // bug in JDK versions prior to 1.5.0_08.
      sourceEnabledProperties.add(BooleanPropertyDefinition.class.cast(pd));
    }
    d = relationDefinition.getChildDefinition();
    if (targetEnabledPropertyName == null) {
      targetEnabledProperty = null;
    } else {
      PropertyDefinition<?> pd = d
          .getPropertyDefinition(targetEnabledPropertyName);
      // Runtime cast is required to workaround a
      // bug in JDK versions prior to 1.5.0_08.
      targetEnabledProperty = BooleanPropertyDefinition.class.cast(pd);
    }
    // Now decode the conditions.
    targetNeedsEnablingCondition.initialize(getManagedObjectDefinition());
    targetIsEnabledCondition.initialize(rd.getChildDefinition());
    // Register a client-side constraint with the referenced
    // definition. This will be used to enforce referential integrity
@@ -1271,7 +1175,7 @@
    };
    d.registerConstraint(constraint);
    rd.getChildDefinition().registerConstraint(constraint);
  }
}
opends/src/server/org/opends/server/admin/Configuration.java
@@ -29,6 +29,7 @@
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.types.DN;
@@ -40,7 +41,7 @@
public interface Configuration {
  /**
   * Get the DN of the LDAP entry associated with this configuration.
   * Gets the DN of the LDAP entry associated with this configuration.
   *
   * @return Returns the DN of the LDAP entry associated with this
   *         configuration.
@@ -50,7 +51,7 @@
  /**
   * Get the configuration definition associated with this
   * Gets the configuration definition associated with this
   * configuration.
   *
   * @return Returns the configuration definition associated with this
@@ -62,9 +63,11 @@
  /**
   * Get a property provider view of this configuration.
   * Gets the underlying server-side managed object associated with
   * this configuration.
   *
   * @return Returns a property provider view of this configuration.
   * @return Returns the underlying server-side managed object
   *         associated with this configuration.
   */
  PropertyProvider properties();
  ServerManagedObject<? extends Configuration> managedObject();
}
opends/src/server/org/opends/server/admin/condition/ANDCondition.java
New file
@@ -0,0 +1,112 @@
/*
 * 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 2007 Sun Microsystems, Inc.
 */
package org.opends.server.admin.condition;
import java.util.Arrays;
import java.util.List;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.config.ConfigException;
import org.opends.server.util.Validator;
/**
 * A condition which evaluates to <code>true</code> if and only if
 * all of its sub-conditions are <code>true</code>.
 */
public final class ANDCondition implements Condition {
  // The list of sub-conditions.
  private final List<Condition> conditions;
  /**
   * Creates a new logical AND condition with the provided
   * sub-conditions.
   *
   * @param conditions
   *          The sub-conditions which will be combined using a
   *          logical AND.
   */
  public ANDCondition(Condition... conditions) {
    Validator.ensureNotNull(conditions);
    this.conditions = Arrays.asList(conditions);
  }
  /**
   * {@inheritDoc}
   */
  public boolean evaluate(ManagementContext context,
      ManagedObject<?> managedObject) throws AuthorizationException,
      CommunicationException {
    for (Condition condition : conditions) {
      if (!condition.evaluate(context, managedObject)) {
        return false;
      }
    }
    return true;
  }
  /**
   * {@inheritDoc}
   */
  public boolean evaluate(ServerManagedObject<?> managedObject)
      throws ConfigException {
    for (Condition condition : conditions) {
      if (!condition.evaluate(managedObject)) {
        return false;
      }
    }
    return true;
  }
  /**
   * {@inheritDoc}
   */
  public void initialize(AbstractManagedObjectDefinition<?, ?> d)
      throws Exception {
    for (Condition condition : conditions) {
      condition.initialize(d);
    }
  }
}
opends/src/server/org/opends/server/admin/condition/Condition.java
New file
@@ -0,0 +1,94 @@
/*
 * 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 2007 Sun Microsystems, Inc.
 */
package org.opends.server.admin.condition;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.config.ConfigException;
/**
 * An interface for evaluating conditions.
 */
public interface Condition {
  /**
   * Initializes this condition.
   *
   * @param d
   *          The abstract managed object definition associated with
   *          this condition.
   * @throws Exception
   *           If this condition could not be initialized.
   */
  void initialize(AbstractManagedObjectDefinition<?, ?> d) throws Exception;
  /**
   * Evaluates this condition against the provided client managed
   * object.
   *
   * @param context
   *          The client management context.
   * @param managedObject
   *          The client managed object.
   * @return Returns <code>true</code> if this condition is
   *         satisfied.
   * @throws AuthorizationException
   *           If the condition could not be evaluated due to an
   *           authorization problem.
   * @throws CommunicationException
   *           If the condition could not be evaluated due to an
   *           communication problem.
   */
  boolean evaluate(ManagementContext context, ManagedObject<?> managedObject)
      throws AuthorizationException, CommunicationException;
  /**
   * Evaluates this condition against the provided server managed
   * object.
   *
   * @param managedObject
   *          The server managed object.
   * @return Returns <code>true</code> if this condition is
   *         satisfied.
   * @throws ConfigException
   *           If the condition could not be evaluated due to an
   *           unexpected configuration exception.
   */
  boolean evaluate(ServerManagedObject<?> managedObject) throws ConfigException;
}
opends/src/server/org/opends/server/admin/condition/Conditions.java
New file
@@ -0,0 +1,237 @@
/*
 * 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 2007 Sun Microsystems, Inc.
 */
package org.opends.server.admin.condition;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.config.ConfigException;
/**
 * This class consists exclusively of static methods that operate on
 * or return conditions.
 */
public final class Conditions {
  /**
   * A condition which always evaluates to <code>false</code>.
   */
  public static final Condition FALSE = new Condition() {
    /**
     * {@inheritDoc}
     */
    public boolean evaluate(ManagementContext context,
        ManagedObject<?> managedObject) throws AuthorizationException,
        CommunicationException {
      return false;
    }
    /**
     * {@inheritDoc}
     */
    public boolean evaluate(ServerManagedObject<?> managedObject)
        throws ConfigException {
      return false;
    }
    /**
     * {@inheritDoc}
     */
    public void initialize(AbstractManagedObjectDefinition<?, ?> d)
        throws Exception {
      // No implementation required.
    }
  };
  /**
   * A condition which always evaluates to <code>true</code>.
   */
  public static final Condition TRUE = new Condition() {
    /**
     * {@inheritDoc}
     */
    public boolean evaluate(ManagementContext context,
        ManagedObject<?> managedObject) throws AuthorizationException,
        CommunicationException {
      return true;
    }
    /**
     * {@inheritDoc}
     */
    public boolean evaluate(ServerManagedObject<?> managedObject)
        throws ConfigException {
      return true;
    }
    /**
     * {@inheritDoc}
     */
    public void initialize(AbstractManagedObjectDefinition<?, ?> d)
        throws Exception {
      // No implementation required.
    }
  };
  /**
   * Creates a condition which evaluates to <code>true</code> if and
   * only if all of its sub-conditions are <code>true</code>.
   *
   * @param conditions
   *          The sub-conditions which be combined using a logical
   *          AND.
   * @return Returns a condition which evaluates to <code>true</code>
   *         if and only if all of its sub-conditions are
   *         <code>true</code>.
   */
  public static Condition and(Condition... conditions) {
    return new ANDCondition(conditions);
  }
  /**
   * Creates a condition which evaluates to <code>true</code> if and
   * only if a property contains a particular value.
   *
   * @param propertyName
   *          The property name.
   * @param propertyStringValue
   *          The string representation of the required property
   *          value.
   * @return Returns a condition which evaluates to <code>true</code>
   *         if and only if a property contains a particular value.
   */
  public static Condition contains(String propertyName,
      String propertyStringValue) {
    return new ContainsValueCondition(propertyName, propertyStringValue);
  }
  /**
   * Creates a condition which evaluates to <code>false</code> if
   * and only if the first sub-condition evaluates to
   * <code>true</code> and the second sub-condition evaluates to
   * <code>false</code>. This can be used to represent if-then
   * relationships.
   *
   * @param premise
   *          The sub-condition which, when <code>true</code>
   *          implies that the implication sub-condition must also be
   *          <code>true</code>.
   * @param implication
   *          The sub-condition which, must be <code>true</code>
   *          when the premise is <code>true</code>.
   * @return Returns a condition which evaluates to <code>false</code>
   *         if and only if the first sub-condition evaluates to
   *         <code>true</code> and the second sub-condition
   *         evaluates to <code>false</code>.
   */
  public static Condition implies(Condition premise, Condition implication) {
    return or(not(premise), implication);
  }
  /**
   * Creates a condition which evaluates to <code>true</code> if and
   * only if a particular property has any values specified.
   *
   * @param propertyName
   *          The property name.
   * @return Returns a condition which evaluates to <code>true</code>
   *         if and only if a particular property has any values
   *         specified.
   */
  public static Condition isPresent(String propertyName) {
    return new IsPresentCondition(propertyName);
  }
  /**
   * Creates a condition which evaluates to <code>true</code> if the
   * sub-condition is <code>false</code>, or <code>false</code>
   * if the sub-condition is <code>true</code>.
   *
   * @param condition
   *          The sub-condition which will be inverted.
   * @return Returns a condition which evaluates to <code>true</code>
   *         if the sub-condition is <code>false</code>, or
   *         <code>false</code> if the sub-condition is
   *         <code>true</code>.
   */
  public static Condition not(Condition condition) {
    return new NOTCondition(condition);
  }
  /**
   * Creates a condition which evaluates to <code>false</code> if
   * and only if all of its sub-conditions are <code>false</code>.
   *
   * @param conditions
   *          The sub-conditions which be combined using a logical OR.
   * @return Returns a condition which evaluates to <code>false</code>
   *         if and only if all of its sub-conditions are
   *         <code>false</code>.
   */
  public static Condition or(Condition... conditions) {
    return new ORCondition(conditions);
  }
  // Prevent instantiation.
  private Conditions() {
    // No implementation required.
  }
}
opends/src/server/org/opends/server/admin/condition/ContainsValueCondition.java
New file
@@ -0,0 +1,197 @@
/*
 * 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 2007 Sun Microsystems, Inc.
 */
package org.opends.server.admin.condition;
import java.util.SortedSet;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.IllegalPropertyValueStringException;
import org.opends.server.admin.PropertyDefinition;
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.config.ConfigException;
import org.opends.server.util.Validator;
/**
 * A condition which evaluates to <code>true</code> if and only if a
 * property contains a particular value.
 */
public final class ContainsValueCondition implements Condition {
  /**
   * The strongly typed underlying implementation.
   *
   * @param <T>
   *          The type of the property value being tested.
   */
  private static final class Impl<T> implements Condition {
    // The property.
    private final PropertyDefinition<T> pd;
    // The required property value.
    private final T value;
    // Private constructor.
    private Impl(PropertyDefinition<T> pd, T value)
        throws IllegalPropertyValueStringException {
      this.pd = pd;
      this.value = value;
    }
    /**
     * {@inheritDoc}
     */
    public boolean evaluate(ManagementContext context,
        ManagedObject<?> managedObject) throws AuthorizationException,
        CommunicationException {
      SortedSet<T> values = managedObject.getPropertyValues(pd);
      return values.contains(value);
    }
    /**
     * {@inheritDoc}
     */
    public boolean evaluate(ServerManagedObject<?> managedObject)
        throws ConfigException {
      SortedSet<T> values = managedObject.getPropertyValues(pd);
      return values.contains(value);
    }
    /**
     * {@inheritDoc}
     */
    public void initialize(AbstractManagedObjectDefinition<?, ?> d)
        throws Exception {
      // Not used.
    }
    // Private implementation of fix() method.
    private void setPropertyValue(ManagedObject<?> managedObject) {
      managedObject.setPropertyValue(pd, value);
    }
  }
  // The strongly typed private implementation.
  private Impl<?> impl = null;
  // The property name.
  private final String propertyName;
  // The string representation of the required property value.
  private final String propertyStringValue;
  /**
   * Creates a new contains value condition.
   *
   * @param propertyName
   *          The property name.
   * @param stringValue
   *          The string representation of the required property
   *          value.
   */
  public ContainsValueCondition(String propertyName, String stringValue) {
    Validator.ensureNotNull(propertyName, stringValue);
    this.propertyName = propertyName;
    this.propertyStringValue = stringValue;
  }
  /**
   * {@inheritDoc}
   */
  public boolean evaluate(ManagementContext context,
      ManagedObject<?> managedObject) throws AuthorizationException,
      CommunicationException {
    return impl.evaluate(context, managedObject);
  }
  /**
   * {@inheritDoc}
   */
  public boolean evaluate(ServerManagedObject<?> managedObject)
      throws ConfigException {
    return impl.evaluate(managedObject);
  }
  /**
   * Modifies the provided managed object so that it has the property
   * value associated with this condition.
   *
   * @param managedObject
   *          The managed object.
   */
  public void setPropertyValue(ManagedObject<?> managedObject) {
    impl.setPropertyValue(managedObject);
  }
  /**
   * {@inheritDoc}
   */
  public void initialize(AbstractManagedObjectDefinition<?, ?> d)
      throws Exception {
    // Decode the property.
    buildImpl(d.getPropertyDefinition(propertyName));
  }
  // Creates the new private implementation.
  private <T> void buildImpl(PropertyDefinition<T> pd)
      throws IllegalPropertyValueStringException {
    T value = pd.decodeValue(propertyStringValue);
    this.impl = new Impl<T>(pd, value);
  }
}
opends/src/server/org/opends/server/admin/condition/IsPresentCondition.java
New file
@@ -0,0 +1,104 @@
/*
 * 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 2007 Sun Microsystems, Inc.
 */
package org.opends.server.admin.condition;
import java.util.SortedSet;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.PropertyDefinition;
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.config.ConfigException;
import org.opends.server.util.Validator;
/**
 * A condition which evaluates to <code>true</code> if and only if a
 * particular property has any values specified.
 */
public final class IsPresentCondition implements Condition {
  // The property name.
  private final String propertyName;
  // The property definition.
  private PropertyDefinition<?> pd;
  /**
   * Creates a new is present condition.
   *
   * @param propertyName
   *          The property name.
   */
  public IsPresentCondition(String propertyName) {
    Validator.ensureNotNull(propertyName);
    this.propertyName = propertyName;
  }
  /**
   * {@inheritDoc}
   */
  public boolean evaluate(ManagementContext context,
      ManagedObject<?> managedObject) throws AuthorizationException,
      CommunicationException {
    SortedSet<?> values = managedObject.getPropertyValues(pd);
    return !values.isEmpty();
  }
  /**
   * {@inheritDoc}
   */
  public boolean evaluate(ServerManagedObject<?> managedObject)
      throws ConfigException {
    SortedSet<?> values = managedObject.getPropertyValues(pd);
    return !values.isEmpty();
  }
  /**
   * {@inheritDoc}
   */
  public void initialize(AbstractManagedObjectDefinition<?, ?> d)
      throws Exception {
    // Decode the property.
    this.pd = d.getPropertyDefinition(propertyName);
  }
}
opends/src/server/org/opends/server/admin/condition/NOTCondition.java
New file
@@ -0,0 +1,97 @@
/*
 * 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 2007 Sun Microsystems, Inc.
 */
package org.opends.server.admin.condition;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.config.ConfigException;
import org.opends.server.util.Validator;
/**
 * A condition which evaluates to <code>true</code> if the
 * sub-condition is <code>false</code>, or <code>false</code> if
 * the sub-condition is <code>true</code>.
 */
public final class NOTCondition implements Condition {
  // The single sub-condition.
  private final Condition condition;
  /**
   * Creates a new logical NOT condition with the provided
   * sub-condition.
   *
   * @param condition
   *          The sub-condition which will be inverted.
   */
  public NOTCondition(Condition condition) {
    Validator.ensureNotNull(condition);
    this.condition = condition;
  }
  /**
   * {@inheritDoc}
   */
  public boolean evaluate(ManagementContext context,
      ManagedObject<?> managedObject) throws AuthorizationException,
      CommunicationException {
    return !condition.evaluate(context, managedObject);
  }
  /**
   * {@inheritDoc}
   */
  public boolean evaluate(ServerManagedObject<?> managedObject)
      throws ConfigException {
    return !condition.evaluate(managedObject);
  }
  /**
   * {@inheritDoc}
   */
  public void initialize(AbstractManagedObjectDefinition<?, ?> d)
      throws Exception {
    condition.initialize(d);
  }
}
opends/src/server/org/opends/server/admin/condition/ORCondition.java
New file
@@ -0,0 +1,112 @@
/*
 * 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 2007 Sun Microsystems, Inc.
 */
package org.opends.server.admin.condition;
import java.util.Arrays;
import java.util.List;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.config.ConfigException;
import org.opends.server.util.Validator;
/**
 * A condition which evaluates to <code>false</code> if and only if
 * all of its sub-conditions are <code>false</code>.
 */
public final class ORCondition implements Condition {
  // The list of sub-conditions.
  private final List<Condition> conditions;
  /**
   * Creates a new logical OR condition with the provided
   * sub-conditions.
   *
   * @param conditions
   *          The sub-conditions which will be combined using a
   *          logical OR.
   */
  public ORCondition(Condition... conditions) {
    Validator.ensureNotNull(conditions);
    this.conditions = Arrays.asList(conditions);
  }
  /**
   * {@inheritDoc}
   */
  public boolean evaluate(ManagementContext context,
      ManagedObject<?> managedObject) throws AuthorizationException,
      CommunicationException {
    for (Condition condition : conditions) {
      if (condition.evaluate(context, managedObject)) {
        return true;
      }
    }
    return false;
  }
  /**
   * {@inheritDoc}
   */
  public boolean evaluate(ServerManagedObject<?> managedObject)
      throws ConfigException {
    for (Condition condition : conditions) {
      if (condition.evaluate(managedObject)) {
        return true;
      }
    }
    return false;
  }
  /**
   * {@inheritDoc}
   */
  public void initialize(AbstractManagedObjectDefinition<?, ?> d)
      throws Exception {
    for (Condition condition : conditions) {
      condition.initialize(d);
    }
  }
}
opends/src/server/org/opends/server/admin/condition/package-info.java
New file
@@ -0,0 +1,36 @@
/*
 * 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 2007 Sun Microsystems, Inc.
 */
/**
 * Logical conditions for defining constraints.
 * <p>
 * This package contains interfaces for building and evaluating
 * arbitrary logical conditions which can be used with constraints.
 */
@org.opends.server.types.PublicAPI(
    stability = org.opends.server.types.StabilityLevel.PRIVATE)
package org.opends.server.admin.condition;
opends/src/server/org/opends/server/tools/dsconfig/CreateSubCommandHandler.java
@@ -46,7 +46,6 @@
import org.opends.messages.Message;
import org.opends.server.admin.AbstractManagedObjectDefinition;
import org.opends.server.admin.AggregationPropertyDefinition;
import org.opends.server.admin.BooleanPropertyDefinition;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.ConfigurationClient;
import org.opends.server.admin.DefaultBehaviorException;
@@ -74,6 +73,8 @@
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.client.MissingMandatoryPropertiesException;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.admin.condition.Condition;
import org.opends.server.admin.condition.ContainsValueCondition;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.tools.ClientException;
import org.opends.server.util.args.ArgumentException;
@@ -454,6 +455,7 @@
    ManagedObjectDefinition<?, ?> d = mo.getManagedObjectDefinition();
    Message ufn = d.getUserFriendlyName();
    try {
    for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
      if (pd instanceof AggregationPropertyDefinition) {
        // Runtime cast is required to workaround a
@@ -461,25 +463,9 @@
        AggregationPropertyDefinition<?, ?> apd =
          AggregationPropertyDefinition.class.cast(pd);
        // Skip this aggregation if it doesn't have an enable
        // property.
        BooleanPropertyDefinition tpd = apd
            .getTargetEnabledPropertyDefinition();
        if (tpd == null) {
          continue;
        }
        // Skip this aggregation if this managed object's enable
        // properties are not all true.
        boolean needsEnabling = true;
        for (BooleanPropertyDefinition bpd : apd
            .getSourceEnabledPropertyDefinitions()) {
          if (!mo.getPropertyValue(bpd)) {
            needsEnabling = false;
            break;
          }
        }
        if (!needsEnabling) {
          // Skip this aggregation if the referenced managed objects
          // do not need to be enabled.
          if (!apd.getTargetNeedsEnablingCondition().evaluate(context, mo)) {
          continue;
        }
@@ -491,10 +477,6 @@
          ManagedObject<?> ref;
          try {
            ref = context.getManagedObject(path);
          } catch (AuthorizationException e) {
            Message msg = ERR_DSCFG_ERROR_CREATE_AUTHZ.get(ufn);
            throw new ClientException(
                LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS, msg);
          } catch (DefinitionDecodingException e) {
            Message msg = ERR_DSCFG_ERROR_GET_CHILD_DDE.get(rufn, rufn, rufn);
            throw new ClientException(LDAPResultCode.OTHER, msg);
@@ -504,21 +486,23 @@
            // partial managed object.
            Message msg = ERR_DSCFG_ERROR_GET_CHILD_MODE.get(rufn);
            throw new ClientException(LDAPResultCode.OTHER, msg, e);
          } catch (CommunicationException e) {
            Message msg = ERR_DSCFG_ERROR_CREATE_CE.get(ufn, e.getMessage());
            throw new ClientException(LDAPResultCode.OTHER, msg);
          } catch (ManagedObjectNotFoundException e) {
            Message msg = ERR_DSCFG_ERROR_GET_CHILD_MONFE.get(rufn);
            throw new ClientException(LDAPResultCode.NO_SUCH_OBJECT, msg);
          }
          while (!ref.getPropertyValue(tpd)) {
            Condition condition = apd.getTargetIsEnabledCondition();
            while (!condition.evaluate(context, ref)) {
            boolean isBadReference = true;
              if (condition instanceof ContainsValueCondition) {
                // Attempt to automatically enable the managed object.
                ContainsValueCondition cvc = (ContainsValueCondition) condition;
            app.println();
            if (app.confirmAction(
                INFO_EDITOR_PROMPT_ENABLED_REFERENCED_COMPONENT.get(rufn, name,
                    ufn), true)) {
              ref.setPropertyValue(tpd, true);
                    INFO_EDITOR_PROMPT_ENABLED_REFERENCED_COMPONENT.get(rufn,
                        name, ufn), true)) {
                  cvc.setPropertyValue(ref);
              try {
                ref.commit();
                isBadReference = false;
@@ -527,9 +511,8 @@
                app.println();
                displayMissingMandatoryPropertyException(app, e);
                app.println();
                if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT.get(rufn), true)) {
                  // FIXME: edit the properties of the referenced
                  // object.
                    if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT.get(rufn),
                        true)) {
                  MenuResult<Void> result = SetPropSubCommandHandler
                      .modifyManagedObject(app, context, ref);
                  if (result.isQuit()) {
@@ -540,20 +523,17 @@
                    isBadReference = false;
                  }
                }
              } catch (AuthorizationException e) {
                Message msg = ERR_DSCFG_ERROR_CREATE_AUTHZ.get(ufn);
                throw new ClientException(
                    LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS, msg);
              } catch (ConcurrentModificationException e) {
                Message msg = ERR_DSCFG_ERROR_CREATE_CME.get(ufn);
                throw new ClientException(LDAPResultCode.CONSTRAINT_VIOLATION,
                    msg);
                    throw new ClientException(
                        LDAPResultCode.CONSTRAINT_VIOLATION, msg);
              } catch (OperationRejectedException e) {
                // Give the user the chance to fix the problems.
                app.println();
                displayOperationRejectedException(app, e);
                app.println();
                if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT.get(rufn), true)) {
                    if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT.get(rufn),
                        true)) {
                  MenuResult<Void> result = SetPropSubCommandHandler
                      .modifyManagedObject(app, context, ref);
                  if (result.isQuit()) {
@@ -564,38 +544,52 @@
                    isBadReference = false;
                  }
                }
              } catch (CommunicationException e) {
                Message msg = ERR_DSCFG_ERROR_CREATE_CE
                    .get(ufn, e.getMessage());
                throw new ClientException(LDAPResultCode.OTHER, msg);
              } catch (ManagedObjectAlreadyExistsException e) {
                // Should never happen.
                throw new IllegalStateException(e);
              }
            }
              } else {
                app.println();
                if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT_TO_ENABLE.get(
                    rufn, name, ufn), true)) {
                  MenuResult<Void> result = SetPropSubCommandHandler
                      .modifyManagedObject(app, context, ref);
                  if (result.isQuit()) {
                    return result;
                  } else if (result.isSuccess()) {
                    // The referenced component was modified
                    // successfully, but may still be disabled.
                    isBadReference = false;
                  }
                }
              }
            // If the referenced component is still disabled because
            // the user refused to modify it, then give the used the
            // option of editing the referencing component.
            if (isBadReference) {
              app.println();
              app.println(ERR_SET_REFERENCED_COMPONENT_DISABLED.get(ufn, rufn));
                app.println(ERR_SET_REFERENCED_COMPONENT_DISABLED
                    .get(ufn, rufn));
              app.println();
              if (app
                  .confirmAction(INFO_DSCFG_PROMPT_EDIT_AGAIN.get(ufn), true)) {
                if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT_AGAIN.get(ufn),
                    true)) {
                return MenuResult.again();
              } else {
                return MenuResult.cancel();
              }
            }
            // If the referenced component is now enabled, then drop out.
            if (ref.getPropertyValue(tpd)) {
              break;
            }
          }
        }
      }
    } catch (AuthorizationException e) {
      Message msg = ERR_DSCFG_ERROR_CREATE_AUTHZ.get(ufn);
      throw new ClientException(LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS, msg);
    } catch (CommunicationException e) {
      Message msg = ERR_DSCFG_ERROR_CREATE_CE.get(ufn, e.getMessage());
      throw new ClientException(LDAPResultCode.OTHER, msg);
    }
    return MenuResult.success();
opends/src/server/org/opends/server/tools/dsconfig/SetPropSubCommandHandler.java
@@ -40,7 +40,6 @@
import org.opends.messages.Message;
import org.opends.server.admin.AggregationPropertyDefinition;
import org.opends.server.admin.BooleanPropertyDefinition;
import org.opends.server.admin.DefinitionDecodingException;
import org.opends.server.admin.IllegalPropertyValueStringException;
import org.opends.server.admin.InstantiableRelationDefinition;
@@ -63,6 +62,8 @@
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.client.MissingMandatoryPropertiesException;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.admin.condition.Condition;
import org.opends.server.admin.condition.ContainsValueCondition;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.tools.ClientException;
import org.opends.server.util.args.ArgumentException;
@@ -340,6 +341,7 @@
    ManagedObjectDefinition<?, ?> d = mo.getManagedObjectDefinition();
    Message ufn = d.getUserFriendlyName();
    try {
    for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
      if (pd instanceof AggregationPropertyDefinition) {
        // Runtime cast is required to workaround a
@@ -347,25 +349,9 @@
        AggregationPropertyDefinition<?, ?> apd =
          AggregationPropertyDefinition.class.cast(pd);
        // Skip this aggregation if it doesn't have an enable
        // property.
        BooleanPropertyDefinition tpd = apd
            .getTargetEnabledPropertyDefinition();
        if (tpd == null) {
          continue;
        }
        // Skip this aggregation if this managed object's enable
        // properties are not all true.
        boolean needsEnabling = true;
        for (BooleanPropertyDefinition bpd : apd
            .getSourceEnabledPropertyDefinitions()) {
          if (!mo.getPropertyValue(bpd)) {
            needsEnabling = false;
            break;
          }
        }
        if (!needsEnabling) {
          // Skip this aggregation if the referenced managed objects
          // do not need to be enabled.
          if (!apd.getTargetNeedsEnablingCondition().evaluate(context, mo)) {
          continue;
        }
@@ -377,10 +363,6 @@
          ManagedObject<?> ref;
          try {
            ref = context.getManagedObject(path);
          } catch (AuthorizationException e) {
            Message msg = ERR_DSCFG_ERROR_MODIFY_AUTHZ.get(ufn);
            throw new ClientException(
                LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS, msg);
          } catch (DefinitionDecodingException e) {
            Message msg = ERR_DSCFG_ERROR_GET_CHILD_DDE.get(rufn, rufn, rufn);
            throw new ClientException(LDAPResultCode.OTHER, msg);
@@ -390,21 +372,23 @@
            // partial managed object.
            Message msg = ERR_DSCFG_ERROR_GET_CHILD_MODE.get(rufn);
            throw new ClientException(LDAPResultCode.OTHER, msg, e);
          } catch (CommunicationException e) {
            Message msg = ERR_DSCFG_ERROR_MODIFY_CE.get(ufn, e.getMessage());
            throw new ClientException(LDAPResultCode.OTHER, msg);
          } catch (ManagedObjectNotFoundException e) {
            Message msg = ERR_DSCFG_ERROR_GET_CHILD_MONFE.get(rufn);
            throw new ClientException(LDAPResultCode.NO_SUCH_OBJECT, msg);
          }
          while (!ref.getPropertyValue(tpd)) {
            Condition condition = apd.getTargetIsEnabledCondition();
            while (!condition.evaluate(context, ref)) {
            boolean isBadReference = true;
              if (condition instanceof ContainsValueCondition) {
                // Attempt to automatically enable the managed object.
                ContainsValueCondition cvc = (ContainsValueCondition) condition;
            app.println();
            if (app.confirmAction(
                INFO_EDITOR_PROMPT_ENABLED_REFERENCED_COMPONENT.get(rufn, name,
                    ufn), true)) {
              ref.setPropertyValue(tpd, true);
                    INFO_EDITOR_PROMPT_ENABLED_REFERENCED_COMPONENT.get(rufn,
                        name, ufn), true)) {
                  cvc.setPropertyValue(ref);
              try {
                ref.commit();
                isBadReference = false;
@@ -413,11 +397,10 @@
                app.println();
                displayMissingMandatoryPropertyException(app, e);
                app.println();
                if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT.get(rufn), true)) {
                  // FIXME: edit the properties of the referenced
                  // object.
                  MenuResult<Void> result =
                    modifyManagedObject(app, context, ref);
                    if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT.get(rufn),
                        true)) {
                      MenuResult<Void> result = modifyManagedObject(app,
                          context, ref);
                  if (result.isQuit()) {
                    return result;
                  } else if (result.isSuccess()) {
@@ -426,22 +409,19 @@
                    isBadReference = false;
                  }
                }
              } catch (AuthorizationException e) {
                Message msg = ERR_DSCFG_ERROR_MODIFY_AUTHZ.get(ufn);
                throw new ClientException(
                    LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS, msg);
              } catch (ConcurrentModificationException e) {
                Message msg = ERR_DSCFG_ERROR_MODIFY_CME.get(ufn);
                throw new ClientException(LDAPResultCode.CONSTRAINT_VIOLATION,
                    msg);
                    throw new ClientException(
                        LDAPResultCode.CONSTRAINT_VIOLATION, msg);
              } catch (OperationRejectedException e) {
                // Give the user the chance to fix the problems.
                app.println();
                displayOperationRejectedException(app, e);
                app.println();
                if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT.get(rufn), true)) {
                  MenuResult<Void> result =
                    modifyManagedObject(app, context, ref);
                    if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT.get(rufn),
                        true)) {
                      MenuResult<Void> result = modifyManagedObject(app,
                          context, ref);
                  if (result.isQuit()) {
                    return result;
                  } else if (result.isSuccess()) {
@@ -450,38 +430,52 @@
                    isBadReference = false;
                  }
                }
              } catch (CommunicationException e) {
                Message msg = ERR_DSCFG_ERROR_MODIFY_CE
                    .get(ufn, e.getMessage());
                throw new ClientException(LDAPResultCode.OTHER, msg);
              } catch (ManagedObjectAlreadyExistsException e) {
                // Should never happen.
                throw new IllegalStateException(e);
              }
            }
              } else {
                app.println();
                if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT_TO_ENABLE.get(
                    rufn, name, ufn), true)) {
                  MenuResult<Void> result = SetPropSubCommandHandler
                      .modifyManagedObject(app, context, ref);
                  if (result.isQuit()) {
                    return result;
                  } else if (result.isSuccess()) {
                    // The referenced component was modified
                    // successfully, but may still be disabled.
                    isBadReference = false;
                  }
                }
              }
            // If the referenced component is still disabled because
            // the user refused to modify it, then give the used the
            // option of editing the referencing component.
            if (isBadReference) {
              app.println();
              app.println(ERR_SET_REFERENCED_COMPONENT_DISABLED.get(ufn, rufn));
                app.println(ERR_SET_REFERENCED_COMPONENT_DISABLED
                    .get(ufn, rufn));
              app.println();
              if (app
                  .confirmAction(INFO_DSCFG_PROMPT_EDIT_AGAIN.get(ufn), true)) {
                if (app.confirmAction(INFO_DSCFG_PROMPT_EDIT_AGAIN.get(ufn),
                    true)) {
                return MenuResult.again();
              } else {
                return MenuResult.cancel();
              }
            }
            // If the referenced component is now enabled, then drop out.
            if (ref.getPropertyValue(tpd)) {
              break;
            }
          }
        }
      }
    } catch (AuthorizationException e) {
      Message msg = ERR_DSCFG_ERROR_MODIFY_AUTHZ.get(ufn);
      throw new ClientException(LDAPResultCode.INSUFFICIENT_ACCESS_RIGHTS, msg);
    } catch (CommunicationException e) {
      Message msg = ERR_DSCFG_ERROR_MODIFY_CE.get(ufn, e.getMessage());
      throw new ClientException(LDAPResultCode.OTHER, msg);
    }
    return MenuResult.success();
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java
@@ -579,7 +579,7 @@
    /**
     * {@inheritDoc}
     */
    public PropertyProvider properties() {
    public ServerManagedObject<? extends TestChildCfg> managedObject() {
      return impl;
    }
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java
@@ -721,7 +721,7 @@
    /**
     * {@inheritDoc}
     */
    public PropertyProvider properties() {
    public ServerManagedObject<? extends TestParentCfg> managedObject() {
      return impl;
    }
opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/AggregationTest.java
@@ -52,6 +52,7 @@
import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.admin.client.ldap.JNDIDirContextAdaptor;
import org.opends.server.admin.condition.Conditions;
import org.opends.server.admin.std.client.ConnectionHandlerCfgClient;
import org.opends.server.admin.std.client.LDAPConnectionHandlerCfgClient;
import org.opends.server.admin.std.client.RootCfgClient;
@@ -306,7 +307,7 @@
        .setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider<String>());
    builder.setParentPath("/");
    builder.setRelationDefinition("connection-handler");
    builder.setTargetEnabledPropertyName("enabled");
    builder.setTargetIsEnabledCondition(Conditions.contains("enabled", "true"));
    aggregationPropertyDefinitionTargetMustBeEnabled = builder.getInstance();
    TestCfg.initializePropertyDefinition(aggregationPropertyDefinitionTargetMustBeEnabled);
@@ -319,8 +320,8 @@
        .setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider<String>());
    builder.setParentPath("/");
    builder.setRelationDefinition("connection-handler");
    builder.setTargetEnabledPropertyName("enabled");
    builder.addSourceEnabledPropertyName("mandatory-boolean-property");
    builder.setTargetIsEnabledCondition(Conditions.contains("enabled", "true"));
    builder.setTargetNeedsEnablingCondition(Conditions.contains("mandatory-boolean-property", "true"));
    aggregationPropertyDefinitionTargetAndSourceMustBeEnabled = builder
        .getInstance();
    TestCfg.initializePropertyDefinition(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled);
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/DomainFakeCfg.java
@@ -28,9 +28,10 @@
import java.util.SortedSet;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.ManagedObjectDefinition;
import org.opends.server.admin.PropertyProvider;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.admin.std.client.ReplicationDomainCfgClient;
import org.opends.server.admin.std.meta.ReplicationDomainCfgDefn.IsolationPolicy;
import org.opends.server.admin.std.server.ReplicationDomainCfg;
@@ -174,8 +175,7 @@
  /**
   * {@inheritDoc}
   */
  public PropertyProvider properties()
  {
  public ServerManagedObject<? extends Configuration> managedObject() {
    return null;
  }
opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/ReplServerFakeConfiguration.java
@@ -28,9 +28,10 @@
import java.util.SortedSet;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.ManagedObjectDefinition;
import org.opends.server.admin.PropertyProvider;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.admin.std.client.ReplicationServerCfgClient;
import org.opends.server.admin.std.server.ReplicationServerCfg;
import org.opends.server.types.DN;
@@ -182,8 +183,7 @@
  /**
   * {@inheritDoc}
   */
  public PropertyProvider properties()
  {
  public ServerManagedObject<? extends Configuration> managedObject() {
    return null;
  }