From d615093a25d37e8e03f98158583a901d6c840e86 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Fri, 28 Sep 2007 15:47:50 +0000
Subject: [PATCH] Add support for specifying arbitrary constraints in managed object definitions and use it within the LDAP and JMX connection handlers to enforce their SSL/StartTLS settings. This feature will be re-used for other managed object definitions as the need arises.

---
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/ldap/TestLDAPConnectionHandler.java |    2 
 opendj-sdk/opends/src/server/org/opends/server/admin/PropertyDefinition.java                                         |    6 
 opendj-sdk/opends/resource/admin/metaMO.xsl                                                                          |   23 +
 opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/LDAPConnectionHandlerConfiguration.xml                  |   70 +++++
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java                   |    2 
 opendj-sdk/opends/resource/admin/preprocessor.xsl                                                                    |    8 
 opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java                               |   21 -
 opendj-sdk/opends/src/server/org/opends/server/admin/AggregationPropertyDefinition.java                              |   49 ++-
 opendj-sdk/opends/resource/admin/messagesMO.xsl                                                                      |    9 
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/AggregationTest.java             |   83 ++++--
 opendj-sdk/opends/src/server/org/opends/server/admin/GenericConstraint.java                                          |  223 ++++++++++++++++++
 opendj-sdk/opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java                            |    8 
 opendj-sdk/opends/resource/admin/admin.xsd                                                                           |   43 +++
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/MockConstraint.java              |    2 
 opendj-sdk/opends/resource/admin/property-types/aggregation.xsl                                                      |    2 
 opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java                             |   57 ----
 opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JMXConnectionHandlerConfiguration.xml                   |   13 +
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/MockConstraint.java         |    2 
 opendj-sdk/opends/src/server/org/opends/server/admin/Constraint.java                                                 |   41 +++
 19 files changed, 528 insertions(+), 136 deletions(-)

diff --git a/opendj-sdk/opends/resource/admin/admin.xsd b/opendj-sdk/opends/resource/admin/admin.xsd
index ba3fd5c..679e827 100644
--- a/opendj-sdk/opends/resource/admin/admin.xsd
+++ b/opendj-sdk/opends/resource/admin/admin.xsd
@@ -120,6 +120,49 @@
           </xsd:attribute>
         </xsd:complexType>
       </xsd:element>
+      <xsd:element name="constraint" minOccurs="0"
+        maxOccurs="unbounded">
+        <xsd:annotation>
+          <xsd:documentation>
+            A constraint on the properties of this managed object. A
+            constraint comprises of a condition which must always
+            evaluate to true before a modification is permitted.
+          </xsd:documentation>
+        </xsd:annotation>
+        <xsd:complexType>
+          <xsd:sequence>
+            <xsd:element name="synopsis"
+              type="tns:rich-description-type">
+              <xsd:annotation>
+                <xsd:documentation>
+                  A brief description of this constraint. The
+                  description should describe, preferably in one
+                  sentence, the purpose the condition associated with
+                  this constraint. The synopsis should be suitable for
+                  use in applications such as tool-tips, CLI help, and
+                  the summary description in Javadoc. It is possible to
+                  embed rich content including XHTML markup (this will
+                  only be used where supported).
+                </xsd:documentation>
+              </xsd:annotation>
+            </xsd:element>
+            <xsd:element name="condition">
+              <xsd:annotation>
+                <xsd:documentation>
+                  The condition associated with this constraint. The
+                  condition must evaluate to true before modifications
+                  are permitted.
+                </xsd:documentation>
+              </xsd:annotation>
+              <xsd:complexType>
+                <xsd:sequence>
+                  <xsd:group ref="tns:condition-group" />
+                </xsd:sequence>
+              </xsd:complexType>
+            </xsd:element>
+          </xsd:sequence>
+        </xsd:complexType>
+      </xsd:element>
       <xsd:element name="profile" type="tns:profile-type" minOccurs="0"
         maxOccurs="unbounded">
         <xsd:annotation>
diff --git a/opendj-sdk/opends/resource/admin/messagesMO.xsl b/opendj-sdk/opends/resource/admin/messagesMO.xsl
index 3b08e7b..44efad7 100644
--- a/opendj-sdk/opends/resource/admin/messagesMO.xsl
+++ b/opendj-sdk/opends/resource/admin/messagesMO.xsl
@@ -72,6 +72,15 @@
       </xsl:for-each>
     </xsl:if>
     <!--
+      Process any constraints associated with this managed object definition.
+    -->
+    <xsl:if test="$this/adm:constraint">
+      <xsl:for-each select="$this/adm:constraint">
+        <xsl:value-of
+          select="concat('constraint.', position(), '.synopsis=', normalize-space(adm:synopsis), '&#xa;')" />
+      </xsl:for-each>
+    </xsl:if>
+    <!--
       Process each property definition.
     -->
     <xsl:for-each select="$this-all-properties">
