From fe6545499558bb95484defd311ed83eced6aedf4 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Thu, 19 Jul 2007 14:54:30 +0000
Subject: [PATCH] Fix issues 1943 (unable to create je-index), 1996 (exception when creating components with empty names), and 1998 (exception when creating components with blank names).
---
opendj-sdk/opends/resource/admin/metaMO.xsl | 28 +
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JEBackendConfiguration.xml | 5
opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java | 72 ++++-
opendj-sdk/opends/resource/admin/admin-ldap.xsd | 4
opendj-sdk/opends/resource/admin/ldapMOProfile.xsl | 16 +
opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/GetPropSubCommandHandler.java | 2
opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/ArgumentExceptionFactory.java | 67 ++++
opendj-sdk/opends/src/server/org/opends/server/admin/InstantiableRelationDefinition.java | 57 +++-
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java | 5
opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/CreateSubCommandHandler.java | 36 ++
opendj-sdk/opends/resource/admin/preprocessor.xsl | 54 +++
opendj-sdk/opends/src/server/org/opends/server/admin/ManagedObjectPath.java | 33 ++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java | 3
opendj-sdk/opends/resource/admin/clientMO.xsl | 11
opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/DeleteSubCommandHandler.java | 2
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/MockLDAPProfile.java | 2
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/BackendConfiguration.xml | 14
opendj-sdk/opends/src/server/org/opends/server/admin/client/IllegalManagedObjectNameException.java | 142 ++++++++++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/LDAPClientTest.java | 3
opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/ListSubCommandHandler.java | 2
opendj-sdk/opends/resource/admin/admin.xsd | 15 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgClient.java | 5
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml | 3
opendj-sdk/opends/src/server/org/opends/server/admin/LDAPProfile.java | 22 +
opendj-sdk/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java | 86 ++++-
opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SetPropSubCommandHandler.java | 2
opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java | 107 +++++++
opendj-sdk/opends/src/server/org/opends/server/admin/client/ManagedObject.java | 4
28 files changed, 700 insertions(+), 102 deletions(-)
diff --git a/opendj-sdk/opends/resource/admin/admin-ldap.xsd b/opendj-sdk/opends/resource/admin/admin-ldap.xsd
index 59e4264..4ebf60d 100644
--- a/opendj-sdk/opends/resource/admin/admin-ldap.xsd
+++ b/opendj-sdk/opends/resource/admin/admin-ldap.xsd
@@ -97,7 +97,9 @@
<xsd:documentation>
Defines which LDAP attribute should be used to name child
managed objects referenced by a relation. When not specified,
- "cn" is used by default.
+ "cn" is used by default. When the relation uses a naming
+ property this element is not required, instead the LDAP
+ attribute associated with the naming property will be used.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
diff --git a/opendj-sdk/opends/resource/admin/admin.xsd b/opendj-sdk/opends/resource/admin/admin.xsd
index a97b475..b4144a7 100644
--- a/opendj-sdk/opends/resource/admin/admin.xsd
+++ b/opendj-sdk/opends/resource/admin/admin.xsd
@@ -593,6 +593,21 @@
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
+ <xsd:attribute name="naming-property" type="tns:name-type"
+ use="optional">
+ <xsd:annotation>
+ <xsd:documentation>
+ Specifies the name of a property in the referenced
+ managed object which should be used for naming
+ instances. For example, an attribute index managed
+ object could be named according to the attribute that
+ it indexes. If present, the naming property must
+ reference a single-valued, mandatory, read-only
+ property. If it is not present, the administration
+ framework will use the default naming mechanism.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:choice>
diff --git a/opendj-sdk/opends/resource/admin/clientMO.xsl b/opendj-sdk/opends/resource/admin/clientMO.xsl
index 2e6197e..c4d166a 100644
--- a/opendj-sdk/opends/resource/admin/clientMO.xsl
+++ b/opendj-sdk/opends/resource/admin/clientMO.xsl
@@ -306,11 +306,13 @@
'{@link DefaultBehaviorException}s that occurred whilst ',
'attempting to determine the default values of the ', $ufn,
'. This argument can be <code>null<code>.
',
- '@return Returns a new ', $ufn,' configuration instance.
')" />
+ '@return Returns a new ', $ufn,' configuration instance.
',
+ '@throws IllegalManagedObjectNameException
',
+ ' If the name of the new ', $ufn,' is invalid.
')" />
</xsl:call-template>
<xsl:value-of
select="concat(' <C extends ', $java-class-name,'CfgClient> C create', $java-relation-name, '(
',
- ' ManagedObjectDefinition<C, ?> d, String name, Collection<DefaultBehaviorException> exceptions);
')" />
+ ' ManagedObjectDefinition<C, ?> d, String name, Collection<DefaultBehaviorException> exceptions) throws IllegalManagedObjectNameException;
')" />
<xsl:text>
</xsl:text>
<xsl:text>
</xsl:text>
<xsl:text>
</xsl:text>
@@ -404,6 +406,11 @@
org.opends.server.admin.client.OperationRejectedException
</import>
</xsl:if>
+ <xsl:if test="$this-local-relations/adm:one-to-many">
+ <import>
+ org.opends.server.admin.client.IllegalManagedObjectNameException
+ </import>
+ </xsl:if>
<xsl:choose>
<xsl:when test="$this/@extends">
<xsl:if test="$parent-package != $this-package">
diff --git a/opendj-sdk/opends/resource/admin/ldapMOProfile.xsl b/opendj-sdk/opends/resource/admin/ldapMOProfile.xsl
index 60c8d08..ea0973a 100644
--- a/opendj-sdk/opends/resource/admin/ldapMOProfile.xsl
+++ b/opendj-sdk/opends/resource/admin/ldapMOProfile.xsl
@@ -80,6 +80,22 @@
<xsl:choose>
<xsl:when
test="adm:profile[@name='ldap']/ldap:naming-attribute">
+ <xsl:if test="not(adm:one-to-many)">
+ <xsl:message terminate="yes">
+ <xsl:value-of
+ select="concat('Naming attribute specified for relation ',
+ @name, ' in managed object definition ',
+ $this-name, ' which is not a one-to-many relation.')" />
+ </xsl:message>
+ </xsl:if>
+ <xsl:if test="adm:one-to-many/@naming-property">
+ <xsl:message terminate="yes">
+ <xsl:value-of
+ select="concat('Naming attribute specified for one-to-many relation ',
+ @name, ' in managed object definition ',
+ $this-name, ' which uses a naming property.')" />
+ </xsl:message>
+ </xsl:if>
<xsl:value-of
select="concat('naming-attribute.',
normalize-space(@name),
diff --git a/opendj-sdk/opends/resource/admin/metaMO.xsl b/opendj-sdk/opends/resource/admin/metaMO.xsl
index c609d89..638fd55 100644
--- a/opendj-sdk/opends/resource/admin/metaMO.xsl
+++ b/opendj-sdk/opends/resource/admin/metaMO.xsl
@@ -822,7 +822,28 @@
select="concat('"', adm:one-to-many/@plural-name, '", ')" />
</xsl:if>
<xsl:value-of
- select="concat($java-managed-object-name, 'CfgDefn.getInstance());
')" />
+ select="concat($java-managed-object-name, 'CfgDefn.getInstance()')" />
+ <xsl:if test="adm:one-to-many">
+ <xsl:value-of select="', '" />
+ <xsl:choose>
+ <xsl:when test="adm:one-to-many/@naming-property">
+ <xsl:variable name="java-property-name">
+ <xsl:call-template name="name-to-java">
+ <xsl:with-param name="value"
+ select="adm:one-to-many/@naming-property" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of
+ select="concat($java-managed-object-name,
+ 'CfgDefn.getInstance().get',
+ $java-property-name, 'PropertyDefinition()')" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'null'" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:value-of select="');
'" />
<xsl:value-of
select="concat(' INSTANCE.registerRelationDefinition(RD_', $java-relation-name,');
')" />
<xsl:value-of select="' }
'" />
@@ -1237,7 +1258,7 @@
' * {@inheritDoc}
',
' */
',
' public <M extends ', $java-class-name, 'CfgClient> M create', $java-relation-name, '(
',
- ' ManagedObjectDefinition<M, ?> d, String name, Collection<DefaultBehaviorException> exceptions) {
',
+ ' ManagedObjectDefinition<M, ?> d, String name, Collection<DefaultBehaviorException> exceptions) throws IllegalManagedObjectNameException {
',
' return impl.createChild(INSTANCE.get', $java-relation-plural-name,'RelationDefinition(), d, name, exceptions).getConfiguration();
',
' }
')" />
<xsl:text>
</xsl:text>
@@ -1793,6 +1814,9 @@
<xsl:if test="$this-all-relations/adm:one-to-many">
<import>java.util.Collection</import>
<import>
+ org.opends.server.admin.client.IllegalManagedObjectNameException
+ </import>
+ <import>
org.opends.server.admin.DefaultBehaviorException
</import>
<import>
diff --git a/opendj-sdk/opends/resource/admin/preprocessor.xsl b/opendj-sdk/opends/resource/admin/preprocessor.xsl
index 9b14b13..dee2c1e 100644
--- a/opendj-sdk/opends/resource/admin/preprocessor.xsl
+++ b/opendj-sdk/opends/resource/admin/preprocessor.xsl
@@ -827,6 +827,60 @@
-->
<xsl:template match="adm:one-to-many" mode="merge-relation">
<xsl:param name="managed-object" select="/.." />
+ <!--
+ Make sure that if this relation uses a naming property that the
+ naming property exists, is single-valued, mandatory, and read-only.
+ -->
+ <xsl:if test="@naming-property">
+ <xsl:variable name="naming-property-name"
+ select="@naming-property" />
+
+ <!--
+ FIXME: this does not cope with the situation where the property
+ is inherited, referenced, or overridden.
+ -->
+ <xsl:variable name="naming-property"
+ select="$managed-object/adm:property[@name=$naming-property-name]" />
+ <xsl:if test="not($naming-property)">
+ <xsl:message terminate="yes">
+ <xsl:value-of
+ select="concat('Relation ', ../@name,
+ ' references an unknown naming property ',
+ $naming-property-name, ' in ',
+ $managed-object/@name, '.')" />
+ </xsl:message>
+ </xsl:if>
+ <xsl:if test="not($naming-property/@read-only='true')">
+ <xsl:message terminate="yes">
+ <xsl:value-of
+ select="concat('Relation ', ../@name,
+ ' references the naming property ',
+ $naming-property-name, ' in ',
+ $managed-object/@name, ' which is not read-only. ',
+ 'Naming properties must be read-only.')" />
+ </xsl:message>
+ </xsl:if>
+ <xsl:if test="not($naming-property/@mandatory='true')">
+ <xsl:message terminate="yes">
+ <xsl:value-of
+ select="concat('Relation ', ../@name,
+ ' references the naming property ',
+ $naming-property-name, ' in ',
+ $managed-object/@name, ' which is not mandatory. ',
+ 'Naming properties must be mandatory.')" />
+ </xsl:message>
+ </xsl:if>
+ <xsl:if test="$naming-property/@multi-valued='true'">
+ <xsl:message terminate="yes">
+ <xsl:value-of
+ select="concat('Relation ', ../@name,
+ ' references the naming property ',
+ $naming-property-name, ' in ',
+ $managed-object/@name, ' which is multi-valued. ',
+ 'Naming properties must be single-valued.')" />
+ </xsl:message>
+ </xsl:if>
+ </xsl:if>
<xsl:copy>
<xsl:copy-of select="@*" />
<!--
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/BackendConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/BackendConfiguration.xml
index 4bf46f8..8dc6d71 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/BackendConfiguration.xml
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/BackendConfiguration.xml
@@ -94,23 +94,15 @@
</ldap:attribute>
</adm:profile>
</adm:property>
- <adm:property name="backend-id"
- mandatory="true"
+ <adm:property name="backend-id" mandatory="true" read-only="true"
multi-valued="false">
<adm:synopsis>
- Provides a name that will be used to identify the associated backend.
+ Provides a name that will be used to identify the associated
+ backend.
</adm:synopsis>
<adm:description>
The name must be unique among all backends in the server.
</adm:description>
- <adm:requires-admin-action>
- <adm:other>
- <adm:synopsis>
- The backend ID may not be altered after the backend is created in
- the server.
- </adm:synopsis>
- </adm:other>
- </adm:requires-admin-action>
<adm:syntax>
<adm:string />
</adm:syntax>
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JEBackendConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JEBackendConfiguration.xml
index 7aefce2..fb9e639 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JEBackendConfiguration.xml
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JEBackendConfiguration.xml
@@ -54,14 +54,11 @@
</ldap:object-class>
</adm:profile>
<adm:relation name="je-index">
- <adm:one-to-many />
+ <adm:one-to-many naming-property="index-attribute"/>
<adm:profile name="ldap">
<ldap:rdn-sequence>
cn=Index
</ldap:rdn-sequence>
- <ldap:naming-attribute>
- ds-cfg-index-attribute
- </ldap:naming-attribute>
</adm:profile>
<adm:profile name="cli">
<cli:relation>
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
index 4885fba..df30b76 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
@@ -230,10 +230,9 @@
</adm:profile>
</adm:relation>
<adm:relation name="backend">
- <adm:one-to-many />
+ <adm:one-to-many naming-property="backend-id"/>
<adm:profile name="ldap">
<ldap:rdn-sequence>cn=Backends,cn=config</ldap:rdn-sequence>
- <ldap:naming-attribute>ds-cfg-backend-id</ldap:naming-attribute>
</adm:profile>
<adm:profile name="cli">
<cli:relation>
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/InstantiableRelationDefinition.java b/opendj-sdk/opends/src/server/org/opends/server/admin/InstantiableRelationDefinition.java
index b5898bf..2035206 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/InstantiableRelationDefinition.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/InstantiableRelationDefinition.java
@@ -27,6 +27,8 @@
package org.opends.server.admin;
+
+
import java.util.Locale;
@@ -46,6 +48,9 @@
<C extends ConfigurationClient, S extends Configuration>
extends RelationDefinition<C, S> {
+ // The optional naming property definition.
+ private final PropertyDefinition<?> namingPropertyDefinition;
+
// The plural name of the relation.
private final String pluralName;
@@ -62,12 +67,43 @@
* The plural name of the relation.
* @param cd
* The child managed object definition.
+ * @param namingPropertyDefinition
+ * The property of the child managed object definition
+ * which should be used for naming, or <code>null</code>
+ * if this relation does not use a property for naming.
*/
public InstantiableRelationDefinition(
AbstractManagedObjectDefinition<?, ?> pd, String name, String pluralName,
- AbstractManagedObjectDefinition<C, S> cd) {
+ AbstractManagedObjectDefinition<C, S> cd,
+ PropertyDefinition<?> namingPropertyDefinition) {
super(pd, name, cd);
this.pluralName = pluralName;
+ this.namingPropertyDefinition = namingPropertyDefinition;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public <R, P> R accept(RelationDefinitionVisitor<R, P> v, P p) {
+ return v.visitInstantiable(this, p);
+ }
+
+
+
+ /**
+ * Get the property of the child managed object definition which
+ * should be used for naming children.
+ *
+ * @return Returns the property of the child managed object
+ * definition which should be used for naming, or
+ * <code>null</code> if this relation does not use a
+ * property for naming.
+ */
+ public final PropertyDefinition<?> getNamingPropertyDefinition() {
+ return namingPropertyDefinition;
}
@@ -106,10 +142,9 @@
* definition in the specified locale.
*/
public final String getUserFriendlyPluralName(Locale locale) {
- String property = "relation." + getName()
- + ".user-friendly-plural-name";
- return ManagedObjectDefinitionI18NResource.getInstance()
- .getMessage(getParentDefinition(), property, locale);
+ String property = "relation." + getName() + ".user-friendly-plural-name";
+ return ManagedObjectDefinitionI18NResource.getInstance().getMessage(
+ getParentDefinition(), property, locale);
}
@@ -125,16 +160,8 @@
builder.append(getParentDefinition().getName());
builder.append(" child=");
builder.append(getChildDefinition().getName());
+ builder.append(" child=");
+ builder.append(getChildDefinition().getName());
builder.append(" minOccurs=0");
}
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public <R, P> R accept(RelationDefinitionVisitor<R, P> v, P p) {
- return v.visitInstantiable(this, p);
- }
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/LDAPProfile.java b/opendj-sdk/opends/src/server/org/opends/server/admin/LDAPProfile.java
index 46e222b..3e2505d 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/LDAPProfile.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/LDAPProfile.java
@@ -83,7 +83,7 @@
* if the property definition is not handled by this LDAP
* profile wrapper.
*/
- public String getAttributeName(ManagedObjectDefinition<?, ?> d,
+ public String getAttributeName(AbstractManagedObjectDefinition<?, ?> d,
PropertyDefinition<?> pd) {
return null;
}
@@ -192,7 +192,7 @@
* If the LDAP profile properties file associated with the
* provided managed object definition could not be loaded.
*/
- public String getAttributeName(ManagedObjectDefinition<?, ?> d,
+ public String getAttributeName(AbstractManagedObjectDefinition<?, ?> d,
PropertyDefinition<?> pd) throws MissingResourceException {
for (Wrapper profile : profiles) {
String attributeName = profile.getAttributeName(d, pd);
@@ -219,14 +219,20 @@
*/
public String getInstantiableRelationChildRDNType(
InstantiableRelationDefinition<?, ?> r) throws MissingResourceException {
- for (Wrapper profile : profiles) {
- String rdnType = profile.getInstantiableRelationChildRDNType(r);
- if (rdnType != null) {
- return rdnType;
+ if (r.getNamingPropertyDefinition() != null) {
+ // Use the attribute associated with the naming property.
+ return getAttributeName(r.getChildDefinition(), r
+ .getNamingPropertyDefinition());
+ } else {
+ for (Wrapper profile : profiles) {
+ String rdnType = profile.getInstantiableRelationChildRDNType(r);
+ if (rdnType != null) {
+ return rdnType;
+ }
}
+ return resource.getString(r.getParentDefinition(), "naming-attribute."
+ + r.getName());
}
- return resource.getString(r.getParentDefinition(), "naming-attribute."
- + r.getName());
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/ManagedObjectPath.java b/opendj-sdk/opends/src/server/org/opends/server/admin/ManagedObjectPath.java
index ced9e0e8..eb164e1 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/ManagedObjectPath.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/ManagedObjectPath.java
@@ -926,6 +926,39 @@
/**
+ * Creates a new managed object path which has the same structure as
+ * this path except that the final path element is renamed. The
+ * final path element must comprise of an instantiable relation.
+ *
+ * @param newName
+ * The new name of the final path element.
+ * @return Returns a new managed object path which has the same
+ * structure as this path except that the final path element
+ * is renamed.
+ * @throws IllegalStateException
+ * If this managed object path is empty or if its final
+ * path element does not comprise of an instantiable
+ * relation.
+ */
+ @SuppressWarnings("unchecked")
+ public ManagedObjectPath<C, S> rename(String newName)
+ throws IllegalStateException {
+ if (elements.size() == 0) {
+ throw new IllegalStateException("Cannot rename an empty path");
+ }
+
+ if (r instanceof InstantiableRelationDefinition) {
+ InstantiableRelationDefinition<? super C, ? super S> ir =
+ (InstantiableRelationDefinition<? super C, ? super S>) r;
+ return parent().child(ir, d, newName);
+ } else {
+ throw new IllegalStateException("Not an instantiable relation");
+ }
+ }
+
+
+
+ /**
* Serialize this managed object path using the provided
* serialization strategy.
* <p>
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/client/IllegalManagedObjectNameException.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/IllegalManagedObjectNameException.java
new file mode 100644
index 0000000..541015e
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/client/IllegalManagedObjectNameException.java
@@ -0,0 +1,142 @@
+/*
+ * 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.client;
+
+
+
+import org.opends.server.admin.IllegalPropertyValueStringException;
+import org.opends.server.admin.OperationsException;
+import org.opends.server.admin.PropertyDefinition;
+import org.opends.server.admin.PropertyDefinitionUsageBuilder;
+
+
+
+/**
+ * Thrown when an attempt is made to create a new managed object with
+ * an illegal name.
+ * <p>
+ * This exception can occur when a new managed object is given a name
+ * which is either an empty string, a string containing just
+ * white-spaces, or a string which is invalid according to the managed
+ * object's naming property (if it has one).
+ */
+public class IllegalManagedObjectNameException extends OperationsException {
+
+ /**
+ * Serialization ID.
+ */
+ private static final long serialVersionUID = 7491748228684293291L;
+
+ // The illegal name.
+ private final String illegalName;
+
+ // The naming property definition if applicable.
+ private final PropertyDefinition<?> namingPropertyDefinition;
+
+
+
+ /**
+ * Create a new illegal name exception and no naming property
+ * definition.
+ *
+ * @param illegalName
+ * The illegal managed object name.
+ */
+ public IllegalManagedObjectNameException(String illegalName) {
+ this(illegalName, null);
+ }
+
+
+
+ /**
+ * Create a new illegal name exception and a naming property
+ * definition.
+ *
+ * @param illegalName
+ * The illegal managed object name.
+ * @param namingPropertyDefinition
+ * The naming property definition.
+ */
+ public IllegalManagedObjectNameException(String illegalName,
+ PropertyDefinition<?> namingPropertyDefinition) {
+ this.illegalName = illegalName;
+ this.namingPropertyDefinition = namingPropertyDefinition;
+ }
+
+
+
+ /**
+ * Get the illegal managed object name.
+ *
+ * @return Returns the illegal managed object name.
+ */
+ public String getIllegalName() {
+ return illegalName;
+ }
+
+
+
+ /**
+ * Get the naming property definition if applicable.
+ *
+ * @return Returns naming property definition, or <code>null</code>
+ * if none was specified.
+ */
+ public PropertyDefinition<?> getNamingPropertyDefinition() {
+ return namingPropertyDefinition;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getMessage() {
+ if (illegalName.length() == 0) {
+ return "Empty managed object names are not permitted";
+ } else if (illegalName.trim().length() == 0) {
+ return "Blank managed object names are not permitted";
+ } else if (namingPropertyDefinition != null) {
+ try {
+ namingPropertyDefinition.decodeValue(illegalName);
+ } catch (IllegalPropertyValueStringException e) {
+ String msg = "The managed object name \"%s\" is not a valid value "
+ + "for the naming property \"%s\", which must have the following "
+ + "syntax: %s";
+ PropertyDefinitionUsageBuilder builder =
+ new PropertyDefinitionUsageBuilder(true);
+ return String.format(msg, illegalName, namingPropertyDefinition
+ .getName(), builder.getUsage(namingPropertyDefinition));
+ }
+ }
+
+ return "The managed object name \"" + illegalName + "\" is not permitted";
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/client/ManagedObject.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/ManagedObject.java
index 857c634..63eaec6 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/client/ManagedObject.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/client/ManagedObject.java
@@ -157,6 +157,8 @@
* values.
* @return Returns a new child managed object bound to the specified
* instantiable relation.
+ * @throws IllegalManagedObjectNameException
+ * If the name of the child managed object is invalid.
* @throws IllegalArgumentException
* If the relation definition is not associated with this
* managed object's definition.
@@ -164,7 +166,7 @@
<M extends ConfigurationClient, N extends M> ManagedObject<N> createChild(
InstantiableRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
String name, Collection<DefaultBehaviorException> exceptions)
- throws IllegalArgumentException;
+ throws IllegalManagedObjectNameException, IllegalArgumentException;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java
index 0cb44f8..0c7630f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java
@@ -83,6 +83,7 @@
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ConcurrentModificationException;
+import org.opends.server.admin.client.IllegalManagedObjectNameException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagedObjectDecodingException;
import org.opends.server.admin.client.MissingMandatoryPropertiesException;
@@ -394,7 +395,8 @@
static ManagedObject<RootCfgClient> getRootManagedObject(
LDAPManagementContext context) {
return new LDAPManagedObject<RootCfgClient>(context, RootCfgDefn
- .getInstance(), ManagedObjectPath.emptyPath(), new PropertySet(), true);
+ .getInstance(), ManagedObjectPath.emptyPath(), new PropertySet(), true,
+ null);
}
@@ -454,8 +456,11 @@
// committed).
private boolean existsOnServer;
+ // Optional naming property definition.
+ private final PropertyDefinition<?> namingPropertyDefinition;
+
// The path associated with this managed object.
- private final ManagedObjectPath<?, ?> path;
+ private ManagedObjectPath<?, ?> path;
// The managed object's properties.
private final PropertySet properties;
@@ -465,12 +470,14 @@
// Create an new LDAP managed object with the provided JNDI context.
private LDAPManagedObject(LDAPManagementContext context,
ManagedObjectDefinition<C, ?> d, ManagedObjectPath path,
- PropertySet properties, boolean existsOnServer) {
+ PropertySet properties, boolean existsOnServer,
+ PropertyDefinition<?> namingPropertyDefinition) {
this.definition = d;
this.context = context;
this.path = path;
this.properties = properties;
this.existsOnServer = existsOnServer;
+ this.namingPropertyDefinition = namingPropertyDefinition;
}
@@ -515,10 +522,27 @@
ManagedObject<N> createChild(
InstantiableRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
String name, Collection<DefaultBehaviorException> exceptions)
- throws IllegalArgumentException {
+ throws IllegalManagedObjectNameException, IllegalArgumentException {
validateRelationDefinition(r);
+
+ // Empty names are not allowed.
+ if (name.trim().length() == 0) {
+ throw new IllegalManagedObjectNameException(name);
+ }
+
+ // If the relation uses a naming property definition then it must
+ // be a valid value.
+ PropertyDefinition<?> pd = r.getNamingPropertyDefinition();
+ if (pd != null) {
+ try {
+ pd.decodeValue(name);
+ } catch (IllegalPropertyValueStringException e) {
+ throw new IllegalManagedObjectNameException(name, pd);
+ }
+ }
+
ManagedObjectPath childPath = path.child(r, name);
- return createNewManagedObject(d, childPath, exceptions);
+ return createNewManagedObject(d, childPath, pd, name, exceptions);
}
@@ -534,7 +558,7 @@
throws IllegalArgumentException {
validateRelationDefinition(r);
ManagedObjectPath childPath = path.child(r);
- return createNewManagedObject(d, childPath, exceptions);
+ return createNewManagedObject(d, childPath, null, null, exceptions);
}
@@ -713,15 +737,11 @@
public <T> void setPropertyValue(PropertyDefinition<T> d, T value)
throws IllegalPropertyValueException, PropertyIsReadOnlyException,
PropertyIsMandatoryException, IllegalArgumentException {
- if (d.hasOption(PropertyOption.MONITORING)) {
- throw new PropertyIsReadOnlyException(d);
+ if (value == null) {
+ setPropertyValues(d, Collections.<T> emptySet());
+ } else {
+ setPropertyValues(d, Collections.singleton(value));
}
-
- if (existsOnServer && d.hasOption(PropertyOption.READ_ONLY)) {
- throw new PropertyIsReadOnlyException(d);
- }
-
- properties.setPropertyValue(d, value);
}
@@ -742,10 +762,15 @@
}
properties.setPropertyValues(d, values);
+
+ // If this is a naming property then update the name.
+ if (d.equals(namingPropertyDefinition)) {
+ // The property must be single-valued and mandatory.
+ String newName = d.encodeValue(values.iterator().next());
+ path = path.rename(newName);
+ }
}
-
-
// Adapts a naming exception to an appropriate admin client
// exception.
private void adaptNamingException(NamingException ne)
@@ -871,9 +896,11 @@
}
attributes.put(oc);
- // Create the naming attribute.
- Rdn rdn = dn.getRdn(dn.size() - 1);
- attributes.put(rdn.getType(), rdn.getValue().toString());
+ // Create the naming attribute if there is not naming property.
+ if (namingPropertyDefinition == null) {
+ Rdn rdn = dn.getRdn(dn.size() - 1);
+ attributes.put(rdn.getType(), rdn.getValue().toString());
+ }
// Create the remaining attributes.
for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
@@ -910,16 +937,24 @@
ManagedObject<M> createExistingManagedObject(
ManagedObjectDefinition<M, ?> d, ManagedObjectPath p,
PropertySet properties) {
- return new LDAPManagedObject<M>(context, d, p, properties, true);
+ RelationDefinition<?, ?> rd = p.getRelationDefinition();
+ PropertyDefinition<?> pd = null;
+ if (rd instanceof InstantiableRelationDefinition) {
+ InstantiableRelationDefinition<?, ?> ird =
+ (InstantiableRelationDefinition) rd;
+ pd = ird.getNamingPropertyDefinition();
+ }
+ return new LDAPManagedObject<M>(context, d, p, properties, true, pd);
}
// Creates a new managed object with no active values, just default
// values.
- private <M extends ConfigurationClient>
+ private <M extends ConfigurationClient, T>
ManagedObject<M> createNewManagedObject(
ManagedObjectDefinition<M, ?> d, ManagedObjectPath p,
+ PropertyDefinition<T> namingPropertyDefinition, String name,
Collection<DefaultBehaviorException> exceptions) {
PropertySet childProperties = new PropertySet();
for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
@@ -933,7 +968,14 @@
}
}
- return new LDAPManagedObject<M>(context, d, p, childProperties, false);
+ // Set the naming property if there is one.
+ if (namingPropertyDefinition != null) {
+ T value = namingPropertyDefinition.decodeValue(name);
+ childProperties.setPropertyValue(namingPropertyDefinition, value);
+ }
+
+ return new LDAPManagedObject<M>(context, d, p, childProperties, false,
+ namingPropertyDefinition);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java b/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java
index 0e76f19..8c1094a 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/messages/ToolMessages.java
@@ -9063,6 +9063,89 @@
/**
+ * The message ID for the message that will be used if the user
+ * attempts create a new managed object having a name which is
+ * invalid according to the managed object's naming property. This
+ * takes three arguments which are the illegal name, the user
+ * friendly name of the associated managed object, and the syntax.
+ */
+ public static final int MSGID_DSCFG_ERROR_ILLEGAL_NAME_SYNTAX =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1204;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user
+ * attempts create a new managed object having an empty name. This
+ * takes a single argument which is the user friendly plural name of
+ * the associated managed object.
+ */
+ public static final int MSGID_DSCFG_ERROR_ILLEGAL_NAME_EMPTY =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1205;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user
+ * attempts create a new managed object having a blank name. This
+ * takes a single argument which is the user friendly plural name of
+ * the associated managed object.
+ */
+ public static final int MSGID_DSCFG_ERROR_ILLEGAL_NAME_BLANK =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1206;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user
+ * attempts create a new managed object having a name which is
+ * invalid for an unspecified reason. This takes two arguments which
+ * are the illegal name and the user friendly name of the associated
+ * managed object.
+ */
+ public static final int MSGID_DSCFG_ERROR_ILLEGAL_NAME_UNKNOWN =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1207;
+
+
+
+ /**
+ * The message ID for the message that will be used as the
+ * description of the a naming argument in create-xxx sub-commands
+ * which do not have a naming property. This takes a single argument
+ * which is the user friendly name for the type of managed objects
+ * being named.
+ */
+ public static final int MSGID_DSCFG_DESCRIPTION_NAME_CREATE =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1208;
+
+
+
+ /**
+ * The message ID for the message that will be used as the
+ * description of the a naming argument in create-xxx sub-commands
+ * which do have a naming property. This takes three arguments which
+ * are the user friendly name for the type of managed objects being
+ * named, the name of the naming property, and the naming property's
+ * synopsis.
+ */
+ public static final int MSGID_DSCFG_DESCRIPTION_NAME_CREATE_EXT =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_INFORMATIONAL | 1209;
+
+
+
+ /**
+ * The message ID for the message that will be used if the user
+ * attempts set a value for the naming property when creating a new
+ * managed object. This takes two arguments, which are the the name
+ * of the naming property, and the user friendly name of the type of
+ * managed object being created.
+ */
+ public static final int MSGID_DSCFG_ERROR_UNABLE_TO_SET_NAMING_PROPERTY =
+ CATEGORY_MASK_TOOLS | SEVERITY_MASK_SEVERE_ERROR | 1210;
+
+
+
+ /**
* Associates a set of generic messages with the message IDs defined in this
* class.
*/
@@ -11374,6 +11457,13 @@
registerMessage(MSGID_DSCFG_DESCRIPTION_NAME,
"The name of the %s");
+ registerMessage(MSGID_DSCFG_DESCRIPTION_NAME_CREATE,
+ "The name of the new %s");
+
+ registerMessage(MSGID_DSCFG_DESCRIPTION_NAME_CREATE_EXT,
+ "The name of the new %s which will also be used as the " +
+ "value of the \"%s\" property: %s");
+
registerMessage(MSGID_DSCFG_DESCRIPTION_HELP_TYPE,
"The type(s) of components whose properties should be " +
"described");
@@ -11457,6 +11547,10 @@
"The %s property \"%s\" is mandatory cannot be reset. " +
"Use the \"%s\" option to specify a new value");
+ registerMessage(MSGID_DSCFG_ERROR_UNABLE_TO_SET_NAMING_PROPERTY,
+ "The property \"%s\" cannot be set as it is defined " +
+ "implicitly by the name of the %s");
+
registerMessage(MSGID_DSCFG_ERROR_PROPERTY_SINGLE_VALUED,
"It is not possible to specify multiple values for the " +
"%s property \"%s\" as it is single-valued");
@@ -11473,6 +11567,19 @@
"The inherited default value(s) of the %s property " +
"\"%s\" could not be determined");
+ registerMessage(MSGID_DSCFG_ERROR_ILLEGAL_NAME_EMPTY,
+ "Empty names are not permitted for %s");
+
+ registerMessage(MSGID_DSCFG_ERROR_ILLEGAL_NAME_BLANK,
+ "Blank names are not permitted for %s");
+
+ registerMessage(MSGID_DSCFG_ERROR_ILLEGAL_NAME_SYNTAX,
+ "The name \"%s\" is not a valid name for the %s " +
+ "which has the following syntax: %s");
+
+ registerMessage(MSGID_DSCFG_ERROR_ILLEGAL_NAME_UNKNOWN,
+ "The name \"%s\" is not a valid name for the %s");
+
registerMessage(MSGID_DSCFG_HEADING_MANAGED_OBJECT_NAME,
"Component");
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/ArgumentExceptionFactory.java b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/ArgumentExceptionFactory.java
index db45bcc..991106c 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/ArgumentExceptionFactory.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/ArgumentExceptionFactory.java
@@ -36,12 +36,14 @@
import org.opends.server.admin.IllegalPropertyValueException;
import org.opends.server.admin.IllegalPropertyValueStringException;
import org.opends.server.admin.ManagedObjectDefinition;
+import org.opends.server.admin.PropertyDefinition;
import org.opends.server.admin.PropertyDefinitionUsageBuilder;
import org.opends.server.admin.PropertyException;
import org.opends.server.admin.PropertyIsMandatoryException;
import org.opends.server.admin.PropertyIsReadOnlyException;
import org.opends.server.admin.PropertyIsSingleValuedException;
import org.opends.server.admin.RelationDefinition;
+import org.opends.server.admin.client.IllegalManagedObjectNameException;
import org.opends.server.admin.client.MissingMandatoryPropertiesException;
import org.opends.server.util.args.ArgumentException;
@@ -54,6 +56,51 @@
final class ArgumentExceptionFactory {
/**
+ * Creates an argument exception from an illegal managed object name
+ * exception.
+ *
+ * @param e
+ * The illegal managed object name exception.
+ * @param d
+ * The managed object definition.
+ * @return Returns an argument exception.
+ */
+ public static ArgumentException adaptIllegalManagedObjectNameException(
+ IllegalManagedObjectNameException e, AbstractManagedObjectDefinition d) {
+ String illegalName = e.getIllegalName();
+ PropertyDefinition<?> pd = e.getNamingPropertyDefinition();
+
+ if (illegalName.length() == 0) {
+ int msgID = MSGID_DSCFG_ERROR_ILLEGAL_NAME_EMPTY;
+ String message = getMessage(msgID, d.getUserFriendlyPluralName());
+ return new ArgumentException(msgID, message);
+ } else if (illegalName.trim().length() == 0) {
+ int msgID = MSGID_DSCFG_ERROR_ILLEGAL_NAME_BLANK;
+ String message = getMessage(msgID, d.getUserFriendlyPluralName());
+ return new ArgumentException(msgID, message);
+ } else if (pd != null) {
+ try {
+ pd.decodeValue(illegalName);
+ } catch (IllegalPropertyValueStringException e1) {
+ PropertyDefinitionUsageBuilder b = new PropertyDefinitionUsageBuilder(
+ true);
+ String syntax = b.getUsage(pd);
+
+ int msgID = MSGID_DSCFG_ERROR_ILLEGAL_NAME_SYNTAX;
+ String message = getMessage(msgID, illegalName,
+ d.getUserFriendlyName(), pd.getName(), syntax);
+ return new ArgumentException(msgID, message);
+ }
+ }
+
+ int msgID = MSGID_DSCFG_ERROR_ILLEGAL_NAME_UNKNOWN;
+ String message = getMessage(msgID, illegalName, d.getUserFriendlyName());
+ return new ArgumentException(msgID, message);
+ }
+
+
+
+ /**
* Creates an argument exception from a missing mandatory properties
* exception.
*
@@ -262,6 +309,26 @@
/**
+ * Creates an argument exception which should be used when an
+ * attempt is made to set the naming property for a managed object
+ * during creation.
+ *
+ * @param d
+ * The managed object definition.
+ * @param pd
+ * The naming property definition.
+ * @return Returns an argument exception.
+ */
+ public static ArgumentException unableToSetNamingProperty(
+ AbstractManagedObjectDefinition d, PropertyDefinition<?> pd) {
+ int msgID = MSGID_DSCFG_ERROR_UNABLE_TO_SET_NAMING_PROPERTY;
+ String message = getMessage(msgID, pd.getName(), d.getUserFriendlyName());
+ return new ArgumentException(msgID, message);
+ }
+
+
+
+ /**
* Creates an argument exception which should be used when the bind
* password could not be read from the standard input.
*
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/CreateSubCommandHandler.java b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/CreateSubCommandHandler.java
index 5aa15c2..47123bc 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/CreateSubCommandHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/CreateSubCommandHandler.java
@@ -62,6 +62,7 @@
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ConcurrentModificationException;
+import org.opends.server.admin.client.IllegalManagedObjectNameException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagedObjectDecodingException;
import org.opends.server.admin.client.ManagementContext;
@@ -105,13 +106,16 @@
*
* @param d
* The managed object definition.
+ * @param namingPropertyDefinition
+ * The naming property definition if there is one.
* @param args
* The property value arguments.
* @throws ArgumentException
* If the property value arguments could not be parsed.
*/
public MyPropertyProvider(ManagedObjectDefinition<?, ?> d,
- List<String> args) throws ArgumentException {
+ PropertyDefinition<?> namingPropertyDefinition, List<String> args)
+ throws ArgumentException {
for (String s : args) {
// Parse the property "property:value".
int sep = s.indexOf(':');
@@ -138,6 +142,12 @@
throw ArgumentExceptionFactory.unknownProperty(d, propertyName);
}
+ // Make sure that the user is not attempting to set the naming
+ // property.
+ if (pd.equals(namingPropertyDefinition)) {
+ throw ArgumentExceptionFactory.unableToSetNamingProperty(d, pd);
+ }
+
// Add the value.
addPropertyValue(d, pd, value);
}
@@ -247,7 +257,8 @@
public static <C extends ConfigurationClient> CreateSubCommandHandler create(
SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p,
InstantiableRelationDefinition<C, ?> r) throws ArgumentException {
- return new CreateSubCommandHandler<C>(parser, p, r, p.child(r, "DUMMY"));
+ return new CreateSubCommandHandler<C>(parser, p, r, r
+ .getNamingPropertyDefinition(), p.child(r, "DUMMY"));
}
@@ -270,12 +281,15 @@
public static <C extends ConfigurationClient> CreateSubCommandHandler create(
SubCommandArgumentParser parser, ManagedObjectPath<?, ?> p,
OptionalRelationDefinition<C, ?> r) throws ArgumentException {
- return new CreateSubCommandHandler<C>(parser, p, r, p.child(r));
+ return new CreateSubCommandHandler<C>(parser, p, r, null, p.child(r));
}
// The sub-commands naming arguments.
private final List<StringArgument> namingArgs;
+ // The optional naming property definition.
+ private final PropertyDefinition<?> namingPropertyDefinition;
+
// The path of the parent managed object.
private final ManagedObjectPath<?, ?> path;
@@ -306,9 +320,11 @@
// Common constructor.
private CreateSubCommandHandler(SubCommandArgumentParser parser,
ManagedObjectPath<?, ?> p, RelationDefinition<C, ?> r,
- ManagedObjectPath<?, ?> c) throws ArgumentException {
+ PropertyDefinition<?> pd, ManagedObjectPath<?, ?> c)
+ throws ArgumentException {
this.path = p;
this.relation = r;
+ this.namingPropertyDefinition = pd;
// Create the sub-command.
String name = "create-" + r.getName();
@@ -321,7 +337,7 @@
this.types = getSubTypes(r.getChildDefinition());
// Create the naming arguments.
- this.namingArgs = createNamingArgs(subCommand, c);
+ this.namingArgs = createNamingArgs(subCommand, c, true);
// Create the --property argument which is used to specify
// property values.
@@ -392,7 +408,8 @@
// Encode the provided properties.
List<String> propertyArgs = propertySetArgument.getValues();
- MyPropertyProvider provider = new MyPropertyProvider(d, propertyArgs);
+ MyPropertyProvider provider = new MyPropertyProvider(d,
+ namingPropertyDefinition, propertyArgs);
// Add the child managed object.
ManagementContext context = app.getManagementContext();
@@ -439,7 +456,12 @@
InstantiableRelationDefinition<C, ?> irelation =
(InstantiableRelationDefinition<C, ?>) relation;
String name = names.get(names.size() - 1);
- child = parent.createChild(irelation, d, name, exceptions);
+ try {
+ child = parent.createChild(irelation, d, name, exceptions);
+ } catch (IllegalManagedObjectNameException e) {
+ throw ArgumentExceptionFactory
+ .adaptIllegalManagedObjectNameException(e, d);
+ }
} else {
OptionalRelationDefinition<C, ?> orelation =
(OptionalRelationDefinition<C, ?>) relation;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/DeleteSubCommandHandler.java b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/DeleteSubCommandHandler.java
index 6878465..426cdf3 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/DeleteSubCommandHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/DeleteSubCommandHandler.java
@@ -151,7 +151,7 @@
descriptionID, ufpn);
// Create the naming arguments.
- this.namingArgs = createNamingArgs(subCommand, c);
+ this.namingArgs = createNamingArgs(subCommand, c, false);
// Create the --force argument which is used to force deletion.
this.forceArgument = new BooleanArgument(OPTION_DSCFG_LONG_FORCE,
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/GetPropSubCommandHandler.java b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/GetPropSubCommandHandler.java
index b6af6cf..f8ecd19 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/GetPropSubCommandHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/GetPropSubCommandHandler.java
@@ -162,7 +162,7 @@
descriptionID, r.getChildDefinition().getUserFriendlyName());
// Create the naming arguments.
- this.namingArgs = createNamingArgs(subCommand, path);
+ this.namingArgs = createNamingArgs(subCommand, path, false);
// Register common arguments.
registerPropertyNameArgument(this.subCommand);
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/ListSubCommandHandler.java b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/ListSubCommandHandler.java
index a37ec83..5bb2598 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/ListSubCommandHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/ListSubCommandHandler.java
@@ -142,7 +142,7 @@
descriptionID, rufn);
// Create the naming arguments.
- this.namingArgs = createNamingArgs(subCommand, path);
+ this.namingArgs = createNamingArgs(subCommand, path, false);
// Register arguments.
registerPropertyNameArgument(this.subCommand);
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SetPropSubCommandHandler.java b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SetPropSubCommandHandler.java
index f489108..fac8445 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SetPropSubCommandHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SetPropSubCommandHandler.java
@@ -242,7 +242,7 @@
descriptionID, r.getChildDefinition().getUserFriendlyName());
// Create the naming arguments.
- this.namingArgs = createNamingArgs(subCommand, path);
+ this.namingArgs = createNamingArgs(subCommand, path, false);
// Create the --set argument.
this.propertySetArgument = new StringArgument(OPTION_DSCFG_LONG_SET,
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java
index a393f3d..ad503d5 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/tools/dsconfig/SubCommandHandler.java
@@ -52,6 +52,8 @@
import org.opends.server.admin.ManagedObjectPath;
import org.opends.server.admin.ManagedObjectPathSerializer;
import org.opends.server.admin.OptionalRelationDefinition;
+import org.opends.server.admin.PropertyDefinition;
+import org.opends.server.admin.PropertyDefinitionUsageBuilder;
import org.opends.server.admin.SingletonRelationDefinition;
import org.opends.server.admin.SizeUnit;
import org.opends.server.admin.Tag;
@@ -344,14 +346,20 @@
* The sub-command.
* @param path
* The managed object path.
+ * @param isCreate
+ * Indicates whether the sub-command is a create-xxx
+ * sub-command, in which case the final path element will
+ * have different usage information.
* @return Returns the naming arguments.
* @throws ArgumentException
* If one or more naming arguments could not be
* registered.
*/
public static List<StringArgument> create(SubCommand subCommand,
- ManagedObjectPath<?, ?> path) throws ArgumentException {
- NamingArgumentBuilder builder = new NamingArgumentBuilder(subCommand);
+ ManagedObjectPath<?, ?> path, boolean isCreate)
+ throws ArgumentException {
+ NamingArgumentBuilder builder = new NamingArgumentBuilder(subCommand,
+ path.size(), isCreate);
path.serialize(builder);
if (builder.e != null) {
@@ -372,16 +380,22 @@
// The sub-command.
private final SubCommand subCommand;
+ // Indicates whether the sub-command is a create-xxx
+ // sub-command, in which case the final path element will
+ // have different usage information.
+ private final boolean isCreate;
+
+ // The number of path elements to expect.
+ private int sz;
- /**
- * Creates a new naming argument builder.
- *
- * @param subCommand
- * Add the naming arguments to this sub-command.
- */
- public NamingArgumentBuilder(SubCommand subCommand) {
+
+ // Private constructor.
+ private NamingArgumentBuilder(SubCommand subCommand, int sz,
+ boolean isCreate) {
this.subCommand = subCommand;
+ this.sz = sz;
+ this.isCreate = isCreate;
}
@@ -393,6 +407,8 @@
void appendManagedObjectPathElement(
InstantiableRelationDefinition<? super C, ? super S> r,
AbstractManagedObjectDefinition<C, S> d, String name) {
+ sz--;
+
// Use the last word in the managed object name as the argument
// prefix.
StringBuilder builder = new StringBuilder();
@@ -406,12 +422,32 @@
}
builder.append("-name");
String argName = builder.toString();
+ StringArgument arg;
try {
- StringArgument arg = new StringArgument(argName, null, argName, true,
- true, "{NAME}", MSGID_DSCFG_DESCRIPTION_NAME, d
- .getUserFriendlyName());
+ if (isCreate && sz == 0) {
+ // The final path element in create-xxx sub-commands should
+ // have a different usage.
+ PropertyDefinition<?> pd = r.getNamingPropertyDefinition();
+ if (pd != null) {
+ // Use syntax and description from naming property.
+ PropertyDefinitionUsageBuilder b =
+ new PropertyDefinitionUsageBuilder(false);
+ String usage = "{" + b.getUsage(pd) + "}";
+ arg = new StringArgument(argName, null, argName, true, true, usage,
+ MSGID_DSCFG_DESCRIPTION_NAME_CREATE_EXT, d
+ .getUserFriendlyName(), pd.getName(), pd.getSynopsis());
+ } else {
+ arg = new StringArgument(argName, null, argName, true, true,
+ "{NAME}", MSGID_DSCFG_DESCRIPTION_NAME_CREATE, d
+ .getUserFriendlyName());
+ }
+ } else {
+ // A normal naming argument.
+ arg = new StringArgument(argName, null, argName, true, true,
+ "{NAME}", MSGID_DSCFG_DESCRIPTION_NAME, d.getUserFriendlyName());
+ }
subCommand.addArgument(arg);
arguments.add(arg);
} catch (ArgumentException e) {
@@ -428,7 +464,7 @@
void appendManagedObjectPathElement(
OptionalRelationDefinition<? super C, ? super S> r,
AbstractManagedObjectDefinition<C, S> d) {
- // No implementation required.
+ sz--;
}
@@ -440,7 +476,7 @@
void appendManagedObjectPathElement(
SingletonRelationDefinition<? super C, ? super S> r,
AbstractManagedObjectDefinition<C, S> d) {
- // No implementation required.
+ sz--;
}
}
@@ -601,14 +637,18 @@
* The sub-command.
* @param p
* The managed object path.
+ * @param isCreate
+ * Indicates whether the sub-command is a create-xxx
+ * sub-command, in which case the final path element will
+ * have different usage information.
* @return Returns the naming arguments.
* @throws ArgumentException
* If one or more naming arguments could not be
* registered.
*/
protected final List<StringArgument> createNamingArgs(SubCommand subCommand,
- ManagedObjectPath<?, ?> p) throws ArgumentException {
- return NamingArgumentBuilder.create(subCommand, p);
+ ManagedObjectPath<?, ?> p, boolean isCreate) throws ArgumentException {
+ return NamingArgumentBuilder.create(subCommand, p, isCreate);
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/MockLDAPProfile.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/MockLDAPProfile.java
index 7fa2c05..c23bc6a 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/MockLDAPProfile.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/MockLDAPProfile.java
@@ -46,7 +46,7 @@
* {@inheritDoc}
*/
@Override
- public String getAttributeName(ManagedObjectDefinition<?, ?> d,
+ public String getAttributeName(AbstractManagedObjectDefinition<?, ?> d,
PropertyDefinition<?> pd) {
if (d == TestParentCfgDefn.getInstance()) {
TestParentCfgDefn td = TestParentCfgDefn.getInstance();
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java
index 61587d0..86db1df 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestCfg.java
@@ -53,7 +53,7 @@
static {
RD_TEST_ONE_TO_MANY_PARENT = new InstantiableRelationDefinition<TestParentCfgClient, TestParentCfg>(
RootCfgDefn.getInstance(), "test-one-to-many-parent",
- "test-one-to-many-parents", TestParentCfgDefn.getInstance());
+ "test-one-to-many-parents", TestParentCfgDefn.getInstance(), null);
}
// Create a one-to-many relation for test-parent components.
@@ -61,7 +61,6 @@
RD_TEST_ONE_TO_ZERO_OR_ONE_PARENT = new OptionalRelationDefinition<TestParentCfgClient, TestParentCfg>(
RootCfgDefn.getInstance(), "test-one-to-zero-or-one-parent",
TestParentCfgDefn.getInstance());
-
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgClient.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgClient.java
index 6bcf604..e574a5c 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgClient.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgClient.java
@@ -33,6 +33,7 @@
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ConcurrentModificationException;
+import org.opends.server.admin.client.IllegalManagedObjectNameException;
import org.opends.server.admin.client.ManagedObjectDecodingException;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.admin.ConfigurationClient;
@@ -239,9 +240,11 @@
* attempting to determine the default values of the
* Test Child. This argument can be <code>null<code>.
* @return Returns a new Test Child configuration instance.
+ * @throws IllegalManagedObjectNameException
+ * If the name is invalid.
*/
<C extends TestChildCfgClient> C createTestChild(
- ManagedObjectDefinition<C, ?> d, String name, Collection<DefaultBehaviorException> exceptions);
+ ManagedObjectDefinition<C, ?> d, String name, Collection<DefaultBehaviorException> exceptions) throws IllegalManagedObjectNameException;
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java
index 3d88428..2c076a8 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java
@@ -37,6 +37,7 @@
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ConcurrentModificationException;
+import org.opends.server.admin.client.IllegalManagedObjectNameException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagedObjectDecodingException;
import org.opends.server.admin.client.MissingMandatoryPropertiesException;
@@ -164,7 +165,7 @@
// Build the "test-children" relation definition.
static {
RD_TEST_CHILDREN = new InstantiableRelationDefinition<TestChildCfgClient, TestChildCfg>(
- INSTANCE, "multiple-children", "test-children", TestChildCfgDefn.getInstance());
+ INSTANCE, "multiple-children", "test-children", TestChildCfgDefn.getInstance(), null);
INSTANCE.registerRelationDefinition(RD_TEST_CHILDREN);
}
@@ -421,7 +422,7 @@
* {@inheritDoc}
*/
public <M extends TestChildCfgClient> M createTestChild(
- ManagedObjectDefinition<M, ?> d, String name, Collection<DefaultBehaviorException> exceptions) {
+ ManagedObjectDefinition<M, ?> d, String name, Collection<DefaultBehaviorException> exceptions) throws IllegalManagedObjectNameException {
return impl.createChild(INSTANCE.getTestChildrenRelationDefinition(), d, name, exceptions).getConfiguration();
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/LDAPClientTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/LDAPClientTest.java
index 1fb6f8f..0bd0390 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/LDAPClientTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/LDAPClientTest.java
@@ -53,6 +53,7 @@
import org.opends.server.admin.client.AuthorizationException;
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ConcurrentModificationException;
+import org.opends.server.admin.client.IllegalManagedObjectNameException;
import org.opends.server.admin.client.ManagedObject;
import org.opends.server.admin.client.ManagedObjectDecodingException;
import org.opends.server.admin.client.ManagementContext;
@@ -813,7 +814,7 @@
String name) throws ManagedObjectDecodingException,
AuthorizationException, ManagedObjectAlreadyExistsException,
ConcurrentModificationException, OperationRejectedException,
- CommunicationException {
+ CommunicationException, IllegalManagedObjectNameException {
ManagedObject<RootCfgClient> root = context
.getRootConfigurationManagedObject();
return root.createChild(TestCfg.getTestOneToManyParentRelationDefinition(),
--
Gitblit v1.10.0