/* * 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 * docs/licenses/cddl.txt * or http://www.opensource.org/licenses/cddl1.php. * 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 * docs/licenses/cddl.txt. 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 2016-2023 Ping Identity Corporation */ package com.unboundid.directory.sdk.examples; import com.unboundid.directory.sdk.common.operation.SearchRequest; import com.unboundid.directory.sdk.common.operation.UpdatableSearchResult; import com.unboundid.directory.sdk.common.schema.AttributeSyntax; import com.unboundid.directory.sdk.common.schema.AttributeType; import com.unboundid.directory.sdk.common.schema.Schema; import com.unboundid.directory.sdk.common.types.ActiveSearchOperationContext; import com.unboundid.directory.sdk.common.types.UpdatableEntry; import com.unboundid.directory.sdk.ds.api.Plugin; import com.unboundid.directory.sdk.ds.config.PluginConfig; import com.unboundid.directory.sdk.ds.types.DirectoryServerContext; import com.unboundid.directory.sdk.ds.types.SearchEntryPluginResult; import com.unboundid.ldap.sdk.Attribute; import com.unboundid.ldap.sdk.Control; import com.unboundid.ldap.sdk.LDAPException; import com.unboundid.ldap.sdk.ResultCode; import com.unboundid.util.args.ArgumentException; import com.unboundid.util.args.ArgumentParser; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; /** * This class provides a simple example of a plugin which will change the values * of distinguished name syntax based attributes to be lowercased. LDAP DNs * are case agnostic and no application should match DNs in a case-sensitive * manner. However, some noncompliant applications may benefit from a plugin * like this example. */ public final class ExampleLowercaseDnAttrsPlugin extends Plugin { // The server context for the server in which this extension is running. private DirectoryServerContext serverContext; // A set of attribute syntax related to DNs private final Set<AttributeSyntax> dnAttributeSyntaxSet = new HashSet<AttributeSyntax>(2); // The OIDs for DN based syntax private static final String[] DN_SYNTAX_OIDS = { "1.3.6.1.4.1.1466.115.121.1.12", // DN (RFC 4517) "1.3.6.1.4.1.1466.115.121.1.34" // Name And Optional UID (RFC 4517) }; /** * Creates a new instance of this plugin. All plugin implementations must * include a default constructor, but any initialization should generally be * done in the {@code initializePlugin} method. */ public ExampleLowercaseDnAttrsPlugin() { // No implementation required. } /** * Retrieves a human-readable name for this extension. * * @return A human-readable name for this extension. */ @Override() public String getExtensionName() { return "Example Lowercase DNs Plugin"; } /** * Retrieves a human-readable description for this extension. Each element * of the array that is returned will be considered a separate paragraph in * generated documentation. * * @return A human-readable description for this extension, or {@code null} * or an empty array if no description should be available. */ @Override() public String[] getExtensionDescription() { return new String[] { "This plugin serves as an example that may be used to demonstrate " + "the process for creating a third-party plugin. It will attempt to " + "modify all values for attributes using DN based syntax " + Arrays.toString(DN_SYNTAX_OIDS) + " returned in search result entries " + "to use a lowercase notation. LDAP DNs are case agnostic and no " + "application should match DNs in a case-sensitive manner, however " + "some noncompliant applications may benefit from a plugin like this " + "example. Note that because this plugin is primarily an example, it " + "does not attempt to be as thorough as might be necessary to handle " + "DNs with special or escaped characters. The code is also optimized " + "for clarity and not performance." }; } /** * Updates the provided argument parser to define any configuration arguments * which may be used by this plugin. The argument parser may also be updated * to define relationships between arguments (e.g., to specify required, * exclusive, or dependent argument sets). * * @param parser The argument parser to be updated with the configuration * arguments which may be used by this plugin. * * @throws ArgumentException If a problem is encountered while updating the * provided argument parser. */ @Override() public void defineConfigArguments(final ArgumentParser parser) throws ArgumentException { // No implementation required. } /** * Initializes this plugin. * * @param serverContext A handle to the server context for the server in * which this extension is running. * @param config The general configuration for this plugin. * @param parser The argument parser which has been initialized from * the configuration for this plugin. * * @throws LDAPException If a problem occurs while initializing this plugin. */ @Override() public void initializePlugin(final DirectoryServerContext serverContext, final PluginConfig config, final ArgumentParser parser) throws LDAPException { serverContext.debugInfo("Beginning plugin initialization"); this.serverContext = serverContext; final Schema schema = serverContext.getSchema(); for (String oid : DN_SYNTAX_OIDS) { AttributeSyntax syntax = schema.getAttributeSyntax(oid); if (syntax == null) { throw new LDAPException(ResultCode.UNDEFINED_ATTRIBUTE_TYPE, "DN based syntax (" + oid + ") is not defined!"); } dnAttributeSyntaxSet.add(syntax); } } /** * Looks at the entry to find any attributes with a DN syntax, and replaces * the values of those attributes with lowercased equivalents. * * @param operationContext The context for the search operation. * @param request The search request being processed. * @param result The result that will be returned to the client if * the plugin result indicates that processing on * the operation should be interrupted. It may be * altered if desired. * @param entry The entry to be returned to the client. It may * be altered if desired. * @param controls The set of controls to be included with the * entry. It may be altered if desired. * * @return Information about the result of the plugin processing. */ @Override() public SearchEntryPluginResult doSearchEntry( final ActiveSearchOperationContext operationContext, final SearchRequest request, final UpdatableSearchResult result, final UpdatableEntry entry, final List<Control> controls) { final Schema schema = serverContext.getSchema(); List<Attribute> replacementAttrs = new ArrayList<Attribute>(); for (Attribute attr : entry.getAttributes()) { AttributeType attrType = schema.getAttributeType(attr.getName(), false); if (attrType != null && dnAttributeSyntaxSet.contains(attrType.getSyntax())) { List<String> newValues = new ArrayList<String>(); for (String attrValue : attr.getValues()) { newValues.add(attrValue.toLowerCase()); } replacementAttrs.add(new Attribute(attr.getName(), newValues)); } } if (! replacementAttrs.isEmpty()) { for (Attribute attr : replacementAttrs) { entry.removeAttribute(attr.getName()); entry.addAttribute(attr); } } return SearchEntryPluginResult.SUCCESS; } }