001    /*
002     * Copyright 2014-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2014-2015 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     */
021    package com.unboundid.ldap.listener.interceptor;
022    
023    
024    
025    import java.util.List;
026    import java.util.HashMap;
027    import java.util.Map;
028    
029    import com.unboundid.ldap.listener.IntermediateResponseTransformer;
030    import com.unboundid.ldap.listener.LDAPListenerClientConnection;
031    import com.unboundid.ldap.listener.LDAPListenerRequestHandler;
032    import com.unboundid.ldap.listener.SearchEntryTransformer;
033    import com.unboundid.ldap.listener.SearchReferenceTransformer;
034    import com.unboundid.ldap.protocol.AddRequestProtocolOp;
035    import com.unboundid.ldap.protocol.AddResponseProtocolOp;
036    import com.unboundid.ldap.protocol.BindRequestProtocolOp;
037    import com.unboundid.ldap.protocol.BindResponseProtocolOp;
038    import com.unboundid.ldap.protocol.CompareRequestProtocolOp;
039    import com.unboundid.ldap.protocol.CompareResponseProtocolOp;
040    import com.unboundid.ldap.protocol.DeleteRequestProtocolOp;
041    import com.unboundid.ldap.protocol.DeleteResponseProtocolOp;
042    import com.unboundid.ldap.protocol.ExtendedRequestProtocolOp;
043    import com.unboundid.ldap.protocol.ExtendedResponseProtocolOp;
044    import com.unboundid.ldap.protocol.IntermediateResponseProtocolOp;
045    import com.unboundid.ldap.protocol.LDAPMessage;
046    import com.unboundid.ldap.protocol.ModifyRequestProtocolOp;
047    import com.unboundid.ldap.protocol.ModifyResponseProtocolOp;
048    import com.unboundid.ldap.protocol.ModifyDNRequestProtocolOp;
049    import com.unboundid.ldap.protocol.ModifyDNResponseProtocolOp;
050    import com.unboundid.ldap.protocol.SearchRequestProtocolOp;
051    import com.unboundid.ldap.protocol.SearchResultDoneProtocolOp;
052    import com.unboundid.ldap.protocol.SearchResultEntryProtocolOp;
053    import com.unboundid.ldap.protocol.SearchResultReferenceProtocolOp;
054    import com.unboundid.ldap.sdk.AddRequest;
055    import com.unboundid.ldap.sdk.CompareRequest;
056    import com.unboundid.ldap.sdk.Control;
057    import com.unboundid.ldap.sdk.DeleteRequest;
058    import com.unboundid.ldap.sdk.LDAPException;
059    import com.unboundid.ldap.sdk.ModifyRequest;
060    import com.unboundid.ldap.sdk.ModifyDNRequest;
061    import com.unboundid.ldap.sdk.ResultCode;
062    import com.unboundid.ldap.sdk.SearchRequest;
063    import com.unboundid.util.Debug;
064    import com.unboundid.util.ObjectPair;
065    import com.unboundid.util.ThreadSafety;
066    import com.unboundid.util.ThreadSafetyLevel;
067    import com.unboundid.util.StaticUtils;
068    
069    import 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)
079    public 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    }