001/*
002 * Copyright 2020 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 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) 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.unboundidds.extensions;
037
038
039
040import com.unboundid.asn1.ASN1Element;
041import com.unboundid.asn1.ASN1Integer;
042import com.unboundid.asn1.ASN1OctetString;
043import com.unboundid.asn1.ASN1Sequence;
044import com.unboundid.ldap.sdk.Control;
045import com.unboundid.ldap.sdk.ExtendedResult;
046import com.unboundid.ldap.sdk.LDAPException;
047import com.unboundid.ldap.sdk.ResultCode;
048import com.unboundid.util.Debug;
049import com.unboundid.util.NotMutable;
050import com.unboundid.util.StaticUtils;
051import com.unboundid.util.ThreadSafety;
052import com.unboundid.util.ThreadSafetyLevel;
053
054import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
055
056
057
058/**
059 * This class provides an implementation of an extended result that provides
060 * information about the result of processing a
061 * {@link CollectSupportDataExtendedRequest}.  Once this message has been
062 * received, all processing for the associated request will be complete, and
063 * there should not be any further
064 * {@link CollectSupportDataOutputIntermediateResponse} or
065 * {@link CollectSupportDataArchiveFragmentIntermediateResponse} messages.
066 * <BR>
067 * <BLOCKQUOTE>
068 *   <B>NOTE:</B>  This class, and other classes within the
069 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
070 *   supported for use against Ping Identity, UnboundID, and
071 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
072 *   for proprietary functionality or for external specifications that are not
073 *   considered stable or mature enough to be guaranteed to work in an
074 *   interoperable way with other types of LDAP servers.
075 * </BLOCKQUOTE>
076 * <BR>
077 * If the extended operation processing failed for some reason before the server
078 * could invoke the collect-support-data tool, then this response may not
079 * include an OID or value.  However, if the collect-support-data tool has been
080 * invoked (regardless of its success or failure), then the extended result
081 * should have an OID of1.3.6.1.4.1.30221.2.6.67 and a value with the following
082 * encoding:
083 * <BR>
084 * <PRE>
085 *   CollectSupportDataResponse ::= SEQUENCE {
086 *      exitCode     [0] INTEGER,
087 *      ... }
088 * </PRE>
089 *
090 * @see  CollectSupportDataExtendedRequest
091 * @see  CollectSupportDataArchiveFragmentIntermediateResponse
092 * @see  CollectSupportDataOutputIntermediateResponse
093 */
094@NotMutable()
095@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
096public final class CollectSupportDataExtendedResult
097       extends ExtendedResult
098{
099  /**
100   * The OID (1.3.6.1.4.1.30221.2.6.67) for the collect support data extended
101   * result.
102   */
103  public static final String COLLECT_SUPPORT_DATA_RESULT_OID =
104       "1.3.6.1.4.1.30221.2.6.67";
105
106
107
108  /**
109   * The BER type for the value element that holds the collect-support-data tool
110   * exit code.
111   */
112  private static final byte TYPE_EXIT_CODE = (byte) 0x80;
113
114
115
116  /**
117   * The serial version UID for this serializable class.
118   */
119  private static final long serialVersionUID = 9005943853349941187L;
120
121
122
123  // The exit code returned by the collect-support-data tool.
124  private final Integer exitCode;
125
126
127
128  /**
129   * Creates a new collect support data extended result with the provided
130   * information.
131   *
132   * @param  messageID          The LDAP message ID for this extended result.
133   * @param  resultCode         The result code for this extended result.  It
134   *                            must not be {@code null}.
135   * @param  diagnosticMessage  The diagnostic message for this extended result.
136   *                            It may be {@code null} if no diagnostic message
137   *                            should be included.
138   * @param  matchedDN          The matched DN for this extended result.  It may
139   *                            be {@code null} if no matched DN should be
140   *                            included.
141   * @param  referralURLs       The set of referral URLs for this extended
142   *                            result.  It may be {@code null} or empty if no
143   *                            referral URLs should be included.
144   * @param  exitCode           The exit code returned when the
145   *                            collect-support-data tool completed.  This may
146   *                            be {@code null} if extended operation processing
147   *                            failed before the collect-support-data tool
148   *                            could complete.
149   * @param  controls           The set of controls to include in the extended
150   *                            result.  It may be [@code null} or empty if no
151   *                            controls should be included.
152   */
153  public CollectSupportDataExtendedResult(final int messageID,
154              final ResultCode resultCode, final String diagnosticMessage,
155              final String matchedDN, final String[] referralURLs,
156              final Integer exitCode, final Control... controls)
157  {
158    super(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs,
159         (exitCode == null) ? null : COLLECT_SUPPORT_DATA_RESULT_OID,
160         encodeValue(exitCode), controls);
161
162    this.exitCode = exitCode;
163  }
164
165
166
167  /**
168   * Constructs an ASN.1 octet string suitable for use as the value of this
169   * extended result.
170   *
171   * @param  exitCode  The exit code returned when the collect-support-data tool
172   *                   completed.  This may be {@code null} if extended
173   *                   operation processing failed before the
174   *                   collect-support-data tool could complete.
175   *
176   * @return  The ASN.1 octet string created for use as the value of this
177   *          extended result, or {@code null} if the extended result should not
178   *          have a value.
179   */
180  private static ASN1OctetString encodeValue(final Integer exitCode)
181  {
182    if (exitCode == null)
183    {
184      return null;
185    }
186
187    final ASN1Sequence valueSequence = new ASN1Sequence(
188         new ASN1Integer(TYPE_EXIT_CODE, exitCode));
189
190    return new ASN1OctetString(valueSequence.encode());
191  }
192
193
194
195  /**
196   * Creates a new collect support data extended result that is decoded from
197   * the provided generic extended result.
198   *
199   * @param  extendedResult  The generic extended result to be decoded as a
200   *                         collect support data extended result.  It must not
201   *                         be {@code null}.
202   *
203   * @throws  LDAPException  If the provided generic extended result cannot be
204   *                         decoded as a collect support data extended result.
205   */
206  public CollectSupportDataExtendedResult(final ExtendedResult extendedResult)
207         throws LDAPException
208  {
209    super(extendedResult);
210
211    final ASN1OctetString value = extendedResult.getValue();
212    if (value == null)
213    {
214      exitCode = null;
215      return;
216    }
217
218    try
219    {
220      final ASN1Sequence valueSequence =
221           ASN1Sequence.decodeAsSequence(value.getValue());
222      final ASN1Element[] elements = valueSequence.elements();
223      exitCode = ASN1Integer.decodeAsInteger(elements[0]).intValue();
224    }
225    catch (final Exception e)
226    {
227      Debug.debugException(e);
228      throw new LDAPException(ResultCode.DECODING_ERROR,
229           ERR_CSD_RESULT_DECODE_ERROR.get(
230                StaticUtils.getExceptionMessage(e)),
231           e);
232    }
233  }
234
235
236
237  /**
238   * Retrieves the exit code returned when the collect-support-data tool
239   * completed.
240   *
241   * @return  The exit code returned when the collect-support-data tool
242   *          completed, or {@code null} if extended operation processing
243   *          failed before the collect-support-data tool could complete.
244   */
245  public Integer getExitCode()
246  {
247    return exitCode;
248  }
249
250
251
252  /**
253   * {@inheritDoc}
254   */
255  @Override()
256  public String getExtendedResultName()
257  {
258    return INFO_COLLECT_SUPPORT_DATA_RESULT_NAME.get();
259  }
260
261
262
263  /**
264   * {@inheritDoc}
265   */
266  @Override()
267  public void toString(final StringBuilder buffer)
268  {
269    buffer.append("CollectSupportDataExtendedResult(resultCode=");
270    buffer.append(getResultCode());
271
272    final int messageID = getMessageID();
273    if (messageID >= 0)
274    {
275      buffer.append(", messageID=");
276      buffer.append(messageID);
277    }
278
279    final String diagnosticMessage = getDiagnosticMessage();
280    if (diagnosticMessage != null)
281    {
282      buffer.append(", diagnosticMessage='");
283      buffer.append(diagnosticMessage);
284      buffer.append('\'');
285    }
286
287    final String matchedDN = getMatchedDN();
288    if (matchedDN != null)
289    {
290      buffer.append(", matchedDN='");
291      buffer.append(matchedDN);
292      buffer.append('\'');
293    }
294
295    final String[] referralURLs = getReferralURLs();
296    if (referralURLs.length > 0)
297    {
298      buffer.append(", referralURLs={");
299      for (int i=0; i < referralURLs.length; i++)
300      {
301        if (i > 0)
302        {
303          buffer.append(", ");
304        }
305
306        buffer.append('\'');
307        buffer.append(referralURLs[i]);
308        buffer.append('\'');
309      }
310      buffer.append('}');
311    }
312
313    if (exitCode != null)
314    {
315      buffer.append(", exitCode=");
316      buffer.append(exitCode);
317    }
318
319    final Control[] responseControls = getResponseControls();
320    if (responseControls.length > 0)
321    {
322      buffer.append(", controls={");
323      for (int i=0; i < responseControls.length; i++)
324      {
325        if (i > 0)
326        {
327          buffer.append(", ");
328        }
329
330        buffer.append(responseControls[i]);
331      }
332      buffer.append('}');
333    }
334
335    buffer.append(')');
336  }
337}