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-2014 UnboundID Corp.
026 */
027 package com.unboundid.directory.sdk.ds.api;
028
029
030
031 import java.util.Collections;
032 import java.util.List;
033 import java.util.Map;
034 import java.util.Set;
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.common.operation.ExtendedRequest;
040 import com.unboundid.directory.sdk.common.operation.UpdatableExtendedResult;
041 import com.unboundid.directory.sdk.common.types.OperationContext;
042 import com.unboundid.directory.sdk.ds.config.ExtendedOperationHandlerConfig;
043 import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension;
044 import com.unboundid.directory.sdk.ds.types.DirectoryServerContext;
045 import com.unboundid.directory.sdk.proxy.internal.DirectoryProxyServerExtension;
046 import com.unboundid.directory.sdk.sync.internal.SynchronizationServerExtension;
047 import com.unboundid.ldap.sdk.LDAPException;
048 import com.unboundid.ldap.sdk.ResultCode;
049 import com.unboundid.util.Extensible;
050 import com.unboundid.util.ThreadSafety;
051 import com.unboundid.util.ThreadSafetyLevel;
052 import com.unboundid.util.args.ArgumentException;
053 import com.unboundid.util.args.ArgumentParser;
054
055
056
057 /**
058 * This class defines an API that must be implemented by extensions which are
059 * used to process extended operations within the server. Extended operations
060 * may be used to perform processing which falls outside of that available by
061 * the core set of LDAP operations. Each extended request will include a
062 * numeric object identifier (OID) which indicates the type of request to be
063 * processed, and may also include a value with additional information about the
064 * processing to be performed. Each extended operation handler must specify the
065 * OIDs of the types of extended requests that it may be used to process.
066 * <BR>
067 * <H2>Configuring Extended Operation Handlers</H2>
068 * In order to configure an extended operation handler created using this API,
069 * use a command like:
070 * <PRE>
071 * dsconfig create-extended-operation-handler \
072 * --handler-name "<I>{handler-name}</I>" \
073 * --type third-party \
074 * --set enabled:true \
075 * --set "extension-class:<I>{class-name}</I>" \
076 * --set "extension-argument:<I>{name=value}</I>"
077 * </PRE>
078 * where "<I>{handler-name}</I>" is the name to use for the extended operation
079 * handler instance, "<I>{class-name}</I>" is the fully-qualified name of the
080 * Java class that extends
081 * {@code com.unboundid.directory.sdk.ds.api.ExtendedOperationHandler}, and
082 * "<I>{name=value}</I>" represents name-value pairs for any arguments to
083 * provide to the extended operation handler. If multiple arguments should be
084 * provided to the extended operation handler, then the
085 * "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option should be
086 * provided multiple times.
087 */
088 @Extensible()
089 @DirectoryServerExtension()
090 @DirectoryProxyServerExtension(appliesToLocalContent=true,
091 appliesToRemoteContent=true,
092 notes="Some extended operation handlers may only apply to local content")
093 @SynchronizationServerExtension(appliesToLocalContent=true,
094 appliesToSynchronizedContent=false)
095 @ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
096 public abstract class ExtendedOperationHandler
097 implements UnboundIDExtension,
098 Reconfigurable<ExtendedOperationHandlerConfig>,
099 ExampleUsageProvider
100 {
101 /**
102 * Creates a new instance of this extended operation handler. All extended
103 * operation handler implementations must include a default constructor, but
104 * any initialization should generally be done in the
105 * {@code initializeExtendedOperationHandler} method.
106 */
107 public ExtendedOperationHandler()
108 {
109 // No implementation is required.
110 }
111
112
113
114 /**
115 * {@inheritDoc}
116 */
117 public abstract String getExtensionName();
118
119
120
121 /**
122 * {@inheritDoc}
123 */
124 public abstract String[] getExtensionDescription();
125
126
127
128 /**
129 * {@inheritDoc}
130 */
131 public void defineConfigArguments(final ArgumentParser parser)
132 throws ArgumentException
133 {
134 // No arguments will be allowed by default.
135 }
136
137
138
139 /**
140 * Initializes this extended operation handler.
141 *
142 * @param serverContext A handle to the server context for the server in
143 * which this extension is running.
144 * @param config The general configuration for this extended
145 * operation handler.
146 * @param parser The argument parser which has been initialized from
147 * the configuration for this extended operation
148 * handler.
149 *
150 * @throws LDAPException If a problem occurs while initializing this
151 * extended operation handler.
152 */
153 public void initializeExtendedOperationHandler(
154 final DirectoryServerContext serverContext,
155 final ExtendedOperationHandlerConfig config,
156 final ArgumentParser parser)
157 throws LDAPException
158 {
159 // No initialization will be performed by default.
160 }
161
162
163
164 /**
165 * {@inheritDoc}
166 */
167 public boolean isConfigurationAcceptable(
168 final ExtendedOperationHandlerConfig config,
169 final ArgumentParser parser,
170 final List<String> unacceptableReasons)
171 {
172 // No extended validation will be performed by default.
173 return true;
174 }
175
176
177
178 /**
179 * {@inheritDoc}
180 */
181 public ResultCode applyConfiguration(
182 final ExtendedOperationHandlerConfig config,
183 final ArgumentParser parser,
184 final List<String> adminActionsRequired,
185 final List<String> messages)
186 {
187 // By default, no configuration changes will be applied. If there are any
188 // arguments, then add an admin action message indicating that the extension
189 // needs to be restarted for any changes to take effect.
190 if (! parser.getNamedArguments().isEmpty())
191 {
192 adminActionsRequired.add(
193 "No configuration change has actually been applied. The new " +
194 "configuration will not take effect until this extended " +
195 "operation handler is disabled and re-enabled or until the " +
196 "server is restarted.");
197 }
198
199 return ResultCode.SUCCESS;
200 }
201
202
203
204 /**
205 * Performs any cleanup which may be necessary when this extended operation
206 * handler is to be taken out of service.
207 */
208 public void finalizeExtendedOperationHandler()
209 {
210 // No implementation is required.
211 }
212
213
214
215 /**
216 * Retrieves the name of the extended operation with the provided OID.
217 *
218 * @param oid The OID of the extended operation for which to retrieve the
219 * corresponding name.
220 *
221 * @return The name of the extended operation with the specified OID, or
222 * {@code null} if the specified OID is not recognized by this
223 * extended operation handler.
224 */
225 public abstract String getExtendedOperationName(final String oid);
226
227
228
229 /**
230 * Retrieves the OIDs of the extended operation types supported by this
231 * extended operation handler.
232 *
233 * @return The OIDs of the extended operation types supported by this
234 * extended operation handler. It must not be {@code null} or
235 * empty, and the contents of the set returned must not change over
236 * the life of this extended operation handler.
237 */
238 public abstract Set<String> getSupportedExtensions();
239
240
241
242 /**
243 * Retrieves the OIDs of any controls supported by this extended operation
244 * handler.
245 *
246 * @return The OIDs of any controls supported by this extended operation
247 * handler. It may be {@code null} or empty if this extended
248 * operation handler does not support any controls.
249 */
250 public Set<String> getSupportedControls()
251 {
252 return Collections.emptySet();
253 }
254
255
256
257 /**
258 * Retrieves the OIDs of any features supported by this extended operation
259 * handler that should be advertised in the server root DSE.
260 *
261 * @return The OIDs of any features supported by this extended operation
262 * handler. It may be {@code null} or empty if this extended
263 * operation handler does not support any features.
264 */
265 public Set<String> getSupportedFeatures()
266 {
267 return Collections.emptySet();
268 }
269
270
271
272 /**
273 * Performs any processing appropriate for the provided extended request.
274 *
275 * @param operationContext The operation context for the extended operation.
276 * @param request The extended request to be processed.
277 * @param result The extended result to be updated with the result
278 * of processing.
279 */
280 public abstract void processExtendedOperation(
281 final OperationContext operationContext,
282 final ExtendedRequest request,
283 final UpdatableExtendedResult result);
284
285
286
287 /**
288 * {@inheritDoc}
289 */
290 public Map<List<String>,String> getExamplesArgumentSets()
291 {
292 return Collections.emptyMap();
293 }
294 }