001    /*
002     * Copyright 2010-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2010-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;
022    
023    
024    
025    import java.io.Serializable;
026    import java.util.ArrayList;
027    import java.util.Collection;
028    import java.util.Collections;
029    import java.util.List;
030    
031    import com.unboundid.ldap.protocol.AddRequestProtocolOp;
032    import com.unboundid.ldap.protocol.AddResponseProtocolOp;
033    import com.unboundid.ldap.protocol.BindRequestProtocolOp;
034    import com.unboundid.ldap.protocol.BindResponseProtocolOp;
035    import com.unboundid.ldap.protocol.CompareRequestProtocolOp;
036    import com.unboundid.ldap.protocol.CompareResponseProtocolOp;
037    import com.unboundid.ldap.protocol.DeleteRequestProtocolOp;
038    import com.unboundid.ldap.protocol.DeleteResponseProtocolOp;
039    import com.unboundid.ldap.protocol.ExtendedRequestProtocolOp;
040    import com.unboundid.ldap.protocol.ExtendedResponseProtocolOp;
041    import com.unboundid.ldap.protocol.LDAPMessage;
042    import com.unboundid.ldap.protocol.ModifyRequestProtocolOp;
043    import com.unboundid.ldap.protocol.ModifyResponseProtocolOp;
044    import com.unboundid.ldap.protocol.ModifyDNRequestProtocolOp;
045    import com.unboundid.ldap.protocol.ModifyDNResponseProtocolOp;
046    import com.unboundid.ldap.protocol.SearchRequestProtocolOp;
047    import com.unboundid.ldap.protocol.SearchResultDoneProtocolOp;
048    import com.unboundid.ldap.protocol.SearchResultEntryProtocolOp;
049    import com.unboundid.ldap.protocol.SearchResultReferenceProtocolOp;
050    import com.unboundid.ldap.sdk.Control;
051    import com.unboundid.ldap.sdk.Entry;
052    import com.unboundid.ldap.sdk.LDAPException;
053    import com.unboundid.ldap.sdk.ResultCode;
054    import com.unboundid.ldap.sdk.SearchResultReference;
055    import com.unboundid.util.Debug;
056    import com.unboundid.util.NotMutable;
057    import com.unboundid.util.ThreadSafety;
058    import com.unboundid.util.ThreadSafetyLevel;
059    import com.unboundid.util.Validator;
060    
061    
062    
063    /**
064     * This class provides a very simple LDAP listener request handler
065     * implementation that simply returns a canned response to the client for each
066     * type of operation.
067     */
068    @NotMutable()
069    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
070    public final class CannedResponseRequestHandler
071           extends LDAPListenerRequestHandler
072           implements Serializable
073    {
074      /**
075       * The serial version UID for this serializable class.
076       */
077      private static final long serialVersionUID = 6199105854736880833L;
078    
079    
080    
081      // The protocol ops that will be used in responses.
082      private final AddResponseProtocolOp addResponseProtocolOp;
083      private final BindResponseProtocolOp bindResponseProtocolOp;
084      private final CompareResponseProtocolOp compareResponseProtocolOp;
085      private final DeleteResponseProtocolOp deleteResponseProtocolOp;
086      private final ExtendedResponseProtocolOp extendedResponseProtocolOp;
087      private final ModifyResponseProtocolOp modifyResponseProtocolOp;
088      private final ModifyDNResponseProtocolOp modifyDNResponseProtocolOp;
089      private final List<SearchResultEntryProtocolOp> searchEntryProtocolOps;
090      private final List<SearchResultReferenceProtocolOp>
091           searchReferenceProtocolOps;
092      private final SearchResultDoneProtocolOp searchResultDoneProtocolOp;
093    
094      // The connection that will be used to communicate with the client.
095      private final LDAPListenerClientConnection clientConnection;
096    
097    
098    
099      /**
100       * Creates a new instance of this canned response request handler that will
101       * immediately return a "SUCCESS" response to any request that is received.
102       */
103      public CannedResponseRequestHandler()
104      {
105        this(ResultCode.SUCCESS, null, null, null);
106      }
107    
108    
109    
110      /**
111       * Creates a new instance of this canned response request handler that will
112       * immediately return a response with the provided information to any request
113       * that is received.
114       *
115       * @param  resultCode         The result code to use for the responses.  It
116       *                            must not be {@code null}.
117       * @param  matchedDN          The matched DN to use for the responses.  It may
118       *                            be {@code null} if no matched DN should be
119       *                            included.
120       * @param  diagnosticMessage  The diagnostic message to use for the responses.
121       *                            It may be {@code null} if no diagnostic message
122       *                            should be included.
123       * @param  referralURLs       The referral URLs to use for the responses.  It
124       *                            may be empty or {@code null} if no referral URLs
125       *                            should be included.
126       */
127      public CannedResponseRequestHandler(final ResultCode resultCode,
128                                          final String matchedDN,
129                                          final String diagnosticMessage,
130                                          final List<String> referralURLs)
131      {
132        this(resultCode, matchedDN, diagnosticMessage, referralURLs, null, null);
133      }
134    
135    
136    
137      /**
138       * Creates a new instance of this canned response request handler that will
139       * immediately return a response with the provided information to any request
140       * that is received.
141       *
142       * @param  resultCode         The result code to use for the responses.  It
143       *                            must not be {@code null}.
144       * @param  matchedDN          The matched DN to use for the responses.  It may
145       *                            be {@code null} if no matched DN should be
146       *                            included.
147       * @param  diagnosticMessage  The diagnostic message to use for the responses.
148       *                            It may be {@code null} if no diagnostic message
149       *                            should be included.
150       * @param  referralURLs       The referral URLs to use for the responses.  It
151       *                            may be empty or {@code null} if no referral URLs
152       *                            should be included.
153       * @param  searchEntries      The set of search result entries that should be
154       *                            returned for every search.  It may be
155       *                            {@code null} or empty if no entries are
156       *                            required.
157       * @param  searchReferences   The set of search result references that should
158       *                            be returned for every search.  It may be
159       *                            {@code null} or empty if no references are
160       *                            required.
161       */
162      public CannedResponseRequestHandler(final ResultCode resultCode,
163                  final String matchedDN, final String diagnosticMessage,
164                  final List<String> referralURLs,
165                  final Collection<? extends Entry> searchEntries,
166                  final Collection<SearchResultReference> searchReferences)
167      {
168        Validator.ensureNotNull(resultCode);
169    
170        clientConnection = null;
171    
172        final int rc = resultCode.intValue();
173        addResponseProtocolOp = new AddResponseProtocolOp(rc, matchedDN,
174             diagnosticMessage, referralURLs);
175        bindResponseProtocolOp = new BindResponseProtocolOp(rc, matchedDN,
176             diagnosticMessage, referralURLs, null);
177        compareResponseProtocolOp = new CompareResponseProtocolOp(rc, matchedDN,
178             diagnosticMessage, referralURLs);
179        deleteResponseProtocolOp = new DeleteResponseProtocolOp(rc, matchedDN,
180             diagnosticMessage, referralURLs);
181        extendedResponseProtocolOp = new ExtendedResponseProtocolOp(rc, matchedDN,
182             diagnosticMessage, referralURLs, null, null);
183        modifyResponseProtocolOp = new ModifyResponseProtocolOp(rc, matchedDN,
184             diagnosticMessage, referralURLs);
185        modifyDNResponseProtocolOp = new ModifyDNResponseProtocolOp(rc, matchedDN,
186             diagnosticMessage, referralURLs);
187        searchResultDoneProtocolOp = new SearchResultDoneProtocolOp(rc, matchedDN,
188             diagnosticMessage, referralURLs);
189    
190        if ((searchEntries == null) || searchEntries.isEmpty())
191        {
192          searchEntryProtocolOps = Collections.emptyList();
193        }
194        else
195        {
196          final ArrayList<SearchResultEntryProtocolOp> l =
197               new ArrayList<SearchResultEntryProtocolOp>(searchEntries.size());
198          for (final Entry e : searchEntries)
199          {
200            l.add(new SearchResultEntryProtocolOp(e));
201          }
202    
203          searchEntryProtocolOps = Collections.unmodifiableList(l);
204        }
205    
206        if ((searchReferences == null) || searchReferences.isEmpty())
207        {
208          searchReferenceProtocolOps = Collections.emptyList();
209        }
210        else
211        {
212          final ArrayList<SearchResultReferenceProtocolOp> l =
213               new ArrayList<SearchResultReferenceProtocolOp>(
214                    searchReferences.size());
215          for (final SearchResultReference r : searchReferences)
216          {
217            l.add(new SearchResultReferenceProtocolOp(r));
218          }
219    
220          searchReferenceProtocolOps = Collections.unmodifiableList(l);
221        }
222      }
223    
224    
225    
226      /**
227       * Creates a new instance of this canned response request handler using the
228       * information of the provided handler and the given client connection.
229       *
230       * @param  h  The request handler from which to take the canned responses.
231       * @param  c  The connection to use to communicate with the client.
232       */
233      private CannedResponseRequestHandler(final CannedResponseRequestHandler h,
234                   final LDAPListenerClientConnection c)
235      {
236        addResponseProtocolOp      = h.addResponseProtocolOp;
237        bindResponseProtocolOp     = h.bindResponseProtocolOp;
238        compareResponseProtocolOp  = h.compareResponseProtocolOp;
239        deleteResponseProtocolOp   = h.deleteResponseProtocolOp;
240        extendedResponseProtocolOp = h.extendedResponseProtocolOp;
241        modifyResponseProtocolOp   = h.modifyResponseProtocolOp;
242        modifyDNResponseProtocolOp = h.modifyDNResponseProtocolOp;
243        searchEntryProtocolOps     = h.searchEntryProtocolOps;
244        searchReferenceProtocolOps = h.searchReferenceProtocolOps;
245        searchResultDoneProtocolOp = h.searchResultDoneProtocolOp;
246    
247        clientConnection = c;
248      }
249    
250    
251    
252      /**
253       * {@inheritDoc}
254       */
255      @Override()
256      public CannedResponseRequestHandler newInstance(
257                  final LDAPListenerClientConnection connection)
258             throws LDAPException
259      {
260        return new CannedResponseRequestHandler(this, connection);
261      }
262    
263    
264    
265      /**
266       * {@inheritDoc}
267       */
268      @Override()
269      public LDAPMessage processAddRequest(final int messageID,
270                                           final AddRequestProtocolOp request,
271                                           final List<Control> controls)
272      {
273        return new LDAPMessage(messageID, addResponseProtocolOp,
274             Collections.<Control>emptyList());
275      }
276    
277    
278    
279      /**
280       * {@inheritDoc}
281       */
282      @Override()
283      public LDAPMessage processBindRequest(final int messageID,
284                                            final BindRequestProtocolOp request,
285                                            final List<Control> controls)
286      {
287        return new LDAPMessage(messageID, bindResponseProtocolOp,
288             Collections.<Control>emptyList());
289      }
290    
291    
292    
293      /**
294       * {@inheritDoc}
295       */
296      @Override()
297      public LDAPMessage processCompareRequest(final int messageID,
298                              final CompareRequestProtocolOp request,
299                              final List<Control> controls)
300      {
301        return new LDAPMessage(messageID, compareResponseProtocolOp,
302             Collections.<Control>emptyList());
303      }
304    
305    
306    
307      /**
308       * {@inheritDoc}
309       */
310      @Override()
311      public LDAPMessage processDeleteRequest(final int messageID,
312                                              final DeleteRequestProtocolOp request,
313                                              final List<Control> controls)
314      {
315        return new LDAPMessage(messageID, deleteResponseProtocolOp,
316             Collections.<Control>emptyList());
317      }
318    
319    
320    
321      /**
322       * {@inheritDoc}
323       */
324      @Override()
325      public LDAPMessage processExtendedRequest(final int messageID,
326                              final ExtendedRequestProtocolOp request,
327                              final List<Control> controls)
328      {
329        return new LDAPMessage(messageID, extendedResponseProtocolOp,
330             Collections.<Control>emptyList());
331      }
332    
333    
334    
335      /**
336       * {@inheritDoc}
337       */
338      @Override()
339      public LDAPMessage processModifyRequest(final int messageID,
340                                              final ModifyRequestProtocolOp request,
341                                              final List<Control> controls)
342      {
343        return new LDAPMessage(messageID, modifyResponseProtocolOp,
344             Collections.<Control>emptyList());
345      }
346    
347    
348    
349      /**
350       * {@inheritDoc}
351       */
352      @Override()
353      public LDAPMessage processModifyDNRequest(final int messageID,
354                              final ModifyDNRequestProtocolOp request,
355                              final List<Control> controls)
356      {
357        return new LDAPMessage(messageID, modifyDNResponseProtocolOp,
358             Collections.<Control>emptyList());
359      }
360    
361    
362    
363      /**
364       * {@inheritDoc}
365       */
366      @Override()
367      public LDAPMessage processSearchRequest(final int messageID,
368                                              final SearchRequestProtocolOp request,
369                                              final List<Control> controls)
370      {
371        for (final SearchResultEntryProtocolOp e : searchEntryProtocolOps)
372        {
373          try
374          {
375            clientConnection.sendSearchResultEntry(messageID, e);
376          }
377          catch (final Exception ex)
378          {
379            Debug.debugException(ex);
380          }
381        }
382    
383        for (final SearchResultReferenceProtocolOp r : searchReferenceProtocolOps)
384        {
385          try
386          {
387            clientConnection.sendSearchResultReference(messageID, r);
388          }
389          catch (final Exception ex)
390          {
391            Debug.debugException(ex);
392          }
393        }
394    
395        return new LDAPMessage(messageID, searchResultDoneProtocolOp,
396             Collections.<Control>emptyList());
397      }
398    }