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.ASN1Enumerated; 042import com.unboundid.asn1.ASN1OctetString; 043import com.unboundid.asn1.ASN1Sequence; 044import com.unboundid.ldap.sdk.Control; 045import com.unboundid.ldap.sdk.IntermediateResponse; 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 intermediate response that can 062 * provide the client with output from the collect-support-data tool in 063 * response to a {@link CollectSupportDataExtendedRequest}. 064 * <BR> 065 * <BLOCKQUOTE> 066 * <B>NOTE:</B> This class, and other classes within the 067 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 068 * supported for use against Ping Identity, UnboundID, and 069 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 070 * for proprietary functionality or for external specifications that are not 071 * considered stable or mature enough to be guaranteed to work in an 072 * interoperable way with other types of LDAP servers. 073 * </BLOCKQUOTE> 074 * <BR> 075 * The collect support data output intermediate response has an OID of 076 * 1.3.6.1.4.1.30221.2.6.65 and a value with the following encoding: 077 * <BR> 078 * <PRE> 079 * CollectSupportDataOutputIntermediateResponse ::= SEQUENCE { 080 * outputStream [0] ENUMERATED { 081 * standardOutput (0), 082 * standardError (1), 083 * ... }, 084 * outputMessage [1] OCTET STRING, 085 * ... } 086 * </PRE> 087 * 088 * @see CollectSupportDataExtendedRequest 089 * @see CollectSupportDataExtendedResult 090 * @see CollectSupportDataArchiveFragmentIntermediateResponse 091 */ 092@NotMutable() 093@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 094public final class CollectSupportDataOutputIntermediateResponse 095 extends IntermediateResponse 096{ 097 /** 098 * The OID (1.3.6.1.4.1.30221.2.6.65) for the collect support data output 099 * intermediate response. 100 */ 101 @NotNull public static final String 102 COLLECT_SUPPORT_DATA_OUTPUT_INTERMEDIATE_RESPONSE_OID = 103 "1.3.6.1.4.1.30221.2.6.65"; 104 105 106 107 /** 108 * The BER type for the value element that specifies the output stream. 109 */ 110 private static final byte TYPE_OUTPUT_STREAM = (byte) 0x80; 111 112 113 114 /** 115 * The BER type for the value element that specifies the output message. 116 */ 117 private static final byte TYPE_OUTPUT_MESSAGE = (byte) 0x81; 118 119 120 121 /** 122 * The serial version UID for this serializable class. 123 */ 124 private static final long serialVersionUID = -2844901273280769861L; 125 126 127 128 // The output stream to which the message was written. 129 @NotNull private final CollectSupportDataOutputStream outputStream; 130 131 // The output message that was written. 132 @NotNull private final String outputMessage; 133 134 135 136 /** 137 * Creates a new collect support data output intermediate response with the 138 * provided information. 139 * 140 * @param outputStream The output stream to which the message was written. 141 * It must not be {@code null}. 142 * @param outputMessage The output message that was written by the tool. It 143 * must not be {@code null}. 144 * @param controls The set of controls to include in this intermediate 145 * response. It may be {@code null} or empty if no 146 * controls are needed. 147 */ 148 public CollectSupportDataOutputIntermediateResponse( 149 @NotNull final CollectSupportDataOutputStream outputStream, 150 @NotNull final String outputMessage, 151 @Nullable final Control... controls) 152 { 153 super(COLLECT_SUPPORT_DATA_OUTPUT_INTERMEDIATE_RESPONSE_OID, 154 encodeValue(outputStream, outputMessage), controls); 155 156 this.outputStream = outputStream; 157 this.outputMessage = outputMessage; 158 } 159 160 161 162 /** 163 * Constructs an ASN.1 octet string suitable for use as the value of this 164 * collect support data output intermediate response. 165 * 166 * @param outputStream The output stream to which the message was written. 167 * It must not be {@code null}. 168 * @param outputMessage The output message that was written by the tool. It 169 * must not be {@code null}. 170 * 171 * @return The ASN.1 octet string containing the encoded value. 172 */ 173 @NotNull() 174 private static ASN1OctetString encodeValue( 175 @NotNull final CollectSupportDataOutputStream outputStream, 176 @NotNull final String outputMessage) 177 { 178 final ASN1Sequence valueSequence = new ASN1Sequence( 179 new ASN1Enumerated(TYPE_OUTPUT_STREAM, outputStream.getIntValue()), 180 new ASN1OctetString(TYPE_OUTPUT_MESSAGE, outputMessage)); 181 182 return new ASN1OctetString(valueSequence.encode()); 183 } 184 185 186 187 /** 188 * Creates a new collect support data output intermediate response that is 189 * decoded from the provided generic intermediate response. 190 * 191 * @param intermediateResponse The generic intermediate response to be 192 * decoded as a collect support data output 193 * intermediate response. It must not be 194 * {@code null}. 195 * 196 * @throws LDAPException If the provided intermediate response object cannot 197 * be decoded as a collect support data output 198 * intermediate response. 199 */ 200 public CollectSupportDataOutputIntermediateResponse( 201 @NotNull final IntermediateResponse intermediateResponse) 202 throws LDAPException 203 { 204 super(intermediateResponse); 205 206 final ASN1OctetString value = intermediateResponse.getValue(); 207 if (value == null) 208 { 209 throw new LDAPException(ResultCode.DECODING_ERROR, 210 ERR_CSD_OUTPUT_IR_DECODE_NO_VALUE.get()); 211 } 212 213 try 214 { 215 final ASN1Sequence valueSequence = 216 ASN1Sequence.decodeAsSequence(value.getValue()); 217 final ASN1Element[] elements = valueSequence.elements(); 218 219 final int outputStreamIntValue = 220 ASN1Enumerated.decodeAsEnumerated(elements[0]).intValue(); 221 outputStream = CollectSupportDataOutputStream.forIntValue( 222 outputStreamIntValue); 223 if (outputStream == null) 224 { 225 throw new LDAPException(ResultCode.DECODING_ERROR, 226 ERR_CSD_OUTPUT_IR_DECODE_UNRECOGNIZED_OUTPUT_STREAM.get( 227 outputStreamIntValue)); 228 } 229 230 outputMessage = 231 ASN1OctetString.decodeAsOctetString(elements[1]).stringValue(); 232 } 233 catch (final LDAPException e) 234 { 235 Debug.debugException(e); 236 throw e; 237 } 238 catch (final Exception e) 239 { 240 Debug.debugException(e); 241 throw new LDAPException(ResultCode.DECODING_ERROR, 242 ERR_CSD_OUTPUT_IR_DECODE_ERROR.get( 243 StaticUtils.getExceptionMessage(e)), 244 e); 245 } 246 } 247 248 249 250 /** 251 * Retrieves the output stream to which the output message was written. 252 * 253 * @return The output stream to which the output was written. 254 */ 255 @NotNull() 256 public CollectSupportDataOutputStream getOutputStream() 257 { 258 return outputStream; 259 } 260 261 262 263 /** 264 * Retrieves the output message that was written. 265 * 266 * @return The output message that was written. 267 */ 268 @NotNull() 269 public String getOutputMessage() 270 { 271 return outputMessage; 272 } 273 274 275 276 /** 277 * {@inheritDoc} 278 */ 279 @Override() 280 @NotNull() 281 public String getIntermediateResponseName() 282 { 283 return INFO_COLLECT_SUPPORT_DATA_OUTPUT_IR_NAME.get(); 284 } 285 286 287 288 /** 289 * {@inheritDoc} 290 */ 291 @Override() 292 @NotNull() 293 public String valueToString() 294 { 295 final StringBuilder buffer = new StringBuilder(); 296 297 buffer.append("outputStream='"); 298 buffer.append(outputStream.getName()); 299 buffer.append("' outputMessage='"); 300 buffer.append(outputMessage); 301 buffer.append('\''); 302 303 return buffer.toString(); 304 } 305 306 307 308 /** 309 * {@inheritDoc} 310 */ 311 @Override() 312 public void toString(@NotNull final StringBuilder buffer) 313 { 314 buffer.append("CollectSupportDataOutputIntermediateResponse(oid='"); 315 buffer.append(getOID()); 316 buffer.append("', outputStream='"); 317 buffer.append(outputStream.getName()); 318 buffer.append("', outputMessage='"); 319 buffer.append(outputMessage); 320 buffer.append('\''); 321 322 final Control[] controls = getControls(); 323 if (controls.length > 0) 324 { 325 buffer.append(", controls={"); 326 for (int i=0; i < controls.length; i++) 327 { 328 if (i > 0) 329 { 330 buffer.append(", "); 331 } 332 333 buffer.append(controls[i]); 334 } 335 buffer.append('}'); 336 } 337 338 buffer.append(')'); 339 } 340}