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