001/*
002 * Copyright 2010-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2010-2018 Ping Identity Corporation
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;
022
023
024
025import java.io.Serializable;
026import java.util.ArrayList;
027import java.util.Collection;
028import java.util.Collections;
029import java.util.List;
030
031import com.unboundid.ldap.protocol.AddRequestProtocolOp;
032import com.unboundid.ldap.protocol.AddResponseProtocolOp;
033import com.unboundid.ldap.protocol.BindRequestProtocolOp;
034import com.unboundid.ldap.protocol.BindResponseProtocolOp;
035import com.unboundid.ldap.protocol.CompareRequestProtocolOp;
036import com.unboundid.ldap.protocol.CompareResponseProtocolOp;
037import com.unboundid.ldap.protocol.DeleteRequestProtocolOp;
038import com.unboundid.ldap.protocol.DeleteResponseProtocolOp;
039import com.unboundid.ldap.protocol.ExtendedRequestProtocolOp;
040import com.unboundid.ldap.protocol.ExtendedResponseProtocolOp;
041import com.unboundid.ldap.protocol.LDAPMessage;
042import com.unboundid.ldap.protocol.ModifyRequestProtocolOp;
043import com.unboundid.ldap.protocol.ModifyResponseProtocolOp;
044import com.unboundid.ldap.protocol.ModifyDNRequestProtocolOp;
045import com.unboundid.ldap.protocol.ModifyDNResponseProtocolOp;
046import com.unboundid.ldap.protocol.SearchRequestProtocolOp;
047import com.unboundid.ldap.protocol.SearchResultDoneProtocolOp;
048import com.unboundid.ldap.protocol.SearchResultEntryProtocolOp;
049import com.unboundid.ldap.protocol.SearchResultReferenceProtocolOp;
050import com.unboundid.ldap.sdk.Control;
051import com.unboundid.ldap.sdk.Entry;
052import com.unboundid.ldap.sdk.LDAPException;
053import com.unboundid.ldap.sdk.ResultCode;
054import com.unboundid.ldap.sdk.SearchResultReference;
055import com.unboundid.util.Debug;
056import com.unboundid.util.NotMutable;
057import com.unboundid.util.ThreadSafety;
058import com.unboundid.util.ThreadSafetyLevel;
059import 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)
070public 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<>(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<>(searchReferences.size());
214      for (final SearchResultReference r : searchReferences)
215      {
216        l.add(new SearchResultReferenceProtocolOp(r));
217      }
218
219      searchReferenceProtocolOps = Collections.unmodifiableList(l);
220    }
221  }
222
223
224
225  /**
226   * Creates a new instance of this canned response request handler using the
227   * information of the provided handler and the given client connection.
228   *
229   * @param  h  The request handler from which to take the canned responses.
230   * @param  c  The connection to use to communicate with the client.
231   */
232  private CannedResponseRequestHandler(final CannedResponseRequestHandler h,
233               final LDAPListenerClientConnection c)
234  {
235    addResponseProtocolOp      = h.addResponseProtocolOp;
236    bindResponseProtocolOp     = h.bindResponseProtocolOp;
237    compareResponseProtocolOp  = h.compareResponseProtocolOp;
238    deleteResponseProtocolOp   = h.deleteResponseProtocolOp;
239    extendedResponseProtocolOp = h.extendedResponseProtocolOp;
240    modifyResponseProtocolOp   = h.modifyResponseProtocolOp;
241    modifyDNResponseProtocolOp = h.modifyDNResponseProtocolOp;
242    searchEntryProtocolOps     = h.searchEntryProtocolOps;
243    searchReferenceProtocolOps = h.searchReferenceProtocolOps;
244    searchResultDoneProtocolOp = h.searchResultDoneProtocolOp;
245
246    clientConnection = c;
247  }
248
249
250
251  /**
252   * {@inheritDoc}
253   */
254  @Override()
255  public CannedResponseRequestHandler newInstance(
256              final LDAPListenerClientConnection connection)
257         throws LDAPException
258  {
259    return new CannedResponseRequestHandler(this, connection);
260  }
261
262
263
264  /**
265   * {@inheritDoc}
266   */
267  @Override()
268  public LDAPMessage processAddRequest(final int messageID,
269                                       final AddRequestProtocolOp request,
270                                       final List<Control> controls)
271  {
272    return new LDAPMessage(messageID, addResponseProtocolOp,
273         Collections.<Control>emptyList());
274  }
275
276
277
278  /**
279   * {@inheritDoc}
280   */
281  @Override()
282  public LDAPMessage processBindRequest(final int messageID,
283                                        final BindRequestProtocolOp request,
284                                        final List<Control> controls)
285  {
286    return new LDAPMessage(messageID, bindResponseProtocolOp,
287         Collections.<Control>emptyList());
288  }
289
290
291
292  /**
293   * {@inheritDoc}
294   */
295  @Override()
296  public LDAPMessage processCompareRequest(final int messageID,
297                          final CompareRequestProtocolOp request,
298                          final List<Control> controls)
299  {
300    return new LDAPMessage(messageID, compareResponseProtocolOp,
301         Collections.<Control>emptyList());
302  }
303
304
305
306  /**
307   * {@inheritDoc}
308   */
309  @Override()
310  public LDAPMessage processDeleteRequest(final int messageID,
311                                          final DeleteRequestProtocolOp request,
312                                          final List<Control> controls)
313  {
314    return new LDAPMessage(messageID, deleteResponseProtocolOp,
315         Collections.<Control>emptyList());
316  }
317
318
319
320  /**
321   * {@inheritDoc}
322   */
323  @Override()
324  public LDAPMessage processExtendedRequest(final int messageID,
325                          final ExtendedRequestProtocolOp request,
326                          final List<Control> controls)
327  {
328    return new LDAPMessage(messageID, extendedResponseProtocolOp,
329         Collections.<Control>emptyList());
330  }
331
332
333
334  /**
335   * {@inheritDoc}
336   */
337  @Override()
338  public LDAPMessage processModifyRequest(final int messageID,
339                                          final ModifyRequestProtocolOp request,
340                                          final List<Control> controls)
341  {
342    return new LDAPMessage(messageID, modifyResponseProtocolOp,
343         Collections.<Control>emptyList());
344  }
345
346
347
348  /**
349   * {@inheritDoc}
350   */
351  @Override()
352  public LDAPMessage processModifyDNRequest(final int messageID,
353                          final ModifyDNRequestProtocolOp request,
354                          final List<Control> controls)
355  {
356    return new LDAPMessage(messageID, modifyDNResponseProtocolOp,
357         Collections.<Control>emptyList());
358  }
359
360
361
362  /**
363   * {@inheritDoc}
364   */
365  @Override()
366  public LDAPMessage processSearchRequest(final int messageID,
367                                          final SearchRequestProtocolOp request,
368                                          final List<Control> controls)
369  {
370    for (final SearchResultEntryProtocolOp e : searchEntryProtocolOps)
371    {
372      try
373      {
374        clientConnection.sendSearchResultEntry(messageID, e);
375      }
376      catch (final Exception ex)
377      {
378        Debug.debugException(ex);
379      }
380    }
381
382    for (final SearchResultReferenceProtocolOp r : searchReferenceProtocolOps)
383    {
384      try
385      {
386        clientConnection.sendSearchResultReference(messageID, r);
387      }
388      catch (final Exception ex)
389      {
390        Debug.debugException(ex);
391      }
392    }
393
394    return new LDAPMessage(messageID, searchResultDoneProtocolOp,
395         Collections.<Control>emptyList());
396  }
397}