001/*
002 * Copyright 2014-2017 UnboundID Corp.
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2014-2017 UnboundID Corp.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.ldap.listener.interceptor;
022
023
024
025import java.util.List;
026import java.util.HashMap;
027import java.util.Map;
028
029import com.unboundid.ldap.listener.IntermediateResponseTransformer;
030import com.unboundid.ldap.listener.LDAPListenerClientConnection;
031import com.unboundid.ldap.listener.LDAPListenerRequestHandler;
032import com.unboundid.ldap.listener.SearchEntryTransformer;
033import com.unboundid.ldap.listener.SearchReferenceTransformer;
034import com.unboundid.ldap.protocol.AddRequestProtocolOp;
035import com.unboundid.ldap.protocol.AddResponseProtocolOp;
036import com.unboundid.ldap.protocol.BindRequestProtocolOp;
037import com.unboundid.ldap.protocol.BindResponseProtocolOp;
038import com.unboundid.ldap.protocol.CompareRequestProtocolOp;
039import com.unboundid.ldap.protocol.CompareResponseProtocolOp;
040import com.unboundid.ldap.protocol.DeleteRequestProtocolOp;
041import com.unboundid.ldap.protocol.DeleteResponseProtocolOp;
042import com.unboundid.ldap.protocol.ExtendedRequestProtocolOp;
043import com.unboundid.ldap.protocol.ExtendedResponseProtocolOp;
044import com.unboundid.ldap.protocol.IntermediateResponseProtocolOp;
045import com.unboundid.ldap.protocol.LDAPMessage;
046import com.unboundid.ldap.protocol.ModifyRequestProtocolOp;
047import com.unboundid.ldap.protocol.ModifyResponseProtocolOp;
048import com.unboundid.ldap.protocol.ModifyDNRequestProtocolOp;
049import com.unboundid.ldap.protocol.ModifyDNResponseProtocolOp;
050import com.unboundid.ldap.protocol.SearchRequestProtocolOp;
051import com.unboundid.ldap.protocol.SearchResultDoneProtocolOp;
052import com.unboundid.ldap.protocol.SearchResultEntryProtocolOp;
053import com.unboundid.ldap.protocol.SearchResultReferenceProtocolOp;
054import com.unboundid.ldap.sdk.AddRequest;
055import com.unboundid.ldap.sdk.CompareRequest;
056import com.unboundid.ldap.sdk.Control;
057import com.unboundid.ldap.sdk.DeleteRequest;
058import com.unboundid.ldap.sdk.LDAPException;
059import com.unboundid.ldap.sdk.ModifyRequest;
060import com.unboundid.ldap.sdk.ModifyDNRequest;
061import com.unboundid.ldap.sdk.ResultCode;
062import com.unboundid.ldap.sdk.SearchRequest;
063import com.unboundid.util.Debug;
064import com.unboundid.util.ObjectPair;
065import com.unboundid.util.ThreadSafety;
066import com.unboundid.util.ThreadSafetyLevel;
067import com.unboundid.util.StaticUtils;
068
069import static com.unboundid.ldap.listener.interceptor.InterceptorMessages.*;
070
071
072
073/**
074 * This class provides an LDAP listener request handler that may be used to
075 * invoke any in-memory operation interceptors in the course of processing
076 * operations for the in-memory directory server.
077 */
078@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
079public final class InMemoryOperationInterceptorRequestHandler
080       extends LDAPListenerRequestHandler
081       implements IntermediateResponseTransformer, SearchEntryTransformer,
082                  SearchReferenceTransformer
083{
084  // The set of interceptors to be used to transform requests and responses.
085  private final InMemoryOperationInterceptor[] interceptors;
086
087  // The client connection associated with this request handler instance.
088  private final LDAPListenerClientConnection connection;
089
090  // The request handler that will be used to ensure that operations actually
091  // get processed.
092  private final LDAPListenerRequestHandler wrappedHandler;
093
094  // A map containing active operations mapped by message ID.
095  private final Map<Integer,InterceptedOperation> activeOperations;
096
097
098
099  /**
100   * Creates a new instance of this LDAP listener request handler that will be
101   * used to process the provided set of operation interceptors.
102   *
103   * @param  interceptors    The set of operation interceptors that will be used
104   *                         to transform requests and responses.  If there are
105   *                         multiple interceptors, then they will be invoked in
106   *                         the same order as elements in the provided list
107   *                         when processing both requests and results.
108   * @param  wrappedHandler  The request handler that will be used to ensure
109   *                         that operations actually get processed.
110   */
111  public InMemoryOperationInterceptorRequestHandler(
112              final List<InMemoryOperationInterceptor> interceptors,
113              final LDAPListenerRequestHandler wrappedHandler)
114  {
115    this.wrappedHandler = wrappedHandler;
116
117    this.interceptors = new InMemoryOperationInterceptor[interceptors.size()];
118    interceptors.toArray(this.interceptors);
119
120    connection       = null;
121    activeOperations = new HashMap<Integer,InterceptedOperation>(5);
122  }
123
124
125
126  /**
127   * Creates a new instance of this LDAP listener request handler that will be
128   * used to process the provided set of operation interceptors.
129   *
130   * @param  interceptors    The set of operation interceptors that will be used
131   *                         to transform requests and responses.  If there are
132   *                         multiple interceptors, then they will be invoked in
133   *                         the same order as elements in the provided list
134   *                         when processing both requests and results.
135   * @param  wrappedHandler  The request handler that will be used to ensure
136   *                         that operations actually get processed.
137   * @param  connection      The client connection associated with this request
138   *                         handler instance.
139   */
140  private InMemoryOperationInterceptorRequestHandler(
141               final InMemoryOperationInterceptor[] interceptors,
142               final LDAPListenerRequestHandler wrappedHandler,
143               final LDAPListenerClientConnection connection)
144  {
145    this.interceptors   = interceptors;
146    this.wrappedHandler = wrappedHandler;
147    this.connection     = connection;
148
149    activeOperations = new HashMap<Integer,InterceptedOperation>(5);
150  }
151
152
153
154  /**
155   * {@inheritDoc}
156   */
157  @Override()
158  public InMemoryOperationInterceptorRequestHandler newInstance(
159              final LDAPListenerClientConnection connection)
160         throws LDAPException
161  {
162    final InMemoryOperationInterceptorRequestHandler handler =
163         new InMemoryOperationInterceptorRequestHandler(interceptors,
164              wrappedHandler.newInstance(connection), connection);
165
166    connection.addSearchEntryTransformer(handler);
167    connection.addSearchReferenceTransformer(handler);
168    connection.addIntermediateResponseTransformer(handler);
169
170    return handler;
171  }
172
173
174
175  /**
176   * {@inheritDoc}
177   */
178  @Override()
179  public LDAPMessage processAddRequest(final int messageID,
180                                       final AddRequestProtocolOp request,
181                                       final List<Control> controls)
182  {
183    final InterceptedAddOperation op = new InterceptedAddOperation(connection,
184         messageID, request, toArray(controls));
185    activeOperations.put(messageID, op);
186
187    try
188    {
189      for (final InMemoryOperationInterceptor i : interceptors)
190      {
191        try
192        {
193          i.processAddRequest(op);
194        }
195        catch (final LDAPException le)
196        {
197          Debug.debugException(le);
198          return new LDAPMessage(messageID,
199               new AddResponseProtocolOp(le.toLDAPResult()),
200               le.getResponseControls());
201        }
202        catch (final Exception e)
203        {
204          Debug.debugException(e);
205          return new LDAPMessage(messageID,
206               new AddResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
207                    ERR_DS_INTERCEPTOR_REQUEST_ERROR.get(
208                         String.valueOf(op), i.getClass().getName(),
209                         StaticUtils.getExceptionMessage(e)),
210                    null
211               )
212          );
213        }
214      }
215
216      final LDAPMessage resultMessage = wrappedHandler.processAddRequest(
217           messageID,
218           new AddRequestProtocolOp((AddRequest) op.getRequest()),
219           op.getRequest().getControlList());
220      op.setResult(resultMessage.getAddResponseProtocolOp().toLDAPResult(
221           toArray(resultMessage.getControls())));
222      for (final InMemoryOperationInterceptor i : interceptors)
223      {
224        try
225        {
226          i.processAddResult(op);
227        }
228        catch (final Exception e)
229        {
230          Debug.debugException(e);
231          return new LDAPMessage(messageID,
232               new AddResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
233                    ERR_DS_INTERCEPTOR_RESULT_ERROR.get(
234                         String.valueOf(op), i.getClass().getName(),
235                         StaticUtils.getExceptionMessage(e)),
236                    null
237               )
238          );
239        }
240      }
241
242      return new LDAPMessage(messageID,
243           new AddResponseProtocolOp(op.getResult()),
244           op.getResult().getResponseControls());
245    }
246    finally
247    {
248      activeOperations.remove(messageID);
249    }
250  }
251
252
253
254  /**
255   * {@inheritDoc}
256   */
257  @Override()
258  public LDAPMessage processBindRequest(final int messageID,
259                                        final BindRequestProtocolOp request,
260                                        final List<Control> controls)
261  {
262    if (request.getCredentialsType() == BindRequestProtocolOp.CRED_TYPE_SIMPLE)
263    {
264      final InterceptedSimpleBindOperation op =
265           new InterceptedSimpleBindOperation(connection, messageID, request,
266                toArray(controls));
267      activeOperations.put(messageID, op);
268
269      try
270      {
271        for (final InMemoryOperationInterceptor i : interceptors)
272        {
273          try
274          {
275            i.processSimpleBindRequest(op);
276          }
277          catch (final LDAPException le)
278          {
279            Debug.debugException(le);
280            return new LDAPMessage(messageID,
281                 new BindResponseProtocolOp(le.toLDAPResult()),
282                 le.getResponseControls());
283          }
284          catch (final Exception e)
285          {
286            Debug.debugException(e);
287            return new LDAPMessage(messageID,
288                 new BindResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
289                      ERR_DS_INTERCEPTOR_REQUEST_ERROR.get(
290                           String.valueOf(op), i.getClass().getName(),
291                           StaticUtils.getExceptionMessage(e)),
292                      null, null));
293          }
294        }
295
296        final LDAPMessage resultMessage = wrappedHandler.processBindRequest(
297             messageID,
298             new BindRequestProtocolOp(op.getRequest()),
299             op.getRequest().getControlList());
300        op.setResult(resultMessage.getBindResponseProtocolOp().toBindResult(
301             toArray(resultMessage.getControls())));
302        for (final InMemoryOperationInterceptor i : interceptors)
303        {
304          try
305          {
306            i.processSimpleBindResult(op);
307          }
308          catch (final Exception e)
309          {
310            Debug.debugException(e);
311            return new LDAPMessage(messageID,
312                 new BindResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
313                      ERR_DS_INTERCEPTOR_RESULT_ERROR.get(
314                           String.valueOf(op), i.getClass().getName(),
315                           StaticUtils.getExceptionMessage(e)),
316                      null, null));
317          }
318        }
319
320        return new LDAPMessage(messageID,
321             new BindResponseProtocolOp(op.getResult()),
322             op.getResult().getResponseControls());
323      }
324      finally
325      {
326        activeOperations.remove(messageID);
327      }
328    }
329    else
330    {
331      final InterceptedSASLBindOperation op =
332           new InterceptedSASLBindOperation(connection, messageID, request,
333                toArray(controls));
334      activeOperations.put(messageID, op);
335
336      try
337      {
338        for (final InMemoryOperationInterceptor i : interceptors)
339        {
340          try
341          {
342            i.processSASLBindRequest(op);
343          }
344          catch (final LDAPException le)
345          {
346            Debug.debugException(le);
347            return new LDAPMessage(messageID,
348                 new BindResponseProtocolOp(le.toLDAPResult()),
349                 le.getResponseControls());
350          }
351          catch (final Exception e)
352          {
353            Debug.debugException(e);
354            return new LDAPMessage(messageID,
355                 new BindResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
356                      ERR_DS_INTERCEPTOR_REQUEST_ERROR.get(
357                           String.valueOf(op), i.getClass().getName(),
358                           StaticUtils.getExceptionMessage(e)),
359                      null, null));
360          }
361        }
362
363        final LDAPMessage resultMessage = wrappedHandler.processBindRequest(
364             messageID,
365             new BindRequestProtocolOp(op.getRequest()),
366             op.getRequest().getControlList());
367        op.setResult(resultMessage.getBindResponseProtocolOp().toBindResult(
368             toArray(resultMessage.getControls())));
369        for (final InMemoryOperationInterceptor i : interceptors)
370        {
371          try
372          {
373            i.processSASLBindResult(op);
374          }
375          catch (final Exception e)
376          {
377            Debug.debugException(e);
378            return new LDAPMessage(messageID,
379                 new BindResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
380                      ERR_DS_INTERCEPTOR_RESULT_ERROR.get(
381                           String.valueOf(op), i.getClass().getName(),
382                           StaticUtils.getExceptionMessage(e)),
383                      null, null));
384          }
385        }
386
387        return new LDAPMessage(messageID,
388             new BindResponseProtocolOp(op.getResult()),
389             op.getResult().getResponseControls());
390      }
391      finally
392      {
393        activeOperations.remove(messageID);
394      }
395    }
396  }
397
398
399
400  /**
401   * {@inheritDoc}
402   */
403  @Override()
404  public LDAPMessage processCompareRequest(final int messageID,
405                          final CompareRequestProtocolOp request,
406                          final List<Control> controls)
407  {
408    final InterceptedCompareOperation op =
409         new InterceptedCompareOperation(connection, messageID, request,
410              toArray(controls));
411    activeOperations.put(messageID, op);
412
413    try
414    {
415      for (final InMemoryOperationInterceptor i : interceptors)
416      {
417        try
418        {
419          i.processCompareRequest(op);
420        }
421        catch (final LDAPException le)
422        {
423          Debug.debugException(le);
424          return new LDAPMessage(messageID,
425               new CompareResponseProtocolOp(le.toLDAPResult()),
426               le.getResponseControls());
427        }
428        catch (final Exception e)
429        {
430          Debug.debugException(e);
431          return new LDAPMessage(messageID,
432               new CompareResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
433                    ERR_DS_INTERCEPTOR_REQUEST_ERROR.get(
434                         String.valueOf(op), i.getClass().getName(),
435                         StaticUtils.getExceptionMessage(e)),
436                    null));
437        }
438      }
439
440      final LDAPMessage resultMessage = wrappedHandler.processCompareRequest(
441           messageID,
442           new CompareRequestProtocolOp((CompareRequest) op.getRequest()),
443           op.getRequest().getControlList());
444      op.setResult(resultMessage.getCompareResponseProtocolOp().toLDAPResult(
445           toArray(resultMessage.getControls())));
446      for (final InMemoryOperationInterceptor i : interceptors)
447      {
448        try
449        {
450          i.processCompareResult(op);
451        }
452        catch (final Exception e)
453        {
454          Debug.debugException(e);
455          return new LDAPMessage(messageID,
456               new CompareResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
457                    ERR_DS_INTERCEPTOR_RESULT_ERROR.get(
458                         String.valueOf(op), i.getClass().getName(),
459                         StaticUtils.getExceptionMessage(e)),
460                    null));
461        }
462      }
463
464      return new LDAPMessage(messageID,
465           new CompareResponseProtocolOp(op.getResult()),
466           op.getResult().getResponseControls());
467    }
468    finally
469    {
470      activeOperations.remove(messageID);
471    }
472  }
473
474
475
476  /**
477   * {@inheritDoc}
478   */
479  @Override()
480  public LDAPMessage processDeleteRequest(final int messageID,
481                                          final DeleteRequestProtocolOp request,
482                                          final List<Control> controls)
483  {
484    final InterceptedDeleteOperation op =
485         new InterceptedDeleteOperation(connection, messageID, request,
486              toArray(controls));
487    activeOperations.put(messageID, op);
488
489    try
490    {
491      for (final InMemoryOperationInterceptor i : interceptors)
492      {
493        try
494        {
495          i.processDeleteRequest(op);
496        }
497        catch (final LDAPException le)
498        {
499          Debug.debugException(le);
500          return new LDAPMessage(messageID,
501               new DeleteResponseProtocolOp(le.toLDAPResult()),
502               le.getResponseControls());
503        }
504        catch (final Exception e)
505        {
506          Debug.debugException(e);
507          return new LDAPMessage(messageID,
508               new DeleteResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
509                    ERR_DS_INTERCEPTOR_REQUEST_ERROR.get(
510                         String.valueOf(op), i.getClass().getName(),
511                         StaticUtils.getExceptionMessage(e)),
512                    null));
513        }
514      }
515
516      final LDAPMessage resultMessage = wrappedHandler.processDeleteRequest(
517           messageID,
518           new DeleteRequestProtocolOp((DeleteRequest) op.getRequest()),
519           op.getRequest().getControlList());
520      op.setResult(resultMessage.getDeleteResponseProtocolOp().toLDAPResult(
521           toArray(resultMessage.getControls())));
522      for (final InMemoryOperationInterceptor i : interceptors)
523      {
524        try
525        {
526          i.processDeleteResult(op);
527        }
528        catch (final Exception e)
529        {
530          Debug.debugException(e);
531          return new LDAPMessage(messageID,
532               new DeleteResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
533                    ERR_DS_INTERCEPTOR_RESULT_ERROR.get(
534                         String.valueOf(op), i.getClass().getName(),
535                         StaticUtils.getExceptionMessage(e)),
536                    null));
537        }
538      }
539
540      return new LDAPMessage(messageID,
541           new DeleteResponseProtocolOp(op.getResult()),
542           op.getResult().getResponseControls());
543    }
544    finally
545    {
546      activeOperations.remove(messageID);
547    }
548  }
549
550
551
552  /**
553   * {@inheritDoc}
554   */
555  @Override()
556  public LDAPMessage processExtendedRequest(final int messageID,
557                          final ExtendedRequestProtocolOp request,
558                          final List<Control> controls)
559  {
560    final InterceptedExtendedOperation op =
561         new InterceptedExtendedOperation(connection, messageID, request,
562              toArray(controls));
563    activeOperations.put(messageID, op);
564
565    try
566    {
567      for (final InMemoryOperationInterceptor i : interceptors)
568      {
569        try
570        {
571          i.processExtendedRequest(op);
572        }
573        catch (final LDAPException le)
574        {
575          Debug.debugException(le);
576          return new LDAPMessage(messageID,
577               new ExtendedResponseProtocolOp(le.toLDAPResult()),
578               le.getResponseControls());
579        }
580        catch (final Exception e)
581        {
582          Debug.debugException(e);
583          return new LDAPMessage(messageID,
584               new ExtendedResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
585                    ERR_DS_INTERCEPTOR_REQUEST_ERROR.get(
586                         String.valueOf(op), i.getClass().getName(),
587                         StaticUtils.getExceptionMessage(e)),
588                    null, null, null));
589        }
590      }
591
592      final LDAPMessage resultMessage = wrappedHandler.processExtendedRequest(
593           messageID,
594           new ExtendedRequestProtocolOp(op.getRequest()),
595           op.getRequest().getControlList());
596      op.setResult(
597           resultMessage.getExtendedResponseProtocolOp().toExtendedResult(
598                toArray(resultMessage.getControls())));
599      for (final InMemoryOperationInterceptor i : interceptors)
600      {
601        try
602        {
603          i.processExtendedResult(op);
604        }
605        catch (final Exception e)
606        {
607          Debug.debugException(e);
608          return new LDAPMessage(messageID,
609               new ExtendedResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
610                    ERR_DS_INTERCEPTOR_RESULT_ERROR.get(
611                         String.valueOf(op), i.getClass().getName(),
612                         StaticUtils.getExceptionMessage(e)),
613                    null, null, null));
614        }
615      }
616
617      return new LDAPMessage(messageID,
618           new ExtendedResponseProtocolOp(op.getResult()),
619           op.getResult().getResponseControls());
620    }
621    finally
622    {
623      activeOperations.remove(messageID);
624    }
625  }
626
627
628
629  /**
630   * {@inheritDoc}
631   */
632  @Override()
633  public LDAPMessage processModifyRequest(final int messageID,
634                                          final ModifyRequestProtocolOp request,
635                                          final List<Control> controls)
636  {
637    final InterceptedModifyOperation op =
638         new InterceptedModifyOperation(connection, messageID, request,
639              toArray(controls));
640    activeOperations.put(messageID, op);
641
642    try
643    {
644      for (final InMemoryOperationInterceptor i : interceptors)
645      {
646        try
647        {
648          i.processModifyRequest(op);
649        }
650        catch (final LDAPException le)
651        {
652          Debug.debugException(le);
653          return new LDAPMessage(messageID,
654               new ModifyResponseProtocolOp(le.toLDAPResult()),
655               le.getResponseControls());
656        }
657        catch (final Exception e)
658        {
659          Debug.debugException(e);
660          return new LDAPMessage(messageID,
661               new ModifyResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
662                    ERR_DS_INTERCEPTOR_REQUEST_ERROR.get(
663                         String.valueOf(op), i.getClass().getName(),
664                         StaticUtils.getExceptionMessage(e)),
665                    null));
666        }
667      }
668
669      final LDAPMessage resultMessage = wrappedHandler.processModifyRequest(
670           messageID,
671           new ModifyRequestProtocolOp((ModifyRequest) op.getRequest()),
672           op.getRequest().getControlList());
673      op.setResult(resultMessage.getModifyResponseProtocolOp().toLDAPResult(
674           toArray(resultMessage.getControls())));
675      for (final InMemoryOperationInterceptor i : interceptors)
676      {
677        try
678        {
679          i.processModifyResult(op);
680        }
681        catch (final Exception e)
682        {
683          Debug.debugException(e);
684          return new LDAPMessage(messageID,
685               new ModifyResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
686                    ERR_DS_INTERCEPTOR_RESULT_ERROR.get(
687                         String.valueOf(op), i.getClass().getName(),
688                         StaticUtils.getExceptionMessage(e)),
689                    null));
690        }
691      }
692
693      return new LDAPMessage(messageID,
694           new ModifyResponseProtocolOp(op.getResult()),
695           op.getResult().getResponseControls());
696    }
697    finally
698    {
699      activeOperations.remove(messageID);
700    }
701  }
702
703
704
705  /**
706   * {@inheritDoc}
707   */
708  @Override()
709  public LDAPMessage processModifyDNRequest(final int messageID,
710                          final ModifyDNRequestProtocolOp request,
711                          final List<Control> controls)
712  {
713    final InterceptedModifyDNOperation op =
714         new InterceptedModifyDNOperation(connection, messageID, request,
715              toArray(controls));
716    activeOperations.put(messageID, op);
717
718    try
719    {
720      for (final InMemoryOperationInterceptor i : interceptors)
721      {
722        try
723        {
724          i.processModifyDNRequest(op);
725        }
726        catch (final LDAPException le)
727        {
728          Debug.debugException(le);
729          return new LDAPMessage(messageID,
730               new ModifyDNResponseProtocolOp(le.toLDAPResult()),
731               le.getResponseControls());
732        }
733        catch (final Exception e)
734        {
735          Debug.debugException(e);
736          return new LDAPMessage(messageID,
737               new ModifyDNResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
738                    ERR_DS_INTERCEPTOR_REQUEST_ERROR.get(
739                         String.valueOf(op), i.getClass().getName(),
740                         StaticUtils.getExceptionMessage(e)),
741                    null));
742        }
743      }
744
745      final LDAPMessage resultMessage = wrappedHandler.processModifyDNRequest(
746           messageID,
747           new ModifyDNRequestProtocolOp((ModifyDNRequest) op.getRequest()),
748           op.getRequest().getControlList());
749      op.setResult(resultMessage.getModifyDNResponseProtocolOp().toLDAPResult(
750           toArray(resultMessage.getControls())));
751      for (final InMemoryOperationInterceptor i : interceptors)
752      {
753        try
754        {
755          i.processModifyDNResult(op);
756        }
757        catch (final Exception e)
758        {
759          Debug.debugException(e);
760          return new LDAPMessage(messageID,
761               new ModifyDNResponseProtocolOp(ResultCode.OTHER_INT_VALUE, null,
762                    ERR_DS_INTERCEPTOR_RESULT_ERROR.get(
763                         String.valueOf(op), i.getClass().getName(),
764                         StaticUtils.getExceptionMessage(e)),
765                    null));
766        }
767      }
768
769      return new LDAPMessage(messageID,
770           new ModifyDNResponseProtocolOp(op.getResult()),
771           op.getResult().getResponseControls());
772    }
773    finally
774    {
775      activeOperations.remove(messageID);
776    }
777  }
778
779
780
781  /**
782   * {@inheritDoc}
783   */
784  @Override()
785  public LDAPMessage processSearchRequest(final int messageID,
786                                          final SearchRequestProtocolOp request,
787                                          final List<Control> controls)
788  {
789    final InterceptedSearchOperation op =
790         new InterceptedSearchOperation(connection, messageID, request,
791              toArray(controls));
792    activeOperations.put(messageID, op);
793
794    try
795    {
796      for (final InMemoryOperationInterceptor i : interceptors)
797      {
798        try
799        {
800          i.processSearchRequest(op);
801        }
802        catch (final LDAPException le)
803        {
804          Debug.debugException(le);
805          return new LDAPMessage(messageID,
806               new SearchResultDoneProtocolOp(le.toLDAPResult()),
807               le.getResponseControls());
808        }
809        catch (final Exception e)
810        {
811          Debug.debugException(e);
812          return new LDAPMessage(messageID,
813               new SearchResultDoneProtocolOp(ResultCode.OTHER_INT_VALUE, null,
814                    ERR_DS_INTERCEPTOR_REQUEST_ERROR.get(
815                         String.valueOf(op), i.getClass().getName(),
816                         StaticUtils.getExceptionMessage(e)),
817                    null));
818        }
819      }
820
821      final LDAPMessage resultMessage = wrappedHandler.processSearchRequest(
822           messageID,
823           new SearchRequestProtocolOp((SearchRequest) op.getRequest()),
824           op.getRequest().getControlList());
825      op.setResult(resultMessage.getSearchResultDoneProtocolOp().toLDAPResult(
826           toArray(resultMessage.getControls())));
827      for (final InMemoryOperationInterceptor i : interceptors)
828      {
829        try
830        {
831          i.processSearchResult(op);
832        }
833        catch (final Exception e)
834        {
835          Debug.debugException(e);
836          return new LDAPMessage(messageID,
837               new SearchResultDoneProtocolOp(ResultCode.OTHER_INT_VALUE, null,
838                    ERR_DS_INTERCEPTOR_RESULT_ERROR.get(
839                         String.valueOf(op), i.getClass().getName(),
840                         StaticUtils.getExceptionMessage(e)),
841                    null));
842        }
843      }
844
845      return new LDAPMessage(messageID,
846           new SearchResultDoneProtocolOp(op.getResult()),
847           op.getResult().getResponseControls());
848    }
849    finally
850    {
851      activeOperations.remove(messageID);
852    }
853  }
854
855
856
857  /**
858   * {@inheritDoc}
859   */
860  public ObjectPair<SearchResultEntryProtocolOp,Control[]> transformEntry(
861              final int messageID, final SearchResultEntryProtocolOp entry,
862              final Control[] controls)
863  {
864    final InterceptedSearchOperation op =
865         (InterceptedSearchOperation) activeOperations.get(messageID);
866    if (op == null)
867    {
868      return new ObjectPair<SearchResultEntryProtocolOp,Control[]>(entry,
869           controls);
870    }
871
872    final InterceptedSearchEntry e =
873         new InterceptedSearchEntry(op, entry, controls);
874    for (final InMemoryOperationInterceptor i : interceptors)
875    {
876      try
877      {
878        i.processSearchEntry(e);
879        if (e.getSearchEntry() == null)
880        {
881          return null;
882        }
883      }
884      catch (final Exception ex)
885      {
886        Debug.debugException(ex);
887        return null;
888      }
889    }
890
891    return new ObjectPair<SearchResultEntryProtocolOp,Control[]>(
892         new SearchResultEntryProtocolOp(e.getSearchEntry()),
893         e.getSearchEntry().getControls());
894  }
895
896
897
898  /**
899   * {@inheritDoc}
900   */
901  public ObjectPair<SearchResultReferenceProtocolOp,Control[]>
902              transformReference(final int messageID,
903                   final SearchResultReferenceProtocolOp reference,
904                   final Control[] controls)
905  {
906    final InterceptedSearchOperation op =
907         (InterceptedSearchOperation) activeOperations.get(messageID);
908    if (op == null)
909    {
910      return new ObjectPair<SearchResultReferenceProtocolOp,Control[]>(
911           reference, controls);
912    }
913
914    final InterceptedSearchReference r =
915         new InterceptedSearchReference(op, reference, controls);
916    for (final InMemoryOperationInterceptor i : interceptors)
917    {
918      try
919      {
920        i.processSearchReference(r);
921        if (r.getSearchReference() == null)
922        {
923          return null;
924        }
925      }
926      catch (final Exception ex)
927      {
928        Debug.debugException(ex);
929        return null;
930      }
931    }
932
933    return new ObjectPair<SearchResultReferenceProtocolOp,Control[]>(
934         new SearchResultReferenceProtocolOp(r.getSearchReference()),
935         r.getSearchReference().getControls());
936  }
937
938
939
940  /**
941   * Transforms the provided intermediate response and/or set of controls to
942   * alter what will be returned to the client.
943   *
944   * @param  messageID  The message ID for the associated search operation.
945   * @param  response   The intermediate response to be processed.  It will not
946   *                    be {@code null}.
947   * @param  controls   The set of controls to be processed.  It will not be
948   *                    {@code null} but may be empty if there are no controls.
949   *
950   * @return  An {@link ObjectPair} containing a possibly updated intermediate
951   *          response and set of controls, or {@code null} to indicate that the
952   *          response should not be returned to the client.
953   */
954  public ObjectPair<IntermediateResponseProtocolOp,Control[]>
955              transformIntermediateResponse(final int messageID,
956                   final IntermediateResponseProtocolOp response,
957                   final Control[] controls)
958  {
959    final InterceptedOperation op = activeOperations.get(messageID);
960    if (op == null)
961    {
962      return new ObjectPair<IntermediateResponseProtocolOp,Control[]>(response,
963           controls);
964    }
965
966    final InterceptedIntermediateResponse r =
967         new InterceptedIntermediateResponse(op, response, controls);
968    for (final InMemoryOperationInterceptor i : interceptors)
969    {
970      try
971      {
972        i.processIntermediateResponse(r);
973        if (r.getIntermediateResponse() == null)
974        {
975          return null;
976        }
977      }
978      catch (final Exception ex)
979      {
980        Debug.debugException(ex);
981        return null;
982      }
983    }
984
985    return new ObjectPair<IntermediateResponseProtocolOp,Control[]>(
986         new IntermediateResponseProtocolOp(r.getIntermediateResponse()),
987         r.getIntermediateResponse().getControls());
988  }
989
990
991
992  /**
993   * Converts the provided control list to a control array.
994   *
995   * @param  controls  The list of controls to be converted to an array.
996   *
997   * @return  The resulting array of controls.
998   */
999  private static Control[] toArray(final List<Control> controls)
1000  {
1001    if ((controls == null) || controls.isEmpty())
1002    {
1003      return StaticUtils.NO_CONTROLS;
1004    }
1005
1006    final Control[] controlArray = new Control[controls.size()];
1007    return controls.toArray(controlArray);
1008  }
1009}