diff --git a/opendj-sdk/opends/resource/admin/metaMO.xsl b/opendj-sdk/opends/resource/admin/metaMO.xsl
index 7a0aa0d..105a87a 100644
--- a/opendj-sdk/opends/resource/admin/metaMO.xsl
+++ b/opendj-sdk/opends/resource/admin/metaMO.xsl
@@ -170,6 +170,25 @@
       <xsl:value-of select="'  }&#xa;'" />
     </xsl:if>
     <!--
+      Register any constraints associated with this managed object definition.
+    -->
+    <xsl:if test="$this/adm:constraint">
+      <xsl:text>&#xa;</xsl:text>
+      <xsl:text>&#xa;</xsl:text>
+      <xsl:text>&#xa;</xsl:text>
+      <xsl:value-of
+        select="'  // Register the constraints associated with this managed object definition.&#xa;'" />
+      <xsl:value-of select="'  static {&#xa;'" />
+      <xsl:for-each select="$this/adm:constraint">
+        <xsl:value-of
+          select="concat('    INSTANCE.registerConstraint(new GenericConstraint(INSTANCE, ', position(), ', ')" />
+        <xsl:apply-templates select="adm:condition/*"
+          mode="compile-condition" />
+        <xsl:value-of select="'));&#xa;'" />
+      </xsl:for-each>
+      <xsl:value-of select="'  }&#xa;'" />
+    </xsl:if>
+    <!--
       Configuration definition singleton getter.
     -->
     <xsl:text>&#xa;</xsl:text>
@@ -1631,6 +1650,10 @@
         <xsl:if test="not(boolean($this/@extends))">
           <import>org.opends.server.admin.TopCfgDefn</import>
         </xsl:if>
+        <xsl:if test="$this/adm:constraint">
+          <import>org.opends.server.admin.GenericConstraint</import>
+          <import>org.opends.server.admin.condition.Conditions</import>
+        </xsl:if>
         <xsl:if
           test="$this-local-properties[@multi-valued='true' or
                                        @read-only='true' or
diff --git a/opendj-sdk/opends/resource/admin/preprocessor.xsl b/opendj-sdk/opends/resource/admin/preprocessor.xsl
index c0ae6f5..a890baa 100644
--- a/opendj-sdk/opends/resource/admin/preprocessor.xsl
+++ b/opendj-sdk/opends/resource/admin/preprocessor.xsl
@@ -182,6 +182,14 @@
         <xsl:with-param name="hierarchy" select="$hierarchy" />
       </xsl:apply-templates>
       <!--
+        Copy constraint elements.
+      -->
+      <xsl:apply-templates select="adm:constraint" mode="pre-process">
+        <xsl:with-param name="moname" select="@name" />
+        <xsl:with-param name="mopackage" select="@package" />
+        <xsl:with-param name="hierarchy" select="$hierarchy" />
+      </xsl:apply-templates>
+      <!--
         Copy profile elements.
       -->
       <xsl:apply-templates select="adm:profile" mode="pre-process">
diff --git a/opendj-sdk/opends/resource/admin/property-types/aggregation.xsl b/opendj-sdk/opends/resource/admin/property-types/aggregation.xsl
index 22d3a33..2bbcac2 100644
--- a/opendj-sdk/opends/resource/admin/property-types/aggregation.xsl
+++ b/opendj-sdk/opends/resource/admin/property-types/aggregation.xsl
@@ -114,7 +114,7 @@
     <xsl:call-template name="name-to-java-constant">
       <xsl:with-param name="value" select="../../@name" />
     </xsl:call-template>
-    <xsl:value-of select="');&#xa;'" />
+    <xsl:value-of select="'.getSourceConstraint());&#xa;'" />
   </xsl:template>
   <!--
     Generate property getter declaration(s).
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JMXConnectionHandlerConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JMXConnectionHandlerConfiguration.xml
index 24a8f75..c468f33 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JMXConnectionHandlerConfiguration.xml
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JMXConnectionHandlerConfiguration.xml
@@ -36,6 +36,19 @@
     is used to interact with clients using the Java Management
     Extensions (JMX) protocol.
   </adm:synopsis>
+  <adm:constraint>
+    <adm:synopsis>
+      A Key Manager Provider must be specified when this
+      <adm:user-friendly-name />
+      is configured to use SSL.
+    </adm:synopsis>
+    <adm:condition>
+      <adm:implies>
+        <adm:contains property="use-ssl" value="true" />
+        <adm:is-present property="key-manager-provider" />
+      </adm:implies>
+    </adm:condition>
+  </adm:constraint>
   <adm:profile name="ldap">
     <ldap:object-class>
       <ldap:name>ds-cfg-jmx-connection-handler</ldap:name>
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/LDAPConnectionHandlerConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/LDAPConnectionHandlerConfiguration.xml
index a46d69c..e516200 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/LDAPConnectionHandlerConfiguration.xml
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/LDAPConnectionHandlerConfiguration.xml
@@ -36,6 +36,76 @@
     is used to interact with clients using LDAP. In particular, it
     provides full support for LDAPv3 and limited support for LDAPv2.
   </adm:synopsis>
