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    }