001/*
002 * Copyright 2007-2020 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2007-2020 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2008-2020 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.ldap.sdk;
037
038
039
040import java.util.List;
041
042import com.unboundid.util.NotMutable;
043import com.unboundid.util.StaticUtils;
044import com.unboundid.util.ThreadSafety;
045import com.unboundid.util.ThreadSafetyLevel;
046
047
048
049/**
050 * This class defines an exception that can be thrown if a problem occurs while
051 * performing LDAP-related processing.  It includes all of the elements of the
052 * {@link SearchResult} object, potentially including entries and references
053 * returned before the failure result.
054 */
055@NotMutable()
056@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
057public final class LDAPSearchException
058       extends LDAPException
059{
060  /**
061   * The serial version UID for this serializable class.
062   */
063  private static final long serialVersionUID = 350230437196125113L;
064
065
066
067  // The search result with information from this exception.
068  private final SearchResult searchResult;
069
070
071
072  /**
073   * Creates a new LDAP search exception with the provided information.
074   *
075   * @param  resultCode    The result code for this LDAP search exception.
076   * @param  errorMessage  The error message for this LDAP search exception.
077   */
078  public LDAPSearchException(final ResultCode resultCode,
079                             final String errorMessage)
080  {
081    super(resultCode, errorMessage);
082
083    searchResult = new SearchResult(-1, resultCode, errorMessage, null,
084         StaticUtils.NO_STRINGS, 0, 0, StaticUtils.NO_CONTROLS);
085  }
086
087
088
089  /**
090   * Creates a new LDAP search exception with the provided information.
091   *
092   * @param  resultCode    The result code for this LDAP search exception.
093   * @param  errorMessage  The error message for this LDAP search exception.
094   * @param  cause         The underlying exception that triggered this LDAP
095   *                       search exception.
096   */
097  public LDAPSearchException(final ResultCode resultCode,
098                             final String errorMessage, final Throwable cause)
099  {
100    super(resultCode, errorMessage, cause);
101
102    searchResult = new SearchResult(-1, resultCode, errorMessage, null,
103         StaticUtils.NO_STRINGS , 0, 0, StaticUtils.NO_CONTROLS);
104  }
105
106
107
108  /**
109   * Creates a new LDAP search exception from the provided exception.
110   *
111   * @param  ldapException  The LDAP exception with the information to include
112   *                        in this LDAP search exception.
113   */
114  public LDAPSearchException(final LDAPException ldapException)
115  {
116    super(ldapException.getResultCode(), ldapException.getMessage(),
117          ldapException.getMatchedDN(), ldapException.getReferralURLs(),
118          ldapException.getResponseControls(), ldapException);
119
120    if (ldapException instanceof LDAPSearchException)
121    {
122      final LDAPSearchException lse = (LDAPSearchException) ldapException;
123      searchResult = lse.searchResult;
124    }
125    else
126    {
127      searchResult = new SearchResult(-1, ldapException.getResultCode(),
128                                      ldapException.getMessage(),
129                                      ldapException.getMatchedDN(),
130                                      ldapException.getReferralURLs(), 0, 0,
131                                      ldapException.getResponseControls());
132    }
133  }
134
135
136
137  /**
138   * Creates a new LDAP search exception with the provided result.
139   *
140   * @param  searchResult  The search result to use to create this LDAP search
141   *                       exception.
142   */
143  public LDAPSearchException(final SearchResult searchResult)
144  {
145    super(searchResult);
146
147    this.searchResult = searchResult;
148  }
149
150
151
152  /**
153   * Retrieves the search result object associated with this LDAP search
154   * exception.
155   *
156   * @return  The search result object associated with this LDAP search
157   *          exception.
158   */
159  public SearchResult getSearchResult()
160  {
161    return searchResult;
162  }
163
164
165
166  /**
167   * Retrieves the number of matching entries returned for the search operation
168   * before this exception was thrown.
169   *
170   * @return  The number of matching entries returned for the search operation
171   *          before this exception was thrown.
172   */
173  public int getEntryCount()
174  {
175    return searchResult.getEntryCount();
176  }
177
178
179
180  /**
181   * Retrieves the number of search references returned for the search
182   * operation before this exception was thrown.
183   *
184   * @return  The number of search references returned for the search operation
185   *          before this exception was thrown.
186   */
187  public int getReferenceCount()
188  {
189    return searchResult.getReferenceCount();
190  }
191
192
193
194  /**
195   * Retrieves a list containing the matching entries returned from the search
196   * operation before this exception was thrown.  This will only be available if
197   * a {@code SearchResultListener} was not used during the search.
198   *
199   * @return  A list containing the matching entries returned from the search
200   *          operation before this exception was thrown, or {@code null} if a
201   *          {@code SearchResultListener} was used during the search.
202   */
203  public List<SearchResultEntry> getSearchEntries()
204  {
205    return searchResult.getSearchEntries();
206  }
207
208
209
210  /**
211   * Retrieves a list containing the search references returned from the search
212   * operation before this exception was thrown.  This will only be available if
213   * a {@code SearchResultListener} was not used during the search.
214   *
215   * @return  A list containing the search references returned from the search
216   *          operation before this exception was thrown, or {@code null} if a
217   *          {@code SearchResultListener} was used during the search.
218   */
219  public List<SearchResultReference> getSearchReferences()
220  {
221    return searchResult.getSearchReferences();
222  }
223
224
225
226  /**
227   * Creates a new {@code SearchResult} object from this exception.
228   *
229   * @return  The {@code SearchResult} object created from this exception.
230   */
231  @Override()
232  public SearchResult toLDAPResult()
233  {
234    return searchResult;
235  }
236
237
238
239  /**
240   * Appends a string representation of this LDAP exception to the provided
241   * buffer.
242   *
243   * @param  buffer  The buffer to which to append a string representation of
244   *                 this LDAP exception.
245   */
246  @Override()
247  public void toString(final StringBuilder buffer)
248  {
249    super.toString(buffer);
250  }
251
252
253
254  /**
255   * {@inheritDoc}
256   */
257  @Override()
258  public void toString(final StringBuilder buffer, final boolean includeCause,
259                       final boolean includeStackTrace)
260  {
261    buffer.append("LDAPException(resultCode=");
262    buffer.append(getResultCode());
263    buffer.append(", numEntries=");
264    buffer.append(searchResult.getEntryCount());
265    buffer.append(", numReferences=");
266    buffer.append(searchResult.getReferenceCount());
267
268    final String errorMessage = getMessage();
269    final String diagnosticMessage = getDiagnosticMessage();
270    if ((errorMessage != null) && (! errorMessage.equals(diagnosticMessage)))
271    {
272      buffer.append(", errorMessage='");
273      buffer.append(errorMessage);
274      buffer.append('\'');
275    }
276
277    if (diagnosticMessage != null)
278    {
279      buffer.append(", diagnosticMessage='");
280      buffer.append(diagnosticMessage);
281      buffer.append('\'');
282    }
283
284    final String matchedDN = getMatchedDN();
285    if (matchedDN != null)
286    {
287      buffer.append(", matchedDN='");
288      buffer.append(matchedDN);
289      buffer.append('\'');
290    }
291
292    final String[] referralURLs = getReferralURLs();
293    if (referralURLs.length > 0)
294    {
295      buffer.append(", referralURLs={");
296
297      for (int i=0; i < referralURLs.length; i++)
298      {
299        if (i > 0)
300        {
301          buffer.append(", ");
302        }
303
304        buffer.append('\'');
305        buffer.append(referralURLs[i]);
306        buffer.append('\'');
307      }
308
309      buffer.append('}');
310    }
311
312    final Control[] responseControls = getResponseControls();
313    if (responseControls.length > 0)
314    {
315      buffer.append(", responseControls={");
316
317      for (int i=0; i < responseControls.length; i++)
318      {
319        if (i > 0)
320        {
321          buffer.append(", ");
322        }
323
324        buffer.append(responseControls[i]);
325      }
326
327      buffer.append('}');
328    }
329
330    if (includeStackTrace)
331    {
332      buffer.append(", trace='");
333      StaticUtils.getStackTrace(getStackTrace(), buffer);
334      buffer.append('\'');
335    }
336
337    if (includeCause || includeStackTrace)
338    {
339      final Throwable cause = getCause();
340      if (cause != null)
341      {
342        buffer.append(", cause=");
343        buffer.append(StaticUtils.getExceptionMessage(cause, true,
344             includeStackTrace));
345      }
346    }
347
348    final String ldapSDKVersionString = ", ldapSDKVersion=" +
349         Version.NUMERIC_VERSION_STRING + ", revision=" + Version.REVISION_ID;
350    if (buffer.indexOf(ldapSDKVersionString) < 0)
351    {
352      buffer.append(ldapSDKVersionString);
353    }
354
355    buffer.append("')");
356  }
357}