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 java.util.ArrayList; 041import java.util.List; 042 043import com.unboundid.asn1.ASN1Boolean; 044import com.unboundid.asn1.ASN1Element; 045import com.unboundid.asn1.ASN1Enumerated; 046import com.unboundid.asn1.ASN1Integer; 047import com.unboundid.asn1.ASN1OctetString; 048import com.unboundid.asn1.ASN1Sequence; 049import com.unboundid.ldap.sdk.Control; 050import com.unboundid.ldap.sdk.ExtendedRequest; 051import com.unboundid.ldap.sdk.ExtendedResult; 052import com.unboundid.ldap.sdk.IntermediateResponse; 053import com.unboundid.ldap.sdk.IntermediateResponseListener; 054import com.unboundid.ldap.sdk.LDAPException; 055import com.unboundid.ldap.sdk.LDAPConnection; 056import com.unboundid.ldap.sdk.LDAPRuntimeException; 057import com.unboundid.ldap.sdk.ResultCode; 058import com.unboundid.ldap.sdk.unboundidds.tasks.CollectSupportDataSecurityLevel; 059import com.unboundid.util.Debug; 060import com.unboundid.util.NotMutable; 061import com.unboundid.util.NotNull; 062import com.unboundid.util.Nullable; 063import com.unboundid.util.StaticUtils; 064import com.unboundid.util.ThreadSafety; 065import com.unboundid.util.ThreadSafetyLevel; 066import com.unboundid.util.Validator; 067 068import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*; 069 070 071 072/** 073 * This class provides an implementation of an extended request that may be used 074 * to invoke the collect-support data tool in a Ping Identity Directory Server 075 * and stream the output (using 076 * {@link CollectSupportDataOutputIntermediateResponse} messages) and the 077 * resulting support data archive (using 078 * {@link CollectSupportDataArchiveFragmentIntermediateResponse} messages) 079 * back to the client before the final 080 * {@link CollectSupportDataExtendedResult} response. 081 * <BR> 082 * <BLOCKQUOTE> 083 * <B>NOTE:</B> This class, and other classes within the 084 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 085 * supported for use against Ping Identity, UnboundID, and 086 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 087 * for proprietary functionality or for external specifications that are not 088 * considered stable or mature enough to be guaranteed to work in an 089 * interoperable way with other types of LDAP servers. 090 * </BLOCKQUOTE> 091 * <BR> 092 * The collect support data extended request has an OID of 093 * 1.3.6.1.4.1.30221.2.6.64 and a value with the following encoding: 094 * <BR> 095 * <PRE> 096 * CollectSupportDataRequest ::= SEQUENCE { 097 * archiveFileName [0] OCTET STRING OPTIONAL, 098 * encryptionPassphrase [1] OCTET STRING OPTIONAL, 099 * includeExpensiveData [2] BOOLEAN DEFAULT FALSE, 100 * includeReplicationStateDump [3] BOOLEAN DEFAULT FALSE, 101 * includeBinaryFiles [4] BOOLEAN DEFAULT FALSE, 102 * includeExtensionSource [5] BOOLEAN DEFAULT FALSE, 103 * useSequentialMode [6] BOOLEAN DEFAULT FALSE, 104 * securityLevel [7] ENUMERATED { 105 * none (0), 106 * obscureSecrets (1), 107 * maximum (2), 108 * ... } DEFAULT obscureSecrets, 109 * jstackCount [8] INTEGER (0..MAX) DEFAULT 10, 110 * reportCount [9] INTEGER (0..MAX) DEFAULT 10, 111 * reportIntervalSeconds [10] INTEGER (1..MAX) DEFAULT 1, 112 * logCaptureWindow [11] CHOICE { 113 * toolDefault [0] NULL, 114 * durationMillis [1] INTEGER (0..MAX), 115 * timeWindow [2] SEQUENCE { 116 * startTime OCTET STRING, 117 * endTime OCTET STRING OPTIONAL }, 118 * headAndTailSize [3] SEQUENCE { 119 * headSizeKB [0] INTEGER OPTIONAL, 120 * tailSizeKB [1] INTEGER OPTIONAL }, 121 * ... } DEFAULT default, 122 * comment [12] OCTET STRING OPTIONAL, 123 * proxyToServer [13] SEQUENCE OF { 124 * address OCTET STRING, 125 * port INTEGER (1..65535), 126 * ... } OPTIONAL, 127 * maximumFragmentSizeBytes [1] INTEGER DEFAULT 1048576, 128 * ... } 129 * </PRE> 130 * <BR><BR> 131 * Because the tool output and the support data archive will be streamed back to 132 * the client using intermediate response messages, the request must be 133 * configured with an intermediate response listener to gain access to that 134 * information. 135 * 136 * @see CollectSupportDataExtendedResult 137 * @see CollectSupportDataOutputIntermediateResponse 138 * @see CollectSupportDataArchiveFragmentIntermediateResponse 139 * @see CollectSupportDataSecurityLevel 140 * @see CollectSupportDataLogCaptureWindow 141 */ 142@NotMutable() 143@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 144public final class CollectSupportDataExtendedRequest 145 extends ExtendedRequest 146 implements IntermediateResponseListener 147{ 148 /** 149 * The OID (1.3.6.1.4.1.30221.2.6.64) for the collect support data extended 150 * request. 151 */ 152 @NotNull public static final String COLLECT_SUPPORT_DATA_REQUEST_OID = 153 "1.3.6.1.4.1.30221.2.6.64"; 154 155 156 157 /** 158 * The BER type for the request element that specifies the name to use for the 159 * archive file. 160 */ 161 private static final byte TYPE_ARCHIVE_FILE_NAME = (byte) 0x80; 162 163 164 165 /** 166 * The BER type for the request element that specifies the passphrase to use 167 * to encrypt the contents of the support data archive. 168 */ 169 static final byte TYPE_ENCRYPTION_PASSPHRASE = (byte) 0x81; 170 171 172 173 /** 174 * The BER type for the request element that indicates whether to include 175 * data that may be expensive to collect. 176 */ 177 private static final byte TYPE_INCLUDE_EXPENSIVE_DATA = (byte) 0x82; 178 179 180 181 /** 182 * The BER type for the request element that indicates whether to include a 183 * replication state dump. 184 */ 185 private static final byte TYPE_INCLUDE_REPLICATION_STATE_DUMP = (byte) 0x83; 186 187 188 189 /** 190 * The BER type for the request element that indicates whether to include 191 * binary files. 192 */ 193 private static final byte TYPE_INCLUDE_BINARY_FILES = (byte) 0x84; 194 195 196 197 /** 198 * The BER type for the request element that indicates whether to include 199 * extension source code. 200 */ 201 private static final byte TYPE_INCLUDE_EXTENSION_SOURCE = (byte) 0x85; 202 203 204 205 /** 206 * The BER type for the request element that indicates whether to collect 207 * information in sequential mode. 208 */ 209 private static final byte TYPE_USE_SEQUENTIAL_MODE = (byte) 0x86; 210 211 212 213 /** 214 * The BER type for the request element that specifies the security level. 215 */ 216 private static final byte TYPE_SECURITY_LEVEL = (byte) 0x87; 217 218 219 220 /** 221 * The BER type for the request element that specifies the number of jstack 222 * stack traces to include. 223 */ 224 private static final byte TYPE_JSTACK_COUNT = (byte) 0x88; 225 226 227 228 /** 229 * The BER type for the request element that specifies the number intervals 230 * to collect from interval-based sampling tools. 231 */ 232 private static final byte TYPE_REPORT_COUNT = (byte) 0x89; 233 234 235 236 /** 237 * The BER type for the request element that specifies the interval duration 238 * to use for interval-based sampling tools. 239 */ 240 private static final byte TYPE_REPORT_INTERVAL_SECONDS = (byte) 0x8A; 241 242 243 244 /** 245 * The BER type for the request element that specifies the log capture window 246 * for the request. 247 */ 248 private static final byte TYPE_LOG_CAPTURE_WINDOW = (byte) 0xAB; 249 250 251 252 /** 253 * The BER type for the request element that specifies a comment to include in 254 * the archive. 255 */ 256 private static final byte TYPE_COMMENT = (byte) 0x8C; 257 258 259 260 /** 261 * The BER type for the request element that specifies the address and port 262 * to which the request should be forwarded. 263 */ 264 private static final byte TYPE_PROXY_TO_SERVER = (byte) 0xAD; 265 266 267 268 /** 269 * The BER type for the request element that specifies the maximum archive 270 * fragment size. 271 */ 272 private static final byte TYPE_MAXIMUM_FRAGMENT_SIZE_BYTES = (byte) 0x8E; 273 274 275 276 /** 277 * The integer value for the {@link CollectSupportDataSecurityLevel#NONE} 278 * security level. 279 */ 280 private static final int SECURITY_LEVEL_VALUE_NONE = 0; 281 282 283 284 /** 285 * The integer value for the 286 * {@link CollectSupportDataSecurityLevel#OBSCURE_SECRETS} security level. 287 */ 288 private static final int SECURITY_LEVEL_VALUE_OBSCURE_SECRETS = 1; 289 290 291 292 /** 293 * The integer value for the {@link CollectSupportDataSecurityLevel#MAXIMUM} 294 * security level. 295 */ 296 private static final int SECURITY_LEVEL_VALUE_MAXIMUM = 2; 297 298 299 300 /** 301 * The serial version UID for this serializable class. 302 */ 303 private static final long serialVersionUID = -8884596371195896085L; 304 305 306 307 // The passphrase to use to encrypt the contents of the support data archive. 308 @Nullable private final ASN1OctetString encryptionPassphrase; 309 310 // Indicates whether to include binary files in the support data archive. 311 @Nullable private final Boolean includeBinaryFiles; 312 313 // Indicates whether to include expensive data in the support data archive. 314 @Nullable private final Boolean includeExpensiveData; 315 316 // Indicates whether to include third-party extension source code in the 317 // support data archive. 318 @Nullable private final Boolean includeExtensionSource; 319 320 // Indicates whether to include a replication state dump in the support data 321 // archive. 322 @Nullable private final Boolean includeReplicationStateDump; 323 324 // Indicates whether to capture information sequentially rather than in 325 // parallel. 326 @Nullable private final Boolean useSequentialMode; 327 328 // The intermediate response listener that will be used for this operation. 329 @NotNull private final CollectSupportDataIntermediateResponseListener 330 intermediateResponseListener; 331 332 // The log capture window that indicates how much log content to include in 333 // the support data archive. 334 @Nullable private final CollectSupportDataLogCaptureWindow logCaptureWindow; 335 336 // The security level to use for data included in the support data archive. 337 @Nullable private final CollectSupportDataSecurityLevel securityLevel; 338 339 // The number of jstacks to include in the support data archive. 340 @Nullable private final Integer jstackCount; 341 342 // The maximum size, in bytes, of any support data archive fragment to include 343 // in a collect support data archive fragment intermediate response. 344 @Nullable private final Integer maximumFragmentSizeBytes; 345 346 // The port of a backend Directory Server instance to which the collect 347 // support data extended request should be forwarded. 348 @Nullable private final Integer proxyToServerPort; 349 350 // The report count to use for sampled metrics. 351 @Nullable private final Integer reportCount; 352 353 // The report interval in seconds to use for sampled metrics. 354 @Nullable private final Integer reportIntervalSeconds; 355 356 // The name (without any path information) the client intends to use for the 357 // support data archive file. 358 @Nullable private final String archiveFileName; 359 360 // A comment to include in the support data archive. 361 @Nullable private final String comment; 362 363 // The address of a backend Directory Server to which the collect support data 364 // extended request should be forwarded. 365 @Nullable private final String proxyToServerAddress; 366 367 368 369 /** 370 * Creates a new instance of this extended request with the provided 371 * information. 372 * 373 * @param properties The properties that should be used 374 * for the collect support data extended 375 * request. It must not be 376 * {@code null}. 377 * @param intermediateResponseListener The listener that will be used to 378 * handle any intermediate response 379 * messages that are received in the 380 * course of processing the collect 381 * support data extended request. It 382 * must not be {@code null}. 383 * @param controls The controls to include in the 384 * collect support data extended 385 * request. It may be {@code null} or 386 * empty if no controls are needed. 387 */ 388 public CollectSupportDataExtendedRequest( 389 @NotNull final CollectSupportDataExtendedRequestProperties properties, 390 @NotNull final CollectSupportDataIntermediateResponseListener 391 intermediateResponseListener, 392 @Nullable final Control... controls) 393 { 394 super(COLLECT_SUPPORT_DATA_REQUEST_OID, encodeValue(properties), controls); 395 396 Validator.ensureNotNullWithMessage(intermediateResponseListener, 397 "CollectSupportDataExtendedRequest.intermediateResponseListener " + 398 "must not be null."); 399 this.intermediateResponseListener = intermediateResponseListener; 400 401 archiveFileName = properties.getArchiveFileName(); 402 encryptionPassphrase = properties.getEncryptionPassphrase(); 403 includeBinaryFiles = properties.getIncludeBinaryFiles(); 404 includeExpensiveData = properties.getIncludeExpensiveData(); 405 includeExtensionSource = properties.getIncludeExtensionSource(); 406 includeReplicationStateDump = properties.getIncludeReplicationStateDump(); 407 useSequentialMode = properties.getUseSequentialMode(); 408 logCaptureWindow = properties.getLogCaptureWindow(); 409 securityLevel = properties.getSecurityLevel(); 410 jstackCount = properties.getJStackCount(); 411 reportCount = properties.getReportCount(); 412 reportIntervalSeconds = properties.getReportIntervalSeconds(); 413 maximumFragmentSizeBytes = properties.getMaximumFragmentSizeBytes(); 414 proxyToServerPort = properties.getProxyToServerPort(); 415 comment = properties.getComment(); 416 proxyToServerAddress = properties.getProxyToServerAddress(); 417 418 setIntermediateResponseListener(this); 419 } 420 421 422 423 /** 424 * Constructs an ASN.1 octet string suitable for use as the value of this 425 * collect support data extended request from the given set of properties. 426 * 427 * @param properties The properties that should be used to construct the 428 * extended request value. It must not be {@code null}. 429 * 430 * @return the ASN.1 octet string that was created. 431 */ 432 @NotNull() 433 private static ASN1OctetString encodeValue( 434 @NotNull final CollectSupportDataExtendedRequestProperties properties) 435 { 436 final List<ASN1Element> elements = new ArrayList<>(20); 437 438 final String archiveFileName = properties.getArchiveFileName(); 439 if (archiveFileName != null) 440 { 441 elements.add(new ASN1OctetString(TYPE_ARCHIVE_FILE_NAME, 442 archiveFileName)); 443 } 444 445 final ASN1OctetString encryptionPassphrase = 446 properties.getEncryptionPassphrase(); 447 if (encryptionPassphrase != null) 448 { 449 elements.add(encryptionPassphrase); 450 } 451 452 final Boolean includeExpensiveData = properties.getIncludeExpensiveData(); 453 if (includeExpensiveData != null) 454 { 455 elements.add(new ASN1Boolean(TYPE_INCLUDE_EXPENSIVE_DATA, 456 includeExpensiveData)); 457 } 458 459 final Boolean includeReplicationStateDump = 460 properties.getIncludeReplicationStateDump(); 461 if (includeReplicationStateDump != null) 462 { 463 elements.add(new ASN1Boolean(TYPE_INCLUDE_REPLICATION_STATE_DUMP, 464 includeReplicationStateDump)); 465 } 466 467 final Boolean includeBinaryFiles = properties.getIncludeBinaryFiles(); 468 if (includeBinaryFiles != null) 469 { 470 elements.add(new ASN1Boolean(TYPE_INCLUDE_BINARY_FILES, 471 includeBinaryFiles)); 472 } 473 474 final Boolean includeExtensionSource = 475 properties.getIncludeExtensionSource(); 476 if (includeExtensionSource != null) 477 { 478 elements.add(new ASN1Boolean(TYPE_INCLUDE_EXTENSION_SOURCE, 479 includeExtensionSource)); 480 } 481 482 final Boolean useSequentialMode = properties.getUseSequentialMode(); 483 if (useSequentialMode != null) 484 { 485 elements.add(new ASN1Boolean(TYPE_USE_SEQUENTIAL_MODE, 486 useSequentialMode)); 487 } 488 489 final CollectSupportDataSecurityLevel securityLevel = 490 properties.getSecurityLevel(); 491 if (securityLevel != null) 492 { 493 final int securityLevelIntValue; 494 switch (securityLevel) 495 { 496 case NONE: 497 securityLevelIntValue = SECURITY_LEVEL_VALUE_NONE; 498 break; 499 case OBSCURE_SECRETS: 500 securityLevelIntValue = SECURITY_LEVEL_VALUE_OBSCURE_SECRETS; 501 break; 502 case MAXIMUM: 503 securityLevelIntValue = SECURITY_LEVEL_VALUE_MAXIMUM; 504 break; 505 default: 506 throw new LDAPRuntimeException(new LDAPException( 507 ResultCode.LOCAL_ERROR, 508 ERR_CSD_REQUEST_UNSUPPORTED_SECURITY_LEVEL.get( 509 securityLevel.getName()))); 510 } 511 512 elements.add(new ASN1Enumerated(TYPE_SECURITY_LEVEL, 513 securityLevelIntValue)); 514 } 515 516 final Integer jstackCount = properties.getJStackCount(); 517 if (jstackCount != null) 518 { 519 elements.add(new ASN1Integer(TYPE_JSTACK_COUNT, jstackCount)); 520 } 521 522 final Integer reportCount = properties.getReportCount(); 523 if (reportCount != null) 524 { 525 elements.add(new ASN1Integer(TYPE_REPORT_COUNT, reportCount)); 526 } 527 528 final Integer reportIntervalSeconds = 529 properties.getReportIntervalSeconds(); 530 if (reportIntervalSeconds != null) 531 { 532 elements.add(new ASN1Integer(TYPE_REPORT_INTERVAL_SECONDS, 533 reportIntervalSeconds)); 534 } 535 536 final CollectSupportDataLogCaptureWindow logCaptureWindow = 537 properties.getLogCaptureWindow(); 538 if (logCaptureWindow != null) 539 { 540 elements.add(new ASN1Element(TYPE_LOG_CAPTURE_WINDOW, 541 logCaptureWindow.encode().encode())); 542 } 543 544 final String comment = properties.getComment(); 545 if (comment != null) 546 { 547 elements.add(new ASN1OctetString(TYPE_COMMENT, comment)); 548 } 549 550 final String proxyToServerAddress = properties.getProxyToServerAddress(); 551 if (proxyToServerAddress != null) 552 { 553 elements.add(new ASN1Sequence(TYPE_PROXY_TO_SERVER, 554 new ASN1OctetString(proxyToServerAddress), 555 new ASN1Integer(properties.getProxyToServerPort()))); 556 } 557 558 final Integer maximumFragmentSizeBytes = 559 properties.getMaximumFragmentSizeBytes(); 560 if (maximumFragmentSizeBytes != null) 561 { 562 elements.add(new ASN1Integer(TYPE_MAXIMUM_FRAGMENT_SIZE_BYTES, 563 maximumFragmentSizeBytes)); 564 } 565 566 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 567 } 568 569 570 571 /** 572 * Creates a new collect support data extended request that is decoded from 573 * the provided generic extended request. 574 * 575 * @param request The generic extended request to be 576 * decoded as a collect support data 577 * extended request. It must not be 578 * {@code null}. 579 * @param intermediateResponseListener The listener that will be used to 580 * handle any intermediate response 581 * messages that are received in the 582 * course of processing the collect 583 * support data extended request. It 584 * must not be {@code null}. 585 * 586 * @throws LDAPException If the provided extended request cannot be decoded 587 * as a valid collect support data extended request. 588 */ 589 public CollectSupportDataExtendedRequest( 590 @NotNull final ExtendedRequest request, 591 @NotNull final CollectSupportDataIntermediateResponseListener 592 intermediateResponseListener) 593 throws LDAPException 594 { 595 super(request); 596 597 Validator.ensureNotNullWithMessage(intermediateResponseListener, 598 "CollectSupportDataExtendedRequest.intermediateResponseListener " + 599 "must not be null."); 600 this.intermediateResponseListener = intermediateResponseListener; 601 602 final ASN1OctetString value = request.getValue(); 603 if (value == null) 604 { 605 throw new LDAPException(ResultCode.DECODING_ERROR, 606 ERR_CSD_REQUEST_DECODE_NO_VALUE.get()); 607 } 608 609 try 610 { 611 ASN1OctetString encPassphrase = null; 612 Boolean includeExpensive = null; 613 Boolean includeReplication = null; 614 Boolean includeBinary = null; 615 Boolean includeSource = null; 616 Boolean sequentialMode = null; 617 CollectSupportDataSecurityLevel secLevel = null; 618 Integer jCount = null; 619 Integer rCount = null; 620 Integer rInterval = null; 621 CollectSupportDataLogCaptureWindow lcw = null; 622 String archiveName = null; 623 String commentStr = null; 624 String proxyToAddress = null; 625 Integer proxyToPort = null; 626 Integer maxFragmentSize = null; 627 628 final ASN1Sequence valueSequence = 629 ASN1Sequence.decodeAsSequence(value.getValue()); 630 final ASN1Element[] elements = valueSequence.elements(); 631 for (final ASN1Element e : elements) 632 { 633 switch (e.getType()) 634 { 635 case TYPE_ARCHIVE_FILE_NAME: 636 archiveName = ASN1OctetString.decodeAsOctetString(e).stringValue(); 637 break; 638 case TYPE_ENCRYPTION_PASSPHRASE: 639 encPassphrase = ASN1OctetString.decodeAsOctetString(e); 640 break; 641 case TYPE_INCLUDE_EXPENSIVE_DATA: 642 includeExpensive = ASN1Boolean.decodeAsBoolean(e).booleanValue(); 643 break; 644 case TYPE_INCLUDE_REPLICATION_STATE_DUMP: 645 includeReplication = ASN1Boolean.decodeAsBoolean(e).booleanValue(); 646 break; 647 case TYPE_INCLUDE_BINARY_FILES: 648 includeBinary = ASN1Boolean.decodeAsBoolean(e).booleanValue(); 649 break; 650 case TYPE_INCLUDE_EXTENSION_SOURCE: 651 includeSource = ASN1Boolean.decodeAsBoolean(e).booleanValue(); 652 break; 653 case TYPE_USE_SEQUENTIAL_MODE: 654 sequentialMode = ASN1Boolean.decodeAsBoolean(e).booleanValue(); 655 break; 656 case TYPE_SECURITY_LEVEL: 657 final int secLevelIntValue = 658 ASN1Enumerated.decodeAsEnumerated(e).intValue(); 659 switch (secLevelIntValue) 660 { 661 case SECURITY_LEVEL_VALUE_NONE: 662 secLevel = CollectSupportDataSecurityLevel.NONE; 663 break; 664 case SECURITY_LEVEL_VALUE_OBSCURE_SECRETS: 665 secLevel = CollectSupportDataSecurityLevel.OBSCURE_SECRETS; 666 break; 667 case SECURITY_LEVEL_VALUE_MAXIMUM: 668 secLevel = CollectSupportDataSecurityLevel.MAXIMUM; 669 break; 670 default: 671 throw new LDAPException(ResultCode.DECODING_ERROR, 672 ERR_CSD_REQUEST_DECODE_UNSUPPORTED_SECURITY_LEVEL.get( 673 secLevelIntValue)); 674 } 675 break; 676 case TYPE_JSTACK_COUNT: 677 jCount = ASN1Integer.decodeAsInteger(e).intValue(); 678 break; 679 case TYPE_REPORT_COUNT: 680 rCount = ASN1Integer.decodeAsInteger(e).intValue(); 681 break; 682 case TYPE_REPORT_INTERVAL_SECONDS: 683 rInterval = ASN1Integer.decodeAsInteger(e).intValue(); 684 break; 685 case TYPE_LOG_CAPTURE_WINDOW: 686 final ASN1Element lcwElement = ASN1Element.decode(e.getValue()); 687 try 688 { 689 lcw = CollectSupportDataLogCaptureWindow.decode(lcwElement); 690 } 691 catch (final Exception ex) 692 { 693 Debug.debugException(ex); 694 throw new LDAPException(ResultCode.DECODING_ERROR, 695 ERR_CSD_REQUEST_DECODE_LCW_FAILED.get( 696 StaticUtils.getExceptionMessage(ex)), 697 ex); 698 } 699 break; 700 case TYPE_COMMENT: 701 commentStr = ASN1OctetString.decodeAsOctetString(e).stringValue(); 702 break; 703 case TYPE_PROXY_TO_SERVER: 704 final ASN1Element[] proxyToElements = 705 ASN1Sequence.decodeAsSequence(e).elements(); 706 proxyToAddress = ASN1OctetString.decodeAsOctetString( 707 proxyToElements[0]).stringValue(); 708 proxyToPort = ASN1Integer.decodeAsInteger( 709 proxyToElements[1]).intValue(); 710 break; 711 case TYPE_MAXIMUM_FRAGMENT_SIZE_BYTES: 712 maxFragmentSize = ASN1Integer.decodeAsInteger(e).intValue(); 713 break; 714 } 715 } 716 717 archiveFileName = archiveName; 718 encryptionPassphrase = encPassphrase; 719 includeExpensiveData = includeExpensive; 720 includeReplicationStateDump = includeReplication; 721 includeBinaryFiles = includeBinary; 722 includeExtensionSource = includeSource; 723 useSequentialMode = sequentialMode; 724 securityLevel = secLevel; 725 jstackCount = jCount; 726 reportCount = rCount; 727 reportIntervalSeconds = rInterval; 728 logCaptureWindow = lcw; 729 comment = commentStr; 730 proxyToServerAddress = proxyToAddress; 731 proxyToServerPort = proxyToPort; 732 maximumFragmentSizeBytes = maxFragmentSize; 733 } 734 catch (final LDAPException e) 735 { 736 Debug.debugException(e); 737 throw e; 738 } 739 catch (final Exception e) 740 { 741 Debug.debugException(e); 742 throw new LDAPException(ResultCode.DECODING_ERROR, 743 ERR_CSD_REQUEST_DECODE_ERROR.get( 744 StaticUtils.getExceptionMessage(e)), 745 e); 746 } 747 } 748 749 750 751 /** 752 * Retrieves the listener that will be notified when any output, archive 753 * fragment, or other types of intermediate response messages are received 754 * in response to this extended request. 755 * 756 * @return The listener that will be notified when any output, archive 757 * fragment, or other types of intermediate response messages are 758 * in response to this extended request. 759 */ 760 @NotNull() 761 public CollectSupportDataIntermediateResponseListener 762 getCollectSupportDataIntermediateResponseListener() 763 { 764 return intermediateResponseListener; 765 } 766 767 768 769 /** 770 * Retrieves the name (without any path information) that the client intends 771 * to use for the support data archive file. 772 * 773 * @return The name (without any path information) that the client intends to 774 * use for the support data archive file, or {@code null} if the 775 * server should generate an archive file name. 776 */ 777 @Nullable() 778 public String getArchiveFileName() 779 { 780 return archiveFileName; 781 } 782 783 784 785 /** 786 * Retrieves the passphrase that should be used to encrypt the contents of the 787 * support data archive. 788 * 789 * @return The passphrase that should be used to encrypt the contents of the 790 * support data archive, or {@code null} if the archive should not 791 * be encrypted. 792 */ 793 @Nullable() 794 public ASN1OctetString getEncryptionPassphrase() 795 { 796 return encryptionPassphrase; 797 } 798 799 800 801 /** 802 * Retrieves the value of a flag that indicates whether the support data 803 * archive may include data that is potentially expensive to collect and 804 * could affect the performance or responsiveness of the server. 805 * 806 * @return The value of a flag that indicates whether the support data 807 * archive may include data that is potentially expensive to collect, 808 * or {@code null} if the property should not be specified when the 809 * task is created (in which case the server will use a default 810 * behavior of excluding expensive data). 811 */ 812 @Nullable() 813 public Boolean getIncludeExpensiveData() 814 { 815 return includeExpensiveData; 816 } 817 818 819 820 /** 821 * Retrieves the value of a flag that indicates whether the support data 822 * archive may include a replication state dump, which may be several 823 * megabytes in size. 824 * 825 * @return The value of a flag that indicates whether the support data 826 * archive may include a replication state dump, or {@code null} if 827 * the property should not be specified when the task is created (in 828 * which case the server will use a default behavior of excluding the 829 * state dump). 830 */ 831 @Nullable() 832 public Boolean getIncludeReplicationStateDump() 833 { 834 return includeReplicationStateDump; 835 } 836 837 838 839 /** 840 * Retrieves the value of a flag that indicates whether the support data 841 * archive may include binary files. 842 * 843 * @return The value of a flag that indicates whether the support data 844 * archive may include binary files, or {@code null} if the property 845 * should not be specified when the task is created (in which case 846 * the server will use a default behavior of excluding binary files). 847 */ 848 @Nullable() 849 public Boolean getIncludeBinaryFiles() 850 { 851 return includeBinaryFiles; 852 } 853 854 855 856 /** 857 * Retrieves the value of a flag that indicates whether the support data 858 * archive should include source code (if available) for any third-party 859 * extensions installed in the server. 860 * 861 * @return The value of a flag that indicates whether the support data 862 * archive should include source code (if available) for any 863 * third-party extensions installed in the server, or {@code null} if 864 * the property should not be specified when the task is created (in 865 * which case the server will use a default behavior of excluding 866 * extension source code). 867 */ 868 @Nullable() 869 public Boolean getIncludeExtensionSource() 870 { 871 return includeExtensionSource; 872 } 873 874 875 876 /** 877 * Retrieves the value of a flag that indicates whether the server should 878 * collect items for the support data archive in sequential mode rather than 879 * in parallel. Collecting data in sequential mode may reduce the amount of 880 * memory consumed during the collection process, but it will take longer to 881 * complete. 882 * 883 * @return The value of a flag that indicates whether the server should 884 * collect items for the support data archive in sequential mode 885 * rather than in parallel, or {@code null} if the property should 886 * not be specified when the task is created (in which case the 887 * server will default to capturing data in parallel). 888 */ 889 @Nullable() 890 public Boolean getUseSequentialMode() 891 { 892 return useSequentialMode; 893 } 894 895 896 897 /** 898 * Retrieves the security level that should be used to indicate which data 899 * should be obscured, redacted, or omitted from the support data archive. 900 * 901 * @return The security level that should be used when creating the support 902 * data archive, or {@code null} if the property should not be 903 * specified when the task is created (in which case the server will 904 * use a default security level). 905 */ 906 @Nullable() 907 public CollectSupportDataSecurityLevel getSecurityLevel() 908 { 909 return securityLevel; 910 } 911 912 913 914 /** 915 * Retrieves the number of times that the jstack utility should be invoked to 916 * obtain stack traces from all threads in the server. 917 * 918 * @return The number of times that the jstack utility should be invoked to 919 * obtain stack traces from all threads in the server, or 920 * {@code null} if the property should not be specified when the task 921 * is created (in which case the server will use a default count). 922 */ 923 @Nullable() 924 public Integer getJStackCount() 925 { 926 return jstackCount; 927 } 928 929 930 931 /** 932 * Retrieves the number of intervals that should be captured from tools that 933 * use interval-based sampling (e.g., vmstat, iostat, mpstat, etc.). 934 * 935 * @return The number of intervals that should be captured from tools that 936 * use interval-based sampling, or {@code null} if the property 937 * should not be specified when the task is created (in which case 938 * the server will use a default report count). 939 */ 940 @Nullable() 941 public Integer getReportCount() 942 { 943 return reportCount; 944 } 945 946 947 948 /** 949 * Retrieves the interval duration in seconds that should be used for tools 950 * that use interval-based sampling (e.g., vmstat, iostat, mpstat, etc.). 951 * 952 * @return The interval duration in seconds that should be used for tools 953 * that use interval-based sampling, or {@code null} if the property 954 * should not be specified when the task is created (in which case 955 * the server will use a default report interval). 956 */ 957 @Nullable() 958 public Integer getReportIntervalSeconds() 959 { 960 return reportIntervalSeconds; 961 } 962 963 964 965 /** 966 * Retrieves the log capture window object that indicates how much log content 967 * should be included in the support data archive. 968 * 969 * @return The log capture window object that indicates how much log content 970 * should be included in the support data archive, or {@code null} 971 * if this should not be specified in the request and the server 972 * should choose an appropriate amount of log content. 973 */ 974 @Nullable() 975 public CollectSupportDataLogCaptureWindow getLogCaptureWindow() 976 { 977 return logCaptureWindow; 978 } 979 980 981 982 /** 983 * Retrieves an additional comment that should be included in the support data 984 * archive. 985 * 986 * @return An additional comment that should be included in the support data 987 * archive, or {@code null} if no comment should be included. 988 */ 989 @Nullable() 990 public String getComment() 991 { 992 return comment; 993 } 994 995 996 997 /** 998 * Retrieves the address of the backend Directory Server to which the collect 999 * support data extended request should be forwarded. 1000 * 1001 * @return The address of the backend Directory Server to which the collect 1002 * support data extended request should be forwarded, or {@code null} 1003 * if the request should be processed directly by the server that 1004 * receives it. 1005 */ 1006 @Nullable() 1007 public String getProxyToServerAddress() 1008 { 1009 return proxyToServerAddress; 1010 } 1011 1012 1013 1014 /** 1015 * Retrieves the port of the backend Directory Server to which the collect 1016 * support data extended request should be forwarded. 1017 * 1018 * @return The port of the backend Directory Server to which the collect 1019 * support data extended request should be forwarded, or {@code null} 1020 * if the request should be processed directly by the server that 1021 * receives it. 1022 */ 1023 @Nullable() 1024 public Integer getProxyToServerPort() 1025 { 1026 return proxyToServerPort; 1027 } 1028 1029 1030 1031 /** 1032 * Retrieves the maximum size, in bytes, that may be used for a support data 1033 * archive fragment returned in any single 1034 * {@link CollectSupportDataArchiveFragmentIntermediateResponse} message. 1035 * 1036 * @return The maximum size, in bytes, that may be used for a support data 1037 * archive fragment in any single archive fragment intermediate 1038 * response message, or {@code null} if the server should use a 1039 * default maximum fragment size. 1040 */ 1041 @Nullable() 1042 public Integer getMaximumFragmentSizeBytes() 1043 { 1044 return maximumFragmentSizeBytes; 1045 } 1046 1047 1048 1049 /** 1050 * {@inheritDoc} 1051 */ 1052 @Override() 1053 @NotNull() 1054 public CollectSupportDataExtendedResult process( 1055 @NotNull final LDAPConnection connection, final int depth) 1056 throws LDAPException 1057 { 1058 final ExtendedResult extendedResponse = super.process(connection, depth); 1059 return new CollectSupportDataExtendedResult(extendedResponse); 1060 } 1061 1062 1063 1064 /** 1065 * {@inheritDoc}. 1066 */ 1067 @Override() 1068 @NotNull() 1069 public CollectSupportDataExtendedRequest duplicate() 1070 { 1071 return duplicate(getControls()); 1072 } 1073 1074 1075 1076 /** 1077 * {@inheritDoc}. 1078 */ 1079 @Override() 1080 @NotNull() 1081 public CollectSupportDataExtendedRequest duplicate( 1082 @Nullable final Control[] controls) 1083 { 1084 final CollectSupportDataExtendedRequest r = 1085 new CollectSupportDataExtendedRequest( 1086 new CollectSupportDataExtendedRequestProperties(this), 1087 intermediateResponseListener, controls); 1088 r.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 1089 r.setReferralDepth(getReferralDepth()); 1090 r.setReferralConnector(getReferralConnectorInternal()); 1091 return r; 1092 } 1093 1094 1095 1096 /** 1097 * {@inheritDoc} 1098 */ 1099 @Override() 1100 @NotNull() 1101 public String getExtendedRequestName() 1102 { 1103 return INFO_COLLECT_SUPPORT_DATA_REQUEST_NAME.get(); 1104 } 1105 1106 1107 1108 1109 /** 1110 * {@inheritDoc} 1111 */ 1112 @Override() 1113 public void intermediateResponseReturned( 1114 @NotNull final IntermediateResponse intermediateResponse) 1115 { 1116 final String oid = intermediateResponse.getOID(); 1117 if (oid == null) 1118 { 1119 intermediateResponseListener.handleOtherIntermediateResponse( 1120 intermediateResponse); 1121 return; 1122 } 1123 1124 switch (oid) 1125 { 1126 case CollectSupportDataOutputIntermediateResponse. 1127 COLLECT_SUPPORT_DATA_OUTPUT_INTERMEDIATE_RESPONSE_OID: 1128 final CollectSupportDataOutputIntermediateResponse 1129 outputIntermediateResponse; 1130 try 1131 { 1132 outputIntermediateResponse = 1133 new CollectSupportDataOutputIntermediateResponse( 1134 intermediateResponse); 1135 } 1136 catch (final Exception e) 1137 { 1138 Debug.debugException(e); 1139 intermediateResponseListener.handleOtherIntermediateResponse( 1140 intermediateResponse); 1141 return; 1142 } 1143 1144 intermediateResponseListener.handleOutputIntermediateResponse( 1145 outputIntermediateResponse); 1146 break; 1147 1148 case CollectSupportDataArchiveFragmentIntermediateResponse. 1149 COLLECT_SUPPORT_DATA_ARCHIVE_FRAGMENT_INTERMEDIATE_RESPONSE_OID: 1150 final CollectSupportDataArchiveFragmentIntermediateResponse 1151 fragmentIntermediateResponse; 1152 try 1153 { 1154 fragmentIntermediateResponse = 1155 new CollectSupportDataArchiveFragmentIntermediateResponse( 1156 intermediateResponse); 1157 } 1158 catch (final Exception e) 1159 { 1160 Debug.debugException(e); 1161 intermediateResponseListener.handleOtherIntermediateResponse( 1162 intermediateResponse); 1163 return; 1164 } 1165 1166 intermediateResponseListener.handleArchiveFragmentIntermediateResponse( 1167 fragmentIntermediateResponse); 1168 break; 1169 1170 default: 1171 intermediateResponseListener.handleOtherIntermediateResponse( 1172 intermediateResponse); 1173 } 1174 } 1175 1176 1177 1178 /** 1179 * {@inheritDoc} 1180 */ 1181 @Override() 1182 public void toString(@NotNull final StringBuilder buffer) 1183 { 1184 buffer.append("CollectSupportDataExtendedRequest(oid='"); 1185 buffer.append(getOID()); 1186 buffer.append('\''); 1187 1188 if (archiveFileName != null) 1189 { 1190 buffer.append(", archiveFileName='"); 1191 buffer.append(archiveFileName); 1192 buffer.append('\''); 1193 } 1194 1195 if (encryptionPassphrase != null) 1196 { 1197 buffer.append(", encryptionPassphrase='*****REDACTED*****'"); 1198 } 1199 1200 if (includeExpensiveData != null) 1201 { 1202 buffer.append(", includeExpensiveData="); 1203 buffer.append(includeExpensiveData); 1204 } 1205 1206 if (includeReplicationStateDump != null) 1207 { 1208 buffer.append(", includeReplicationStateDump="); 1209 buffer.append(includeReplicationStateDump); 1210 } 1211 1212 if (includeBinaryFiles != null) 1213 { 1214 buffer.append(", includeBinaryFiles="); 1215 buffer.append(includeBinaryFiles); 1216 } 1217 1218 if (includeExtensionSource != null) 1219 { 1220 buffer.append(", includeExtensionSource="); 1221 buffer.append(includeExtensionSource); 1222 } 1223 1224 if (useSequentialMode != null) 1225 { 1226 buffer.append(", useSequentialMode="); 1227 buffer.append(useSequentialMode); 1228 } 1229 1230 if (securityLevel != null) 1231 { 1232 buffer.append(", securityLevel='"); 1233 buffer.append(securityLevel.getName()); 1234 buffer.append('\''); 1235 } 1236 1237 if (jstackCount != null) 1238 { 1239 buffer.append(", jstackCount="); 1240 buffer.append(jstackCount); 1241 } 1242 1243 if (reportCount != null) 1244 { 1245 buffer.append(", reportCount="); 1246 buffer.append(reportCount); 1247 } 1248 1249 if (reportIntervalSeconds != null) 1250 { 1251 buffer.append(", reportIntervalSeconds="); 1252 buffer.append(reportIntervalSeconds); 1253 } 1254 1255 if (logCaptureWindow != null) 1256 { 1257 buffer.append(", logCaptureWindow="); 1258 logCaptureWindow.toString(buffer); 1259 } 1260 1261 if (comment != null) 1262 { 1263 buffer.append(", comment='"); 1264 buffer.append(comment); 1265 buffer.append('\''); 1266 } 1267 1268 if (proxyToServerAddress != null) 1269 { 1270 buffer.append(", proxyToServerAddress='"); 1271 buffer.append(proxyToServerAddress); 1272 buffer.append('\''); 1273 } 1274 1275 if (proxyToServerPort != null) 1276 { 1277 buffer.append(", proxyToServerPort="); 1278 buffer.append(proxyToServerPort); 1279 } 1280 1281 if (maximumFragmentSizeBytes != null) 1282 { 1283 buffer.append(", maximumFragmentSizeBytes="); 1284 buffer.append(maximumFragmentSizeBytes); 1285 } 1286 1287 final Control[] controls = getControls(); 1288 if (controls.length > 0) 1289 { 1290 buffer.append(", controls={"); 1291 for (int i=0; i < controls.length; i++) 1292 { 1293 if (i > 0) 1294 { 1295 buffer.append(", "); 1296 } 1297 1298 buffer.append(controls[i]); 1299 } 1300 buffer.append('}'); 1301 } 1302 1303 buffer.append(')'); 1304 } 1305}