From 9971cf7ea019068c313db98499001cb1eb1f72ab Mon Sep 17 00:00:00 2001
From: sin <sin@localhost>
Date: Fri, 15 May 2009 14:38:45 +0000
Subject: [PATCH] issue 3961:Implement operational attribute 'governingstructurerule
---
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/GoverningStructureRuleVirtualAttributeConfiguration.xml | 69 +
opendj-sdk/opends/src/server/org/opends/server/extensions/StructuralObjectClassVirtualAttributeProvider.java | 214 +++++
opendj-sdk/opends/src/server/org/opends/server/extensions/SubschemaSubentryVirtualAttributeProvider.java | 2
opendj-sdk/opends/src/messages/messages/extension.properties | 2
opendj-sdk/opends/src/server/org/opends/server/extensions/GoverningStructureRuleVirtualAttributeProvider.java | 298 +++++++
opendj-sdk/opends/resource/config/config.ldif | 20
opendj-sdk/opends/resource/schema/00-core.ldif | 6
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/GoverningStructureRuleVirtualAttributeProviderTestCase.java | 898 +++++++++++++++++++++
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/StructuralObjectClassVirtualAttributeConfiguration.xml | 69 +
opendj-sdk/opends/resource/schema/02-config.ldif | 10
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/StructuralObjectClassVirtualAttributeProviderTestCase.java | 870 +++++++++++++++++++++
11 files changed, 2,456 insertions(+), 2 deletions(-)
diff --git a/opendj-sdk/opends/resource/config/config.ldif b/opendj-sdk/opends/resource/config/config.ldif
index b19db2a..a6d685c 100644
--- a/opendj-sdk/opends/resource/config/config.ldif
+++ b/opendj-sdk/opends/resource/config/config.ldif
@@ -2394,6 +2394,26 @@
ds-cfg-attribute-type: subschemaSubentry
ds-cfg-conflict-behavior: virtual-overrides-real
+dn: cn=structuralObjectClass,cn=Virtual Attributes,cn=config
+objectClass: top
+objectClass: ds-cfg-virtual-attribute
+objectClass: ds-cfg-structural-object-class-virtual-attribute
+cn: structuralObjectClass
+ds-cfg-java-class: org.opends.server.extensions.StructuralObjectClassVirtualAttributeProvider
+ds-cfg-enabled: true
+ds-cfg-attribute-type: structuralObjectClass
+ds-cfg-conflict-behavior: virtual-overrides-real
+
+dn: cn=governingStructureRule,cn=Virtual Attributes,cn=config
+objectClass: top
+objectClass: ds-cfg-virtual-attribute
+objectClass: ds-cfg-governing-structure-rule-virtual-attribute
+cn: governingStructureRule
+ds-cfg-java-class: org.opends.server.extensions.GoverningStructureRuleVirtualAttributeProvider
+ds-cfg-enabled: true
+ds-cfg-attribute-type: governingStructureRule
+ds-cfg-conflict-behavior: virtual-overrides-real
+
dn: cn=Virtual Static member,cn=Virtual Attributes,cn=config
objectClass: top
objectClass: ds-cfg-virtual-attribute
diff --git a/opendj-sdk/opends/resource/schema/00-core.ldif b/opendj-sdk/opends/resource/schema/00-core.ldif
index 8476378..97ced53 100644
--- a/opendj-sdk/opends/resource/schema/00-core.ldif
+++ b/opendj-sdk/opends/resource/schema/00-core.ldif
@@ -195,6 +195,12 @@
attributeTypes: ( 2.5.21.8 NAME 'matchingRuleUse' EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 USAGE directoryOperation
X-ORIGIN 'RFC 4512' )
+attributeTypes: ( 2.5.21.9 NAME 'structuralObjectClass' EQUALITY objectIdentifierMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 SINGLE-VALUE NO-USER-MODIFICATION
+ USAGE directoryOperation X-ORIGIN 'RFC 4512' )
+attributeTypes: ( 2.5.21.10 NAME 'governingStructureRule' EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE NO-USER-MODIFICATION
+ USAGE directoryOperation X-ORIGIN 'RFC 4512' )
attributeTypes: ( 1.3.6.1.4.1.1466.101.120.5 NAME 'namingContexts'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 USAGE dSAOperation X-ORIGIN 'RFC 4512' )
attributeTypes: ( 1.3.6.1.4.1.1466.101.120.6 NAME 'altServer'
diff --git a/opendj-sdk/opends/resource/schema/02-config.ldif b/opendj-sdk/opends/resource/schema/02-config.ldif
index 6f5adf7..cdea6f0 100644
--- a/opendj-sdk/opends/resource/schema/02-config.ldif
+++ b/opendj-sdk/opends/resource/schema/02-config.ldif
@@ -4039,4 +4039,14 @@
SUP ds-cfg-backend
STRUCTURAL
X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.201
+ NAME 'ds-cfg-structural-object-class-virtual-attribute'
+ SUP ds-cfg-virtual-attribute
+ STRUCTURAL
+ X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.202
+ NAME 'ds-cfg-governing-structure-rule-virtual-attribute'
+ SUP ds-cfg-virtual-attribute
+ STRUCTURAL
+ X-ORIGIN 'OpenDS Directory Server' )
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/GoverningStructureRuleVirtualAttributeConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/GoverningStructureRuleVirtualAttributeConfiguration.xml
new file mode 100644
index 0000000..7b85b64
--- /dev/null
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/GoverningStructureRuleVirtualAttributeConfiguration.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ! 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
+ !
+ !
+ ! Copyright 2009 Sun Microsystems, Inc.
+ ! -->
+<adm:managed-object name="governing-structure-rule-virtual-attribute"
+ plural-name="governing-structure-rule-virtual-attributes"
+ package="org.opends.server.admin.std" extends="virtual-attribute"
+ xmlns:adm="http://www.opends.org/admin"
+ xmlns:ldap="http://www.opends.org/admin-ldap">
+ <adm:synopsis>
+ The
+ <adm:user-friendly-name />
+ generates a virtual attribute that specifies the DIT structure rule
+ with the schema definitions in effect for the
+ entry. This attribute is defined in RFC 4512.
+ </adm:synopsis>
+ <adm:profile name="ldap">
+ <ldap:object-class>
+ <ldap:name>ds-cfg-governing-structure-rule-virtual-attribute</ldap:name>
+ <ldap:superior>ds-cfg-virtual-attribute</ldap:superior>
+ </ldap:object-class>
+ </adm:profile>
+ <adm:property-override name="java-class" advanced="true">
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>
+ org.opends.server.extensions.GoverningSturctureRuleVirtualAttributeProvider
+ </adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ </adm:property-override>
+ <adm:property-override name="conflict-behavior" advanced="true">
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>virtual-overrides-real</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ </adm:property-override>
+ <adm:property-override name="attribute-type">
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>governingStructureRule</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ </adm:property-override>
+</adm:managed-object>
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/StructuralObjectClassVirtualAttributeConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/StructuralObjectClassVirtualAttributeConfiguration.xml
new file mode 100644
index 0000000..5b3c862
--- /dev/null
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/StructuralObjectClassVirtualAttributeConfiguration.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ! 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
+ !
+ !
+ ! Copyright 2009 Sun Microsystems, Inc.
+ ! -->
+<adm:managed-object name="structural-object-class-virtual-attribute"
+ plural-name="structural-object-class-virtual-attributes"
+ package="org.opends.server.admin.std" extends="virtual-attribute"
+ xmlns:adm="http://www.opends.org/admin"
+ xmlns:ldap="http://www.opends.org/admin-ldap">
+ <adm:synopsis>
+ The
+ <adm:user-friendly-name />
+ generates a virtual attribute that specifies the structural object class
+ with the schema definitions in effect for the
+ entry. This attribute is defined in RFC 4512.
+ </adm:synopsis>
+ <adm:profile name="ldap">
+ <ldap:object-class>
+ <ldap:name>ds-cfg-structural-object-class-virtual-attribute</ldap:name>
+ <ldap:superior>ds-cfg-virtual-attribute</ldap:superior>
+ </ldap:object-class>
+ </adm:profile>
+ <adm:property-override name="java-class" advanced="true">
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>
+ org.opends.server.extensions.StructuralObjectClassVirtualAttributeProvider
+ </adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ </adm:property-override>
+ <adm:property-override name="conflict-behavior" advanced="true">
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>virtual-overrides-real</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ </adm:property-override>
+ <adm:property-override name="attribute-type">
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>structuralObjectClass</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ </adm:property-override>
+</adm:managed-object>
diff --git a/opendj-sdk/opends/src/messages/messages/extension.properties b/opendj-sdk/opends/src/messages/messages/extension.properties
index 3461468..e63b8aa 100644
--- a/opendj-sdk/opends/src/messages/messages/extension.properties
+++ b/opendj-sdk/opends/src/messages/messages/extension.properties
@@ -1134,7 +1134,7 @@
MILD_ERR_UNIQUECHARS_VALIDATOR_NOT_ENOUGH_UNIQUE_CHARS_458=The provided \
password does not contain enough unique characters. The minimum number of \
unique characters that may appear in a user password is %d
-MILD_ERR_SUBSCHEMASUBENTRY_VATTR_NOT_SEARCHABLE_459=The %s attribute is not \
+MILD_ERR_VATTR_NOT_SEARCHABLE_459=The %s attribute is not \
searchable and should not be included in otherwise unindexed search filters
MILD_ERR_DICTIONARY_VALIDATOR_PASSWORD_IN_DICTIONARY_460=The provided \
password was found in the server's dictionary
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/GoverningStructureRuleVirtualAttributeProvider.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/GoverningStructureRuleVirtualAttributeProvider.java
new file mode 100644
index 0000000..2aad816
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/GoverningStructureRuleVirtualAttributeProvider.java
@@ -0,0 +1,298 @@
+/*
+ * 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
+ *
+ *
+ * Copyright 2009 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.opends.messages.Message;
+import org.opends.server.admin.std.server.
+ GoverningStructureRuleVirtualAttributeCfg;
+import org.opends.server.api.VirtualAttributeProvider;
+import org.opends.server.config.ConfigException;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.core.SearchOperation;
+import org.opends.server.types.*;
+
+import static org.opends.messages.ExtensionMessages.*;
+
+
+
+/**
+ * This class implements a virtual attribute provider that is meant to serve
+ * the governingStructuralRule operational attribute as described in RFC 4512.
+ */
+public class GoverningStructureRuleVirtualAttributeProvider extends
+ VirtualAttributeProvider<GoverningStructureRuleVirtualAttributeCfg>
+{
+ /**
+ * Creates a new instance of this governingStructureRule virtual attribute
+ * provider.
+ */
+ public GoverningStructureRuleVirtualAttributeProvider()
+ {
+ super();
+
+ // All initialization should be performed in the
+ // initializeVirtualAttributeProvider method.
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void initializeVirtualAttributeProvider(
+ GoverningStructureRuleVirtualAttributeCfg configuration)
+ throws ConfigException, InitializationException
+ {
+ // No initialization is required.
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public boolean isMultiValued()
+ {
+ return false;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public Set<AttributeValue> getValues(Entry entry,
+ VirtualAttributeRule rule)
+ {
+ DITStructureRule ditRule = getDITStructureRule(entry);
+
+ if(ditRule !=null)
+ {
+ return Collections.singleton(AttributeValues.create(
+ rule.getAttributeType(),
+ String.valueOf(ditRule.getRuleID())));
+ }
+
+ return Collections.<AttributeValue>emptySet();
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public boolean hasValue(Entry entry, VirtualAttributeRule rule)
+ {
+ return getDITStructureRule(entry)!=null;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public ConditionResult matchesSubstring(Entry entry,
+ VirtualAttributeRule rule,
+ ByteString subInitial,
+ List<ByteString> subAny,
+ ByteString subFinal)
+ {
+ // DITStructureRule cannot be used in substring matching.
+ return ConditionResult.UNDEFINED;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public ConditionResult greaterThanOrEqualTo(Entry entry,
+ VirtualAttributeRule rule,
+ AttributeValue value)
+ {
+ // DITStructureRule cannot be used in ordering matching.
+ return ConditionResult.UNDEFINED;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public ConditionResult lessThanOrEqualTo(Entry entry,
+ VirtualAttributeRule rule,
+ AttributeValue value)
+ {
+ // DITStructureRule cannot be used in ordering matching.
+ return ConditionResult.UNDEFINED;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public ConditionResult approximatelyEqualTo(Entry entry,
+ VirtualAttributeRule rule,
+ AttributeValue value)
+ {
+ // DITStructureRule cannot be used in approximate matching.
+ return ConditionResult.UNDEFINED;
+ }
+
+
+
+ /**
+ * {@inheritDoc}. This virtual attribute will support search operations only
+ * if one of the following is true about the search filter:
+ * <UL>
+ * <LI>It is an equality filter targeting the associated attribute
+ * type.</LI>
+ * <LI>It is an AND filter in which at least one of the components is an
+ * equality filter targeting the associated attribute type.</LI>
+ * <LI>It is an OR filter in which all of the components are equality
+ * filters targeting the associated attribute type.</LI>
+ * </UL>
+ */
+ @Override()
+ public boolean isSearchable(VirtualAttributeRule rule,
+ SearchOperation searchOperation)
+ {
+ //Non-searchable for unindexed searches.
+ return false;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void processSearch(VirtualAttributeRule rule,
+ SearchOperation searchOperation)
+ {
+ searchOperation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
+
+ Message message = ERR_VATTR_NOT_SEARCHABLE.get(
+ rule.getAttributeType().getNameOrOID());
+ searchOperation.appendErrorMessage(message);
+ }
+
+
+
+ //Checks if the entry matches the nameform.
+ private boolean matchesNameForm(NameForm nameForm,
+ AcceptRejectWarn structuralPolicy,
+ Entry entry)
+ {
+ RDN rdn = entry.getDN().getRDN();
+ if (rdn != null)
+ {
+ // Make sure that all the required attributes are present.
+ for (AttributeType t : nameForm.getRequiredAttributes())
+ {
+ if (! rdn.hasAttributeType(t))
+ {
+ if (structuralPolicy == AcceptRejectWarn.REJECT)
+ {
+ return false;
+ }
+ }
+ }
+
+ // Make sure that all attributes in the RDN are allowed.
+ int numAVAs = rdn.getNumValues();
+ for (int i = 0; i < numAVAs; i++)
+ {
+ AttributeType t = rdn.getAttributeType(i);
+ if (! nameForm.isRequiredOrOptional(t))
+ {
+ if (structuralPolicy == AcceptRejectWarn.REJECT)
+ {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+
+
+ //Finds the appropriate DIT structure rule for an entry.
+ private DITStructureRule getDITStructureRule(Entry entry)
+ {
+ ObjectClass oc = entry.getStructuralObjectClass();
+ List<NameForm> listForms = DirectoryServer.getNameForm(oc);
+ NameForm nameForm = null;
+ DITStructureRule ditRule = null;
+ //We iterate over all the nameforms while creating the entry and
+ //select the first one that matches. Since the entry exists, the same
+ //algorithm should work fine to retrieve the nameform which was
+ //applied while creating the entry.
+ if(listForms != null)
+ {
+ boolean obsolete = true;
+ AcceptRejectWarn structuralPolicy =
+ DirectoryServer.getSingleStructuralObjectClassPolicy();
+ for(NameForm nf : listForms)
+ {
+ if(!nf.isObsolete())
+ {
+ obsolete = false;
+ if(matchesNameForm(nf,
+ structuralPolicy, entry))
+ {
+ nameForm = nf;
+ break;
+ }
+ }
+ }
+ if( nameForm != null && !obsolete)
+ {
+ ditRule =
+ DirectoryServer.getDITStructureRule(nameForm);
+ }
+ }
+ return ditRule;
+ }
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/StructuralObjectClassVirtualAttributeProvider.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/StructuralObjectClassVirtualAttributeProvider.java
new file mode 100644
index 0000000..6a1568b
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/StructuralObjectClassVirtualAttributeProvider.java
@@ -0,0 +1,214 @@
+/*
+ * 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
+ *
+ *
+ * Copyright 2009 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.opends.messages.Message;
+import org.opends.server.admin.std.server.
+ StructuralObjectClassVirtualAttributeCfg;
+import org.opends.server.api.VirtualAttributeProvider;
+import org.opends.server.config.ConfigException;
+import org.opends.server.core.SearchOperation;
+import org.opends.server.types.*;
+
+import static org.opends.messages.ExtensionMessages.*;
+
+
+
+/**
+ * This class implements a virtual attribute provider that is meant to serve
+ * the structuralObjectClass operational attribute as described in RFC 4512.
+ */
+public class StructuralObjectClassVirtualAttributeProvider
+ extends VirtualAttributeProvider<StructuralObjectClassVirtualAttributeCfg>
+{
+ /**
+ * Creates a new instance of this structuralObjectClass virtual attribute
+ * provider.
+ */
+ public StructuralObjectClassVirtualAttributeProvider()
+ {
+ super();
+
+ // All initialization should be performed in the
+ // initializeVirtualAttributeProvider method.
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void initializeVirtualAttributeProvider(
+ StructuralObjectClassVirtualAttributeCfg configuration)
+ throws ConfigException, InitializationException
+ {
+ // No initialization is required.
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public boolean isMultiValued()
+ {
+ return false;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public Set<AttributeValue> getValues(Entry entry,
+ VirtualAttributeRule rule)
+ {
+ AttributeValue value =
+ AttributeValues.create(rule.getAttributeType(),
+ entry.getStructuralObjectClass().getNameOrOID());
+ return Collections.singleton(value);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public boolean hasValue(Entry entry, VirtualAttributeRule rule)
+ {
+ //A structural object class is always present in an entry.
+ return true;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public ConditionResult matchesSubstring(Entry entry,
+ VirtualAttributeRule rule,
+ ByteString subInitial,
+ List<ByteString> subAny,
+ ByteString subFinal)
+ {
+ //Substring matching is not supported.
+ return ConditionResult.UNDEFINED;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public ConditionResult greaterThanOrEqualTo(Entry entry,
+ VirtualAttributeRule rule,
+ AttributeValue value)
+ {
+ // An object class can not be used for ordering.
+ return ConditionResult.UNDEFINED;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public ConditionResult lessThanOrEqualTo(Entry entry,
+ VirtualAttributeRule rule,
+ AttributeValue value)
+ {
+ // An object class can not be used for ordering.
+ return ConditionResult.UNDEFINED;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public ConditionResult approximatelyEqualTo(Entry entry,
+ VirtualAttributeRule rule,
+ AttributeValue value)
+ {
+ // An object class can not be used in approximate matching.
+ return ConditionResult.UNDEFINED;
+ }
+
+
+
+ /**
+ * {@inheritDoc}. This virtual attribute will support search operations only
+ * if one of the following is true about the search filter:
+ * <UL>
+ * <LI>It is an equality filter targeting the associated attribute
+ * type.</LI>
+ * <LI>It is an AND filter in which at least one of the components is an
+ * equality filter targeting the associated attribute type.</LI>
+ * <LI>It is an OR filter in which all of the components are equality
+ * filters targeting the associated attribute type.</LI>
+ * </UL>
+ */
+ @Override()
+ public boolean isSearchable(VirtualAttributeRule rule,
+ SearchOperation searchOperation)
+ {
+ // This attribute is not searchable, since it will have the same value in
+ // tons of entries.
+ return false;
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override()
+ public void processSearch(VirtualAttributeRule rule,
+ SearchOperation searchOperation)
+ {
+ searchOperation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
+
+ Message message = ERR_VATTR_NOT_SEARCHABLE.get(
+ rule.getAttributeType().getNameOrOID());
+ searchOperation.appendErrorMessage(message);
+ }
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/SubschemaSubentryVirtualAttributeProvider.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/SubschemaSubentryVirtualAttributeProvider.java
index adf9955..d06d9e4 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/SubschemaSubentryVirtualAttributeProvider.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/SubschemaSubentryVirtualAttributeProvider.java
@@ -194,7 +194,7 @@
{
searchOperation.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
- Message message = ERR_SUBSCHEMASUBENTRY_VATTR_NOT_SEARCHABLE.get(
+ Message message = ERR_VATTR_NOT_SEARCHABLE.get(
rule.getAttributeType().getNameOrOID());
searchOperation.appendErrorMessage(message);
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/GoverningStructureRuleVirtualAttributeProviderTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/GoverningStructureRuleVirtualAttributeProviderTestCase.java
new file mode 100644
index 0000000..ef30b65
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/GoverningStructureRuleVirtualAttributeProviderTestCase.java
@@ -0,0 +1,898 @@
+/*
+ * 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
+ *
+ *
+ * Copyright 2009 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import static org.opends.server.util.ServerConstants.*;
+import static org.testng.Assert.*;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.opends.server.TestCaseUtils;
+import org.opends.server.admin.std.meta.VirtualAttributeCfgDefn;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.protocols.internal.InternalClientConnection;
+import org.opends.server.protocols.internal.InternalSearchOperation;
+import org.opends.server.protocols.ldap.LDAPControl;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.AttributeValues;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DereferencePolicy;
+import org.opends.server.types.Entry;
+import org.opends.server.types.SearchFilter;
+import org.opends.server.types.SearchScope;
+import org.opends.server.types.VirtualAttributeRule;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * A set of test cases for the governing structure rule virtual attribute
+ * provider.
+ */
+public class GoverningStructureRuleVirtualAttributeProviderTestCase
+ extends ExtensionsTestCase
+{
+ // The attribute type for the governingStructureRule attribute.
+ private AttributeType governingStructureRuleType;
+
+
+
+ /**
+ * Ensures that the Directory Server is running.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @BeforeClass()
+ public void startServer()
+ throws Exception
+ {
+ TestCaseUtils.startServer();
+
+ governingStructureRuleType =
+ DirectoryServer.getAttributeType("governingstructurerule", false);
+ assertNotNull(governingStructureRuleType);
+ int resultCode = TestCaseUtils.applyModifications(true,
+ "dn: cn=schema",
+ "changetype: modify",
+ "add: nameForms",
+ "nameForms: ( domainNameForm-oid NAME 'domainNameForm' OC domain MUST ( dc ) )",
+ "nameForms: ( organizationalNameForm-oid NAME 'organizationalNameForm' OC organization MUST ( o ) )",
+ "-",
+ "add: ditStructureRules",
+ "dITStructureRules: ( 21 NAME 'domainStructureRule' FORM domainNameForm )",
+ "dITStructureRules: ( 22 NAME 'organizationalStructureRule' FORM organizationalNameForm SUP 21 )"
+ );
+ assertTrue(resultCode == 0);
+ }
+
+
+
+ /**
+ * Ensures that the schema is cleaned up.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @AfterClass()
+ public void cleanup() throws Exception
+ {
+ int resultCode = TestCaseUtils.applyModifications(true,
+ "dn: cn=schema",
+ "changetype: modify",
+ "delete: ditStructureRules",
+ "dITStructureRules: ( 22 NAME 'organizationalStructureRule' FORM organizationalNameForm SUP 21 )",
+ "dITStructureRules: ( 21 NAME 'domainStructureRule' FORM domainNameForm )",
+ "-",
+ "delete: nameForms",
+ "nameForms: ( domainNameForm-oid NAME 'domainNameForm' OC domain MUST ( dc ) )",
+ "nameForms: ( organizationalNameForm-oid NAME 'organizationalNameForm' OC organization MUST ( o ) )"
+ );
+ assertTrue(resultCode == 0);
+ }
+
+
+
+ /**
+ * Retrieves a set of entry DNs for use in testing the
+ * governingStructureRule virtual attribute.
+ *
+ * @return A set of entry DNs for use in testing the governingStructureRule
+ * virtual attribute.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @DataProvider(name = "testEntryDNs")
+ public Object[][] getTestEntryDNs()
+ throws Exception
+ {
+ return new Object[][]
+ {
+ new Object[] { DN.decode("o=test") },
+ new Object[] { DN.decode("dc=example,dc=com") }
+ };
+ }
+
+
+
+ /**
+ * Retrieves a set of entry DNs and corresponding governing structure rule
+ * ids for use in testing the governingStructureRule virtual attribute.
+ *
+ * @return A set of entry DNs and id for use in testing the
+ * governingStructureRule virtual attribute.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @DataProvider(name = "testDNRuleID")
+ public Object[][] getTestEntryDNRuleID()
+ throws Exception
+ {
+ return new Object[][] {
+ {DN.decode("o=test"), "22"},
+ {DN.decode("dc=example,dc=com"), "21"},
+ };
+ }
+
+
+
+ /**
+ * Tests the {@code getEntry} method for the specified entry to ensure that
+ * the entry returned includes the governingStructureRule operational
+ * attribute with the correct value.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ * @param ruleId The rule id of the DITStructureRule.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testDNRuleID")
+ public void testGetEntry(DN entryDN,String ruleId)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ Entry e = DirectoryServer.getEntry(entryDN);
+ assertNotNull(e);
+ assertTrue(e.hasAttribute(governingStructureRuleType));
+
+ List<Attribute> attrList = e.getAttribute(governingStructureRuleType);
+ assertNotNull(attrList);
+ assertFalse(attrList.isEmpty());
+ for (Attribute a : attrList)
+ {
+ assertTrue(!a.isEmpty());
+ assertEquals(a.size(), 1);
+ assertTrue(a.contains(AttributeValues.create(governingStructureRuleType,
+ ruleId)));
+ }
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the governingStructureRule attribute is not included when the list of attributes
+ * requested is empty (defaulting to all user attributes).
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchEmptyAttrs(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT, filter);
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertFalse(e.hasAttribute(governingStructureRuleType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the governingStructureRule attribute is not included when the list of requested
+ * attributes is "1.1", meaning no attributes.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchNoAttrs(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("1.1");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, attrList);
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertFalse(e.hasAttribute(governingStructureRuleType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the governingStructureRule attribute is not included when all user attributes
+ * are requested.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchAllUserAttrs(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("*");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, attrList);
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertFalse(e.hasAttribute(governingStructureRuleType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the governingStructureRuleType attribute is included when all operational attributes
+ * are requested.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchAllOperationalAttrs(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("+");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, attrList);
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertTrue(e.hasAttribute(governingStructureRuleType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the governingStructureRule attribute is included when that attribute is
+ * specifically requested.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchGoverningStructureRulesAttr(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("governingStructureRule");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, attrList);
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertTrue(e.hasAttribute(governingStructureRuleType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the governingStructureRule attribute is not included when it is not in the list
+ * of attributes that is explicitly requested.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchExcludeGovStructRuleAttr(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("objectClass");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, attrList);
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertFalse(e.hasAttribute(governingStructureRuleType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the governingStructureRule attribute is included when that attribute is
+ * specifically requested and the governingStructureRule attribute is used in the
+ * search filter with a matching value.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testDNRuleID")
+ public void testSearchGovStructRuleInMatchingFilter(DN entryDN,String oc)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("governingstructurerule="+oc);
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("governingStructureRule");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, attrList);
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertTrue(e.hasAttribute(governingStructureRuleType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * no entries are returned when the governingStructureRule attribute is used in the
+ * search filter with a non-matching value.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchGovStructRuleAttrInNonMatchingFilter(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(governingStructureRule=1)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("governingStructureRuleType");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, attrList);
+ assertEquals(searchOperation.getSearchEntries().size(), 0);
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the governingStructureRule attribute is not included when that attribute is
+ * specifically requested and the real attributes only control is included in
+ * the request.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchGovStructRuleAttrRealAttrsOnly(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("governingStructureRuleType");
+
+ LinkedList<Control> requestControls = new LinkedList<Control>();
+ requestControls.add(new LDAPControl(OID_REAL_ATTRS_ONLY, true));
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ new InternalSearchOperation(conn, InternalClientConnection
+ .nextOperationID(), InternalClientConnection
+ .nextMessageID(), requestControls, entryDN,
+ SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, filter,
+ attrList, null);
+ searchOperation.run();
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertFalse(e.hasAttribute(governingStructureRuleType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the governingStructureRule attribute is included when that attribute is
+ * specifically requested and the virtual attributes only control is included
+ * in the request.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchGovStructRuleAttrVirtualAttrsOnly(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("governingStructureRule");
+
+ LinkedList<Control> requestControls = new LinkedList<Control>();
+ requestControls.add(new LDAPControl(OID_VIRTUAL_ATTRS_ONLY, true));
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ new InternalSearchOperation(conn, InternalClientConnection
+ .nextOperationID(), InternalClientConnection
+ .nextMessageID(), requestControls, entryDN,
+ SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, filter,
+ attrList, null);
+ searchOperation.run();
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertTrue(e.hasAttribute(governingStructureRuleType));
+ }
+
+
+
+ /**
+ * Tests the {@code isMultiValued} method.
+ */
+ @Test()
+ public void testIsMultiValued()
+ {
+ GoverningStructureRuleVirtualAttributeProvider provider =
+ new GoverningStructureRuleVirtualAttributeProvider();
+ assertFalse(provider.isMultiValued());
+ }
+
+
+
+ /**
+ * Tests the {@code getValues} method for an entry.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testGetValues()
+ throws Exception
+ {
+ GoverningStructureRuleVirtualAttributeProvider provider =
+ new GoverningStructureRuleVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectclass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(governingStructureRuleType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ Set<AttributeValue> values = provider.getValues(entry, rule);
+ assertNotNull(values);
+ assertEquals(values.size(), 1);
+ assertTrue(values.contains(AttributeValues.create(governingStructureRuleType,
+ "22")));
+ }
+
+
+
+ /**
+ * Tests the {@code hasValue} method variant that doesn't take a specific
+ * value.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasAnyValue()
+ throws Exception
+ {
+ GoverningStructureRuleVirtualAttributeProvider provider =
+ new GoverningStructureRuleVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectClass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(governingStructureRuleType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ assertTrue(provider.hasValue(entry, rule));
+ }
+
+
+
+ /**
+ * Tests the {@code hasValue} method variant that takes a specific value when
+ * the provided value is a match.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasMatchingValue()
+ throws Exception
+ {
+ GoverningStructureRuleVirtualAttributeProvider provider =
+ new GoverningStructureRuleVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectclass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(governingStructureRuleType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ assertTrue(provider.hasValue(entry, rule,
+ AttributeValues.create(governingStructureRuleType,"22")));
+ }
+
+
+
+ /**
+ * Tests the {@code hasValue} method variant that takes a specific value when
+ * the provided value is not a match.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasNonMatchingValue()
+ throws Exception
+ {
+ GoverningStructureRuleVirtualAttributeProvider provider =
+ new GoverningStructureRuleVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectClass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(governingStructureRuleType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ assertFalse(provider.hasValue(entry, rule,
+ AttributeValues.create(governingStructureRuleType,
+ "1")));
+ }
+
+
+
+ /**
+ * Tests the {@code hasAnyValue} method with an empty set of values.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasAnyValueEmptySet()
+ throws Exception
+ {
+ GoverningStructureRuleVirtualAttributeProvider provider =
+ new GoverningStructureRuleVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectclass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(governingStructureRuleType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ assertFalse(provider.hasAnyValue(entry, rule,
+ Collections.<AttributeValue>emptySet()));
+ }
+
+
+
+ /**
+ * Tests the {@code hasAnyValue} method with a set of values containing only
+ * the correct value.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasAnyValueOnlyCorrect()
+ throws Exception
+ {
+ GoverningStructureRuleVirtualAttributeProvider provider =
+ new GoverningStructureRuleVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectClass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(governingStructureRuleType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(1);
+ values.add(AttributeValues.create(governingStructureRuleType, "22"));
+
+ assertTrue(provider.hasAnyValue(entry, rule, values));
+ }
+
+
+
+ /**
+ * Tests the {@code hasAnyValue} method with a set of values containing only
+ * an incorrect value.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasAnyValueOnlyIncorrect()
+ throws Exception
+ {
+ GoverningStructureRuleVirtualAttributeProvider provider =
+ new GoverningStructureRuleVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectclass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(governingStructureRuleType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(1);
+ values.add(AttributeValues.create(governingStructureRuleType, "1"));
+
+ assertFalse(provider.hasAnyValue(entry, rule, values));
+ }
+
+
+
+ /**
+ * Tests the {@code hasAnyValue} method with a set of values containing the
+ * correct value as well as multiple incorrect values.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasAnyValueIncludesCorrect()
+ throws Exception
+ {
+ GoverningStructureRuleVirtualAttributeProvider provider =
+ new GoverningStructureRuleVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectClass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(governingStructureRuleType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(3);
+ values.add(AttributeValues.create(governingStructureRuleType, "22"));
+ values.add(AttributeValues.create(governingStructureRuleType, "1"));
+ values.add(AttributeValues.create(governingStructureRuleType,"2"));
+
+ assertTrue(provider.hasAnyValue(entry, rule, values));
+ }
+
+
+
+ /**
+ * Tests the {@code hasAnyValue} method with a set of multiple values, none of
+ * which are correct.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasAnyValueMissingCorrect()
+ throws Exception
+ {
+ GoverningStructureRuleVirtualAttributeProvider provider =
+ new GoverningStructureRuleVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectclass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(governingStructureRuleType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(3);
+ values.add(AttributeValues.create(governingStructureRuleType, "1"));
+ values.add(AttributeValues.create(governingStructureRuleType, "2"));
+ values.add(AttributeValues.create(governingStructureRuleType,"3"));
+
+ assertFalse(provider.hasAnyValue(entry, rule, values));
+ }
+}
+
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/StructuralObjectClassVirtualAttributeProviderTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/StructuralObjectClassVirtualAttributeProviderTestCase.java
new file mode 100644
index 0000000..afb8571
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/StructuralObjectClassVirtualAttributeProviderTestCase.java
@@ -0,0 +1,870 @@
+/*
+ * 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
+ *
+ *
+ * Copyright 2009 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import static org.opends.server.util.ServerConstants.*;
+import static org.testng.Assert.*;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.opends.server.TestCaseUtils;
+import org.opends.server.admin.std.meta.VirtualAttributeCfgDefn;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.protocols.internal.InternalClientConnection;
+import org.opends.server.protocols.internal.InternalSearchOperation;
+import org.opends.server.protocols.ldap.LDAPControl;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.AttributeValues;
+import org.opends.server.types.Control;
+import org.opends.server.types.DN;
+import org.opends.server.types.DereferencePolicy;
+import org.opends.server.types.Entry;
+import org.opends.server.types.SearchFilter;
+import org.opends.server.types.SearchScope;
+import org.opends.server.types.VirtualAttributeRule;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * A set of test cases for the structural object class virtual attribute
+ * provider.
+ */
+public class StructuralObjectClassVirtualAttributeProviderTestCase
+ extends ExtensionsTestCase
+{
+ // The attribute type for the structuralobjectclass attribute.
+ private AttributeType structuralObjectClassType;
+
+
+
+ /**
+ * Ensures that the Directory Server is running.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @BeforeClass()
+ public void startServer()
+ throws Exception
+ {
+ TestCaseUtils.startServer();
+
+ structuralObjectClassType =
+ DirectoryServer.getAttributeType("structuralobjectclass", false);
+ assertNotNull(structuralObjectClassType);
+ }
+
+
+
+ /**
+ * Retrieves a set of entry DNs for use in testing the
+ * structuralObjectClassType virtual attribute.
+ *
+ * @return A set of entry DNs for use in testing the structuralobjectclass
+ * virtual attribute.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @DataProvider(name = "testEntryDNs")
+ public Object[][] getTestEntryDNs()
+ throws Exception
+ {
+ return new Object[][]
+ {
+ new Object[] { DN.decode("") },
+ new Object[] { DN.decode("o=test") },
+ new Object[] { DN.decode("dc=example,dc=com") },
+ new Object[] { DN.decode("cn=config") },
+ new Object[] { DN.decode("cn=schema") },
+ new Object[] { DN.decode("cn=tasks") },
+ new Object[] { DN.decode("cn=monitor") },
+ new Object[] { DN.decode("cn=backups") }
+ };
+ }
+
+
+
+ /**
+ * Retrieves a set of entry DNs and corresponding structural object classes
+ * for use in testing the structuralObjectClassType virtual attribute.
+ *
+ * @return A set of entry DNs and oc for use in testing the
+ * structuralobjectclass virtual attribute.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @DataProvider(name = "testDNOC")
+ public Object[][] getTestEntryDNOC()
+ throws Exception
+ {
+ return new Object[][] {
+ {DN.decode("o=test"), "structuralObjectClass=organization"},
+ {DN.decode("dc=example,dc=com"), "structuralObjectClass=domain"},
+ };
+ }
+
+
+
+ /**
+ * Tests the {@code getEntry} method for the specified entry to ensure that
+ * the entry returned includes the structuralObjectClass operational
+ * attribute with the correct value.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testGetEntry(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ Entry e = DirectoryServer.getEntry(entryDN);
+ assertNotNull(e);
+ assertTrue(e.hasAttribute(structuralObjectClassType));
+
+ List<Attribute> attrList = e.getAttribute(structuralObjectClassType);
+ assertNotNull(attrList);
+ assertFalse(attrList.isEmpty());
+ for (Attribute a : attrList)
+ {
+ assertTrue(!a.isEmpty());
+ assertEquals(a.size(), 1);
+ assertTrue(a.contains(AttributeValues.create(structuralObjectClassType,
+ e.getStructuralObjectClass().getNameOrOID())));
+ }
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the structuralObjectClass attribute is not included when the list of attributes
+ * requested is empty (defaulting to all user attributes).
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchEmptyAttrs(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT, filter);
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertFalse(e.hasAttribute(structuralObjectClassType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the structuralObjectClass attribute is not included when the list of requested
+ * attributes is "1.1", meaning no attributes.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchNoAttrs(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("1.1");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, attrList);
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertFalse(e.hasAttribute(structuralObjectClassType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the structuralObjectClass attribute is not included when all user attributes
+ * are requested.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchAllUserAttrs(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("*");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, attrList);
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertFalse(e.hasAttribute(structuralObjectClassType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the structuralObjectClass attribute is included when all operational attributes
+ * are requested.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchAllOperationalAttrs(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("+");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, attrList);
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertTrue(e.hasAttribute(structuralObjectClassType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the structuralObjectClass attribute is included when that attribute is
+ * specifically requested.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchStructuralOCAttr(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("structuralobjectclass");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, attrList);
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertTrue(e.hasAttribute(structuralObjectClassType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the structuralObjectClass attribute is not included when it is not in the list
+ * of attributes that is explicitly requested.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchExcludeStructuralOCAttr(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("objectClass");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, attrList);
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertFalse(e.hasAttribute(structuralObjectClassType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the structuralObjectClass attribute is included when that attribute is
+ * specifically requested and the structuralObjectClass attribute is used in the
+ * search filter with a matching value.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testDNOC")
+ public void testSearchStructuralOCAttrInMatchingFilter(DN entryDN,String oc)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString(oc);
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("structuralObjectClass");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, attrList);
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertTrue(e.hasAttribute(structuralObjectClassType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * no entries are returned when the structuralObjectClass attribute is used in the
+ * search filter with a non-matching value.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchStructuralOCAttrInNonMatchingFilter(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(structuralObjectClass=abc)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("structuralObjectClass");
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ conn.processSearch(entryDN, SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+ filter, attrList);
+ assertEquals(searchOperation.getSearchEntries().size(), 0);
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the structuralObjectClass attribute is not included when that attribute is
+ * specifically requested and the real attributes only control is included in
+ * the request.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchStructuralOCAttrRealAttrsOnly(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("structuralObjectClass");
+
+ LinkedList<Control> requestControls = new LinkedList<Control>();
+ requestControls.add(new LDAPControl(OID_REAL_ATTRS_ONLY, true));
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ new InternalSearchOperation(conn, InternalClientConnection
+ .nextOperationID(), InternalClientConnection
+ .nextMessageID(), requestControls, entryDN,
+ SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, filter,
+ attrList, null);
+ searchOperation.run();
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertFalse(e.hasAttribute(structuralObjectClassType));
+ }
+
+
+
+ /**
+ * Performs an internal search to retrieve the specified entry, ensuring that
+ * the structuralObjectClass attribute is included when that attribute is
+ * specifically requested and the virtual attributes only control is included
+ * in the request.
+ *
+ * @param entryDN The DN of the entry to retrieve and verify.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test(dataProvider = "testEntryDNs")
+ public void testSearchStructuralOCAttrVirtualAttrsOnly(DN entryDN)
+ throws Exception
+ {
+ TestCaseUtils.initializeTestBackend(true);
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ SearchFilter filter =
+ SearchFilter.createFilterFromString("(objectClass=*)");
+ LinkedHashSet<String> attrList = new LinkedHashSet<String>(1);
+ attrList.add("structuralObjectClass");
+
+ LinkedList<Control> requestControls = new LinkedList<Control>();
+ requestControls.add(new LDAPControl(OID_VIRTUAL_ATTRS_ONLY, true));
+
+ InternalClientConnection conn =
+ InternalClientConnection.getRootConnection();
+ InternalSearchOperation searchOperation =
+ new InternalSearchOperation(conn, InternalClientConnection
+ .nextOperationID(), InternalClientConnection
+ .nextMessageID(), requestControls, entryDN,
+ SearchScope.BASE_OBJECT,
+ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, filter,
+ attrList, null);
+ searchOperation.run();
+ assertEquals(searchOperation.getSearchEntries().size(), 1);
+
+ Entry e = searchOperation.getSearchEntries().get(0);
+ assertNotNull(e);
+ assertTrue(e.hasAttribute(structuralObjectClassType));
+ }
+
+
+
+ /**
+ * Tests the {@code isMultiValued} method.
+ */
+ @Test()
+ public void testIsMultiValued()
+ {
+ StructuralObjectClassVirtualAttributeProvider provider =
+ new StructuralObjectClassVirtualAttributeProvider();
+ assertFalse(provider.isMultiValued());
+ }
+
+
+
+ /**
+ * Tests the {@code getValues} method for an entry.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testGetValues()
+ throws Exception
+ {
+ StructuralObjectClassVirtualAttributeProvider provider =
+ new StructuralObjectClassVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectClass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(structuralObjectClassType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ Set<AttributeValue> values = provider.getValues(entry, rule);
+ assertNotNull(values);
+ assertEquals(values.size(), 1);
+ assertTrue(values.contains(AttributeValues.create(structuralObjectClassType,
+ entry.getStructuralObjectClass().getNameOrOID())));
+ }
+
+
+
+ /**
+ * Tests the {@code hasValue} method variant that doesn't take a specific
+ * value.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasAnyValue()
+ throws Exception
+ {
+ StructuralObjectClassVirtualAttributeProvider provider =
+ new StructuralObjectClassVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectClass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(structuralObjectClassType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ assertTrue(provider.hasValue(entry, rule));
+ }
+
+
+
+ /**
+ * Tests the {@code hasValue} method variant that takes a specific value when
+ * the provided value is a match.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasMatchingValue()
+ throws Exception
+ {
+ StructuralObjectClassVirtualAttributeProvider provider =
+ new StructuralObjectClassVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectClass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(structuralObjectClassType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ assertTrue(provider.hasValue(entry, rule,
+ AttributeValues.create(structuralObjectClassType,
+ entry.getStructuralObjectClass().getNameOrOID())));
+ }
+
+
+
+ /**
+ * Tests the {@code hasValue} method variant that takes a specific value when
+ * the provided value is not a match.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasNonMatchingValue()
+ throws Exception
+ {
+ StructuralObjectClassVirtualAttributeProvider provider =
+ new StructuralObjectClassVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectClass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(structuralObjectClassType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ assertFalse(provider.hasValue(entry, rule,
+ AttributeValues.create(structuralObjectClassType,
+ "inetorgperson")));
+ }
+
+
+
+ /**
+ * Tests the {@code hasAnyValue} method with an empty set of values.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasAnyValueEmptySet()
+ throws Exception
+ {
+ StructuralObjectClassVirtualAttributeProvider provider =
+ new StructuralObjectClassVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectClass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(structuralObjectClassType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ assertFalse(provider.hasAnyValue(entry, rule,
+ Collections.<AttributeValue>emptySet()));
+ }
+
+
+
+ /**
+ * Tests the {@code hasAnyValue} method with a set of values containing only
+ * the correct value.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasAnyValueOnlyCorrect()
+ throws Exception
+ {
+ StructuralObjectClassVirtualAttributeProvider provider =
+ new StructuralObjectClassVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectClass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(structuralObjectClassType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(1);
+ values.add(AttributeValues.create(structuralObjectClassType, "organization"));
+
+ assertTrue(provider.hasAnyValue(entry, rule, values));
+ }
+
+
+
+ /**
+ * Tests the {@code hasAnyValue} method with a set of values containing only
+ * an incorrect value.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasAnyValueOnlyIncorrect()
+ throws Exception
+ {
+ StructuralObjectClassVirtualAttributeProvider provider =
+ new StructuralObjectClassVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectClass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(structuralObjectClassType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(1);
+ values.add(AttributeValues.create(structuralObjectClassType, "inetorgperson"));
+
+ assertFalse(provider.hasAnyValue(entry, rule, values));
+ }
+
+
+
+ /**
+ * Tests the {@code hasAnyValue} method with a set of values containing the
+ * correct value as well as multiple incorrect values.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasAnyValueIncludesCorrect()
+ throws Exception
+ {
+ StructuralObjectClassVirtualAttributeProvider provider =
+ new StructuralObjectClassVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectClass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(structuralObjectClassType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(3);
+ values.add(AttributeValues.create(structuralObjectClassType, "organization"));
+ values.add(AttributeValues.create(structuralObjectClassType, "inetorgperson"));
+ values.add(AttributeValues.create(structuralObjectClassType,
+ "top"));
+
+ assertTrue(provider.hasAnyValue(entry, rule, values));
+ }
+
+
+
+ /**
+ * Tests the {@code hasAnyValue} method with a set of multiple values, none of
+ * which are correct.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @Test()
+ public void testHasAnyValueMissingCorrect()
+ throws Exception
+ {
+ StructuralObjectClassVirtualAttributeProvider provider =
+ new StructuralObjectClassVirtualAttributeProvider();
+
+ Entry entry = TestCaseUtils.makeEntry(
+ "dn: o=test",
+ "objectClass: top",
+ "objectClass: organization",
+ "o: test");
+ entry.processVirtualAttributes();
+
+ VirtualAttributeRule rule =
+ new VirtualAttributeRule(structuralObjectClassType, provider,
+ Collections.<DN>emptySet(), Collections.<DN>emptySet(),
+ Collections.<SearchFilter>emptySet(),
+ VirtualAttributeCfgDefn.ConflictBehavior.
+ VIRTUAL_OVERRIDES_REAL);
+
+ LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(3);
+ values.add(AttributeValues.create(structuralObjectClassType, "inetorgperson"));
+ values.add(AttributeValues.create(structuralObjectClassType,
+ "top"));
+ values.add(AttributeValues.create(structuralObjectClassType,
+ "domain"));
+
+ assertFalse(provider.hasAnyValue(entry, rule, values));
+ }
+}
+
--
Gitblit v1.10.0