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 * Copyright 2010-2012 UnboundID Corp.
026 */
027 package com.unboundid.directory.sdk.sync.api;
028
029
030
031 import java.util.Collections;
032 import java.util.List;
033 import java.util.Map;
034 import java.util.concurrent.atomic.AtomicReference;
035
036 import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider;
037 import com.unboundid.directory.sdk.common.internal.Reconfigurable;
038 import com.unboundid.directory.sdk.common.internal.UnboundIDExtension;
039 import com.unboundid.directory.sdk.sync.config.LDAPSyncSourcePluginConfig;
040 import com.unboundid.directory.sdk.sync.internal.SynchronizationServerExtension;
041 import com.unboundid.directory.sdk.sync.types.PostStepResult;
042 import com.unboundid.directory.sdk.sync.types.SyncOperation;
043 import com.unboundid.directory.sdk.sync.types.SyncServerContext;
044 import com.unboundid.ldap.sdk.Entry;
045 import com.unboundid.ldap.sdk.LDAPException;
046 import com.unboundid.ldap.sdk.LDAPInterface;
047 import com.unboundid.ldap.sdk.ResultCode;
048 import com.unboundid.util.Extensible;
049 import com.unboundid.util.ThreadSafety;
050 import com.unboundid.util.ThreadSafetyLevel;
051 import com.unboundid.util.args.ArgumentException;
052 import com.unboundid.util.args.ArgumentParser;
053
054
055
056 /**
057 * This class defines an API that must be implemented by extensions that
058 * perform processing on synchronization operations within an LDAP Sync
059 * Source. These extensions may be used to
060 * <ul>
061 * <li>Filter out certain changes from being synchronized.</li>
062 * <li>Change how an entry is fetched.</li>
063 * </ul>
064 * <BR>
065 * A note on exception handling: in general subclasses should not
066 * catch LDAPExceptions that are thrown when using the provided
067 * LDAPInterface unless there are specific exceptions that are
068 * expected. The Synchronization Server will handle
069 * LDAPExceptions in an appropriate way based on the specific
070 * cause of the exception. For example, some errors will result
071 * in the SyncOperation being retried, and others will trigger
072 * fail over to a different server.
073 * <BR>
074 * <H2>Configuring LDAP Sync Source Plugins</H2>
075 * In order to configure an LDAP sync source plugin created using this API, use
076 * a command like:
077 * <PRE>
078 * dsconfig create-sync-source-plugin \
079 * --plugin-name "<I>{plugin-name}</I>" \
080 * --type third-party-ldap \
081 * --set "extension-class:<I>{class-name}</I>" \
082 * --set "extension-argument:<I>{name=value}</I>"
083 * </PRE>
084 * where "<I>{plugin-name}</I>" is the name to use for the LDAP sync source
085 * plugin instance, "<I>{class-name}</I>" is the fully-qualified name of the
086 * Java class that extends
087 * {@code com.unboundid.directory.sdk.sync.api.LDAPSyncSourcePlugin}, and
088 * "<I>{name=value}</I>" represents name-value pairs for any arguments to
089 * provide to the LDAP sync source plugin. If multiple arguments should be
090 * provided to the LDAP sync source plugin, then the
091 * "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option should be
092 * provided multiple times.
093 *
094 * @see com.unboundid.directory.sdk.sync.scripting.ScriptedLDAPSyncSourcePlugin
095 */
096 @Extensible()
097 @SynchronizationServerExtension(appliesToLocalContent=false,
098 appliesToSynchronizedContent=true)
099 @ThreadSafety(level= ThreadSafetyLevel.INTERFACE_THREADSAFE)
100 public abstract class LDAPSyncSourcePlugin
101 implements UnboundIDExtension,
102 Reconfigurable<LDAPSyncSourcePluginConfig>,
103 ExampleUsageProvider
104 {
105 /**
106 * Creates a new instance of this LDAP sync source plugin. All sync
107 * source implementations must include a default constructor, but any
108 * initialization should generally be done in the
109 * {@code initializeLDAPSyncSourcePlugin} method.
110 */
111 public LDAPSyncSourcePlugin()
112 {
113 // No implementation is required.
114 }
115
116
117
118 /**
119 * {@inheritDoc}
120 */
121 public abstract String getExtensionName();
122
123
124
125 /**
126 * {@inheritDoc}
127 */
128 public abstract String[] getExtensionDescription();
129
130
131
132 /**
133 * {@inheritDoc}
134 */
135 public void defineConfigArguments(final ArgumentParser parser)
136 throws ArgumentException
137 {
138 // No arguments will be allowed by default.
139 }
140
141
142
143 /**
144 * Initializes this LDAP sync source plugin. This method will be called
145 * before any other methods in the class.
146 *
147 * @param serverContext A handle to the server context for the
148 * Synchronization Server in which this extension is
149 * running. Extensions should typically store this
150 * in a class member.
151 * @param config The general configuration for this proxy
152 * transformation.
153 * @param parser The argument parser which has been initialized from
154 * the configuration for this LDAP sync source
155 * plugin.
156 *
157 * @throws LDAPException If a problem occurs while initializing this ldap
158 * sync source plugin.
159 */
160 public void initializeLDAPSyncSourcePlugin(
161 final SyncServerContext serverContext,
162 final LDAPSyncSourcePluginConfig config,
163 final ArgumentParser parser)
164 throws LDAPException
165 {
166 // No initialization will be performed by default.
167 }
168
169
170
171 /**
172 * {@inheritDoc}
173 */
174 public boolean isConfigurationAcceptable(
175 final LDAPSyncSourcePluginConfig config,
176 final ArgumentParser parser,
177 final List<String> unacceptableReasons)
178 {
179 // No extended validation will be performed by default.
180 return true;
181 }
182
183
184
185 /**
186 * {@inheritDoc}
187 */
188 public ResultCode applyConfiguration(final LDAPSyncSourcePluginConfig config,
189 final ArgumentParser parser,
190 final List<String> adminActionsRequired,
191 final List<String> messages)
192 {
193 // By default, no configuration changes will be applied.
194 return ResultCode.SUCCESS;
195 }
196
197
198
199 /**
200 * Performs any cleanup which may be necessary when this LDAP sync source
201 * plugin is taken out of service. This can happen when it is deleted from
202 * the configuration and at server shutdown.
203 */
204 public void finalizeLDAPSyncSourcePlugin()
205 {
206 // No implementation is required.
207 }
208
209
210
211 /**
212 * This method is called after fetching a source entry. A
213 * connection to the source server is provided. This method is
214 * overridden by plugins that need to manipulate the search results that
215 * are returned to the Sync Pipe. This can include filtering out certain
216 * entries, remove information from the entries, or adding additional
217 * information, possibly by doing a followup LDAP search.
218 *
219 * @param sourceConnection A connection to the source server.
220 * @param fetchedEntryRef A reference to the entry that was fetched.
221 * This entry can be edited in place, or the
222 * reference can be changed to point to a
223 * different entry that the plugin constructs.
224 * @param operation The synchronization operation for this
225 * change.
226 *
227 * @return The result of the plugin processing.
228 *
229 * @throws LDAPException In general subclasses should not catch
230 * LDAPExceptions that are thrown when
231 * using the LDAPInterface unless there
232 * are specific exceptions that are
233 * expected. The Synchronization Server
234 * will handle LDAPExceptions in an
235 * appropriate way based on the specific
236 * cause of the exception. For example,
237 * some errors will result in the
238 * SyncOperation being retried, and others
239 * will trigger fail over to a different
240 * server. Plugins should only throw
241 * LDAPException for errors related to
242 * communication with the LDAP server.
243 * Use the return code to indicate other
244 * types of errors, which might require
245 * retry.
246 */
247 public PostStepResult postFetch(final LDAPInterface sourceConnection,
248 final AtomicReference<Entry> fetchedEntryRef,
249 final SyncOperation operation)
250 throws LDAPException
251 {
252 return PostStepResult.CONTINUE;
253 }
254
255
256
257 /**
258 * Retrieves a string representation of this LDAP sync source plugin.
259 *
260 * @return A string representation of this LDAP sync source plugin.
261 */
262 @Override()
263 public final String toString()
264 {
265 final StringBuilder buffer = new StringBuilder();
266 toString(buffer);
267 return buffer.toString();
268 }
269
270
271
272 /**
273 * Appends a string representation of this LDAP sync source plugin to the
274 * provided buffer.
275 *
276 * @param buffer The buffer to which the string representation should be
277 * appended.
278 */
279 public abstract void toString(final StringBuilder buffer);
280
281
282
283 /**
284 * {@inheritDoc}
285 */
286 public Map<List<String>,String> getExamplesArgumentSets()
287 {
288 return Collections.emptyMap();
289 }
290 }