+  <adm:constraint>
+    <adm:synopsis>
+      A Key Manager Provider must be specified when this
+      <adm:user-friendly-name />
+      is configured to use SSL.
+    </adm:synopsis>
+    <adm:condition>
+      <adm:implies>
+        <adm:contains property="use-ssl" value="true" />
+        <adm:is-present property="key-manager-provider" />
+      </adm:implies>
+    </adm:condition>
+  </adm:constraint>
+  <adm:constraint>
+    <adm:synopsis>
+      A Key Manager Provider must be specified when this
+      <adm:user-friendly-name />
+      is configured to allow StartTLS.
+    </adm:synopsis>
+    <adm:condition>
+      <adm:implies>
+        <adm:contains property="allow-start-tls" value="true" />
+        <adm:is-present property="key-manager-provider" />
+      </adm:implies>
+    </adm:condition>
+  </adm:constraint>
+  <adm:constraint>
+    <adm:synopsis>
+      A Trust Manager Provider must be specified when this
+      <adm:user-friendly-name />
+      is configured to use SSL.
+    </adm:synopsis>
+    <adm:condition>
+      <adm:implies>
+        <adm:contains property="use-ssl" value="true" />
+        <adm:is-present property="trust-manager-provider" />
+      </adm:implies>
+    </adm:condition>
+  </adm:constraint>
+  <adm:constraint>
+    <adm:synopsis>
+      A Trust Manager Provider must be specified when this
+      <adm:user-friendly-name />
+      is configured to allow StartTLS.
+    </adm:synopsis>
+    <adm:condition>
+      <adm:implies>
+        <adm:contains property="allow-start-tls" value="true" />
+        <adm:is-present property="trust-manager-provider" />
+      </adm:implies>
+    </adm:condition>
+  </adm:constraint>
+  <adm:constraint>
+    <adm:synopsis>
+      A
+      <adm:user-friendly-name />
+      cannot be configured to support SSL and StartTLS at the same time.
+      Either SSL or StartTLS must be disabled in order for this
+      <adm:user-friendly-name />
+      to be used.
+    </adm:synopsis>
+    <adm:condition>
+      <adm:not>
+        <adm:and>
+          <adm:contains property="use-ssl" value="true" />
+          <adm:contains property="allow-start-tls" value="true" />
+        </adm:and>
+      </adm:not>
+    </adm:condition>
+  </adm:constraint>
   <adm:profile name="ldap">
     <ldap:object-class>
       <ldap:name>ds-cfg-ldap-connection-handler</ldap:name>
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java b/opendj-sdk/opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java
index 846bb70..da3bc07 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/AbstractManagedObjectDefinition.java
@@ -752,6 +752,10 @@
       pd.initialize();
       pd.getDefaultBehaviorProvider().initialize();
     }
+
+    for (Constraint constraint : getAllConstraints()) {
+      constraint.initialize();
+    }
   }
 
 
@@ -830,7 +834,9 @@
    *          The constraint to be deregistered.
    */
   final void deregisterConstraint(Constraint constraint) {
-    constraints.remove(constraint);
+    if (!constraints.remove(constraint)) {
+      throw new RuntimeException("Failed to deregister a constraint");
+    }
   }
 
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/AggregationPropertyDefinition.java b/opendj-sdk/opends/src/server/org/opends/server/admin/AggregationPropertyDefinition.java
index b0a23b8..d93c0ac 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/AggregationPropertyDefinition.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/AggregationPropertyDefinition.java
@@ -108,7 +108,7 @@
  */
 public final class AggregationPropertyDefinition
     <C extends ConfigurationClient, S extends Configuration>
-    extends PropertyDefinition<String> implements Constraint {
+    extends PropertyDefinition<String> {
 
   /**
    * An interface for incrementally constructing aggregation property
@@ -910,6 +910,9 @@
   // aggregated managed objects.
   private InstantiableRelationDefinition<C, S> relationDefinition;
 
+  // The source constraint.
+  private final Constraint sourceConstraint;
+
   // The condition which is used to determine if a referenced managed
   // object is enabled.
   private final Condition targetIsEnabledCondition;
@@ -933,6 +936,26 @@
     this.rdName = rdName;
     this.targetNeedsEnablingCondition = targetNeedsEnablingCondition;
     this.targetIsEnabledCondition = targetIsEnabledCondition;
+    this.sourceConstraint = new Constraint() {
+
+      /**
+       * {@inheritDoc}
+       */
+      public Collection<ClientConstraintHandler> getClientConstraintHandlers() {
+        ClientConstraintHandler handler = new SourceClientHandler();
+        return Collections.singleton(handler);
+      }
+
+
+
+      /**
+       * {@inheritDoc}
+       */
+      public Collection<ServerConstraintHandler> getServerConstraintHandlers() {
+        ServerConstraintHandler handler = new ServerHandler();
+        return Collections.singleton(handler);
+      }
+    };
   }
 
 
