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