001/* 002 * Copyright 2013-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2018 Ping Identity Corporation 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.sdk.unboundidds.extensions; 022 023 024 025import java.io.ByteArrayInputStream; 026import java.io.InputStream; 027 028import com.unboundid.asn1.ASN1Element; 029import com.unboundid.asn1.ASN1Enumerated; 030import com.unboundid.asn1.ASN1OctetString; 031import com.unboundid.asn1.ASN1Sequence; 032import com.unboundid.ldap.sdk.Control; 033import com.unboundid.ldap.sdk.ExtendedResult; 034import com.unboundid.ldap.sdk.LDAPException; 035import com.unboundid.ldap.sdk.ResultCode; 036import com.unboundid.util.Debug; 037import com.unboundid.util.StaticUtils; 038import com.unboundid.util.ThreadSafety; 039import com.unboundid.util.ThreadSafetyLevel; 040import com.unboundid.util.Validator; 041 042import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*; 043 044 045 046/** 047 * This class provides an implementation of an extended result that can be used 048 * to retrieve a version of the server configuration. 049 * <BR> 050 * <BLOCKQUOTE> 051 * <B>NOTE:</B> This class, and other classes within the 052 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 053 * supported for use against Ping Identity, UnboundID, and 054 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 055 * for proprietary functionality or for external specifications that are not 056 * considered stable or mature enough to be guaranteed to work in an 057 * interoperable way with other types of LDAP servers. 058 * </BLOCKQUOTE> 059 * <BR> 060 * The OID for this extended result is 1.3.6.1.4.1.30221.2.6.29. If the request 061 * was processed successfully, then the response will have a value with the 062 * following encoding: 063 * <PRE> 064 * GetConfigurationResult ::= SEQUENCE { 065 * configurationType [0] ENUMERATED { 066 * active (0), 067 * baseline (1), 068 * archived (2), 069 * ... }, 070 * fileName [1] OCTET STRING, 071 * configurationFileData [2] OCTET STRING, 072 * ... } 073 * </PRE> 074 * 075 * @see GetConfigurationExtendedRequest 076 * @see ListConfigurationsExtendedRequest 077 */ 078@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 079public final class GetConfigurationExtendedResult 080 extends ExtendedResult 081{ 082 /** 083 * The OID (1.3.6.1.4.1.30221.2.6.29) for the get configuration extended 084 * result. 085 */ 086 public static final String GET_CONFIG_RESULT_OID = 087 "1.3.6.1.4.1.30221.2.6.29"; 088 089 090 091 /** 092 * The BER type for the element holding the type of configuration that has 093 * been returned. 094 */ 095 private static final byte TYPE_CONFIG_TYPE = (byte) 0x80; 096 097 098 099 /** 100 * The BER type for the element holding the name of the configuration file 101 * that has been returned. 102 */ 103 private static final byte TYPE_FILE_NAME = (byte) 0x81; 104 105 106 107 /** 108 * The BER type for the element holding the raw LDIF data that comprises the 109 * configuration file that has been returned. 110 */ 111 private static final byte TYPE_FILE_DATA = (byte) 0x82; 112 113 114 115 /** 116 * The serial version UID for this serializable class. 117 */ 118 private static final long serialVersionUID = 6042324433827773678L; 119 120 121 122 // The raw data for the configuration file that has been returned. 123 private final byte[] fileData; 124 125 // The type of configuration that has been returned. 126 private final GetConfigurationType configurationType; 127 128 // The name of the configuration file that has been returned. 129 private final String fileName; 130 131 132 133 /** 134 * Creates a new get configuration extended result from the provided generic 135 * extended result. 136 * 137 * @param result The generic extended result to be decoded as a get 138 * configuration extended result. 139 * 140 * @throws LDAPException If the provided extended result cannot be parsed as 141 * a valid get configuration extended result. 142 */ 143 public GetConfigurationExtendedResult(final ExtendedResult result) 144 throws LDAPException 145 { 146 super(result); 147 148 final ASN1OctetString value = result.getValue(); 149 if (value == null) 150 { 151 configurationType = null; 152 fileName = null; 153 fileData = null; 154 return; 155 } 156 157 try 158 { 159 final ASN1Element[] elements = 160 ASN1Sequence.decodeAsSequence(value.getValue()).elements(); 161 162 final int configType = 163 ASN1Enumerated.decodeAsEnumerated(elements[0]).intValue(); 164 configurationType = GetConfigurationType.forIntValue(configType); 165 if (configurationType == null) 166 { 167 throw new LDAPException(ResultCode.DECODING_ERROR, 168 ERR_GET_CONFIG_RESULT_INVALID_CONFIG_TYPE.get(configType)); 169 } 170 171 fileName = ASN1OctetString.decodeAsOctetString(elements[1]).stringValue(); 172 fileData = ASN1OctetString.decodeAsOctetString(elements[2]).getValue(); 173 } 174 catch (final LDAPException le) 175 { 176 Debug.debugException(le); 177 throw le; 178 } 179 catch (final Exception e) 180 { 181 Debug.debugException(e); 182 throw new LDAPException(ResultCode.DECODING_ERROR, 183 ERR_GET_CONFIG_RESULT_ERROR_PARSING_VALUE.get( 184 StaticUtils.getExceptionMessage(e)), 185 e); 186 } 187 } 188 189 190 191 /** 192 * Creates a new get configuration extended result with the provided 193 * information. 194 * 195 * @param messageID The message ID for the LDAP message that is 196 * associated with this LDAP result. 197 * @param resultCode The result code from the response. 198 * @param diagnosticMessage The diagnostic message from the response, if 199 * available. 200 * @param matchedDN The matched DN from the response, if available. 201 * @param referralURLs The set of referral URLs from the response, if 202 * available. 203 * @param configurationType The type of configuration that has been 204 * returned. 205 * @param fileName The name of the configuration file that has been 206 * returned. 207 * @param fileData The raw data for the configuration file that has 208 * been returned. 209 * @param responseControls The set of controls from the response, if 210 * available. 211 */ 212 public GetConfigurationExtendedResult(final int messageID, 213 final ResultCode resultCode, final String diagnosticMessage, 214 final String matchedDN, final String[] referralURLs, 215 final GetConfigurationType configurationType, 216 final String fileName, final byte[] fileData, 217 final Control... responseControls) 218 { 219 super(messageID, resultCode, diagnosticMessage, matchedDN, referralURLs, 220 ((configurationType == null) ? null : GET_CONFIG_RESULT_OID), 221 encodeValue(configurationType, fileName, fileData), responseControls); 222 223 this.configurationType = configurationType; 224 this.fileName = fileName; 225 this.fileData = fileData; 226 } 227 228 229 230 /** 231 * Creates an ASN.1 octet string containing an encoded representation of the 232 * value for a get configuration extended result with the provided 233 * information. 234 * 235 * @param configurationType The type of configuration that has been 236 * returned. 237 * @param fileName The name of the configuration file that has been 238 * returned. 239 * @param fileData The raw data for the configuration file that has 240 * been returned. 241 * 242 * @return An ASN.1 octet string containing an encoded representation of the 243 * value for a get configuration extended result, or {@code null} if 244 * a result with the provided information should not have a value. 245 */ 246 public static ASN1OctetString encodeValue( 247 final GetConfigurationType configurationType, 248 final String fileName, final byte[] fileData) 249 { 250 if (configurationType == null) 251 { 252 Validator.ensureTrue((fileName == null), 253 "The configuration file name must be null if the configuration " + 254 "type is null."); 255 Validator.ensureTrue((fileData == null), 256 "The configuration file data must be null if the configuration " + 257 "type is null."); 258 return null; 259 } 260 261 Validator.ensureTrue((fileName != null), 262 "The configuration file name must not be null if the configuration " + 263 "type is not null."); 264 Validator.ensureTrue((fileData != null), 265 "The configuration file data must not be null if the configuration " + 266 "type is not null."); 267 268 final ASN1Sequence valueSequence = new ASN1Sequence( 269 new ASN1Enumerated(TYPE_CONFIG_TYPE, configurationType.getIntValue()), 270 new ASN1OctetString(TYPE_FILE_NAME, fileName), 271 new ASN1OctetString(TYPE_FILE_DATA, fileData)); 272 return new ASN1OctetString(valueSequence.encode()); 273 } 274 275 276 277 /** 278 * Retrieves the type of configuration that has been returned, if available. 279 * 280 * @return The type of configuration that has been returned, or {@code null} 281 * if this is not available. 282 */ 283 public GetConfigurationType getConfigurationType() 284 { 285 return configurationType; 286 } 287 288 289 290 /** 291 * Retrieves the name of the configuration file that has been returned, if 292 * available. 293 * 294 * @return The name of the configuration file that has been returned, or 295 * {@code null} if this is not available. 296 */ 297 public String getFileName() 298 { 299 return fileName; 300 } 301 302 303 304 /** 305 * Retrieves the raw data for the configuration file that has been returned, 306 * if available. 307 * 308 * @return The raw data for the configuration file that has been returned, 309 * or {@code null} if this is not available. 310 */ 311 public byte[] getFileData() 312 { 313 return fileData; 314 } 315 316 317 318 /** 319 * Retrieves an input stream that may be used to read the file data that has 320 * been returned, if available. 321 * 322 * @return An input stream that may be used to read the file data that has 323 * been returned, or {@code null} if this is not available. 324 */ 325 public InputStream getFileDataInputStream() 326 { 327 if (fileData == null) 328 { 329 return null; 330 } 331 else 332 { 333 return new ByteArrayInputStream(fileData); 334 } 335 } 336 337 338 339 /** 340 * {@inheritDoc} 341 */ 342 @Override() 343 public String getExtendedResultName() 344 { 345 return INFO_EXTENDED_RESULT_NAME_GET_CONFIG.get(); 346 } 347 348 349 350 /** 351 * {@inheritDoc} 352 */ 353 @Override() 354 public void toString(final StringBuilder buffer) 355 { 356 buffer.append("GetConfigurationExtendedResult(resultCode="); 357 buffer.append(getResultCode()); 358 359 final int messageID = getMessageID(); 360 if (messageID >= 0) 361 { 362 buffer.append(", messageID="); 363 buffer.append(messageID); 364 } 365 366 if (configurationType != null) 367 { 368 buffer.append(", configType="); 369 buffer.append(configurationType.name()); 370 } 371 372 if (fileName != null) 373 { 374 buffer.append(", fileName='"); 375 buffer.append(fileName); 376 buffer.append('\''); 377 } 378 379 if (fileData != null) 380 { 381 buffer.append(", fileLength="); 382 buffer.append(fileData.length); 383 } 384 385 final String diagnosticMessage = getDiagnosticMessage(); 386 if (diagnosticMessage != null) 387 { 388 buffer.append(", diagnosticMessage='"); 389 buffer.append(diagnosticMessage); 390 buffer.append('\''); 391 } 392 393 final String matchedDN = getMatchedDN(); 394 if (matchedDN != null) 395 { 396 buffer.append(", matchedDN='"); 397 buffer.append(matchedDN); 398 buffer.append('\''); 399 } 400 401 final String[] referralURLs = getReferralURLs(); 402 if (referralURLs.length > 0) 403 { 404 buffer.append(", referralURLs={"); 405 for (int i=0; i < referralURLs.length; i++) 406 { 407 if (i > 0) 408 { 409 buffer.append(", "); 410 } 411 412 buffer.append('\''); 413 buffer.append(referralURLs[i]); 414 buffer.append('\''); 415 } 416 buffer.append('}'); 417 } 418 419 final Control[] responseControls = getResponseControls(); 420 if (responseControls.length > 0) 421 { 422 buffer.append(", responseControls={"); 423 for (int i=0; i < responseControls.length; i++) 424 { 425 if (i > 0) 426 { 427 buffer.append(", "); 428 } 429 430 buffer.append(responseControls[i]); 431 } 432 buffer.append('}'); 433 } 434 435 buffer.append(')'); 436 } 437}