com.unboundid.directory.sdk.sync.api.SyncPipePlugin Maven / Gradle / Ivy
Show all versions of server-sdk Show documentation
/*
* 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.api;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider;
import com.unboundid.directory.sdk.common.internal.Reconfigurable;
import com.unboundid.directory.sdk.common.internal.UnboundIDExtension;
import com.unboundid.directory.sdk.sync.config.SyncPipePluginConfig;
import com.unboundid.directory.sdk.sync.internal.SynchronizationServerExtension;
import com.unboundid.directory.sdk.sync.types.PostStepResult;
import com.unboundid.directory.sdk.sync.types.PreStepResult;
import com.unboundid.directory.sdk.sync.types.SyncOperation;
import com.unboundid.directory.sdk.sync.types.SyncServerContext;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.ResultCode;
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 extensions that
* perform processing on synchronization operations within the Sync Pipe. These
* extensions may be used to
*
* - Filter out certain changes from being synchronized.
* - Add and remove attributes that should be synchronized with the
* destination independent of whether they changed at the source or
* not.
* - Manipulate the changes that are synchronized to ignore certain
* modified attributes or change the representation of modified
* attributes.
* - Skip certain steps in Sync Pipe processing, e.g. attribute
* and DN mapping.
*
* Most plugins will need to override the {@code postMapping} method but not
* the {@code preMapping} method. These extensions do not have access to the
* Sync Source or Sync Destination.
*
* Configuring Sync Pipe Plugins
* In order to configure a sync pipe plugin created using this API, use a
* command like:
*
* dsconfig create-sync-pipe-plugin \
* --plugin-name "{plugin-name}" \
* --type third-party \
* --set "extension-class:{class-name}" \
* --set "extension-argument:{name=value}"
*
* where "{plugin-name}" is the name to use for the sync pipe plugin
* instance, "{class-name}" is the fully-qualified name of the Java class
* that extends {@code com.unboundid.directory.sdk.sync.api.SyncPipePlugin},
* and "{name=value}" represents name-value pairs for any arguments to
* provide to the sync pipe plugin. If multiple arguments should be provided to
* the sync pipe plugin, then the
* "--set extension-argument:{name=value}
" option should be
* provided multiple times.
*
* @see com.unboundid.directory.sdk.sync.scripting.ScriptedSyncPipePlugin
*/
@Extensible()
@SynchronizationServerExtension(appliesToLocalContent=false,
appliesToSynchronizedContent=true)
@ThreadSafety(level= ThreadSafetyLevel.INTERFACE_THREADSAFE)
public abstract class SyncPipePlugin
implements UnboundIDExtension, Reconfigurable,
ExampleUsageProvider
{
/**
* Creates a new instance of this sync pipe plugin. All sync pipe plugin
* implementations must include a default constructor, but any
* initialization should generally be done in the
* {@code initializeSyncPipePlugin} method.
*/
public SyncPipePlugin()
{
// No implementation is required.
}
/**
* {@inheritDoc}
*/
public abstract String getExtensionName();
/**
* {@inheritDoc}
*/
public abstract String[] getExtensionDescription();
/**
* {@inheritDoc}
*/
public void defineConfigArguments(final ArgumentParser parser)
throws ArgumentException
{
// No arguments will be allowed by default.
}
/**
* Initializes this sync pipe plugin. This method will be called before
* any other methods in the class.
*
* @param serverContext A handle to the server context for the
* ${SYNC_SERVER_BASE_NAME} in which this extension is
* running. Extensions should typically store this
* in a class member.
* @param config The general configuration for this proxy
* transformation.
* @param parser The argument parser which has been initialized from
* the configuration for this sync pipe plugin.
*
* @throws LDAPException If a problem occurs while initializing this sync
* pipe plugin.
*/
public void initializeSyncPipePlugin(final SyncServerContext serverContext,
final SyncPipePluginConfig config,
final ArgumentParser parser)
throws LDAPException
{
// No initialization will be performed by default.
}
/**
* {@inheritDoc}
*/
public boolean isConfigurationAcceptable(
final SyncPipePluginConfig config,
final ArgumentParser parser,
final List unacceptableReasons)
{
// No extended validation will be performed by default.
return true;
}
/**
* {@inheritDoc}
*/
public ResultCode applyConfiguration(final SyncPipePluginConfig config,
final ArgumentParser parser,
final List adminActionsRequired,
final List messages)
{
// By default, no configuration changes will be applied.
return ResultCode.SUCCESS;
}
/**
* Performs any cleanup which may be necessary when this sync pipe plugin
* is taken out of service. This can happen when it is deleted from the
* configuration and at server shutdown.
*/
public void finalizeSyncPipePlugin()
{
// No implementation is required.
}
/**
* This method is called immediately before the attributes and DN in
* the source entry are mapped into the equivalent destination entry.
* This equivalent destination entry is then compared to the actual
* destination entry to determine which of the modified attributes need
* to be updated.
*
* This method is typically used to either filter out certain changes
* (by returning {@link PreStepResult#ABORT_OPERATION}) or to manipulate the
* source entry before it is converted into an equivalent destination entry.
* Attributes that will not otherwise be affected by attribute mapping
* can be set in {@code equivalentDestinationEntry}. Although, due to the
* possibility of being overwritten in the mapping phase, manipulation of
* {@code equivalentDestinationEntry} is typically reserved for the
* {@link #postMapping} method.
*
* The set of source attributes that should be synchronized at the destination
* can be manipulated by calling
* {@link SyncOperation#addModifiedSourceAttribute} and
* {@link SyncOperation#removeModifiedSourceAttribute} on
* {@code operation}.
*
* Additional steps must be taken if this plugin adds destination attributes
* in {@code equivalentDestinationEntry} that need to be modified at the
* destination. For operations with an operation type of
* {@link com.unboundid.directory.sdk.sync.types.SyncOperationType#CREATE},
* any updates made to
* {@code equivalentDestinationEntry} will be included in the
* entry created at the destination. However, for operations with an
* operation type of
* {@link com.unboundid.directory.sdk.sync.types.SyncOperationType#MODIFY},
* destination attributes
* added by this plugin that need to be modified must be updated
* explicitly by calling
* {@link SyncOperation#addModifiedDestinationAttribute}.
*
* With the exception of aborting changes or skipping the mapping step
* completely, most plugins will not need to override this method since
* the {@link #postMapping} method has access to the fully mapped destination
* entry.
*
* @param sourceEntry The entry that was fetched from the
* source.
* @param equivalentDestinationEntry The destination entry that is
* equivalent to the source. This entry
* will be empty except for any
* modifications that have been performed
* by other sync pipe plugins.
* @param operation The operation that is being
* synchronized.
*
* @return The result of the plugin processing. Note:
* {@code PreStepResult#3SKIP_CURRENT_STEP} should only be returned
* if this plugin takes responsibility for fully constructing the
* equivalent destination entry.
*/
public PreStepResult preMapping(final Entry sourceEntry,
final Entry equivalentDestinationEntry,
final SyncOperation operation)
{
return PreStepResult.CONTINUE;
}
/**
* This method is called immediately after the attributes and DN in
* the source entry are mapped into the equivalent destination entry.
* Once this mapping is complete, this equivalent destination entry is then
* compared to the actual destination entry to determine which of the modified
* attributes need to be updated.
*
* This method is typically used to manipulate the equivalent destination
* entry before these necessary changes are calculated. It can also be used
* to filter out certain changes (by returning
* {@link PostStepResult#ABORT_OPERATION}), but this is typically done in
* the {@link #preMapping} method.
*
* The set of source attributes that should be synchronized at the destination
* can be manipulated by calling
* {@link SyncOperation#addModifiedSourceAttribute} and
* {@link SyncOperation#removeModifiedSourceAttribute} on
* {@code operation}.
*
* Additional steps must be taken if this plugin adds destination attributes
* in {@code equivalentDestinationEntry} that need to be modified at the
* destination. For operations with an operation type of
* {@link com.unboundid.directory.sdk.sync.types.SyncOperationType#CREATE},
* any updates made to
* {@code equivalentDestinationEntry} will be included in the
* entry created at the destination. However, for operations with an
* operation type of
* {@link com.unboundid.directory.sdk.sync.types.SyncOperationType#MODIFY},
* destination attributes
* added by this plugin that need to be modified must be updated
* explicitly by calling
* {@link SyncOperation#addModifiedDestinationAttribute}.
*
* With the exception of aborting changes or skipping the mapping step
* completely, most plugins will override this method instead of
* {@link #preMapping} because this method has access to the fully mapped
* destination entry.
*
* @param sourceEntry The entry that was fetched from the
* source.
* @param equivalentDestinationEntry The destination entry that is
* equivalent to the source. This entry
* will include all attributes mapped
* from the source entry.
* @param operation The operation that is being
* synchronized.
*
* @return The result of the plugin processing.
*/
public PostStepResult postMapping(final Entry sourceEntry,
final Entry equivalentDestinationEntry,
final SyncOperation operation)
{
return PostStepResult.CONTINUE;
}
/**
* Retrieves a string representation of this sync pipe plugin.
*
* @return A string representation of this sync pipe plugin.
*/
@Override()
public final String toString()
{
final StringBuilder buffer = new StringBuilder();
toString(buffer);
return buffer.toString();
}
/**
* Appends a string representation of this sync pipe plugin to the provided
* buffer.
*
* @param buffer The buffer to which the string representation should be
* appended.
*/
public abstract void toString(final StringBuilder buffer);
/**
* {@inheritDoc}
*/
public Map,String> getExamplesArgumentSets()
{
return Collections.emptyMap();
}
}