Fix the following issues:
* 1444: implement inherited default values
* 1445: prevent commit if mandatory properties are missing
* 1446: refactor managed object factory method API in generated APIs
* 1625: allow read-only properties to be defined during managed object construction and add support for "monitoring" properties (e.g. a property which is server generated and contains the list of support ciphers)
These issues have been fixed in a single change as they depend upon each (issue 1446 being the main issue).
[Reviewed by Josu]
6 files deleted
2 files added
24 files modified
| | |
| | | <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> |
| | |
| | | </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> |
| | |
| | | </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> |
| | |
| | | <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"> |
| | |
| | | <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> |
| | |
| | | <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> |
| | |
| | | <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 |
| | |
| | | </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 |
| | |
| | | select="concat(' /**
', |
| | | ' * {@inheritDoc}
', |
| | | ' */
', |
| | | ' public void commit() throws ConcurrentModificationException,
', |
| | | ' public void commit() throws ManagedObjectAlreadyExistsException,
', |
| | | ' MissingMandatoryPropertiesException, ConcurrentModificationException,
', |
| | | ' OperationRejectedException, AuthorizationException,
', |
| | | ' CommunicationException {
', |
| | | ' impl.commit();
', |
| | |
| | | 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> |
| | |
| | | </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"> |
| | |
| | | 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" /> |
| | |
| | | $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> |
| | |
| | | <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);
', |
| | |
| | | ' * {@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> |
| | |
| | | ' * {@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> |
| | |
| | | <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> |
| | |
| | | </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 |
| | |
| | | </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> |
| | |
| | | </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 |
| | |
| | | <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 |
| | |
| | | <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"> |
| | |
| | | </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" |
| | |
| | | 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"> |
| | |
| | | <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> |
| | |
| | | <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> |
| | |
| | | |
| | | 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; |
| | |
| | | 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) |
| | |
| | | |
| | | |
| | | /** |
| | | * 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. |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | |
| | | |
| | | 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; |
| | | |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | | |
| New file |
| | |
| | | /* |
| | | * 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() + "\""; |
| | | } |
| | | } |
| | |
| | | /** |
| | | * 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 |
| | |
| | | * 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; |
| | |
| | | |
| | | |
| | | /** |
| | | * 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. |
| | | * |
| | |
| | | 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) { |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public InstantiableRelationDefinition<? super C, ? super S> |
| | | getRelationDefinition() { |
| | | return r; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void serialize(ManagedObjectPathSerializer serializer) { |
| | | serializer.appendManagedObjectPathElement(r, |
| | | getManagedObjectDefinition(), name); |
| | |
| | | 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); |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public OptionalRelationDefinition<? super C, ? super S> |
| | | getRelationDefinition() { |
| | | return r; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void serialize(ManagedObjectPathSerializer serializer) { |
| | | serializer |
| | | .appendManagedObjectPathElement(r, getManagedObjectDefinition()); |
| | |
| | | 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); |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public SingletonRelationDefinition<? super C, ? super S> |
| | | getRelationDefinition() { |
| | | return r; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void serialize(ManagedObjectPathSerializer serializer) { |
| | | serializer |
| | | .appendManagedObjectPathElement(r, getManagedObjectDefinition()); |
| | |
| | | |
| | | // 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 |
| | |
| | | |
| | | // Parse the elements. |
| | | LinkedList<Element<?, ?>> elements = new LinkedList<Element<?, ?>>(); |
| | | Element<?, ?> lastElement = null; |
| | | AbstractManagedObjectDefinition<?, ?> definition = RootCfgDefn |
| | | .getInstance(); |
| | | |
| | |
| | | + "\" 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; |
| | |
| | | } |
| | | |
| | | // 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()) { |
| | |
| | | } |
| | | |
| | | // Construct the new path. |
| | | return create(elements, definition); |
| | | return create(elements, lastElement); |
| | | } |
| | | |
| | | |
| | |
| | | // 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()); |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | // 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; |
| | | } |
| | | |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | | |
| | |
| | | * 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()); |
| | | } |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | | |
| | |
| | | * 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()); |
| | | } |
| | | |
| | |
| | | * 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; |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | /** |
| | | * 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. |
| | |
| | | |
| | | 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()); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * 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, |
| | | |
| | |
| | | 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 |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * 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. |
| | |
| | | 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. |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * 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); |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | |
| | | /** |
| | | * 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; |
| | |
| | | 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; |
| | |
| | | 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; |
| | | |
| | |
| | | |
| | | /** |
| | | * 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 |
| | |
| | | * 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 |
| | |
| | | * 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; |
| | | |
| | | |
| | | |
| | |
| | | * 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 |
| | |
| | | * 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 |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | } |
| | | |
| | | } |
| | |
| | | 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 { |
| | | |
| | |
| | | */ |
| | | 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); |
| | | } |
| | | |
| | | |
| | |
| | | * {@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. |
| | |
| | | /** |
| | | * {@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. |
| | |
| | | |
| | | |
| | | |
| | | // 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) |
| | |
| | | /** |
| | | * 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 { |
| | |
| | | /** |
| | | * 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 { |
| | |
| | | /** |
| | | * 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 { |
| | |
| | | /** |
| | | * 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. |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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; |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * {@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(); |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * {@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)); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | |
| | | |
| | |
| | | */ |
| | | 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); |
| | | } |
| | | |
| | | |
| | |
| | | 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; |
| | |
| | | // 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; |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * {@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(); |
| | | } |
| | | } |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | | |
| | |
| | | CommunicationException { |
| | | validateRelationDefinition(d); |
| | | ensureThisManagedObjectExists(); |
| | | return readEntry(context, path.child(d, name), d.getChildDefinition()); |
| | | return readManagedObject(d.getChildDefinition(), path.child(d, name)); |
| | | } |
| | | |
| | | |
| | |
| | | AuthorizationException, CommunicationException { |
| | | validateRelationDefinition(d); |
| | | ensureThisManagedObjectExists(); |
| | | return readEntry(context, path.child(d), d.getChildDefinition()); |
| | | return readManagedObject(d.getChildDefinition(), path.child(d)); |
| | | } |
| | | |
| | | |
| | |
| | | AuthorizationException, CommunicationException { |
| | | validateRelationDefinition(d); |
| | | ensureThisManagedObjectExists(); |
| | | return readEntry(context, path.child(d), d.getChildDefinition()); |
| | | return readManagedObject(d.getChildDefinition(), path.child(d)); |
| | | } |
| | | |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | // 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) { |
| | |
| | | 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; |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | 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(); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | // 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, |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | import org.opends.server.types.DirectoryException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * A server-side managed object. |
| | | * |
| | |
| | | * 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; |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | |
| | | * 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 { |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | |
| | |
| | | // 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; |
| | | |
| | |
| | | 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; |
| | |
| | | */ |
| | | 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); |
| | |
| | | * 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); |
| | | |
| | |
| | | */ |
| | | 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); |
| | |
| | | */ |
| | | 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); |
| | |
| | | InstantiableRelationDefinition<?, M> d, String name) |
| | | throws IllegalArgumentException, ConfigException { |
| | | validateRelationDefinition(d); |
| | | |
| | | ManagedObjectPath childPath = path.child(d, name); |
| | | return getChild(childPath, d); |
| | | } |
| | |
| | | * 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); |
| | | } |
| | |
| | | * 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); |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * 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. |
| | |
| | | @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)); |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | 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); |
| | |
| | | * 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); |
| | | } |
| | | |
| | |
| | | */ |
| | | 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); |
| | | } |
| | | |
| | |
| | | */ |
| | | 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); |
| | |
| | | */ |
| | | 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); |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | // 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) { |
| | |
| | | } |
| | | } catch (ConfigException e) { |
| | | // Ignore the exception since this implies deregistration. |
| | | if (debugEnabled()) |
| | | { |
| | | if (debugEnabled()) { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | |
| | | 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; |
| | |
| | | } |
| | | } catch (ConfigException e) { |
| | | // Ignore the exception since this implies deregistration. |
| | | if (debugEnabled()) |
| | | { |
| | | if (debugEnabled()) { |
| | | TRACER.debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | |
| | | |
| | | // 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); |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | // 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()); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | |
| | | 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")); |
| | |
| | | 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 |
| | |
| | | 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"); |
| | |
| | | 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"); |
| | |
| | | |
| | | 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); |
| | |
| | | * @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(); |
| | | } |
| | |
| | | * 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; |
| | | } |
| | |
| | | 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; |
| | |
| | | // 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 |
| | |
| | | |
| | | |
| | | /** |
| | | * 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 { |
| | |
| | | /** |
| | | * {@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; |
| | | } |
| | |
| | | */ |
| | | public void commit() throws ConcurrentModificationException, |
| | | OperationRejectedException, AuthorizationException, |
| | | CommunicationException { |
| | | CommunicationException, ManagedObjectAlreadyExistsException, |
| | | MissingMandatoryPropertiesException { |
| | | impl.commit(); |
| | | } |
| | | } |
| | |
| | | /** |
| | | * {@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; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | import java.util.Collection; |
| | | |
| | | import org.opends.server.admin.ConfigurationClient; |
| | | import org.opends.server.admin.ManagedObjectDefinition; |
| | | import org.opends.server.admin.client.AuthorizationException; |
| | |
| | | * 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); |
| | | |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | |
| | | */ |
| | | public void commit() throws ConcurrentModificationException, |
| | | OperationRejectedException, AuthorizationException, |
| | | CommunicationException { |
| | | CommunicationException, ManagedObjectAlreadyExistsException, |
| | | MissingMandatoryPropertiesException { |
| | | impl.commit(); |
| | | } |
| | | |
| | |
| | | * {@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(); |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * 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 |
| | |
| | | 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); |
| | | } |
| | | } |
| | | |
| | |
| | | // 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 |
| | |
| | | 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); |
| | | } |
| | | |
| | | } |
| | |
| | | } |
| | | |
| | | 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 |
| | |
| | | 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>() |
| | | ); |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | 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; |
| | |
| | | "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", "" }; |
| | | |
| | | |
| | | |
| | |
| | | */ |
| | | @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); |
| | |
| | | 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(); |
| | | } |
| | | |
| | |
| | | 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(); |
| | | } |
| | | |
| | |
| | | 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); |
| | | } |
| | |
| | | */ |
| | | @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(); |
| | | } |
| | | |
| | |
| | | |
| | | 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(); |
| | | } |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | | |
| | |
| | | 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); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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(); |
| | | } |
| | | |
| | | |