Add initial support for a virtual attribute subsystem, and implement a few
different kinds of virtual attributes. This commit addresses the following
issues:
- Issue #1475 -- General virtual attribute support
- Issue #539 -- Support for the isMemberOf virtual attribute
- Issue #544 -- Support for the entryDN virtual attribute
- Issue #1056 -- Support for the subschemaSubentry virtual attribute
- Issue #85 -- Support for the real attributes only control
- Issue #86 -- Support for the virutal attributes only control
In general, virtual attribute support consists of three parts:
- An implementation of the org.opends.server.api.VirtualAttributeProvider
class, which provides the logic for actually generating the values, providing
support for various kinds of matching, and potentially the ability to process
search operations involving the virtual attribute that might not otherwise be
indexed.
- The org.opends.server.types.VirtualAttribute class, which is a subclass of
org.opends.server.types.Attribute and uses the virtual attribute provider to
generate its values.
- The org.opends.server.types.VirtualAttributeRule class, which associates a
virtual attribute provider with a given attribute type, and also with a set
of criteria that controls which entries should have the attribute.
The virtual attribute rule currently supports the following criteria that can
be used to decide whether an entry should have a given virtual attribute:
- Zero or more base DNs. If any base DNs are provided, then any entry which
falls below one of those base DNs will be a candidate to get the virtual
attribute. If no base DNs are provided, then DIT location will not be taken
into account when determining eligibility.
- Zero or more group DNs. If any group DNs are provided, then any entry that
belongs to one of the specified groups will be a candidate to get the virtual
attribute. If no group DNs are provided, then group membership will not be
taken into account when determining eligibility.
- Zero or more search filters. If any filters are provided, then any entry
that matches one of the specified filters will be a candidate to get the
virtual attribute. If no filters are provided, then the contents of the
entry will not be taken into account when determining eligibility.
In addition to that criteria, virtual attribute rules define a conflict
behavior, which controls how to behave when the entry already has one or more
real values for the attribute. The conflict behavior can be
"real-overrides-virtual" (to only show the real values),
"virtual-overrides-real" (to only show the virtual values), or
"merge-real-and-virtual" (to show both real and virtual values).
The virtual attribute implementation has been designed so that there should be
virtually no performance impact unless the attribute needs to be returned to
the client or it is referenced in a search filter, and you can completely
disable virtual attributes if you don't need them.
1 files deleted
13 files added
40 files modified
| | |
| | | objectClass: ds-cfg-branch |
| | | cn: Virtual Attributes |
| | | |
| | | dn: cn=entryDN,cn=Virtual Attributes,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-virtual-attribute |
| | | cn: entryDN |
| | | ds-cfg-virtual-attribute-class: org.opends.server.extensions.EntryDNVirtualAttributeProvider |
| | | ds-cfg-virtual-attribute-enabled: true |
| | | ds-cfg-virtual-attribute-type: entryDN |
| | | ds-cfg-virtual-attribute-conflict-behavior: virtual-overrides-real |
| | | |
| | | dn: cn=isMemberOf,cn=Virtual Attributes,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-virtual-attribute |
| | | cn: isMemberOf |
| | | ds-cfg-virtual-attribute-class: org.opends.server.extensions.IsMemberOfVirtualAttributeProvider |
| | | ds-cfg-virtual-attribute-enabled: true |
| | | ds-cfg-virtual-attribute-type: isMemberOf |
| | | ds-cfg-virtual-attribute-filter: (objectClass=person) |
| | | ds-cfg-virtual-attribute-conflict-behavior: virtual-overrides-real |
| | | |
| | | dn: cn=subschemaSubentry,cn=Virtual Attributes,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-virtual-attribute |
| | | cn: subschemaSubentry |
| | | ds-cfg-virtual-attribute-class: org.opends.server.extensions.SubschemaSubentryVirtualAttributeProvider |
| | | ds-cfg-virtual-attribute-enabled: true |
| | | ds-cfg-virtual-attribute-type: subschemaSubentry |
| | | ds-cfg-virtual-attribute-conflict-behavior: virtual-overrides-real |
| | | |
| | | dn: cn=Work Queue,cn=config |
| | | objectClass: top |
| | | objectClass: ds-cfg-work-queue |
| | |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'RFC 1274' ) |
| | | attributeTypes: ( 0.9.2342.19200300.100.1.31 NAME 'cNAMERecord' |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'RFC 1274' ) |
| | | attributeTypes: ( 2.16.840.1.113730.3.1.602 NAME 'entryDN' |
| | | DESC 'DN of the entry' EQUALITY distinguishedNameMatch |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE NO-USER-MODIFICATION |
| | | USAGE directoryOperation X-ORIGIN 'draft-zeilenga-ldap-entrydn' ) |
| | | objectClasses: ( 2.5.6.0 NAME 'top' ABSTRACT MUST objectClass |
| | | X-ORIGIN 'RFC 4512' ) |
| | | objectClasses: ( 2.5.6.1 NAME 'alias' SUP top STRUCTURAL MUST aliasedObjectName |
| | |
| | | NAME 'ds-cfg-case-sensitive-validation' |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.325 |
| | | NAME 'ds-cfg-virtual-attribute-class' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 |
| | | SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.326 |
| | | NAME 'ds-cfg-virtual-attribute-enabled' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 |
| | | SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.327 |
| | | NAME 'ds-cfg-virtual-attribute-type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 |
| | | SINGLE-VALUE X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.328 |
| | | NAME 'ds-cfg-virtual-attribute-base-dn' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.329 |
| | | NAME 'ds-cfg-virtual-attribute-group-dn' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.330 |
| | | NAME 'ds-cfg-virtual-attribute-filter' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | attributeTypes: ( 1.3.6.1.4.1.26027.1.1.331 |
| | | NAME 'ds-cfg-virtual-attribute-conflict-behavior' |
| | | SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | objectClasses: ( 1.3.6.1.4.1.26027.1.2.1 |
| | | NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL |
| | | MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled ) |
| | |
| | | SUP ds-cfg-password-validator STRUCTURAL |
| | | MUST ( ds-cfg-maximum-consecutive-length $ ds-cfg-case-sensitive-validation ) |
| | | X-ORIGIN 'OpenDS Directory Server' ) |
| | | objectClasses: ( 1.3.6.1.4.1.26027.1.2.91 NAME 'ds-cfg-virtual-attribute' |
| | | SUP top STRUCTURAL MUST ( cn $ ds-cfg-virtual-attribute-class $ |
| | | ds-cfg-virtual-attribute-enabled $ ds-cfg-virtual-attribute-type $ |
| | | ds-cfg-virtual-attribute-conflict-behavior ) |
| | | MAY ( ds-cfg-virtual-attribute-base-dn $ ds-cfg-virtual-attribute-group-dn $ |
| | | ds-cfg-virtual-attribute-filter ) X-ORIGIN 'OpenDS Directory Server' ) |
| | | |
| | |
| | | </ldap:rdn-sequence> |
| | | </adm:profile> |
| | | </adm:relation> |
| | | <adm:relation name="virtual-attribute"> |
| | | <adm:one-to-many /> |
| | | <adm:profile name="ldap"> |
| | | <ldap:rdn-sequence> |
| | | cn=Virtual Attributes,cn=config |
| | | </ldap:rdn-sequence> |
| | | </adm:profile> |
| | | </adm:relation> |
| | | <adm:product-name>OpenDS Directory Server</adm:product-name> |
| | | </adm:root-managed-object> |
| New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <adm:managed-object name="virtual-attribute" |
| | | plural-name="virtual-attributes" |
| | | package="org.opends.server.admin.std" |
| | | xmlns:adm="http://www.opends.org/admin" |
| | | xmlns:ldap="http://www.opends.org/admin-ldap"> |
| | | <adm:synopsis> |
| | | <adm:user-friendly-plural-name /> |
| | | are responsible for dynamically generating attribute values that appear in |
| | | entries but are not persistently stored in the backend. |
| | | </adm:synopsis> |
| | | <adm:profile name="ldap"> |
| | | <ldap:object-class> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.2.91</ldap:oid> |
| | | <ldap:name>ds-cfg-virtual-attribute</ldap:name> |
| | | <ldap:superior>top</ldap:superior> |
| | | </ldap:object-class> |
| | | </adm:profile> |
| | | |
| | | <adm:property name="provider-class" mandatory="true"> |
| | | <adm:synopsis> |
| | | The fully-qualified name of the Java class that provides the |
| | | <adm:user-friendly-name /> |
| | | implementation. |
| | | </adm:synopsis> |
| | | <adm:syntax> |
| | | <adm:java-class> |
| | | <adm:instance-of> |
| | | org.opends.server.api.VirtualAttributeProvider |
| | | </adm:instance-of> |
| | | </adm:java-class> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.325</ldap:oid> |
| | | <ldap:name>ds-cfg-virtual-attribute-class</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property name="enabled" mandatory="true"> |
| | | <adm:synopsis> |
| | | Indicate whether the |
| | | <adm:user-friendly-name /> |
| | | is enabled for use. |
| | | </adm:synopsis> |
| | | <adm:syntax> |
| | | <adm:boolean /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.326</ldap:oid> |
| | | <ldap:name>ds-cfg-virtual-attribute-enabled</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property name="attribute-type" mandatory="true"> |
| | | <adm:synopsis> |
| | | Specifies the attribute type for the attribute whose values should be |
| | | dynamically assigned by the virtual attribute. |
| | | </adm:synopsis> |
| | | <adm:syntax> |
| | | <adm:attribute-type /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.327</ldap:oid> |
| | | <ldap:name>ds-cfg-virtual-attribute-type</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property name="base-dn" mandatory="false" multi-valued="true"> |
| | | <adm:synopsis> |
| | | Specifies the base DNs for the branches containing entries that may be |
| | | eligible to use this virtual attribute. |
| | | </adm:synopsis> |
| | | <adm:default-behavior> |
| | | <adm:alias> |
| | | <adm:synopsis> |
| | | The location of the entry in the server will not be taken into account |
| | | when determining whether an entry is eligible to use this virtual |
| | | attribute. |
| | | </adm:synopsis> |
| | | </adm:alias> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:dn /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.328</ldap:oid> |
| | | <ldap:name>ds-cfg-virtual-attribute-base-dn</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property name="group-dn" mandatory="false" multi-valued="true"> |
| | | <adm:synopsis> |
| | | Specifies the DNs for the groups whose members may be eligible to use this |
| | | virtual attribute. |
| | | </adm:synopsis> |
| | | <adm:default-behavior> |
| | | <adm:alias> |
| | | <adm:synopsis> |
| | | Group membership will not be taken into accountwhen determining |
| | | whether an entry is eligible to use this virtual attribute. |
| | | </adm:synopsis> |
| | | </adm:alias> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:dn /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.329</ldap:oid> |
| | | <ldap:name>ds-cfg-virtual-attribute-group-dn</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property name="filter" mandatory="false" multi-valued="true"> |
| | | <adm:synopsis> |
| | | Specifies the search filters for entries that may be eligible to use this |
| | | virtual attribute. |
| | | </adm:synopsis> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>(objectClass=*)</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:string /> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.330</ldap:oid> |
| | | <ldap:name>ds-cfg-virtual-attribute-filter</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | |
| | | <adm:property name="conflict-behavior" mandatory="false"> |
| | | <adm:synopsis> |
| | | Specifies the behavior that the server should exhibit for entries that |
| | | contain one or more real values for the associated attribute. |
| | | </adm:synopsis> |
| | | <adm:default-behavior> |
| | | <adm:defined> |
| | | <adm:value>real-overrides-virtual</adm:value> |
| | | </adm:defined> |
| | | </adm:default-behavior> |
| | | <adm:syntax> |
| | | <adm:enumeration> |
| | | <adm:value name="real-overrides-virtual"> |
| | | <adm:synopsis> |
| | | Any real values contained in the entry should be preserved and |
| | | virtual values should not be generated. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="virtual-overrides-real"> |
| | | <adm:synopsis> |
| | | Any real values contained in the entry should be suppressed and |
| | | virtual values should be generated. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | <adm:value name="merge-real-and-virtual"> |
| | | <adm:synopsis> |
| | | Any real values contained in the entry should be preserved and |
| | | merged with the set of generated virtual values. |
| | | </adm:synopsis> |
| | | </adm:value> |
| | | </adm:enumeration> |
| | | </adm:syntax> |
| | | <adm:profile name="ldap"> |
| | | <ldap:attribute> |
| | | <ldap:oid>1.3.6.1.4.1.26027.1.1.331</ldap:oid> |
| | | <ldap:name>ds-cfg-virtual-attribute-conflict-behavior</ldap:name> |
| | | </ldap:attribute> |
| | | </adm:profile> |
| | | </adm:property> |
| | | </adm:managed-object> |
| | |
| | | */ |
| | | public abstract class ClientConnection |
| | | { |
| | | |
| | | |
| | | |
| | | // The set of authentication information for this client connection. |
| | | private AuthenticationInfo authenticationInfo; |
| | | |
| | |
| | | * searches performed using this client |
| | | * connection. |
| | | */ |
| | | public final void setSizeLimit(int sizeLimit) |
| | | public void setSizeLimit(int sizeLimit) |
| | | { |
| | | this.sizeLimit = sizeLimit; |
| | | } |
| | |
| | | * entries that should be check for |
| | | * matches during a search. |
| | | */ |
| | | public final void setLookthroughLimit(int lookthroughLimit) |
| | | public void setLookthroughLimit(int lookthroughLimit) |
| | | { |
| | | this.lookthroughLimit = lookthroughLimit; |
| | | } |
| | |
| | | * searches performed using this client |
| | | * connection. |
| | | */ |
| | | public final void setTimeLimit(int timeLimit) |
| | | public void setTimeLimit(int timeLimit) |
| | | { |
| | | this.timeLimit = timeLimit; |
| | | } |
| | |
| | | */ |
| | | public abstract class Group |
| | | { |
| | | |
| | | |
| | | |
| | | /** |
| | | * Initializes a "shell" instance of this group implementation that |
| | | * may be used to identify and instantiate instances of this type of |
| 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 2006-2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.api; |
| | | |
| | | |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | |
| | | import org.opends.server.admin.std.server.VirtualAttributeCfg; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.core.SearchOperation; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ConditionResult; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.VirtualAttributeRule; |
| | | |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class defines the set of methods and structures that must be |
| | | * implemented by a Directory Server module that implements the |
| | | * functionality required for one or more virtual attributes. |
| | | * |
| | | * @param <T> The type of configuration handled by this virtual |
| | | * attribute provider. |
| | | */ |
| | | public abstract class VirtualAttributeProvider |
| | | <T extends VirtualAttributeCfg> |
| | | { |
| | | /** |
| | | * Initializes this virtual attribute based on the information in |
| | | * the provided configuration entry. |
| | | * |
| | | * @param configuration The configuration to use to initialize |
| | | * this virtual attribute provider. |
| | | * |
| | | * @throws ConfigException If an unrecoverable problem arises in |
| | | * the process of performing the |
| | | * initialization. |
| | | * |
| | | * @throws InitializationException If a problem occurs during |
| | | * initialization that is not |
| | | * related to the server |
| | | * configuration. |
| | | */ |
| | | public abstract void initializeVirtualAttributeProvider( |
| | | T configuration) |
| | | throws ConfigException, InitializationException; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs any finalization that may be necessary whenever this |
| | | * virtual attribute provider is taken out of service. |
| | | */ |
| | | public void finalizeVirtualAttributeProvider() |
| | | { |
| | | // No implementation required by default. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this virtual attribute provider may generate |
| | | * multiple values. |
| | | * |
| | | * @return {@code true} if this virtual attribute provider may |
| | | * generate multiple values, or {@code false} if not. |
| | | */ |
| | | public abstract boolean isMultiValued(); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Generates a set of values for the provided entry. |
| | | * |
| | | * @param entry The entry for which the values are to be |
| | | * generated. |
| | | * @param rule The virtual attribute rule which defines the |
| | | * constraints for the virtual attribute. |
| | | * |
| | | * @return The set of values generated for the provided entry. It |
| | | * may be empty, but it must not be {@code null}. |
| | | */ |
| | | public abstract LinkedHashSet<AttributeValue> |
| | | getValues(Entry entry, |
| | | VirtualAttributeRule rule); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this virtual attribute provider will generate |
| | | * at least one value for the provided entry. |
| | | * |
| | | * @param entry The entry for which to make the determination. |
| | | * @param rule The virtual attribute rule which defines the |
| | | * constraints for the virtual attribute. |
| | | * |
| | | * @return {@code true} if this virtual attribute provider will |
| | | * generate at least one value for the provided entry, or |
| | | * {@code false} if not. |
| | | */ |
| | | public boolean hasValue(Entry entry, VirtualAttributeRule rule) |
| | | { |
| | | return (! getValues(entry, rule).isEmpty()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this virtual attribute provider will generate |
| | | * the provided value. |
| | | * |
| | | * @param entry The entry for which to make the determination. |
| | | * @param rule The virtual attribute rule which defines the |
| | | * constraints for the virtual attribute. |
| | | * @param value The value for which to make the determination. |
| | | * |
| | | * @return {@code true} if this virtual attribute provider will |
| | | * generate the specified vaule for the provided entry, or |
| | | * {@code false} if not. |
| | | */ |
| | | public boolean hasValue(Entry entry, VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | return getValues(entry, rule).contains(value); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this virtual attribute provider will generate |
| | | * all of the values in the provided collection. |
| | | * |
| | | * @param entry The entry for which to make the determination. |
| | | * @param rule The virtual attribute rule which defines the |
| | | * constraints for the virtual attribute. |
| | | * @param values The set of values for which to make the |
| | | * determination. |
| | | * |
| | | * @return {@code true} if this attribute provider will generate |
| | | * all of the values in the provided collection, or |
| | | * {@code false} if it will not generate at least one of |
| | | * them. |
| | | */ |
| | | public boolean hasAllValues(Entry entry, VirtualAttributeRule rule, |
| | | Collection<AttributeValue> values) |
| | | { |
| | | for (AttributeValue value : values) |
| | | { |
| | | if (! getValues(entry, rule).contains(value)) |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this virutal attribute provider will generate |
| | | * any of the values in the provided collection. |
| | | * |
| | | * @param entry The entry for which to make the determination. |
| | | * @param rule The virtual attribute rule which defines the |
| | | * constraints for the virtual attribute. |
| | | * @param values The set of values for which to make the |
| | | * determination. |
| | | * |
| | | * @return {@code true} if this attribute provider will generate |
| | | * at least one of the values in the provided collection, |
| | | * or {@code false} if it will not generate any of them. |
| | | */ |
| | | public boolean hasAnyValue(Entry entry, VirtualAttributeRule rule, |
| | | Collection<AttributeValue> values) |
| | | { |
| | | for (AttributeValue value : values) |
| | | { |
| | | if (getValues(entry, rule).contains(value)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this virtual attribute provider will generate |
| | | * any value which matches the provided substring. |
| | | * |
| | | * @param entry The entry for which to make the |
| | | * determination. |
| | | * @param rule The virtual attribute rule which defines the |
| | | * constraints for the virtual attribute. |
| | | * @param subInitial The subInitial component to use in the |
| | | * determination. |
| | | * @param subAny The subAny components to use in the |
| | | * determination. |
| | | * @param subFinal The subFinal component to use in the |
| | | * determination. |
| | | * |
| | | * @return <CODE>UNDEFINED</CODE> if this attribute does not have a |
| | | * substring matching rule, <CODE>TRUE</CODE> if at least |
| | | * one value matches the provided substring, or |
| | | * <CODE>FALSE</CODE> otherwise. |
| | | */ |
| | | public ConditionResult matchesSubstring(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | ByteString subInitial, |
| | | List<ByteString> subAny, |
| | | ByteString subFinal) |
| | | { |
| | | SubstringMatchingRule matchingRule = |
| | | rule.getAttributeType().getSubstringMatchingRule(); |
| | | if (matchingRule == null) |
| | | { |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | |
| | | ByteString normalizedSubInitial; |
| | | if (subInitial == null) |
| | | { |
| | | normalizedSubInitial = null; |
| | | } |
| | | else |
| | | { |
| | | try |
| | | { |
| | | normalizedSubInitial = |
| | | matchingRule.normalizeSubstring(subInitial); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // The substring couldn't be normalized. We have to return |
| | | // "undefined". |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | } |
| | | |
| | | |
| | | ArrayList<ByteString> normalizedSubAny; |
| | | if (subAny == null) |
| | | { |
| | | normalizedSubAny = null; |
| | | } |
| | | else |
| | | { |
| | | normalizedSubAny = |
| | | new ArrayList<ByteString>(subAny.size()); |
| | | for (ByteString subAnyElement : subAny) |
| | | { |
| | | try |
| | | { |
| | | normalizedSubAny.add(matchingRule.normalizeSubstring( |
| | | subAnyElement)); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // The substring couldn't be normalized. We have to return |
| | | // "undefined". |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | ByteString normalizedSubFinal; |
| | | if (subFinal == null) |
| | | { |
| | | normalizedSubFinal = null; |
| | | } |
| | | else |
| | | { |
| | | try |
| | | { |
| | | normalizedSubFinal = |
| | | matchingRule.normalizeSubstring(subFinal); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // The substring couldn't be normalized. We have to return |
| | | // "undefined". |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | } |
| | | |
| | | |
| | | ConditionResult result = ConditionResult.FALSE; |
| | | for (AttributeValue value : getValues(entry, rule)) |
| | | { |
| | | try |
| | | { |
| | | if (matchingRule.valueMatchesSubstring( |
| | | value.getNormalizedValue(), |
| | | normalizedSubInitial, |
| | | normalizedSubAny, |
| | | normalizedSubFinal)) |
| | | { |
| | | return ConditionResult.TRUE; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // The value couldn't be normalized. If we can't find a |
| | | // definite match, then we should return "undefined". |
| | | result = ConditionResult.UNDEFINED; |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this virtual attribute provider will generate |
| | | * any value for the provided entry that is greater than or equal to |
| | | * the given value. |
| | | * |
| | | * @param entry The entry for which to make the determination. |
| | | * @param rule The virtual attribute rule which defines the |
| | | * constraints for the virtual attribute. |
| | | * @param value The value for which to make the determination. |
| | | * |
| | | * @return {@code UNDEFINED} if the associated attribute type does |
| | | * not have an ordering matching rule, {@code TRUE} if at |
| | | * least one of the generated values will be greater than |
| | | * or equal to the specified value, or {@code FALSE} if |
| | | * none of the generated values will be greater than or |
| | | * equal to the specified value. |
| | | */ |
| | | public ConditionResult greaterThanOrEqualTo(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | OrderingMatchingRule matchingRule = |
| | | rule.getAttributeType().getOrderingMatchingRule(); |
| | | if (matchingRule == null) |
| | | { |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | ByteString normalizedValue; |
| | | try |
| | | { |
| | | normalizedValue = value.getNormalizedValue(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't normalize the provided value. We should return |
| | | // "undefined". |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | ConditionResult result = ConditionResult.FALSE; |
| | | for (AttributeValue v : getValues(entry, rule)) |
| | | { |
| | | try |
| | | { |
| | | ByteString nv = v.getNormalizedValue(); |
| | | int comparisonResult = |
| | | matchingRule.compareValues(nv, normalizedValue); |
| | | if (comparisonResult >= 0) |
| | | { |
| | | return ConditionResult.TRUE; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't normalize one of the attribute values. If we |
| | | // can't find a definite match, then we should return |
| | | // "undefined". |
| | | result = ConditionResult.UNDEFINED; |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this virtual attribute provider will generate |
| | | * any value for the provided entry that is less than or equal to |
| | | * the given value. |
| | | * |
| | | * @param entry The entry for which to make the determination. |
| | | * @param rule The virtual attribute rule which defines the |
| | | * constraints for the virtual attribute. |
| | | * @param value The value for which to make the determination. |
| | | * |
| | | * @return {@code UNDEFINED} if the associated attribute type does |
| | | * not have an ordering matching rule, {@code TRUE} if at |
| | | * least one of the generated values will be less than or |
| | | * equal to the specified value, or {@code FALSE} if none |
| | | * of the generated values will be greater than or equal to |
| | | * the specified value. |
| | | */ |
| | | public ConditionResult lessThanOrEqualTo(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | OrderingMatchingRule matchingRule = |
| | | rule.getAttributeType().getOrderingMatchingRule(); |
| | | if (matchingRule == null) |
| | | { |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | ByteString normalizedValue; |
| | | try |
| | | { |
| | | normalizedValue = value.getNormalizedValue(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't normalize the provided value. We should return |
| | | // "undefined". |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | ConditionResult result = ConditionResult.FALSE; |
| | | for (AttributeValue v : getValues(entry, rule)) |
| | | { |
| | | try |
| | | { |
| | | ByteString nv = v.getNormalizedValue(); |
| | | int comparisonResult = |
| | | matchingRule.compareValues(nv, normalizedValue); |
| | | if (comparisonResult <= 0) |
| | | { |
| | | return ConditionResult.TRUE; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't normalize one of the attribute values. If we |
| | | // can't find a definite match, then we should return |
| | | // "undefined". |
| | | result = ConditionResult.UNDEFINED; |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this virtual attribute provider will generate |
| | | * any value for the provided entry that is approximately equal to |
| | | * the given value. |
| | | * |
| | | * @param entry The entry for which to make the determination. |
| | | * @param rule The virtual attribute rule which defines the |
| | | * constraints for the virtual attribute. |
| | | * @param value The value for which to make the determination. |
| | | * |
| | | * @return {@code UNDEFINED} if the associated attribute type does |
| | | * not have an aproximate matching rule, {@code TRUE} if at |
| | | * least one of the generated values will be approximately |
| | | * equal to the specified value, or {@code FALSE} if none |
| | | * of the generated values will be approximately equal to |
| | | * the specified value. |
| | | */ |
| | | public ConditionResult approximatelyEqualTo(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | ApproximateMatchingRule matchingRule = |
| | | rule.getAttributeType().getApproximateMatchingRule(); |
| | | if (matchingRule == null) |
| | | { |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | ByteString normalizedValue; |
| | | try |
| | | { |
| | | normalizedValue = matchingRule.normalizeValue(value.getValue()); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't normalize the provided value. We should return |
| | | // "undefined". |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | ConditionResult result = ConditionResult.FALSE; |
| | | for (AttributeValue v : getValues(entry, rule)) |
| | | { |
| | | try |
| | | { |
| | | ByteString nv = matchingRule.normalizeValue(v.getValue()); |
| | | if (matchingRule.approximatelyMatch(nv, normalizedValue)) |
| | | { |
| | | return ConditionResult.TRUE; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | // We couldn't normalize one of the attribute values. If we |
| | | // can't find a definite match, then we should return |
| | | // "undefined". |
| | | result = ConditionResult.UNDEFINED; |
| | | } |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this attribute may be included in search |
| | | * filters as part of the criteria for locating entries. |
| | | * |
| | | * @param rule The virtual attribute rule which defines |
| | | * the constraints for the virtual |
| | | * attribute. |
| | | * @param searchOperation The search operation for which to make |
| | | * the determination. |
| | | * |
| | | * @return <CODE>true</CODE> if this attribute may be included in |
| | | * search filters, or <CODE>false</CODE> if not. |
| | | */ |
| | | public abstract boolean isSearchable(VirtualAttributeRule rule, |
| | | SearchOperation |
| | | searchOperation); |
| | | |
| | | |
| | | |
| | | /** |
| | | * Processes the provided search operation in which the search |
| | | * criteria includes an operation targeted at this virtual |
| | | * attribute. This method should only be called if |
| | | * <CODE>isSearchable</CODE> returns true and it is not possible to |
| | | * construct a manageable candidate list by processing other |
| | | * elements of the search criteria. |
| | | * |
| | | * @param rule The virtual attribute rule which defines |
| | | * the constraints for the virtual |
| | | * attribute. |
| | | * @param searchOperation The search operation to be processed. |
| | | */ |
| | | public abstract void processSearch(VirtualAttributeRule rule, |
| | | SearchOperation searchOperation); |
| | | } |
| | | |
| | |
| | | extends Backend |
| | | implements ConfigurableComponent |
| | | { |
| | | |
| | | |
| | | |
| | | // The DN of the configuration entry for this backend. |
| | | private DN configEntryDN; |
| | | |
| | |
| | | { |
| | | super(); |
| | | |
| | | |
| | | |
| | | // Perform all initialization in initializeBackend. |
| | | } |
| | | |
| | |
| | | // If the requested entry was the backend base entry, then retrieve it. |
| | | if (entryDN.equals(backupBaseDN)) |
| | | { |
| | | return backupBaseEntry; |
| | | return backupBaseEntry.duplicate(true); |
| | | } |
| | | |
| | | |
| | |
| | | userAttrs.put(t, attrList); |
| | | |
| | | |
| | | return new Entry(entryDN, ocMap, userAttrs, opAttrs); |
| | | Entry e = new Entry(entryDN, ocMap, userAttrs, opAttrs); |
| | | e.processVirtualAttributes(); |
| | | return e; |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | return new Entry(entryDN, ocMap, userAttrs, opAttrs); |
| | | Entry e = new Entry(entryDN, ocMap, userAttrs, opAttrs); |
| | | e.processVirtualAttributes(); |
| | | return e; |
| | | } |
| | | |
| | | |
| | |
| | | public class MemoryBackend |
| | | extends Backend |
| | | { |
| | | |
| | | |
| | | |
| | | // The base DNs for this backend. |
| | | private DN[] baseDNs; |
| | | |
| | |
| | | { |
| | | super(); |
| | | |
| | | |
| | | |
| | | // Perform all initialization in initializeBackend. |
| | | } |
| | | |
| | |
| | | public synchronized void addEntry(Entry entry, AddOperation addOperation) |
| | | throws DirectoryException |
| | | { |
| | | Entry e = entry.duplicate(true); |
| | | |
| | | // See if the target entry already exists. If so, then fail. |
| | | DN entryDN = entry.getDN(); |
| | | DN entryDN = e.getDN(); |
| | | if (entryMap.containsKey(entryDN)) |
| | | { |
| | | int msgID = MSGID_MEMORYBACKEND_ENTRY_ALREADY_EXISTS; |
| | |
| | | // If the entry is one of the base DNs, then add it. |
| | | if (baseDNSet.contains(entryDN)) |
| | | { |
| | | entryMap.put(entryDN, entry); |
| | | entryMap.put(entryDN, e); |
| | | return; |
| | | } |
| | | |
| | |
| | | throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message, msgID); |
| | | } |
| | | |
| | | entryMap.put(entryDN, entry); |
| | | entryMap.put(entryDN, e); |
| | | HashSet<DN> children = childDNs.get(parentDN); |
| | | if (children == null) |
| | | { |
| | |
| | | ModifyOperation modifyOperation) |
| | | throws DirectoryException |
| | | { |
| | | Entry e = entry.duplicate(true); |
| | | |
| | | // Make sure the entry exists. If not, then throw an exception. |
| | | DN entryDN = entry.getDN(); |
| | | DN entryDN = e.getDN(); |
| | | if (! entryMap.containsKey(entryDN)) |
| | | { |
| | | int msgID = MSGID_MEMORYBACKEND_ENTRY_DOESNT_EXIST; |
| | |
| | | |
| | | |
| | | // Replace the old entry with the new one. |
| | | entryMap.put(entryDN, entry); |
| | | entryMap.put(entryDN, e); |
| | | } |
| | | |
| | | |
| | |
| | | ModifyDNOperation modifyDNOperation) |
| | | throws DirectoryException |
| | | { |
| | | Entry e = entry.duplicate(true); |
| | | |
| | | // Make sure that the target entry exists. |
| | | if (! entryMap.containsKey(currentDN)) |
| | | { |
| | |
| | | |
| | | |
| | | // Make sure that no entry exists with the new DN. |
| | | if (entryMap.containsKey(entry.getDN())) |
| | | if (entryMap.containsKey(e.getDN())) |
| | | { |
| | | int msgID = MSGID_MEMORYBACKEND_ENTRY_ALREADY_EXISTS; |
| | | String message = getMessage(msgID, String.valueOf(entry.getDN())); |
| | | String message = getMessage(msgID, String.valueOf(e.getDN())); |
| | | throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message, msgID); |
| | | } |
| | | |
| | |
| | | boolean matchFound = false; |
| | | for (DN dn : baseDNs) |
| | | { |
| | | if (dn.isAncestorOf(entry.getDN())) |
| | | if (dn.isAncestorOf(e.getDN())) |
| | | { |
| | | matchFound = true; |
| | | break; |
| | |
| | | |
| | | |
| | | // Make sure that the parent of the new entry exists. |
| | | DN parentDN = entry.getDN().getParentDNInSuffix(); |
| | | DN parentDN = e.getDN().getParentDNInSuffix(); |
| | | if ((parentDN == null) || (! entryMap.containsKey(parentDN))) |
| | | { |
| | | int msgID = MSGID_MEMORYBACKEND_RENAME_PARENT_DOESNT_EXIST; |
| | |
| | | |
| | | // Delete the current entry and add the new one. |
| | | deleteEntry(currentDN, null); |
| | | addEntry(entry, null); |
| | | addEntry(e, null); |
| | | } |
| | | |
| | | |
| | |
| | | extends Backend |
| | | implements ConfigurableComponent |
| | | { |
| | | |
| | | |
| | | |
| | | // The set of user-defined attributes that will be included in the base |
| | | // monitor entry. |
| | | private ArrayList<Attribute> userDefinedAttributes; |
| | |
| | | { |
| | | super(); |
| | | |
| | | |
| | | |
| | | // Perform all initialization in initializeBackend. |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | // Construct and return the entry. |
| | | return new Entry(baseMonitorDN, monitorClasses, monitorUserAttrs, |
| | | monitorOperationalAttrs); |
| | | Entry e = new Entry(baseMonitorDN, monitorClasses, monitorUserAttrs, |
| | | monitorOperationalAttrs); |
| | | e.processVirtualAttributes(); |
| | | return e; |
| | | } |
| | | |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | return new Entry(entryDN, monitorClasses, attrMap, |
| | | new HashMap<AttributeType,List<Attribute>>(0)); |
| | | Entry e = new Entry(entryDN, monitorClasses, attrMap, |
| | | new HashMap<AttributeType,List<Attribute>>(0)); |
| | | e.processVirtualAttributes(); |
| | | return e; |
| | | } |
| | | |
| | | |
| | |
| | | extends Backend |
| | | implements ConfigurableComponent |
| | | { |
| | | |
| | | |
| | | |
| | | // The set of standard "static" attributes that we will always include in the |
| | | // root DSE entry and won't change while the server is running. |
| | | private ArrayList<Attribute> staticDSEAttributes; |
| | |
| | | { |
| | | super(); |
| | | |
| | | |
| | | |
| | | // Perform all initialization in initializeBackend. |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | // Add the "subschemaSubentry" attribute. |
| | | DN schemaDN = DirectoryServer.getSchemaDN(); |
| | | if (schemaDN != null) |
| | | { |
| | | Attribute subschemaSubentryAttr = |
| | | createAttribute(ATTR_SUBSCHEMA_SUBENTRY, ATTR_SUBSCHEMA_SUBENTRY_LC, |
| | | String.valueOf(schemaDN)); |
| | | ArrayList<Attribute> subschemaSubentryAttrs = new ArrayList<Attribute>(1); |
| | | subschemaSubentryAttrs.add(subschemaSubentryAttr); |
| | | if (showAllAttributes || |
| | | (! subschemaSubentryAttr.getAttributeType().isOperational())) |
| | | { |
| | | dseUserAttrs.put(subschemaSubentryAttr.getAttributeType(), |
| | | subschemaSubentryAttrs); |
| | | } |
| | | else |
| | | { |
| | | dseOperationalAttrs.put(subschemaSubentryAttr.getAttributeType(), |
| | | subschemaSubentryAttrs); |
| | | } |
| | | } |
| | | |
| | | |
| | | // Add all the standard "static" attributes. |
| | | for (Attribute a : staticDSEAttributes) |
| | | { |
| | |
| | | |
| | | |
| | | // Construct and return the entry. |
| | | return new Entry(rootDSEDN, dseObjectClasses, dseUserAttrs, |
| | | dseOperationalAttrs); |
| | | Entry e = new Entry(rootDSEDN, dseObjectClasses, dseUserAttrs, |
| | | dseOperationalAttrs); |
| | | e.processVirtualAttributes(); |
| | | return e; |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | // Construct and return the entry. |
| | | return new Entry(entryDN, schemaObjectClasses, userAttrs, operationalAttrs); |
| | | Entry e = new Entry(entryDN, schemaObjectClasses, userAttrs, |
| | | operationalAttrs); |
| | | e.processVirtualAttributes(); |
| | | return e; |
| | | } |
| | | |
| | | |
| | |
| | | //Try to decode the entry based on the version number. On later versions, |
| | | //a case could be written to upgrade entries if it is not the current |
| | | //version |
| | | Entry entry = null; |
| | | switch(entryVersion) |
| | | { |
| | | case JebFormat.FORMAT_VERSION : |
| | | try |
| | | { |
| | | return JebFormat.entryFromDatabase(entryBytes); |
| | | entry = JebFormat.entryFromDatabase(entryBytes); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | |
| | | String message = getMessage(msgID, id.toString()); |
| | | throw new JebException(msgID, message); |
| | | } |
| | | break; |
| | | |
| | | //case 0x00 : |
| | | // Call upgrade method? Call 0x00 decode method? |
| | | default : |
| | |
| | | String message = getMessage(msgID, id.toString(), entryVersion); |
| | | throw new JebException(msgID, message); |
| | | } |
| | | |
| | | if (entry != null) |
| | | { |
| | | entry.processVirtualAttributes(); |
| | | } |
| | | |
| | | return entry; |
| | | } |
| | | |
| | | /** |
| | |
| | | { |
| | | for (Attribute a : list) |
| | | { |
| | | if (a.isVirtual()) |
| | | { |
| | | continue; |
| | | } |
| | | userAttrElements.add(new LDAPAttribute(a).encode()); |
| | | } |
| | | } |
| | |
| | | { |
| | | for (Attribute a : list) |
| | | { |
| | | if (a.isVirtual()) |
| | | { |
| | | continue; |
| | | } |
| | | opAttrElements.add(new LDAPAttribute(a).encode()); |
| | | } |
| | | } |
| | |
| | | extends Backend |
| | | implements ConfigurableComponent |
| | | { |
| | | |
| | | |
| | | |
| | | /** |
| | | * The set of time units that will be used for expressing the task retention |
| | | * time. |
| | |
| | | { |
| | | super(); |
| | | |
| | | |
| | | |
| | | // Perform all initialization in initializeBackend. |
| | | } |
| | | |
| | |
| | | public void addEntry(Entry entry, AddOperation addOperation) |
| | | throws DirectoryException |
| | | { |
| | | Entry e = entry.duplicate(false); |
| | | |
| | | // Get the DN for the entry and then get its parent. |
| | | DN entryDN = entry.getDN(); |
| | | DN entryDN = e.getDN(); |
| | | DN parentDN = entryDN.getParentDNInSuffix(); |
| | | |
| | | if (parentDN == null) |
| | |
| | | // treat the provided entry like a scheduled task. |
| | | if (parentDN.equals(scheduledTaskParentDN)) |
| | | { |
| | | Task task = taskScheduler.entryToScheduledTask(entry, addOperation); |
| | | Task task = taskScheduler.entryToScheduledTask(e, addOperation); |
| | | taskScheduler.scheduleTask(task, true); |
| | | return; |
| | | } |
| | |
| | | // treat the provided entry like a recurring task. |
| | | if (parentDN.equals(recurringTaskParentDN)) |
| | | { |
| | | RecurringTask recurringTask = taskScheduler.entryToRecurringTask(entry); |
| | | RecurringTask recurringTask = taskScheduler.entryToRecurringTask(e); |
| | | taskScheduler.addRecurringTask(recurringTask, true); |
| | | return; |
| | | } |
| | |
| | | */ |
| | | public Entry getTaskRootEntry() |
| | | { |
| | | return taskRootEntry; |
| | | return taskRootEntry.duplicate(true); |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | public Entry getScheduledTaskParentEntry() |
| | | { |
| | | return scheduledTaskParentEntry; |
| | | return scheduledTaskParentEntry.duplicate(true); |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | public Entry getRecurringTaskParentEntry() |
| | | { |
| | | return recurringTaskParentEntry; |
| | | return recurringTaskParentEntry.duplicate(true); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | if (scheduledTaskEntryDN.equals(taskEntry.getDN())) |
| | | { |
| | | return taskEntry; |
| | | return taskEntry.duplicate(true); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | try |
| | | { |
| | | Entry e = t.getTaskEntry(); |
| | | Entry e = t.getTaskEntry().duplicate(true); |
| | | if (filter.matchesEntry(e)) |
| | | { |
| | | if (! searchOperation.returnEntry(e, null)) |
| | |
| | | |
| | | if (recurringTaskEntryDN.equals(recurringTaskEntry.getDN())) |
| | | { |
| | | return recurringTaskEntry; |
| | | return recurringTaskEntry.duplicate(true); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | try |
| | | { |
| | | Entry e = rt.getRecurringTaskEntry(); |
| | | Entry e = rt.getRecurringTaskEntry().duplicate(true); |
| | | if (filter.matchesEntry(e)) |
| | | { |
| | | if (! searchOperation.returnEntry(e, null)) |
| | |
| | | */ |
| | | public ConfigEntry duplicate() |
| | | { |
| | | return new ConfigEntry(entry.duplicate(), parent); |
| | | return new ConfigEntry(entry.duplicate(false), parent); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | if (postReadRequest != null) |
| | | { |
| | | Entry addedEntry = entry.duplicate(); |
| | | Entry addedEntry = entry.duplicate(true); |
| | | |
| | | if (! postReadRequest.allowsAttribute( |
| | | DirectoryServer.getObjectClassAttributeType())) |
| | |
| | | |
| | | if (preReadRequest != null) |
| | | { |
| | | Entry entryCopy = entry.duplicate(); |
| | | Entry entryCopy = entry.duplicate(true); |
| | | |
| | | if (! preReadRequest.allowsAttribute( |
| | | DirectoryServer.getObjectClassAttributeType())) |
| | |
| | | // between the mechanism name and the handler). |
| | | private ConcurrentHashMap<String,SASLMechanismHandler> saslMechanismHandlers; |
| | | |
| | | // The set of virtual attributes defined in the server (mapped between the |
| | | // lowercase names and the virtual attributes). |
| | | private ConcurrentHashMap<String,VirtualAttribute> virtualAttributes; |
| | | |
| | | // The connection handler configuration manager for the Directory Server. |
| | | private ConnectionHandlerConfigManager connectionHandlerConfigManager; |
| | | |
| | |
| | | private CopyOnWriteArrayList<SynchronizationProvider> |
| | | synchronizationProviders; |
| | | |
| | | // The set of virtual attributes defined in the server. |
| | | private CopyOnWriteArrayList<VirtualAttributeRule> virtualAttributes; |
| | | |
| | | // The set of backend initialization listeners registered with the Directory |
| | | // Server. |
| | | private CopyOnWriteArraySet<BackendInitializationListener> |
| | |
| | | // The trust manager provider configuration manager for the Directory Server. |
| | | private TrustManagerProviderConfigManager trustManagerProviderConfigManager; |
| | | |
| | | // The virtual attribute provider configuration manager for the Directory |
| | | // Server. |
| | | private VirtualAttributeConfigManager virtualAttributeConfigManager; |
| | | |
| | | // The work queue that will be used to service client requests. |
| | | private WorkQueue workQueue; |
| | | |
| | |
| | | directoryServer.supportedControls = new TreeSet<String>(); |
| | | directoryServer.supportedFeatures = new TreeSet<String>(); |
| | | directoryServer.virtualAttributes = |
| | | new ConcurrentHashMap<String,VirtualAttribute>(); |
| | | new CopyOnWriteArrayList<VirtualAttributeRule>(); |
| | | directoryServer.connectionHandlers = |
| | | new CopyOnWriteArrayList<ConnectionHandler>(); |
| | | directoryServer.identityMappers = |
| | |
| | | supportedControls.add(OID_MATCHED_VALUES); |
| | | supportedControls.add(OID_LDAP_SUBENTRIES); |
| | | supportedControls.add(OID_PASSWORD_POLICY_CONTROL); |
| | | supportedControls.add(OID_REAL_ATTRS_ONLY); |
| | | supportedControls.add(OID_VIRTUAL_ATTRS_ONLY); |
| | | } |
| | | |
| | | |
| | |
| | | private void initializeVirtualAttributes() |
| | | throws ConfigException, InitializationException |
| | | { |
| | | // NYI |
| | | virtualAttributeConfigManager = new VirtualAttributeConfigManager(); |
| | | virtualAttributeConfigManager.initializeVirtualAttributes(); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of virtual attribute rules registered with the Directory |
| | | * Server. |
| | | * |
| | | * @return The set of virtual attribute rules registered with the Directory |
| | | * Server. |
| | | */ |
| | | public static List<VirtualAttributeRule> getVirtualAttributes() |
| | | { |
| | | return directoryServer.virtualAttributes; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of virtual attribute rules registered with the Directory |
| | | * Server that are applicable to the provided entry. |
| | | * |
| | | * @param entry The entry for which to retrieve the applicable virtual |
| | | * attribute rules. |
| | | * |
| | | * @return The set of virtual attribute rules registered with the Directory |
| | | * Server that apply to the given entry. It may be an empty list if |
| | | * there are no applicable virtual attribute rules. |
| | | */ |
| | | public static List<VirtualAttributeRule> getVirtualAttributes(Entry entry) |
| | | { |
| | | LinkedList<VirtualAttributeRule> ruleList = |
| | | new LinkedList<VirtualAttributeRule>(); |
| | | |
| | | for (VirtualAttributeRule rule : directoryServer.virtualAttributes) |
| | | { |
| | | if (rule.appliesToEntry(entry)) |
| | | { |
| | | ruleList.add(rule); |
| | | } |
| | | } |
| | | |
| | | return ruleList; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Registers the provided virtual attribute rule with the Directory Server. |
| | | * |
| | | * @param rule The virtual attribute rule to be registered. |
| | | */ |
| | | public static void registerVirtualAttribute(VirtualAttributeRule rule) |
| | | { |
| | | synchronized (directoryServer.virtualAttributes) |
| | | { |
| | | directoryServer.virtualAttributes.add(rule); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Deregisters the provided virtual attribute rule with the Directory Server. |
| | | * |
| | | * @param rule The virutal attribute rule to be deregistered. |
| | | */ |
| | | public static void deregisterVirtualAttribute(VirtualAttributeRule rule) |
| | | { |
| | | synchronized (directoryServer.virtualAttributes) |
| | | { |
| | | directoryServer.virtualAttributes.remove(rule); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Replaces the specified virtual attribute rule in the set of virtual |
| | | * attributes registered with the Directory Server. If the old rule cannot |
| | | * be found in the list, then the set of registered virtual attributes is not |
| | | * updated. |
| | | * |
| | | * @param oldRule The existing rule that should be replaced with the new |
| | | * rule. |
| | | * @param newRule The new rule that should be used in place of the existing |
| | | * rule. |
| | | * |
| | | * @return {@code true} if the old rule was found and replaced with the new |
| | | * version, or {@code false} if it was not. |
| | | */ |
| | | public static boolean replaceVirtualAttribute(VirtualAttributeRule oldRule, |
| | | VirtualAttributeRule newRule) |
| | | { |
| | | synchronized (directoryServer.virtualAttributes) |
| | | { |
| | | int pos = directoryServer.virtualAttributes.indexOf(oldRule); |
| | | if (pos >= 0) |
| | | { |
| | | directoryServer.virtualAttributes.set(pos, newRule); |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a reference to the JMX MBean server that is associated with the |
| | | * Directory Server. |
| | | * |
| | |
| | | |
| | | // Duplicate the entry and set its new DN. Also, create an empty list |
| | | // to hold the attribute-level modifications. |
| | | newEntry = currentEntry.duplicate(); |
| | | newEntry = currentEntry.duplicate(false); |
| | | newEntry.setDN(newDN); |
| | | modifications = new ArrayList<Modification>(); |
| | | |
| | |
| | | |
| | | if (preReadRequest != null) |
| | | { |
| | | Entry entry = currentEntry.duplicate(); |
| | | Entry entry = currentEntry.duplicate(true); |
| | | |
| | | if (! preReadRequest.allowsAttribute( |
| | | DirectoryServer.getObjectClassAttributeType())) |
| | |
| | | |
| | | if (postReadRequest != null) |
| | | { |
| | | Entry entry = newEntry.duplicate(); |
| | | Entry entry = newEntry.duplicate(true); |
| | | |
| | | if (! postReadRequest.allowsAttribute( |
| | | DirectoryServer.getObjectClassAttributeType())) |
| | |
| | | |
| | | |
| | | // Create a duplicate of the entry and apply the changes to it. |
| | | modifiedEntry = currentEntry.duplicate(); |
| | | modifiedEntry = currentEntry.duplicate(false); |
| | | |
| | | if (! noOp) |
| | | { |
| | |
| | | |
| | | if (preReadRequest != null) |
| | | { |
| | | Entry entry = currentEntry.duplicate(); |
| | | Entry entry = currentEntry.duplicate(true); |
| | | |
| | | if (! preReadRequest.allowsAttribute( |
| | | DirectoryServer.getObjectClassAttributeType())) |
| | |
| | | |
| | | if (postReadRequest != null) |
| | | { |
| | | Entry entry = modifiedEntry.duplicate(); |
| | | Entry entry = modifiedEntry.duplicate(true); |
| | | |
| | | if (! postReadRequest.allowsAttribute( |
| | | DirectoryServer.getObjectClassAttributeType())) |
| | |
| | | PostOperationSearchOperation, PostResponseSearchOperation, |
| | | SearchEntrySearchOperation, SearchReferenceSearchOperation |
| | | { |
| | | |
| | | |
| | | |
| | | // Indicates whether a search result done response has been sent to the |
| | | // client. |
| | | private AtomicBoolean responseSent; |
| | |
| | | // entries. |
| | | private boolean includeUsableControl; |
| | | |
| | | // Indicates whether to only real attributes should be returned. |
| | | private boolean realAttributesOnly; |
| | | |
| | | // Indicates whether LDAP subentries should be returned. |
| | | private boolean returnLDAPSubentries; |
| | | |
| | | // Indicates whether to include attribute types only or both types and values. |
| | | private boolean typesOnly; |
| | | |
| | | // Indicates whether to only virtual attributes should be returned. |
| | | private boolean virtualAttributesOnly; |
| | | |
| | | // The raw, unprocessed base DN as included in the request from the client. |
| | | private ByteString rawBaseDN; |
| | | |
| | |
| | | persistentSearch = null; |
| | | returnLDAPSubentries = false; |
| | | matchedValuesControl = null; |
| | | realAttributesOnly = false; |
| | | virtualAttributesOnly = false; |
| | | } |
| | | |
| | | |
| | |
| | | Entry entryToReturn; |
| | | if ((attributes == null) || attributes.isEmpty()) |
| | | { |
| | | entryToReturn = entry.duplicateWithoutOperationalAttributes(typesOnly); |
| | | entryToReturn = entry.duplicateWithoutOperationalAttributes(typesOnly, |
| | | true); |
| | | } |
| | | else |
| | | { |
| | |
| | | } |
| | | |
| | | |
| | | if (realAttributesOnly) |
| | | { |
| | | entryToReturn.stripVirtualAttributes(); |
| | | } |
| | | else if (virtualAttributesOnly) |
| | | { |
| | | entryToReturn.stripRealAttributes(); |
| | | } |
| | | |
| | | |
| | | // If there is a matched values control, then further pare down the entry |
| | | // based on the filters that it contains. |
| | | if ((matchedValuesControl != null) && (! typesOnly)) |
| | |
| | | { |
| | | includeUsableControl = true; |
| | | } |
| | | else if (oid.equals(OID_REAL_ATTRS_ONLY)) |
| | | { |
| | | realAttributesOnly = true; |
| | | } |
| | | else if (oid.equals(OID_VIRTUAL_ATTRS_ONLY)) |
| | | { |
| | | virtualAttributesOnly = true; |
| | | } |
| | | |
| | | // NYI -- Add support for additional controls. |
| | | else if (c.isCritical()) |
| 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.core; |
| | | |
| | | |
| | | |
| | | import java.lang.reflect.Method; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | import org.opends.server.admin.ClassPropertyDefinition; |
| | | import org.opends.server.admin.server.ConfigurationAddListener; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.server.ConfigurationDeleteListener; |
| | | import org.opends.server.admin.std.meta.VirtualAttributeCfgDefn; |
| | | import org.opends.server.admin.std.server.VirtualAttributeCfg; |
| | | import org.opends.server.admin.std.server.RootCfg; |
| | | import org.opends.server.admin.server.ServerManagementContext; |
| | | import org.opends.server.api.VirtualAttributeProvider; |
| | | import org.opends.server.config.ConfigException; |
| | | import org.opends.server.types.ConfigChangeResult; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.ErrorLogCategory; |
| | | import org.opends.server.types.ErrorLogSeverity; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.SearchFilter; |
| | | import org.opends.server.types.VirtualAttributeRule; |
| | | |
| | | import static org.opends.server.loggers.Error.*; |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import static org.opends.server.messages.ConfigMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class defines a utility that will be used to manage the set of |
| | | * virtual attribute providers defined in the Directory Server. It will |
| | | * initialize the providers when the server starts, and then will manage any |
| | | * additions, removals, or modifications to any virtual attribute providers |
| | | * while the server is running. |
| | | */ |
| | | public class VirtualAttributeConfigManager |
| | | implements ConfigurationChangeListener<VirtualAttributeCfg>, |
| | | ConfigurationAddListener<VirtualAttributeCfg>, |
| | | ConfigurationDeleteListener<VirtualAttributeCfg> |
| | | { |
| | | // A mapping between the DNs of the config entries and the associated |
| | | // virtual attribute rules. |
| | | private ConcurrentHashMap<DN,VirtualAttributeRule> rules; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of this virtual attribute config manager. |
| | | */ |
| | | public VirtualAttributeConfigManager() |
| | | { |
| | | rules = new ConcurrentHashMap<DN,VirtualAttributeRule>(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Initializes all virtual attribute providers currently defined in the |
| | | * Directory Server configuration. This should only be called at Directory |
| | | * Server startup. |
| | | * |
| | | * @throws ConfigException If a configuration problem causes the virtual |
| | | * attribute provider initialization process to |
| | | * fail. |
| | | * |
| | | * @throws InitializationException If a problem occurs while initializing |
| | | * the virtual attribute providers that is |
| | | * not related to the server configuration. |
| | | */ |
| | | public void initializeVirtualAttributes() |
| | | throws ConfigException, InitializationException |
| | | { |
| | | // Get the root configuration object. |
| | | ServerManagementContext managementContext = |
| | | ServerManagementContext.getInstance(); |
| | | RootCfg rootConfiguration = |
| | | managementContext.getRootConfiguration(); |
| | | |
| | | |
| | | // Register as an add and delete listener with the root configuration so we |
| | | // can be notified if any virtual attribute provider entries are added or |
| | | // removed. |
| | | rootConfiguration.addVirtualAttributeAddListener(this); |
| | | rootConfiguration.addVirtualAttributeDeleteListener(this); |
| | | |
| | | |
| | | //Initialize the existing virtual attribute providers. |
| | | for (String providerName : rootConfiguration.listVirtualAttributes()) |
| | | { |
| | | VirtualAttributeCfg cfg = |
| | | rootConfiguration.getVirtualAttribute(providerName); |
| | | cfg.addChangeListener(this); |
| | | |
| | | if (cfg.isEnabled()) |
| | | { |
| | | String className = cfg.getProviderClass(); |
| | | try |
| | | { |
| | | VirtualAttributeProvider<? extends VirtualAttributeCfg> provider = |
| | | loadProvider(className, cfg); |
| | | |
| | | LinkedHashSet<SearchFilter> filters = |
| | | new LinkedHashSet<SearchFilter>(); |
| | | for (String filterString : cfg.getFilter()) |
| | | { |
| | | try |
| | | { |
| | | filters.add(SearchFilter.createFilterFromString(filterString)); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, de); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_VATTR_INVALID_SEARCH_FILTER; |
| | | String message = getMessage(msgID, filterString, |
| | | String.valueOf(cfg.dn()), |
| | | de.getErrorMessage()); |
| | | throw new ConfigException(msgID, message, de); |
| | | } |
| | | } |
| | | |
| | | if (cfg.getAttributeType().isSingleValue()) |
| | | { |
| | | if (provider.isMultiValued()) |
| | | { |
| | | int msgID = MSGID_CONFIG_VATTR_SV_TYPE_WITH_MV_PROVIDER; |
| | | String message = getMessage(msgID, String.valueOf(cfg.dn()), |
| | | cfg.getAttributeType().getNameOrOID(), |
| | | className); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | else if (cfg.getConflictBehavior() == |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | MERGE_REAL_AND_VIRTUAL) |
| | | { |
| | | int msgID = MSGID_CONFIG_VATTR_SV_TYPE_WITH_MERGE_VALUES; |
| | | String message = getMessage(msgID, String.valueOf(cfg.dn()), |
| | | cfg.getAttributeType().getNameOrOID()); |
| | | throw new ConfigException(msgID, message); |
| | | } |
| | | } |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(cfg.getAttributeType(), provider, |
| | | cfg.getBaseDN(), cfg.getGroupDN(), |
| | | filters, cfg.getConflictBehavior()); |
| | | rules.put(cfg.dn(), rule); |
| | | DirectoryServer.registerVirtualAttribute(rule); |
| | | } |
| | | catch (InitializationException ie) |
| | | { |
| | | logError(ErrorLogCategory.CONFIGURATION, |
| | | ErrorLogSeverity.SEVERE_ERROR, |
| | | ie.getMessage(), ie.getMessageID()); |
| | | continue; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationAddAcceptable( |
| | | VirtualAttributeCfg configuration, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | if (configuration.isEnabled()) |
| | | { |
| | | // Get the name of the class and make sure we can instantiate it as a |
| | | // virtual attribute provider. |
| | | String className = configuration.getProviderClass(); |
| | | try |
| | | { |
| | | loadProvider(className, null); |
| | | } |
| | | catch (InitializationException ie) |
| | | { |
| | | unacceptableReasons.add(ie.getMessage()); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // If there were any search filters provided, then make sure they are all |
| | | // valid. |
| | | for (String filterString : configuration.getFilter()) |
| | | { |
| | | try |
| | | { |
| | | SearchFilter.createFilterFromString(filterString); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, de); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_VATTR_INVALID_SEARCH_FILTER; |
| | | String message = getMessage(msgID, filterString, |
| | | String.valueOf(configuration.dn()), |
| | | de.getErrorMessage()); |
| | | unacceptableReasons.add(message); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // If we've gotten here, then it's fine. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationAdd( |
| | | VirtualAttributeCfg configuration) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | configuration.addChangeListener(this); |
| | | |
| | | if (! configuration.isEnabled()) |
| | | { |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | // Make sure that we can parse all of the search filters. |
| | | LinkedHashSet<SearchFilter> filters = |
| | | new LinkedHashSet<SearchFilter>(); |
| | | for (String filterString : configuration.getFilter()) |
| | | { |
| | | try |
| | | { |
| | | filters.add(SearchFilter.createFilterFromString(filterString)); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, de); |
| | | } |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX; |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_VATTR_INVALID_SEARCH_FILTER; |
| | | String message = getMessage(msgID, filterString, |
| | | String.valueOf(configuration.dn()), |
| | | de.getErrorMessage()); |
| | | messages.add(message); |
| | | } |
| | | } |
| | | |
| | | // Get the name of the class and make sure we can instantiate it as a |
| | | // certificate mapper. |
| | | VirtualAttributeProvider<? extends VirtualAttributeCfg> provider = null; |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | String className = configuration.getProviderClass(); |
| | | try |
| | | { |
| | | provider = loadProvider(className, configuration); |
| | | } |
| | | catch (InitializationException ie) |
| | | { |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | messages.add(ie.getMessage()); |
| | | } |
| | | } |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(configuration.getAttributeType(), provider, |
| | | configuration.getBaseDN(), |
| | | configuration.getGroupDN(), |
| | | filters, |
| | | configuration.getConflictBehavior()); |
| | | |
| | | rules.put(configuration.dn(), rule); |
| | | DirectoryServer.registerVirtualAttribute(rule); |
| | | } |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationDeleteAcceptable( |
| | | VirtualAttributeCfg configuration, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | // We will always allow getting rid of a virtual attribute rule. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationDelete( |
| | | VirtualAttributeCfg configuration) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | VirtualAttributeRule rule = rules.remove(configuration.dn()); |
| | | if (rule != null) |
| | | { |
| | | DirectoryServer.deregisterVirtualAttribute(rule); |
| | | rule.getProvider().finalizeVirtualAttributeProvider(); |
| | | } |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public boolean isConfigurationChangeAcceptable( |
| | | VirtualAttributeCfg configuration, |
| | | List<String> unacceptableReasons) |
| | | { |
| | | if (configuration.isEnabled()) |
| | | { |
| | | // Get the name of the class and make sure we can instantiate it as a |
| | | // virtual attribute provider. |
| | | String className = configuration.getProviderClass(); |
| | | try |
| | | { |
| | | loadProvider(className, null); |
| | | } |
| | | catch (InitializationException ie) |
| | | { |
| | | unacceptableReasons.add(ie.getMessage()); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // If there were any search filters provided, then make sure they are all |
| | | // valid. |
| | | for (String filterString : configuration.getFilter()) |
| | | { |
| | | try |
| | | { |
| | | SearchFilter.createFilterFromString(filterString); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, de); |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_VATTR_INVALID_SEARCH_FILTER; |
| | | String message = getMessage(msgID, filterString, |
| | | String.valueOf(configuration.dn()), |
| | | de.getErrorMessage()); |
| | | unacceptableReasons.add(message); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // If we've gotten here, then it's fine. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ConfigChangeResult applyConfigurationChange( |
| | | VirtualAttributeCfg configuration) |
| | | { |
| | | ResultCode resultCode = ResultCode.SUCCESS; |
| | | boolean adminActionRequired = false; |
| | | ArrayList<String> messages = new ArrayList<String>(); |
| | | |
| | | |
| | | // Get the existing rule if it's already enabled. |
| | | VirtualAttributeRule existingRule = rules.get(configuration.dn()); |
| | | |
| | | |
| | | // If the new configuration has the rule disabled, then disable it if it |
| | | // is enabled, or do nothing if it's already disabled. |
| | | if (! configuration.isEnabled()) |
| | | { |
| | | if (existingRule != null) |
| | | { |
| | | DirectoryServer.deregisterVirtualAttribute(existingRule); |
| | | existingRule.getProvider().finalizeVirtualAttributeProvider(); |
| | | } |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | // Make sure that we can parse all of the search filters. |
| | | LinkedHashSet<SearchFilter> filters = |
| | | new LinkedHashSet<SearchFilter>(); |
| | | for (String filterString : configuration.getFilter()) |
| | | { |
| | | try |
| | | { |
| | | filters.add(SearchFilter.createFilterFromString(filterString)); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, de); |
| | | } |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX; |
| | | } |
| | | |
| | | int msgID = MSGID_CONFIG_VATTR_INVALID_SEARCH_FILTER; |
| | | String message = getMessage(msgID, filterString, |
| | | String.valueOf(configuration.dn()), |
| | | de.getErrorMessage()); |
| | | messages.add(message); |
| | | } |
| | | } |
| | | |
| | | // Get the name of the class and make sure we can instantiate it as a |
| | | // certificate mapper. |
| | | VirtualAttributeProvider<? extends VirtualAttributeCfg> provider = null; |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | String className = configuration.getProviderClass(); |
| | | try |
| | | { |
| | | provider = loadProvider(className, configuration); |
| | | } |
| | | catch (InitializationException ie) |
| | | { |
| | | resultCode = DirectoryServer.getServerErrorResultCode(); |
| | | messages.add(ie.getMessage()); |
| | | } |
| | | } |
| | | |
| | | if (resultCode == ResultCode.SUCCESS) |
| | | { |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(configuration.getAttributeType(), provider, |
| | | configuration.getBaseDN(), |
| | | configuration.getGroupDN(), |
| | | filters, |
| | | configuration.getConflictBehavior()); |
| | | |
| | | rules.put(configuration.dn(), rule); |
| | | if (existingRule == null) |
| | | { |
| | | DirectoryServer.registerVirtualAttribute(rule); |
| | | } |
| | | else |
| | | { |
| | | DirectoryServer.replaceVirtualAttribute(existingRule, rule); |
| | | existingRule.getProvider().finalizeVirtualAttributeProvider(); |
| | | } |
| | | } |
| | | |
| | | return new ConfigChangeResult(resultCode, adminActionRequired, messages); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Loads the specified class, instantiates it as a certificate mapper, and |
| | | * optionally initializes that instance. |
| | | * |
| | | * @param className The fully-qualified name of the certificate mapper |
| | | * class to load, instantiate, and initialize. |
| | | * @param configuration The configuration to use to initialize the |
| | | * certificate mapper, or {@code null} if the |
| | | * certificate mapper should not be initialized. |
| | | * |
| | | * @return The possibly initialized certificate mapper. |
| | | * |
| | | * @throws InitializationException If a problem occurred while attempting to |
| | | * initialize the certificate mapper. |
| | | */ |
| | | private VirtualAttributeProvider<? extends VirtualAttributeCfg> |
| | | loadProvider(String className, VirtualAttributeCfg configuration) |
| | | throws InitializationException |
| | | { |
| | | try |
| | | { |
| | | VirtualAttributeCfgDefn definition = |
| | | VirtualAttributeCfgDefn.getInstance(); |
| | | ClassPropertyDefinition propertyDefinition = |
| | | definition.getProviderClassPropertyDefinition(); |
| | | Class<? extends VirtualAttributeProvider> providerClass = |
| | | propertyDefinition.loadClass(className, |
| | | VirtualAttributeProvider.class); |
| | | VirtualAttributeProvider<? extends VirtualAttributeCfg> provider = |
| | | (VirtualAttributeProvider<? extends VirtualAttributeCfg>) |
| | | providerClass.newInstance(); |
| | | |
| | | if (configuration != null) |
| | | { |
| | | Method method = |
| | | provider.getClass().getMethod("initializeVirtualAttributeProvider", |
| | | configuration.definition().getServerConfigurationClass()); |
| | | method.invoke(provider, configuration); |
| | | } |
| | | |
| | | return provider; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | int msgID = MSGID_CONFIG_VATTR_INITIALIZATION_FAILED; |
| | | String message = getMessage(msgID, className, |
| | | String.valueOf(configuration.dn()), |
| | | stackTraceToSingleLineString(e)); |
| | | throw new InitializationException(msgID, message, e); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | return null; |
| | | } |
| | | |
| | | return configEntry.getEntry(); |
| | | return configEntry.getEntry().duplicate(true); |
| | | } |
| | | |
| | | |
| | |
| | | public void addEntry(Entry entry, AddOperation addOperation) |
| | | throws DirectoryException |
| | | { |
| | | Entry e = entry.duplicate(false); |
| | | |
| | | // If there is an add operation, then make sure that the associated user has |
| | | // both the CONFIG_READ and CONFIG_WRITE privileges. |
| | | if (addOperation != null) |
| | |
| | | { |
| | | // Make sure that the target DN does not already exist. If it does, then |
| | | // fail. |
| | | DN entryDN = entry.getDN(); |
| | | DN entryDN = e.getDN(); |
| | | if (configEntries.containsKey(entryDN)) |
| | | { |
| | | int msgID = MSGID_CONFIG_FILE_ADD_ALREADY_EXISTS; |
| | |
| | | |
| | | |
| | | // Encapsulate the provided entry in a config entry. |
| | | ConfigEntry newEntry = new ConfigEntry(entry, parentEntry); |
| | | ConfigEntry newEntry = new ConfigEntry(e, parentEntry); |
| | | |
| | | |
| | | // See if the parent entry has any add listeners. If so, then iterate |
| | |
| | | public void replaceEntry(Entry entry, ModifyOperation modifyOperation) |
| | | throws DirectoryException |
| | | { |
| | | Entry e = entry.duplicate(false); |
| | | |
| | | // If there is a modify operation, then make sure that the associated user |
| | | // has both the CONFIG_READ and CONFIG_WRITE privileges. Also, if the |
| | | // operation targets the set of root privileges then make sure the user has |
| | |
| | | try |
| | | { |
| | | // Get the DN of the target entry for future reference. |
| | | DN entryDN = entry.getDN(); |
| | | DN entryDN = e.getDN(); |
| | | |
| | | |
| | | // Get the target entry. If it does not exist, then fail. |
| | |
| | | |
| | | |
| | | // Create a new config entry to use for the validation testing. |
| | | ConfigEntry newEntry = new ConfigEntry(entry, currentEntry.getParent()); |
| | | ConfigEntry newEntry = new ConfigEntry(e, currentEntry.getParent()); |
| | | |
| | | |
| | | // See if there are any config change listeners registered for this entry. |
| | |
| | | // We'll just overwrite the core entry in the current config entry so that |
| | | // we keep all the registered listeners, references to the parent and |
| | | // children, and other metadata. |
| | | currentEntry.setEntry(entry); |
| | | currentEntry.setEntry(e); |
| | | writeUpdatedConfig(); |
| | | |
| | | |
| | |
| | | case BASE_OBJECT: |
| | | // We are only interested in the base entry itself. See if it matches |
| | | // and if so then return the entry. |
| | | Entry e = baseEntry.getEntry(); |
| | | Entry e = baseEntry.getEntry().duplicate(true); |
| | | if (filter.matchesEntry(e)) |
| | | { |
| | | searchOperation.returnEntry(e, null); |
| | |
| | | // Iterate through them and return the ones that match the filter. |
| | | for (ConfigEntry child : baseEntry.getChildren().values()) |
| | | { |
| | | e = child.getEntry(); |
| | | e = child.getEntry().duplicate(true); |
| | | if (filter.matchesEntry(e)) |
| | | { |
| | | if (! searchOperation.returnEntry(e, null)) |
| | |
| | | SearchOperation searchOperation) |
| | | throws DirectoryException |
| | | { |
| | | Entry e = baseEntry.getEntry(); |
| | | Entry e = baseEntry.getEntry().duplicate(true); |
| | | if (filter.matchesEntry(e)) |
| | | { |
| | | if (! searchOperation.returnEntry(e, null)) |
| 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.extensions; |
| | | |
| | | |
| | | |
| | | import java.util.Collection; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | |
| | | import org.opends.server.admin.std.server.VirtualAttributeCfg; |
| | | 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.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ByteStringFactory; |
| | | import org.opends.server.types.ConditionResult; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.SearchFilter; |
| | | import org.opends.server.types.SearchScope; |
| | | import org.opends.server.types.VirtualAttributeRule; |
| | | |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class implements a virtual attribute provider that is meant to serve the |
| | | * entryDN operational attribute as described in draft-zeilenga-ldap-entrydn. |
| | | */ |
| | | public class EntryDNVirtualAttributeProvider |
| | | extends VirtualAttributeProvider<VirtualAttributeCfg> |
| | | { |
| | | /** |
| | | * Creates a new instance of this entryDN virtual attribute provider. |
| | | */ |
| | | public EntryDNVirtualAttributeProvider() |
| | | { |
| | | super(); |
| | | |
| | | // All initialization should be performed in the |
| | | // initializeVirtualAttributeProvider method. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializeVirtualAttributeProvider( |
| | | VirtualAttributeCfg configuration) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | // No initialization is required. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean isMultiValued() |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public LinkedHashSet<AttributeValue> getValues(Entry entry, |
| | | VirtualAttributeRule rule) |
| | | { |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(1); |
| | | |
| | | String normDNString = entry.getDN().toNormalizedString(); |
| | | values.add(new AttributeValue(ByteStringFactory.create(normDNString), |
| | | ByteStringFactory.create(normDNString))); |
| | | |
| | | return values; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean hasValue(Entry entry, VirtualAttributeRule rule) |
| | | { |
| | | // This virtual attribute provider will always generate a value. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean hasValue(Entry entry, VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | try |
| | | { |
| | | String normalizedDN = entry.getDN().toNormalizedString(); |
| | | String normalizedValue = value.getNormalizedStringValue(); |
| | | return normalizedDN.equals(normalizedValue); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean hasAnyValue(Entry entry, VirtualAttributeRule rule, |
| | | Collection<AttributeValue> values) |
| | | { |
| | | String ndnString = entry.getDN().toNormalizedString(); |
| | | |
| | | AttributeValue v = new AttributeValue(ByteStringFactory.create(ndnString), |
| | | ByteStringFactory.create(ndnString)); |
| | | return values.contains(v); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult matchesSubstring(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | ByteString subInitial, |
| | | List<ByteString> subAny, |
| | | ByteString subFinal) |
| | | { |
| | | // DNs cannot be used in substring matching. |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult greaterThanOrEqualTo(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | // DNs cannot be used in ordering matching. |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult lessThanOrEqualTo(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | // DNs cannot be used in ordering matching. |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult approximatelyEqualTo(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | // DNs 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) |
| | | { |
| | | return isSearchable(rule.getAttributeType(), searchOperation.getFilter(), |
| | | 0); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided search filter is one that may be used with |
| | | * this virtual attribute provider, optionally operating in a recursive manner |
| | | * to make the determination. |
| | | * |
| | | * @param attributeType The attribute type used to hold the entryDN value. |
| | | * @param searchFilter The search filter for which to make the |
| | | * determination. |
| | | * @param depth The current recursion depth for this processing. |
| | | * |
| | | * @return {@code true} if the provided filter may be used with this virtual |
| | | * attribute provider, or {@code false} if not. |
| | | */ |
| | | private boolean isSearchable(AttributeType attributeType, SearchFilter filter, |
| | | int depth) |
| | | { |
| | | switch (filter.getFilterType()) |
| | | { |
| | | case AND: |
| | | if (depth >= MAX_NESTED_FILTER_DEPTH) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | for (SearchFilter f : filter.getFilterComponents()) |
| | | { |
| | | if (isSearchable(attributeType, f, depth+1)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | |
| | | case OR: |
| | | if (depth >= MAX_NESTED_FILTER_DEPTH) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | for (SearchFilter f : filter.getFilterComponents()) |
| | | { |
| | | if (! isSearchable(attributeType, f, depth+1)) |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | return true; |
| | | |
| | | case EQUALITY: |
| | | return filter.getAttributeType().equals(attributeType); |
| | | |
| | | default: |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void processSearch(VirtualAttributeRule rule, |
| | | SearchOperation searchOperation) |
| | | { |
| | | SearchFilter filter = searchOperation.getFilter(); |
| | | LinkedHashSet<DN> dnSet = new LinkedHashSet<DN>(); |
| | | extractDNs(rule.getAttributeType(), filter, dnSet); |
| | | |
| | | if (dnSet.isEmpty()) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | DN baseDN = searchOperation.getBaseDN(); |
| | | SearchScope scope = searchOperation.getScope(); |
| | | for (DN dn : dnSet) |
| | | { |
| | | if (! dn.matchesBaseAndScope(baseDN, scope)) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | try |
| | | { |
| | | Entry entry = DirectoryServer.getEntry(dn); |
| | | if ((entry != null) && filter.matchesEntry(entry)) |
| | | { |
| | | searchOperation.returnEntry(entry, null); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Extracts the user DNs from the provided filter, operating recursively as |
| | | * necessary, and adds them to the provided set. |
| | | * |
| | | * @param attributeType The attribute type holding the entryDN value. |
| | | * @param filter The search filter to be processed. |
| | | * @param dnSet The set into which the identified DNs should be |
| | | * placed. |
| | | */ |
| | | private void extractDNs(AttributeType attributeType, SearchFilter filter, |
| | | LinkedHashSet<DN> dnSet) |
| | | { |
| | | switch (filter.getFilterType()) |
| | | { |
| | | case AND: |
| | | case OR: |
| | | for (SearchFilter f : filter.getFilterComponents()) |
| | | { |
| | | extractDNs(attributeType, f, dnSet); |
| | | } |
| | | break; |
| | | |
| | | case EQUALITY: |
| | | if (filter.getAttributeType().equals(attributeType)) |
| | | { |
| | | try |
| | | { |
| | | dnSet.add(DN.decode(filter.getAssertionValue().getValue())); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| 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.extensions; |
| | | |
| | | |
| | | |
| | | import java.util.Collection; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | |
| | | import org.opends.server.admin.std.server.VirtualAttributeCfg; |
| | | import org.opends.server.api.Group; |
| | | 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.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ConditionResult; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.MemberList; |
| | | import org.opends.server.types.SearchFilter; |
| | | import org.opends.server.types.SearchScope; |
| | | import org.opends.server.types.VirtualAttributeRule; |
| | | |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class implements a virtual attribute provider that is meant to serve the |
| | | * isMemberOf operational attribute. This attribute will be used to provide a |
| | | * list of all groups in which the specified user is a member. |
| | | */ |
| | | public class IsMemberOfVirtualAttributeProvider |
| | | extends VirtualAttributeProvider<VirtualAttributeCfg> |
| | | { |
| | | /** |
| | | * Creates a new instance of this entryDN virtual attribute provider. |
| | | */ |
| | | public IsMemberOfVirtualAttributeProvider() |
| | | { |
| | | super(); |
| | | |
| | | // All initialization should be performed in the |
| | | // initializeVirtualAttributeProvider method. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializeVirtualAttributeProvider( |
| | | VirtualAttributeCfg configuration) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | // No initialization is required. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean isMultiValued() |
| | | { |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public LinkedHashSet<AttributeValue> getValues(Entry entry, |
| | | VirtualAttributeRule rule) |
| | | { |
| | | // FIXME -- This probably isn't the most efficient implementation. |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(); |
| | | for (Group g : DirectoryServer.getGroupManager().getGroupInstances()) |
| | | { |
| | | try |
| | | { |
| | | if (g.isMember(entry)) |
| | | { |
| | | values.add(new AttributeValue(rule.getAttributeType(), |
| | | g.getGroupDN().toString())); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return values; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean hasValue(Entry entry, VirtualAttributeRule rule) |
| | | { |
| | | // FIXME -- This probably isn't the most efficient implementation. |
| | | for (Group g : DirectoryServer.getGroupManager().getGroupInstances()) |
| | | { |
| | | try |
| | | { |
| | | if (g.isMember(entry)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean hasValue(Entry entry, VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | try |
| | | { |
| | | DN groupDN = DN.decode(value.getValue()); |
| | | Group g = DirectoryServer.getGroupManager().getGroupInstance(groupDN); |
| | | if (g == null) |
| | | { |
| | | return false; |
| | | } |
| | | else |
| | | { |
| | | return g.isMember(entry); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean hasAnyValue(Entry entry, VirtualAttributeRule rule, |
| | | Collection<AttributeValue> values) |
| | | { |
| | | for (AttributeValue value : values) |
| | | { |
| | | if (hasValue(entry, rule, value)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult matchesSubstring(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | ByteString subInitial, |
| | | List<ByteString> subAny, |
| | | ByteString subFinal) |
| | | { |
| | | // DNs cannot be used in substring matching. |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult greaterThanOrEqualTo(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | // DNs cannot be used in ordering matching. |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult lessThanOrEqualTo(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | // DNs cannot be used in ordering matching. |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult approximatelyEqualTo(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | // DNs 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> |
| | | * </UL> |
| | | */ |
| | | @Override() |
| | | public boolean isSearchable(VirtualAttributeRule rule, |
| | | SearchOperation searchOperation) |
| | | { |
| | | return isSearchable(rule.getAttributeType(), searchOperation.getFilter(), |
| | | 0); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether the provided search filter is one that may be used with |
| | | * this virtual attribute provider, optionally operating in a recursive manner |
| | | * to make the determination. |
| | | * |
| | | * @param attributeType The attribute type used to hold the entryDN value. |
| | | * @param searchFilter The search filter for which to make the |
| | | * determination. |
| | | * @param depth The current recursion depth for this processing. |
| | | * |
| | | * @return {@code true} if the provided filter may be used with this virtual |
| | | * attribute provider, or {@code false} if not. |
| | | */ |
| | | private boolean isSearchable(AttributeType attributeType, SearchFilter filter, |
| | | int depth) |
| | | { |
| | | switch (filter.getFilterType()) |
| | | { |
| | | case AND: |
| | | if (depth >= MAX_NESTED_FILTER_DEPTH) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | for (SearchFilter f : filter.getFilterComponents()) |
| | | { |
| | | if (isSearchable(attributeType, f, depth+1)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | |
| | | case EQUALITY: |
| | | return filter.getAttributeType().equals(attributeType); |
| | | |
| | | default: |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void processSearch(VirtualAttributeRule rule, |
| | | SearchOperation searchOperation) |
| | | { |
| | | SearchFilter filter = searchOperation.getFilter(); |
| | | Group group = extractGroup(rule.getAttributeType(), filter); |
| | | if (group == null) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | DN baseDN = searchOperation.getBaseDN(); |
| | | SearchScope scope = searchOperation.getScope(); |
| | | try |
| | | { |
| | | MemberList memberList = group.getMembers(); |
| | | while (memberList.hasMoreMembers()) |
| | | { |
| | | try |
| | | { |
| | | Entry e = memberList.nextMemberEntry(); |
| | | if (e.matchesBaseAndScope(baseDN, scope) && |
| | | filter.matchesEntry(e)) |
| | | { |
| | | searchOperation.returnEntry(e, null); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | | searchOperation.setResponseData(de); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Extracts the first group DN encountered in the provided filter, operating |
| | | * recursively as necessary. |
| | | * |
| | | * @param attributeType The attribute type holding the entryDN value. |
| | | * @param filter The search filter to be processed. |
| | | * |
| | | * @return The first group encountered in the provided filter, or |
| | | * {@code null} if there is no match. |
| | | */ |
| | | private Group extractGroup(AttributeType attributeType, SearchFilter filter) |
| | | { |
| | | switch (filter.getFilterType()) |
| | | { |
| | | case AND: |
| | | for (SearchFilter f : filter.getFilterComponents()) |
| | | { |
| | | Group g = extractGroup(attributeType, f); |
| | | if (g != null) |
| | | { |
| | | return g; |
| | | } |
| | | } |
| | | break; |
| | | |
| | | case EQUALITY: |
| | | if (filter.getAttributeType().equals(attributeType)) |
| | | { |
| | | try |
| | | { |
| | | DN dn = DN.decode(filter.getAssertionValue().getValue()); |
| | | return DirectoryServer.getGroupManager().getGroupInstance(dn); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | } |
| | | break; |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | } |
| | | |
| 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 2006-2007 Sun Microsystems, Inc. |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | |
| | | |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | |
| | | import org.opends.server.admin.std.server.VirtualAttributeCfg; |
| | | 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.AttributeValue; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ConditionResult; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.InitializationException; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.VirtualAttributeRule; |
| | | |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import static org.opends.server.messages.ExtensionsMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class implements a virtual attribute provider that is meant to serve the |
| | | * subschemaSubentry operational attribute as described in RFC 4512. |
| | | */ |
| | | public class SubschemaSubentryVirtualAttributeProvider |
| | | extends VirtualAttributeProvider<VirtualAttributeCfg> |
| | | { |
| | | /** |
| | | * Creates a new instance of this subschemaSubentry virtual attribute |
| | | * provider. |
| | | */ |
| | | public SubschemaSubentryVirtualAttributeProvider() |
| | | { |
| | | super(); |
| | | |
| | | // All initialization should be performed in the |
| | | // initializeVirtualAttributeProvider method. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void initializeVirtualAttributeProvider( |
| | | VirtualAttributeCfg configuration) |
| | | throws ConfigException, InitializationException |
| | | { |
| | | // No initialization is required. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean isMultiValued() |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public LinkedHashSet<AttributeValue> getValues(Entry entry, |
| | | VirtualAttributeRule rule) |
| | | { |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(1); |
| | | |
| | | values.add(new AttributeValue(rule.getAttributeType(), |
| | | DirectoryServer.getSchemaDN().toString())); |
| | | |
| | | return values; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult matchesSubstring(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | ByteString subInitial, |
| | | List<ByteString> subAny, |
| | | ByteString subFinal) |
| | | { |
| | | // DNs cannot be used in substring matching. |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult greaterThanOrEqualTo(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | // DNs cannot be used in ordering matching. |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult lessThanOrEqualTo(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | // DNs cannot be used in ordering matching. |
| | | return ConditionResult.UNDEFINED; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult approximatelyEqualTo(Entry entry, |
| | | VirtualAttributeRule rule, |
| | | AttributeValue value) |
| | | { |
| | | // DNs 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) |
| | | { |
| | | // 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); |
| | | |
| | | int msgID = MSGID_SUBSCHEMASUBENTRY_VATTR_NOT_SEARCHABLE; |
| | | String message = getMessage(msgID, rule.getAttributeType().getNameOrOID()); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.RDN; |
| | | |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import org.opends.server.types.DebugLogLevel; |
| | | import org.opends.server.types.RDN; |
| | | import org.opends.server.types.SearchScope; |
| | | |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | |
| | | public class LazyDN |
| | | extends DN |
| | | { |
| | | |
| | | |
| | | |
| | | /** |
| | | * The serial version identifier required to satisfy the compiler because this |
| | | * class implements the {@code java.io.Serializable} interface. This value |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean matchesBaseAndScope(DN baseDN, SearchScope scope) |
| | | throws RuntimeException |
| | | { |
| | | return getDecodedDN().matchesBaseAndScope(baseDN, scope); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean equals(Object o) |
| | | throws RuntimeException |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if a virtual attribute |
| | | * definition has an invalid search filter. This takes three arguments, which |
| | | * are the filter string, the configuration entry DN, and a message explaining |
| | | * the problem that occurred. |
| | | */ |
| | | public static final int MSGID_CONFIG_VATTR_INVALID_SEARCH_FILTER = |
| | | CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 649; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if an error occurs while |
| | | * trying to load and/or initialize a class as a virtual attribute provider. |
| | | * This takes three arguments, which are the class name, the configuration |
| | | * entry DN, and string representation of the exception that was caught. |
| | | */ |
| | | public static final int MSGID_CONFIG_VATTR_INITIALIZATION_FAILED = |
| | | CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 650; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the configured |
| | | * attribute type is single-valued, but the virtual attribute provider may |
| | | * generate multiple values. This takes three arguments, which are the DN of |
| | | * the configuration entry, the name or OID of the attribute type, and the |
| | | * name of the virtual attribute provider class. |
| | | */ |
| | | public static final int MSGID_CONFIG_VATTR_SV_TYPE_WITH_MV_PROVIDER = |
| | | CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 651; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if the configured |
| | | * attribute type is single-valued, but the conflict behavior is to merge the |
| | | * real and virtual values. This takes two arguments, which are the DN of |
| | | * the configuration entry and the name or OID of the attribute type. |
| | | */ |
| | | public static final int MSGID_CONFIG_VATTR_SV_TYPE_WITH_MERGE_VALUES = |
| | | CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 652; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Associates a set of generic messages with the message IDs defined in this |
| | | * class. |
| | | */ |
| | |
| | | registerMessage(MSGID_CONFIG_CHANGE_RESULT_MESSAGES, |
| | | "%s.%s succeeded but generated the following messages " + |
| | | "for entry %s: %s."); |
| | | |
| | | |
| | | registerMessage(MSGID_CONFIG_VATTR_INVALID_SEARCH_FILTER, |
| | | "Unable to parse value \"%s\" from config entry \"%s\" " + |
| | | "as a valid search filter: %s."); |
| | | registerMessage(MSGID_CONFIG_VATTR_SV_TYPE_WITH_MV_PROVIDER, |
| | | "The virtual attribute configuration in entry \"%s\" is " + |
| | | "not valid because attribute type %s is single-valued " + |
| | | "but provider %s may generate multiple values."); |
| | | registerMessage(MSGID_CONFIG_VATTR_SV_TYPE_WITH_MERGE_VALUES, |
| | | "The virtual attribute configuration in entry \"%s\" is " + |
| | | "not valid because attribute type %s is single-valued " + |
| | | "but the conflict behavior is configured to merge real " + |
| | | "and virtual values."); |
| | | registerMessage(MSGID_CONFIG_VATTR_INITIALIZATION_FAILED, |
| | | "An error occurred while trying to load an instance " + |
| | | "of class %s referenced in configuration entry %s as a " + |
| | | "virtual attribute provider: %s."); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * The message ID for the message that will be used if a search operation has |
| | | * a filter targeting the subschemaSubentry virtual attribute, which is not |
| | | * searchable. This takes a single argument, which is the name of the |
| | | * subschemaSubentry attribute type. |
| | | */ |
| | | public static final int MSGID_SUBSCHEMASUBENTRY_VATTR_NOT_SEARCHABLE = |
| | | CATEGORY_MASK_EXTENSIONS | SEVERITY_MASK_MILD_ERROR | 459; |
| | | |
| | | |
| | | /** |
| | | * Associates a set of generic messages with the message IDs defined in this |
| | | * class. |
| | | */ |
| | |
| | | "The provided password does not contain enough unique " + |
| | | "characters. The minimum number of unique characters " + |
| | | "that may appear in a user password is %d."); |
| | | |
| | | |
| | | registerMessage(MSGID_SUBSCHEMASUBENTRY_VATTR_NOT_SEARCHABLE, |
| | | "The %s attribute is not searchable and should not be " + |
| | | "included in otherwise unindexed search filters."); |
| | | } |
| | | } |
| | | |
| | |
| | | public class InternalClientConnection |
| | | extends ClientConnection |
| | | { |
| | | |
| | | |
| | | // The message ID counter to use for internal connections. |
| | | private static AtomicInteger nextMessageID; |
| | | |
| | |
| | | this.authenticationInfo = |
| | | new AuthenticationInfo(internalUserEntry, true); |
| | | super.setAuthenticationInfo(authenticationInfo); |
| | | setSizeLimit(0); |
| | | setTimeLimit(0); |
| | | setLookthroughLimit(0); |
| | | super.setSizeLimit(0); |
| | | super.setTimeLimit(0); |
| | | super.setLookthroughLimit(0); |
| | | } |
| | | catch (DirectoryException de) |
| | | { |
| | |
| | | |
| | | this.authenticationInfo = authInfo; |
| | | super.setAuthenticationInfo(authInfo); |
| | | setSizeLimit(0); |
| | | setTimeLimit(0); |
| | | setLookthroughLimit(0); |
| | | super.setSizeLimit(0); |
| | | super.setTimeLimit(0); |
| | | super.setLookthroughLimit(0); |
| | | |
| | | connectionID = nextConnectionID.getAndDecrement(); |
| | | operationList = new LinkedList<Operation>(); |
| | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void setSizeLimit(int sizeLimit) |
| | | { |
| | | // No implementation required. We never want to set a nonzero |
| | | // size limit for internal client connections. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void setLookthroughLimit(int lookthroughLimit) |
| | | { |
| | | // No implementation required. We never want to set a nonzero |
| | | // lookthrough limit for internal client connections. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void setTimeLimit(int timeLimit) |
| | | { |
| | | // No implementation required. We never want to set a nonzero |
| | | // time limit for internal client connections. |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this client connection is currently using a |
| | | * secure mechanism to communicate with the server. Note that this |
| | | * may change over time based on operations performed by the client |
| | |
| | | { |
| | | controlOID = OID_SUBTREE_DELETE_CONTROL; |
| | | } |
| | | else if (lowerOID.equals("realattrsonly") || |
| | | lowerOID.equals("realattributesonly")) |
| | | { |
| | | controlOID = OID_REAL_ATTRS_ONLY; |
| | | } |
| | | else if (lowerOID.equals("virtualattrsonly") || |
| | | lowerOID.equals("virtualattributesonly")) |
| | | { |
| | | controlOID = OID_VIRTUAL_ATTRS_ONLY; |
| | | } |
| | | |
| | | if (idx < 0) |
| | | { |
| | |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.util.Base64; |
| | | |
| | | import static |
| | | org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static |
| | | org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | |
| | | */ |
| | | public class Attribute |
| | | { |
| | | |
| | | |
| | | |
| | | // The attribute type for this attribute. |
| | | private final AttributeType attributeType; |
| | | |
| | |
| | | */ |
| | | public boolean hasValue() |
| | | { |
| | | return (! values.isEmpty()); |
| | | return (! getValues().isEmpty()); |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | public boolean hasValue(AttributeValue value) |
| | | { |
| | | return values.contains(value); |
| | | return getValues().contains(value); |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | for (AttributeValue value : values) |
| | | { |
| | | if (! this.values.contains(value)) |
| | | if (! getValues().contains(value)) |
| | | { |
| | | return false; |
| | | } |
| | |
| | | { |
| | | for (AttributeValue value : values) |
| | | { |
| | | if (this.values.contains(value)) |
| | | if (getValues().contains(value)) |
| | | { |
| | | return true; |
| | | } |
| | |
| | | |
| | | |
| | | ConditionResult result = ConditionResult.FALSE; |
| | | for (AttributeValue value : values) |
| | | for (AttributeValue value : getValues()) |
| | | { |
| | | try |
| | | { |
| | |
| | | } |
| | | |
| | | ConditionResult result = ConditionResult.FALSE; |
| | | for (AttributeValue v : values) |
| | | for (AttributeValue v : getValues()) |
| | | { |
| | | try |
| | | { |
| | |
| | | } |
| | | |
| | | ConditionResult result = ConditionResult.FALSE; |
| | | for (AttributeValue v : values) |
| | | for (AttributeValue v : getValues()) |
| | | { |
| | | try |
| | | { |
| | |
| | | } |
| | | |
| | | ConditionResult result = ConditionResult.FALSE; |
| | | for (AttributeValue v : values) |
| | | for (AttributeValue v : getValues()) |
| | | { |
| | | try |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this is a virtual attribute rather than a real |
| | | * attribute. |
| | | * |
| | | * @return {@code true} if this is a virtual attribute, or |
| | | * {@code false} if it is a real attribute. |
| | | */ |
| | | public boolean isVirtual() |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a duplicate of this attribute that can be modified |
| | | * without impacting this attribute. |
| | | * |
| | |
| | | else |
| | | { |
| | | LinkedHashSet<AttributeValue> valuesCopy = |
| | | new LinkedHashSet<AttributeValue>(values.size()); |
| | | for (AttributeValue v : values) |
| | | { |
| | | valuesCopy.add(v); |
| | | } |
| | | new LinkedHashSet<AttributeValue>(getValues()); |
| | | |
| | | return new Attribute(attributeType, name, optionsCopy, |
| | | valuesCopy); |
| | |
| | | return false; |
| | | } |
| | | |
| | | if (values.size() != a.values.size()) |
| | | if (getValues().size() != a.getValues().size()) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | if (! hasAllValues(a.values)) |
| | | if (! hasAllValues(a.getValues())) |
| | | { |
| | | return false; |
| | | } |
| | |
| | | public int hashCode() |
| | | { |
| | | int hashCode = attributeType.hashCode(); |
| | | for (AttributeValue value : values) |
| | | for (AttributeValue value : getValues()) |
| | | { |
| | | hashCode += value.hashCode(); |
| | | } |
| | |
| | | buffer.append(", {"); |
| | | |
| | | boolean firstValue = true; |
| | | for (AttributeValue value : values) |
| | | for (AttributeValue value : getValues()) |
| | | { |
| | | if (! firstValue) |
| | | { |
| | |
| | | */ |
| | | public void toLDIF(StringBuilder buffer) |
| | | { |
| | | for (AttributeValue value : values) |
| | | for (AttributeValue value : getValues()) |
| | | { |
| | | buffer.append(name); |
| | | |
| | |
| | | |
| | | |
| | | /******************** |
| | | * NOTE: Any changes to the set of public methods defined in this |
| | | * class or the arguments that they contain must also be made |
| | | * in the org.opends.server.interop.LazyDN package to ensure |
| | | * continued interoperability with third-party applications |
| | | * that rely on that functionality. |
| | | * NOTE: Any changes to the set of non-static public methods defined |
| | | * in this class or the arguments that they contain must also |
| | | * be made in the org.opends.server.interop.LazyDN package to |
| | | * ensure continued interoperability with third-party |
| | | * applications that rely on that functionality. |
| | | ********************/ |
| | | |
| | | |
| | |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | |
| | | import static org.opends.server.config.ConfigConstants.*; |
| | | import static |
| | | org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static |
| | | org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | | import static org.opends.server.messages.SchemaMessages.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | |
| | | public class DN |
| | | implements Comparable<DN>, Serializable |
| | | { |
| | | |
| | | |
| | | |
| | | /** |
| | | * A singleton instance of the null DN (a DN with no components). |
| | | */ |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this entry falls within the range of the |
| | | * provided search base DN and scope. |
| | | * |
| | | * @param baseDN The base DN for which to make the determination. |
| | | * @param scope The search scope for which to make the |
| | | * determination. |
| | | * |
| | | * @return <CODE>true</CODE> if this entry is within the given |
| | | * base and scope, or <CODE>false</CODE> if it is not. |
| | | */ |
| | | public boolean matchesBaseAndScope(DN baseDN, SearchScope scope) |
| | | { |
| | | switch (scope) |
| | | { |
| | | case BASE_OBJECT: |
| | | // The base DN must equal this DN. |
| | | return equals(baseDN); |
| | | |
| | | case SINGLE_LEVEL: |
| | | // The parent DN must equal the base DN. |
| | | return baseDN.equals(getParent()); |
| | | |
| | | case WHOLE_SUBTREE: |
| | | // This DN must be a descendant of the provided base DN. |
| | | return isDescendantOf(baseDN); |
| | | |
| | | case SUBORDINATE_SUBTREE: |
| | | // This DN must be a descendant of the provided base DN, but |
| | | // not equal to it. |
| | | return ((! equals(baseDN)) && isDescendantOf(baseDN)); |
| | | |
| | | default: |
| | | // This is a scope that we don't recognize. |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Decodes the provided ASN.1 octet string as a DN. |
| | | * |
| | | * @param dnString The ASN.1 octet string to decode as a DN. |
| | |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.util.LDIFException; |
| | | |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugCaught; |
| | | import static |
| | | org.opends.server.loggers.debug.DebugLogger.debugEnabled; |
| | | import static |
| | | org.opends.server.loggers.debug.DebugLogger.debugVerbose; |
| | | import static org.opends.server.loggers.debug.DebugLogger.debugInfo; |
| | | import static |
| | | org.opends.server.loggers.debug.DebugLogger.debugWarning; |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import static org.opends.server.loggers.Error.*; |
| | | import static org.opends.server.messages.CoreMessages.*; |
| | | import static org.opends.server.messages.MessageHandler.*; |
| | |
| | | public class Entry |
| | | implements ProtocolElement |
| | | { |
| | | |
| | | |
| | | // Indicates whether virtual attribute processing has been performed |
| | | // for this entry. |
| | | private boolean virtualAttributeProcessingPerformed; |
| | | |
| | | // The set of operational attributes for this entry. |
| | | private Map<AttributeType,List<Attribute>> operationalAttributes; |
| | |
| | | // The set of user attributes for this entry. |
| | | private Map<AttributeType,List<Attribute>> userAttributes; |
| | | |
| | | // The set of suppressed real attributes for this entry. |
| | | private Map<AttributeType,List<Attribute>> suppressedAttributes; |
| | | |
| | | // The set of objectclasses for this entry. |
| | | private Map<ObjectClass,String> objectClasses; |
| | | |
| | |
| | | Map<AttributeType,List<Attribute>> |
| | | operationalAttributes) |
| | | { |
| | | attachment = null; |
| | | schema = DirectoryServer.getSchema(); |
| | | attachment = null; |
| | | schema = DirectoryServer.getSchema(); |
| | | virtualAttributeProcessingPerformed = false; |
| | | |
| | | |
| | | suppressedAttributes = |
| | | new LinkedHashMap<AttributeType,List<Attribute>>(); |
| | | |
| | | |
| | | if (dn == null) |
| | |
| | | * Creates a duplicate of this entry that may be altered without |
| | | * impacting the information in this entry. |
| | | * |
| | | * @param processVirtual Indicates whether virtual attribute |
| | | * processing should be performed for the |
| | | * entry. |
| | | * |
| | | * @return A duplicate of this entry that may be altered without |
| | | * impacting the information in this entry. |
| | | */ |
| | | public Entry duplicate() |
| | | public Entry duplicate(boolean processVirtual) |
| | | { |
| | | HashMap<ObjectClass,String> objectClassesCopy = |
| | | new HashMap<ObjectClass,String>(objectClasses); |
| | |
| | | operationalAttributes.size()); |
| | | deepCopy(operationalAttributes, operationalAttrsCopy, false); |
| | | |
| | | return new Entry(dn, objectClassesCopy, userAttrsCopy, |
| | | operationalAttrsCopy); |
| | | for (AttributeType t : suppressedAttributes.keySet()) |
| | | { |
| | | List<Attribute> attrList = suppressedAttributes.get(t); |
| | | if (t.isOperational()) |
| | | { |
| | | operationalAttributes.put(t, attrList); |
| | | } |
| | | else |
| | | { |
| | | userAttributes.put(t, attrList); |
| | | } |
| | | } |
| | | |
| | | Entry e = new Entry(dn, objectClassesCopy, userAttrsCopy, |
| | | operationalAttrsCopy); |
| | | if (processVirtual) |
| | | { |
| | | e.processVirtualAttributes(); |
| | | } |
| | | return e; |
| | | } |
| | | |
| | | |
| | |
| | | * attributes that may be altered without impacting the information |
| | | * in this entry. |
| | | * |
| | | * @param typesOnly Indicates whether to include attribute types |
| | | * only without values. |
| | | * @param typesOnly Indicates whether to include attribute |
| | | * types only without values. |
| | | * @param processVirtual Indicates whether virtual attribute |
| | | * processing should be performed for the |
| | | * entry. |
| | | * |
| | | * @return A duplicate of this entry that may be altered without |
| | | * impacting the information in this entry and that does |
| | | * not contain any operational attributes. |
| | | */ |
| | | public Entry duplicateWithoutOperationalAttributes( |
| | | boolean typesOnly) |
| | | boolean typesOnly, boolean processVirtual) |
| | | { |
| | | HashMap<ObjectClass,String> objectClassesCopy; |
| | | if (typesOnly) |
| | |
| | | HashMap<AttributeType,List<Attribute>> operationalAttrsCopy = |
| | | new HashMap<AttributeType,List<Attribute>>(0); |
| | | |
| | | return new Entry(dn, objectClassesCopy, userAttrsCopy, |
| | | operationalAttrsCopy); |
| | | for (AttributeType t : suppressedAttributes.keySet()) |
| | | { |
| | | List<Attribute> attrList = suppressedAttributes.get(t); |
| | | if (! t.isOperational()) |
| | | { |
| | | userAttributes.put(t, attrList); |
| | | } |
| | | } |
| | | |
| | | Entry e = new Entry(dn, objectClassesCopy, userAttrsCopy, |
| | | operationalAttrsCopy); |
| | | |
| | | if (processVirtual) |
| | | { |
| | | e.processVirtualAttributes(false); |
| | | } |
| | | |
| | | return e; |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * Performs a deep copy from the source map to the target map. In |
| | | * this case, the attributes in the list will be duplicates rather |
| | | * than re-using the same reference. |
| | | * than re-using the same reference. Virtual attributes will not be |
| | | * included when making the copy. |
| | | * |
| | | * @param source The source map from which to obtain the |
| | | * information. |
| | | * @param target The target map into which to place the copied |
| | | * information. |
| | | * @param omitValues <CODE>true</CODE> if the values should be |
| | | * omitted. |
| | | * @param source The source map from which to obtain the |
| | | * information. |
| | | * @param target The target map into which to place the |
| | | * copied information. |
| | | * @param omitValues Indicates whether to omit attribute values |
| | | * when processing. |
| | | */ |
| | | private void deepCopy(Map<AttributeType,List<Attribute>> source, |
| | | Map<AttributeType,List<Attribute>> target, |
| | |
| | | |
| | | for (Attribute a : sourceList) |
| | | { |
| | | if (a.isVirtual()) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | targetList.add(a.duplicate(omitValues)); |
| | | } |
| | | |
| | | target.put(t, targetList); |
| | | if (! targetList.isEmpty()) |
| | | { |
| | | target.put(t, targetList); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | */ |
| | | public boolean matchesBaseAndScope(DN baseDN, SearchScope scope) |
| | | { |
| | | switch (scope) |
| | | return dn.matchesBaseAndScope(baseDN, scope); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs any necessary virtual attribute processing for this |
| | | * entry. This should only be called at the time the entry is |
| | | * decoded or created within the backend. |
| | | */ |
| | | public void processVirtualAttributes() |
| | | { |
| | | processVirtualAttributes(true); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs any necessary virtual attribute processing for this |
| | | * entry. This should only be called at the time the entry is |
| | | * decoded or created within the backend. |
| | | * |
| | | * @param includeOperational Indicates whether to include |
| | | * operational attributes. |
| | | */ |
| | | public void processVirtualAttributes(boolean includeOperational) |
| | | { |
| | | for (VirtualAttributeRule rule : |
| | | DirectoryServer.getVirtualAttributes(this)) |
| | | { |
| | | case BASE_OBJECT: |
| | | // The entry DN must equal the base DN. |
| | | return baseDN.equals(dn); |
| | | AttributeType attributeType = rule.getAttributeType(); |
| | | if (attributeType.isOperational() && (! includeOperational)) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | case SINGLE_LEVEL: |
| | | // The parent DN for this entry must equal the base DN. |
| | | return baseDN.equals(dn.getParentDNInSuffix()); |
| | | List<Attribute> attrList = userAttributes.get(attributeType); |
| | | if ((attrList == null) || attrList.isEmpty()) |
| | | { |
| | | attrList = operationalAttributes.get(attributeType); |
| | | if ((attrList == null) || attrList.isEmpty()) |
| | | { |
| | | // There aren't any conflicts, so we can just add the |
| | | // attribute to the entry. |
| | | attrList = new LinkedList<Attribute>(); |
| | | attrList.add(new VirtualAttribute(attributeType, this, |
| | | rule)); |
| | | if (attributeType.isOperational()) |
| | | { |
| | | operationalAttributes.put(attributeType, attrList); |
| | | } |
| | | else |
| | | { |
| | | userAttributes.put(attributeType, attrList); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // There is a conflict with an existing operational |
| | | // attribute. |
| | | if (attrList.get(0).isVirtual()) |
| | | { |
| | | // The existing attribute is already virtual, so we've got |
| | | // a different conflict, but we'll let the first win. |
| | | // FIXME -- Should we handle this differently? |
| | | continue; |
| | | } |
| | | |
| | | case WHOLE_SUBTREE: |
| | | // The base DN must be an ancestor of the entry DN. |
| | | return baseDN.isAncestorOf(dn); |
| | | // The conflict is with a real attribute. See what the |
| | | // conflict behavior is and figure out how to handle it. |
| | | switch (rule.getConflictBehavior()) |
| | | { |
| | | case REAL_OVERRIDES_VIRTUAL: |
| | | // We don't need to update the entry because the real |
| | | // attribute will take precedence. |
| | | break; |
| | | |
| | | case SUBORDINATE_SUBTREE: |
| | | // The base DN must be an ancstor of the entry DN, but it |
| | | // must not equal the entry DN. |
| | | return ((! baseDN.equals(dn)) && baseDN.isAncestorOf(dn)); |
| | | case VIRTUAL_OVERRIDES_REAL: |
| | | // We need to move the real attribute to the suppressed |
| | | // list and replace it with the virtual attribute. |
| | | suppressedAttributes.put(attributeType, attrList); |
| | | attrList = new LinkedList<Attribute>(); |
| | | attrList.add(new VirtualAttribute(attributeType, this, |
| | | rule)); |
| | | operationalAttributes.put(attributeType, attrList); |
| | | break; |
| | | |
| | | default: |
| | | // This is a scope that we don't recognize. |
| | | return false; |
| | | case MERGE_REAL_AND_VIRTUAL: |
| | | // We need to add the virtual attribute to the list and |
| | | // keep the existing real attribute(s). |
| | | attrList.add(new VirtualAttribute(attributeType, this, |
| | | rule)); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // There is a conflict with an existing user attribute. |
| | | if (attrList.get(0).isVirtual()) |
| | | { |
| | | // The existing attribute is already virtual, so we've got |
| | | // a different conflict, but we'll let the first win. |
| | | // FIXME -- Should we handle this differently? |
| | | continue; |
| | | } |
| | | |
| | | // The conflict is with a real attribute. See what the |
| | | // conflict behavior is and figure out how to handle it. |
| | | switch (rule.getConflictBehavior()) |
| | | { |
| | | case REAL_OVERRIDES_VIRTUAL: |
| | | // We don't need to update the entry because the real |
| | | // attribute will take precedence. |
| | | break; |
| | | |
| | | case VIRTUAL_OVERRIDES_REAL: |
| | | // We need to move the real attribute to the suppressed |
| | | // list and replace it with the virtual attribute. |
| | | suppressedAttributes.put(attributeType, attrList); |
| | | attrList = new LinkedList<Attribute>(); |
| | | attrList.add(new VirtualAttribute(attributeType, this, |
| | | rule)); |
| | | userAttributes.put(attributeType, attrList); |
| | | break; |
| | | |
| | | case MERGE_REAL_AND_VIRTUAL: |
| | | // We need to add the virtual attribute to the list and |
| | | // keep the existing real attribute(s). |
| | | attrList.add(new VirtualAttribute(attributeType, this, |
| | | rule)); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | virtualAttributeProcessingPerformed = true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether virtual attribute processing has been performed |
| | | * for this entry. |
| | | * |
| | | * @return {@code true} if virtual attribute processing has been |
| | | * performed for this entry, or {@code false} if not. |
| | | */ |
| | | public boolean virtualAttributeProcessingPerformed() |
| | | { |
| | | return virtualAttributeProcessingPerformed; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Strips out all real attributes from this entry so that it only |
| | | * contains virtual attributes. |
| | | */ |
| | | public void stripRealAttributes() |
| | | { |
| | | // The objectClass attribute will always be a real attribute. |
| | | objectClasses.clear(); |
| | | |
| | | Iterator<Map.Entry<AttributeType,List<Attribute>>> |
| | | attrListIterator = userAttributes.entrySet().iterator(); |
| | | while (attrListIterator.hasNext()) |
| | | { |
| | | Map.Entry<AttributeType,List<Attribute>> mapEntry = |
| | | attrListIterator.next(); |
| | | Iterator<Attribute> attrIterator = |
| | | mapEntry.getValue().iterator(); |
| | | while (attrIterator.hasNext()) |
| | | { |
| | | Attribute a = attrIterator.next(); |
| | | if (! a.isVirtual()) |
| | | { |
| | | attrIterator.remove(); |
| | | } |
| | | } |
| | | |
| | | if (mapEntry.getValue().isEmpty()) |
| | | { |
| | | attrListIterator.remove(); |
| | | } |
| | | } |
| | | |
| | | attrListIterator = operationalAttributes.entrySet().iterator(); |
| | | while (attrListIterator.hasNext()) |
| | | { |
| | | Map.Entry<AttributeType,List<Attribute>> mapEntry = |
| | | attrListIterator.next(); |
| | | Iterator<Attribute> attrIterator = |
| | | mapEntry.getValue().iterator(); |
| | | while (attrIterator.hasNext()) |
| | | { |
| | | Attribute a = attrIterator.next(); |
| | | if (! a.isVirtual()) |
| | | { |
| | | attrIterator.remove(); |
| | | } |
| | | } |
| | | |
| | | if (mapEntry.getValue().isEmpty()) |
| | | { |
| | | attrListIterator.remove(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Strips out all virtual attributes from this entry so that it only |
| | | * contains real attributes. |
| | | */ |
| | | public void stripVirtualAttributes() |
| | | { |
| | | Iterator<Map.Entry<AttributeType,List<Attribute>>> |
| | | attrListIterator = userAttributes.entrySet().iterator(); |
| | | while (attrListIterator.hasNext()) |
| | | { |
| | | Map.Entry<AttributeType,List<Attribute>> mapEntry = |
| | | attrListIterator.next(); |
| | | Iterator<Attribute> attrIterator = |
| | | mapEntry.getValue().iterator(); |
| | | while (attrIterator.hasNext()) |
| | | { |
| | | Attribute a = attrIterator.next(); |
| | | if (a.isVirtual()) |
| | | { |
| | | attrIterator.remove(); |
| | | } |
| | | } |
| | | |
| | | if (mapEntry.getValue().isEmpty()) |
| | | { |
| | | attrListIterator.remove(); |
| | | } |
| | | } |
| | | |
| | | attrListIterator = operationalAttributes.entrySet().iterator(); |
| | | while (attrListIterator.hasNext()) |
| | | { |
| | | Map.Entry<AttributeType,List<Attribute>> mapEntry = |
| | | attrListIterator.next(); |
| | | Iterator<Attribute> attrIterator = |
| | | mapEntry.getValue().iterator(); |
| | | while (attrIterator.hasNext()) |
| | | { |
| | | Attribute a = attrIterator.next(); |
| | | if (a.isVirtual()) |
| | | { |
| | | attrIterator.remove(); |
| | | } |
| | | } |
| | | |
| | | if (mapEntry.getValue().isEmpty()) |
| | | { |
| | | attrListIterator.remove(); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | List<Attribute> attrList = userAttributes.get(attrType); |
| | | for (Attribute a : attrList) |
| | | { |
| | | if (a.isVirtual() && |
| | | (! exportConfig.includeVirtualAttributes())) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | if (exportConfig.typesOnly()) |
| | | { |
| | | StringBuilder attrName = new StringBuilder(a.getName()); |
| | |
| | | } |
| | | |
| | | |
| | | // Finally, the set of operational attributes. |
| | | // Next, the set of operational attributes. |
| | | if (exportConfig.includeOperationalAttributes()) |
| | | { |
| | | for (AttributeType attrType : operationalAttributes.keySet()) |
| | |
| | | operationalAttributes.get(attrType); |
| | | for (Attribute a : attrList) |
| | | { |
| | | if (a.isVirtual() && |
| | | (! exportConfig.includeVirtualAttributes())) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | if (exportConfig.typesOnly()) |
| | | { |
| | | StringBuilder attrName = new StringBuilder(a.getName()); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // If we are not supposed to include virtual attributes, then |
| | | // write any attributes that may normally be suppressed by a |
| | | // virtual attribute. |
| | | if (! exportConfig.includeVirtualAttributes()) |
| | | { |
| | | for (AttributeType t : suppressedAttributes.keySet()) |
| | | { |
| | | if (exportConfig.includeAttribute(t)) |
| | | { |
| | | for (Attribute a : suppressedAttributes.get(t)) |
| | | { |
| | | if (exportConfig.typesOnly()) |
| | | { |
| | | StringBuilder attrName = new StringBuilder(a.getName()); |
| | | for (String o : a.getOptions()) |
| | | { |
| | | attrName.append(";"); |
| | | attrName.append(o); |
| | | } |
| | | attrName.append(":"); |
| | | |
| | | writeLDIFLine(attrName, writer, wrapLines, wrapColumn); |
| | | } |
| | | else |
| | | { |
| | | StringBuilder attrName = new StringBuilder(a.getName()); |
| | | for (String o : a.getOptions()) |
| | | { |
| | | attrName.append(";"); |
| | | attrName.append(o); |
| | | } |
| | | |
| | | for (AttributeValue v : a.getValues()) |
| | | { |
| | | StringBuilder attrLine = new StringBuilder(); |
| | | attrLine.append(attrName); |
| | | appendLDIFSeparatorAndValue(attrLine, |
| | | v.getValueBytes()); |
| | | writeLDIFLine(attrLine, writer, wrapLines, |
| | | wrapColumn); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | // Make sure there is a blank line after the entry. |
| | | writer.newLine(); |
| | | |
| | |
| | | */ |
| | | public class LDIFExportConfig |
| | | { |
| | | |
| | | |
| | | |
| | | // Indicates whether the data should be compressed as it is written. |
| | | private boolean compressData; |
| | | |
| | |
| | | // export. |
| | | private boolean includeOperationalAttributes; |
| | | |
| | | // Indicates whether to include virutal attributes in the export. |
| | | private boolean includeVirtualAttributes; |
| | | |
| | | // Indicates whether to invoke LDIF export plugins on entries being |
| | | // exported. |
| | | private boolean invokeExportPlugins; |
| | |
| | | hashData = false; |
| | | includeObjectClasses = true; |
| | | includeOperationalAttributes = true; |
| | | includeVirtualAttributes = false; |
| | | invokeExportPlugins = false; |
| | | signHash = false; |
| | | typesOnly = false; |
| | |
| | | hashData = false; |
| | | includeObjectClasses = true; |
| | | includeOperationalAttributes = true; |
| | | includeVirtualAttributes = false; |
| | | invokeExportPlugins = false; |
| | | signHash = false; |
| | | typesOnly = false; |
| | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether virtual attributes should be included in the |
| | | * export. |
| | | * |
| | | * @return {@code true} if virtual attributes should be included in |
| | | * the export, or {@code false} if not. |
| | | */ |
| | | public boolean includeVirtualAttributes() |
| | | { |
| | | return includeVirtualAttributes; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Specifies whether virtual attributes should be included in the |
| | | * export. |
| | | * |
| | | * @param includeVirtualAttributes Specifies whether virtual |
| | | * attributes should be included |
| | | * in the export. |
| | | */ |
| | | public void setIncludeVirtualAttributes( |
| | | boolean includeVirtualAttributes) |
| | | { |
| | | this.includeVirtualAttributes = includeVirtualAttributes; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of attributes that should be excluded from the |
| | | * entries written to LDIF. The set that is returned may be altered |
| | | * by the caller. |
| 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.types; |
| | | |
| | | |
| | | |
| | | import java.util.Collection; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | |
| | | import org.opends.server.admin.std.server.VirtualAttributeCfg; |
| | | import org.opends.server.api.VirtualAttributeProvider; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class defines a virtual attribute, which is a special kind of |
| | | * attribute whose values do not actually exist in persistent storage |
| | | * but rather are computed or otherwise obtained dynamically. |
| | | */ |
| | | public class VirtualAttribute |
| | | extends Attribute |
| | | { |
| | | // The entry with which this virtual attribute is associated. |
| | | private final Entry entry; |
| | | |
| | | // The virtual attribute provider for this virtual attribute. |
| | | private final VirtualAttributeProvider< |
| | | ? extends VirtualAttributeCfg> provider; |
| | | |
| | | // The virtual attribute rule for this virtual attribute. |
| | | private final VirtualAttributeRule rule; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new virtual attribute with the provided information. |
| | | * |
| | | * @param attributeType The attribute type for this virtual |
| | | * attribute. |
| | | * @param entry The entry in which this virtual attribute |
| | | * exists. |
| | | * @param rule The virutal attribute rule that governs |
| | | * the behavior of this virtual attribute. |
| | | */ |
| | | public VirtualAttribute(AttributeType attributeType, Entry entry, |
| | | VirtualAttributeRule rule) |
| | | { |
| | | super(attributeType); |
| | | |
| | | this.entry = entry; |
| | | this.rule = rule; |
| | | |
| | | provider = rule.getProvider(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the entry in which this virtual attribute exists. |
| | | * |
| | | * @return The entry in which this virtual attribute exists. |
| | | */ |
| | | public Entry getEntry() |
| | | { |
| | | return entry; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the virtual attribute rule that governs the behavior of |
| | | * this virtual attribute. |
| | | * |
| | | * @return The virtual attribute rule that governs the behavior of |
| | | * this virtual attribute. |
| | | */ |
| | | public VirtualAttributeRule getVirtualAttributeRule() |
| | | { |
| | | return rule; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public LinkedHashSet<AttributeValue> getValues() |
| | | { |
| | | return provider.getValues(entry, rule); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean hasValue() |
| | | { |
| | | return provider.hasValue(entry, rule); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean hasValue(AttributeValue value) |
| | | { |
| | | return provider.hasValue(entry, rule, value); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean hasAllValues(Collection<AttributeValue> values) |
| | | { |
| | | return provider.hasAllValues(entry, rule, values); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean hasAnyValue(Collection<AttributeValue> values) |
| | | { |
| | | return provider.hasAnyValue(entry, rule, values); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult matchesSubstring(ByteString subInitial, |
| | | List<ByteString> subAny, |
| | | ByteString subFinal) |
| | | { |
| | | return provider.matchesSubstring(entry, rule, subInitial, subAny, |
| | | subFinal); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult greaterThanOrEqualTo(AttributeValue value) |
| | | { |
| | | return provider.greaterThanOrEqualTo(entry, rule, value); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult lessThanOrEqualTo(AttributeValue value) |
| | | { |
| | | return provider.lessThanOrEqualTo(entry, rule, value); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public ConditionResult approximatelyEqualTo(AttributeValue value) |
| | | { |
| | | return provider.approximatelyEqualTo(entry, rule, value); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public boolean isVirtual() |
| | | { |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public Attribute duplicate(boolean omitValues) |
| | | { |
| | | return new VirtualAttribute(getAttributeType(), entry, rule); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override() |
| | | public void toString(StringBuilder buffer) |
| | | { |
| | | buffer.append("VirtualAttribute("); |
| | | buffer.append(getAttributeType().getNameOrOID()); |
| | | buffer.append(", {"); |
| | | |
| | | boolean firstValue = true; |
| | | for (AttributeValue value : getValues()) |
| | | { |
| | | if (! firstValue) |
| | | { |
| | | buffer.append(", "); |
| | | } |
| | | |
| | | value.toString(buffer); |
| | | firstValue = false; |
| | | } |
| | | |
| | | buffer.append("})"); |
| | | } |
| | | } |
| | | |
| 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.types; |
| | | |
| | | |
| | | |
| | | import java.util.Iterator; |
| | | import java.util.Set; |
| | | |
| | | import org.opends.server.admin.std.meta.VirtualAttributeCfgDefn; |
| | | import org.opends.server.admin.std.server.VirtualAttributeCfg; |
| | | import org.opends.server.api.Group; |
| | | import org.opends.server.api.VirtualAttributeProvider; |
| | | import org.opends.server.core.DirectoryServer; |
| | | |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import static org.opends.server.util.Validator.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class defines a virtual attribute rule, which associates a |
| | | * virtual attribute provider with its associated configuration, |
| | | * including the attribute type for which the values should be |
| | | * generated; the base DN(s), group DN(s), and search filter(s) that |
| | | * should be used to identify which entries should have the virtual |
| | | * attribute, and how conflicts between real and virtual values should |
| | | * be handled. |
| | | */ |
| | | public class VirtualAttributeRule |
| | | { |
| | | // The attribute type for which the values should be generated. |
| | | private final AttributeType attributeType; |
| | | |
| | | // The set of base DNs for branches that are eligible to have this |
| | | // virtual attribute. |
| | | private final Set<DN> baseDNs; |
| | | |
| | | // The set of DNs for groups whose members are eligible to have this |
| | | // virtual attribute. |
| | | private final Set<DN> groupDNs; |
| | | |
| | | // The set of search filters for entries that are eligible to have |
| | | // this virtual attribute. |
| | | private final Set<SearchFilter> filters; |
| | | |
| | | // The virtual attribute provider used to generate the values. |
| | | private final VirtualAttributeProvider< |
| | | ? extends VirtualAttributeCfg> provider; |
| | | |
| | | // The behavior that should be exhibited for entries that already |
| | | // have real values for the target attribute. |
| | | private final VirtualAttributeCfgDefn.ConflictBehavior |
| | | conflictBehavior; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new virtual attribute rule with the provided |
| | | * information. |
| | | * |
| | | * @param attributeType The attribute type for which the values |
| | | * should be generated. |
| | | * @param provider The virtual attribute provider to use |
| | | * to generate the values. |
| | | * @param baseDNs The set of base DNs for branches that |
| | | * are eligible to have this virtual |
| | | * attribute. |
| | | * @param groupDNs The set of DNs for groups whose members |
| | | * are eligible to have this virtual |
| | | * attribute. |
| | | * @param filters The set of search filters for entries |
| | | * that are eligible to have this virtual |
| | | * attribute. |
| | | * @param conflictBehavior The behavior that the server should |
| | | * exhibit for entries that already have |
| | | * one or more real values for the target |
| | | * attribute. |
| | | */ |
| | | public VirtualAttributeRule(AttributeType attributeType, |
| | | VirtualAttributeProvider<? extends VirtualAttributeCfg> |
| | | provider, |
| | | Set<DN> baseDNs, Set<DN> groupDNs, |
| | | Set<SearchFilter> filters, |
| | | VirtualAttributeCfgDefn.ConflictBehavior |
| | | conflictBehavior) |
| | | { |
| | | ensureNotNull(attributeType, provider, baseDNs, groupDNs); |
| | | ensureNotNull(filters, conflictBehavior); |
| | | |
| | | this.attributeType = attributeType; |
| | | this.provider = provider; |
| | | this.baseDNs = baseDNs; |
| | | this.groupDNs = groupDNs; |
| | | this.filters = filters; |
| | | this.conflictBehavior = conflictBehavior; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the attribute type for which the values should be |
| | | * generated. |
| | | * |
| | | * @return The attribute type for which the values should be |
| | | * generated. |
| | | */ |
| | | public AttributeType getAttributeType() |
| | | { |
| | | return attributeType; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * |
| | | * Retrieves the virtual attribute provider used to generate the |
| | | * values. |
| | | * |
| | | * @return The virtual attribute provider to use to generate the |
| | | * values. |
| | | */ |
| | | public VirtualAttributeProvider<? extends VirtualAttributeCfg> |
| | | getProvider() |
| | | { |
| | | return provider; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of base DNs for branches that are eligible to |
| | | * have this virtual attribute. |
| | | * |
| | | * @return The set of base DNs for branches that are eligible to |
| | | * have this virtual attribute. |
| | | */ |
| | | public Set<DN> getBaseDNs() |
| | | { |
| | | return baseDNs; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of DNs for groups whose members are eligible to |
| | | * have this virtual attribute. |
| | | * |
| | | * @return The set of DNs for groups whose members are eligible to |
| | | * have this virtual attribute. |
| | | */ |
| | | public Set<DN> getGroupDNs() |
| | | { |
| | | return groupDNs; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the set of search filters for entries that are eligible |
| | | * to have this virtual attribute. |
| | | * |
| | | * @return The set of search filters for entries that are eligible |
| | | * to have this virtual attribute. |
| | | */ |
| | | public Set<SearchFilter> getFilters() |
| | | { |
| | | return filters; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves the behavior that the server should exhibit for entries |
| | | * that already have one or more real values for the target |
| | | * attribute. |
| | | * |
| | | * @return The behavior that the server should exhibit for entries |
| | | * that already have one or more real values for the target |
| | | * attribute. |
| | | */ |
| | | public VirtualAttributeCfgDefn.ConflictBehavior |
| | | getConflictBehavior() |
| | | { |
| | | return conflictBehavior; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Indicates whether this virtual attribute rule applies to the |
| | | * provided entry, taking into account the eligibility requirements |
| | | * defined in the rule. |
| | | * |
| | | * @param entry The entry for which to make the determination. |
| | | * |
| | | * @return {@code true} if this virtual attribute rule may be used |
| | | * to generate values for the entry, or {@code false} if |
| | | * not. |
| | | */ |
| | | public boolean appliesToEntry(Entry entry) |
| | | { |
| | | // We'll do this in order of expense so that the checks which are |
| | | // potentially most expensive are done last. First, check to see |
| | | // if real values should override virtual ones and if so whether |
| | | // the entry already has virtual values. |
| | | if ((conflictBehavior == VirtualAttributeCfgDefn.ConflictBehavior. |
| | | REAL_OVERRIDES_VIRTUAL) && |
| | | entry.hasAttribute(attributeType)) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | // If there are any base DNs defined, then the entry must be below |
| | | // one of them. |
| | | DN entryDN = entry.getDN(); |
| | | if (! baseDNs.isEmpty()) |
| | | { |
| | | boolean found = false; |
| | | for (DN dn : baseDNs) |
| | | { |
| | | if (entryDN.isDescendantOf(dn)) |
| | | { |
| | | found = true; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (! found) |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // If there are any search filters defined, then the entry must |
| | | // match one of them. |
| | | if (! filters.isEmpty()) |
| | | { |
| | | boolean found = false; |
| | | for (SearchFilter filter : filters) |
| | | { |
| | | try |
| | | { |
| | | if (filter.matchesEntry(entry)) |
| | | { |
| | | found = true; |
| | | break; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (! found) |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // If there are any group memberships defined, then the entry must |
| | | // be a member of one of them. |
| | | if (! groupDNs.isEmpty()) |
| | | { |
| | | boolean found = false; |
| | | for (DN dn : groupDNs) |
| | | { |
| | | try |
| | | { |
| | | Group group = |
| | | DirectoryServer.getGroupManager().getGroupInstance(dn); |
| | | if ((group != null) && group.isMember(entry)) |
| | | { |
| | | found = true; |
| | | break; |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | if (debugEnabled()) |
| | | { |
| | | debugCaught(DebugLogLevel.ERROR, e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (! found) |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | // If we've gotten here, then the rule is applicable. |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a string representation of this virtual attribute rule. |
| | | * |
| | | * @return A string representation of this virutal attribute rule. |
| | | */ |
| | | public String toString() |
| | | { |
| | | StringBuilder buffer = new StringBuilder(); |
| | | toString(buffer); |
| | | return buffer.toString(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Appends a string representation of this virtual attribute rule to |
| | | * the provided buffer. |
| | | * |
| | | * @param buffer The buffer to which the information should be |
| | | * written. |
| | | */ |
| | | public void toString(StringBuilder buffer) |
| | | { |
| | | buffer.append("VirtualAttributeRule(attrType="); |
| | | buffer.append(attributeType.getNameOrOID()); |
| | | buffer.append(", providerDN=\""); |
| | | buffer.append(provider.getClass().getName()); |
| | | |
| | | buffer.append("\", baseDNs={"); |
| | | if (! baseDNs.isEmpty()) |
| | | { |
| | | buffer.append("\""); |
| | | Iterator<DN> iterator = baseDNs.iterator(); |
| | | buffer.append(iterator.next()); |
| | | |
| | | while (iterator.hasNext()) |
| | | { |
| | | buffer.append("\", \""); |
| | | buffer.append(iterator.next()); |
| | | } |
| | | |
| | | buffer.append("\""); |
| | | } |
| | | |
| | | buffer.append("}, groupDNs={"); |
| | | if (! groupDNs.isEmpty()) |
| | | { |
| | | buffer.append("\""); |
| | | Iterator<DN> iterator = groupDNs.iterator(); |
| | | buffer.append(iterator.next()); |
| | | |
| | | while (iterator.hasNext()) |
| | | { |
| | | buffer.append("\", \""); |
| | | buffer.append(iterator.next()); |
| | | } |
| | | |
| | | buffer.append("\""); |
| | | } |
| | | |
| | | buffer.append("}, filters={"); |
| | | if (! filters.isEmpty()) |
| | | { |
| | | buffer.append("\""); |
| | | Iterator<SearchFilter> iterator = filters.iterator(); |
| | | buffer.append(iterator.next()); |
| | | |
| | | while (iterator.hasNext()) |
| | | { |
| | | buffer.append("\", \""); |
| | | buffer.append(iterator.next()); |
| | | } |
| | | |
| | | buffer.append("\""); |
| | | } |
| | | |
| | | buffer.append("}, conflictBehavior="); |
| | | buffer.append(conflictBehavior); |
| | | buffer.append(")"); |
| | | } |
| | | } |
| | | |
| | |
| | | */ |
| | | public final class LDIFWriter |
| | | { |
| | | |
| | | |
| | | // FIXME -- Add support for generating a hash when writing the data. |
| | | // FIXME -- Add support for signing the hash that is generated. |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * The OID for the real attributes only control. |
| | | */ |
| | | public static final String OID_REAL_ATTRS_ONLY = "2.16.840.1.113730.3.4.17"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The OID for the subtree delete control. |
| | | */ |
| | | public static final String OID_SUBTREE_DELETE_CONTROL = |
| | |
| | | |
| | | |
| | | |
| | | /** |
| | | * The OID for the virtual attributes only control. |
| | | */ |
| | | public static final String OID_VIRTUAL_ATTRS_ONLY = |
| | | "2.16.840.1.113730.3.4.19"; |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * The block length in bytes used when generating an HMAC-MD5 digest. |
| | |
| | | } |
| | | |
| | | // The add operation changes the attributes, so let's duplicate the entry. |
| | | Entry duplicateEntry = testEntry.duplicate(); |
| | | Entry duplicateEntry = testEntry.duplicate(false); |
| | | |
| | | AddOperation addOperation = |
| | | connection.processAdd(duplicateEntry.getDN(), |
| 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.extensions; |
| | | |
| | | |
| | | |
| | | import java.util.Collections; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | 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.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ByteStringFactory; |
| | | import org.opends.server.types.ConditionResult; |
| | | import org.opends.server.types.Control; |
| | | import org.opends.server.types.DereferencePolicy; |
| | | import org.opends.server.types.DN; |
| | | 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 static org.testng.Assert.*; |
| | | |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * A set of test cases for the entryDN virtual attribute provider. |
| | | */ |
| | | public class EntryDNVirtualAttributeProviderTestCase |
| | | extends ExtensionsTestCase |
| | | { |
| | | // The attribute type for the entryDN attribute. |
| | | private AttributeType entryDNType; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Ensures that the Directory Server is running. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @BeforeClass() |
| | | public void startServer() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.startServer(); |
| | | |
| | | entryDNType = DirectoryServer.getAttributeType("entrydn", false); |
| | | assertNotNull(entryDNType); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a set of entry DNs for use in testing the entryDN virtual |
| | | * attribute. |
| | | * |
| | | * @return A set of entry DNs for use in testing the entryDN 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") } |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code getEntry} method for the specified entry to ensure that |
| | | * the entry returned includes the entryDN 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(entryDNType)); |
| | | |
| | | List<Attribute> attrList = e.getAttribute(entryDNType); |
| | | assertNotNull(attrList); |
| | | assertFalse(attrList.isEmpty()); |
| | | for (Attribute a : attrList) |
| | | { |
| | | assertTrue(a.hasValue()); |
| | | assertEquals(a.getValues().size(), 1); |
| | | assertTrue(a.hasValue(new AttributeValue(entryDNType, |
| | | entryDN.toNormalizedString()))); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the entryDN 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(entryDNType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the entryDN 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(entryDNType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the entryDN 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(entryDNType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the entryDN 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(entryDNType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the entryDN attribute is included when the entryDN 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 testSearchEntryDNAttr(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("entrydn"); |
| | | |
| | | 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(entryDNType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the entryDN 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 testSearchExcludeEntryDNAttr(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(entryDNType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the entryDN attribute is included when the entryDN attribute is |
| | | * specifically requested and the entryDN 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 = "testEntryDNs") |
| | | public void testSearchEntryDNAttrInMatchingFilter(DN entryDN) |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com"); |
| | | |
| | | SearchFilter filter = |
| | | SearchFilter.createFilterFromString("(entryDN=" + entryDN.toString() + |
| | | ")"); |
| | | LinkedHashSet<String> attrList = new LinkedHashSet<String>(1); |
| | | attrList.add("entrydn"); |
| | | |
| | | 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(entryDNType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * no entries are returned when the entryDN 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 testSearchEntryDNAttrInNonMatchingFilter(DN entryDN) |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com"); |
| | | |
| | | SearchFilter filter = |
| | | SearchFilter.createFilterFromString("(entryDN=cn=Not A Match)"); |
| | | LinkedHashSet<String> attrList = new LinkedHashSet<String>(1); |
| | | attrList.add("entrydn"); |
| | | |
| | | 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 entryDN attribute is not included when the entryDN 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 testSearchEntryDNAttrRealAttrsOnly(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("entrydn"); |
| | | |
| | | LinkedList<Control> requestControls = new LinkedList<Control>(); |
| | | requestControls.add(new Control(OID_REAL_ATTRS_ONLY, true)); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | InternalSearchOperation searchOperation = |
| | | new InternalSearchOperation(conn, conn.nextOperationID(), |
| | | conn.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(entryDNType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the entryDN attribute is included when the entryDN 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 testSearchEntryDNAttrVirtualAttrsOnly(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("entrydn"); |
| | | |
| | | LinkedList<Control> requestControls = new LinkedList<Control>(); |
| | | requestControls.add(new Control(OID_VIRTUAL_ATTRS_ONLY, true)); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | InternalSearchOperation searchOperation = |
| | | new InternalSearchOperation(conn, conn.nextOperationID(), |
| | | conn.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(entryDNType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code isMultiValued} method. |
| | | */ |
| | | @Test() |
| | | public void testIsMultiValued() |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | assertFalse(provider.isMultiValued()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code getValues} method for an entry. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testGetValues() |
| | | throws Exception |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedHashSet<AttributeValue> values = provider.getValues(entry, rule); |
| | | assertNotNull(values); |
| | | assertEquals(values.size(), 1); |
| | | assertTrue(values.contains(new AttributeValue(entryDNType, "o=test"))); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, 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 |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | assertTrue(provider.hasValue(entry, rule, |
| | | new AttributeValue(entryDNType, "o=test"))); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | assertFalse(provider.hasValue(entry, rule, |
| | | new AttributeValue(entryDNType, "o=not test"))); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code hasAnyValue} method with an empty set of values. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testHasAnyValueEmptySet() |
| | | throws Exception |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, 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 |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(1); |
| | | values.add(new AttributeValue(entryDNType, "o=test")); |
| | | |
| | | 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 |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(1); |
| | | values.add(new AttributeValue(entryDNType, "o=not test")); |
| | | |
| | | 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 |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(3); |
| | | values.add(new AttributeValue(entryDNType, "o=test")); |
| | | values.add(new AttributeValue(entryDNType, "o=not test")); |
| | | values.add(new AttributeValue(entryDNType, "o=not test either")); |
| | | |
| | | 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 |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(3); |
| | | values.add(new AttributeValue(entryDNType, "o=not test")); |
| | | values.add(new AttributeValue(entryDNType, "o=not test either")); |
| | | values.add(new AttributeValue(entryDNType, "o=still not test")); |
| | | |
| | | assertFalse(provider.hasAnyValue(entry, rule, values)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code matchesSubstring} method to ensure that it returns a |
| | | * result of "undefined". |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testMatchesSubstring() |
| | | throws Exception |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedList<ByteString> subAny = new LinkedList<ByteString>(); |
| | | subAny.add(ByteStringFactory.create("=")); |
| | | |
| | | assertEquals(provider.matchesSubstring(entry, rule, null, subAny, null), |
| | | ConditionResult.UNDEFINED); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code greaterThanOrEqualTo} method to ensure that it returns a |
| | | * result of "undefined". |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testGreaterThanOrEqualTo() |
| | | throws Exception |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | AttributeValue value = new AttributeValue(entryDNType, "o=test2"); |
| | | assertEquals(provider.greaterThanOrEqualTo(entry, rule, value), |
| | | ConditionResult.UNDEFINED); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code lessThanOrEqualTo} method to ensure that it returns a |
| | | * result of "undefined". |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testLessThanOrEqualTo() |
| | | throws Exception |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | AttributeValue value = new AttributeValue(entryDNType, "o=test2"); |
| | | assertEquals(provider.lessThanOrEqualTo(entry, rule, value), |
| | | ConditionResult.UNDEFINED); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code approximatelyEqualTo} method to ensure that it returns a |
| | | * result of "undefined". |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testApproximatelyEqualTo() |
| | | throws Exception |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | AttributeValue value = new AttributeValue(entryDNType, "o=test2"); |
| | | assertEquals(provider.approximatelyEqualTo(entry, rule, value), |
| | | ConditionResult.UNDEFINED); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a set of filters for use in testing searchability. The returned |
| | | * data will actually include three elements: |
| | | * <OL> |
| | | * <LI>The string representation of the search filter to use</LI> |
| | | * <LI>An indication of whether it should be searchable</LI> |
| | | * <LI>An indication of whether a minimal o=test entry should match</LI> |
| | | * </OL> |
| | | * |
| | | * @return A set of filters for use in testing searchability. |
| | | */ |
| | | @DataProvider(name = "testFilters") |
| | | public Object[][] getTestFilters() |
| | | { |
| | | return new Object[][] |
| | | { |
| | | new Object[] { "(entryDN=o=test)", true, true }, |
| | | new Object[] { "(entryDN=o=not test)", true, false }, |
| | | new Object[] { "(o=test)", false, false }, |
| | | new Object[] { "(entryDN=*)", false, false }, |
| | | new Object[] { "(&(objectClass=*)(entryDN=o=test))", true, true }, |
| | | new Object[] { "(&(entryDN=o=test)(entryDN=o=not test))", true, false }, |
| | | new Object[] { "(|(objectClass=*)(entryDN=o=test))", false, false }, |
| | | new Object[] { "(|(entryDN=o=test)(entryDN=o=not test))", true, true }, |
| | | new Object[] { "(&(|(entryDN=o=test)(entryDN=o=not test))" + |
| | | "(&(objectClass=top)(|(objectClass=organization)" + |
| | | "(objectClass=domain)))" + |
| | | "(|(o=test)(o=not test)))", true, true } |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code isSearchable} method with the provided information. |
| | | * |
| | | * @param filterString The string representation of the search filter to use |
| | | * for the test. |
| | | * @param isSearchable Indicates whether a search with the given filter |
| | | * should be considered searchable. |
| | | * @param shouldMatch Indicates whether the provided filter should match |
| | | * a minimal o=test entry. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(dataProvider = "testFilters") |
| | | public void testIsSearchable(String filterString, boolean isSearchable, |
| | | boolean shouldMatch) |
| | | throws Exception |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | SearchFilter filter = SearchFilter.createFilterFromString(filterString); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | InternalSearchOperation searchOperation = |
| | | new InternalSearchOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), null, |
| | | DN.decode("o=test"), |
| | | SearchScope.WHOLE_SUBTREE, |
| | | DereferencePolicy.NEVER_DEREF_ALIASES, 0, |
| | | 0, false, filter, null, null); |
| | | |
| | | assertEquals(provider.isSearchable(rule, searchOperation), isSearchable); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code processSearch} method with the provided information. |
| | | * |
| | | * @param filterString The string representation of the search filter to use |
| | | * for the test. |
| | | * @param isSearchable Indicates whether a search with the given filter |
| | | * should be considered searchable. |
| | | * @param shouldMatch Indicates whether the provided filter should match |
| | | * a minimal o=test entry. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(dataProvider = "testFilters") |
| | | public void testProcessSearch(String filterString, boolean isSearchable, |
| | | boolean shouldMatch) |
| | | throws Exception |
| | | { |
| | | if (! isSearchable) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | SearchFilter filter = SearchFilter.createFilterFromString(filterString); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | InternalSearchOperation searchOperation = |
| | | new InternalSearchOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), null, |
| | | DN.decode("o=test"), |
| | | SearchScope.WHOLE_SUBTREE, |
| | | DereferencePolicy.NEVER_DEREF_ALIASES, 0, |
| | | 0, false, filter, null, null); |
| | | provider.processSearch(rule, searchOperation); |
| | | |
| | | if (shouldMatch) |
| | | { |
| | | assertEquals(searchOperation.getSearchEntries().size(), 1); |
| | | } |
| | | else |
| | | { |
| | | assertEquals(searchOperation.getSearchEntries().size(), 0); |
| | | } |
| | | } |
| | | } |
| | | |
| 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.extensions; |
| | | |
| | | |
| | | |
| | | import java.util.Collections; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.admin.std.meta.VirtualAttributeCfgDefn; |
| | | import org.opends.server.core.DeleteOperation; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.protocols.internal.InternalSearchOperation; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ByteStringFactory; |
| | | import org.opends.server.types.ConditionResult; |
| | | import org.opends.server.types.Control; |
| | | import org.opends.server.types.DereferencePolicy; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.ResultCode; |
| | | import org.opends.server.types.SearchFilter; |
| | | import org.opends.server.types.SearchScope; |
| | | import org.opends.server.types.VirtualAttributeRule; |
| | | |
| | | import static org.testng.Assert.*; |
| | | |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * A set of test cases for the isMemberOf virtual attribute provider. |
| | | */ |
| | | public class IsMemberOfVirtualAttributeProviderTestCase |
| | | extends ExtensionsTestCase |
| | | { |
| | | // The attribute type for the isMemberOf attribute. |
| | | private AttributeType isMemberOfType; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Ensures that the Directory Server is running. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @BeforeClass() |
| | | public void startServer() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.startServer(); |
| | | |
| | | isMemberOfType = DirectoryServer.getAttributeType("ismemberof", false); |
| | | assertNotNull(isMemberOfType); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests that the isMemberOf virtual attribute is properly generated for an |
| | | * entry that is a member of a static group based on the member attribute. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testStaticGroupMembershipMember() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | TestCaseUtils.addEntries( |
| | | "dn: ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: People", |
| | | "", |
| | | "dn: uid=test.user,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: Groups", |
| | | "", |
| | | "dn: cn=Test Static Group,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Static Group", |
| | | "member: uid=test.user,ou=People,o=test"); |
| | | |
| | | Entry e = |
| | | DirectoryServer.getEntry(DN.decode("uid=test.user,ou=People,o=test")); |
| | | assertNotNull(e); |
| | | assertTrue(e.hasAttribute(isMemberOfType)); |
| | | for (Attribute a : e.getAttribute(isMemberOfType)) |
| | | { |
| | | assertEquals(a.getValues().size(), 1); |
| | | |
| | | assertTrue(a.hasValue()); |
| | | assertTrue(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=test static group,ou=groups,o=test"))); |
| | | assertFalse(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=not a group,ou=groups,o=test"))); |
| | | assertFalse(a.hasValue(new AttributeValue(isMemberOfType, "invalid"))); |
| | | } |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | DeleteOperation deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test static group,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests that the isMemberOf virtual attribute is properly generated for an |
| | | * entry that is a member of a static group based on the uniqueMember |
| | | * attribute. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testStaticGroupMembershipUniqueMember() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | TestCaseUtils.addEntries( |
| | | "dn: ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: People", |
| | | "", |
| | | "dn: uid=test.user,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: Groups", |
| | | "", |
| | | "dn: cn=Test Static Group,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfUniqueNames", |
| | | "cn: Test Static Group", |
| | | "uniqueMember: uid=test.user,ou=People,o=test"); |
| | | |
| | | Entry e = |
| | | DirectoryServer.getEntry(DN.decode("uid=test.user,ou=People,o=test")); |
| | | assertNotNull(e); |
| | | assertTrue(e.hasAttribute(isMemberOfType)); |
| | | for (Attribute a : e.getAttribute(isMemberOfType)) |
| | | { |
| | | assertEquals(a.getValues().size(), 1); |
| | | |
| | | assertTrue(a.hasValue()); |
| | | assertTrue(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=test static group,ou=groups,o=test"))); |
| | | assertFalse(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=not a group,ou=groups,o=test"))); |
| | | assertFalse(a.hasValue(new AttributeValue(isMemberOfType, "invalid"))); |
| | | } |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | DeleteOperation deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test static group,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests that the isMemberOf virtual attribute is properly generated for an |
| | | * entry that is a member of a dynamic group. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testDynamicGroupMembership() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | TestCaseUtils.addEntries( |
| | | "dn: ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: People", |
| | | "", |
| | | "dn: uid=test.user,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: Groups", |
| | | "", |
| | | "dn: cn=Test Dynamic Group,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfURLs", |
| | | "cn: Test Dynamic Group", |
| | | "memberURL: ldap:///ou=People,o=test??sub?(sn=user)"); |
| | | |
| | | Entry e = |
| | | DirectoryServer.getEntry(DN.decode("uid=test.user,ou=People,o=test")); |
| | | assertNotNull(e); |
| | | assertTrue(e.hasAttribute(isMemberOfType)); |
| | | for (Attribute a : e.getAttribute(isMemberOfType)) |
| | | { |
| | | assertEquals(a.getValues().size(), 1); |
| | | |
| | | assertTrue(a.hasValue()); |
| | | assertTrue(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=test dynamic group,ou=groups,o=test"))); |
| | | assertFalse(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=not a group,ou=groups,o=test"))); |
| | | assertFalse(a.hasValue(new AttributeValue(isMemberOfType, "invalid"))); |
| | | } |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | DeleteOperation deleteOperation = |
| | | conn.processDelete( |
| | | DN.decode("cn=test dynamic group,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests that the isMemberOf virtual attribute is properly generated for an |
| | | * entry that is a member of multiple static groups. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testMultipleStaticGroups() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | TestCaseUtils.addEntries( |
| | | "dn: ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: People", |
| | | "", |
| | | "dn: uid=test.user,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: uid=test.user2,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user2", |
| | | "givenName: Test", |
| | | "sn: User2", |
| | | "cn: Test User2", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: Groups", |
| | | "", |
| | | "dn: cn=Test Group 1,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Group 1", |
| | | "member: uid=test.user,ou=People,o=test", |
| | | "", |
| | | "dn: cn=Test Group 2,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Group 2", |
| | | "member: uid=test.user2,ou=People,o=test", |
| | | "", |
| | | "dn: cn=Test Group 3,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Group 3", |
| | | "member: uid=test.user,ou=People,o=test", |
| | | "member: uid=test.user2,ou=People,o=test"); |
| | | |
| | | Entry e = |
| | | DirectoryServer.getEntry(DN.decode("uid=test.user,ou=People,o=test")); |
| | | assertNotNull(e); |
| | | assertTrue(e.hasAttribute(isMemberOfType)); |
| | | for (Attribute a : e.getAttribute(isMemberOfType)) |
| | | { |
| | | assertEquals(a.getValues().size(), 2); |
| | | |
| | | assertTrue(a.hasValue()); |
| | | assertTrue(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=test group 1,ou=groups,o=test"))); |
| | | assertFalse(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=test group 2,ou=groups,o=test"))); |
| | | assertTrue(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=test group 3,ou=groups,o=test"))); |
| | | assertFalse(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=not a group,ou=groups,o=test"))); |
| | | assertFalse(a.hasValue(new AttributeValue(isMemberOfType, "invalid"))); |
| | | } |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | DeleteOperation deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test group 1,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test group 2,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test group 3,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests that the isMemberOf virtual attribute is properly generated for an |
| | | * entry that is a member of multiple static and dynamic groups. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testMultipleGroups() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | TestCaseUtils.addEntries( |
| | | "dn: ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: People", |
| | | "", |
| | | "dn: uid=test.user,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: uid=test.user2,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user2", |
| | | "givenName: Test", |
| | | "sn: User2", |
| | | "cn: Test User2", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: Groups", |
| | | "", |
| | | "dn: cn=Test Group 1,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Group 1", |
| | | "member: uid=test.user,ou=People,o=test", |
| | | "", |
| | | "dn: cn=Test Group 2,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Group 2", |
| | | "member: uid=test.user2,ou=People,o=test", |
| | | "", |
| | | "dn: cn=Test Group 3,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Group 3", |
| | | "member: uid=test.user,ou=People,o=test", |
| | | "member: uid=test.user2,ou=People,o=test", |
| | | "", |
| | | "dn: cn=Test Group 4,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfURLs", |
| | | "cn: Test Group 4", |
| | | "memberURL: ldap:///o=test??sub?(uid=test.user)", |
| | | "", |
| | | "dn: cn=Test Group 5,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfURLs", |
| | | "cn: Test Group 5", |
| | | "memberURL: ldap:///o=test??sub?(uid=test.user1)", |
| | | "", |
| | | "dn: cn=Test Group 6,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfURLs", |
| | | "cn: Test Group 6", |
| | | "memberURL: ldap:///o=test??sub?(givenName=test)"); |
| | | |
| | | Entry e = |
| | | DirectoryServer.getEntry(DN.decode("uid=test.user,ou=People,o=test")); |
| | | assertNotNull(e); |
| | | assertTrue(e.hasAttribute(isMemberOfType)); |
| | | for (Attribute a : e.getAttribute(isMemberOfType)) |
| | | { |
| | | assertEquals(a.getValues().size(), 4); |
| | | |
| | | assertTrue(a.hasValue()); |
| | | assertTrue(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=test group 1,ou=groups,o=test"))); |
| | | assertFalse(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=test group 2,ou=groups,o=test"))); |
| | | assertTrue(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=test group 3,ou=groups,o=test"))); |
| | | assertTrue(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=test group 4,ou=groups,o=test"))); |
| | | assertFalse(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=test group 5,ou=groups,o=test"))); |
| | | assertTrue(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=test group 6,ou=groups,o=test"))); |
| | | assertFalse(a.hasValue(new AttributeValue(isMemberOfType, |
| | | "cn=not a group,ou=groups,o=test"))); |
| | | assertFalse(a.hasValue(new AttributeValue(isMemberOfType, "invalid"))); |
| | | } |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | DeleteOperation deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test group 1,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test group 2,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test group 3,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test group 4,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test group 5,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test group 6,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code isMultiValued} method. |
| | | */ |
| | | @Test() |
| | | public void testIsMultiValued() |
| | | { |
| | | IsMemberOfVirtualAttributeProvider provider = |
| | | new IsMemberOfVirtualAttributeProvider(); |
| | | assertTrue(provider.isMultiValued()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code hasAnyValue} method with an empty set of values. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testHasAnyValueEmptySet() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | TestCaseUtils.addEntries( |
| | | "dn: ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: People", |
| | | "", |
| | | "dn: uid=test.user,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: Groups", |
| | | "", |
| | | "dn: cn=Test Static Group,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Static Group", |
| | | "member: uid=test.user,ou=People,o=test"); |
| | | |
| | | Entry e = |
| | | DirectoryServer.getEntry(DN.decode("uid=test.user,ou=People,o=test")); |
| | | |
| | | IsMemberOfVirtualAttributeProvider provider = |
| | | new IsMemberOfVirtualAttributeProvider(); |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(isMemberOfType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | assertFalse(provider.hasAnyValue(e, rule, |
| | | Collections.<AttributeValue>emptySet())); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | DeleteOperation deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test static group,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | TestCaseUtils.addEntries( |
| | | "dn: ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: People", |
| | | "", |
| | | "dn: uid=test.user,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: Groups", |
| | | "", |
| | | "dn: cn=Test Static Group,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Static Group", |
| | | "member: uid=test.user,ou=People,o=test"); |
| | | |
| | | Entry e = |
| | | DirectoryServer.getEntry(DN.decode("uid=test.user,ou=People,o=test")); |
| | | |
| | | IsMemberOfVirtualAttributeProvider provider = |
| | | new IsMemberOfVirtualAttributeProvider(); |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(isMemberOfType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(); |
| | | values.add(new AttributeValue(isMemberOfType, |
| | | "cn=test static group,ou=groups,o=test")); |
| | | |
| | | assertTrue(provider.hasAnyValue(e, rule, values)); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | DeleteOperation deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test static group,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | TestCaseUtils.addEntries( |
| | | "dn: ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: People", |
| | | "", |
| | | "dn: uid=test.user,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: Groups", |
| | | "", |
| | | "dn: cn=Test Static Group,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Static Group", |
| | | "member: uid=test.user,ou=People,o=test"); |
| | | |
| | | Entry e = |
| | | DirectoryServer.getEntry(DN.decode("uid=test.user,ou=People,o=test")); |
| | | |
| | | IsMemberOfVirtualAttributeProvider provider = |
| | | new IsMemberOfVirtualAttributeProvider(); |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(isMemberOfType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(); |
| | | values.add(new AttributeValue(isMemberOfType, |
| | | "cn=test dynamic group,ou=groups,o=test")); |
| | | |
| | | assertFalse(provider.hasAnyValue(e, rule, values)); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | DeleteOperation deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test static group,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | TestCaseUtils.addEntries( |
| | | "dn: ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: People", |
| | | "", |
| | | "dn: uid=test.user,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: Groups", |
| | | "", |
| | | "dn: cn=Test Static Group,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Static Group", |
| | | "member: uid=test.user,ou=People,o=test"); |
| | | |
| | | Entry e = |
| | | DirectoryServer.getEntry(DN.decode("uid=test.user,ou=People,o=test")); |
| | | |
| | | IsMemberOfVirtualAttributeProvider provider = |
| | | new IsMemberOfVirtualAttributeProvider(); |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(isMemberOfType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(); |
| | | values.add(new AttributeValue(isMemberOfType, |
| | | "cn=test static group,ou=groups,o=test")); |
| | | values.add(new AttributeValue(isMemberOfType, |
| | | "cn=test dynamic group,ou=groups,o=test")); |
| | | |
| | | assertTrue(provider.hasAnyValue(e, rule, values)); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | DeleteOperation deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test static group,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | TestCaseUtils.addEntries( |
| | | "dn: ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: People", |
| | | "", |
| | | "dn: uid=test.user,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: Groups", |
| | | "", |
| | | "dn: cn=Test Static Group,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Static Group", |
| | | "member: uid=test.user,ou=People,o=test"); |
| | | |
| | | Entry e = |
| | | DirectoryServer.getEntry(DN.decode("uid=test.user,ou=People,o=test")); |
| | | |
| | | IsMemberOfVirtualAttributeProvider provider = |
| | | new IsMemberOfVirtualAttributeProvider(); |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(isMemberOfType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(); |
| | | values.add(new AttributeValue(isMemberOfType, |
| | | "cn=test nonstatic group,ou=groups,o=test")); |
| | | values.add(new AttributeValue(isMemberOfType, |
| | | "cn=test dynamic group,ou=groups,o=test")); |
| | | |
| | | assertFalse(provider.hasAnyValue(e, rule, values)); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | DeleteOperation deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test static group,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code matchesSubstring} method to ensure that it returns a |
| | | * result of "undefined". |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testMatchesSubstring() |
| | | throws Exception |
| | | { |
| | | IsMemberOfVirtualAttributeProvider provider = |
| | | new IsMemberOfVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(isMemberOfType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedList<ByteString> subAny = new LinkedList<ByteString>(); |
| | | subAny.add(ByteStringFactory.create("=")); |
| | | |
| | | assertEquals(provider.matchesSubstring(entry, rule, null, subAny, null), |
| | | ConditionResult.UNDEFINED); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code greaterThanOrEqualTo} method to ensure that it returns a |
| | | * result of "undefined". |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testGreaterThanOrEqualTo() |
| | | throws Exception |
| | | { |
| | | IsMemberOfVirtualAttributeProvider provider = |
| | | new IsMemberOfVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(isMemberOfType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | AttributeValue value = new AttributeValue(isMemberOfType, "o=test2"); |
| | | assertEquals(provider.greaterThanOrEqualTo(entry, rule, value), |
| | | ConditionResult.UNDEFINED); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code lessThanOrEqualTo} method to ensure that it returns a |
| | | * result of "undefined". |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testLessThanOrEqualTo() |
| | | throws Exception |
| | | { |
| | | IsMemberOfVirtualAttributeProvider provider = |
| | | new IsMemberOfVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(isMemberOfType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | AttributeValue value = new AttributeValue(isMemberOfType, "o=test2"); |
| | | assertEquals(provider.lessThanOrEqualTo(entry, rule, value), |
| | | ConditionResult.UNDEFINED); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code approximatelyEqualTo} method to ensure that it returns a |
| | | * result of "undefined". |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testApproximatelyEqualTo() |
| | | throws Exception |
| | | { |
| | | IsMemberOfVirtualAttributeProvider provider = |
| | | new IsMemberOfVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(isMemberOfType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | AttributeValue value = new AttributeValue(isMemberOfType, "o=test2"); |
| | | assertEquals(provider.approximatelyEqualTo(entry, rule, value), |
| | | ConditionResult.UNDEFINED); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a set of filters for use in testing searchability. The returned |
| | | * data will actually include three elements: |
| | | * <OL> |
| | | * <LI>The string representation of the search filter to use</LI> |
| | | * <LI>An indication of whether it should be searchable</LI> |
| | | * <LI>An indication of whether the uid=test.user,ou=People,o=test entry |
| | | * should match</LI> |
| | | * </OL> |
| | | * |
| | | * @return A set of filters for use in testing searchability. |
| | | */ |
| | | @DataProvider(name = "testFilters") |
| | | public Object[][] getTestFilters() |
| | | { |
| | | return new Object[][] |
| | | { |
| | | new Object[] { "(isMemberOf=*)", false, false }, |
| | | new Object[] { "(isMemberOf=cn*)", false, false }, |
| | | new Object[] { "(isMemberOf=invalid)", true, false }, |
| | | new Object[] { "(&(isMemberOf=invalid1)(isMemberOf=invalid2))", |
| | | true, false }, |
| | | new Object[] { "(isMemberOf>=cn=Test Group 1,ou=Groups,o=test)", |
| | | false, false }, |
| | | new Object[] { "(isMemberOf<=cn=Test Group 1,ou=Groups,o=test)", |
| | | false, false }, |
| | | new Object[] { "(isMemberOf~=cn=Test Group 1,ou=Groups,o=test)", |
| | | false, false }, |
| | | new Object[] { "(isMemberOf=cn=Test Group 1,ou=Groups,o=test)", |
| | | true, true }, |
| | | new Object[] { "(isMemberOf=cn=Test Group 2,ou=Groups,o=test)", |
| | | true, false }, |
| | | new Object[] { "(&(isMemberOf=cn=Test Group 1,ou=Groups,o=test)" + |
| | | "(givenName=test))", |
| | | true, true }, |
| | | new Object[] { "(&(isMemberOf=cn=Test Group 1,ou=Groups,o=test)" + |
| | | "(isMemberOf=invalid))", |
| | | true, false }, |
| | | new Object[] { "(&(isMemberOf=invalid)" + |
| | | "(isMemberOf=cn=Test Group 1,ou=Groups,o=test))", |
| | | true, false }, |
| | | new Object[] { "(&(isMemberOf=cn=Test Group 1,ou=Groups,o=test)" + |
| | | "(givenName=not test))", |
| | | true, false }, |
| | | new Object[] { "(&(isMemberOf=cn=Test Group 1,ou=Groups,o=test)" + |
| | | "(isMemberOf=cn=Test Group 2,ou=Groups,o=test))", |
| | | true, false }, |
| | | new Object[] { "(&(isMemberOf=cn=Test Group 1,ou=Groups,o=test)" + |
| | | "(isMemberOf=cn=Test Group 3,ou=Groups,o=test))", |
| | | true, true }, |
| | | new Object[] { "(&(isMemberOf=cn=Test Group 2,ou=Groups,o=test)" + |
| | | "(isMemberOf=cn=Test Group 4,ou=Groups,o=test))", |
| | | true, false }, |
| | | new Object[] { "(|(isMemberOf=cn=Test Group 1,ou=Groups,o=test)" + |
| | | "(isMemberOf=cn=Test Group 3,ou=Groups,o=test))", |
| | | false, false }, |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code isSearchable} method with the provided information. |
| | | * |
| | | * @param filterString The string representation of the search filter to use |
| | | * for the test. |
| | | * @param isSearchable Indicates whether a search with the given filter |
| | | * should be considered searchable. |
| | | * @param shouldMatch Indicates whether the provided filter should match |
| | | * a minimal o=test entry. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(dataProvider = "testFilters") |
| | | public void testIsSearchable(String filterString, boolean isSearchable, |
| | | boolean shouldMatch) |
| | | throws Exception |
| | | { |
| | | IsMemberOfVirtualAttributeProvider provider = |
| | | new IsMemberOfVirtualAttributeProvider(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(isMemberOfType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | SearchFilter filter = SearchFilter.createFilterFromString(filterString); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | InternalSearchOperation searchOperation = |
| | | new InternalSearchOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), null, |
| | | DN.decode("o=test"), |
| | | SearchScope.WHOLE_SUBTREE, |
| | | DereferencePolicy.NEVER_DEREF_ALIASES, 0, |
| | | 0, false, filter, null, null); |
| | | |
| | | assertEquals(provider.isSearchable(rule, searchOperation), isSearchable); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code processSearch} method with the provided information. |
| | | * |
| | | * @param filterString The string representation of the search filter to use |
| | | * for the test. |
| | | * @param isSearchable Indicates whether a search with the given filter |
| | | * should be considered searchable. |
| | | * @param shouldMatch Indicates whether the provided filter should match |
| | | * a minimal o=test entry. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(dataProvider = "testFilters") |
| | | public void testProcessSearch(String filterString, boolean isSearchable, |
| | | boolean shouldMatch) |
| | | throws Exception |
| | | { |
| | | if (! isSearchable) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | |
| | | TestCaseUtils.addEntries( |
| | | "dn: ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: People", |
| | | "", |
| | | "dn: uid=test.user,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user", |
| | | "givenName: Test", |
| | | "sn: User", |
| | | "cn: Test User", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: uid=test.user2,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user2", |
| | | "givenName: Test", |
| | | "sn: User2", |
| | | "cn: Test User2", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: uid=test.user3,ou=People,o=test", |
| | | "objectClass: top", |
| | | "objectClass: person", |
| | | "objectClass: organizationalPerson", |
| | | "objectClass: inetOrgPerson", |
| | | "uid: test.user3", |
| | | "givenName: Test", |
| | | "sn: User3", |
| | | "cn: Test User3", |
| | | "userPassword: password", |
| | | "", |
| | | "dn: ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: organizationalUnit", |
| | | "ou: Groups", |
| | | "", |
| | | "dn: cn=Test Group 1,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Group 1", |
| | | "member: uid=test.user,ou=People,o=test", |
| | | "", |
| | | "dn: cn=Test Group 2,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Group 2", |
| | | "member: uid=test.user2,ou=People,o=test", |
| | | "", |
| | | "dn: cn=Test Group 3,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Group 3", |
| | | "member: uid=test.user,ou=People,o=test", |
| | | "member: uid=test.user2,ou=People,o=test", |
| | | "", |
| | | "dn: cn=Test Group 4,ou=Groups,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfNames", |
| | | "cn: Test Group 4", |
| | | "member: uid=test.user2,ou=People,o=test", |
| | | "member: uid=test.user3,ou=People,o=test"); |
| | | |
| | | Entry userEntry = |
| | | DirectoryServer.getEntry(DN.decode("uid=test.user,ou=People,o=test")); |
| | | assertNotNull(userEntry); |
| | | |
| | | IsMemberOfVirtualAttributeProvider provider = |
| | | new IsMemberOfVirtualAttributeProvider(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(isMemberOfType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | SearchFilter filter = SearchFilter.createFilterFromString(filterString); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | InternalSearchOperation searchOperation = |
| | | new InternalSearchOperation(conn, conn.nextOperationID(), |
| | | conn.nextMessageID(), null, |
| | | DN.decode("o=test"), |
| | | SearchScope.WHOLE_SUBTREE, |
| | | DereferencePolicy.NEVER_DEREF_ALIASES, 0, |
| | | 0, false, filter, null, null); |
| | | provider.processSearch(rule, searchOperation); |
| | | |
| | | boolean matchFound = false; |
| | | for (Entry e : searchOperation.getSearchEntries()) |
| | | { |
| | | if (e.getDN().equals(userEntry.getDN())) |
| | | { |
| | | if (matchFound) |
| | | { |
| | | fail("Multiple matches found for the same user."); |
| | | } |
| | | else |
| | | { |
| | | matchFound = true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | assertEquals(matchFound, shouldMatch); |
| | | |
| | | DeleteOperation deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test group 1,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test group 2,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test group 3,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | |
| | | deleteOperation = |
| | | conn.processDelete(DN.decode("cn=test group 4,ou=groups,o=test")); |
| | | assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS); |
| | | } |
| | | } |
| | | |
| 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.extensions; |
| | | |
| | | |
| | | |
| | | import java.util.Collections; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | 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.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | | import org.opends.server.types.ByteString; |
| | | import org.opends.server.types.ByteStringFactory; |
| | | import org.opends.server.types.ConditionResult; |
| | | import org.opends.server.types.Control; |
| | | import org.opends.server.types.DereferencePolicy; |
| | | import org.opends.server.types.DN; |
| | | 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 static org.testng.Assert.*; |
| | | |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * A set of test cases for the subschemaSubentry virtual attribute provider. |
| | | */ |
| | | public class SubschemaSubentryVirtualAttributeProviderTestCase |
| | | extends ExtensionsTestCase |
| | | { |
| | | // The attribute type for the subschemaSubentry attribute. |
| | | private AttributeType subschemaSubentryType; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Ensures that the Directory Server is running. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @BeforeClass() |
| | | public void startServer() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.startServer(); |
| | | |
| | | subschemaSubentryType = |
| | | DirectoryServer.getAttributeType("subschemasubentry", false); |
| | | assertNotNull(subschemaSubentryType); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a set of entry DNs for use in testing the subschemaSubentry |
| | | * virtual attribute. |
| | | * |
| | | * @return A set of entry DNs for use in testing the subschemaSubentry |
| | | * 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") } |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code getEntry} method for the specified entry to ensure that |
| | | * the entry returned includes the subschemaSubentry 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(subschemaSubentryType)); |
| | | |
| | | List<Attribute> attrList = e.getAttribute(subschemaSubentryType); |
| | | assertNotNull(attrList); |
| | | assertFalse(attrList.isEmpty()); |
| | | for (Attribute a : attrList) |
| | | { |
| | | assertTrue(a.hasValue()); |
| | | assertEquals(a.getValues().size(), 1); |
| | | assertTrue(a.hasValue(new AttributeValue(subschemaSubentryType, |
| | | "cn=schema"))); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the subschemaSubentry 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(subschemaSubentryType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the subschemaSubentry 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(subschemaSubentryType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the subschemaSubentry 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(subschemaSubentryType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the subschemaSubentry 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(subschemaSubentryType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the subschemaSubentry 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 testSearchSubschemaSubentryAttr(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("subschemasubentry"); |
| | | |
| | | 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(subschemaSubentryType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the subschemaSubentry 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 testSearchExcludeSubschemaSubentryAttr(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(subschemaSubentryType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the subschemaSubentry attribute is included when that attribute is |
| | | * specifically requested and the subschemaSubentry 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 = "testEntryDNs") |
| | | public void testSearchSubschemaSubentryAttrInMatchingFilter(DN entryDN) |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com"); |
| | | |
| | | SearchFilter filter = |
| | | SearchFilter.createFilterFromString("(subschemaSubentry=cn=schema)"); |
| | | LinkedHashSet<String> attrList = new LinkedHashSet<String>(1); |
| | | attrList.add("subschemaSubentry"); |
| | | |
| | | 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(subschemaSubentryType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * no entries are returned when the subschemaSubentry 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 testSearchSubschemaSubentryAttrInNonMatchingFilter(DN entryDN) |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com"); |
| | | |
| | | SearchFilter filter = |
| | | SearchFilter.createFilterFromString("(subschemaSubentry=cn=foo)"); |
| | | LinkedHashSet<String> attrList = new LinkedHashSet<String>(1); |
| | | attrList.add("subschemaSubentry"); |
| | | |
| | | 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 subschemaSubentry 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 testSearchSubschemaSubentryAttrRealAttrsOnly(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("subschemaSubentry"); |
| | | |
| | | LinkedList<Control> requestControls = new LinkedList<Control>(); |
| | | requestControls.add(new Control(OID_REAL_ATTRS_ONLY, true)); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | InternalSearchOperation searchOperation = |
| | | new InternalSearchOperation(conn, conn.nextOperationID(), |
| | | conn.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(subschemaSubentryType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Performs an internal search to retrieve the specified entry, ensuring that |
| | | * the subschemaSubentry 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 testSearchSubschemaSubentryAttrVirtualAttrsOnly(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("subschemaSubentry"); |
| | | |
| | | LinkedList<Control> requestControls = new LinkedList<Control>(); |
| | | requestControls.add(new Control(OID_VIRTUAL_ATTRS_ONLY, true)); |
| | | |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | InternalSearchOperation searchOperation = |
| | | new InternalSearchOperation(conn, conn.nextOperationID(), |
| | | conn.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(subschemaSubentryType)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code isMultiValued} method. |
| | | */ |
| | | @Test() |
| | | public void testIsMultiValued() |
| | | { |
| | | SubschemaSubentryVirtualAttributeProvider provider = |
| | | new SubschemaSubentryVirtualAttributeProvider(); |
| | | assertFalse(provider.isMultiValued()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code getValues} method for an entry. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testGetValues() |
| | | throws Exception |
| | | { |
| | | SubschemaSubentryVirtualAttributeProvider provider = |
| | | new SubschemaSubentryVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(subschemaSubentryType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedHashSet<AttributeValue> values = provider.getValues(entry, rule); |
| | | assertNotNull(values); |
| | | assertEquals(values.size(), 1); |
| | | assertTrue(values.contains(new AttributeValue(subschemaSubentryType, |
| | | "cn=schema"))); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | | { |
| | | SubschemaSubentryVirtualAttributeProvider provider = |
| | | new SubschemaSubentryVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(subschemaSubentryType, 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 |
| | | { |
| | | SubschemaSubentryVirtualAttributeProvider provider = |
| | | new SubschemaSubentryVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(subschemaSubentryType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | assertTrue(provider.hasValue(entry, rule, |
| | | new AttributeValue(subschemaSubentryType, |
| | | "cn=schema"))); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | | { |
| | | SubschemaSubentryVirtualAttributeProvider provider = |
| | | new SubschemaSubentryVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(subschemaSubentryType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | assertFalse(provider.hasValue(entry, rule, |
| | | new AttributeValue(subschemaSubentryType, |
| | | "cn=not schema"))); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code hasAnyValue} method with an empty set of values. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testHasAnyValueEmptySet() |
| | | throws Exception |
| | | { |
| | | SubschemaSubentryVirtualAttributeProvider provider = |
| | | new SubschemaSubentryVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(subschemaSubentryType, 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 |
| | | { |
| | | SubschemaSubentryVirtualAttributeProvider provider = |
| | | new SubschemaSubentryVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(subschemaSubentryType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(1); |
| | | values.add(new AttributeValue(subschemaSubentryType, "cn=schema")); |
| | | |
| | | 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 |
| | | { |
| | | SubschemaSubentryVirtualAttributeProvider provider = |
| | | new SubschemaSubentryVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(subschemaSubentryType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(1); |
| | | values.add(new AttributeValue(subschemaSubentryType, "cn=not schema")); |
| | | |
| | | 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 |
| | | { |
| | | SubschemaSubentryVirtualAttributeProvider provider = |
| | | new SubschemaSubentryVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(subschemaSubentryType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(3); |
| | | values.add(new AttributeValue(subschemaSubentryType, "cn=schema")); |
| | | values.add(new AttributeValue(subschemaSubentryType, "cn=not schema")); |
| | | values.add(new AttributeValue(subschemaSubentryType, |
| | | "cn=not schema either")); |
| | | |
| | | 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 |
| | | { |
| | | SubschemaSubentryVirtualAttributeProvider provider = |
| | | new SubschemaSubentryVirtualAttributeProvider(); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | entry.processVirtualAttributes(); |
| | | |
| | | VirtualAttributeRule rule = |
| | | new VirtualAttributeRule(subschemaSubentryType, provider, |
| | | Collections.<DN>emptySet(), Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | VirtualAttributeCfgDefn.ConflictBehavior. |
| | | VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>(3); |
| | | values.add(new AttributeValue(subschemaSubentryType, "cn=not schema")); |
| | | values.add(new AttributeValue(subschemaSubentryType, |
| | | "cn=not schema either")); |
| | | values.add(new AttributeValue(subschemaSubentryType, |
| | | "cn=still not schema")); |
| | | |
| | | assertFalse(provider.hasAnyValue(entry, rule, values)); |
| | | } |
| | | } |
| | | |
| | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.RDN; |
| | | import org.opends.server.types.SearchScope; |
| | | |
| | | import static org.testng.Assert.*; |
| | | |
| | |
| | | sigs.add(new String[] { "isAncestorOf", |
| | | "boolean", |
| | | "org.opends.server.types.DN" }); |
| | | sigs.add(new String[] { "matchesBaseAndScope", |
| | | "boolean", |
| | | "org.opends.server.types.DN", |
| | | "org.opends.server.types.SearchScope" }); |
| | | sigs.add(new String[] { "equals", |
| | | "boolean", |
| | | "java.lang.Object" }); |
| | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code matchesBaseAndScope} method with valid DN strings. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testMatchesBaseAndScope() |
| | | throws Exception |
| | | { |
| | | assertTrue(new LazyDN("").matchesBaseAndScope(DN.nullDN(), |
| | | SearchScope.BASE_OBJECT)); |
| | | assertTrue(new LazyDN("dc=example,dc=com").matchesBaseAndScope( |
| | | DN.decode("dc=example,dc=com"), SearchScope.BASE_OBJECT)); |
| | | assertTrue(new LazyDN("ou=People,dc=example,dc=com").matchesBaseAndScope( |
| | | DN.decode("dc=example,dc=com"), SearchScope.WHOLE_SUBTREE)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code matchesBaseAndScope} method with an invalid DN string. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(expectedExceptions = { RuntimeException.class }) |
| | | public void testMatchesBaseandScopeInvalid() |
| | | throws Exception |
| | | { |
| | | new LazyDN("invalid").matchesBaseAndScope(DN.decode("dc=example,dc=com"), |
| | | SearchScope.WHOLE_SUBTREE); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code equals} method with valid DN strings. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | |
| | | assertTrue(checkChangelogQueueSize(CHANGELOG_QUEUE_SIZE)); |
| | | |
| | | // Create an Entry (add operation) that will be later used in the test. |
| | | Entry tmp = personEntry.duplicate(); |
| | | Entry tmp = personEntry.duplicate(false); |
| | | AddOperation addOp = new AddOperation(connection, |
| | | InternalClientConnection.nextOperationID(), InternalClientConnection |
| | | .nextMessageID(), null, tmp.getDN(), |
| | |
| | | */ |
| | | |
| | | // Create an Entry (add operation) that will be later used in the test. |
| | | Entry tmp = personEntry.duplicate(); |
| | | Entry tmp = personEntry.duplicate(false); |
| | | AddOperation addOp = new AddOperation(connection, |
| | | InternalClientConnection.nextOperationID(), InternalClientConnection |
| | | .nextMessageID(), null, tmp.getDN(), |
| | |
| | | while ((count> 0) && (found != exist)) |
| | | { |
| | | Thread.sleep(200); |
| | | |
| | | |
| | | found = DirectoryServer.entryExists(dn); |
| | | count--; |
| | | } |
| | | |
| | | |
| | | Lock lock = null; |
| | | for (int i=0; i < 3; i++) |
| | | { |
| | |
| | | break; |
| | | } |
| | | } |
| | | |
| | | |
| | | if (lock == null) |
| | | { |
| | | throw new Exception("could not lock entry " + dn); |
| | | } |
| | | |
| | | |
| | | try |
| | | { |
| | | Entry entry = DirectoryServer.getEntry(dn); |
| | | if (entry == null) |
| | | return null; |
| | | else |
| | | return entry.duplicate(); |
| | | return entry.duplicate(true); |
| | | } |
| | | finally |
| | | { |
| | |
| | | */ |
| | | |
| | | // Create an Entry (add operation) |
| | | Entry tmp = personEntry.duplicate(); |
| | | Entry tmp = personEntry.duplicate(false); |
| | | AddOperation addOp = new AddOperation(connection, |
| | | InternalClientConnection.nextOperationID(), InternalClientConnection |
| | | .nextMessageID(), null, tmp.getDN(), |
| 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.types; |
| | | |
| | | |
| | | |
| | | import java.util.Collections; |
| | | import java.util.LinkedHashSet; |
| | | |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.admin.std.meta. |
| | | VirtualAttributeCfgDefn.ConflictBehavior; |
| | | import org.opends.server.extensions.EntryDNVirtualAttributeProvider; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | |
| | | import static org.testng.Assert.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class provides a set of test cases for virtual attribute rules, which |
| | | * link a virtual attribute provider implementation with an attribute type and a |
| | | * set of criteria for identifying the entries with which that provider should |
| | | * be used. |
| | | */ |
| | | public class VirtualAttributeRuleTestCase |
| | | extends TypesTestCase |
| | | { |
| | | // The attribute type for the entryDN attribute. |
| | | private AttributeType entryDNType; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Ensures that the Directory Server is running. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @BeforeClass() |
| | | public void startServer() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.startServer(); |
| | | |
| | | entryDNType = DirectoryConfig.getAttributeType("entrydn", false); |
| | | assertNotNull(entryDNType); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Retrieves a set of virtual attribute rules that may be used for testing |
| | | * purposes. The return data will also include a Boolean value indicating |
| | | * whether the rule would apply to a minimal "o=test" entry. |
| | | * |
| | | * @return A set of virtual attribute rules that may be used for testing |
| | | * purposes. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @DataProvider(name = "testRules") |
| | | public Object[][] getVirtualAttributeRules() |
| | | throws Exception |
| | | { |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | LinkedHashSet<DN> dnSet1 = new LinkedHashSet<DN>(1); |
| | | dnSet1.add(DN.decode("o=test")); |
| | | |
| | | LinkedHashSet<DN> dnSet2 = new LinkedHashSet<DN>(1); |
| | | dnSet2.add(DN.decode("dc=example,dc=com")); |
| | | |
| | | LinkedHashSet<DN> dnSet3 = new LinkedHashSet<DN>(2); |
| | | dnSet3.add(DN.decode("o=test")); |
| | | dnSet3.add(DN.decode("dc=example,dc=com")); |
| | | |
| | | |
| | | LinkedHashSet<DN> groupSet1 = new LinkedHashSet<DN>(1); |
| | | groupSet1.add(DN.decode("cn=Test Group,o=test")); |
| | | |
| | | LinkedHashSet<DN> groupSet2 = new LinkedHashSet<DN>(1); |
| | | groupSet2.add(DN.decode("cn=Example Group,o=test")); |
| | | |
| | | LinkedHashSet<DN> groupSet3= new LinkedHashSet<DN>(2); |
| | | groupSet3.add(DN.decode("cn=Test Group,o=test")); |
| | | groupSet3.add(DN.decode("cn=Example Group,o=test")); |
| | | |
| | | |
| | | LinkedHashSet<SearchFilter> filterSet1 = new LinkedHashSet<SearchFilter>(1); |
| | | filterSet1.add(SearchFilter.createFilterFromString("(objectClass=*)")); |
| | | |
| | | LinkedHashSet<SearchFilter> filterSet2 = new LinkedHashSet<SearchFilter>(1); |
| | | filterSet2.add(SearchFilter.createFilterFromString("(o=test)")); |
| | | |
| | | LinkedHashSet<SearchFilter> filterSet3 = new LinkedHashSet<SearchFilter>(1); |
| | | filterSet3.add(SearchFilter.createFilterFromString("(foo=bar)")); |
| | | |
| | | LinkedHashSet<SearchFilter> filterSet4 = new LinkedHashSet<SearchFilter>(2); |
| | | filterSet4.add(SearchFilter.createFilterFromString("(o=test)")); |
| | | filterSet4.add(SearchFilter.createFilterFromString("(foo=bar)")); |
| | | |
| | | return new Object[][] |
| | | { |
| | | new Object[] |
| | | { |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), |
| | | Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | ConflictBehavior.VIRTUAL_OVERRIDES_REAL), |
| | | true |
| | | }, |
| | | |
| | | new Object[] |
| | | { |
| | | new VirtualAttributeRule(entryDNType, provider, dnSet1, |
| | | Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | ConflictBehavior.VIRTUAL_OVERRIDES_REAL), |
| | | true |
| | | }, |
| | | |
| | | new Object[] |
| | | { |
| | | new VirtualAttributeRule(entryDNType, provider, dnSet2, |
| | | Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | ConflictBehavior.VIRTUAL_OVERRIDES_REAL), |
| | | false |
| | | }, |
| | | |
| | | new Object[] |
| | | { |
| | | new VirtualAttributeRule(entryDNType, provider, dnSet3, |
| | | Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | ConflictBehavior.VIRTUAL_OVERRIDES_REAL), |
| | | true |
| | | }, |
| | | |
| | | new Object[] |
| | | { |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), groupSet1, |
| | | Collections.<SearchFilter>emptySet(), |
| | | ConflictBehavior.VIRTUAL_OVERRIDES_REAL), |
| | | true |
| | | }, |
| | | |
| | | new Object[] |
| | | { |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), groupSet2, |
| | | Collections.<SearchFilter>emptySet(), |
| | | ConflictBehavior.VIRTUAL_OVERRIDES_REAL), |
| | | false |
| | | }, |
| | | |
| | | new Object[] |
| | | { |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), groupSet3, |
| | | Collections.<SearchFilter>emptySet(), |
| | | ConflictBehavior.VIRTUAL_OVERRIDES_REAL), |
| | | true |
| | | }, |
| | | |
| | | new Object[] |
| | | { |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), |
| | | Collections.<DN>emptySet(), filterSet1, |
| | | ConflictBehavior.VIRTUAL_OVERRIDES_REAL), |
| | | true |
| | | }, |
| | | |
| | | new Object[] |
| | | { |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), |
| | | Collections.<DN>emptySet(), filterSet2, |
| | | ConflictBehavior.VIRTUAL_OVERRIDES_REAL), |
| | | true |
| | | }, |
| | | |
| | | new Object[] |
| | | { |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), |
| | | Collections.<DN>emptySet(), filterSet3, |
| | | ConflictBehavior.VIRTUAL_OVERRIDES_REAL), |
| | | false |
| | | }, |
| | | |
| | | new Object[] |
| | | { |
| | | new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), |
| | | Collections.<DN>emptySet(), filterSet4, |
| | | ConflictBehavior.VIRTUAL_OVERRIDES_REAL), |
| | | true |
| | | }, |
| | | }; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the various getter methods in the virtual attribute rule class. |
| | | * |
| | | * @param rule The rule for which to perform the test. |
| | | * @param appliesToEntry Indicates whether the provided rule applies to a |
| | | * minimal "o=test" entry. |
| | | */ |
| | | @Test(dataProvider = "testRules") |
| | | public void testGetters(VirtualAttributeRule rule, boolean appliesToEntry) |
| | | { |
| | | assertEquals(rule.getAttributeType(), entryDNType); |
| | | assertEquals(rule.getProvider().getClass().getName(), |
| | | EntryDNVirtualAttributeProvider.class.getName()); |
| | | assertNotNull(rule.getBaseDNs()); |
| | | assertNotNull(rule.getGroupDNs()); |
| | | assertNotNull(rule.getFilters()); |
| | | assertNotNull(rule.getConflictBehavior()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code appliesToEntry} method. |
| | | * |
| | | * @param rule The rule for which to perform the test. |
| | | * @param appliesToEntry Indicates whether the provided rule applies to a |
| | | * minimal "o=test" entry. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test(dataProvider = "testRules") |
| | | public void testAppliesToEntry(VirtualAttributeRule rule, |
| | | boolean appliesToEntry) |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.initializeTestBackend(true); |
| | | addGroups(); |
| | | assertEquals(rule.appliesToEntry( |
| | | DirectoryConfig.getEntry(DN.decode("o=test"))), |
| | | appliesToEntry); |
| | | removeGroups(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code toString} method. |
| | | * |
| | | * @param rule The rule for which to perform the test. |
| | | * @param appliesToEntry Indicates whether the provided rule applies to a |
| | | * minimal "o=test" entry. |
| | | */ |
| | | @Test(dataProvider = "testRules") |
| | | public void testToString(VirtualAttributeRule rule, boolean appliesToEntry) |
| | | { |
| | | String ruleString = rule.toString(); |
| | | assertNotNull(ruleString); |
| | | assertTrue(ruleString.length() > 0); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Adds a group to the server in which the "o=test" entry is a member. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void addGroups() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.addEntries( |
| | | "dn: cn=Test Group,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfUniqueNames", |
| | | "cn: Test Group", |
| | | "uniqueMember: o=test", |
| | | "", |
| | | "dn: cn=Example Group,o=test", |
| | | "objectClass: top", |
| | | "objectClass: groupOfUniqueNames", |
| | | "cn: Example Group", |
| | | "uniqueMember: dc=example,dc=com"); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Removes the test group from the server. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | private void removeGroups() |
| | | throws Exception |
| | | { |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | conn.processDelete(DN.decode("cn=Test Group,o=Test")); |
| | | conn.processDelete(DN.decode("cn=Example Group,o=Test")); |
| | | } |
| | | } |
| | | |
| 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.types; |
| | | |
| | | |
| | | |
| | | import java.util.Collections; |
| | | import java.util.LinkedHashSet; |
| | | |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.admin.std.meta. |
| | | VirtualAttributeCfgDefn.ConflictBehavior; |
| | | import org.opends.server.extensions.EntryDNVirtualAttributeProvider; |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | |
| | | import static org.testng.Assert.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class provides a set of test cases for virtual attributes. |
| | | */ |
| | | public class VirtualAttributeTestCase |
| | | extends TypesTestCase |
| | | { |
| | | // The attribute type for the entryDN attribute. |
| | | private AttributeType entryDNType; |
| | | |
| | | // The virtual attribute instance that will be used for all the testing. |
| | | private VirtualAttribute virtualAttribute; |
| | | |
| | | // The virutal attribute rule that will be used for the testing. |
| | | private VirtualAttributeRule virtualAttributeRule; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Ensures that the Directory Server is running. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @BeforeClass() |
| | | public void startServer() |
| | | throws Exception |
| | | { |
| | | TestCaseUtils.startServer(); |
| | | |
| | | entryDNType = DirectoryConfig.getAttributeType("entrydn", false); |
| | | assertNotNull(entryDNType); |
| | | |
| | | EntryDNVirtualAttributeProvider provider = |
| | | new EntryDNVirtualAttributeProvider(); |
| | | |
| | | virtualAttributeRule = new VirtualAttributeRule(entryDNType, provider, |
| | | Collections.<DN>emptySet(), |
| | | Collections.<DN>emptySet(), |
| | | Collections.<SearchFilter>emptySet(), |
| | | ConflictBehavior.VIRTUAL_OVERRIDES_REAL); |
| | | |
| | | Entry entry = TestCaseUtils.makeEntry( |
| | | "dn: o=test", |
| | | "objectClass: top", |
| | | "objectClass: organization", |
| | | "o: test"); |
| | | |
| | | virtualAttribute = new VirtualAttribute(entryDNType, entry, |
| | | virtualAttributeRule); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the various getter methods for virtual attributes. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testGetters() |
| | | throws Exception |
| | | { |
| | | assertNotNull(virtualAttribute.getEntry()); |
| | | assertEquals(virtualAttribute.getEntry().getDN(), |
| | | DN.decode("o=test")); |
| | | |
| | | assertEquals(virtualAttribute.getVirtualAttributeRule(), |
| | | virtualAttributeRule); |
| | | |
| | | assertTrue(virtualAttribute.isVirtual()); |
| | | assertTrue(virtualAttribute.duplicate(true).isVirtual()); |
| | | assertTrue(virtualAttribute.duplicate(false).isVirtual()); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the various methods that interact with the virtual values. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testValues() |
| | | throws Exception |
| | | { |
| | | LinkedHashSet<AttributeValue> values = virtualAttribute.getValues(); |
| | | assertEquals(values.size(), 1); |
| | | assertTrue(values.contains(new AttributeValue(entryDNType, "o=test"))); |
| | | |
| | | assertTrue(virtualAttribute.hasValue()); |
| | | |
| | | assertTrue(virtualAttribute.hasValue(new AttributeValue(entryDNType, |
| | | "o=test"))); |
| | | assertFalse(virtualAttribute.hasValue(new AttributeValue(entryDNType, |
| | | "o=not test"))); |
| | | |
| | | LinkedHashSet<AttributeValue> testValues = |
| | | new LinkedHashSet<AttributeValue>(); |
| | | testValues.add(new AttributeValue(entryDNType, "o=test")); |
| | | assertTrue(virtualAttribute.hasAllValues(testValues)); |
| | | assertTrue(virtualAttribute.hasAnyValue(testValues)); |
| | | |
| | | testValues.add(new AttributeValue(entryDNType, "o=not test")); |
| | | assertFalse(virtualAttribute.hasAllValues(testValues)); |
| | | assertTrue(virtualAttribute.hasAnyValue(testValues)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the various methods that apply to different kinds of matching. |
| | | * |
| | | * @throws Exception If an unexpected problem occurs. |
| | | */ |
| | | @Test() |
| | | public void testMatching() |
| | | throws Exception |
| | | { |
| | | assertEquals(virtualAttribute.matchesSubstring( |
| | | ByteStringFactory.create("o="), null, |
| | | ByteStringFactory.create("test")), |
| | | ConditionResult.UNDEFINED); |
| | | |
| | | AttributeValue assertionValue = new AttributeValue(entryDNType, "o=test"); |
| | | assertEquals(virtualAttribute.greaterThanOrEqualTo(assertionValue), |
| | | ConditionResult.UNDEFINED); |
| | | assertEquals(virtualAttribute.lessThanOrEqualTo(assertionValue), |
| | | ConditionResult.UNDEFINED); |
| | | assertEquals(virtualAttribute.approximatelyEqualTo(assertionValue), |
| | | ConditionResult.UNDEFINED); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Tests the {@code toString} method. |
| | | */ |
| | | @Test() |
| | | public void testToString() |
| | | { |
| | | String vattrString = virtualAttribute.toString(); |
| | | assertNotNull(vattrString); |
| | | assertTrue(vattrString.length() > 0); |
| | | } |
| | | } |
| | | |