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.proxy.scripting;
028
029
030
031 import java.util.List;
032
033 import com.unboundid.directory.sdk.common.internal.Reconfigurable;
034 import com.unboundid.directory.sdk.proxy.config.ProxyTransformationConfig;
035 import com.unboundid.directory.sdk.proxy.internal.DirectoryProxyServerExtension;
036 import com.unboundid.directory.sdk.proxy.internal.SearchResultProvider;
037 import com.unboundid.directory.sdk.proxy.types.ProxyOperationContext;
038 import com.unboundid.directory.sdk.proxy.types.ProxyServerContext;
039 import com.unboundid.ldap.sdk.AddRequest;
040 import com.unboundid.ldap.sdk.BindRequest;
041 import com.unboundid.ldap.sdk.BindResult;
042 import com.unboundid.ldap.sdk.CompareRequest;
043 import com.unboundid.ldap.sdk.DeleteRequest;
044 import com.unboundid.ldap.sdk.LDAPException;
045 import com.unboundid.ldap.sdk.LDAPResult;
046 import com.unboundid.ldap.sdk.ModifyRequest;
047 import com.unboundid.ldap.sdk.ModifyDNRequest;
048 import com.unboundid.ldap.sdk.ReadOnlyAddRequest;
049 import com.unboundid.ldap.sdk.ReadOnlyCompareRequest;
050 import com.unboundid.ldap.sdk.ReadOnlyDeleteRequest;
051 import com.unboundid.ldap.sdk.ReadOnlyModifyRequest;
052 import com.unboundid.ldap.sdk.ReadOnlyModifyDNRequest;
053 import com.unboundid.ldap.sdk.ReadOnlySearchRequest;
054 import com.unboundid.ldap.sdk.ResultCode;
055 import com.unboundid.ldap.sdk.SearchRequest;
056 import com.unboundid.ldap.sdk.SearchResult;
057 import com.unboundid.ldap.sdk.SearchResultEntry;
058 import com.unboundid.ldap.sdk.SearchResultReference;
059 import com.unboundid.util.Extensible;
060 import com.unboundid.util.ThreadSafety;
061 import com.unboundid.util.ThreadSafetyLevel;
062 import com.unboundid.util.args.ArgumentException;
063 import com.unboundid.util.args.ArgumentParser;
064
065
066
067 /**
068 * This class defines an API that must be implemented by scripted extensions
069 * which are used to transform requests and/or responses as they pass through
070 * the Directory Proxy Server. They may be used to alter the contents of any
071 * add, bind, compare, delete, modify, modify DN, or search request or result
072 * passing through the Directory Proxy Server, or they may cause a result to be
073 * returned to the client without it being forwarded to a backend server. In
074 * addition, transformations may be applied to search result entries and
075 * references to be returned to the client, or those entries and references may
076 * be silently dropped so that they are not returned.
077 * <BR>
078 * <H2>Configuring Groovy-Scripted Proxy Transformations</H2>
079 * In order to configure a scripted proxy transformation based on this API and
080 * written in the Groovy scripting language, use a command like:
081 * <PRE>
082 * dsconfig create-proxy-transformation \
083 * --transformation-name "<I>{transformation-name}</I>" \
084 * --type groovy-scripted \
085 * --set enabled:true \
086 * --set "script-class:<I>{class-name}</I>" \
087 * --set "script-argument:<I>{name=value}</I>"
088 * </PRE>
089 * where "<I>{transformation-name}</I>" is the name to use for the proxy
090 * transformation instance, "<I>{class-name}</I>" is the fully-qualified name of
091 * the Groovy class written using this API, and "<I>{name=value}</I>" represents
092 * name-value pairs for any arguments to provide to the proxy transformation.
093 * If multiple arguments should be provided to the proxy transformation, then
094 * the "<CODE>--set script-argument:<I>{name=value}</I></CODE>" option should be
095 * provided multiple times.
096 *
097 * @see com.unboundid.directory.sdk.proxy.api.ProxyTransformation
098 */
099 @Extensible()
100 @DirectoryProxyServerExtension(appliesToLocalContent=false,
101 appliesToRemoteContent=true)
102 @ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
103 public abstract class ScriptedProxyTransformation
104 implements Reconfigurable<ProxyTransformationConfig>
105 {
106 /**
107 * Creates a new instance of this proxy transformation. All proxy
108 * transformation implementations must include a default constructor, but any
109 * initialization should generally be done in the
110 * {@code initializeProxyTransformation} method.
111 */
112 public ScriptedProxyTransformation()
113 {
114 // No implementation is required.
115 }
116
117
118
119 /**
120 * {@inheritDoc}
121 */
122 public void defineConfigArguments(final ArgumentParser parser)
123 throws ArgumentException
124 {
125 // No arguments will be allowed by default.
126 }
127
128
129
130 /**
131 * Initializes this proxy transformation.
132 *
133 * @param serverContext A handle to the server context for the server in
134 * which this extension is running.
135 * @param config The general configuration for this proxy
136 * transformation.
137 * @param parser The argument parser which has been initialized from
138 * the configuration for this proxy transformation.
139 *
140 * @throws LDAPException If a problem occurs while initializing this proxy
141 * transformation.
142 */
143 public void initializeProxyTransformation(
144 final ProxyServerContext serverContext,
145 final ProxyTransformationConfig config,
146 final ArgumentParser parser)
147 throws LDAPException
148 {
149 // No initialization will be performed by default.
150 }
151
152
153
154 /**
155 * Performs any cleanup which may be necessary when this proxy transformation
156 * is to be taken out of service.
157 */
158 public void finalizeProxyTransformation()
159 {
160 // No implementation is required.
161 }
162
163
164
165 /**
166 * {@inheritDoc}
167 */
168 public boolean isConfigurationAcceptable(
169 final ProxyTransformationConfig config,
170 final ArgumentParser parser,
171 final List<String> unacceptableReasons)
172 {
173 // No extended validation will be performed.
174 return true;
175 }
176
177
178
179 /**
180 * {@inheritDoc}
181 */
182 public ResultCode applyConfiguration(final ProxyTransformationConfig 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 proxy " +
195 "transformation is disabled and re-enabled or until the " +
196 "server is restarted.");
197 }
198
199 return ResultCode.SUCCESS;
200 }
201
202
203
204 /**
205 * Applies any necessary transformation to the provided add request.
206 *
207 * @param operationContext Information about the operation being processed
208 * in the Directory Proxy Server.
209 * @param addRequest The add request to be transformed.
210 *
211 * @return A new add request which has been transformed as necessary, or the
212 * original request if no transformation is required or the provided
213 * add request has been updated in place.
214 *
215 * @throws LDAPException If a problem is encountered while processing the
216 * transformation, or if the provided request should
217 * not be forwarded to a backend server.
218 */
219 public AddRequest transformAddRequest(
220 final ProxyOperationContext operationContext,
221 final AddRequest addRequest)
222 throws LDAPException
223 {
224 return addRequest;
225 }
226
227
228
229 /**
230 * Applies any necessary transformation to the provided add result.
231 *
232 * @param operationContext Information about the operation being processed
233 * in the Directory Proxy Server.
234 * @param addRequest The add request that was processed.
235 * @param addResult The add result to be transformed.
236 *
237 * @return A new add result which has been transformed as necessary, or the
238 * original result if no transformation is required or the provided
239 * add result has been updated in place.
240 */
241 public LDAPResult transformAddResult(
242 final ProxyOperationContext operationContext,
243 final ReadOnlyAddRequest addRequest,
244 final LDAPResult addResult)
245 {
246 return addResult;
247 }
248
249
250
251 /**
252 * Applies any necessary transformation to the provided bind request.
253 *
254 * @param operationContext Information about the operation being processed
255 * in the Directory Proxy Server.
256 * @param bindRequest The bind request to be transformed.
257 *
258 * @return A new bind request which has been transformed as necessary, or the
259 * original request if no transformation is required.
260 *
261 * @throws LDAPException If a problem is encountered while processing the
262 * transformation, or if the provided request should
263 * not be forwarded to a backend server.
264 */
265 public BindRequest transformBindRequest(
266 final ProxyOperationContext operationContext,
267 final BindRequest bindRequest)
268 throws LDAPException
269 {
270 return bindRequest;
271 }
272
273
274
275 /**
276 * Applies any necessary transformation to the provided bind request.
277 *
278 * @param operationContext Information about the operation being processed
279 * in the Directory Proxy Server.
280 * @param bindRequest The bind request that was processed.
281 * @param bindResult The bind result to be transformed.
282 *
283 * @return A new bind result which has been transformed as necessary, or the
284 * original result if no transformation is required.
285 */
286 public BindResult transformBindResult(
287 final ProxyOperationContext operationContext,
288 final BindRequest bindRequest,
289 final BindResult bindResult)
290 {
291 return bindResult;
292 }
293
294
295
296 /**
297 * Applies any necessary transformation to the provided compare request.
298 *
299 * @param operationContext Information about the operation being processed
300 * in the Directory Proxy Server.
301 * @param compareRequest The compare request to be transformed.
302 *
303 * @return A new compare request which has been transformed as necessary, or
304 * the original request if no transformation is required or the
305 * provided compare request has been updated in place.
306 *
307 * @throws LDAPException If a problem is encountered while processing the
308 * transformation, or if the provided request should
309 * not be forwarded to a backend server.
310 */
311 public CompareRequest transformCompareRequest(
312 final ProxyOperationContext operationContext,
313 final CompareRequest compareRequest)
314 throws LDAPException
315 {
316 return compareRequest;
317 }
318
319
320
321 /**
322 * Applies any necessary transformation to the provided compare result.
323 *
324 * @param operationContext Information about the operation being processed
325 * in the Directory Proxy Server.
326 * @param compareRequest The compare request that was processed.
327 * @param compareResult The compare result to be transformed.
328 *
329 * @return A new compare result which has been transformed as necessary, or
330 * the original result if no transformation is required or the
331 * provided compare result has been updated in place.
332 */
333 public LDAPResult transformCompareResult(
334 final ProxyOperationContext operationContext,
335 final ReadOnlyCompareRequest compareRequest,
336 final LDAPResult compareResult)
337 {
338 return compareResult;
339 }
340
341
342
343 /**
344 * Applies any necessary transformation to the provided delete request.
345 *
346 * @param operationContext Information about the operation being processed
347 * in the Directory Proxy Server.
348 * @param deleteRequest The delete request to be transformed.
349 *
350 * @return A new delete request which has been transformed as necessary, or
351 * the original request if no transformation is required or the
352 * provided delete request has been updated in place.
353 *
354 * @throws LDAPException If a problem is encountered while processing the
355 * transformation, or if the provided request should
356 * not be forwarded to a backend server.
357 */
358 public DeleteRequest transformDeleteRequest(
359 final ProxyOperationContext operationContext,
360 final DeleteRequest deleteRequest)
361 throws LDAPException
362 {
363 return deleteRequest;
364 }
365
366
367
368 /**
369 * Applies any necessary transformation to the provided delete result.
370 *
371 * @param operationContext Information about the operation being processed
372 * in the Directory Proxy Server.
373 * @param deleteRequest The delete request that was processed.
374 * @param deleteResult The delete result to be transformed.
375 *
376 * @return A new delete result which has been transformed as necessary, or
377 * the original result if no transformation is required or the
378 * provided delete result has been updated in place.
379 */
380 public LDAPResult transformDeleteResult(
381 final ProxyOperationContext operationContext,
382 final ReadOnlyDeleteRequest deleteRequest,
383 final LDAPResult deleteResult)
384 {
385 return deleteResult;
386 }
387
388
389
390 /**
391 * Applies any necessary transformation to the provided modify request.
392 *
393 * @param operationContext Information about the operation being processed
394 * in the Directory Proxy Server.
395 * @param modifyRequest The modify request to be transformed.
396 *
397 * @return A new modify request which has been transformed as necessary, or
398 * the original request if no transformation is required or the
399 * provided modify request has been updated in place.
400 *
401 * @throws LDAPException If a problem is encountered while processing the
402 * transformation, or if the provided request should
403 * not be forwarded to a backend server.
404 */
405 public ModifyRequest transformModifyRequest(
406 final ProxyOperationContext operationContext,
407 final ModifyRequest modifyRequest)
408 throws LDAPException
409 {
410 return modifyRequest;
411 }
412
413
414
415 /**
416 * Applies any necessary transformation to the provided modify result.
417 *
418 * @param operationContext Information about the operation being processed
419 * in the Directory Proxy Server.
420 * @param modifyRequest The modify request that was processed.
421 * @param modifyResult The modify result to be transformed.
422 *
423 * @return A new modify result which has been transformed as necessary, or
424 * the original result if no transformation is required or the
425 * provided modify result has been updated in place.
426 */
427 public LDAPResult transformModifyResult(
428 final ProxyOperationContext operationContext,
429 final ReadOnlyModifyRequest modifyRequest,
430 final LDAPResult modifyResult)
431 {
432 return modifyResult;
433 }
434
435
436
437 /**
438 * Applies any necessary transformation to the provided modify DN request.
439 *
440 * @param operationContext Information about the operation being processed
441 * in the Directory Proxy Server.
442 * @param modifyDNRequest The modify DN request to be transformed.
443 *
444 * @return A new modify DN request which has been transformed as necessary,
445 * or the original request if no transformation is required or the
446 * provided modify DN request has been updated in place.
447 *
448 * @throws LDAPException If a problem is encountered while processing the
449 * transformation, or if the provided request should
450 * not be forwarded to a backend server.
451 */
452 public ModifyDNRequest transformModifyDNRequest(
453 final ProxyOperationContext operationContext,
454 final ModifyDNRequest modifyDNRequest)
455 throws LDAPException
456 {
457 return modifyDNRequest;
458 }
459
460
461
462 /**
463 * Applies any necessary transformation to the provided modify DN result.
464 *
465 * @param operationContext Information about the operation being processed
466 * in the Directory Proxy Server.
467 * @param modifyDNRequest The modify DN request that was processed.
468 * @param modifyDNResult The modify DN result to be transformed.
469 *
470 * @return A new modify DN result which has been transformed as necessary, or
471 * the original result if no transformation is required or the
472 * provided modify DN result has been updated in place.
473 */
474 public LDAPResult transformModifyDNResult(
475 final ProxyOperationContext operationContext,
476 final ReadOnlyModifyDNRequest modifyDNRequest,
477 final LDAPResult modifyDNResult)
478 {
479 return modifyDNResult;
480 }
481
482
483
484 /**
485 * Applies any necessary transformation to the provided search request.
486 *
487 * @param operationContext Information about the operation being processed
488 * in the Directory Proxy Server.
489 * @param searchRequest The search request to be transformed.
490 *
491 * @return A new search request which has been transformed as necessary, or
492 * the original request if no transformation is required or the
493 * provided search request has been updated in place.
494 *
495 * @throws LDAPException If a problem is encountered while processing the
496 * transformation, or if the provided request should
497 * not be forwarded to a backend server.
498 */
499 public SearchRequest transformSearchRequest(
500 final ProxyOperationContext operationContext,
501 final SearchRequest searchRequest)
502 throws LDAPException
503 {
504 return searchRequest;
505 }
506
507
508
509 /**
510 * Applies any necessary transformation to the provided search result.
511 *
512 * @param operationContext Information about the operation being processed
513 * in the Directory Proxy Server.
514 * @param searchRequest The search request that was processed.
515 * @param searchResult The search result to be transformed.
516 * @param resultProvider The search result provider which may be used to
517 * send additional search result entries and/or
518 * references to the client.
519 *
520 * @return A new search result which has been transformed as necessary, or
521 * the original result if no transformation is required or the
522 * provided search result has been updated in place.
523 */
524 public SearchResult transformSearchResult(
525 final ProxyOperationContext operationContext,
526 final ReadOnlySearchRequest searchRequest,
527 final SearchResult searchResult,
528 final SearchResultProvider resultProvider)
529 {
530 return searchResult;
531 }
532
533
534
535 /**
536 * Applies any necessary transformation to the provided search result entry.
537 *
538 * @param operationContext Information about the operation being processed
539 * in the Directory Proxy Server.
540 * @param searchRequest The search request that is being processed.
541 * @param searchEntry The search result entry to be transformed.
542 *
543 * @return A new search result entry which has been transformed as necessary,
544 * the original search result entry if no transformation is required,
545 * or {@code null} if the entry should not be returned to the client.
546 */
547 public SearchResultEntry transformSearchResultEntry(
548 final ProxyOperationContext operationContext,
549 final ReadOnlySearchRequest searchRequest,
550 final SearchResultEntry searchEntry)
551 {
552 return searchEntry;
553 }
554
555
556
557 /**
558 * Applies any necessary transformation to the provided search result
559 * reference.
560 *
561 * @param operationContext Information about the operation being processed
562 * in the Directory Proxy Server.
563 * @param searchRequest The search request that is being processed.
564 * @param searchReference The search result reference to be transformed.
565 *
566 * @return A new search result reference which has been transformed as
567 * necessary, the original search result reference if no
568 * transformation is required, or {@code null} if the reference
569 * should not be returned to the client.
570 */
571 public SearchResultReference transformSearchResultReference(
572 final ProxyOperationContext operationContext,
573 final ReadOnlySearchRequest searchRequest,
574 final SearchResultReference searchReference)
575 {
576 return searchReference;
577 }
578 }