@@ -1008,16 +1031,6 @@
 
 
   /**
-   * {@inheritDoc}
-   */
-  public Collection<ClientConstraintHandler> getClientConstraintHandlers() {
-    ClientConstraintHandler handler = new SourceClientHandler();
-    return Collections.singleton(handler);
-  }
-
-
-
-  /**
    * Gets the name of the managed object which is the parent of the
    * aggregated managed objects.
    *
@@ -1044,11 +1057,14 @@
 
 
   /**
-   * {@inheritDoc}
+   * Gets the constraint which should be enforced on the aggregating
+   * managed object.
+   *
+   * @return Returns the constraint which should be enforced on the
+   *         aggregating managed object.
    */
-  public Collection<ServerConstraintHandler> getServerConstraintHandlers() {
-    ServerConstraintHandler handler = new ServerHandler();
-    return Collections.singleton(handler);
+  public Constraint getSourceConstraint() {
+    return sourceConstraint;
   }
 
 
@@ -1137,7 +1153,7 @@
    */
   @SuppressWarnings("unchecked")
   @Override
-  protected void initialize() throws Exception {
+  public void initialize() throws Exception {
     // Decode the path.
     parentPath = ManagedObjectPath.valueOf(parentPathString);
 
@@ -1172,7 +1188,6 @@
       public Collection<ServerConstraintHandler> getServerConstraintHandlers() {
         return Collections.emptyList();
       }
-
     };
 
     rd.getChildDefinition().registerConstraint(constraint);
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/Constraint.java b/opendj-sdk/opends/src/server/org/opends/server/admin/Constraint.java
index be8e4ca..c23af74 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/Constraint.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/Constraint.java
@@ -29,6 +29,7 @@
 
 
 import java.util.Collection;
+import java.util.Collections;
 
 import org.opends.server.admin.client.ClientConstraintHandler;
 import org.opends.server.admin.server.ServerConstraintHandler;
@@ -60,11 +61,22 @@
  * new managed object is created, changes to a managed object are
  * applied, or an existing managed object is deleted.
  */
-public interface Constraint {
+public abstract class Constraint {
+
+  /**
+   * Creates a new constraint.
+   */
+  protected Constraint() {
+    // No implementation required.
+  }
+
+
 
   /**
    * Gets the client-side constraint handlers which will be used to
-   * enforce this constraint in client applications.
+   * enforce this constraint in client applications. The default
+   * implementation is to return an empty set of client constraint
+   * handlers.
    *
    * @return Returns the client-side constraint handlers which will be
    *         used to enforce this constraint in client applications.
@@ -72,13 +84,17 @@
    *         but maybe empty (indicating that the constraint can only
    *         be enforced on the server-side).
    */
-  Collection<ClientConstraintHandler> getClientConstraintHandlers();
+  public Collection<ClientConstraintHandler> getClientConstraintHandlers() {
+    return Collections.emptySet();
+  }
 
 
 
   /**
    * Gets the server-side constraint handlers which will be used to
-   * enforce this constraint within the server.
+   * enforce this constraint within the server. The default
+   * implementation is to return an empty set of server constraint
+   * handlers.
    *
    * @return Returns the server-side constraint handlers which will be
    *         used to enforce this constraint within the server. The
@@ -86,6 +102,21 @@
    *         must not be empty, since constraints must always be
    *         enforced on the server.
    */
-  Collection<ServerConstraintHandler> getServerConstraintHandlers();
+  public Collection<ServerConstraintHandler> getServerConstraintHandlers() {
+    return Collections.emptySet();
+  }
+
+
+
+  /**
+   * Initializes this constraint. The default implementation is to do
+   * nothing.
+   *
+   * @throws Exception
+   *           If this constraint could not be initialized.
+   */
+  protected void initialize() throws Exception {
+    // Default implementation is to do nothing.
+  }
 
 }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/GenericConstraint.java b/opendj-sdk/opends/src/server/org/opends/server/admin/GenericConstraint.java
new file mode 100644
index 0000000..74f1fb8
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/GenericConstraint.java
@@ -0,0 +1,223 @@
+/*
+ * 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;
+
+
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Locale;
+
+import org.opends.messages.Message;
+import org.opends.server.admin.client.AuthorizationException;
+import org.opends.server.admin.client.ClientConstraintHandler;
+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.condition.Condition;
+import org.opends.server.admin.server.ServerConstraintHandler;
+import org.opends.server.admin.server.ServerManagedObject;
+import org.opends.server.config.ConfigException;
+
+
+
+/**
+ * A generic constraint which comprises of an underlying condition and
+ * a description. The condition must evaluate to <code>true</code>
+ * in order for a new managed object to be created or modified.
+ */
+public class GenericConstraint extends Constraint {
+
+  /**
+   * The client-side constraint handler.
+   */
+  private class ClientHandler extends ClientConstraintHandler {
+
+    // Private constructor.
+    private ClientHandler() {
+      // No implementation required.
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isAddAcceptable(ManagementContext context,
+        ManagedObject<?> managedObject, Collection<Message> unacceptableReasons)
+        throws AuthorizationException, CommunicationException {
+      if (!condition.evaluate(context, managedObject)) {
+        unacceptableReasons.add(getSynopsis());
+        return false;
+      } else {
+        return true;
+      }
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isModifyAcceptable(ManagementContext context,
+        ManagedObject<?> managedObject, Collection<Message> unacceptableReasons)
+        throws AuthorizationException, CommunicationException {
+      if (!condition.evaluate(context, managedObject)) {
+        unacceptableReasons.add(getSynopsis());
+        return false;
+      } else {
+        return true;
+      }
+    }
+
+  };
+
+
+
+  /**
+   * The server-side constraint handler.
+   */
+  private class ServerHandler extends ServerConstraintHandler {
+
+    // Private constructor.
+    private ServerHandler() {
+      // No implementation required.
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isUsable(ServerManagedObject<?> managedObject,
+        Collection<Message> unacceptableReasons) throws ConfigException {
+      if (!condition.evaluate(managedObject)) {
+        unacceptableReasons.add(getSynopsis());
+        return false;
+      } else {
+        return true;
+      }
+    }
+
+  };
+
+  // The client-side constraint handler.
+  private final ClientConstraintHandler clientHandler = new ClientHandler();
+
+  // The condition associated with this constraint.
+  private final Condition condition;
+
+  // The managed object definition associated with this constraint.
+  private final AbstractManagedObjectDefinition<?, ?> definition;
+
+  // The constraint ID.
+  private final int id;
+
+  // The server-side constraint handler.
+  private final ServerConstraintHandler serverHandler = new ServerHandler();
+
+
+
+  /**
+   * Creates a new generic constraint.
+   *
+   * @param definition
+   *          The managed object definition associated with this
+   *          constraint.
+   * @param id
+   *          The constraint ID.
+   * @param condition
+   *          The condition associated with this constraint.
+   */
+  public GenericConstraint(AbstractManagedObjectDefinition<?, ?> definition,
+      int id, Condition condition) {
+    this.definition = definition;
+    this.id = id;
+    this.condition = condition;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Collection<ClientConstraintHandler> getClientConstraintHandlers() {
+    return Collections.singleton(clientHandler);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Collection<ServerConstraintHandler> getServerConstraintHandlers() {
+    return Collections.singleton(serverHandler);
+  }
+
+
+
+  /**
+   * Gets the synopsis of this constraint in the default locale.
+   *
+   * @return Returns the synopsis of this constraint in the default
+   *         locale.
+   */
+  public final Message getSynopsis() {
+    return getSynopsis(Locale.getDefault());
+  }
+
+
+
+  /**
+   * Gets the synopsis of this constraint in the specified locale.
+   *
+   * @param locale
+   *          The locale.
+   * @return Returns the synopsis of this constraint in the specified
+   *         locale.
+   */
+  public final Message getSynopsis(Locale locale) {
+    ManagedObjectDefinitionI18NResource resource =
+      ManagedObjectDefinitionI18NResource.getInstance();
+    String property = "constraint." + id + ".synopsis";
+    return resource.getMessage(definition, property, locale);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected void initialize() throws Exception {
+    condition.initialize(definition);
+  }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/PropertyDefinition.java b/opendj-sdk/opends/src/server/org/opends/server/admin/PropertyDefinition.java
index dec0715..e1d53f5 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/PropertyDefinition.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/PropertyDefinition.java
@@ -549,11 +549,7 @@
     ManagedObjectDefinitionI18NResource resource =
       ManagedObjectDefinitionI18NResource.getInstance();
     String property = "property." + propertyName + ".synopsis";
-    try {
-      return resource.getMessage(definition, property, locale);
-    } catch (MissingResourceException e) {
-      return null;
-    }
+    return resource.getMessage(definition, property, locale);
   }
 
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java b/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java
index 568be6a..6ac3305 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/protocols/jmx/JmxConnectionHandler.java
@@ -323,15 +323,6 @@
   public void initializeConnectionHandler(JMXConnectionHandlerCfg config)
          throws ConfigException, InitializationException
   {
-    // Issue warning if there is not key manager by SSL is enabled.
-    if (config.isUseSSL() && config.getKeyManagerProvider() == null) {
-      // TODO: give a more useful feedback message.
-      Message message = ERR_JMX_CONNHANDLER_CANNOT_DETERMINE_USE_SSL.get(
-          String.valueOf(currentConfig.dn()), "");
-      logError(message);
-      throw new ConfigException(message);
-    }
-
     // Configuration is ok.
     currentConfig = config;
 
@@ -426,16 +417,8 @@
   public boolean isConfigurationChangeAcceptable(
       JMXConnectionHandlerCfg config,
       List<Message> unacceptableReasons) {
-    boolean isAcceptable = true;
-
-    if (config.isUseSSL() && config.getKeyManagerProvider() == null) {
-      // TODO: give a more useful feedback message.
-      unacceptableReasons.add(ERR_JMX_CONNHANDLER_CANNOT_DETERMINE_USE_SSL.get(
-              String.valueOf(config.dn()), ""));
-      isAcceptable = false;
-    }
-
-    return isAcceptable;
+    // All validation is performed by the admin framework.
+    return true;
   }
 
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java b/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
index d52f5f6..20d188e 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
@@ -590,30 +590,6 @@
   public void initializeConnectionHandler(LDAPConnectionHandlerCfg config)
          throws ConfigException, InitializationException
   {
-    // SSL and StartTLS are mutually exclusive.
-    if (config.isAllowStartTLS() && config.isUseSSL()) {
-      Message message = ERR_LDAP_CONNHANDLER_CANNOT_HAVE_SSL_AND_STARTTLS.get(
-          String.valueOf(config.dn()));
-      logError(message);
-    }
-
-    if (config.isAllowStartTLS() || config.isUseSSL())
-    {
-      // Validate the key manager provider.
-      if (config.getKeyManagerProvider() == null) {
-        Message message = ERR_LDAP_CONNHANDLER_NO_KEYMANAGER_DN.get(
-            String.valueOf(config.dn()));
-        throw new ConfigException(message);
-      }
-
-      // Validate the trust manager provider.
-      if (config.getTrustManagerProvider() == null) {
-        Message message = ERR_LDAP_CONNHANDLER_NO_TRUSTMANAGER_DN.get(
-            String.valueOf(config.dn()));
-        throw new ConfigException(message);
-      }
-    }
-
     // Open the selector.
     try {
       selector = Selector.open();
@@ -793,37 +769,8 @@
   public boolean isConfigurationChangeAcceptable(
       LDAPConnectionHandlerCfg config,
       List<Message> unacceptableReasons) {
-    boolean isAcceptable = true;
-
-    // SSL and StartTLS are mutually exclusive.
-    if (config.isAllowStartTLS() && config.isUseSSL()) {
-
-      unacceptableReasons.add(
-              ERR_LDAP_CONNHANDLER_CANNOT_HAVE_SSL_AND_STARTTLS.get(
-                      String.valueOf(config.dn())));
-      isAcceptable = false;
-    }
-
-    if (config.isAllowStartTLS() || config.isUseSSL())
-    {
-      // Validate the key manager provider.
-      if (config.getKeyManagerProvider() == null) {
-        Message message = ERR_LDAP_CONNHANDLER_NO_KEYMANAGER_DN.get(
-                String.valueOf(config.dn()));
-        unacceptableReasons.add(message);
-        isAcceptable = false;
-      }
-
-      // Validate the trust manager provider DN.
-      if (config.getTrustManagerProvider() == null) {
-        Message message = ERR_LDAP_CONNHANDLER_NO_TRUSTMANAGER_DN.get(
-                String.valueOf(config.dn()));
-        unacceptableReasons.add(message);
-        isAcceptable = false;
-      }
-    }
-
-    return isAcceptable;
+    // All validation is performed by the admin framework.
+    return true;
   }
 
 
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java
index 24c8f74..a073a5b 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java
@@ -116,7 +116,7 @@
       builder.setRelationDefinition("connection-handler");
       PD_AGGREGATION_PROPERTY = builder.getInstance();
       INSTANCE.registerPropertyDefinition(PD_AGGREGATION_PROPERTY);
-      INSTANCE.registerConstraint(PD_AGGREGATION_PROPERTY);
+      INSTANCE.registerConstraint(PD_AGGREGATION_PROPERTY.getSourceConstraint());
   }
 
 
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/MockConstraint.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/MockConstraint.java
index a0c6033..238b3c0 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/MockConstraint.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/MockConstraint.java
@@ -47,7 +47,7 @@
  * A mock constraint which can be configured to refuse various types
  * of operation.
  */
-public final class MockConstraint implements Constraint {
+public final class MockConstraint extends Constraint {
 
   /**
    * Mock client constraint handler.
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/AggregationTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/AggregationTest.java
index f156ea0..629c525 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/AggregationTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/AggregationTest.java
@@ -309,7 +309,8 @@
     builder.setRelationDefinition("connection-handler");
     builder.setTargetIsEnabledCondition(Conditions.contains("enabled", "true"));
     aggregationPropertyDefinitionTargetMustBeEnabled = builder.getInstance();
-    TestCfg.initializePropertyDefinition(aggregationPropertyDefinitionTargetMustBeEnabled);
+    TestCfg
+        .initializePropertyDefinition(aggregationPropertyDefinitionTargetMustBeEnabled);
 
     builder = AggregationPropertyDefinition.createBuilder(d,
         "aggregation-property");
@@ -321,10 +322,12 @@
     builder.setParentPath("/");
     builder.setRelationDefinition("connection-handler");
     builder.setTargetIsEnabledCondition(Conditions.contains("enabled", "true"));
-    builder.setTargetNeedsEnablingCondition(Conditions.contains("mandatory-boolean-property", "true"));
+    builder.setTargetNeedsEnablingCondition(Conditions.contains(
+        "mandatory-boolean-property", "true"));
     aggregationPropertyDefinitionTargetAndSourceMustBeEnabled = builder
         .getInstance();
-    TestCfg.initializePropertyDefinition(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled);
+    TestCfg
+        .initializePropertyDefinition(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled);
   }
 
 
@@ -452,10 +455,12 @@
     }
 
     // Register the temporary aggregation definition.
-    TestCfg.removeConstraint(aggregationPropertyDefinitionDefault);
+    TestCfg.removeConstraint(aggregationPropertyDefinitionDefault
+        .getSourceConstraint());
     TestCfg
         .addPropertyDefinition(aggregationPropertyDefinitionTargetMustBeEnabled);
-    TestCfg.addConstraint(aggregationPropertyDefinitionTargetMustBeEnabled);
+    TestCfg.addConstraint(aggregationPropertyDefinitionTargetMustBeEnabled
+        .getSourceConstraint());
 
     try {
       TestParentCfg parent = getParent("test parent 1");
@@ -475,10 +480,11 @@
       }
     } finally {
       // Put back the default aggregation definition.
-      TestCfg
-          .removeConstraint(aggregationPropertyDefinitionTargetMustBeEnabled);
+      TestCfg.removeConstraint(aggregationPropertyDefinitionTargetMustBeEnabled
+          .getSourceConstraint());
       TestCfg.addPropertyDefinition(aggregationPropertyDefinitionDefault);
-      TestCfg.addConstraint(aggregationPropertyDefinitionDefault);
+      TestCfg.addConstraint(aggregationPropertyDefinitionDefault
+          .getSourceConstraint());
 
       try {
         deleteSubtree(TEST_CHILD_6_DN);
@@ -510,10 +516,12 @@
     }
 
     // Register the temporary aggregation definition.
-    TestCfg.removeConstraint(aggregationPropertyDefinitionDefault);
+    TestCfg.removeConstraint(aggregationPropertyDefinitionDefault
+        .getSourceConstraint());
     TestCfg
         .addPropertyDefinition(aggregationPropertyDefinitionTargetMustBeEnabled);
-    TestCfg.addConstraint(aggregationPropertyDefinitionTargetMustBeEnabled);
+    TestCfg.addConstraint(aggregationPropertyDefinitionTargetMustBeEnabled
+        .getSourceConstraint());
 
     try {
       TestParentCfg parent = getParent("test parent 1");
@@ -533,10 +541,11 @@
       }
     } finally {
       // Put back the default aggregation definition.
-      TestCfg
-          .removeConstraint(aggregationPropertyDefinitionTargetMustBeEnabled);
+      TestCfg.removeConstraint(aggregationPropertyDefinitionTargetMustBeEnabled
+          .getSourceConstraint());
       TestCfg.addPropertyDefinition(aggregationPropertyDefinitionDefault);
-      TestCfg.addConstraint(aggregationPropertyDefinitionDefault);
+      TestCfg.addConstraint(aggregationPropertyDefinitionDefault
+          .getSourceConstraint());
 
       try {
         deleteSubtree(TEST_CHILD_7_DN);
@@ -569,11 +578,13 @@
     }
 
     // Register the temporary aggregation definition.
-    TestCfg.removeConstraint(aggregationPropertyDefinitionDefault);
+    TestCfg.removeConstraint(aggregationPropertyDefinitionDefault
+        .getSourceConstraint());
     TestCfg
         .addPropertyDefinition(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled);
     TestCfg
-        .addConstraint(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled);
+        .addConstraint(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled
+            .getSourceConstraint());
 
     try {
       TestParentCfg parent = getParent("test parent 1");
@@ -594,9 +605,11 @@
     } finally {
       // Put back the default aggregation definition.
       TestCfg
-          .removeConstraint(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled);
+          .removeConstraint(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled
+              .getSourceConstraint());
       TestCfg.addPropertyDefinition(aggregationPropertyDefinitionDefault);
-      TestCfg.addConstraint(aggregationPropertyDefinitionDefault);
+      TestCfg.addConstraint(aggregationPropertyDefinitionDefault
+          .getSourceConstraint());
 
       try {
         deleteSubtree(TEST_CHILD_6_DN);
@@ -628,11 +641,13 @@
     }
 
     // Register the temporary aggregation definition.
-    TestCfg.removeConstraint(aggregationPropertyDefinitionDefault);
+    TestCfg.removeConstraint(aggregationPropertyDefinitionDefault
+        .getSourceConstraint());
     TestCfg
         .addPropertyDefinition(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled);
     TestCfg
-        .addConstraint(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled);
+        .addConstraint(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled
+            .getSourceConstraint());
 
     try {
       TestParentCfg parent = getParent("test parent 1");
@@ -640,9 +655,11 @@
     } finally {
       // Put back the default aggregation definition.
       TestCfg
-          .removeConstraint(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled);
+          .removeConstraint(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled
+              .getSourceConstraint());
       TestCfg.addPropertyDefinition(aggregationPropertyDefinitionDefault);
-      TestCfg.addConstraint(aggregationPropertyDefinitionDefault);
+      TestCfg.addConstraint(aggregationPropertyDefinitionDefault
+          .getSourceConstraint());
 
       try {
         deleteSubtree(TEST_CHILD_7_DN);
@@ -740,10 +757,12 @@
     }
 
     // Register the temporary aggregation definition.
-    TestCfg.removeConstraint(aggregationPropertyDefinitionDefault);
+    TestCfg.removeConstraint(aggregationPropertyDefinitionDefault
+        .getSourceConstraint());
     TestCfg
         .addPropertyDefinition(aggregationPropertyDefinitionTargetMustBeEnabled);
-    TestCfg.addConstraint(aggregationPropertyDefinitionTargetMustBeEnabled);
+    TestCfg.addConstraint(aggregationPropertyDefinitionTargetMustBeEnabled
+        .getSourceConstraint());
 
     ConfigurationDeleteListener<TestChildCfg> dl = new DummyDeleteListener();
     ConfigurationChangeListener<TestChildCfg> cl = new DummyChangeListener();
@@ -780,9 +799,11 @@
 
           // Put back the default aggregation definition.
           TestCfg
-              .removeConstraint(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled);
+              .removeConstraint(aggregationPropertyDefinitionTargetMustBeEnabled
+                  .getSourceConstraint());
           TestCfg.addPropertyDefinition(aggregationPropertyDefinitionDefault);
-          TestCfg.addConstraint(aggregationPropertyDefinitionDefault);
+          TestCfg.addConstraint(aggregationPropertyDefinitionDefault
+              .getSourceConstraint());
         }
       }
     }
@@ -810,10 +831,12 @@
     }
 
     // Register the temporary aggregation definition.
-    TestCfg.removeConstraint(aggregationPropertyDefinitionDefault);
+    TestCfg.removeConstraint(aggregationPropertyDefinitionDefault
+        .getSourceConstraint());
     TestCfg
         .addPropertyDefinition(aggregationPropertyDefinitionTargetMustBeEnabled);
-    TestCfg.addConstraint(aggregationPropertyDefinitionTargetMustBeEnabled);
+    TestCfg.addConstraint(aggregationPropertyDefinitionTargetMustBeEnabled
+        .getSourceConstraint());
 
     ConfigurationDeleteListener<TestChildCfg> dl = new DummyDeleteListener();
     ConfigurationChangeListener<TestChildCfg> cl = new DummyChangeListener();
@@ -852,9 +875,11 @@
 
           // Put back the default aggregation definition.
           TestCfg
-              .removeConstraint(aggregationPropertyDefinitionTargetAndSourceMustBeEnabled);
+              .removeConstraint(aggregationPropertyDefinitionTargetMustBeEnabled
+                  .getSourceConstraint());
           TestCfg.addPropertyDefinition(aggregationPropertyDefinitionDefault);
-          TestCfg.addConstraint(aggregationPropertyDefinitionDefault);
+          TestCfg.addConstraint(aggregationPropertyDefinitionDefault
+              .getSourceConstraint());
         }
       }
     }
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/MockConstraint.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/MockConstraint.java
index 77c594d..a838ec9 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/MockConstraint.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/server/MockConstraint.java
@@ -46,7 +46,7 @@
  * A mock constraint which can be configured to refuse various types
  * of operation.
  */
-public final class MockConstraint implements Constraint {
+public final class MockConstraint extends Constraint {
 
   /**
    * Mock server constraint handler.
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/ldap/TestLDAPConnectionHandler.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/ldap/TestLDAPConnectionHandler.java
index d7e0b01..5d8ecb9 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/ldap/TestLDAPConnectionHandler.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/ldap/TestLDAPConnectionHandler.java
@@ -127,7 +127,7 @@
     LDAPHandlerEntry.removeAttribute(useSSL, null);
     LDAPHandlerEntry.removeAttribute(startTls, null);
     Attribute useSSL1=new Attribute(ATTR_USE_SSL, String.valueOf(true));
-    Attribute startTls1=new Attribute(ATTR_ALLOW_STARTTLS, String.valueOf(true));
+    Attribute startTls1=new Attribute(ATTR_ALLOW_STARTTLS, String.valueOf(false));
     LDAPHandlerEntry.addAttribute(useSSL1,null);
     LDAPHandlerEntry.addAttribute(startTls1,null);
     LDAPConnectionHandler LDAPSConnHandler = getLDAPHandlerInstance(LDAPHandlerEntry);

--
Gitblit v1.10.0