From 73bf799efd605eca244e788d1655a31a5e1bd671 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Mon, 28 May 2007 15:31:13 +0000
Subject: [PATCH] Fix the following issues:
---
opendj-sdk/opends/resource/admin/metaMO.xsl | 125 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgDefn.java | 117 +
opendj-sdk/opends/resource/admin/property-types.xsl | 44
opendj-sdk/opends/src/server/org/opends/server/admin/PropertyOption.java | 23
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgClient.java | 42
opendj-sdk/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java | 723 +++++++----
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java | 20
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfg.java | 18
opendj-sdk/opends/src/server/org/opends/server/admin/client/PropertySet.java | 584 +-------
opendj-sdk/opends/src/ads/org/opends/admin/ads/ADSContextHelper.java | 5
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgDefn.java | 15
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/PropertySetTest.java | 76
opendj-sdk/opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java | 80
opendj-sdk/opends/resource/admin/preprocessor.xsl | 30
opendj-sdk/opends/src/server/org/opends/server/admin/ManagedObjectPath.java | 206 ++
opendj-sdk/opends/resource/admin/clientMO.xsl | 77
opendj-sdk/opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java | 53
/dev/null | 111 -
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/LDAPClientTest.java | 115 +
opendj-sdk/opends/src/server/org/opends/server/admin/client/MissingMandatoryPropertiesException.java | 120 +
opendj-sdk/opends/src/server/org/opends/server/admin/DefaultBehaviorException.java | 90 +
opendj-sdk/opends/resource/admin/admin.xsd | 80
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestParentCfgClient.java | 35
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java | 63
opendj-sdk/opends/src/server/org/opends/server/admin/client/ldap/LDAPManagedObject.java | 799 ++++++++----
opendj-sdk/opends/src/server/org/opends/server/admin/client/ManagedObject.java | 124 -
opendj-sdk/opends/src/server/org/opends/server/admin/ConfigurationClient.java | 32
27 files changed, 2,302 insertions(+), 1,505 deletions(-)
diff --git a/opendj-sdk/opends/resource/admin/admin.xsd b/opendj-sdk/opends/resource/admin/admin.xsd
index a2c9104..281d00a 100644
--- a/opendj-sdk/opends/resource/admin/admin.xsd
+++ b/opendj-sdk/opends/resource/admin/admin.xsd
@@ -308,8 +308,23 @@
<xsd:annotation>
<xsd:documentation>
Indicates whether or not this property is read-only. By
- default, properties are modifiable. Read-only monitoring
- information is a good use-case for read-only properties.
+ default, properties are not read-only. Read-only properties
+ can only be initialized during construction of the associated
+ managed object and cannot be modified once the managed object
+ has been created.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="monitoring" type="xsd:boolean" use="optional"
+ default="false">
+ <xsd:annotation>
+ <xsd:documentation>
+ Indicates whether or not this property is read-only and
+ generated automatically by the server as monitoring
+ information. By default, properties are not for monitoring.
+ Monitoring properties are always read-only because their
+ values are generated by the server. During construction of a
+ managed object their values are undefined.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
@@ -746,6 +761,25 @@
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
+ <xsd:attribute name="managed-object-name"
+ type="tns:name-type" use="required">
+ <xsd:annotation>
+ <xsd:documentation>
+ The type of managed object providing the default
+ values.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
+ <xsd:attribute name="managed-object-package"
+ type="tns:package-type" use="optional">
+ <xsd:annotation>
+ <xsd:documentation>
+ The package containing the managed object
+ definition if it is not the same as this managed
+ object's package.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
<xsd:attribute name="property-name" type="tns:name-type"
use="required">
<xsd:annotation>
@@ -765,16 +799,15 @@
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
- <xsd:sequence>
- <xsd:element name="path">
- <xsd:annotation>
- <xsd:documentation>
- TODO: not sure what form this will take.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:complexType />
- </xsd:element>
- </xsd:sequence>
+ <xsd:attribute name="path" type="tns:path-type"
+ use="required">
+ <xsd:annotation>
+ <xsd:documentation>
+ The location of the managed object containing the
+ default values.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
<xsd:attribute name="property-name" type="tns:name-type"
use="required">
<xsd:annotation>
@@ -1237,19 +1270,28 @@
<xsd:annotation>
<xsd:documentation>
A managed object path which can be used to specify the location
- of refererenced managed objects. A managed object path has a
+ of referenced managed objects. A managed object path has a
similar syntax to unix file system paths, and comprises of zero
or more path elements separated by a forward slash "/". The root
configuration is referenced using the path "/". Subsequent path
- elements name either a relation or its subordinate named managed
- object (for one-to-many relations). For example, the path
- "/connection-handlers/LDAP connection handler" references the
- LDAP connection handler managed object referenced by the root
- configuration's connection-handlers relation.
+ elements identify subordinate managed objects. Each path element
+ is comprised of the relation name, an optional definition name,
+ and the name of the managed object instance if the relation is
+ one-to-many. The path "/relation=connection-handler+name=my
+ handler" identifies a connection handler called "my handler"
+ where "my handler" can be any type of connection handler. If "my
+ handler" must be an LDAP connection handler then the type needs
+ to be specified in the path:
+ "/relation=connection-handler+type=ldap-connection-handler+name=my
+ handler". The global configuration is identified by the path
+ "/relation=global-configuration" (no name is required because
+ the relation is one-to-one).
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
- <xsd:pattern value="/([^/]+(/[^/]+)*)?"></xsd:pattern>
+ <xsd:pattern
+ value="/|(/relation=[^/+]+(\+type=[^/+]+)?(\+name=[^/]+)?)+">
+ </xsd:pattern>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="profile-type">
diff --git a/opendj-sdk/opends/resource/admin/clientMO.xsl b/opendj-sdk/opends/resource/admin/clientMO.xsl
index 3db6324..2e6197e 100644
--- a/opendj-sdk/opends/resource/admin/clientMO.xsl
+++ b/opendj-sdk/opends/resource/admin/clientMO.xsl
@@ -176,34 +176,26 @@
<xsl:with-param name="indent" select="2" />
<xsl:with-param name="content"
select="concat(
- 'Creates the ', $ufn,' if it does not exist yet.
',
+ 'Creates a new ', $ufn,'. The new ', $ufn,' will initially ',
+ 'not contain any property values (including mandatory ',
+ 'properties). Once the ', $ufn,' has been configured it ',
+ 'can be added to the server using the {@link #commit()} ',
+ 'method.
',
'
',
'@param <C>
',
- ' The type of the ', $ufn,' being added.
',
+ ' The type of the ', $ufn,' being created.
',
'@param d
',
' The definition of the ', $ufn,' to be created.
',
- '@param p
',
- ' A property provider which can be used to initialize the property values of the new ', $ufn,'.
',
- '@return Returns the ', $ufn,' instance representing the ', $ufn,' that was created.
',
- '@throws ManagedObjectDecodingException
',
- ' If the ', $ufn,' could not be created because one or more of its properties are invalid.
',
- '@throws ManagedObjectAlreadyExistsException
',
- ' If the ', $ufn,' cannot be created because it already exists on the server.
',
- '@throws ConcurrentModificationException
',
- ' If this ', $ufn,' has been removed from the server by another client.
',
- '@throws OperationRejectedException
',
- ' If the server refuses to create the ', $ufn,' due to some server-side constraint which cannot be satisfied.
',
- '@throws AuthorizationException
',
- ' If the server refuses to create the ', $ufn,' because the client does not have the correct privileges.
',
- '@throws CommunicationException
',
- ' If the client cannot contact the server due to an underlying communication problem.
')" />
+ '@param exceptions
',
+ ' An optional collection in which to place any ',
+ '{@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.
')" />
</xsl:call-template>
<xsl:value-of
select="concat(' <C extends ', $java-class-name,'CfgClient> C create', $java-relation-name, '(
',
- ' ManagedObjectDefinition<C, ?> d, PropertyProvider p)
',
- ' throws ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,
',
- ' ConcurrentModificationException, OperationRejectedException,
',
- ' AuthorizationException, CommunicationException;
')" />
+ ' ManagedObjectDefinition<C, ?> d, Collection<DefaultBehaviorException> exceptions);
')" />
<xsl:text>
</xsl:text>
<xsl:text>
</xsl:text>
<xsl:text>
</xsl:text>
@@ -297,36 +289,28 @@
<xsl:with-param name="indent" select="2" />
<xsl:with-param name="content"
select="concat(
- 'Creates a new ', $ufn,'.
',
+ 'Creates a new ', $ufn,'. The new ', $ufn,' will initially ',
+ 'not contain any property values (including mandatory ',
+ 'properties). Once the ', $ufn,' has been configured it ',
+ 'can be added to the server using the {@link #commit()} ',
+ 'method.
',
'
',
'@param <C>
',
- ' The type of the ', $ufn,' being added.
',
+ ' The type of the ', $ufn,' being created.
',
'@param d
',
' The definition of the ', $ufn,' to be created.
',
'@param name
',
' The name of the new ', $ufn,'.
',
- '@param p
',
- ' A property provider which can be used to initialize the property values of the new ', $ufn,'.
',
- '@return Returns a new ', $ufn,' instance representing the ', $ufn,' that was created.
',
- '@throws ManagedObjectDecodingException
',
- ' If the ', $ufn,' could not be created because one or more of its properties are invalid.
',
- '@throws ManagedObjectAlreadyExistsException
',
- ' If the ', $ufn,' cannot be created because it already exists on the server.
',
- '@throws ConcurrentModificationException
',
- ' If this ', $ufn,' has been removed from the server by another client.
',
- '@throws OperationRejectedException
',
- ' If the server refuses to create the ', $ufn,' due to some server-side constraint which cannot be satisfied.
',
- '@throws AuthorizationException
',
- ' If the server refuses to create the ', $ufn,' because the client does not have the correct privileges.
',
- '@throws CommunicationException
',
- ' If the client cannot contact the server due to an underlying communication problem.
')" />
+ '@param exceptions
',
+ ' An optional collection in which to place any ',
+ '{@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.
')" />
</xsl:call-template>
<xsl:value-of
select="concat(' <C extends ', $java-class-name,'CfgClient> C create', $java-relation-name, '(
',
- ' ManagedObjectDefinition<C, ?> d, String name, PropertyProvider p)
',
- ' throws ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,
',
- ' ConcurrentModificationException, OperationRejectedException,
',
- ' AuthorizationException, CommunicationException;
')" />
+ ' ManagedObjectDefinition<C, ?> d, String name, Collection<DefaultBehaviorException> exceptions);
')" />
<xsl:text>
</xsl:text>
<xsl:text>
</xsl:text>
<xsl:text>
</xsl:text>
@@ -382,11 +366,14 @@
<import>java.util.Collection</import>
<import>java.util.SortedSet</import>
</xsl:if>
- <xsl:if test="$this-local-properties[not(@read-only='true')]">
+ <xsl:if test="$this-local-properties[not(@monitoring='true')]">
<import>
org.opends.server.admin.IllegalPropertyValueException
</import>
</xsl:if>
+ <xsl:if test="$this-local-properties[@read-only='true']">
+ <import>org.opends.server.admin.PropertyIsReadOnlyException</import>
+ </xsl:if>
<xsl:if test="$this-local-relations">
<import>
org.opends.server.admin.DefinitionDecodingException
@@ -409,9 +396,9 @@
</xsl:if>
<xsl:if
test="$this-local-relations/adm:one-to-zero-or-one|$this-local-relations/adm:one-to-many">
- <import>org.opends.server.admin.PropertyProvider</import>
+ <import>java.util.Collection</import>
<import>
- org.opends.server.admin.ManagedObjectAlreadyExistsException
+ org.opends.server.admin.DefaultBehaviorException
</import>
<import>
org.opends.server.admin.client.OperationRejectedException
diff --git a/opendj-sdk/opends/resource/admin/metaMO.xsl b/opendj-sdk/opends/resource/admin/metaMO.xsl
index 46a998d..9ba6a10 100644
--- a/opendj-sdk/opends/resource/admin/metaMO.xsl
+++ b/opendj-sdk/opends/resource/admin/metaMO.xsl
@@ -387,7 +387,8 @@
select="concat(' /**
',
' * {@inheritDoc}
',
' */
',
- ' public void commit() throws ConcurrentModificationException,
',
+ ' public void commit() throws ManagedObjectAlreadyExistsException,
',
+ ' MissingMandatoryPropertiesException, ConcurrentModificationException,
',
' OperationRejectedException, AuthorizationException,
',
' CommunicationException {
',
' impl.commit();
',
@@ -568,29 +569,33 @@
select="concat(' ', $type, '.Builder builder = ', $type, '.createBuilder(INSTANCE, "',@name, '");
')" />
</xsl:otherwise>
</xsl:choose>
- <xsl:if test="string(@multi-valued) = 'true'">
+ <xsl:if test="@multi-valued='true'">
<xsl:value-of
select="' builder.setOption(PropertyOption.MULTI_VALUED);
'" />
</xsl:if>
- <xsl:if test="string(@read-only) = 'true'">
+ <xsl:if test="@read-only='true'">
<xsl:value-of
select="' builder.setOption(PropertyOption.READ_ONLY);
'" />
</xsl:if>
+ <xsl:if test="@monitoring='true'">
+ <xsl:value-of
+ select="' builder.setOption(PropertyOption.MONITORING);
'" />
+ </xsl:if>
<xsl:if
test="adm:requires-admin-action/adm:server-restart|adm:requires-admin-action/adm:component-restart|adm:requires-admin-action/adm:other">
<xsl:value-of
select="' builder.setOption(PropertyOption.REQUIRES_ADMIN_ACTION);
'" />
</xsl:if>
- <xsl:if test="string(@mandatory) = 'true'">
+ <xsl:if test="@mandatory='true'">
<xsl:value-of
select="' builder.setOption(PropertyOption.MANDATORY);
'" />
</xsl:if>
- <xsl:if test="string(@hidden) = 'true'">
+ <xsl:if test="@hidden='true'">
<xsl:value-of
select="' builder.setOption(PropertyOption.HIDDEN);
'" />
</xsl:if>
<xsl:choose>
- <xsl:when test="string(@mandatory) = 'true'">
+ <xsl:when test="@mandatory='true'">
<xsl:value-of
select="concat(' builder.setDefaultBehaviorProvider(new UndefinedDefaultBehaviorProvider<', $value-type,'>());
')" />
</xsl:when>
@@ -629,19 +634,37 @@
</xsl:when>
<xsl:when
test="adm:default-behavior/adm:inherited/adm:relative">
- <xsl:message terminate="yes">
- <xsl:value-of
- select="concat('Relative inherited property defaults not yet implemented (property "', @name,
- '").')" />
- </xsl:message>
+ <xsl:value-of
+ select="concat(' DefaultBehaviorProvider<', $value-type,'> provider = ',
+ 'new RelativeInheritedDefaultBehaviorProvider<', $value-type,'>(')" />
+ <xsl:variable name="managed-object-name">
+ <xsl:call-template name="name-to-java">
+ <xsl:with-param name="value"
+ select="adm:default-behavior/adm:inherited/adm:relative/@managed-object-name" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="property-name"
+ select="adm:default-behavior/adm:inherited/adm:relative/@property-name" />
+ <xsl:variable name="offset"
+ select="adm:default-behavior/adm:inherited/adm:relative/@offset" />
+ <xsl:value-of
+ select="concat($managed-object-name, 'CfgDefn.getInstance(), "', $property-name, '", ', $offset, ');
')" />
+ <xsl:value-of
+ select="' builder.setDefaultBehaviorProvider(provider);
'" />
</xsl:when>
<xsl:when
test="adm:default-behavior/adm:inherited/adm:absolute">
- <xsl:message terminate="yes">
- <xsl:value-of
- select="concat('Absolute inherited property defaults not yet implemented (property "', @name,
- '").')" />
- </xsl:message>
+ <xsl:value-of
+ select="concat(' DefaultBehaviorProvider<', $value-type,'> provider = ',
+ 'new AbsoluteInheritedDefaultBehaviorProvider<', $value-type,'>(')" />
+ <xsl:variable name="property-name"
+ select="adm:default-behavior/adm:inherited/adm:absolute/@property-name" />
+ <xsl:variable name="path"
+ select="adm:default-behavior/adm:inherited/adm:absolute/@path" />
+ <xsl:value-of
+ select="concat('ManagedObjectPath.valueOf("', $path, '"), "', $property-name, '");
')" />
+ <xsl:value-of
+ select="' builder.setDefaultBehaviorProvider(provider);
'" />
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">
@@ -1017,7 +1040,7 @@
Generate a property value setter.
-->
<xsl:template name="generate-property-setter">
- <xsl:if test="string(@read-only) != 'true'">
+ <xsl:if test="not(@monitoring='true')">
<xsl:variable name="java-prop-name">
<xsl:call-template name="name-to-java">
<xsl:with-param name="value" select="@name" />
@@ -1031,9 +1054,9 @@
$java-prop-name ,
'(')" />
<xsl:choose>
- <xsl:when test="string(@multi-valued) != 'true'">
+ <xsl:when test="not(@multi-valued='true')">
<xsl:choose>
- <xsl:when test="@mandatory = 'true'">
+ <xsl:when test="@mandatory='true'">
<xsl:call-template
name="get-property-java-primitive-type" />
</xsl:when>
@@ -1041,8 +1064,12 @@
<xsl:call-template name="get-property-java-type" />
</xsl:otherwise>
</xsl:choose>
+ <xsl:value-of select="' value)'" />
+ <xsl:if test="@read-only='true'">
+ <xsl:value-of select="' throws PropertyIsReadOnlyException'" />
+ </xsl:if>
<xsl:value-of
- select="concat(' value) {
' ,
+ select="concat(' {
' ,
' impl.setPropertyValue(INSTANCE.get',
$java-prop-name ,
'PropertyDefinition(), value);
',
@@ -1119,11 +1146,8 @@
' * {@inheritDoc}
',
' */
',
' public <M extends ', $java-class-name, 'CfgClient> M create', $java-relation-name, '(
',
- ' ManagedObjectDefinition<M, ?> d, PropertyProvider p)
',
- ' throws ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,
',
- ' ConcurrentModificationException, OperationRejectedException,
',
- ' AuthorizationException, CommunicationException {
',
- ' return impl.createChild(INSTANCE.get', $java-relation-name,'RelationDefinition(), d, p).getConfiguration();
',
+ ' ManagedObjectDefinition<M, ?> d, Collection<DefaultBehaviorException> exceptions) {
',
+ ' return impl.createChild(INSTANCE.get', $java-relation-name,'RelationDefinition(), d, exceptions).getConfiguration();
',
' }
')" />
<xsl:text>
</xsl:text>
<xsl:text>
</xsl:text>
@@ -1175,11 +1199,8 @@
' * {@inheritDoc}
',
' */
',
' public <M extends ', $java-class-name, 'CfgClient> M create', $java-relation-name, '(
',
- ' ManagedObjectDefinition<M, ?> d, String name, PropertyProvider p)
',
- ' throws ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,
',
- ' ConcurrentModificationException, OperationRejectedException,
',
- ' AuthorizationException, CommunicationException {
',
- ' return impl.createChild(INSTANCE.get', $java-relation-plural-name,'RelationDefinition(), d, name, p).getConfiguration();
',
+ ' ManagedObjectDefinition<M, ?> d, String name, Collection<DefaultBehaviorException> exceptions) {
',
+ ' return impl.createChild(INSTANCE.get', $java-relation-plural-name,'RelationDefinition(), d, name, exceptions).getConfiguration();
',
' }
')" />
<xsl:text>
</xsl:text>
<xsl:text>
</xsl:text>
@@ -1571,6 +1592,7 @@
<xsl:if
test="$this-local-properties[@multi-valued='true' or
@read-only='true' or
+ @monitoring='true' or
@hidden='true' or
@mandatory='true']">
<import>org.opends.server.admin.PropertyOption</import>
@@ -1589,6 +1611,34 @@
</import>
</xsl:if>
<xsl:if
+ test="$this-local-properties/adm:default-behavior/adm:inherited/adm:absolute">
+ <import>
+ org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider
+ </import>
+ <import>org.opends.server.admin.ManagedObjectPath</import>
+ </xsl:if>
+ <xsl:if
+ test="$this-local-properties/adm:default-behavior/adm:inherited/adm:relative">
+ <import>
+ org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider
+ </import>
+ <xsl:for-each
+ select="$this-local-properties/adm:default-behavior/adm:inherited/adm:relative">
+ <xsl:if test="@managed-object-package != $this-package">
+ <xsl:variable name="java-class-name">
+ <xsl:call-template name="name-to-java">
+ <xsl:with-param name="value"
+ select="@managed-object-name" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:element name="import">
+ <xsl:value-of
+ select="concat(@managed-object-package, '.meta.', $java-class-name, 'CfgDefn')" />
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if
test="$this-local-properties/adm:default-behavior/adm:defined">
<import>
org.opends.server.admin.DefinedDefaultBehaviorProvider
@@ -1655,6 +1705,12 @@
</import>
<import>org.opends.server.admin.PropertyProvider</import>
<import>
+ org.opends.server.admin.client.MissingMandatoryPropertiesException
+ </import>
+ <import>
+ org.opends.server.admin.ManagedObjectAlreadyExistsException
+ </import>
+ <import>
org.opends.server.admin.client.AuthorizationException
</import>
<import>
@@ -1692,8 +1748,9 @@
</import>
</xsl:if>
<xsl:if test="$this-all-relations/adm:one-to-many">
+ <import>java.util.Collection</import>
<import>
- org.opends.server.admin.ManagedObjectAlreadyExistsException
+ org.opends.server.admin.DefaultBehaviorException
</import>
<import>
org.opends.server.admin.server.ConfigurationAddListener
@@ -1704,8 +1761,9 @@
<import>org.opends.server.config.ConfigException</import>
</xsl:if>
<xsl:if test="$this-all-relations/adm:one-to-zero-or-one">
+ <import>java.util.Collection</import>
<import>
- org.opends.server.admin.ManagedObjectAlreadyExistsException
+ org.opends.server.admin.DefaultBehaviorException
</import>
<import>
org.opends.server.admin.server.ConfigurationAddListener
@@ -1722,6 +1780,9 @@
<import>java.util.SortedSet</import>
<import>java.util.Collection</import>
</xsl:if>
+ <xsl:if test="$this-all-properties[@read-only='true']">
+ <import>org.opends.server.admin.PropertyIsReadOnlyException</import>
+ </xsl:if>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="$this/@extends">
diff --git a/opendj-sdk/opends/resource/admin/preprocessor.xsl b/opendj-sdk/opends/resource/admin/preprocessor.xsl
index 56a18f7..246a4e2 100644
--- a/opendj-sdk/opends/resource/admin/preprocessor.xsl
+++ b/opendj-sdk/opends/resource/admin/preprocessor.xsl
@@ -696,6 +696,36 @@
</xsl:copy>
</xsl:template>
<!--
+ Process a relative inherited default behavior
+ -->
+ <xsl:template match="adm:relative" mode="pre-process">
+ <xsl:param name="mopackage" select="/.." />
+ <xsl:param name="moname" select="/.." />
+ <xsl:param name="hierarchy" select="/.." />
+ <xsl:copy>
+ <!--
+ Shallow copy.
+ -->
+ <xsl:copy-of select="@*" />
+ <!--
+ Add missing attribute managed-object-package if it is not provided.
+ -->
+ <xsl:if test="not(@managed-object-package)">
+ <xsl:attribute name="managed-object-package">
+ <xsl:value-of select="$mopackage" />
+ </xsl:attribute>
+ </xsl:if>
+ <!--
+ Apply templates to subordinate elements.
+ -->
+ <xsl:apply-templates mode="pre-process">
+ <xsl:with-param name="mopackage" select="$mopackage" />
+ <xsl:with-param name="moname" select="$moname" />
+ <xsl:with-param name="hierarchy" select="$hierarchy" />
+ </xsl:apply-templates>
+ </xsl:copy>
+ </xsl:template>
+ <!--
Process a user-friendly-name element.
-->
<xsl:template match="adm:user-friendly-name"
diff --git a/opendj-sdk/opends/resource/admin/property-types.xsl b/opendj-sdk/opends/resource/admin/property-types.xsl
index 9dc2aac..69f94d0 100644
--- a/opendj-sdk/opends/resource/admin/property-types.xsl
+++ b/opendj-sdk/opends/resource/admin/property-types.xsl
@@ -270,7 +270,7 @@
Generate the property setter declarations.
-->
<xsl:template name="generate-property-setter-declaration">
- <xsl:if test="string(@read-only) != 'true'">
+ <xsl:if test="not(@monitoring='true')">
<xsl:variable name="name" select="@name" />
<xsl:variable name="java-property-name">
<xsl:call-template name="name-to-java">
@@ -294,14 +294,28 @@
<xsl:with-param name="content" select="adm:description" />
</xsl:call-template>
</xsl:if>
+ <xsl:if test="@read-only='true'">
+ <xsl:value-of select="' * <p>
'" />
+ <xsl:value-of
+ select="concat(
+ ' * This property is read-only and can only be modified during
',
+ ' * creation of a ', $this-ufn, '.
')" />
+ </xsl:if>
<xsl:choose>
- <xsl:when test="string(@multi-valued) != 'true'">
+ <xsl:when test="not(@multi-valued='true')">
<xsl:value-of
select="concat(' *
',
' * @param value The value of the "', $name, '" property.
',
' * @throws IllegalPropertyValueException
',
- ' * If the new value is invalid.
',
- ' *
',
+ ' * If the new value is invalid.
')" />
+ <xsl:if test="@read-only='true'">
+ <xsl:value-of
+ select="concat(
+ ' * @throws PropertyIsReadOnlyException
',
+ ' * If this ', $this-ufn, ' is not being initialized.
')" />
+ </xsl:if>
+ <xsl:value-of
+ select="concat(
' */
',
' void set', $java-property-name, '(')" />
<xsl:choose>
@@ -313,23 +327,33 @@
<xsl:call-template name="get-property-java-type" />
</xsl:otherwise>
</xsl:choose>
- <xsl:value-of
- select="' value) throws IllegalPropertyValueException;
'" />
+ <xsl:value-of select="' value'" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of
select="concat(' *
',
' * @param values The values of the "', $name, '" property.
',
' * @throws IllegalPropertyValueException
',
- ' * If one or more of the new values are invalid.
',
- ' *
',
+ ' * If one or more of the new values are invalid.
')" />
+ <xsl:if test="@read-only='true'">
+ <xsl:value-of
+ select="concat(
+ ' * @throws PropertyIsReadOnlyException
',
+ ' * If this ', $this-ufn, ' is not being initialized.
')" />
+ </xsl:if>
+ <xsl:value-of
+ select="concat(
' */
',
' void set', $java-property-name, '(Collection<')" />
<xsl:call-template name="get-property-java-type" />
- <xsl:value-of
- select="'> values) throws IllegalPropertyValueException;
'" />
+ <xsl:value-of select="'> values'" />
</xsl:otherwise>
</xsl:choose>
+ <xsl:value-of select="') throws IllegalPropertyValueException'" />
+ <xsl:if test="@read-only='true'">
+ <xsl:value-of select="', PropertyIsReadOnlyException'" />
+ </xsl:if>
+ <xsl:value-of select="';
'" />
</xsl:if>
</xsl:template>
</xsl:stylesheet>
diff --git a/opendj-sdk/opends/src/ads/org/opends/admin/ads/ADSContextHelper.java b/opendj-sdk/opends/src/ads/org/opends/admin/ads/ADSContextHelper.java
index a925d19..2fce4d3 100644
--- a/opendj-sdk/opends/src/ads/org/opends/admin/ads/ADSContextHelper.java
+++ b/opendj-sdk/opends/src/ads/org/opends/admin/ads/ADSContextHelper.java
@@ -32,7 +32,6 @@
import javax.naming.ldap.InitialLdapContext;
-import org.opends.server.admin.client.InitialManagedObject;
import org.opends.server.admin.client.ManagementContext;
import org.opends.server.admin.client.ldap.JNDIDirContextAdaptor;
import org.opends.server.admin.client.ldap.LDAPManagementContext;
@@ -121,9 +120,7 @@
if (backend == null)
{
BackendCfgDefn provider = BackendCfgDefn.getInstance();
- backend = root.createBackend(provider, backendName,
- new InitialManagedObject<BackendCfgClient>(
- BackendCfgDefn.getInstance()));
+ backend = root.createBackend(provider, backendName, null);
}
SortedSet<DN> suffixes = backend.getBackendBaseDN();
if (suffixes == null)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java b/opendj-sdk/opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java
index d6b82c5..c1671af 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/AbsoluteInheritedDefaultBehaviorProvider.java
@@ -29,9 +29,10 @@
/**
- * A default behavior provider which retrieves default values from a managed
- * object in an abolute location. It should be used by properties which inherit
- * their default value(s) from properties held in an other managed object.
+ * A default behavior provider which retrieves default values from a
+ * managed object in an abolute location. It should be used by
+ * properties which inherit their default value(s) from properties
+ * held in an other managed object.
*
* @param <T>
* The type of values represented by this provider.
@@ -48,16 +49,26 @@
/**
- * Create an absolute inherited default behavior provider associated with the
- * managed object at the specified absolute location.
+ * Create an absolute inherited default behavior provider associated
+ * with the managed object at the specified absolute location.
*
* @param path
* The absolute location of the managed object.
* @param propertyName
- * The name of the property containing the inherited default values.
+ * The name of the property containing the inherited
+ * default values.
+ * @throws IllegalArgumentException
+ * If the named property is associated with the managed
+ * object definition identified by the path.
+ * @throws ClassCastException
+ * If the named property does not have the same type of
+ * property values as this default behavior provider.
*/
+ @SuppressWarnings("unchecked")
public AbsoluteInheritedDefaultBehaviorProvider(ManagedObjectPath path,
- String propertyName) {
+ String propertyName) throws IllegalArgumentException, ClassCastException {
+ // We do not decode the property name now because the property
+ // might not have been constructed at this point.
this.path = path;
this.propertyName = propertyName;
}
@@ -74,11 +85,24 @@
/**
- * Get the absolute path of the managed object containing the property which
- * has the default values.
+ * Get the definition of the parent managed object containing the
+ * inherited default values.
*
- * @return Returns the absolute path of the managed object containing the
- * property which has the default values.
+ * @return Returns the definition of the parent managed object
+ * containing the inherited default values.
+ */
+ public AbstractManagedObjectDefinition<?, ?> getManagedObjectDefinition() {
+ return path.getManagedObjectDefinition();
+ }
+
+
+
+ /**
+ * Get the absolute path of the managed object containing the
+ * property which has the default values.
+ *
+ * @return Returns the absolute path of the managed object
+ * containing the property which has the default values.
*/
public ManagedObjectPath getManagedObjectPath() {
return path;
@@ -87,10 +111,11 @@
/**
- * Get the name of the property containing the inherited default values.
+ * Get the name of the property containing the inherited default
+ * values.
*
- * @return Returns the name of the property containing the inherited default
- * values.
+ * @return Returns the name of the property containing the inherited
+ * default values.
*/
public String getPropertyName() {
return propertyName;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/ConfigurationClient.java b/opendj-sdk/opends/src/server/org/opends/server/admin/ConfigurationClient.java
index b5e5ba5..d5a1341 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/ConfigurationClient.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/ConfigurationClient.java
@@ -27,9 +27,12 @@
package org.opends.server.admin;
+
+
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.MissingMandatoryPropertiesException;
import org.opends.server.admin.client.OperationRejectedException;
@@ -62,22 +65,35 @@
/**
- * Commit any changes made to this configuration client.
+ * If this is a new configuration this method will attempt to add it
+ * to the server, otherwise it will commit any changes made to this
+ * configuration.
*
+ * @throws ManagedObjectAlreadyExistsException
+ * If this is a new configuration but it could not be
+ * added to the server because it already exists.
+ * @throws MissingMandatoryPropertiesException
+ * If this configuration contains some mandatory
+ * properties which have been left undefined.
* @throws ConcurrentModificationException
- * If this configuration has been removed from the server
- * by another client.
+ * If this is a new configuration which is being added to
+ * the server but its parent has been removed by another
+ * client, or if this configuration is being modified but
+ * it has been removed from the server by another client.
* @throws OperationRejectedException
- * If the server refuses to apply the changes due to some
- * server-side constraint which cannot be satisfied.
+ * If the server refuses to add or modify this
+ * configuration due to some server-side constraint which
+ * cannot be satisfied.
* @throws AuthorizationException
- * If the server refuses to apply the changes because the
- * client does not have the correct privileges.
+ * If the server refuses to add or modify this
+ * configuration because the client does not have the
+ * correct privileges.
* @throws CommunicationException
* If the client cannot contact the server due to an
* underlying communication problem.
*/
- void commit() throws ConcurrentModificationException,
+ void commit() throws ManagedObjectAlreadyExistsException,
+ MissingMandatoryPropertiesException, ConcurrentModificationException,
OperationRejectedException, AuthorizationException,
CommunicationException;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/DefaultBehaviorException.java b/opendj-sdk/opends/src/server/org/opends/server/admin/DefaultBehaviorException.java
new file mode 100644
index 0000000..1ecc04a
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/DefaultBehaviorException.java
@@ -0,0 +1,90 @@
+/*
+ * 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;
+
+
+
+/**
+ * This exception is thrown when a property's default values cannot be
+ * determined. This can occur in the following situations:
+ * <ul>
+ * <li>the property has a well-defined set of default values but they
+ * are invalid according to the property's syntax
+ * <li>the property inherits its default values from another managed
+ * object but they could not be retrieved, perhaps because of a
+ * communication problem.
+ * </ul>
+ */
+public class DefaultBehaviorException extends PropertyException {
+
+ /**
+ * Serialization ID.
+ */
+ private static final long serialVersionUID = -2542117466747573053L;
+
+ // The cause of this exception.
+ private final Throwable cause;
+
+
+
+ /**
+ * Create a new default behavior exception with a cause.
+ *
+ * @param pd
+ * The property definition whose default values could not
+ * be determined.
+ * @param cause
+ * The exception that prevented the default values from
+ * being determined.
+ */
+ public DefaultBehaviorException(PropertyDefinition pd, Throwable cause) {
+ super(pd);
+ this.cause = cause;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Throwable getCause() {
+ return cause;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getMessage() {
+ return "The default values could not be determined "
+ + "for the property \"" + getPropertyDefinition().getName() + "\"";
+ }
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/DefaultBehaviorPropertyValueException.java b/opendj-sdk/opends/src/server/org/opends/server/admin/DefaultBehaviorPropertyValueException.java
deleted file mode 100644
index c06c24e..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/DefaultBehaviorPropertyValueException.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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;
-
-
-
-/**
- * Thrown to indicate that a property's default values were invalid.
- */
-public class DefaultBehaviorPropertyValueException extends PropertyException {
-
- /**
- * Serialization ID.
- */
- private static final long serialVersionUID = 8653244240567431537L;
-
- // The underlying property exception that caused this exception
- private final PropertyException cause;
-
-
-
- /**
- * Create a new default behavior property value exception.
- *
- * @param d
- * The property definition.
- * @param cause
- * The property exception that caused this exception.
- */
- public DefaultBehaviorPropertyValueException(PropertyDefinition d,
- PropertyException cause) {
- super(d);
- this.cause = cause;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Throwable getCause() {
- return cause;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getMessage() {
- return "The default values could not be determined "
- + "for the property \"" + getPropertyDefinition().getName() + "\"";
- }
-
-
-
- /**
- * Get the property exception that caused this exception.
- *
- * @return Returns the property exception that caused this exception.
- */
- public final PropertyException getPropertyException() {
- return cause;
- }
-
-}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/InheritedDefaultValueException.java b/opendj-sdk/opends/src/server/org/opends/server/admin/InheritedDefaultValueException.java
deleted file mode 100644
index 1793271..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/InheritedDefaultValueException.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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;
-
-
-
-/**
- * Thrown to indicate that a property's inherited default values could not be
- * determined due to some underlying operations exception which occurred when
- * attempting to retrieve them.
- */
-public class InheritedDefaultValueException extends PropertyException {
-
- /**
- * Serialization ID.
- */
- private static final long serialVersionUID = 7228186032995472371L;
-
- // The operations exception that caused default value look up to fail.
- private final OperationsException cause;
-
-
-
- /**
- * Create a new inherited default value exception.
- *
- * @param d
- * The property definition.
- * @param cause
- * The operations exception that caused default value look up to
- * fail.
- */
- public InheritedDefaultValueException(PropertyDefinition d,
- OperationsException cause) {
- super(d);
- this.cause = cause;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Throwable getCause() {
- return cause;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getMessage() {
- return "The inherited default values could not be determined "
- + "for the property \"" + getPropertyDefinition().getName() + "\"";
- }
-
-
-
- /**
- * Get the operations exception that caused default value look up to fail.
- *
- * @return Returns the operations exception that caused default value look up
- * to fail.
- */
- public final OperationsException getOperationsException() {
- return cause;
- }
-
-}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/InheritedDefaultValueProvider.java b/opendj-sdk/opends/src/server/org/opends/server/admin/InheritedDefaultValueProvider.java
deleted file mode 100644
index 75e5a25..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/InheritedDefaultValueProvider.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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;
-
-
-
-/**
- * An interface for retrieving inherited default property values.
- */
-public interface InheritedDefaultValueProvider {
-
- /**
- * Get the path of the managed object which should be used as the base for
- * determining parent managed objects.
- *
- * @return Returns the path of the managed object which should be used as the
- * base for determining parent managed objects.
- */
- ManagedObjectPath getManagedObjectPath();
-
-
-
- /**
- * Retrieves the values of a property from a managed object at the specified
- * location.
- *
- * @param path
- * The location of the managed object containing the property.
- * @param propertyName
- * The name of the property containing the default values.
- * @return Returns the values of a property from a managed object at the
- * specified location.
- * @throws OperationsException
- * If the managed object could not be read due to some underlying
- * communication problem.
- * @throws PropertyNotFoundException
- * If the property name was not recognized.
- */
- Collection<?> getDefaultPropertyValues(ManagedObjectPath path,
- String propertyName) throws OperationsException,
- PropertyNotFoundException;
-}
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 1571cbb..ced9e0e8 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
@@ -44,6 +44,64 @@
/**
* A path which can be used to determine the location of a managed
* object instance.
+ * <p>
+ * A path is made up of zero or more elements each of which represents
+ * a managed object. Managed objects are arranged hierarchically with
+ * the root configuration being the top-most managed object. Elements
+ * are ordered such that the root configuration managed object is the
+ * first element and subsequent elements representing managed objects
+ * further down the hierarchy.
+ * <p>
+ * A path can be encoded into a string representation using the
+ * {@link #toString()} and {@link #toString(StringBuilder)} methods.
+ * Conversely, this string representation can be parsed using the
+ * {@link #valueOf(String)} method.
+ * <p>
+ * The string representation of a managed object path is similar in
+ * principle to a UNIX file-system path and is defined as follows:
+ * <ul>
+ * <li>the root element is represented by the string <code>/</code>
+ * <li>subordinate elements are arranged in big-endian order
+ * separated by a forward slash <code>/</code> character
+ * <li>an element representing a managed object associated with a
+ * one-to-one (singleton) or one-to-zero-or-one (optional) relation
+ * has the form <code>relation=</code><i>relation</i>
+ * <code>[+type=</code><i>definition</i><code>]</code>, where
+ * <i>relation</i> is the name of the relation and <i>definition</i>
+ * is the name of the referenced managed object's definition if
+ * required (usually this is implied by the relation itself)
+ * <li>an element representing a managed object associated with a
+ * one-to-many (instantiable) relation has the form
+ * <code>relation=</code><i>relation</i><code>[+type=</code>
+ * <i>definition</i><code>]</code><code>+name=</code><i>name</i>,
+ * where <i>relation</i> is the name of the relation and
+ * <i>definition</i> is the name of the referenced managed object's
+ * definition if required (usually this is implied by the relation
+ * itself), and <i>name</i> is the name of the managed object
+ * instance.
+ * </ul>
+ * The following path string representation identifies a connection
+ * handler instance (note that the <code>type</code> is not
+ * specified indicating that the path identifies a connection handler
+ * called <i>my handler</i> which can be any type of connection
+ * handler):
+ *
+ * <pre>
+ * /relation=connection-handler+name=my handler
+ * </pre>
+ *
+ * If the identified connection handler must be an LDAP connection
+ * handler then the above path should include the <code>type</code>:
+ *
+ * <pre>
+ * /relation=connection-handler+type=ldap-connection-handler+name=my handler
+ * </pre>
+ *
+ * The final example identifies the global configuration:
+ *
+ * <pre>
+ * /relation=global-configuration
+ * </pre>
*
* @param <C>
* The type of client managed object configuration that this
@@ -52,14 +110,14 @@
* The type of server managed object configuration that this
* path references.
*/
-public final class ManagedObjectPath
- <C extends ConfigurationClient, S extends Configuration> {
+public final class ManagedObjectPath<C extends ConfigurationClient,
+ S extends Configuration> {
/**
* Abstract path element.
*/
- private static abstract class Element
- <C extends ConfigurationClient, S extends Configuration> {
+ private static abstract class Element<C extends ConfigurationClient,
+ S extends Configuration> {
// The type of managed object referenced by this element.
private final AbstractManagedObjectDefinition<C, S> definition;
@@ -92,6 +150,17 @@
/**
+ * Get the relation definition associated with this element.
+ *
+ * @return Returns the relation definition associated with this
+ * element.
+ */
+ public abstract RelationDefinition<? super C, ? super S>
+ getRelationDefinition();
+
+
+
+ /**
* Serialize this path element using the provided serialization
* strategy.
*
@@ -111,8 +180,8 @@
extends Element<C, S> {
// Factory method.
- private static final
- <C extends ConfigurationClient, S extends Configuration>
+ private static final <C extends ConfigurationClient,
+ S extends Configuration>
InstantiableElement<C, S> create(
InstantiableRelationDefinition<? super C, ? super S> r,
AbstractManagedObjectDefinition<C, S> d, String name) {
@@ -142,6 +211,17 @@
* {@inheritDoc}
*/
@Override
+ public InstantiableRelationDefinition<? super C, ? super S>
+ getRelationDefinition() {
+ return r;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public void serialize(ManagedObjectPathSerializer serializer) {
serializer.appendManagedObjectPathElement(r,
getManagedObjectDefinition(), name);
@@ -158,9 +238,8 @@
extends Element<C, S> {
// Factory method.
- private static final
- <C extends ConfigurationClient, S extends Configuration>
- OptionalElement<C, S> create(
+ private static final <C extends ConfigurationClient,
+ S extends Configuration> OptionalElement<C, S> create(
OptionalRelationDefinition<? super C, ? super S> r,
AbstractManagedObjectDefinition<C, S> d) {
return new OptionalElement<C, S>(r, d);
@@ -184,6 +263,17 @@
* {@inheritDoc}
*/
@Override
+ public OptionalRelationDefinition<? super C, ? super S>
+ getRelationDefinition() {
+ return r;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public void serialize(ManagedObjectPathSerializer serializer) {
serializer
.appendManagedObjectPathElement(r, getManagedObjectDefinition());
@@ -200,9 +290,8 @@
extends Element<C, S> {
// Factory method.
- private static final
- <C extends ConfigurationClient, S extends Configuration>
- SingletonElement<C, S> create(
+ private static final <C extends ConfigurationClient,
+ S extends Configuration> SingletonElement<C, S> create(
SingletonRelationDefinition<? super C, ? super S> r,
AbstractManagedObjectDefinition<C, S> d) {
return new SingletonElement<C, S>(r, d);
@@ -227,6 +316,17 @@
* {@inheritDoc}
*/
@Override
+ public SingletonRelationDefinition<? super C, ? super S>
+ getRelationDefinition() {
+ return r;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public void serialize(ManagedObjectPathSerializer serializer) {
serializer
.appendManagedObjectPathElement(r, getManagedObjectDefinition());
@@ -312,8 +412,8 @@
// Single instance of a root path.
private static final ManagedObjectPath<RootCfgClient, RootCfg> EMPTY_PATH =
- new ManagedObjectPath<RootCfgClient, RootCfg>(
- new LinkedList<Element<?, ?>>(), RootCfgDefn.getInstance());
+ new ManagedObjectPath<RootCfgClient, RootCfg>(
+ new LinkedList<Element<?, ?>>(), null, RootCfgDefn.getInstance());
// A regular expression used to parse path elements.
private static final Pattern PE_REGEXP = Pattern
@@ -358,6 +458,7 @@
// Parse the elements.
LinkedList<Element<?, ?>> elements = new LinkedList<Element<?, ?>>();
+ Element<?, ?> lastElement = null;
AbstractManagedObjectDefinition<?, ?> definition = RootCfgDefn
.getInstance();
@@ -397,10 +498,14 @@
+ "\" in path \"" + ns + "\"");
}
- String relation = m.group(1); // Mandatory.
- String type = m.group(3); // Optional.
- String name = m.group(5); // Mandatory if relation is
- // instantiable.
+ // Mandatory.
+ String relation = m.group(1);
+
+ // Optional.
+ String type = m.group(3);
+
+ // Mandatory if relation is instantiable.
+ String name = m.group(5);
// Get the relation definition.
RelationDefinition<?, ?> r;
@@ -413,9 +518,9 @@
}
// Append the next element.
- Element<?, ?> e = createElement(r, ns, es, type, name);
- elements.add(e);
- definition = e.getManagedObjectDefinition();
+ lastElement = createElement(r, ns, es, type, name);
+ elements.add(lastElement);
+ definition = lastElement.getManagedObjectDefinition();
// Update start to point to the beginning of the next element.
if (end < ns.length()) {
@@ -428,7 +533,7 @@
}
// Construct the new path.
- return create(elements, definition);
+ return create(elements, lastElement);
}
@@ -437,9 +542,9 @@
// construction of new paths.
private static <C extends ConfigurationClient, S extends Configuration>
ManagedObjectPath<C, S> create(
- LinkedList<Element<?, ?>> elements,
- AbstractManagedObjectDefinition<C, S> definition) {
- return new ManagedObjectPath<C, S>(elements, definition);
+ LinkedList<Element<?, ?>> elements, Element<C, S> lastElement) {
+ return new ManagedObjectPath<C, S>(elements, lastElement
+ .getRelationDefinition(), lastElement.getManagedObjectDefinition());
}
@@ -508,19 +613,24 @@
}
}
- // The last element in this path.
- private final AbstractManagedObjectDefinition<C, S> definition;
+ // The managed object definition in this path.
+ private final AbstractManagedObjectDefinition<C, S> d;
// The list of path elements in this path.
private final List<Element<?, ?>> elements;
+ // The last relation definition in this path.
+ private final RelationDefinition<? super C, ? super S> r;
+
// Private constructor.
private ManagedObjectPath(LinkedList<Element<?, ?>> elements,
- AbstractManagedObjectDefinition<C, S> definition) {
+ RelationDefinition<? super C, ? super S> r,
+ AbstractManagedObjectDefinition<C, S> d) {
this.elements = Collections.unmodifiableList(elements);
- this.definition = definition;
+ this.r = r;
+ this.d = d;
}
@@ -552,7 +662,7 @@
LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
elements);
celements.add(new InstantiableElement<M, N>(r, d, name));
- return new ManagedObjectPath<M, N>(celements, d);
+ return new ManagedObjectPath<M, N>(celements, r, d);
}
@@ -607,7 +717,7 @@
LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
elements);
celements.add(new OptionalElement<M, N>(r, d));
- return new ManagedObjectPath<M, N>(celements, d);
+ return new ManagedObjectPath<M, N>(celements, r, d);
}
@@ -628,8 +738,7 @@
* provided parent path.
*/
public <M extends ConfigurationClient, N extends Configuration>
- ManagedObjectPath<M, N> child(
- OptionalRelationDefinition<M, N> r) {
+ ManagedObjectPath<M, N> child(OptionalRelationDefinition<M, N> r) {
return child(r, r.getChildDefinition());
}
@@ -660,7 +769,7 @@
LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
elements);
celements.add(new SingletonElement<M, N>(r, d));
- return new ManagedObjectPath<M, N>(celements, d);
+ return new ManagedObjectPath<M, N>(celements, r, d);
}
@@ -681,8 +790,7 @@
* provided parent path.
*/
public <M extends ConfigurationClient, N extends Configuration>
- ManagedObjectPath<M, N> child(
- SingletonRelationDefinition<M, N> r) {
+ ManagedObjectPath<M, N> child(SingletonRelationDefinition<M, N> r) {
return child(r, r.getChildDefinition());
}
@@ -716,7 +824,23 @@
* empty.
*/
public AbstractManagedObjectDefinition<C, S> getManagedObjectDefinition() {
- return definition;
+ return d;
+ }
+
+
+
+ /**
+ * Get the relation definition of the managed object referred to by
+ * this path.
+ * <p>
+ * When the path is empty, the <code>null</code> is returned.
+ *
+ * @return Returns the relation definition of the managed object
+ * referred to by this path, or the <code>null</code> if
+ * the path is empty.
+ */
+ public RelationDefinition<? super C, ? super S> getRelationDefinition() {
+ return r;
}
@@ -745,8 +869,8 @@
/**
* Creates a new parent managed object path representing the
- * immediate parent of this path. This method is a short-hand
- * for <code>parent(1)</code>.
+ * immediate parent of this path. This method is a short-hand for
+ * <code>parent(1)</code>.
*
* @return Returns a new parent managed object path representing the
* immediate parent of this path.
@@ -796,9 +920,7 @@
LinkedList<Element<?, ?>> celements = new LinkedList<Element<?, ?>>(
elements.subList(0, elements.size() - offset));
- AbstractManagedObjectDefinition<?, ?> definition = celements.getLast()
- .getManagedObjectDefinition();
- return create(celements, definition);
+ return create(celements, celements.getLast());
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/PropertyOption.java b/opendj-sdk/opends/src/server/org/opends/server/admin/PropertyOption.java
index 2d4341e..9f97611 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/PropertyOption.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/PropertyOption.java
@@ -30,13 +30,13 @@
/**
- * This enumeration contains various options that can be associated with
- * property definitions.
+ * This enumeration contains various options that can be associated
+ * with property definitions.
*/
public enum PropertyOption {
/**
- * Use this option to identify properties which must not be directly exposed
- * in client applications.
+ * Use this option to identify properties which must not be directly
+ * exposed in client applications.
*/
HIDDEN,
@@ -51,14 +51,21 @@
MULTI_VALUED,
/**
- * Use this option to identify properties which cannot be modified.
+ * Use this option to identify properties which can be initialized
+ * once only and are read-only thereafter.
*/
READ_ONLY,
/**
- * Use this option to identify properties which, when modified, will require
- * some additiona administrator action in order for the changes to take
- * effect.
+ * Use this option to identify properties which are for monitoring
+ * purposes only and are generated automatically by the server..
+ */
+ MONITORING,
+
+ /**
+ * Use this option to identify properties which, when modified, will
+ * require some additiona administrator action in order for the
+ * changes to take effect.
*/
REQUIRES_ADMIN_ACTION
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java b/opendj-sdk/opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java
index 49c52e9..ee9468a 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProvider.java
@@ -29,9 +29,10 @@
/**
- * A default behavior provider which retrieves default values from a parent
- * managed object. It should be used by properties which inherit their default
- * value(s) from properties held in an other managed object.
+ * A default behavior provider which retrieves default values from a
+ * parent managed object. It should be used by properties which
+ * inherit their default value(s) from properties held in an other
+ * managed object.
*
* @param <T>
* The type of values represented by this provider.
@@ -39,8 +40,11 @@
public final class RelativeInheritedDefaultBehaviorProvider<T> implements
DefaultBehaviorProvider<T> {
- // The relative offset (where 1 = parent, 2 = grandparent) of the managed
- // object containing the property.
+ // The type of managed object expected at the relative offset.
+ private final AbstractManagedObjectDefinition<?, ?> d;
+
+ // The relative offset (where 1 = parent, 2 = grandparent) of the
+ // managed object containing the property.
private final int offset;
// The name of the property containing the inherited default values.
@@ -49,23 +53,33 @@
/**
- * Create a relative inherited default behavior provider associated with a
- * parent managed object.
+ * Create a relative inherited default behavior provider associated
+ * with a parent managed object.
*
- * @param offset
- * The relative location of the parent managed object (where 0 is the
- * managed object itself, 1 is the parent, and 2 is the
- * grand-parent).
+ * @param d
+ * The type of parent managed object expected at the
+ * relative location.
* @param propertyName
- * The name of the property containing the inherited default values.
+ * The name of the property containing the inherited
+ * default values.
+ * @param offset
+ * The relative location of the parent managed object
+ * (where 0 is the managed object itself, 1 is the parent,
+ * and 2 is the grand-parent).
* @throws IllegalArgumentException
* If the offset is less than 0.
*/
- public RelativeInheritedDefaultBehaviorProvider(int offset,
- String propertyName) throws IllegalArgumentException {
+ @SuppressWarnings("unchecked")
+ public RelativeInheritedDefaultBehaviorProvider(
+ AbstractManagedObjectDefinition<?, ?> d, String propertyName, int offset)
+ throws IllegalArgumentException {
+ // We do not decode the property name now because the property
+ // might not have been constructed at this point (e.g. when the
+ // offset is 0).
if (offset < 0) {
throw new IllegalArgumentException("Negative offset");
}
+ this.d = d;
this.propertyName = propertyName;
this.offset = offset;
}
@@ -82,14 +96,27 @@
/**
- * Get the absolute path of the managed object containing the property which
- * has the default values.
+ * Get the definition of the parent managed object containing the
+ * inherited default values.
+ *
+ * @return Returns the definition of the parent managed object
+ * containing the inherited default values.
+ */
+ public AbstractManagedObjectDefinition<?, ?> getManagedObjectDefinition() {
+ return d;
+ }
+
+
+
+ /**
+ * Get the absolute path of the managed object containing the
+ * property which has the default values.
*
* @param path
- * The path of the current managed object from which the relative
- * path should be determined.
- * @return Returns the absolute path of the managed object containing the
- * property which has the default values.
+ * The path of the current managed object from which the
+ * relative path should be determined.
+ * @return Returns the absolute path of the managed object
+ * containing the property which has the default values.
*/
public ManagedObjectPath getManagedObjectPath(ManagedObjectPath path) {
return path.parent(offset);
@@ -98,10 +125,11 @@
/**
- * Get the name of the property containing the inherited default values.
+ * Get the name of the property containing the inherited default
+ * values.
*
- * @return Returns the name of the property containing the inherited default
- * values.
+ * @return Returns the name of the property containing the inherited
+ * default values.
*/
public String getPropertyName() {
return propertyName;
@@ -112,9 +140,9 @@
/**
* Get the relative location of the parent managed object.
*
- * @return Returns the relative location of the parent managed object (where 0
- * is the managed object itself, 1 is the parent, and 2 is the
- * grand-parent).
+ * @return Returns the relative location of the parent managed
+ * object (where 0 is the managed object itself, 1 is the
+ * parent, and 2 is the grand-parent).
*/
public int getRelativeOffset() {
return offset;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/StringPropertyProvider.java b/opendj-sdk/opends/src/server/org/opends/server/admin/StringPropertyProvider.java
deleted file mode 100644
index 6597197..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/StringPropertyProvider.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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;
-
-
-
-/**
- * An interface which can be used to initialize the contents of a managed object
- * using the string representation of property values.
- */
-public interface StringPropertyProvider {
-
- /**
- * A property provider which always returns empty property values, indicating
- * default behavior.
- */
- public static final StringPropertyProvider DEFAULT_PROVIDER =
- new StringPropertyProvider() {
-
- /**
- * {@inheritDoc}
- */
- public Collection<String> getPropertyValues(PropertyDefinition<?> d)
- throws IllegalArgumentException {
- return Collections.<String> emptySet();
- }
-
- };
-
-
-
- /**
- * Get the property string values associated with the specified property
- * definition.
- * <p>
- * Implementations are not required to validate the values that they provide.
- * Specifically:
- * <ul>
- * <li>they do not need to guarantee that the provided values are valid
- * according to the property's syntax
- * <li>they do not need to provide values for mandatory properties
- * <li>they do not need to ensure that single-valued properties do contain at
- * most one value.
- * </ul>
- * The returned set of values is allowed to contain duplicates.
- *
- * @param d
- * The Property definition.
- * @return Returns a newly allocated set containing a copy of the property's
- * string values. An empty set indicates that the property has no
- * values defined and any default behavior is applicable.
- * @throws IllegalArgumentException
- * If this property provider does not recognise the requested
- * property definition.
- */
- Collection<String> getPropertyValues(PropertyDefinition<?> d)
- throws IllegalArgumentException;
-}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/client/InitialManagedObject.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/InitialManagedObject.java
deleted file mode 100644
index b5a7c64..0000000
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/client/InitialManagedObject.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * 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 java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.SortedSet;
-
-import org.opends.server.admin.ConfigurationClient;
-import org.opends.server.admin.IllegalPropertyValueException;
-import org.opends.server.admin.InheritedDefaultValueProvider;
-import org.opends.server.admin.InstantiableRelationDefinition;
-import org.opends.server.admin.ManagedObjectDefinition;
-import org.opends.server.admin.ManagedObjectPath;
-import org.opends.server.admin.OperationsException;
-import org.opends.server.admin.OptionalRelationDefinition;
-import org.opends.server.admin.PropertyDefinition;
-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.PropertyNotFoundException;
-import org.opends.server.admin.PropertyProvider;
-import org.opends.server.admin.SingletonRelationDefinition;
-
-
-
-/**
- * A managed object which is not bound to any underlying management
- * context.
- * <p>
- * The purpose of this managed object implementation is to facilitate
- * the construction of new configuration objects. Once all appropriate
- * properties are set, the initial managed object can be used as a
- * property provider during an invocation of
- * <code>ManagedObject#createChild</code>.
- * <p>
- * Any attempt to commit, retrieve, list, remove, or add new child
- * managed objects will result in an
- * {@link UnsupportedOperationException}.
- *
- * @param <C>
- * The type of client configuration represented by the client
- * managed object.
- */
-public final class InitialManagedObject<C extends ConfigurationClient>
- implements ManagedObject<C> {
-
- /**
- * Internal inherited default value provider implementation.
- * <p>
- * FIXME: very dumb implementation which always throws a
- * PropertyNotFoundException.
- */
- private static class MyInheritedDefaultValueProvider implements
- InheritedDefaultValueProvider {
-
- // Private constructor.
- private MyInheritedDefaultValueProvider() {
- // No implementation required.
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public Collection<?> getDefaultPropertyValues(ManagedObjectPath path,
- String propertyName) throws OperationsException,
- PropertyNotFoundException {
- throw new PropertyNotFoundException(propertyName);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public ManagedObjectPath getManagedObjectPath() {
- return ManagedObjectPath.emptyPath();
- }
- }
-
- // The managed object definition associated with this managed
- // object.
- private final ManagedObjectDefinition<C, ?> definition;
-
- // The managed object's properties.
- private final PropertySet properties;
-
-
-
- /**
- * Creates a new initial managed object associated with the
- * specified definition.
- *
- * @param definition
- * The managed object definition.
- */
- public InitialManagedObject(ManagedObjectDefinition<C, ?> definition) {
- this.definition = definition;
-
- // FIXME: how will we cope with inherited default values?
- List<PropertyException> exceptions = new LinkedList<PropertyException>();
- this.properties = PropertySet.create(definition,
- PropertyProvider.DEFAULT_PROVIDER,
- new MyInheritedDefaultValueProvider(), exceptions);
- }
-
-
-
- /**
- * {@inheritDoc}
- * <p>
- * This implementation throws an
- * {@link UnsupportedOperationException}.
- */
- public void commit() throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
- }
-
-
-
- /**
- * {@inheritDoc}
- * <p>
- * This implementation throws an
- * {@link UnsupportedOperationException}.
- */
- public <M extends ConfigurationClient, N extends M>
- ManagedObject<N> createChild(
- InstantiableRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
- String name, PropertyProvider p) throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
- }
-
-
-
- /**
- * {@inheritDoc}
- * <p>
- * This implementation throws an
- * {@link UnsupportedOperationException}.
- */
- public <M extends ConfigurationClient, N extends M>
- ManagedObject<N> createChild(
- OptionalRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
- PropertyProvider p) throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
- }
-
-
-
- /**
- * {@inheritDoc}
- * <p>
- * This implementation throws an
- * {@link UnsupportedOperationException}.
- */
- public <M extends ConfigurationClient> ManagedObject<? extends M> getChild(
- InstantiableRelationDefinition<M, ?> d, String name)
- throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
- }
-
-
-
- /**
- * {@inheritDoc}
- * <p>
- * This implementation throws an
- * {@link UnsupportedOperationException}.
- */
- public <M extends ConfigurationClient> ManagedObject<? extends M> getChild(
- OptionalRelationDefinition<M, ?> d) throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
- }
-
-
-
- /**
- * {@inheritDoc}
- * <p>
- * This implementation throws an
- * {@link UnsupportedOperationException}.
- */
- public <M extends ConfigurationClient> ManagedObject<? extends M> getChild(
- SingletonRelationDefinition<M, ?> d)
- throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public C getConfiguration() {
- return definition.createClientConfiguration(this);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public ManagedObjectDefinition<C, ?> getManagedObjectDefinition() {
- return definition;
- }
-
-
-
- /**
- * {@inheritDoc}
- * <p>
- * This implementation throws an
- * {@link UnsupportedOperationException}.
- */
- public ManagedObjectPath getManagedObjectPath() {
- throw new UnsupportedOperationException();
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public <T> T getPropertyValue(PropertyDefinition<T> d)
- throws IllegalArgumentException {
- return properties.getPropertyValue(d);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public <T> SortedSet<T> getPropertyValues(PropertyDefinition<T> d)
- throws IllegalArgumentException {
- return properties.getPropertyValues(d);
- }
-
-
-
- /**
- * {@inheritDoc}
- * <p>
- * This implementation throws an
- * {@link UnsupportedOperationException}.
- */
- public boolean hasChild(OptionalRelationDefinition<?, ?> d)
- throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
- }
-
-
-
- /**
- * {@inheritDoc}
- * <p>
- * This implementation throws an
- * {@link UnsupportedOperationException}.
- */
- public String[] listChildren(InstantiableRelationDefinition<?, ?> d)
- throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
- }
-
-
-
- /**
- * {@inheritDoc}
- * <p>
- * This implementation throws an
- * {@link UnsupportedOperationException}.
- */
- public <M extends ConfigurationClient> void removeChild(
- InstantiableRelationDefinition<M, ?> d, String name)
- throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
- }
-
-
-
- /**
- * {@inheritDoc}
- * <p>
- * This implementation throws an
- * {@link UnsupportedOperationException}.
- */
- public <M extends ConfigurationClient> void removeChild(
- OptionalRelationDefinition<M, ?> d) throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
-
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public <T> void setPropertyValue(PropertyDefinition<T> d, T value)
- throws IllegalPropertyValueException, PropertyIsReadOnlyException,
- PropertyIsMandatoryException, IllegalArgumentException {
- properties.setPropertyValue(d, value);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public <T> void setPropertyValues(PropertyDefinition<T> d,
- Collection<T> values) throws IllegalPropertyValueException,
- PropertyIsSingleValuedException, PropertyIsReadOnlyException,
- PropertyIsMandatoryException, IllegalArgumentException {
- properties.setPropertyValues(d, values);
- }
-
-}
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 63694e0..857c634 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
@@ -32,6 +32,7 @@
import java.util.Collection;
import java.util.SortedSet;
+import org.opends.server.admin.DefaultBehaviorException;
import org.opends.server.admin.DefinitionDecodingException;
import org.opends.server.admin.IllegalPropertyValueException;
import org.opends.server.admin.InstantiableRelationDefinition;
@@ -91,27 +92,40 @@
PropertyProvider {
/**
- * Commit any changes made to this managed object. Pending property
- * values will be committed to the managed object. If successful,
- * the pending values will become active values.
+ * Adds this managed object to the server or commits any changes
+ * made to it depending on whether or not the managed object already
+ * exists on the server. Pending property values will be committed
+ * to the managed object. If successful, the pending values will
+ * become active values.
* <p>
* See the class description for more information regarding pending
* and active values.
*
+ * @throws ManagedObjectAlreadyExistsException
+ * If the managed object cannot be added to the server
+ * because it already exists.
+ * @throws MissingMandatoryPropertiesException
+ * If the managed object contains some mandatory
+ * properties which have been left undefined.
* @throws ConcurrentModificationException
- * If this managed object has been removed from the server
- * by another client.
+ * If the managed object is being added to the server but
+ * its parent has been removed by another client, or if
+ * this managed object is being modified but it has been
+ * removed from the server by another client.
* @throws OperationRejectedException
- * If the server refuses to apply the changes due to some
- * server-side constraint which cannot be satisfied.
+ * If the server refuses to add or modify this managed
+ * object due to some server-side constraint which cannot
+ * be satisfied.
* @throws AuthorizationException
- * If the server refuses to apply the changes because the
- * client does not have the correct privileges.
+ * If the server refuses to add or modify this managed
+ * object because the client does not have the correct
+ * privileges.
* @throws CommunicationException
* If the client cannot contact the server due to an
* underlying communication problem.
*/
- void commit() throws ConcurrentModificationException,
+ void commit() throws ManagedObjectAlreadyExistsException,
+ MissingMandatoryPropertiesException, ConcurrentModificationException,
OperationRejectedException, AuthorizationException,
CommunicationException;
@@ -119,10 +133,10 @@
/**
* Creates a new child managed object bound to the specified
- * instantiable relation. The new managed object instance will be
- * created with values taken from a property provider. The caller
- * must make sure that the property provider provides values for
- * mandatory properties.
+ * instantiable relation. The new managed object will initially not
+ * contain any property values (including mandatory properties).
+ * Once the managed object has been configured it can be added to
+ * the server using the {@link #commit()} method.
*
* @param <M>
* The expected type of the child managed object
@@ -136,50 +150,30 @@
* The definition of the managed object to be created.
* @param name
* The name of the child managed object.
- * @param p
- * A property provider which should be used to initialize
- * property values of the new managed object.
+ * @param exceptions
+ * A collection in which to place any
+ * {@link DefaultBehaviorException}s that occurred whilst
+ * attempting to determine the managed object's default
+ * values.
* @return Returns a new child managed object bound to the specified
* instantiable relation.
* @throws IllegalArgumentException
* If the relation definition is not associated with this
* managed object's definition.
- * @throws ManagedObjectDecodingException
- * If the managed object could not be create because one
- * or more of its properties are invalid.
- * @throws ManagedObjectAlreadyExistsException
- * If the managed object cannot be created because it
- * already exists on the server.
- * @throws ConcurrentModificationException
- * If this managed object has been removed from the server
- * by another client.
- * @throws OperationRejectedException
- * If the server refuses to create the managed object due
- * to some server-side constraint which cannot be
- * satisfied.
- * @throws AuthorizationException
- * If the server refuses to create the managed object
- * because the client does not have the correct
- * privileges.
- * @throws CommunicationException
- * If the client cannot contact the server due to an
- * underlying communication problem.
*/
<M extends ConfigurationClient, N extends M> ManagedObject<N> createChild(
InstantiableRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
- String name, PropertyProvider p) throws IllegalArgumentException,
- ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,
- ConcurrentModificationException, OperationRejectedException,
- AuthorizationException, CommunicationException;
+ String name, Collection<DefaultBehaviorException> exceptions)
+ throws IllegalArgumentException;
/**
* Creates a new child managed object bound to the specified
- * optional relation. The new managed object instance will be
- * created with values taken from a property provider. The caller
- * must make sure that the property provider provides values for
- * mandatory properties.
+ * optional relation. The new managed object will initially not
+ * contain any property values (including mandatory properties).
+ * Once the managed object has been configured it can be added to
+ * the server using the {@link #commit()} method.
*
* @param <M>
* The expected type of the child managed object
@@ -191,41 +185,21 @@
* The optional relation definition.
* @param d
* The definition of the managed object to be created.
- * @param p
- * A property provider which should be used to initialize
- * property values of the new managed object.
+ * @param exceptions
+ * A collection in which to place any
+ * {@link DefaultBehaviorException}s that occurred whilst
+ * attempting to determine the managed object's default
+ * values.
* @return Returns a new child managed object bound to the specified
* optional relation.
* @throws IllegalArgumentException
* If the relation definition is not associated with this
* managed object's definition.
- * @throws ManagedObjectDecodingException
- * If the managed object could not be created because one
- * or more of its properties are invalid.
- * @throws ManagedObjectAlreadyExistsException
- * If the managed object cannot be created because it
- * already exists on the server.
- * @throws ConcurrentModificationException
- * If this managed object has been removed from the server
- * by another client.
- * @throws OperationRejectedException
- * If the server refuses to create the managed object due
- * to some server-side constraint which cannot be
- * satisfied.
- * @throws AuthorizationException
- * If the server refuses to create the managed object
- * because the client does not have the correct
- * privileges.
- * @throws CommunicationException
- * If the client cannot contact the server due to an
- * underlying communication problem.
*/
<M extends ConfigurationClient, N extends M> ManagedObject<N> createChild(
OptionalRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
- PropertyProvider p) throws IllegalArgumentException,
- ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,
- ConcurrentModificationException, OperationRejectedException,
- AuthorizationException, CommunicationException;
+ Collection<DefaultBehaviorException> exceptions)
+ throws IllegalArgumentException;
@@ -576,7 +550,8 @@
* If the new pending value is deemed to be invalid
* according to the property definition.
* @throws PropertyIsReadOnlyException
- * If an attempt was made to modify a read-only property.
+ * If this is not a new managed object and the property is
+ * read-only or for monitoring purposes.
* @throws PropertyIsMandatoryException
* If an attempt was made to remove a mandatory property.
* @throws IllegalArgumentException
@@ -611,7 +586,8 @@
* If an attempt was made to add multiple pending values
* to a single-valued property.
* @throws PropertyIsReadOnlyException
- * If an attempt was made to modify a read-only property.
+ * If this is not a new managed object and the property is
+ * read-only or for monitoring purposes.
* @throws PropertyIsMandatoryException
* If an attempt was made to remove a mandatory property.
* @throws IllegalArgumentException
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/client/MissingMandatoryPropertiesException.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/MissingMandatoryPropertiesException.java
new file mode 100644
index 0000000..4b9f02a
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/client/MissingMandatoryPropertiesException.java
@@ -0,0 +1,120 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opends.server.admin.OperationsException;
+import org.opends.server.admin.PropertyIsMandatoryException;
+import org.opends.server.util.Validator;
+
+
+
+/**
+ * This exception is thrown when an attempt is made to add or modify a
+ * managed object when one or more of its mandatory properties are
+ * undefined.
+ */
+public class MissingMandatoryPropertiesException extends OperationsException {
+
+ /**
+ * Serialization ID.
+ */
+ private static final long serialVersionUID = 6342522125252055588L;
+
+ // The causes of this exception.
+ private final Collection<PropertyIsMandatoryException> causes;
+
+
+
+ /**
+ * Creates a new missing mandatory properties exception with the
+ * provided causes.
+ *
+ * @param causes
+ * The causes of this exception (must be non-<code>null</code>
+ * and non-empty).
+ */
+ public MissingMandatoryPropertiesException(
+ Collection<PropertyIsMandatoryException> causes) {
+ Validator.ensureNotNull(causes);
+ Validator.ensureTrue(!causes.isEmpty());
+
+ this.causes = new ArrayList<PropertyIsMandatoryException>(causes);
+ }
+
+
+
+ /**
+ * Gets the first exception that caused this exception.
+ *
+ * @return Returns the first exception that caused this exception.
+ */
+ @Override
+ public PropertyIsMandatoryException getCause() {
+ return causes.iterator().next();
+ }
+
+
+
+ /**
+ * Gets an unmodifiable collection view of the causes of this
+ * exception.
+ *
+ * @return Returns an unmodifiable collection view of the causes of
+ * this exception.
+ */
+ public Collection<PropertyIsMandatoryException> getCauses() {
+ return Collections.unmodifiableCollection(causes);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getMessage() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("The following properties are mandatory: ");
+ boolean isFirst = true;
+ for (PropertyIsMandatoryException e : causes) {
+ if (!isFirst) {
+ builder.append(", ");
+ }
+ builder.append(e.getPropertyDefinition().getName());
+ isFirst = false;
+ }
+ return builder.toString();
+ }
+
+}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/client/PropertySet.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/PropertySet.java
index 155ad0b..963b125 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/client/PropertySet.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/client/PropertySet.java
@@ -32,41 +32,23 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
-import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider;
-import org.opends.server.admin.AliasDefaultBehaviorProvider;
-import org.opends.server.admin.DefaultBehaviorPropertyValueException;
-import org.opends.server.admin.DefaultBehaviorProviderVisitor;
-import org.opends.server.admin.DefinedDefaultBehaviorProvider;
import org.opends.server.admin.IllegalPropertyValueException;
-import org.opends.server.admin.IllegalPropertyValueStringException;
-import org.opends.server.admin.InheritedDefaultValueException;
-import org.opends.server.admin.InheritedDefaultValueProvider;
-import org.opends.server.admin.ManagedObjectDefinition;
-import org.opends.server.admin.ManagedObjectPath;
-import org.opends.server.admin.OperationsException;
import org.opends.server.admin.PropertyDefinition;
-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.PropertyOption;
import org.opends.server.admin.PropertyProvider;
-import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider;
-import org.opends.server.admin.StringPropertyProvider;
-import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
/**
- * A set of properties. Instances of this class can be used as the core of a
- * managed object implementation.
+ * A set of properties. Instances of this class can be used as the
+ * core of a managed object implementation.
*/
public final class PropertySet implements PropertyProvider {
@@ -78,50 +60,65 @@
*/
private static final class MyProperty<T> implements Property<T> {
+ // The active set of values.
+ private final SortedSet<T> activeValues;
+
// The definition associated with this property.
private final PropertyDefinition<T> d;
// The default set of values (read-only).
private final SortedSet<T> defaultValues;
- // The active set of values (read-only).
- private final SortedSet<T> activeValues;
-
// The pending set of values.
private final SortedSet<T> pendingValues;
/**
- * Create a property with the provided sets of pre-validated default and
- * active values.
- * <p>
- * This constructor takes ownership of the provided value sets.
+ * Create a property with the provided sets of pre-validated
+ * default and active values.
*
- * @param d
+ * @param pd
* The property definition.
* @param defaultValues
* The set of default values for the property.
* @param activeValues
* The set of active values for the property.
*/
- public MyProperty(PropertyDefinition<T> d, SortedSet<T> defaultValues,
- SortedSet<T> activeValues) {
- this.d = d;
- this.defaultValues = Collections.unmodifiableSortedSet(defaultValues);
- this.activeValues = Collections.unmodifiableSortedSet(activeValues);
+ public MyProperty(PropertyDefinition<T> pd, Collection<T> defaultValues,
+ Collection<T> activeValues) {
+ this.d = pd;
- // Initially the pending values is the same as the active values.
+ SortedSet<T> sortedDefaultValues = new TreeSet<T>(pd);
+ sortedDefaultValues.addAll(defaultValues);
+ this.defaultValues = Collections
+ .unmodifiableSortedSet(sortedDefaultValues);
+
+ this.activeValues = new TreeSet<T>(pd);
+ this.activeValues.addAll(activeValues);
+
+ // Initially the pending values is the same as the active
+ // values.
this.pendingValues = new TreeSet<T>(this.activeValues);
}
/**
+ * Makes the pending values active.
+ */
+ public void commit() {
+ activeValues.clear();
+ activeValues.addAll(pendingValues);
+ }
+
+
+
+ /**
* {@inheritDoc}
*/
public SortedSet<T> getActiveValues() {
- return activeValues;
+ return Collections.unmodifiableSortedSet(activeValues);
}
@@ -181,21 +178,18 @@
* {@inheritDoc}
*/
public boolean isModified() {
- if (activeValues == pendingValues) {
+ if (activeValues.size() == pendingValues.size()
+ && activeValues.containsAll(pendingValues)) {
return false;
- } else if (activeValues.size() != pendingValues.size()) {
- return true;
- } else if (activeValues.containsAll(pendingValues)) {
- return false;
- } else {
- return true;
}
+ return true;
}
/**
- * Replace all pending values of this property with the provided values.
+ * Replace all pending values of this property with the provided
+ * values.
*
* @param c
* The new set of pending property values.
@@ -210,376 +204,19 @@
/**
* {@inheritDoc}
*/
- public boolean wasEmpty() {
- return activeValues.isEmpty();
- }
-
-
-
- /**
- * {@inheritDoc}
- */
@Override
public String toString() {
return getEffectiveValues().toString();
}
- }
-
-
-
- /**
- * Internal default behavior visitor implementation.
- *
- * @param <T>
- * The type of the default property values.
- */
- private static final class DefaultVisitor<T> implements
- DefaultBehaviorProviderVisitor<T, SortedSet<T>,
- Collection<PropertyException>> {
-
- // The property definition.
- private final PropertyDefinition<T> pd;
-
- // Used to retrieve inherited properties.
- private final InheritedDefaultValueProvider provider;
-
-
-
- // Private constructor.
- private DefaultVisitor(PropertyDefinition<T> pd,
- InheritedDefaultValueProvider provider) {
- this.pd = pd;
- this.provider = provider;
- }
-
-
-
- // Cast a set of objects to the required type.
- private Collection<T> castValues(Collection<?> values,
- Collection<PropertyException> exceptions) {
- List<T> castValues = new LinkedList<T>();
- for (Object value : values) {
- try {
- castValues.add(pd.castValue(value));
- } catch (ClassCastException e) {
- exceptions.add(new IllegalPropertyValueException(pd, value));
- }
- }
- return castValues;
- }
-
-
-
- // Build set of default values and validate them.
- private SortedSet<T> validateStrings(Collection<String> values,
- Collection<PropertyException> exceptions) {
- TreeSet<T> defaultValues = new TreeSet<T>(pd);
- for (String value : values) {
- try {
- defaultValues.add(pd.decodeValue(value));
- } catch (IllegalPropertyValueStringException e) {
- exceptions.add(new DefaultBehaviorPropertyValueException(pd, e));
- }
- }
-
- if (!pd.hasOption(PropertyOption.MULTI_VALUED)) {
- if (defaultValues.size() > 1) {
- PropertyException e = new PropertyIsSingleValuedException(pd);
- exceptions.add(new DefaultBehaviorPropertyValueException(pd, e));
- }
- }
-
- return defaultValues;
- }
-
-
-
- // Build set of default values and validate them.
- private SortedSet<T> validate(Collection<T> values,
- Collection<PropertyException> exceptions) {
- TreeSet<T> defaultValues = new TreeSet<T>(pd);
- for (T value : values) {
- try {
- pd.validateValue(value);
- defaultValues.add(value);
- } catch (IllegalPropertyValueException e) {
- exceptions.add(new DefaultBehaviorPropertyValueException(pd, e));
- }
- }
-
- if (!pd.hasOption(PropertyOption.MULTI_VALUED)) {
- if (defaultValues.size() > 1) {
- PropertyException e = new PropertyIsSingleValuedException(pd);
- exceptions.add(new DefaultBehaviorPropertyValueException(pd, e));
- }
- }
-
- return defaultValues;
- }
/**
* {@inheritDoc}
*/
- public SortedSet<T> visitAbsoluteInherited(
- AbsoluteInheritedDefaultBehaviorProvider<T> d,
- Collection<PropertyException> p) {
- // Get the values from the managed object at the specified path.
- try {
- // Get the property values/defaults.
- ManagedObjectPath path = d.getManagedObjectPath();
- Collection<?> values = provider.getDefaultPropertyValues(path, d
- .getPropertyName());
- return validate(castValues(values, p), p);
- } catch (OperationsException e) {
- p.add(new InheritedDefaultValueException(pd, e));
- return new TreeSet<T>(pd);
- }
+ public boolean wasEmpty() {
+ return activeValues.isEmpty();
}
-
-
-
- /**
- * {@inheritDoc}
- */
- public SortedSet<T> visitAlias(AliasDefaultBehaviorProvider<T> d,
- Collection<PropertyException> p) {
- // No values applicable - just return the empty set.
- return new TreeSet<T>(pd);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public SortedSet<T> visitDefined(DefinedDefaultBehaviorProvider<T> d,
- Collection<PropertyException> p) {
- return validateStrings(d.getDefaultValues(), p);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public SortedSet<T> visitRelativeInherited(
- RelativeInheritedDefaultBehaviorProvider<T> d,
- Collection<PropertyException> p) {
- if (d.getRelativeOffset() == 0) {
- // TODO: we're inheriting default values from another property in this
- // property set. Logging is a good use-case: there is a general logging
- // level for all categories and then category specific levels which can
- // override. Should the default values be determined dynamically every
- // time they are accessed? If dynamically, how will decoding errors be
- // handled? Dynamically: we could return a SortedSet<T> which is lazily
- // computed.
- return new TreeSet<T>(pd);
- } else {
- // Inheriting default values from a parent managed object.
- try {
- ManagedObjectPath base = provider.getManagedObjectPath();
- ManagedObjectPath path = d.getManagedObjectPath(base);
- Collection<?> values = provider.getDefaultPropertyValues(path, d
- .getPropertyName());
- return validate(castValues(values, p), p);
- } catch (OperationsException e) {
- p.add(new InheritedDefaultValueException(pd, e));
- return new TreeSet<T>(pd);
- }
- }
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public SortedSet<T> visitUndefined(UndefinedDefaultBehaviorProvider<T> d,
- Collection<PropertyException> p) {
- // No values applicable - just return the empty set.
- return new TreeSet<T>(pd);
- }
- }
-
-
-
- /**
- * Create a new property set using a property provider to supply the active
- * property values. This constructor takes care of validation of the property
- * values and retrieval of any default values.
- * <p>
- * Any exceptions that occurred whilst processing the properties will be
- * placed in the provided exception collection. Properties that caused the
- * exceptions will be created with an empty set of values (note that this
- * could mean that the resulting property set might contain empty mandatory
- * properties).
- *
- * @param d
- * The managed object definition.
- * @param p
- * The property provider.
- * @param i
- * An inherited managed object provider for retrieving inherited
- * properties.
- * @param exceptions
- * A collection in which any property exceptions can be placed.
- * @return Returns the new property set.
- */
- public static PropertySet create(ManagedObjectDefinition<?, ?> d,
- PropertyProvider p, InheritedDefaultValueProvider i,
- Collection<PropertyException> exceptions) {
- Map<PropertyDefinition, MyProperty> properties =
- new HashMap<PropertyDefinition, MyProperty>();
-
- // Copy the properties from the provider.
- for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
- createProperty(pd, p, i, properties, exceptions);
- }
-
- return new PropertySet(properties);
- }
-
-
-
- /**
- * Create a new property set using a string property provider to supply the
- * active property values. This constructor takes care of validation of the
- * property values and retrieval of any default values.
- * <p>
- * Any exceptions that occurred whilst processing the properties will be
- * placed in the provided exception collection. Properties that caused the
- * exceptions will be created with an empty set of values (note that this
- * could mean that the resulting property set might contain empty mandatory
- * properties).
- *
- * @param d
- * The managed object definition.
- * @param p
- * The string property provider.
- * @param i
- * An inherited managed object provider for retrieving inherited
- * properties.
- * @param exceptions
- * A collection in which any property exceptions can be placed.
- * @return Returns the new property set.
- */
- public static PropertySet create(ManagedObjectDefinition<?, ?> d,
- StringPropertyProvider p, InheritedDefaultValueProvider i,
- Collection<PropertyException> exceptions) {
- Map<PropertyDefinition, MyProperty> properties =
- new HashMap<PropertyDefinition, MyProperty>();
-
- // Copy the properties from the provider.
- for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
- createProperty(pd, p, i, properties, exceptions);
- }
-
- return new PropertySet(properties);
- }
-
-
-
- // Create new property using string values taken from a property provider.
- private static <T> void createProperty(PropertyDefinition<T> pd,
- StringPropertyProvider p, InheritedDefaultValueProvider i,
- Map<PropertyDefinition, MyProperty> properties,
- Collection<PropertyException> exceptions) {
-
- // Get the active values for this property.
- Collection<String> activeStringValues;
-
- try {
- activeStringValues = p.getPropertyValues(pd);
- } catch (IllegalArgumentException e) {
- // Default to empty set of values.
- activeStringValues = Collections.<String> emptySet();
- }
-
- SortedSet<T> activeValues = new TreeSet<T>(pd);
- boolean gotException = false;
- for (String stringValue : activeStringValues) {
- try {
- activeValues.add(pd.decodeValue(stringValue));
- } catch (IllegalPropertyValueStringException e) {
- exceptions.add(e);
- gotException = true;
- }
- }
-
- if (gotException == false) {
- if (pd.hasOption(PropertyOption.MANDATORY)) {
- if (activeValues.isEmpty()) {
- exceptions.add(new PropertyIsMandatoryException(pd));
- }
- }
- }
-
- createProperty(pd, activeValues, i, properties, exceptions);
- }
-
-
-
- // Create new property using values taken from a property provider.
- private static <T> void createProperty(PropertyDefinition<T> pd,
- PropertyProvider p, InheritedDefaultValueProvider i,
- Map<PropertyDefinition, MyProperty> properties,
- Collection<PropertyException> exceptions) {
- // Get the active values for this property.
- Collection<T> activeValues;
-
- try {
- activeValues = p.getPropertyValues(pd);
- } catch (IllegalArgumentException e) {
- // Default to empty set of values.
- activeValues = Collections.<T> emptySet();
- }
-
- SortedSet<T> validActiveValues = new TreeSet<T>(pd);
- boolean gotException = false;
- for (T value : activeValues) {
- try {
- pd.validateValue(value);
- validActiveValues.add(value);
- } catch (IllegalPropertyValueException e) {
- exceptions.add(e);
- gotException = true;
- }
- }
-
- if (gotException == false) {
- if (pd.hasOption(PropertyOption.MANDATORY)) {
- if (validActiveValues.isEmpty()) {
- exceptions.add(new PropertyIsMandatoryException(pd));
- }
- }
- }
-
- createProperty(pd, validActiveValues, i, properties, exceptions);
- }
-
-
-
- // Create new property using the provided validated values.
- private static <T> void createProperty(PropertyDefinition<T> pd,
- SortedSet<T> activeValues, InheritedDefaultValueProvider i,
- Map<PropertyDefinition, MyProperty> properties,
- Collection<PropertyException> exceptions) {
- // Do remaining validation of active values.
- if (!pd.hasOption(PropertyOption.MULTI_VALUED)) {
- if (activeValues.size() > 1) {
- exceptions.add(new PropertyIsSingleValuedException(pd));
- }
- }
-
- // Get the default values for this property.
- DefaultVisitor<T> visitor = new DefaultVisitor<T>(pd, i);
- SortedSet<T> defaultValues = pd.getDefaultBehaviorProvider().accept(
- visitor, exceptions);
-
- // Create the property.
- properties.put(pd, new MyProperty<T>(pd, defaultValues, activeValues));
}
// The properties.
@@ -587,25 +224,60 @@
- // Private constructor.
- private PropertySet(Map<PropertyDefinition, MyProperty> properties) {
- this.properties = properties;
+ /**
+ * Creates a new empty property set.
+ */
+ public PropertySet() {
+ this.properties = new HashMap<PropertyDefinition, MyProperty>();
}
/**
- * Get the property associated with the specified property definition.
+ * Creates a property with the provided sets of pre-validated
+ * default and active values.
+ *
+ * @param <T>
+ * The type of the property.
+ * @param pd
+ * The property definition.
+ * @param defaultValues
+ * The set of default values for the property.
+ * @param activeValues
+ * The set of active values for the property.
+ */
+ public <T> void addProperty(PropertyDefinition<T> pd,
+ Collection<T> defaultValues, Collection<T> activeValues) {
+ MyProperty<T> p = new MyProperty<T>(pd, defaultValues, activeValues);
+ properties.put(pd, p);
+ }
+
+
+
+ /**
+ * Makes all pending values active.
+ */
+ public void commit() {
+ for (MyProperty<?> p : properties.values()) {
+ p.commit();
+ }
+ }
+
+
+
+ /**
+ * Get the property associated with the specified property
+ * definition.
*
* @param <T>
* The underlying type of the property.
* @param d
* The Property definition.
- * @return Returns the property associated with the specified property
- * definition.
+ * @return Returns the property associated with the specified
+ * property definition.
* @throws IllegalArgumentException
- * If this property provider does not recognise the requested
- * property definition.
+ * If this property provider does not recognise the
+ * requested property definition.
*/
@SuppressWarnings("unchecked")
public <T> Property<T> getProperty(PropertyDefinition<T> d)
@@ -622,18 +294,19 @@
/**
* Get the effective value of the specified property.
* <p>
- * See the class description for more information about how the effective
- * property value is derived.
+ * See the class description for more information about how the
+ * effective property value is derived.
*
* @param <T>
* The type of the property to be retrieved.
* @param d
* The property to be retrieved.
- * @return Returns the property's effective value, or <code>null</code> if
- * there is no effective value defined.
+ * @return Returns the property's effective value, or
+ * <code>null</code> if there is no effective value
+ * defined.
* @throws IllegalArgumentException
- * If the property definition is not associated with this managed
- * object's definition.
+ * If the property definition is not associated with this
+ * managed object's definition.
*/
public <T> T getPropertyValue(PropertyDefinition<T> d)
throws IllegalArgumentException {
@@ -650,18 +323,18 @@
/**
* Get the effective values of the specified property.
* <p>
- * See the class description for more information about how the effective
- * property values are derived.
+ * See the class description for more information about how the
+ * effective property values are derived.
*
* @param <T>
* The type of the property to be retrieved.
* @param d
* The property to be retrieved.
- * @return Returns the property's effective values, or an empty set if there
- * are no effective values defined.
+ * @return Returns the property's effective values, or an empty set
+ * if there are no effective values defined.
* @throws IllegalArgumentException
- * If the property definition is not associated with this managed
- * object's definition.
+ * If the property definition is not associated with this
+ * managed object's definition.
*/
public <T> SortedSet<T> getPropertyValues(PropertyDefinition<T> d)
throws IllegalArgumentException {
@@ -674,29 +347,29 @@
/**
* Set a new pending value for the specified property.
* <p>
- * See the class description for more information regarding pending values.
+ * See the class description for more information regarding pending
+ * values.
*
* @param <T>
* The type of the property to be modified.
* @param d
* The property to be modified.
* @param value
- * The new pending value for the property, or <code>null</code> if
- * the property should be reset to its default behavior.
+ * The new pending value for the property, or
+ * <code>null</code> if the property should be reset to
+ * its default behavior.
* @throws IllegalPropertyValueException
- * If the new pending value is deemed to be invalid according to the
- * property definition.
- * @throws PropertyIsReadOnlyException
- * If an attempt was made to modify a read-only property.
+ * If the new pending value is deemed to be invalid
+ * according to the property definition.
* @throws PropertyIsMandatoryException
* If an attempt was made to remove a mandatory property.
* @throws IllegalArgumentException
- * If the specified property definition is not associated with this
- * managed object.
+ * If the specified property definition is not associated
+ * with this managed object.
*/
public <T> void setPropertyValue(PropertyDefinition<T> d, T value)
- throws IllegalPropertyValueException, PropertyIsReadOnlyException,
- PropertyIsMandatoryException, IllegalArgumentException {
+ throws IllegalPropertyValueException, PropertyIsMandatoryException,
+ IllegalArgumentException {
if (value == null) {
setPropertyValues(d, Collections.<T> emptySet());
} else {
@@ -709,51 +382,42 @@
/**
* Set a new pending values for the specified property.
* <p>
- * See the class description for more information regarding pending values.
+ * See the class description for more information regarding pending
+ * values.
*
* @param <T>
* The type of the property to be modified.
* @param d
* The property to be modified.
* @param values
- * A non-<code>null</code> set of new pending values for the
- * property (an empty set indicates that the property should be reset
- * to its default behavior). The set will not be referenced by this
- * managed object.
+ * A non-<code>null</code> set of new pending values for
+ * the property (an empty set indicates that the property
+ * should be reset to its default behavior). The set will
+ * not be referenced by this managed object.
* @throws IllegalPropertyValueException
- * If a new pending value is deemed to be invalid according to the
- * property definition.
+ * If a new pending value is deemed to be invalid
+ * according to the property definition.
* @throws PropertyIsSingleValuedException
- * If an attempt was made to add multiple pending values to a
- * single-valued property.
- * @throws PropertyIsReadOnlyException
- * If an attempt was made to modify a read-only property.
+ * If an attempt was made to add multiple pending values
+ * to a single-valued property.
* @throws PropertyIsMandatoryException
* If an attempt was made to remove a mandatory property.
* @throws IllegalArgumentException
- * If the specified property definition is not associated with this
- * managed object.
+ * If the specified property definition is not associated
+ * with this managed object.
*/
public <T> void setPropertyValues(PropertyDefinition<T> d,
Collection<T> values) throws IllegalPropertyValueException,
- PropertyIsSingleValuedException, PropertyIsReadOnlyException,
- PropertyIsMandatoryException, IllegalArgumentException {
+ PropertyIsSingleValuedException, PropertyIsMandatoryException,
+ IllegalArgumentException {
MyProperty<T> property = (MyProperty<T>) getProperty(d);
- if (d.hasOption(PropertyOption.READ_ONLY)) {
- throw new PropertyIsReadOnlyException(d);
+ if (values.size() > 1 && !d.hasOption(PropertyOption.MULTI_VALUED)) {
+ throw new PropertyIsSingleValuedException(d);
}
- if (!d.hasOption(PropertyOption.MULTI_VALUED)) {
- if (values.size() > 1) {
- throw new PropertyIsSingleValuedException(d);
- }
- }
-
- if (d.hasOption(PropertyOption.MANDATORY)) {
- if (values.isEmpty()) {
- throw new PropertyIsMandatoryException(d);
- }
+ if (values.isEmpty() && d.hasOption(PropertyOption.MANDATORY)) {
+ throw new PropertyIsMandatoryException(d);
}
// Validate each value.
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 d2f3d56..a0a5bfc 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
@@ -51,18 +51,22 @@
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
+import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider;
import org.opends.server.admin.AbstractManagedObjectDefinition;
+import org.opends.server.admin.AliasDefaultBehaviorProvider;
import org.opends.server.admin.ConfigurationClient;
+import org.opends.server.admin.DefaultBehaviorException;
+import org.opends.server.admin.DefaultBehaviorProviderVisitor;
+import org.opends.server.admin.DefinedDefaultBehaviorProvider;
import org.opends.server.admin.DefinitionDecodingException;
import org.opends.server.admin.DefinitionResolver;
import org.opends.server.admin.IllegalPropertyValueException;
-import org.opends.server.admin.InheritedDefaultValueProvider;
+import org.opends.server.admin.IllegalPropertyValueStringException;
import org.opends.server.admin.InstantiableRelationDefinition;
import org.opends.server.admin.ManagedObjectAlreadyExistsException;
import org.opends.server.admin.ManagedObjectDefinition;
import org.opends.server.admin.ManagedObjectNotFoundException;
import org.opends.server.admin.ManagedObjectPath;
-import org.opends.server.admin.OperationsException;
import org.opends.server.admin.OptionalRelationDefinition;
import org.opends.server.admin.PropertyDefinition;
import org.opends.server.admin.PropertyException;
@@ -70,16 +74,18 @@
import org.opends.server.admin.PropertyIsReadOnlyException;
import org.opends.server.admin.PropertyIsSingleValuedException;
import org.opends.server.admin.PropertyNotFoundException;
-import org.opends.server.admin.PropertyProvider;
+import org.opends.server.admin.PropertyOption;
import org.opends.server.admin.RelationDefinition;
+import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider;
import org.opends.server.admin.SingletonRelationDefinition;
-import org.opends.server.admin.StringPropertyProvider;
+import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
import org.opends.server.admin.DefinitionDecodingException.Reason;
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.ManagedObject;
import org.opends.server.admin.client.ManagedObjectDecodingException;
+import org.opends.server.admin.client.MissingMandatoryPropertiesException;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.admin.client.Property;
import org.opends.server.admin.client.PropertySet;
@@ -99,31 +105,66 @@
ManagedObject<C> {
/**
- * Internal inherited default value provider implementation.
+ * A default behavior visitor used for retrieving the default values
+ * of a property.
+ *
+ * @param <T>
+ * The type of the property.
*/
- private static class MyInheritedDefaultValueProvider implements
- InheritedDefaultValueProvider {
+ private static class DefaultValueFinder<T> implements
+ DefaultBehaviorProviderVisitor<T, Collection<T>, ManagedObjectPath> {
+
+ /**
+ * Get the default values for the specified property.
+ *
+ * @param <T>
+ * The type of the property.
+ * @param context
+ * The LDAP management context.
+ * @param p
+ * The managed object path of the current managed object.
+ * @param pd
+ * The property definition.
+ * @return Returns the default values for the specified property.
+ * @throws DefaultBehaviorException
+ * If the default values could not be retrieved or
+ * decoded properly.
+ */
+ public static <T> Collection<T> getDefaultValues(
+ LDAPManagementContext context, ManagedObjectPath p,
+ PropertyDefinition<T> pd) throws DefaultBehaviorException {
+ DefaultValueFinder<T> v = new DefaultValueFinder<T>(context, pd);
+ Collection<T> values = pd.getDefaultBehaviorProvider().accept(v, p);
+
+ if (v.exception != null) {
+ throw v.exception;
+ }
+
+ if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
+ throw new DefaultBehaviorException(pd,
+ new PropertyIsSingleValuedException(pd));
+ }
+
+ return values;
+ }
// The LDAP management context.
private final LDAPManagementContext context;
- // The base path.
- private final ManagedObjectPath path;
+ // Any exception that occurred whilst retrieving inherited default
+ // values.
+ private DefaultBehaviorException exception = null;
+
+ // The property definition whose default values are required.
+ private final PropertyDefinition<T> pd;
- /**
- * Create a new inherited default value provider.
- *
- * @param context
- * The LDAP management context.
- * @param path
- * The base path.
- */
- public MyInheritedDefaultValueProvider(LDAPManagementContext context,
- ManagedObjectPath path) {
+ // Private constructor.
+ private DefaultValueFinder(LDAPManagementContext context,
+ PropertyDefinition<T> pd) {
this.context = context;
- this.path = path;
+ this.pd = pd;
}
@@ -131,26 +172,15 @@
/**
* {@inheritDoc}
*/
- public Collection<?> getDefaultPropertyValues(ManagedObjectPath path,
- String propertyName) throws OperationsException,
- PropertyNotFoundException {
- ManagedObjectPath<?, ?> tmp = path;
- ManagedObject<?> mo;
+ public Collection<T> visitAbsoluteInherited(
+ AbsoluteInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) {
try {
- mo = readEntry(context, tmp, tmp.getManagedObjectDefinition());
- } catch (AuthorizationException e) {
- throw new OperationsException(e);
- } catch (CommunicationException e) {
- throw new OperationsException(e);
+ return getInheritedProperty(d.getManagedObjectPath(), d
+ .getManagedObjectDefinition(), d.getPropertyName());
+ } catch (DefaultBehaviorException e) {
+ exception = new DefaultBehaviorException(pd, e);
}
- ManagedObjectDefinition<?, ?> mod = mo.getManagedObjectDefinition();
-
- try {
- PropertyDefinition<?> dpd = mod.getPropertyDefinition(propertyName);
- return mo.getPropertyValues(dpd);
- } catch (IllegalArgumentException e) {
- throw new PropertyNotFoundException(propertyName);
- }
+ return Collections.emptySet();
}
@@ -158,10 +188,133 @@
/**
* {@inheritDoc}
*/
- public ManagedObjectPath getManagedObjectPath() {
- return path;
+ public Collection<T> visitAlias(AliasDefaultBehaviorProvider<T> d,
+ ManagedObjectPath p) {
+ return Collections.emptySet();
}
- }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<T> visitDefined(DefinedDefaultBehaviorProvider<T> d,
+ ManagedObjectPath p) {
+ Collection<String> stringValues = d.getDefaultValues();
+ List<T> values = new ArrayList<T>(stringValues.size());
+
+ for (String stringValue : stringValues) {
+ try {
+ values.add(pd.decodeValue(stringValue));
+ } catch (IllegalPropertyValueStringException e) {
+ exception = new DefaultBehaviorException(pd, e);
+ break;
+ }
+ }
+
+ return values;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<T> visitRelativeInherited(
+ RelativeInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) {
+ try {
+ return getInheritedProperty(d.getManagedObjectPath(p), d
+ .getManagedObjectDefinition(), d.getPropertyName());
+ } catch (DefaultBehaviorException e) {
+ exception = new DefaultBehaviorException(pd, e);
+ }
+ return Collections.emptySet();
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<T> visitUndefined(UndefinedDefaultBehaviorProvider<T> d,
+ ManagedObjectPath p) {
+ return Collections.emptySet();
+ }
+
+
+
+ // Get an inherited property value.
+ private Collection<T> getInheritedProperty(ManagedObjectPath target,
+ AbstractManagedObjectDefinition<?, ?> d, String propertyName)
+ throws DefaultBehaviorException {
+ try {
+ // First check that the requested type of managed object
+ // corresponds to the path.
+ AbstractManagedObjectDefinition<?, ?> supr = target
+ .getManagedObjectDefinition();
+ if (!supr.isParentOf(d)) {
+ throw new DefinitionDecodingException(Reason.WRONG_TYPE_INFORMATION);
+ }
+
+ // Get the actual managed object definition.
+ LdapName dn = LDAPNameBuilder.create(target, context.getLDAPProfile());
+ ManagedObjectDefinition<?, ?> mod = getEntryDefinition(context, d, dn);
+
+ PropertyDefinition<?> pd2;
+ try {
+ pd2 = mod.getPropertyDefinition(propertyName);
+ } catch (IllegalArgumentException e) {
+ throw new PropertyNotFoundException(propertyName);
+ }
+
+ String attrID = context.getLDAPProfile().getAttributeName(mod, pd2);
+ Attributes attributes = context.getLDAPConnection().readEntry(dn,
+ Collections.singleton(attrID));
+ Attribute attr = attributes.get(attrID);
+ if (attr == null || attr.size() == 0) {
+ // Recursively retrieve this property's default values.
+ Collection<?> tmp = getDefaultValues(context, target, pd2);
+ Collection<T> values = new ArrayList<T>(tmp.size());
+ for (Object o : tmp) {
+ T value;
+ try {
+ value = pd.castValue(o);
+ } catch (ClassCastException e) {
+ throw new IllegalPropertyValueException(pd, o);
+ }
+ pd.validateValue(value);
+ values.add(value);
+ }
+ return values;
+ } else {
+ Collection<T> values = new LinkedList<T>();
+ NamingEnumeration<?> ne = attr.getAll();
+ while (ne.hasMore()) {
+ Object value = ne.next();
+ if (value != null) {
+ values.add(pd.decodeValue(value.toString()));
+ }
+ }
+ return values;
+ }
+ } catch (DefinitionDecodingException e) {
+ throw new DefaultBehaviorException(pd, e);
+ } catch (PropertyNotFoundException e) {
+ throw new DefaultBehaviorException(pd, e);
+ } catch (IllegalPropertyValueException e) {
+ throw new DefaultBehaviorException(pd, e);
+ } catch (IllegalPropertyValueStringException e) {
+ throw new DefaultBehaviorException(pd, e);
+ } catch (NameNotFoundException e) {
+ throw new DefaultBehaviorException(pd,
+ new ManagedObjectNotFoundException());
+ } catch (NoPermissionException e) {
+ throw new DefaultBehaviorException(pd, new AuthorizationException(e));
+ } catch (NamingException e) {
+ throw new DefaultBehaviorException(pd, new CommunicationException(e));
+ }
+ }
+ };
@@ -176,30 +329,8 @@
*/
static ManagedObject<RootCfgClient> getRootManagedObject(
LDAPManagementContext context) {
- List<PropertyException> exceptions = new LinkedList<PropertyException>();
- InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
- context, ManagedObjectPath.emptyPath());
- PropertySet properties = PropertySet.create(RootCfgDefn.getInstance(),
- PropertyProvider.DEFAULT_PROVIDER, i, exceptions);
-
- // Should never get any exceptions.
- if (!exceptions.isEmpty()) {
- throw new RuntimeException(
- "Got exceptions when creating root managed object");
- }
-
return new LDAPManagedObject<RootCfgClient>(context, RootCfgDefn
- .getInstance(), ManagedObjectPath.emptyPath(), properties);
- }
-
-
-
- // Create a new child LDAP managed object.
- private static <M extends ConfigurationClient>
- ManagedObject<M> createLDAPManagedObject(
- LDAPManagementContext context, ManagedObjectDefinition<M, ?> d,
- ManagedObjectPath p, PropertySet properties) {
- return new LDAPManagedObject<M>(context, d, p, properties);
+ .getInstance(), ManagedObjectPath.emptyPath(), new PropertySet(), true);
}
@@ -247,104 +378,17 @@
return d.resolveManagedObjectDefinition(resolver);
}
-
-
- // Read the entry identified by the path and which is a sub-type of
- // the specified definition.
- private static <M extends ConfigurationClient>
- ManagedObject<? extends M> readEntry(
- final LDAPManagementContext context, ManagedObjectPath p,
- AbstractManagedObjectDefinition<M, ?> d)
- throws DefinitionDecodingException, ManagedObjectDecodingException,
- ManagedObjectNotFoundException, AuthorizationException,
- CommunicationException {
- LdapName dn = LDAPNameBuilder.create(p, context.getLDAPProfile());
-
- final ManagedObjectDefinition<? extends M, ?> mod;
- final Attributes attributes;
- try {
- mod = getEntryDefinition(context, d, dn);
- ArrayList<String> attrIds = new ArrayList<String>();
- for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
- String attrId = context.getLDAPProfile().getAttributeName(mod, pd);
- attrIds.add(attrId);
- }
- attributes = context.getLDAPConnection().readEntry(dn, attrIds);
- } catch (NameNotFoundException e) {
- throw new ManagedObjectNotFoundException();
- } catch (NoPermissionException e) {
- throw new AuthorizationException(e);
- } catch (NamingException e) {
- throw new CommunicationException(e);
- }
-
- // Create a provider which uses LDAP string representations.
-
- // TODO: the exception handling is a bit of a hack here.
- final List<NamingException> nelist = new LinkedList<NamingException>();
- StringPropertyProvider provider = new StringPropertyProvider() {
-
- public Collection<String> getPropertyValues(PropertyDefinition<?> d)
- throws IllegalArgumentException {
- String attrID = context.getLDAPProfile().getAttributeName(mod, d);
- Attribute attribute = attributes.get(attrID);
- List<String> values = new LinkedList<String>();
-
- if (attribute != null && attribute.size() != 0) {
- try {
- NamingEnumeration<?> ldapValues = attribute.getAll();
- while (ldapValues.hasMore()) {
- Object obj = ldapValues.next();
- if (obj != null) {
- values.add(obj.toString());
- }
- }
- } catch (NamingException e) {
- nelist.add(e);
- }
- }
-
- return values;
- }
-
- };
-
- // There can only be at most one exception.
- if (!nelist.isEmpty()) {
- try {
- throw nelist.get(0);
- } catch (NameNotFoundException e) {
- throw new ManagedObjectNotFoundException();
- } catch (NoPermissionException e) {
- throw new AuthorizationException(e);
- } catch (NamingException e) {
- throw new CommunicationException(e);
- }
- }
-
- // Now decode the properties using the provider.
- List<PropertyException> exceptions = new LinkedList<PropertyException>();
- InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
- context, p);
- PropertySet properties = PropertySet.create(mod, provider, i, exceptions);
- ManagedObject<? extends M> mo = createLDAPManagedObject(context, mod, p,
- properties);
-
- // If there were no decoding problems then return the object,
- // otherwise throw an operations exception.
- if (exceptions.isEmpty()) {
- return mo;
- } else {
- throw new ManagedObjectDecodingException(mo, exceptions);
- }
- }
+ // The LDAP management context used for the ldap connection.
+ private final LDAPManagementContext context;
// The managed object definition associated with this managed
// object.
private final ManagedObjectDefinition<C, ?> definition;
- // The LDAP management context used for the ldap connection.
- private final LDAPManagementContext context;
+ // Indicates whether or not this managed object exists on the server
+ // (false means the managed object is new and has not been
+ // committed).
+ private boolean existsOnServer;
// The path associated with this managed object.
private final ManagedObjectPath<?, ?> path;
@@ -357,11 +401,12 @@
// Create an new LDAP managed object with the provided JNDI context.
private LDAPManagedObject(LDAPManagementContext context,
ManagedObjectDefinition<C, ?> d, ManagedObjectPath path,
- PropertySet properties) {
+ PropertySet properties, boolean existsOnServer) {
this.definition = d;
this.context = context;
this.path = path;
this.properties = properties;
+ this.existsOnServer = existsOnServer;
}
@@ -369,36 +414,30 @@
/**
* {@inheritDoc}
*/
- public void commit() throws ConcurrentModificationException,
- OperationRejectedException, AuthorizationException,
- CommunicationException {
- // Build the list of modified attributes.
- ManagedObjectDefinition<C, ?> d = getManagedObjectDefinition();
- Attributes mods = new BasicAttributes();
- for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
+ public void commit() throws MissingMandatoryPropertiesException,
+ ConcurrentModificationException, OperationRejectedException,
+ AuthorizationException, CommunicationException,
+ ManagedObjectAlreadyExistsException {
+ // First make sure all mandatory properties are defined.
+ List<PropertyIsMandatoryException> exceptions =
+ new LinkedList<PropertyIsMandatoryException>();
+
+ for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
Property<?> p = properties.getProperty(pd);
- if (p.isModified()) {
- String attrID = context.getLDAPProfile().getAttributeName(d, pd);
- Attribute attribute = new BasicAttribute(attrID);
- encodeProperty(attribute, pd, properties);
- mods.put(attribute);
+ if (pd.hasOption(PropertyOption.MANDATORY) && p.isEmpty()) {
+ exceptions.add(new PropertyIsMandatoryException(pd));
}
}
- // Perform the LDAP modification if something has changed.
- if (mods.size() > 0) {
- try {
- LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
- context.getLDAPConnection().modifyEntry(dn, mods);
- } catch (NoPermissionException e) {
- throw new AuthorizationException(e);
- } catch (OperationNotSupportedException e) {
- // Unwilling to perform.
- throw new OperationRejectedException(e);
- } catch (NamingException e) {
- // Just treat it as a communication problem.
- throw new CommunicationException(e);
- }
+ if (!exceptions.isEmpty()) {
+ throw new MissingMandatoryPropertiesException(exceptions);
+ }
+
+ // Commit the managed object.
+ if (existsOnServer) {
+ commitExistingManagedObject();
+ } else {
+ commitNewManagedObject();
}
}
@@ -410,60 +449,11 @@
public <M extends ConfigurationClient, N extends M>
ManagedObject<N> createChild(
InstantiableRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
- String name, PropertyProvider p) throws IllegalArgumentException,
- ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,
- ConcurrentModificationException, OperationRejectedException,
- AuthorizationException, CommunicationException {
+ String name, Collection<DefaultBehaviorException> exceptions)
+ throws IllegalArgumentException {
validateRelationDefinition(r);
-
ManagedObjectPath childPath = path.child(r, name);
-
- // First make sure all the properties are valid.
- List<PropertyException> exceptions = new LinkedList<PropertyException>();
- InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
- context, childPath);
- PropertySet properties = PropertySet.create(d, p, i, exceptions);
- if (!exceptions.isEmpty()) {
- ManagedObject<N> mo = new LDAPManagedObject<N>(context, d, childPath,
- properties);
- throw new ManagedObjectDecodingException(mo, exceptions);
- }
-
- ensureThisManagedObjectExists();
-
- // TODO: this implementation does not handle relations which
- // comprise of more than one RDN arc (this will probably never
- // be required anyway).
- LdapName dn = LDAPNameBuilder.create(path, r, context.getLDAPProfile());
- if (!entryExists(dn)) {
- // Need to create the child managed object's parent entry i.e.
- // the entry representing the relation itself.
- Attributes attributes = new BasicAttributes();
-
- // Create the branch's object class attribute.
- Attribute oc = new BasicAttribute("objectClass");
- for (String objectClass : context.getLDAPProfile()
- .getInstantiableRelationObjectClasses(r)) {
- oc.add(objectClass);
- }
- attributes.put(oc);
-
- // Create the branch's naming attribute.
- Rdn rdn = dn.getRdn(dn.size() - 1);
- attributes.put(rdn.getType(), rdn.getValue().toString());
-
- // Create the entry.
- try {
- context.getLDAPConnection().createEntry(dn, attributes);
- } catch (OperationNotSupportedException e) {
- // Unwilling to perform.
- throw new OperationRejectedException(e);
- } catch (NamingException e) {
- adaptNamingException(e);
- }
- }
-
- return createManagedObject(childPath, d, properties);
+ return createNewManagedObject(d, childPath, exceptions);
}
@@ -474,28 +464,11 @@
public <M extends ConfigurationClient, N extends M>
ManagedObject<N> createChild(
OptionalRelationDefinition<M, ?> r, ManagedObjectDefinition<N, ?> d,
- PropertyProvider p) throws IllegalArgumentException,
- ManagedObjectDecodingException, ManagedObjectAlreadyExistsException,
- ConcurrentModificationException, OperationRejectedException,
- AuthorizationException, CommunicationException {
+ Collection<DefaultBehaviorException> exceptions)
+ throws IllegalArgumentException {
validateRelationDefinition(r);
-
ManagedObjectPath childPath = path.child(r);
-
- // First make sure all the properties are valid.
- List<PropertyException> exceptions = new LinkedList<PropertyException>();
- InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
- context, childPath);
- PropertySet properties = PropertySet.create(d, p, i, exceptions);
- if (!exceptions.isEmpty()) {
- ManagedObject<N> mo = new LDAPManagedObject<N>(context, d, childPath,
- properties);
- throw new ManagedObjectDecodingException(mo, exceptions);
- }
-
- ensureThisManagedObjectExists();
-
- return createManagedObject(childPath, d, properties);
+ return createNewManagedObject(d, childPath, exceptions);
}
@@ -511,7 +484,7 @@
CommunicationException {
validateRelationDefinition(d);
ensureThisManagedObjectExists();
- return readEntry(context, path.child(d, name), d.getChildDefinition());
+ return readManagedObject(d.getChildDefinition(), path.child(d, name));
}
@@ -526,7 +499,7 @@
AuthorizationException, CommunicationException {
validateRelationDefinition(d);
ensureThisManagedObjectExists();
- return readEntry(context, path.child(d), d.getChildDefinition());
+ return readManagedObject(d.getChildDefinition(), path.child(d));
}
@@ -541,7 +514,7 @@
AuthorizationException, CommunicationException {
validateRelationDefinition(d);
ensureThisManagedObjectExists();
- return readEntry(context, path.child(d), d.getChildDefinition());
+ return readManagedObject(d.getChildDefinition(), path.child(d));
}
@@ -674,6 +647,14 @@
public <T> void setPropertyValue(PropertyDefinition<T> d, T value)
throws IllegalPropertyValueException, PropertyIsReadOnlyException,
PropertyIsMandatoryException, IllegalArgumentException {
+ if (d.hasOption(PropertyOption.MONITORING)) {
+ throw new PropertyIsReadOnlyException(d);
+ }
+
+ if (existsOnServer && d.hasOption(PropertyOption.READ_ONLY)) {
+ throw new PropertyIsReadOnlyException(d);
+ }
+
properties.setPropertyValue(d, value);
}
@@ -686,6 +667,14 @@
Collection<T> values) throws IllegalPropertyValueException,
PropertyIsSingleValuedException, PropertyIsReadOnlyException,
PropertyIsMandatoryException, IllegalArgumentException {
+ if (d.hasOption(PropertyOption.MONITORING)) {
+ throw new PropertyIsReadOnlyException(d);
+ }
+
+ if (existsOnServer && d.hasOption(PropertyOption.READ_ONLY)) {
+ throw new PropertyIsReadOnlyException(d);
+ }
+
properties.setPropertyValues(d, values);
}
@@ -711,30 +700,118 @@
- // Creates a new managed object. The parent LDAP entry is assumed to
- // already exist.
- private <N extends ConfigurationClient> ManagedObject<N> createManagedObject(
- ManagedObjectPath path, ManagedObjectDefinition<N, ?> d,
- PropertySet properties) throws ManagedObjectAlreadyExistsException,
- OperationRejectedException, AuthorizationException,
- CommunicationException {
+ // Commit modifications made to this managed object.
+ private void commitExistingManagedObject()
+ throws ConcurrentModificationException, OperationRejectedException,
+ AuthorizationException, CommunicationException {
+ // Build the list of modified attributes.
+ Attributes mods = new BasicAttributes();
+ for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
+ Property<?> p = properties.getProperty(pd);
+ if (p.isModified()) {
+ String attrID = context.getLDAPProfile().getAttributeName(definition,
+ pd);
+ Attribute attribute = new BasicAttribute(attrID);
+ encodeProperty(attribute, pd, properties);
+ mods.put(attribute);
+ }
+ }
+
+ // Perform the LDAP modification if something has changed.
+ if (mods.size() > 0) {
+ try {
+ LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
+ context.getLDAPConnection().modifyEntry(dn, mods);
+ } catch (NoPermissionException e) {
+ throw new AuthorizationException(e);
+ } catch (OperationNotSupportedException e) {
+ // Unwilling to perform.
+ throw new OperationRejectedException(e);
+ } catch (NamingException e) {
+ // Just treat it as a communication problem.
+ throw new CommunicationException(e);
+ }
+ }
+
+ // The changes were committed successfully so update this managed
+ // object's state.
+ properties.commit();
+ }
+
+
+
+ // Commit this new managed object.
+ private void commitNewManagedObject() throws AuthorizationException,
+ CommunicationException, OperationRejectedException,
+ ConcurrentModificationException, ManagedObjectAlreadyExistsException {
+ // First make sure that the parent managed object still exists.
+ ManagedObjectPath<?, ?> parent = path.parent();
+ if (!parent.isEmpty()) {
+ LdapName dn = LDAPNameBuilder.create(parent, context.getLDAPProfile());
+ if (!entryExists(dn)) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ // We may need to create the parent "relation" entry if this is a
+ // child of an instantiable relation.
+ RelationDefinition<?, ?> r = path.getRelationDefinition();
+ if (r instanceof InstantiableRelationDefinition) {
+ InstantiableRelationDefinition<?, ?> ir =
+ (InstantiableRelationDefinition<?, ?>) r;
+
+ // TODO: this implementation does not handle relations which
+ // comprise of more than one RDN arc (this will probably never
+ // be required anyway).
+ LdapName dn = LDAPNameBuilder
+ .create(parent, ir, context.getLDAPProfile());
+ if (!entryExists(dn)) {
+ // We need to create the entry.
+ Attributes attributes = new BasicAttributes();
+
+ // Create the branch's object class attribute.
+ Attribute oc = new BasicAttribute("objectClass");
+ for (String objectClass : context.getLDAPProfile()
+ .getInstantiableRelationObjectClasses(ir)) {
+ oc.add(objectClass);
+ }
+ attributes.put(oc);
+
+ // Create the branch's naming attribute.
+ Rdn rdn = dn.getRdn(dn.size() - 1);
+ attributes.put(rdn.getType(), rdn.getValue().toString());
+
+ // Create the entry.
+ try {
+ context.getLDAPConnection().createEntry(dn, attributes);
+ } catch (OperationNotSupportedException e) {
+ // Unwilling to perform.
+ throw new OperationRejectedException(e);
+ } catch (NamingException e) {
+ adaptNamingException(e);
+ }
+ }
+ }
+
+ // Now add the entry representing this new managed object.
LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
Attributes attributes = new BasicAttributes(true);
- // Create the child's object class attribute.
+ // Create the object class attribute.
Attribute oc = new BasicAttribute("objectclass");
- for (String objectClass : context.getLDAPProfile().getObjectClasses(d)) {
+ for (String objectClass : context.getLDAPProfile().getObjectClasses(
+ definition)) {
oc.add(objectClass);
}
attributes.put(oc);
- // Create the child's naming attribute.
+ // Create the naming attribute.
Rdn rdn = dn.getRdn(dn.size() - 1);
attributes.put(rdn.getType(), rdn.getValue().toString());
// Create the remaining attributes.
- for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
- String attrID = context.getLDAPProfile().getAttributeName(d, pd);
+ for (PropertyDefinition<?> pd : definition.getAllPropertyDefinitions()) {
+ String attrID = context.getLDAPProfile().getAttributeName(definition, pd);
Attribute attribute = new BasicAttribute(attrID);
encodeProperty(attribute, pd, properties);
if (attribute.size() != 0) {
@@ -754,7 +831,108 @@
adaptNamingException(e);
}
- return new LDAPManagedObject<N>(context, d, path, properties);
+ // The entry was created successfully so update this managed
+ // object's state.
+ properties.commit();
+ existsOnServer = true;
+ }
+
+
+
+ // Create a managed object which already exists on the server.
+ private <M extends ConfigurationClient>
+ ManagedObject<M> createExistingManagedObject(
+ ManagedObjectDefinition<M, ?> d, ManagedObjectPath p,
+ PropertySet properties) {
+ return new LDAPManagedObject<M>(context, d, p, properties, true);
+ }
+
+
+
+ // Creates a new managed object with no active values, just default
+ // values.
+ private <M extends ConfigurationClient>
+ ManagedObject<M> createNewManagedObject(
+ ManagedObjectDefinition<M, ?> d, ManagedObjectPath p,
+ Collection<DefaultBehaviorException> exceptions) {
+ PropertySet childProperties = new PropertySet();
+ for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
+ try {
+ createProperty(childProperties, p, pd);
+ } catch (DefaultBehaviorException e) {
+ // Add the exception if requested.
+ if (exceptions != null) {
+ exceptions.add(e);
+ }
+ }
+ }
+
+ return new LDAPManagedObject<M>(context, d, p, childProperties, false);
+ }
+
+
+
+ // Create an empty property.
+ private <T> void createProperty(PropertySet properties, ManagedObjectPath p,
+ PropertyDefinition<T> pd) throws DefaultBehaviorException {
+ try {
+ Collection<T> defaultValues = DefaultValueFinder.getDefaultValues(
+ context, p, pd);
+ properties.addProperty(pd, defaultValues, Collections.<T> emptySet());
+ } catch (DefaultBehaviorException e) {
+ // Make sure that we have still created the property.
+ properties.addProperty(pd, Collections.<T> emptySet(), Collections
+ .<T> emptySet());
+ throw e;
+ }
+ }
+
+
+
+ // Create a property using the provided string values.
+ private <T> void decodeProperty(PropertySet newProperties,
+ ManagedObjectPath p, PropertyDefinition<T> pd, List<String> values)
+ throws PropertyException {
+ PropertyException exception = null;
+
+ // Get the property's active values.
+ Collection<T> activeValues = new ArrayList<T>(values.size());
+ for (String value : values) {
+ try {
+ activeValues.add(pd.decodeValue(value));
+ } catch (IllegalPropertyValueStringException e) {
+ exception = e;
+ }
+ }
+
+ if (activeValues.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
+ // This exception takes precedence over previous exceptions.
+ exception = new PropertyIsSingleValuedException(pd);
+ T value = activeValues.iterator().next();
+ activeValues.clear();
+ activeValues.add(value);
+ }
+
+ if (activeValues.isEmpty() && pd.hasOption(PropertyOption.MANDATORY)) {
+ // The active values maybe empty because of a previous exception.
+ if (exception == null) {
+ exception = new PropertyIsMandatoryException(pd);
+ }
+ }
+
+ // Get the property's default values.
+ Collection<T> defaultValues;
+ try {
+ defaultValues = DefaultValueFinder.getDefaultValues(context, p, pd);
+ } catch (DefaultBehaviorException e) {
+ defaultValues = Collections.emptySet();
+ exception = e;
+ }
+
+ newProperties.addProperty(pd, defaultValues, activeValues);
+ if (exception != null) {
+ throw exception;
+ }
}
@@ -775,9 +953,11 @@
private void ensureThisManagedObjectExists()
throws ConcurrentModificationException, CommunicationException,
AuthorizationException {
- LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
- if (!entryExists(dn)) {
- throw new ConcurrentModificationException();
+ if (!path.isEmpty()) {
+ LdapName dn = LDAPNameBuilder.create(path, context.getLDAPProfile());
+ if (!entryExists(dn)) {
+ throw new ConcurrentModificationException();
+ }
}
}
@@ -796,6 +976,75 @@
+ // Read the entry identified by the path and which is a sub-type of
+ // the specified definition.
+ private <M extends ConfigurationClient>
+ ManagedObject<? extends M> readManagedObject(
+ AbstractManagedObjectDefinition<M, ?> d, ManagedObjectPath p)
+ throws DefinitionDecodingException, ManagedObjectDecodingException,
+ ManagedObjectNotFoundException, AuthorizationException,
+ CommunicationException {
+ try {
+ // Read the entry associated with the managed object.
+ LdapName dn = LDAPNameBuilder.create(p, context.getLDAPProfile());
+ ManagedObjectDefinition<? extends M, ?> mod = getEntryDefinition(context,
+ d, dn);
+
+ ArrayList<String> attrIds = new ArrayList<String>();
+ for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
+ String attrId = context.getLDAPProfile().getAttributeName(mod, pd);
+ attrIds.add(attrId);
+ }
+
+ Attributes attributes = context.getLDAPConnection()
+ .readEntry(dn, attrIds);
+
+ // Build the managed object's properties.
+ List<PropertyException> exceptions = new LinkedList<PropertyException>();
+ PropertySet newProperties = new PropertySet();
+ for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
+ String attrID = context.getLDAPProfile().getAttributeName(mod, pd);
+ Attribute attribute = attributes.get(attrID);
+ List<String> values = new LinkedList<String>();
+
+ if (attribute != null && attribute.size() != 0) {
+ NamingEnumeration<?> ldapValues = attribute.getAll();
+ while (ldapValues.hasMore()) {
+ Object obj = ldapValues.next();
+ if (obj != null) {
+ values.add(obj.toString());
+ }
+ }
+ }
+
+ try {
+ decodeProperty(newProperties, p, pd, values);
+ } catch (PropertyException e) {
+ exceptions.add(e);
+ }
+ }
+
+ // If there were no decoding problems then return the object,
+ // otherwise throw an operations exception.
+ ManagedObject<? extends M> mo = createExistingManagedObject(mod, p,
+ newProperties);
+
+ if (exceptions.isEmpty()) {
+ return mo;
+ } else {
+ throw new ManagedObjectDecodingException(mo, exceptions);
+ }
+ } catch (NameNotFoundException e) {
+ throw new ManagedObjectNotFoundException();
+ } catch (NoPermissionException e) {
+ throw new AuthorizationException(e);
+ } catch (NamingException e) {
+ throw new CommunicationException(e);
+ }
+ }
+
+
+
// Remove the named managed object.
private void removeManagedObject(ManagedObjectPath p)
throws CommunicationException, AuthorizationException,
diff --git a/opendj-sdk/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java b/opendj-sdk/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java
index 654b806..6cc2865 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java
@@ -29,38 +29,49 @@
-import org.opends.server.loggers.debug.DebugTracer;
import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.messages.MessageHandler.getMessage;
-import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
+import static org.opends.server.messages.MessageHandler.*;
+import static org.opends.server.util.StaticUtils.*;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
+import java.util.TreeSet;
+import org.opends.server.admin.AbsoluteInheritedDefaultBehaviorProvider;
import org.opends.server.admin.AbstractManagedObjectDefinition;
+import org.opends.server.admin.AliasDefaultBehaviorProvider;
import org.opends.server.admin.Configuration;
+import org.opends.server.admin.DefaultBehaviorException;
+import org.opends.server.admin.DefaultBehaviorProviderVisitor;
+import org.opends.server.admin.DefinedDefaultBehaviorProvider;
import org.opends.server.admin.DefinitionDecodingException;
import org.opends.server.admin.DefinitionResolver;
-import org.opends.server.admin.InheritedDefaultValueProvider;
+import org.opends.server.admin.IllegalPropertyValueException;
+import org.opends.server.admin.IllegalPropertyValueStringException;
import org.opends.server.admin.InstantiableRelationDefinition;
import org.opends.server.admin.LDAPProfile;
import org.opends.server.admin.ManagedObjectDefinition;
-import org.opends.server.admin.ManagedObjectNotFoundException;
import org.opends.server.admin.ManagedObjectPath;
-import org.opends.server.admin.OperationsException;
import org.opends.server.admin.OptionalRelationDefinition;
import org.opends.server.admin.PropertyDefinition;
import org.opends.server.admin.PropertyException;
+import org.opends.server.admin.PropertyIsMandatoryException;
+import org.opends.server.admin.PropertyIsSingleValuedException;
import org.opends.server.admin.PropertyNotFoundException;
+import org.opends.server.admin.PropertyOption;
import org.opends.server.admin.PropertyProvider;
import org.opends.server.admin.RelationDefinition;
+import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider;
import org.opends.server.admin.SingletonRelationDefinition;
-import org.opends.server.admin.StringPropertyProvider;
-import org.opends.server.admin.client.PropertySet;
+import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
+import org.opends.server.admin.DefinitionDecodingException.Reason;
import org.opends.server.admin.std.meta.RootCfgDefn;
import org.opends.server.admin.std.server.RootCfg;
import org.opends.server.api.AttributeValueDecoder;
@@ -70,6 +81,7 @@
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
+import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.messages.AdminMessages;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
@@ -78,6 +90,7 @@
import org.opends.server.types.DirectoryException;
+
/**
* A server-side managed object.
*
@@ -85,81 +98,246 @@
* The type of server configuration represented by the server
* managed object.
*/
-public final class ServerManagedObject<S extends Configuration>
- implements PropertyProvider {
+public final class ServerManagedObject<S extends Configuration> implements
+ PropertyProvider {
+
+ /**
+ * A default behavior visitor used for retrieving the default values
+ * of a property.
+ *
+ * @param <T>
+ * The type of the property.
+ */
+ private static class DefaultValueFinder<T> implements
+ DefaultBehaviorProviderVisitor<T, Collection<T>, ManagedObjectPath> {
+
+ /**
+ * Get the default values for the specified property.
+ *
+ * @param <T>
+ * The type of the property.
+ * @param p
+ * The managed object path of the current managed object.
+ * @param pd
+ * The property definition.
+ * @return Returns the default values for the specified property.
+ * @throws DefaultBehaviorException
+ * If the default values could not be retrieved or
+ * decoded properly.
+ */
+ public static <T> Collection<T> getDefaultValues(ManagedObjectPath p,
+ PropertyDefinition<T> pd) throws DefaultBehaviorException {
+ DefaultValueFinder<T> v = new DefaultValueFinder<T>(pd);
+ Collection<T> values = pd.getDefaultBehaviorProvider().accept(v, p);
+
+ if (v.exception != null) {
+ throw v.exception;
+ }
+
+ if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
+ throw new DefaultBehaviorException(pd,
+ new PropertyIsSingleValuedException(pd));
+ }
+
+ return values;
+ }
+
+ // Any exception that occurred whilst retrieving inherited default
+ // values.
+ private DefaultBehaviorException exception = null;
+
+ // The property definition whose default values are required.
+ private final PropertyDefinition<T> pd;
+
+
+
+ // Private constructor.
+ private DefaultValueFinder(PropertyDefinition<T> pd) {
+ this.pd = pd;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<T> visitAbsoluteInherited(
+ AbsoluteInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) {
+ try {
+ return getInheritedProperty(d.getManagedObjectPath(), d
+ .getManagedObjectDefinition(), d.getPropertyName());
+ } catch (DefaultBehaviorException e) {
+ exception = new DefaultBehaviorException(pd, e);
+ }
+ return Collections.emptySet();
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<T> visitAlias(AliasDefaultBehaviorProvider<T> d,
+ ManagedObjectPath p) {
+ return Collections.emptySet();
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<T> visitDefined(DefinedDefaultBehaviorProvider<T> d,
+ ManagedObjectPath p) {
+ Collection<String> stringValues = d.getDefaultValues();
+ List<T> values = new ArrayList<T>(stringValues.size());
+
+ for (String stringValue : stringValues) {
+ try {
+ values.add(pd.decodeValue(stringValue));
+ } catch (IllegalPropertyValueStringException e) {
+ exception = new DefaultBehaviorException(pd, e);
+ break;
+ }
+ }
+
+ return values;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<T> visitRelativeInherited(
+ RelativeInheritedDefaultBehaviorProvider<T> d, ManagedObjectPath p) {
+ try {
+ return getInheritedProperty(d.getManagedObjectPath(p), d
+ .getManagedObjectDefinition(), d.getPropertyName());
+ } catch (DefaultBehaviorException e) {
+ exception = new DefaultBehaviorException(pd, e);
+ }
+ return Collections.emptySet();
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection<T> visitUndefined(UndefinedDefaultBehaviorProvider<T> d,
+ ManagedObjectPath p) {
+ return Collections.emptySet();
+ }
+
+
+
+ // Get an inherited property value.
+ private Collection<T> getInheritedProperty(ManagedObjectPath target,
+ AbstractManagedObjectDefinition<?, ?> d, String propertyName)
+ throws DefaultBehaviorException {
+ try {
+ // First check that the requested type of managed object
+ // corresponds to the path.
+ AbstractManagedObjectDefinition<?, ?> supr = target
+ .getManagedObjectDefinition();
+ if (!supr.isParentOf(d)) {
+ throw new DefinitionDecodingException(Reason.WRONG_TYPE_INFORMATION);
+ }
+
+ // Get the actual managed object definition.
+ DN dn = DNBuilder.create(target);
+ ConfigEntry configEntry = getManagedObjectConfigEntry(dn);
+ DefinitionResolver resolver = new MyDefinitionResolver(configEntry);
+ ManagedObjectDefinition<?, ?> mod = d
+ .resolveManagedObjectDefinition(resolver);
+
+ PropertyDefinition<?> pd2;
+ try {
+ pd2 = mod.getPropertyDefinition(propertyName);
+ } catch (IllegalArgumentException e) {
+ throw new PropertyNotFoundException(propertyName);
+ }
+
+ List<String> stringValues = getAttribute(mod, pd2, configEntry);
+ if (stringValues.isEmpty()) {
+ // Recursively retrieve this property's default values.
+ Collection<?> tmp = getDefaultValues(target, pd2);
+ Collection<T> values = new ArrayList<T>(tmp.size());
+ for (Object o : tmp) {
+ T value;
+ try {
+ value = pd.castValue(o);
+ } catch (ClassCastException e) {
+ throw new IllegalPropertyValueException(pd, o);
+ }
+ pd.validateValue(value);
+ values.add(value);
+ }
+ return values;
+ } else {
+ Collection<T> values = new ArrayList<T>(stringValues.size());
+ for (String s : stringValues) {
+ values.add(pd.decodeValue(s));
+ }
+ return values;
+ }
+ } catch (DefinitionDecodingException e) {
+ throw new DefaultBehaviorException(pd, e);
+ } catch (PropertyNotFoundException e) {
+ throw new DefaultBehaviorException(pd, e);
+ } catch (IllegalPropertyValueException e) {
+ throw new DefaultBehaviorException(pd, e);
+ } catch (IllegalPropertyValueStringException e) {
+ throw new DefaultBehaviorException(pd, e);
+ } catch (ConfigException e) {
+ throw new DefaultBehaviorException(pd, e);
+ }
+ }
+ }
+
+
+
+ /**
+ * A definition resolver that determines the managed object
+ * definition from the object classes of a ConfigEntry.
+ */
+ private static class MyDefinitionResolver implements DefinitionResolver {
+
+ // The config entry.
+ private final ConfigEntry entry;
+
+
+
+ // Private constructor.
+ private MyDefinitionResolver(ConfigEntry entry) {
+ this.entry = entry;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean matches(AbstractManagedObjectDefinition<?, ?> d) {
+ String oc = LDAPProfile.getInstance().getObjectClass(d);
+ return entry.hasObjectClass(oc);
+ }
+ };
+
+ /**
+ * The root server managed object.
+ */
+ private static final ServerManagedObject<RootCfg> ROOT =
+ new ServerManagedObject<RootCfg>(
+ ManagedObjectPath.emptyPath(), RootCfgDefn.getInstance(), Collections
+ .<PropertyDefinition<?>, SortedSet<?>> emptyMap(), null);
/**
* The tracer object for the debug logger.
*/
private static final DebugTracer TRACER = getTracer();
- /**
- * Internal inherited default value provider implementation.
- */
- private static class MyInheritedDefaultValueProvider implements
- InheritedDefaultValueProvider {
-
- // The base path.
- private final ManagedObjectPath<?, ?> path;
-
-
-
- /**
- * Create a new inherited default value provider.
- *
- * @param path
- * The base path.
- */
- public MyInheritedDefaultValueProvider(ManagedObjectPath path) {
- this.path = path;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public Collection<?> getDefaultPropertyValues(
- ManagedObjectPath path, String propertyName)
- throws OperationsException, PropertyNotFoundException {
- // Get the configuration entry.
- DN targetDN = DNBuilder.create(path);
- final ConfigEntry configEntry;
- try {
- configEntry = DirectoryServer.getConfigEntry(targetDN);
- } catch (ConfigException e) {
- throw new ManagedObjectNotFoundException(e);
- }
-
- if (configEntry == null) {
- throw new ManagedObjectNotFoundException();
- }
-
- ManagedObjectPath<?, ?> tmp = path;
- ServerManagedObject<?> mo = decode(tmp, tmp
- .getManagedObjectDefinition(), configEntry);
- ManagedObjectDefinition<?, ?> mod = mo
- .getManagedObjectDefinition();
- try {
- PropertyDefinition<?> dpd = mod
- .getPropertyDefinition(propertyName);
- return mo.getPropertyValues(dpd);
- } catch (IllegalArgumentException e) {
- throw new PropertyNotFoundException(propertyName);
- }
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public ManagedObjectPath getManagedObjectPath() {
- return path;
- }
-
- }
-
/**
@@ -183,74 +361,34 @@
* If one or more of the managed object's properties could
* not be decoded.
*/
- static <S extends Configuration>
- ServerManagedObject<? extends S> decode(
- ManagedObjectPath path,
- AbstractManagedObjectDefinition<?, S> definition,
- final ConfigEntry configEntry)
- throws DefinitionDecodingException,
+ static <S extends Configuration> ServerManagedObject<? extends S> decode(
+ ManagedObjectPath path, AbstractManagedObjectDefinition<?, S> definition,
+ ConfigEntry configEntry) throws DefinitionDecodingException,
ServerManagedObjectDecodingException {
// First determine the correct definition to use for the entry.
// This could either be the provided definition, or one of its
// sub-definitions.
- DefinitionResolver resolver = new DefinitionResolver() {
-
- public boolean matches(AbstractManagedObjectDefinition<?, ?> d) {
- String oc = LDAPProfile.getInstance().getObjectClass(d);
- return configEntry.hasObjectClass(oc);
- }
-
- };
-
- final ManagedObjectDefinition<?, ? extends S> mod = definition
+ DefinitionResolver resolver = new MyDefinitionResolver(configEntry);
+ ManagedObjectDefinition<?, ? extends S> mod = definition
.resolveManagedObjectDefinition(resolver);
- // Use a string-based property provider to pull in the property
- // values.
- StringPropertyProvider provider = new StringPropertyProvider() {
-
- public Collection<String> getPropertyValues(
- PropertyDefinition<?> d) throws IllegalArgumentException {
- String attrID = LDAPProfile.getInstance().getAttributeName(
- mod, d);
- // TODO: we create a default attribute type if it is
- // undefined. We should log a warning here if this is the case
- // since the attribute should have been defined.
- AttributeType type = DirectoryServer.getAttributeType(attrID, true);
- AttributeValueDecoder<String> decoder =
- new AttributeValueDecoder<String>() {
-
- public String decode(AttributeValue value)
- throws DirectoryException {
- return value.getStringValue();
- }
- };
-
- try {
- Collection<String> values = new LinkedList<String>();
- configEntry.getEntry().getAttributeValues(type, decoder,
- values);
- return values;
- } catch (DirectoryException e) {
- // Should not happen.
- throw new RuntimeException(e);
- }
- }
-
- };
-
- // Create the new managed object's property set, saving any
- // decoding exceptions.
+ // Build the managed object's properties.
List<PropertyException> exceptions = new LinkedList<PropertyException>();
- InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
- path);
- PropertySet properties = PropertySet.create(mod, provider, i,
- exceptions);
- ServerManagedObject<? extends S> mo = decodeAux(path, mod,
- properties, configEntry);
+ Map<PropertyDefinition<?>, SortedSet<?>> properties =
+ new HashMap<PropertyDefinition<?>, SortedSet<?>>();
+ for (PropertyDefinition<?> pd : mod.getAllPropertyDefinitions()) {
+ List<String> values = getAttribute(mod, pd, configEntry);
+ try {
+ decodeProperty(properties, path, pd, values);
+ } catch (PropertyException e) {
+ exceptions.add(e);
+ }
+ }
- // If there were no decoding problems then return the object,
- // otherwise throw an operations exception.
+ // If there were no decoding problems then return the managed
+ // object, otherwise throw an operations exception.
+ ServerManagedObject<? extends S> mo = decodeAux(path, mod, properties,
+ configEntry);
if (exceptions.isEmpty()) {
return mo;
} else {
@@ -261,28 +399,12 @@
/**
- * Construct a root server managed object.
+ * Gets the root server managed object.
*
- * @return Returns a root server managed object.
+ * @return Returns the root server managed object.
*/
static ServerManagedObject<RootCfg> getRootManagedObject() {
- ManagedObjectPath path = ManagedObjectPath.emptyPath();
- List<PropertyException> exceptions = new LinkedList<PropertyException>();
- InheritedDefaultValueProvider i = new MyInheritedDefaultValueProvider(
- path);
- PropertySet properties = PropertySet.create(
- RootCfgDefn.getInstance(),
- PropertyProvider.DEFAULT_PROVIDER, i, exceptions);
-
- // Should never get any exceptions.
- if (!exceptions.isEmpty()) {
- throw new RuntimeException(
- "Got exceptions when creating root managed object");
- }
-
- return new ServerManagedObject<RootCfg>(path,
- RootCfgDefn.getInstance(), properties,
- null);
+ return ROOT;
}
@@ -290,11 +412,125 @@
// Decode helper method required to avoid generics warning.
private static <S extends Configuration> ServerManagedObject<S> decodeAux(
ManagedObjectPath path, ManagedObjectDefinition<?, S> d,
- PropertySet properties, ConfigEntry configEntry) {
- return new ServerManagedObject<S>(path, d, properties,
- configEntry);
+ Map<PropertyDefinition<?>, SortedSet<?>> properties,
+ ConfigEntry configEntry) {
+ return new ServerManagedObject<S>(path, d, properties, configEntry);
}
+
+
+ // Create a property using the provided string values.
+ private static <T> void decodeProperty(
+ Map<PropertyDefinition<?>, SortedSet<?>> properties,
+ ManagedObjectPath path, PropertyDefinition<T> pd,
+ List<String> stringValues) throws PropertyException {
+ PropertyException exception = null;
+ SortedSet<T> values = new TreeSet<T>(pd);
+
+ if (!stringValues.isEmpty()) {
+ // The property has values defined for it.
+ for (String value : stringValues) {
+ try {
+ values.add(pd.decodeValue(value));
+ } catch (IllegalPropertyValueStringException e) {
+ exception = e;
+ }
+ }
+ } else {
+ // No values defined so get the defaults.
+ try {
+ values.addAll(DefaultValueFinder.getDefaultValues(path, pd));
+ } catch (DefaultBehaviorException e) {
+ exception = e;
+ }
+ }
+
+ if (values.size() > 1 && !pd.hasOption(PropertyOption.MULTI_VALUED)) {
+ // This exception takes precedence over previous exceptions.
+ exception = new PropertyIsSingleValuedException(pd);
+ T value = values.first();
+ values.clear();
+ values.add(value);
+ }
+
+ if (values.isEmpty() && pd.hasOption(PropertyOption.MANDATORY)) {
+ // The values maybe empty because of a previous exception.
+ if (exception == null) {
+ exception = new PropertyIsMandatoryException(pd);
+ }
+ }
+
+ // TODO: If an exception occurs should we leave the property
+ // empty?
+ properties.put(pd, values);
+ if (exception != null) {
+ throw exception;
+ }
+ }
+
+
+
+ // Gets the attribute associated with a property from a ConfigEntry.
+ private static List<String> getAttribute(ManagedObjectDefinition<?, ?> d,
+ PropertyDefinition<?> pd, ConfigEntry configEntry) {
+ // TODO: we create a default attribute type if it is
+ // undefined. We should log a warning here if this is the case
+ // since the attribute should have been defined.
+ String attrID = LDAPProfile.getInstance().getAttributeName(d, pd);
+ AttributeType type = DirectoryServer.getAttributeType(attrID, true);
+ AttributeValueDecoder<String> decoder =
+ new AttributeValueDecoder<String>() {
+
+ public String decode(AttributeValue value) throws DirectoryException {
+ return value.getStringValue();
+ }
+ };
+
+ List<String> values = new LinkedList<String>();
+ try {
+ configEntry.getEntry().getAttributeValues(type, decoder, values);
+ } catch (DirectoryException e) {
+ // Should not happen.
+ throw new RuntimeException(e);
+ }
+ return values;
+ }
+
+
+
+ // Gets a config entry required for a managed object and throws a
+ // config exception on failure.
+ private static ConfigEntry getManagedObjectConfigEntry(DN dn)
+ throws ConfigException {
+ ConfigEntry configEntry;
+ try {
+ configEntry = DirectoryServer.getConfigEntry(dn);
+ } catch (ConfigException e) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ int msgID = AdminMessages.MSGID_ADMIN_CANNOT_GET_MANAGED_OBJECT;
+ String message = getMessage(msgID, String.valueOf(dn),
+ stackTraceToSingleLineString(e));
+ throw new ConfigException(msgID, message, e);
+ }
+
+ // The configuration handler is free to return null indicating
+ // that the entry does not exist.
+ if (configEntry == null) {
+ int msgID = AdminMessages.MSGID_ADMIN_MANAGED_OBJECT_DOES_NOT_EXIST;
+ String message = getMessage(msgID, String.valueOf(dn));
+ throw new ConfigException(msgID, message);
+ }
+
+ return configEntry;
+ }
+
+ // The configuration entry associated with this server managed
+ // object (null if root).
+ private ConfigEntry configEntry;
+
// The managed object's definition.
private final ManagedObjectDefinition<?, S> definition;
@@ -303,17 +539,14 @@
private final ManagedObjectPath<?, ?> path;
// The managed object's properties.
- private final PropertySet properties;
-
- // The configuration entry associated with this server managed
- // object (null if root).
- private ConfigEntry configEntry;
+ private final Map<PropertyDefinition<?>, SortedSet<?>> properties;
// Create an new server side managed object.
private ServerManagedObject(ManagedObjectPath path,
- ManagedObjectDefinition<?, S> d, PropertySet properties,
+ ManagedObjectDefinition<?, S> d,
+ Map<PropertyDefinition<?>, SortedSet<?>> properties,
ConfigEntry configEntry) {
this.definition = d;
this.path = path;
@@ -338,8 +571,7 @@
*/
public <M extends Configuration> void deregisterAddListener(
InstantiableRelationDefinition<?, M> d,
- ConfigurationAddListener<M> listener)
- throws IllegalArgumentException {
+ ConfigurationAddListener<M> listener) throws IllegalArgumentException {
validateRelationDefinition(d);
DN baseDN = DNBuilder.create(path, d);
@@ -362,8 +594,7 @@
* with this managed object's definition.
*/
public <M extends Configuration> void deregisterAddListener(
- OptionalRelationDefinition<?, M> d,
- ConfigurationAddListener<M> listener)
+ OptionalRelationDefinition<?, M> d, ConfigurationAddListener<M> listener)
throws IllegalArgumentException {
validateRelationDefinition(d);
@@ -408,8 +639,7 @@
*/
public <M extends Configuration> void deregisterDeleteListener(
InstantiableRelationDefinition<?, M> d,
- ConfigurationDeleteListener<M> listener)
- throws IllegalArgumentException {
+ ConfigurationDeleteListener<M> listener) throws IllegalArgumentException {
validateRelationDefinition(d);
DN baseDN = DNBuilder.create(path, d);
@@ -433,8 +663,7 @@
*/
public <M extends Configuration> void deregisterDeleteListener(
OptionalRelationDefinition<?, M> d,
- ConfigurationDeleteListener<M> listener)
- throws IllegalArgumentException {
+ ConfigurationDeleteListener<M> listener) throws IllegalArgumentException {
validateRelationDefinition(d);
DN baseDN = DNBuilder.create(path);
@@ -465,7 +694,6 @@
InstantiableRelationDefinition<?, M> d, String name)
throws IllegalArgumentException, ConfigException {
validateRelationDefinition(d);
-
ManagedObjectPath childPath = path.child(d, name);
return getChild(childPath, d);
}
@@ -489,11 +717,9 @@
* could not be decoded.
*/
public <M extends Configuration> ServerManagedObject<? extends M> getChild(
- OptionalRelationDefinition<?, M> d)
- throws IllegalArgumentException, ConfigException {
+ OptionalRelationDefinition<?, M> d) throws IllegalArgumentException,
+ ConfigException {
validateRelationDefinition(d);
-
- // Get the configuration entry.
ManagedObjectPath childPath = path.child(d);
return getChild(childPath, d);
}
@@ -517,11 +743,9 @@
* could not be decoded.
*/
public <M extends Configuration> ServerManagedObject<? extends M> getChild(
- SingletonRelationDefinition<?, M> d)
- throws IllegalArgumentException, ConfigException {
+ SingletonRelationDefinition<?, M> d) throws IllegalArgumentException,
+ ConfigException {
validateRelationDefinition(d);
-
- // Get the configuration entry.
ManagedObjectPath childPath = path.child(d);
return getChild(childPath, d);
}
@@ -582,44 +806,49 @@
/**
- * Get the current value of the specified property.
- * <p>
- * If the value has been modified then the new value is returned,
- * otherwise the original value will be returned.
+ * Get the effective value of the specified property. If the
+ * property is multi-valued then just the first value is returned.
+ * If the property does not have a value then its default value is
+ * returned if it has one, or <code>null</code> indicating that
+ * any default behavior is applicable.
*
* @param <T>
* The type of the property to be retrieved.
* @param d
* The property to be retrieved.
- * @return Returns the property's current value, or
- * <code>null</code> if there is no value(s) associated
- * with the property and any default behavior is
- * applicable.
+ * @return Returns the property's effective value, or
+ * <code>null</code> indicating that any default behavior
+ * is applicable.
* @throws IllegalArgumentException
* If the property definition is not associated with this
* managed object's definition.
*/
public <T> T getPropertyValue(PropertyDefinition<T> d)
throws IllegalArgumentException {
- return properties.getPropertyValue(d);
+ Set<T> values = getPropertyValues(d);
+ if (values.isEmpty()) {
+ return null;
+ } else {
+ return values.iterator().next();
+ }
}
/**
- * Get the current values of the specified property.
- * <p>
- * If the property has been modified then the new values are
- * returned, otherwise the original values will be returned.
+ * Get the effective values of the specified property. If the
+ * property does not have any values then its default values are
+ * returned if it has any, or an empty set indicating that any
+ * default behavior is applicable.
*
* @param <T>
* The type of the property to be retrieved.
* @param d
* The property to be retrieved.
* @return Returns a newly allocated set containing a copy of the
- * property's current values. An empty set indicates that
- * the property has no values defined and any default
- * behavior is applicable.
+ * property's effective values. An empty set indicates that
+ * the property has no default values defined and any
+ * default behavior is applicable.
* @throws IllegalArgumentException
* If the property definition is not associated with this
* managed object's definition.
@@ -627,7 +856,10 @@
@SuppressWarnings("unchecked")
public <T> SortedSet<T> getPropertyValues(PropertyDefinition<T> d)
throws IllegalArgumentException {
- return properties.getPropertyValues(d);
+ if (!properties.containsKey(d)) {
+ throw new IllegalArgumentException("Unknown property " + d.getName());
+ }
+ return new TreeSet<T>((SortedSet<T>) properties.get(d));
}
@@ -721,14 +953,14 @@
*/
public <M extends Configuration> void registerAddListener(
InstantiableRelationDefinition<?, M> d,
- ConfigurationAddListener<M> listener)
- throws IllegalArgumentException, ConfigException {
+ ConfigurationAddListener<M> listener) throws IllegalArgumentException,
+ ConfigException {
validateRelationDefinition(d);
DN baseDN = DNBuilder.create(path, d);
ConfigEntry relationEntry = getListenerConfigEntry(baseDN);
- ConfigAddListener adaptor = new ConfigAddListenerAdaptor<M>(path,
- d, listener);
+ ConfigAddListener adaptor = new ConfigAddListenerAdaptor<M>(path, d,
+ listener);
if (relationEntry != null) {
relationEntry.registerAddListener(adaptor);
@@ -758,13 +990,12 @@
* with this managed object's definition.
*/
public <M extends Configuration> void registerAddListener(
- OptionalRelationDefinition<?, M> d,
- ConfigurationAddListener<M> listener)
+ OptionalRelationDefinition<?, M> d, ConfigurationAddListener<M> listener)
throws IllegalArgumentException {
validateRelationDefinition(d);
- ConfigAddListener adaptor = new ConfigAddListenerAdaptor<M>(path,
- d, listener);
+ ConfigAddListener adaptor = new ConfigAddListenerAdaptor<M>(path, d,
+ listener);
configEntry.registerAddListener(adaptor);
}
@@ -779,8 +1010,8 @@
*/
public void registerChangeListener(
ConfigurationChangeListener<? super S> listener) {
- ConfigChangeListener adaptor = new ConfigChangeListenerAdaptor<S>(
- path, definition, listener);
+ ConfigChangeListener adaptor = new ConfigChangeListenerAdaptor<S>(path,
+ definition, listener);
configEntry.registerChangeListener(adaptor);
}
@@ -805,14 +1036,14 @@
*/
public <M extends Configuration> void registerDeleteListener(
InstantiableRelationDefinition<?, M> d,
- ConfigurationDeleteListener<M> listener)
- throws IllegalArgumentException, ConfigException {
+ ConfigurationDeleteListener<M> listener) throws IllegalArgumentException,
+ ConfigException {
validateRelationDefinition(d);
DN baseDN = DNBuilder.create(path, d);
ConfigEntry relationEntry = getListenerConfigEntry(baseDN);
- ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<M>(
- path, d, listener);
+ ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<M>(path, d,
+ listener);
if (relationEntry != null) {
relationEntry.registerDeleteListener(adaptor);
@@ -843,12 +1074,11 @@
*/
public <M extends Configuration> void registerDeleteListener(
OptionalRelationDefinition<?, M> d,
- ConfigurationDeleteListener<M> listener)
- throws IllegalArgumentException {
+ ConfigurationDeleteListener<M> listener) throws IllegalArgumentException {
validateRelationDefinition(d);
- ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<M>(
- path, d, listener);
+ ConfigDeleteListener adaptor = new ConfigDeleteListenerAdaptor<M>(path, d,
+ listener);
configEntry.registerDeleteListener(adaptor);
}
@@ -870,8 +1100,8 @@
// Deregister an add listener.
- private <M extends Configuration> void deregisterAddListener(
- DN baseDN, ConfigurationAddListener<M> listener) {
+ private <M extends Configuration> void deregisterAddListener(DN baseDN,
+ ConfigurationAddListener<M> listener) {
try {
ConfigEntry configEntry = getListenerConfigEntry(baseDN);
if (configEntry != null) {
@@ -886,8 +1116,7 @@
}
} catch (ConfigException e) {
// Ignore the exception since this implies deregistration.
- if (debugEnabled())
- {
+ if (debugEnabled()) {
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
}
@@ -901,8 +1130,7 @@
try {
ConfigEntry configEntry = getListenerConfigEntry(baseDN);
if (configEntry != null) {
- for (ConfigDeleteListener l : configEntry
- .getDeleteListeners()) {
+ for (ConfigDeleteListener l : configEntry.getDeleteListeners()) {
if (l instanceof ConfigDeleteListenerAdaptor) {
ConfigDeleteListenerAdaptor adaptor =
(ConfigDeleteListenerAdaptor) l;
@@ -914,8 +1142,7 @@
}
} catch (ConfigException e) {
// Ignore the exception since this implies deregistration.
- if (debugEnabled())
- {
+ if (debugEnabled()) {
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
}
@@ -945,15 +1172,13 @@
// Gets a config entry required for a listener and throws a config
// exception on failure or returns null if the entry does not exist.
- private ConfigEntry getListenerConfigEntry(DN dn)
- throws ConfigException {
+ private ConfigEntry getListenerConfigEntry(DN dn) throws ConfigException {
// Attempt to retrieve the listener base entry.
ConfigEntry configEntry;
try {
configEntry = DirectoryServer.getConfigEntry(dn);
} catch (ConfigException e) {
- if (debugEnabled())
- {
+ if (debugEnabled()) {
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
@@ -968,48 +1193,14 @@
- // Gets a config entry required for a managed object and throws a
- // config exception on failure.
- private ConfigEntry getManagedObjectConfigEntry(DN dn)
- throws ConfigException {
- ConfigEntry configEntry;
- try {
- configEntry = DirectoryServer.getConfigEntry(dn);
- } catch (ConfigException e) {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = AdminMessages.MSGID_ADMIN_CANNOT_GET_MANAGED_OBJECT;
- String message = getMessage(msgID, String.valueOf(dn),
- stackTraceToSingleLineString(e));
- throw new ConfigException(msgID, message, e);
- }
-
- // The configuration handler is free to return null indicating
- // that the entry does not exist.
- if (configEntry == null) {
- int msgID = AdminMessages.MSGID_ADMIN_MANAGED_OBJECT_DOES_NOT_EXIST;
- String message = getMessage(msgID, String.valueOf(dn));
- throw new ConfigException(msgID, message);
- }
-
- return configEntry;
- }
-
-
-
// Validate that a relation definition belongs to this managed
// object.
private void validateRelationDefinition(RelationDefinition<?, ?> rd)
throws IllegalArgumentException {
- RelationDefinition tmp = definition.getRelationDefinition(rd
- .getName());
+ RelationDefinition tmp = definition.getRelationDefinition(rd.getName());
if (tmp != rd) {
- throw new IllegalArgumentException("The relation "
- + rd.getName() + " is not associated with a "
- + definition.getName());
+ throw new IllegalArgumentException("The relation " + rd.getName()
+ + " is not associated with a " + definition.getName());
}
}
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java
index 6b65d80..ab16299 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/ManagedObjectPathTest.java
@@ -116,6 +116,17 @@
/**
+ * Tests that the empty path represents has no relation.
+ */
+ @Test
+ public void testEmptyPathHasNoRelation() {
+ ManagedObjectPath<?, ?> path = ManagedObjectPath.emptyPath();
+ assertEquals(path.getRelationDefinition(), null);
+ }
+
+
+
+ /**
* Tests that the empty path has a string representation of "/".
*/
@Test
@@ -152,6 +163,8 @@
assertEquals(child.parent(), path);
assertEquals(child.getManagedObjectDefinition(), GlobalCfgDefn
.getInstance());
+ assertEquals(child.getRelationDefinition(), RootCfgDefn.getInstance()
+ .getGlobalConfigurationRelationDefinition());
assertEquals(child.toString(), "/relation=global-configuration");
assertEquals(child, ManagedObjectPath
.valueOf("/relation=global-configuration"));
@@ -175,6 +188,8 @@
assertEquals(child.parent(), path);
assertEquals(child.getManagedObjectDefinition(), ConnectionHandlerCfgDefn
.getInstance());
+ assertEquals(child.getRelationDefinition(), RootCfgDefn.getInstance()
+ .getConnectionHandlersRelationDefinition());
assertEquals(child.toString(),
"/relation=connection-handler+name=LDAP connection handler");
assertEquals(child, ManagedObjectPath
@@ -200,6 +215,8 @@
assertEquals(child.parent(), path);
assertEquals(child.getManagedObjectDefinition(),
LDAPConnectionHandlerCfgDefn.getInstance());
+ assertEquals(child.getRelationDefinition(), RootCfgDefn.getInstance()
+ .getConnectionHandlersRelationDefinition());
assertEquals(
child.toString(),
"/relation=connection-handler+type=ldap-connection-handler+name=LDAP connection handler");
@@ -229,6 +246,9 @@
assertEquals(domain.parent(2), root);
assertEquals(domain.getManagedObjectDefinition(), MultimasterDomainCfgDefn
.getInstance());
+ assertEquals(domain.getRelationDefinition(),
+ MultimasterSynchronizationProviderCfgDefn.getInstance()
+ .getMultimasterDomainsRelationDefinition());
assertEquals(
domain.toString(),
"/relation=synchronization-provider+type=multimaster-synchronization-provider+name=MMR/relation=multimaster-domain+name=Domain");
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java
index cc4043d..5ab5dd1 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/RelativeInheritedDefaultBehaviorProviderTest.java
@@ -27,61 +27,104 @@
package org.opends.server.admin;
+
+
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeClass;
+
+
/**
* RelativeInheritedDefaultBehaviorProvider Tester.
*/
public class RelativeInheritedDefaultBehaviorProviderTest {
- static private final String PROPERTY_NAME = "test-property";
- static private final int OFFSET = 0;
+ private static final int OFFSET = 0;
- private RelativeInheritedDefaultBehaviorProvider<Object> ridbp = null;
+ private static final TestParentCfgDefn d = TestParentCfgDefn.getInstance();
+ private RelativeInheritedDefaultBehaviorProvider<Integer> ridbp = null;
+
+
+
+ /**
+ * Creates the default behavior provider.
+ */
@BeforeClass
public void setUp() {
- this.ridbp = new RelativeInheritedDefaultBehaviorProvider<Object>(OFFSET, PROPERTY_NAME);
+ this.ridbp = new RelativeInheritedDefaultBehaviorProvider<Integer>(d, d
+ .getMaximumLengthPropertyDefinition().getName(), OFFSET);
}
+
+
+ /**
+ * Tests the accept method.
+ */
@Test
public void testAccept() {
- ridbp.accept(new DefaultBehaviorProviderVisitor<Object,Object,Object>(){
+ ridbp.accept(new DefaultBehaviorProviderVisitor<Integer, Object, Object>() {
- public Object visitAbsoluteInherited(AbsoluteInheritedDefaultBehaviorProvider d, Object o) {
+ public Object visitAbsoluteInherited(
+ AbsoluteInheritedDefaultBehaviorProvider d, Object o) {
return null;
}
+
+
public Object visitAlias(AliasDefaultBehaviorProvider d, Object o) {
return null;
}
+
+
public Object visitDefined(DefinedDefaultBehaviorProvider d, Object o) {
return null;
}
- public Object visitRelativeInherited(RelativeInheritedDefaultBehaviorProvider d, Object o) {
+
+
+ public Object visitRelativeInherited(
+ RelativeInheritedDefaultBehaviorProvider d, Object o) {
return null;
}
+
+
public Object visitUndefined(UndefinedDefaultBehaviorProvider d, Object o) {
return null;
}
}, new Object());
}
+
+
+ /**
+ * Tests the getManagedObjectPath method.
+ */
@Test
public void testGetManagedObjectPath() {
- ridbp.getManagedObjectPath(ManagedObjectPath.emptyPath());
+ assertEquals(ridbp.getManagedObjectPath(ManagedObjectPath.emptyPath()),
+ ManagedObjectPath.emptyPath());
}
+
+
+ /**
+ * Tests the getPropertyDefinition method.
+ */
@Test
- public void testGetPropertyName() {
- assertEquals(ridbp.getPropertyName(), PROPERTY_NAME);
+ public void testGetPropertyDefinition() {
+ assertEquals(ridbp.getPropertyName(), d
+ .getMaximumLengthPropertyDefinition().getName());
}
+
+
+ /**
+ * Tests the getRelativeOffset method.
+ */
@Test
public void testGetRelativeOffset() {
assertEquals(ridbp.getRelativeOffset(), OFFSET);
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfg.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfg.java
index 9272699..03648f2 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfg.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfg.java
@@ -51,4 +51,22 @@
* @return Returns the value of the "heartbeat-interval" property.
*/
long getHeartbeatInterval();
+
+
+
+ /**
+ * Get the "maximum-length" property.
+ *
+ * @return Returns the value of the "maximum-length" property.
+ */
+ int getMaximumLength();
+
+
+
+ /**
+ * Get the "minimum-length" property.
+ *
+ * @return Returns the value of the "minimum-length" property.
+ */
+ int getMinimumLength();
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgClient.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgClient.java
index ea53db8..816dea1 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgClient.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/TestChildCfgClient.java
@@ -63,4 +63,46 @@
* If the new value is invalid.
*/
void setHeartbeatInterval(Long value) throws IllegalPropertyValueException;
+
+
+
+ /**
+ * Get the "maximum-length" property.
+ *
+ * @return Returns the value of the "maximum-length" property.
+ */
+ int getMaximumLength();
+
+
+
+ /**
+ * Set the "maximum-length" property.
+ *
+ * @param value
+ * The value of the "maximum-length" property.
+ * @throws IllegalPropertyValueException
+ * If the new value is invalid.
+ */
+ void setMaximumLength(Integer value) throws IllegalPropertyValueException;
+
+
+
+ /**
+ * Get the "minimum-length" property.
+ *
+ * @return Returns the value of the "minimum-length" property.
+ */
+ int getMinimumLength();
+
+
+
+ /**
+ * Set the "minimum-length" property.
+ *
+ * @param value
+ * The value of the "minimum-length" property.
+ * @throws IllegalPropertyValueException
+ * If the new value is invalid.
+ */
+ void setMinimumLength(Integer value) throws IllegalPropertyValueException;
}
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 46ee42f..84c16f0 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
@@ -32,6 +32,7 @@
import org.opends.server.admin.client.CommunicationException;
import org.opends.server.admin.client.ConcurrentModificationException;
import org.opends.server.admin.client.ManagedObject;
+import org.opends.server.admin.client.MissingMandatoryPropertiesException;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.types.DN;
@@ -47,9 +48,40 @@
// The singleton configuration definition instance.
private static final TestChildCfgDefn INSTANCE = new TestChildCfgDefn();
+ // The "maximum-length" property definition.
+ private static final IntegerPropertyDefinition PD_MAXIMUM_LENGTH;
+
+ // The "minimum-length" property definition.
+ private static final IntegerPropertyDefinition PD_MINIMUM_LENGTH;
+
// The "heartbeat-interval" property definition.
private static final DurationPropertyDefinition PD_HEARTBEAT_INTERVAL;
+ // Build the "maximum-length" property definition.
+ static {
+ IntegerPropertyDefinition.Builder builder = IntegerPropertyDefinition
+ .createBuilder(INSTANCE, "maximum-length");
+ DefaultBehaviorProvider<Integer> provider = new RelativeInheritedDefaultBehaviorProvider<Integer>(
+ TestParentCfgDefn.getInstance(), "maximum-length", 1);
+ builder.setDefaultBehaviorProvider(provider);
+ builder.setLowerLimit(0);
+ PD_MAXIMUM_LENGTH = builder.getInstance();
+ INSTANCE.registerPropertyDefinition(PD_MAXIMUM_LENGTH);
+ }
+
+ // Build the "minimum-length" property definition.
+ static {
+ IntegerPropertyDefinition.Builder builder = IntegerPropertyDefinition
+ .createBuilder(INSTANCE, "minimum-length");
+ DefaultBehaviorProvider<Integer> provider = new AbsoluteInheritedDefaultBehaviorProvider<Integer>(
+ ManagedObjectPath.valueOf("/relation=test-parent+name=test parent 2"),
+ "minimum-length");
+ builder.setDefaultBehaviorProvider(provider);
+ builder.setLowerLimit(0);
+ PD_MINIMUM_LENGTH = builder.getInstance();
+ INSTANCE.registerPropertyDefinition(PD_MINIMUM_LENGTH);
+ }
+
// Build the "heartbeat-interval" property definition.
static {
DurationPropertyDefinition.Builder builder = DurationPropertyDefinition
@@ -127,6 +159,28 @@
/**
+ * Get the "maximum-length" property definition.
+ *
+ * @return Returns the "maximum-length" property definition.
+ */
+ public IntegerPropertyDefinition getMaximumLengthPropertyDefinition() {
+ return PD_MAXIMUM_LENGTH;
+ }
+
+
+
+ /**
+ * Get the "minimum-length" property definition.
+ *
+ * @return Returns the "minimum-length" property definition.
+ */
+ public IntegerPropertyDefinition getMinimumLengthPropertyDefinition() {
+ return PD_MINIMUM_LENGTH;
+ }
+
+
+
+ /**
* Managed object client implementation.
*/
private static class TestChildCfgClientImpl implements TestChildCfgClient {
@@ -167,6 +221,46 @@
/**
* {@inheritDoc}
*/
+ public int getMaximumLength() {
+ return impl.getPropertyValue(INSTANCE
+ .getMaximumLengthPropertyDefinition());
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setMaximumLength(Integer value) {
+ impl.setPropertyValue(INSTANCE.getMaximumLengthPropertyDefinition(),
+ value);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getMinimumLength() {
+ return impl.getPropertyValue(INSTANCE
+ .getMinimumLengthPropertyDefinition());
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setMinimumLength(Integer value) {
+ impl.setPropertyValue(INSTANCE.getMinimumLengthPropertyDefinition(),
+ value);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
public ManagedObjectDefinition<? extends TestChildCfgClient, ? extends TestChildCfg> definition() {
return INSTANCE;
}
@@ -187,7 +281,8 @@
*/
public void commit() throws ConcurrentModificationException,
OperationRejectedException, AuthorizationException,
- CommunicationException {
+ CommunicationException, ManagedObjectAlreadyExistsException,
+ MissingMandatoryPropertiesException {
impl.commit();
}
}
@@ -225,6 +320,26 @@
/**
* {@inheritDoc}
*/
+ public int getMaximumLength() {
+ return impl.getPropertyValue(INSTANCE
+ .getMaximumLengthPropertyDefinition());
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getMinimumLength() {
+ return impl.getPropertyValue(INSTANCE
+ .getMinimumLengthPropertyDefinition());
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
public ManagedObjectDefinition<? extends TestChildCfgClient, ? extends TestChildCfg> definition() {
return INSTANCE;
}
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 5a27cdc..b83125e 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
@@ -28,6 +28,8 @@
+import java.util.Collection;
+
import org.opends.server.admin.ConfigurationClient;
import org.opends.server.admin.ManagedObjectDefinition;
import org.opends.server.admin.client.AuthorizationException;
@@ -111,36 +113,17 @@
* The definition of the test child to be created.
* @param name
* The name of the new test child.
- * @param p
- * A property provider which can be used to initialize the
- * property values of the new test child.
+ * @param exceptions
+ * An optional collection in which to place any {@link
+ * DefaultBehaviorException}s that occurred whilst
+ * attempting to determine the default values of the test
+ * child. This argument can be <code>null<code>.
* @return Returns a new test child instance representing the test
* child that was created.
- * @throws ManagedObjectDecodingException
- * If the test child could not be created because one or
- * more of its properties are invalid.
- * @throws ManagedObjectAlreadyExistsException
- * If the test child cannot be created because it already
- * exists on the server.
- * @throws ConcurrentModificationException
- * If this test parent has been removed from the server by
- * another client.
- * @throws OperationRejectedException
- * If the server refuses to create the test child due to
- * some server-side constraint which cannot be satisfied.
- * @throws AuthorizationException
- * If the server refuses to create the test child because
- * the client does not have the correct privileges.
- * @throws CommunicationException
- * If the client cannot contact the server due to an
- * underlying communication problem.
*/
<C extends TestChildCfgClient> C createTestChild(
- ManagedObjectDefinition<C, ?> d, String name, PropertyProvider p)
- throws ManagedObjectDecodingException,
- ManagedObjectAlreadyExistsException, ConcurrentModificationException,
- OperationRejectedException, AuthorizationException,
- CommunicationException;
+ ManagedObjectDefinition<C, ?> d, String name,
+ Collection<DefaultBehaviorException> exceptions);
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 8fdd739..48b7a2b 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
@@ -28,11 +28,14 @@
+import java.util.Collection;
+
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.ManagedObject;
import org.opends.server.admin.client.ManagedObjectDecodingException;
+import org.opends.server.admin.client.MissingMandatoryPropertiesException;
import org.opends.server.admin.client.OperationRejectedException;
import org.opends.server.admin.server.ServerManagedObject;
import org.opends.server.admin.std.meta.RootCfgDefn;
@@ -266,7 +269,8 @@
*/
public void commit() throws ConcurrentModificationException,
OperationRejectedException, AuthorizationException,
- CommunicationException {
+ CommunicationException, ManagedObjectAlreadyExistsException,
+ MissingMandatoryPropertiesException {
impl.commit();
}
@@ -276,13 +280,10 @@
* {@inheritDoc}
*/
public <C extends TestChildCfgClient> C createTestChild(
- ManagedObjectDefinition<C, ?> d, String name, PropertyProvider p)
- throws ManagedObjectDecodingException,
- ManagedObjectAlreadyExistsException, ConcurrentModificationException,
- OperationRejectedException, AuthorizationException,
- CommunicationException {
+ ManagedObjectDefinition<C, ?> d, String name,
+ Collection<DefaultBehaviorException> exceptions) {
return impl.createChild(INSTANCE.getTestChildrenRelationDefinition(), d,
- name, p).getConfiguration();
+ name, exceptions).getConfiguration();
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/PropertySetTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/PropertySetTest.java
index 007a896..5633837 100755
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/PropertySetTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/PropertySetTest.java
@@ -140,16 +140,6 @@
}
/**
- * Tests basic property set creation with a string
- * property provider
- */
- @Test
- public void testCreate1() {
- PropertySet ps = createTestPropertySet(StringPropertyProvider.DEFAULT_PROVIDER);
- assertNotNull(ps);
- }
-
- /**
* Tests setting and getting property values
* @param pd PropertyDefinition for which values are set and gotten
* @param values property values to test
@@ -229,9 +219,9 @@
PropertySet ps = createTestPropertySet();
Property<T> p = ps.getProperty(pd);
SortedSet<T> ss = p.getDefaultValues();
- assertTrue(ss.size() == expected.size());
+ assertEquals(ss.size(), expected.size());
for (T v : expected) {
- ss.contains(v);
+ assertTrue(ss.contains(v), "does not contain " + v);
}
}
@@ -282,9 +272,9 @@
// before setting any values, the effective data
// is supposed to just be the defaults
Set<T> ev1 = p.getEffectiveValues();
- assertTrue(ev1.size() == expectedDefaults.size());
+ assertEquals(ev1.size(), expectedDefaults.size());
for(T v : ev1) {
- assertTrue(expectedDefaults.contains(v));
+ assertTrue(expectedDefaults.contains(v), "does not contain " + v);
}
// now set some data and make sure the effective
@@ -292,9 +282,9 @@
ps.setPropertyValues(pd, newValues);
Set<T> ev2 = p.getEffectiveValues();
- assertTrue(ev2.size() == newValues.size());
+ assertEquals(ev2.size(), newValues.size());
for(T v : ev2) {
- assertTrue(newValues.contains(v));
+ assertTrue(newValues.contains(v), "does not contain " + v);
}
}
@@ -391,21 +381,27 @@
}
private PropertySet createTestPropertySet(PropertyProvider pp) {
- return PropertySet.create(
- new TestManagedObjectDefinition<ConfigurationClient, Configuration>("test-mod",null),
- pp,
- new InheritedDefaultValueProvider() {
- public ManagedObjectPath getManagedObjectPath() {
- System.out.println("getManagedObjectPath");
- return null;
- }
- public Collection<?> getDefaultPropertyValues(ManagedObjectPath path, String propertyName) throws OperationsException {
- System.out.println("getDefPrV path=" + path + " pn=" + propertyName);
- return null;
- }
- },
- new HashSet<PropertyException>()
- );
+ ManagedObjectDefinition<?, ?> d = new TestManagedObjectDefinition<ConfigurationClient, Configuration>("test-mod", null);
+ PropertySet ps = new PropertySet();
+ for (PropertyDefinition<?> pd : d.getPropertyDefinitions()) {
+ addProperty(ps, pd, pp);
+ }
+ return ps;
+ }
+
+ private <T> void addProperty(PropertySet ps, PropertyDefinition<T> pd, PropertyProvider pp) {
+ Collection<T> defaultValues = new LinkedList<T>();
+ DefaultBehaviorProvider<T> dbp = pd.getDefaultBehaviorProvider();
+ if (dbp instanceof DefinedDefaultBehaviorProvider) {
+ DefinedDefaultBehaviorProvider<T> ddbp = (DefinedDefaultBehaviorProvider<T>) dbp;
+ Collection<String> stringValues = ddbp.getDefaultValues();
+ for (String sv : stringValues) {
+ defaultValues.add(pd.decodeValue(sv));
+ }
+ }
+
+ Collection<T> activeValues = pp.getPropertyValues(pd);
+ ps.addProperty(pd, defaultValues, activeValues);
}
private class TestManagedObjectDefinition<C extends ConfigurationClient,S extends Configuration> extends
@@ -476,23 +472,5 @@
return createTestPropertySet(PropertyProvider.DEFAULT_PROVIDER);
}
- private PropertySet createTestPropertySet(StringPropertyProvider pp) {
- return PropertySet.create(
- new TestManagedObjectDefinition<ConfigurationClient, Configuration>("test-mod", null),
- pp,
- new InheritedDefaultValueProvider() {
- public ManagedObjectPath getManagedObjectPath() {
- System.out.println("getManagedObjectPath");
- return null;
- }
- public Collection<?> getDefaultPropertyValues(ManagedObjectPath path, String propertyName) throws OperationsException {
- System.out.println("getDefPrV path=" + path + " pn=" + propertyName);
- return null;
- }
- },
- new HashSet<PropertyException>()
- );
- }
-
}
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 f31742f..2b0a7c8 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
@@ -41,7 +41,6 @@
import org.opends.server.admin.ManagedObjectAlreadyExistsException;
import org.opends.server.admin.ManagedObjectNotFoundException;
import org.opends.server.admin.MockLDAPProfile;
-import org.opends.server.admin.PropertyProvider;
import org.opends.server.admin.TestChildCfgClient;
import org.opends.server.admin.TestChildCfgDefn;
import org.opends.server.admin.TestParentCfgClient;
@@ -77,13 +76,16 @@
"ds-cfg-maximum-length: 20000", "",
"dn:cn=test-children,cn=test parent 1,cn=test-parents",
"objectclass: top", "objectclass: ds-cfg-branch", "cn: test-children",
+ "", "dn:cn=test-children,cn=test parent 2,cn=test-parents",
+ "objectclass: top", "objectclass: ds-cfg-branch", "cn: test-children",
"",
"dn: cn=test child 1,cn=test-children,cn=test parent 1,cn=test-parents",
"objectclass: top", "objectclass: ds-cfg-test-child", "cn: test child 1",
"",
"dn: cn=test child 2,cn=test-children,cn=test parent 1,cn=test-parents",
"objectclass: top", "objectclass: ds-cfg-test-child", "cn: test child 2",
- "ds-cfg-heartbeat-interval: 12345s", "" };
+ "ds-cfg-heartbeat-interval: 12345s", "ds-cfg-minimum-length: 11111",
+ "ds-cfg-maximum-length: 22222", "" };
@@ -159,7 +161,6 @@
*/
@Test
public void testCreateChildManagedObject() throws Exception {
- MockPropertyProvider p = new MockPropertyProvider();
CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
"cn=test child 3,cn=test-children,cn=test parent 1,cn=test-parents");
c.importLDIF(TEST_LDIF);
@@ -167,13 +168,16 @@
c.addExpectedAttribute("objectclass", "top", "ds-cfg-test-child");
// LDAP encoding uses base unit.
- p.addProperty("heartbeat-interval", "10s");
c.addExpectedAttribute("ds-cfg-heartbeat-interval", "10000ms");
ManagementContext ctx = LDAPManagementContext.createFromContext(c,
new MockLDAPProfile());
TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
- parent.createTestChild(TestChildCfgDefn.getInstance(), "test child 3", p);
+ TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn
+ .getInstance(), "test child 3", null);
+ child.setHeartbeatInterval(10000L);
+ child.commit();
+
c.assertEntryIsCreated();
}
@@ -196,8 +200,10 @@
ManagementContext ctx = LDAPManagementContext.createFromContext(c,
new MockLDAPProfile());
TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
- parent.createTestChild(TestChildCfgDefn.getInstance(), "test child 3",
- new MockPropertyProvider());
+ TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn
+ .getInstance(), "test child 3", null);
+ child.commit();
+
c.assertEntryIsCreated();
}
@@ -231,7 +237,8 @@
ManagementContext ctx = LDAPManagementContext.createFromContext(c,
new MockLDAPProfile());
try {
- createTestParent(ctx, "test parent 3", new MockPropertyProvider());
+ TestParentCfgClient parent = createTestParent(ctx, "test parent 3");
+ parent.commit();
} catch (Exception e) {
Assert.assertEquals(e.getClass(), expected);
}
@@ -247,21 +254,20 @@
*/
@Test
public void testCreateTopLevelManagedObject() throws Exception {
- MockPropertyProvider p = new MockPropertyProvider();
CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
"cn=test parent 3,cn=test-parents");
c.importLDIF(TEST_LDIF);
c.addExpectedAttribute("cn", "test parent 3");
c.addExpectedAttribute("objectclass", "top", "ds-cfg-test-parent");
-
- p.addProperty("maximum-length", "54321");
c.addExpectedAttribute("ds-cfg-maximum-length", "54321");
- p.addProperty("minimum-length", "12345");
c.addExpectedAttribute("ds-cfg-minimum-length", "12345");
ManagementContext ctx = LDAPManagementContext.createFromContext(c,
new MockLDAPProfile());
- createTestParent(ctx, "test parent 3", p);
+ TestParentCfgClient parent = createTestParent(ctx, "test parent 3");
+ parent.setMaximumLength(54321);
+ parent.setMinimumLength(12345);
+ parent.commit();
c.assertEntryIsCreated();
}
@@ -283,7 +289,8 @@
ManagementContext ctx = LDAPManagementContext.createFromContext(c,
new MockLDAPProfile());
- createTestParent(ctx, "test parent 3", new MockPropertyProvider());
+ TestParentCfgClient parent = createTestParent(ctx, "test parent 3");
+ parent.commit();
c.assertEntryIsCreated();
}
@@ -302,6 +309,8 @@
TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
TestChildCfgClient child = parent.getTestChild("test child 2");
Assert.assertEquals(child.getHeartbeatInterval(), 12345000);
+ Assert.assertEquals(child.getMinimumLength(), 11111);
+ Assert.assertEquals(child.getMaximumLength(), 22222);
}
@@ -318,6 +327,8 @@
TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
TestChildCfgClient child = parent.getTestChild("test child 1");
Assert.assertEquals(child.getHeartbeatInterval(), 1000);
+ Assert.assertEquals(child.getMinimumLength(), 10000);
+ Assert.assertEquals(child.getMaximumLength(), 456);
}
@@ -565,16 +576,84 @@
+ /**
+ * Tests retrieval of relative inherited default values.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testInheritedDefaultValues1() throws Exception {
+ CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
+ "cn=test child 3,cn=test-children,cn=test parent 1,cn=test-parents");
+ c.importLDIF(TEST_LDIF);
+ c.addExpectedAttribute("cn", "test child 3");
+ c.addExpectedAttribute("objectclass", "top", "ds-cfg-test-child");
+
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c,
+ new MockLDAPProfile());
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 1");
+ TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn
+ .getInstance(), "test child 3", null);
+
+ // Inherits from parent (test parent 1).
+ Assert.assertEquals(child.getMinimumLength(), 10000);
+
+ // Inherits from test parent 2.
+ Assert.assertEquals(child.getMaximumLength(), 456);
+
+ // Check that the default values are not committed.
+ child.commit();
+
+ c.assertEntryIsCreated();
+ }
+
+
+
+ /**
+ * Tests retrieval of relative inherited default values.
+ *
+ * @throws Exception
+ * If an unexpected error occurred.
+ */
+ @Test
+ public void testInheritedDefaultValues2() throws Exception {
+ CreateEntryMockLDAPConnection c = new CreateEntryMockLDAPConnection(
+ "cn=test child 3,cn=test-children,cn=test parent 2,cn=test-parents");
+ c.importLDIF(TEST_LDIF);
+ c.addExpectedAttribute("cn", "test child 3");
+ c.addExpectedAttribute("objectclass", "top", "ds-cfg-test-child");
+
+ ManagementContext ctx = LDAPManagementContext.createFromContext(c,
+ new MockLDAPProfile());
+ TestParentCfgClient parent = getTestParent(ctx, "test parent 2");
+ TestChildCfgClient child = parent.createTestChild(TestChildCfgDefn
+ .getInstance(), "test child 3", null);
+
+ // Inherits from parent (test parent 2).
+ Assert.assertEquals(child.getMinimumLength(), 10000);
+
+ // Inherits from test parent 2.
+ Assert.assertEquals(child.getMaximumLength(), 20000);
+
+ // Check that the default values are not committed.
+ child.commit();
+
+ c.assertEntryIsCreated();
+ }
+
+
+
// Create the named test parent managed object.
- private void createTestParent(ManagementContext context, String name,
- PropertyProvider p) throws ManagedObjectDecodingException,
+ private TestParentCfgClient createTestParent(ManagementContext context,
+ String name) throws ManagedObjectDecodingException,
AuthorizationException, ManagedObjectAlreadyExistsException,
ConcurrentModificationException, OperationRejectedException,
CommunicationException {
ManagedObject<RootCfgClient> root = context
.getRootConfigurationManagedObject();
- root.createChild(TestParentCfgDefn.RD_TEST_PARENT, TestParentCfgDefn
- .getInstance(), name, p);
+ return root.createChild(TestParentCfgDefn.RD_TEST_PARENT,
+ TestParentCfgDefn.getInstance(), name, null).getConfiguration();
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/MockPropertyProvider.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/MockPropertyProvider.java
deleted file mode 100644
index 765a2b8..0000000
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/admin/client/ldap/MockPropertyProvider.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.ldap;
-
-
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.opends.server.admin.PropertyDefinition;
-import org.opends.server.admin.PropertyProvider;
-import org.opends.server.util.Validator;
-
-
-
-/**
- * A mock property provider which simplifies creation of managed
- * objects and LDAP attribute comparisons.
- */
-public final class MockPropertyProvider implements PropertyProvider {
-
- // The properties.
- private final Map<String, List<String>> properties = new HashMap<String, List<String>>();
-
-
-
- /**
- * Default constructor.
- */
- public MockPropertyProvider() {
- // No implementation required.
- }
-
-
-
- /**
- * Add a property.
- *
- * @param name
- * The name of the property.
- * @param values
- * The property's values.
- */
- public void addProperty(String name, String... values) {
- Validator.ensureNotNull(name);
- Validator.ensureNotNull(values);
- Validator.ensureTrue(values.length > 0);
- properties.put(name, Arrays.asList(values));
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public <T> Collection<T> getPropertyValues(PropertyDefinition<T> d)
- throws IllegalArgumentException {
- List<String> values = properties.get(d.getName());
-
- if (values == null) {
- return Collections.<T> emptySet();
- }
-
- List<T> encodedValues = new ArrayList<T>(values.size());
- for (String value : values) {
- encodedValues.add(d.decodeValue(value));
- }
-
- return encodedValues;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString() {
- return properties.toString();
- }
-
-}
--
Gitblit v1.10.0