001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * docs/licenses/cddl.txt
011 * or http://www.opensource.org/licenses/cddl1.php.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * docs/licenses/cddl.txt.  If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 *      Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 *      Portions Copyright 2012-2023 Ping Identity Corporation
026 */
027package com.unboundid.directory.sdk.ds.scripting;
028
029
030
031import java.util.List;
032
033import com.unboundid.directory.sdk.common.internal.Reconfigurable;
034import com.unboundid.directory.sdk.common.types.Entry;
035import com.unboundid.directory.sdk.ds.config.UncachedAttributeCriteriaConfig;
036import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension;
037import com.unboundid.directory.sdk.ds.types.DirectoryServerContext;
038import com.unboundid.ldap.sdk.Attribute;
039import com.unboundid.ldap.sdk.LDAPException;
040import com.unboundid.ldap.sdk.ResultCode;
041import com.unboundid.util.Extensible;
042import com.unboundid.util.ThreadSafety;
043import com.unboundid.util.ThreadSafetyLevel;
044import com.unboundid.util.args.ArgumentException;
045import com.unboundid.util.args.ArgumentParser;
046
047
048
049/**
050 * This class defines an API that must be implemented by scripted extensions
051 * which have the ability to determine which attributes should be stored in the
052 * uncached-id2entry database of a local DB backend, while the remainder of the
053 * entry is stored in the id2entry database.  In environments with data sets too
054 * large to fit in available memory, and in which entries have a significant
055 * amount of space consumed by attributes which are not frequently accessed,
056 * this can help the server better use the memory it does have for attributes
057 * that are more likely to be accessed.
058 * <BR>
059 * <H2>Configuring Groovy-Scripted Uncached Attribute Criteria</H2>
060 * In order to configure a scripted uncached attribute criteria object based on
061 * this API and written in the Groovy scripting language, use a command like:
062 * <PRE>
063 *      dsconfig create-uncached-attribute-criteria \
064 *           --criteria-name "<I>{criteria-name}</I>" \
065 *           --type groovy-scripted \
066 *           --set enabled:true \
067 *           --set "script-class:<I>{class-name}</I>" \
068 *           --set "script-argument:<I>{name=value}</I>"
069 * </PRE>
070 * where "<I>{handler-name}</I>" is the name to use for the uncached attribute
071 * criteria instance, "<I>{class-name}</I>" is the fully-qualified name of the
072 * Groovy class written using this API, and "<I>{name=value}</I>" represents
073 * name-value pairs for any arguments to provide to the uncached attribute
074 * criteria object.  If multiple arguments should be provided to the uncached
075 * attribute criteria, then the
076 * "<CODE>--set script-argument:<I>{name=value}</I></CODE>"
077 * option should be provided multiple times.
078 *
079 * @see  com.unboundid.directory.sdk.ds.api.UncachedAttributeCriteria
080 */
081@Extensible()
082@DirectoryServerExtension()
083@ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
084public abstract class ScriptedUncachedAttributeCriteria
085       implements Reconfigurable<UncachedAttributeCriteriaConfig>
086{
087  /**
088   * Creates a new instance of this uncached attribute criteria.  All uncached
089   * attribute criteria implementations must include a default constructor, but
090   * any initialization should generally be done in the
091   * {@code initializeUncachedAttributeCriteria} method.
092   */
093  public ScriptedUncachedAttributeCriteria()
094  {
095    // No implementation is required.
096  }
097
098
099
100  /**
101   * {@inheritDoc}
102   */
103  public void defineConfigArguments(final ArgumentParser parser)
104         throws ArgumentException
105  {
106    // No arguments will be allowed by default.
107  }
108
109
110
111  /**
112   * Initializes this uncached attribute criteria.
113   *
114   * @param  serverContext  A handle to the server context for the server in
115   *                        which this extension is running.
116   * @param  config         The general configuration for this uncached
117   *                        attribute criteria.
118   * @param  parser         The argument parser which has been initialized from
119   *                        the configuration for this uncached attribute
120   *                        criteria.
121   *
122   * @throws  LDAPException  If a problem occurs while initializing this
123   *                         uncached attribute criteria.
124   */
125  public void initializeUncachedAttributeCriteria(
126                   final DirectoryServerContext serverContext,
127                   final UncachedAttributeCriteriaConfig config,
128                   final ArgumentParser parser)
129         throws LDAPException
130  {
131    // No initialization will be performed by default.
132  }
133
134
135
136  /**
137   * {@inheritDoc}
138   */
139  public boolean isConfigurationAcceptable(
140                      final UncachedAttributeCriteriaConfig config,
141                      final ArgumentParser parser,
142                      final List<String> unacceptableReasons)
143  {
144    // No extended validation will be performed.
145    return true;
146  }
147
148
149
150  /**
151   * {@inheritDoc}
152   */
153  public ResultCode applyConfiguration(
154                         final UncachedAttributeCriteriaConfig config,
155                         final ArgumentParser parser,
156                         final List<String> adminActionsRequired,
157                         final List<String> messages)
158  {
159    // By default, no configuration changes will be applied.  If there are any
160    // arguments, then add an admin action message indicating that the extension
161    // needs to be restarted for any changes to take effect.
162    if (! parser.getNamedArguments().isEmpty())
163    {
164      adminActionsRequired.add(
165           "No configuration change has actually been applied.  The new " +
166                "configuration will not take effect until this uncached " +
167                "attribute criteria is disabled and re-enabled or until the " +
168                "server is restarted.");
169    }
170
171    return ResultCode.SUCCESS;
172  }
173
174
175
176  /**
177   * Performs any cleanup which may be necessary when this uncached attribute
178   * criteria instance is to be taken out of service.
179   */
180  public void finalizeUncachedAttributeCriteria()
181  {
182    // No implementation is required.
183  }
184
185
186
187  /**
188   * Indicates whether the provided attribute should be written into the
189   * uncached-id2entry database rather than into id2entry.
190   *
191   * @param  attribute  A read-only representation of the attribute for which to
192   *                    make the determination.
193   * @param  entry      A read-only representation of the full entry to be
194   *                    encoded.
195   *
196   * @return  {@code true} if the attribute should be written into the
197   *          uncached-id2entry database, or {@code false} if it should be
198   *          written into the id2entry database.
199   */
200  public abstract boolean shouldBeUncached(final Attribute attribute,
201                                           final Entry entry);
202}