001/*
002 * Copyright 2010-2017 UnboundID Corp.
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2010-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;
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<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}