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 2016-2023 Ping Identity Corporation
026 */
027package com.unboundid.directory.sdk.broker.api;
028
029import com.unboundid.directory.sdk.broker.config.StoreAdapterPluginConfig;
030import com.unboundid.directory.sdk.broker.internal.BrokerExtension;
031import com.unboundid.directory.sdk.broker.types.BrokerContext;
032import com.unboundid.directory.sdk.broker.types.StorePostCreateRequestContext;
033import com.unboundid.directory.sdk.broker.types.StorePostDeleteRequestContext;
034import com.unboundid.directory.sdk.broker.types.StorePostRetrieveRequestContext;
035import com.unboundid.directory.sdk.broker.types.StorePostSearchEntryContext;
036import com.unboundid.directory.sdk.broker.types.StorePostUpdateRequestContext;
037import com.unboundid.directory.sdk.broker.types.StorePreCreateRequestContext;
038import com.unboundid.directory.sdk.broker.types.StorePreDeleteRequestContext;
039import com.unboundid.directory.sdk.broker.types.StorePreRetrieveRequestContext;
040import com.unboundid.directory.sdk.broker.types.StorePreSearchRequestContext;
041import com.unboundid.directory.sdk.broker.types.StorePreUpdateRequestContext;
042import com.unboundid.directory.sdk.common.internal.Configurable;
043import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider;
044import com.unboundid.directory.sdk.common.internal.UnboundIDExtension;
045import com.unboundid.scim2.common.exceptions.ScimException;
046import com.unboundid.util.Extensible;
047import com.unboundid.util.ThreadSafety;
048import com.unboundid.util.ThreadSafetyLevel;
049import com.unboundid.util.args.ArgumentException;
050import com.unboundid.util.args.ArgumentParser;
051
052import java.util.Collections;
053import java.util.List;
054import java.util.Map;
055
056
057
058/**
059 * This class defines an API that must be implemented by extensions that need
060 * to intercept operations processed by a Store Adapter. The API has
061 * pre-request methods to intercept and make changes to store adapter requests
062 * before they are processed by the Store Adapter, and corresponding
063 * post-request methods to intercept and make changes to the results returned
064 * by the Store Adapter. All SCIM attributes in this API refer to native Store
065 * Adapter attributes, not attributes in the external client SCIM schema.
066 * <p>
067 * The Store Adapter Plugin is defined in the configuration and then referenced
068 * by a Store Adapter configuration object.
069 */
070@Extensible()
071@BrokerExtension
072@ThreadSafety(level= ThreadSafetyLevel.INTERFACE_THREADSAFE)
073public abstract class StoreAdapterPlugin implements UnboundIDExtension,
074    Configurable, ExampleUsageProvider
075{
076  /**
077   * Creates a new instance of this store adapter plugin.  All
078   * implementations must include a default constructor, but any
079   * initialization should generally be done in the
080   * {@link #initializeStoreAdapterPlugin} method.
081   */
082  public StoreAdapterPlugin()
083  {
084    // No implementation is required.
085  }
086
087  /**
088   * {@inheritDoc}
089   */
090  @Override
091  public abstract String getExtensionName();
092
093  /**
094   * {@inheritDoc}
095   */
096  @Override
097  public abstract String[] getExtensionDescription();
098
099  /**
100   * {@inheritDoc}
101   */
102  @Override
103  public Map<List<String>,String> getExamplesArgumentSets()
104  {
105    return Collections.emptyMap();
106  }
107
108  /**
109   * {@inheritDoc}
110   */
111  @Override
112  public void defineConfigArguments(final ArgumentParser parser)
113         throws ArgumentException
114  {
115    // No arguments will be allowed by default.
116  }
117
118  /**
119   * Initializes this store adapter plugin. Any initialization should be
120   * performed here. This method should generally store the
121   * {@link BrokerContext} in a class member so that it can be used elsewhere in
122   * the implementation.
123   * <p>
124   * The default implementation is empty.
125   *
126   * @param  serverContext  A handle to the server context for the server in
127   *                        which this extension is running. Extensions should
128   *                        typically store this in a class member.
129   * @param  config         The general configuration for this object.
130   * @param  parser         The argument parser which has been initialized from
131   *                        the configuration for this store adapter plugin.
132   * @throws Exception      If a problem occurs while initializing this store
133   *                        adapter plugin.
134   */
135  public void initializeStoreAdapterPlugin(
136      final BrokerContext serverContext,
137      final StoreAdapterPluginConfig config,
138      final ArgumentParser parser)
139      throws Exception
140  {
141    // No initialization will be performed by default.
142  }
143
144  /**
145   * This hook is called when the store adapter plugin is disabled or the
146   * PingAuthorize Server shuts down. Any clean-up of this store adapter plugin
147   * should be performed here.
148   * <p>
149   * The default implementation is empty.
150   */
151  public void finalizeStoreAdapterPlugin()
152  {
153    // No finalization will be performed by default.
154  }
155
156  /**
157   * This method is called before an entry is created in the native data store.
158   *
159   * @param context The store adapter request context.
160   * @throws ScimException If thrown, the operation will be aborted and a
161   *                       corresponding SCIM ErrorResponse will be returned to
162   *                       the client.
163   */
164  public void preCreate(final StorePreCreateRequestContext context)
165      throws ScimException
166  {
167    // No implementation is required by default.
168  }
169
170  /**
171   * This method is called after an entry is created in the native data store.
172   * This method will not be called if the create fails.
173   *
174   * @param context The store adapter request context.
175   * @throws ScimException If thrown, a corresponding SCIM ErrorResponse will be
176   *                       returned to the client. No attempt is made to roll
177   *                       back the committed create operation.
178   */
179  public void postCreate(final StorePostCreateRequestContext context)
180      throws ScimException
181  {
182    // No implementation is required by default.
183  }
184
185  /**
186   * This method is called before an entry is retrieved from the native data
187   * store in the following cases:
188   * <UL>
189   *   <LI>
190   *     To fetch an entry for a SCIM retrieve operation.
191   *   </LI>
192   *   <LI>
193   *     To fetch an entry from a secondary store adapter for each primary store
194   *     adapter entry obtained during a SCIM search.
195   *   </LI>
196   *   <LI>
197   *     To fetch an entry from the primary store adapter for each secondary
198   *     store adapter entry obtained when a SCIM search filter is processed
199   *     by a secondary store adapter.
200   *   </LI>
201   * </UL>
202   *
203   * @param context The store adapter request context.
204   * @throws ScimException If thrown, the operation will be aborted and a
205   *                       corresponding SCIM ErrorResponse will be returned to
206   *                       the client.
207   */
208  public void preRetrieve(final StorePreRetrieveRequestContext context)
209      throws ScimException
210  {
211    // No implementation is required by default.
212  }
213
214  /**
215   * This method is called after an entry is retrieved from the native data
216   * store.
217   * This method will not be called if the retrieve fails.
218   *
219   * @param context The store adapter request context.
220   * @throws ScimException If thrown, a corresponding SCIM ErrorResponse will be
221   *                       returned to the client.
222   */
223  public void postRetrieve(final StorePostRetrieveRequestContext context)
224      throws ScimException
225  {
226    // No implementation is required by default.
227  }
228
229  /**
230   * This method is called before an entry is updated in the native data
231   * store.
232   *
233   * @param context The store adapter request context.
234   * @throws ScimException If thrown, the operation will be aborted and a
235   *                       corresponding SCIM ErrorResponse will be returned to
236   *                       the client.
237   */
238  public void preUpdate(final StorePreUpdateRequestContext context)
239      throws ScimException
240  {
241    // No implementation is required by default.
242  }
243
244  /**
245   * This method is called after an entry is updated in the native data
246   * store.
247   * This method will not be called if the update fails.
248   *
249   * @param context The store adapter request context.
250   * @throws ScimException If thrown, a corresponding SCIM ErrorResponse will be
251   *                       returned to the client. No attempt is made to roll
252   *                       back the committed update operation.
253   */
254  public void postUpdate(final StorePostUpdateRequestContext context)
255      throws ScimException
256  {
257    // No implementation is required by default.
258  }
259
260  /**
261   * This method is called before an entry is deleted in the native data
262   * store.
263   *
264   * @param context The store adapter request context.
265   * @throws ScimException If thrown, the operation will be aborted and a
266   *                       corresponding SCIM ErrorResponse will be returned to
267   *                       the client.
268   */
269  public void preDelete(final StorePreDeleteRequestContext context)
270      throws ScimException
271  {
272    // No implementation is required by default.
273  }
274
275  /**
276   * This method is called after an entry is deleted in the native data
277   * store.
278   * This method will not be called if the delete fails.
279   *
280   * @param context The store adapter request context.
281   * @throws ScimException If thrown, a corresponding SCIM ErrorResponse will be
282   *                       returned to the client. No attempt is made to roll
283   *                       back the committed delete operation.
284   */
285  public void postDelete(final StorePostDeleteRequestContext context)
286      throws ScimException
287  {
288    // No implementation is required by default.
289  }
290
291  /**
292   * This method is called before searching for entries in the native data
293   * store.
294   * <p>
295   * Note that the contract for store adapter searches allows the store adapter
296   * to return a superset of entries matching the original search filter. The
297   * results from the store adapter are subsequently filtered by the
298   * PingAuthorize Server.
299   *
300   * @param context The store adapter request context.
301   * @throws ScimException If thrown, the operation will be aborted and a
302   *                       corresponding SCIM ErrorResponse will be returned to
303   *                       the client.
304   */
305  public void preSearch(final StorePreSearchRequestContext context)
306      throws ScimException
307  {
308    // No implementation is required by default.
309  }
310
311  /**
312   * This method is called for each entry found during a search in the native
313   * data store.
314   * This method will not be called if the search fails.
315   * <p>
316   * Note that the contract for store adapter searches allows the store adapter
317   * to return a superset of entries matching the original search filter. The
318   * results from the store adapter are subsequently filtered by the
319   * PingAuthorize Server.
320   *
321   * @param context The store adapter request context.
322   */
323  public void postSearchEntry(final StorePostSearchEntryContext context)
324  {
325    // No implementation is required by default.
326  }
327}