All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.unboundid.directory.sdk.sync.scripting.ScriptedJDBCSyncDestination Maven / Gradle / Ivy

Go to download

The UnboundID Server SDK is a library that may be used to develop various types of extensions to Ping Identity server products, including the PingDirectory Server, PingDirectoryProxy Server, PingDataSync Server, PingDataMetrics Server, and PingAuthorize Server.

The newest version!
/*
 * 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 2010-2024 Ping Identity Corporation
 */
package com.unboundid.directory.sdk.sync.scripting;

import java.sql.SQLException;
import java.util.List;

import com.unboundid.directory.sdk.common.internal.Configurable;
import com.unboundid.directory.sdk.sync.config.JDBCSyncDestinationConfig;
import com.unboundid.directory.sdk.sync.internal.SynchronizationServerExtension;
import com.unboundid.directory.sdk.sync.types.SyncOperation;
import com.unboundid.directory.sdk.sync.types.SyncServerContext;
import com.unboundid.directory.sdk.sync.types.TransactionContext;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.Modification;
import com.unboundid.util.Extensible;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;
import com.unboundid.util.args.ArgumentException;
import com.unboundid.util.args.ArgumentParser;

/**
 * This class defines an API that must be implemented by scripted extensions
 * in order to synchronize data into a relational database. Since the UnboundID
 * ${SYNC_SERVER_BASE_NAME} is LDAP-centric,
 * this API allows you to take LDAP entries and split them out into
 * database content and make the appropriate updates. The lifecycle of a sync
 * operation is as follows:
 * 
    *
  1. Detect change at the synchronization source
  2. *
  3. Fetch full source entry
  4. *
  5. Perform any mappings and compute the equivalent destination entry
  6. *
  7. Fetch full destination entry
  8. *
  9. Diff the computed destination entry and actual destination entry
  10. *
  11. Apply the minimal set of changes at the destination to bring it in sync *
  12. *
* This implies that the {@link #fetchEntry(TransactionContext, Entry, * SyncOperation)} method will * always be called once prior to any of the other methods in this class. *

* In several places a {@link TransactionContext} is provided, which allows * controlled access to the target database. By default, methods in this class * are always provided with a fresh connection (i.e. a new transaction), and the * ${SYNC_SERVER_BASE_NAME} will always commit or rollback the transaction * automatically, depending on whether the method returned normally or threw an * exception. Implementers may optionally perform their own transaction * management within these methods if necessary. *

* Several of these methods throw {@link SQLException}, which should be used in * the case of any database access error. For other types of errors, runtime * exceptions may be used (IllegalStateException, NullPointerException, etc.). * The ${SYNC_SERVER_BASE_NAME} will automatically retry operations that fail, * up to a configurable amount of attempts. The exception to this rule is if a * SQLException is thrown with a SQL state string beginning with "08"; this * indicates a connection error, and in this case the operation is retried * indefinitely. *
*

Configuring Groovy-Scripted JDBC Sync Destinations

* In order to configure a scripted JDBC sync destination based on this API and * written in the Groovy scripting language, use a command like: *
 *      dsconfig create-sync-destination \
 *           --destination-name "{destination-name}" \
 *           --type groovy-scripted-jdbc \
 *           --set "server:{server-name}" \
 *           --set "script-class:{class-name}" \
 *           --set "script-argument:{name=value}"
 * 
* where "{destination-name}" is the name to use for the JDBC sync * destination instance, "{server-name}" is the name of the JDBC external * server that will be used as the sync destination, "{class-name}" is * the fully-qualified name of the Groovy class written using this API, and * "{name=value}" represents name-value pairs for any arguments to * provide to the JDBC sync destination. If multiple arguments should be * provided to the JDBC sync destination, then the * "--set script-argument:{name=value}" option should be * provided multiple times. */ @Extensible() @SynchronizationServerExtension(appliesToLocalContent=false, appliesToSynchronizedContent=true) public abstract class ScriptedJDBCSyncDestination implements Configurable { /** * {@inheritDoc} */ public void defineConfigArguments(final ArgumentParser parser) throws ArgumentException { // No arguments will be allowed by default. } /** * This hook is called when a Sync Pipe first starts up, or when the Resync * process first starts up. Any initialization should be performed here. *

* A {@link TransactionContext} is provided, which allows * controlled access to the target database. The context will contain a fresh * fresh connection (i.e. a new transaction), and the ${SYNC_SERVER_BASE_NAME} * will always commit or rollback the transaction automatically, depending on * whether this method returns normally or throws an exception. Implementers * may optionally perform their own transaction management within this method * if necessary. *

* The default implementation is empty. * * @param ctx * a TransactionContext which provides a valid JDBC connection to the * database. * @param serverContext A handle to the server context for the server in * which this extension is running. * @param config The general configuration for this sync destination. * @param parser The argument parser which has been initialized from * the configuration for this JDBC sync destination. */ @ThreadSafety(level = ThreadSafetyLevel.METHOD_NOT_THREADSAFE) public void initializeJDBCSyncDestination( final TransactionContext ctx, final SyncServerContext serverContext, final JDBCSyncDestinationConfig config, final ArgumentParser parser) { // No initialization will be performed by default. } /** * This hook is called when a Sync Pipe shuts down, or when the Resync process * shuts down. Any clean-up should be performed here. *

* A {@link TransactionContext} is provided, which allows * controlled access to the target database. The context will contain a fresh * fresh connection (i.e. a new transaction), and the ${SYNC_SERVER_BASE_NAME} * will always commit or rollback the transaction automatically, depending on * whether this method returns normally or throws an exception. Implementers * may optionally perform their own transaction management within this method * if necessary. *

* The default implementation is empty. * * @param ctx * a TransactionContext which provides a valid JDBC connection to the * database. */ @ThreadSafety(level = ThreadSafetyLevel.METHOD_NOT_THREADSAFE) public void finalizeJDBCSyncDestination( final TransactionContext ctx) { //no implementation required } /** * Return a full destination entry (in LDAP form) from the database, * corresponding to the source {@link Entry} that is passed in. This * method should perform any queries necessary to gather the latest values for * all the attributes to be synchronized and return them in an Entry. *

* Note that the if the source entry was renamed (see * {@link SyncOperation#isModifyDN}), the destEntryMappedFromSrc * will have the new DN; the old DN can be obtained by calling * {@link SyncOperation#getDestinationEntryBeforeChange()} and getting the DN * from there. This method should return the entry in its existing form * (i.e. with the old DN, before it is changed). *

* A {@link TransactionContext} is provided, which allows * controlled access to the target database. The context will contain a fresh * fresh connection (i.e. a new transaction), and the ${SYNC_SERVER_BASE_NAME} * will always commit or rollback the transaction automatically, depending on * whether this method returns normally or throws an exception. Implementers * may optionally perform their own transaction management within this method * if necessary. *

* This method must be thread safe, as it will be called repeatedly and * concurrently by each of the Sync Pipe worker threads as they process * entries. * * @param ctx * a TransactionContext which provides a valid JDBC connection to the * database. * @param destEntryMappedFromSrc * the LDAP entry which corresponds to the database * "entry" to fetch * @param operation * the sync operation for this change * @return a full LDAP Entry, or null if no such entry exists. * @throws SQLException * if there is an error fetching the entry */ @ThreadSafety(level = ThreadSafetyLevel.METHOD_THREADSAFE) public abstract Entry fetchEntry(final TransactionContext ctx, final Entry destEntryMappedFromSrc, final SyncOperation operation) throws SQLException; /** * Creates a full database "entry", corresponding to the LDAP * {@link Entry} that is passed in. This method should perform any inserts and * updates necessary to make sure the entry is fully created on the database. *

* A {@link TransactionContext} is provided, which allows * controlled access to the target database. The context will contain a fresh * fresh connection (i.e. a new transaction), and the ${SYNC_SERVER_BASE_NAME} * will always commit or rollback the transaction automatically, depending on * whether this method returns normally or throws an exception. Implementers * may optionally perform their own transaction management within this method * if necessary. *

* This method must be thread safe, as it will be called repeatedly and * concurrently by the Sync Pipe worker threads as they process CREATE * operations. * * @param ctx * a TransactionContext which provides a valid JDBC connection to the * database. * @param entryToCreate * the LDAP entry which corresponds to the database "entry" to create * @param operation * the sync operation for this change * @throws SQLException * if there is an error creating the entry */ @ThreadSafety(level = ThreadSafetyLevel.METHOD_THREADSAFE) public abstract void createEntry(final TransactionContext ctx, final Entry entryToCreate, final SyncOperation operation) throws SQLException; /** * Modify an "entry" in the database, corresponding to the LDAP * {@link Entry} that is passed in. This method may perform multiple updates * (including inserting or deleting rows) in order to fully synchronize the * entire entry on the database. *

* Note that the if the source entry was renamed (see * {@link SyncOperation#isModifyDN}), the * fetchedDestEntry will have the old DN; the new DN can * be obtained by calling * {@link SyncOperation#getDestinationEntryAfterChange()} and getting the DN * from there. *

* A {@link TransactionContext} is provided, which allows * controlled access to the target database. The context will contain a fresh * fresh connection (i.e. a new transaction), and the ${SYNC_SERVER_BASE_NAME} * will always commit or rollback the transaction automatically, depending on * whether this method returns normally or throws an exception. Implementers * may optionally perform their own transaction management within this method * if necessary. *

* This method must be thread safe, as it will be called repeatedly and * concurrently by the Sync Pipe worker threads as they process MODIFY * operations. * * @param ctx * a TransactionContext which provides a valid JDBC connection to the * database. * @param fetchedDestEntry * the LDAP entry which corresponds to the database "entry" to modify * @param modsToApply * a list of Modification objects which should be applied * @param operation * the sync operation for this change * @throws SQLException * if there is an error modifying the entry */ @ThreadSafety(level = ThreadSafetyLevel.METHOD_THREADSAFE) public abstract void modifyEntry(final TransactionContext ctx, final Entry fetchedDestEntry, final List modsToApply, final SyncOperation operation) throws SQLException; /** * Delete a full "entry" from the database, corresponding to the LDAP * {@link Entry} that is passed in. This method may perform multiple deletes * or updates if necessary to fully delete the entry from the database. *

* A {@link TransactionContext} is provided, which allows * controlled access to the target database. The context will contain a fresh * fresh connection (i.e. a new transaction), and the ${SYNC_SERVER_BASE_NAME} * will always commit or rollback the transaction automatically, depending on * whether this method returns normally or throws an exception. Implementers * may optionally perform their own transaction management within this method * if necessary. *

* This method must be thread safe, as it will be called repeatedly and * concurrently by the Sync Pipe worker threads as they process DELETE * operations. * * @param ctx * a TransactionContext which provides a valid JDBC connection to the * database. * @param fetchedDestEntry * the LDAP entry which corresponds to the database "entry" to delete * @param operation * the sync operation for this change * @throws SQLException * if there is an error deleting the entry */ @ThreadSafety(level = ThreadSafetyLevel.METHOD_THREADSAFE) public abstract void deleteEntry(final TransactionContext ctx, final Entry fetchedDestEntry, final SyncOperation operation) throws SQLException; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy