001/*
002 * Copyright 2020-2026 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2020-2026 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-2026 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.tasks;
037
038
039
040import java.util.ArrayList;
041import java.util.Arrays;
042import java.util.Collections;
043import java.util.Date;
044import java.util.LinkedHashMap;
045import java.util.List;
046import java.util.Map;
047import java.util.concurrent.TimeUnit;
048
049import com.unboundid.ldap.sdk.Attribute;
050import com.unboundid.ldap.sdk.Entry;
051import com.unboundid.util.Debug;
052import com.unboundid.util.NotMutable;
053import com.unboundid.util.NotNull;
054import com.unboundid.util.Nullable;
055import com.unboundid.util.StaticUtils;
056import com.unboundid.util.ThreadSafety;
057import com.unboundid.util.ThreadSafetyLevel;
058import com.unboundid.util.args.ArgumentException;
059import com.unboundid.util.args.DurationArgument;
060
061import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*;
062
063
064
065/**
066 * This class defines a Directory Server task that can be used to invoke the
067 * collect-support-data tool to capture a variety of information that may help
068 * monitor the state of the server or diagnose potential problems.
069 * <BR>
070 * <BLOCKQUOTE>
071 *   <B>NOTE:</B>  This class, and other classes within the
072 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
073 *   supported for use against Ping Identity, UnboundID, and
074 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
075 *   for proprietary functionality or for external specifications that are not
076 *   considered stable or mature enough to be guaranteed to work in an
077 *   interoperable way with other types of LDAP servers.
078 * </BLOCKQUOTE>
079 * <BR>
080 * The properties that are available for use with this type of task include:
081 * <UL>
082 *   <LI>The path (on the server filesystem) to which the support data archive
083 *       should be written.  If this is not provided, then the server will
084 *       determine an appropriate output file to use.  If this is provided and
085 *       refers to a file that exists, that file will be overwritten.  If this
086 *       is provided and refers to a directory that exists, then a file will
087 *       be created in that directory with a server-generated name.  If this
088 *       is provided and refers to a file that does not exist, then its parent
089 *       directory must exist, and a new file will be created with the specified
090 *       path.</LI>
091 *   <LI>The path (on the server filesystem) to a file containing the passphrase
092 *       to use to encrypt the contents of the support data archive.  If this is
093 *       not provided, then the support data archive will not be encrypted.</LI>
094 *   <LI>A flag that indicates whether to include data that may be expensive to
095 *       capture in the support data archive.  This information will not be
096 *       included by default.</LI>
097 *   <LI>A flag that indicates whether to include a replication state dump
098 *       (which may be several megabytes in size) in the support data
099 *       archive.  This information will not be included by default.</LI>
100 *   <LI>A flag that indicates whether to include binary files in the support
101 *       data archive.  Binary files will not be included by default.</LI>
102 *   <LI>A flag that indicates whether to include source code (if available) to
103 *       any third-party extensions installed in the server.  Extension source
104 *       code will not be included by default.</LI>
105 *   <LI>The data security level to use when redacting data to include in the
106 *       support data archive.  If this is not specified, the server will
107 *       select an appropriate security level.</LI>
108 *   <LI>A flag that indicates whether to capture items in sequential mode
109 *       (which will use less memory, but at the expense of taking longer to
110 *       complete) rather than in parallel.  Support data will be captured in
111 *       parallel by default.</LI>
112 *   <LI>The number and duration between intervals for use when collecting
113 *       output of tools (like vmstat, iostat, mpstat, etc.) that use
114 *       sampling over time.  If this is not provided, the server will use a
115 *       default count and interval.</LI>
116 *   <LI>The number of times to invoke the jstack utility to obtain a stack
117 *       trace of threads running in the JVM.  If this is not provided, the
118 *       server will use a default count.</LI>
119 *   <LI>The duration (the length of time before the time the task is invoked)
120 *       for log messages to be included in the support data archive.  If this
121 *       is not provided, the server will automatically select the amount of
122 *       log content to include.</LI>
123 *   <LI>The amount of data in kilobytes to capture from the beginning or end of
124 *       each log file.  If this is not provided, the server will automatically
125 *       select the amount of log content to include.</LI>
126 *   <LI>A flag that indicates whether the server should exclude Java Flight
127 *       Recorder (JFR) data from the archive.</LI>
128 *   <LI>An optional comment to include in the support data archive.</LI>
129 * </UL>
130 */
131@NotMutable()
132@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
133public final class CollectSupportDataTask
134       extends Task
135{
136  /**
137   * The fully-qualified name of the Java class that is used for the collect
138   * support data task.
139   */
140  @NotNull static final String COLLECT_SUPPORT_DATA_TASK_CLASS =
141       "com.unboundid.directory.server.tasks.CollectSupportDataTask";
142
143
144
145  /**
146   * The prefix that will appear at the beginning of all attribute names used by
147   * the collect support data task.
148   */
149  @NotNull private static final String ATTR_PREFIX =
150       "ds-task-collect-support-data-";
151
152
153
154  /**
155   * The name of the attribute used to specify a comment to include in the
156   * support data archive.
157   */
158  @NotNull public static final String ATTR_COMMENT = ATTR_PREFIX + "comment";
159
160
161
162  /**
163   * The name of the attribute used to specify the path to a file containing the
164   * passphrase to use to encrypt the contents of the support data archive.
165   */
166  @NotNull public static final String ATTR_ENCRYPTION_PASSPHRASE_FILE =
167       ATTR_PREFIX + "encryption-passphrase-file";
168
169
170
171  /**
172   * The name of the attribute used to indicate whether the support data archive
173   * may include binary files that may otherwise have been omitted.
174   */
175  @NotNull public static final String ATTR_INCLUDE_BINARY_FILES =
176       ATTR_PREFIX + "include-binary-files";
177
178
179
180  /**
181   * The name of the attribute used to indicate whether the support data archive
182   * should include information that may be expensive to capture.
183   */
184  @NotNull public static final String ATTR_INCLUDE_EXPENSIVE_DATA =
185       ATTR_PREFIX + "include-expensive-data";
186
187
188
189  /**
190   * The name of the attribute used to indicate whether the support data archive
191   * may include the source code (if available) for any third-party extensions
192   * installed in the server.
193   */
194  @NotNull public static final String ATTR_INCLUDE_EXTENSION_SOURCE =
195       ATTR_PREFIX + "include-extension-source";
196
197
198
199  /**
200   * The name of the attribute used to indicate whether the support data archive
201   * should include a replication state dump (which may be several megabytes in
202   * size).
203   */
204  @NotNull public static final String ATTR_INCLUDE_REPLICATION_STATE_DUMP =
205       ATTR_PREFIX + "include-replication-state-dump";
206
207
208
209  /**
210   * The name of the attribute used to specify the number of times to invoke the
211   * jstack utility to capture server thread stack traces.
212   */
213  @NotNull public static final String ATTR_JSTACK_COUNT =
214       ATTR_PREFIX + "jstack-count";
215
216
217
218  /**
219   * The name of the attribute used to specify the length of time that should be
220   * covered by the log data included in the support data archive.
221   */
222  @NotNull public static final String ATTR_LOG_DURATION =
223       ATTR_PREFIX + "log-duration";
224
225
226
227  /**
228   * The name of the attribute used to specify the end time for the range of
229   * log messages that should be included in the support data archive.
230   */
231  @NotNull public static final String ATTR_LOG_END_TIME =
232       ATTR_PREFIX + "log-end-time";
233
234
235
236  /**
237   * The name of the attribute used to specify the start time for the range of
238   * log messages that should be included in the support data archive.
239   */
240  @NotNull public static final String ATTR_LOG_START_TIME =
241       ATTR_PREFIX + "log-start-time";
242
243
244
245  /**
246   * The name of the attribute used to specify the amount of data in kilobytes
247   * to capture from the beginning of each log file included in the support data
248   * archive.
249   */
250  @NotNull public static final String ATTR_LOG_FILE_HEAD_COLLECTION_SIZE_KB =
251       ATTR_PREFIX + "log-file-head-collection-size-kb";
252
253
254
255  /**
256   * The name of the attribute used to specify the amount of data in kilobytes
257   * to capture from the end of each log file included in the support data
258   * archive.
259   */
260  @NotNull public static final String ATTR_LOG_FILE_TAIL_COLLECTION_SIZE_KB =
261       ATTR_PREFIX + "log-file-tail-collection-size-kb";
262
263
264
265  /**
266   * The name of the attribute used to specify the path to which the support
267   * data archive should be written.
268   */
269  @NotNull public static final String ATTR_OUTPUT_PATH =
270       ATTR_PREFIX + "output-path";
271
272
273
274  /**
275   * The name of the attribute used to specify the number of intervals to
276   * capture for tools that capture multiple samples.
277   */
278  @NotNull public static final String ATTR_REPORT_COUNT =
279       ATTR_PREFIX + "report-count";
280
281
282
283  /**
284   * The name of the attribute used to specify the length of time, in seconds,
285   * between samples collected from tools that capture multiple samples.
286   */
287  @NotNull public static final String ATTR_REPORT_INTERVAL_SECONDS =
288       ATTR_PREFIX + "report-interval-seconds";
289
290
291
292  /**
293   *The name of the attribute used to specify the minimum age of previous
294   * support data archives that should be retained.
295   */
296  @NotNull public static final String ATTR_RETAIN_PREVIOUS_ARCHIVE_AGE =
297       ATTR_PREFIX + "retain-previous-support-data-archive-age";
298
299
300
301  /**
302   *The name of the attribute used to specify the minimum number of previous
303   * support data archives that should be retained.
304   */
305  @NotNull public static final String ATTR_RETAIN_PREVIOUS_ARCHIVE_COUNT =
306       ATTR_PREFIX + "retain-previous-support-data-archive-count";
307
308
309
310  /**
311   * The name of the attribute used to specify the security level to use for
312   * information added to the support data archive.
313   */
314  @NotNull public static final String ATTR_SECURITY_LEVEL =
315       ATTR_PREFIX + "security-level";
316
317
318
319  /**
320   * The name of the attribute used to indicate whether to skip the collection
321   * of Java Flight Recorder data.
322   */
323  @NotNull public static final String ATTR_NO_JFR =
324       ATTR_PREFIX + "no-jfr";
325
326
327
328  /**
329   * The name of the attribute used to indicate whether to collect items
330   * sequentially rather than in parallel.
331   */
332  @NotNull public static final String ATTR_USE_SEQUENTIAL_MODE =
333       ATTR_PREFIX + "use-sequential-mode";
334
335
336
337  /**
338   * The name of the object class used in collect support data task entries.
339   */
340  @NotNull public static final String OC_COLLECT_SUPPORT_DATA_TASK =
341       "ds-task-collect-support-data";
342
343
344
345  /**
346   * The task property that will be used for the comment.
347   */
348  @NotNull static final TaskProperty PROPERTY_COMMENT =
349     new TaskProperty(ATTR_COMMENT, INFO_CSD_DISPLAY_NAME_COMMENT.get(),
350          INFO_CSD_DESCRIPTION_COMMENT.get(), String.class, false, false,
351          false);
352
353
354
355  /**
356   * The task property that will be used for the encryption passphrase file.
357   */
358  @NotNull static final TaskProperty PROPERTY_ENCRYPTION_PASSPHRASE_FILE =
359     new TaskProperty(ATTR_ENCRYPTION_PASSPHRASE_FILE,
360          INFO_CSD_DISPLAY_NAME_ENC_PW_FILE.get(),
361          INFO_CSD_DESCRIPTION_ENC_PW_FILE.get(), String.class, false, false,
362          false);
363
364
365
366  /**
367   * The task property that will be used for the include binary files flag.
368   */
369  @NotNull static final TaskProperty PROPERTY_INCLUDE_BINARY_FILES =
370     new TaskProperty(ATTR_INCLUDE_BINARY_FILES,
371          INFO_CSD_DISPLAY_NAME_INCLUDE_BINARY_FILES.get(),
372          INFO_CSD_DESCRIPTION_INCLUDE_BINARY_FILES.get(), Boolean.class, false,
373          false, false);
374
375
376
377  /**
378   * The task property that will be used for the include expensive data flag.
379   */
380  @NotNull static final TaskProperty PROPERTY_INCLUDE_EXPENSIVE_DATA =
381     new TaskProperty(ATTR_INCLUDE_EXPENSIVE_DATA,
382          INFO_CSD_DISPLAY_NAME_INCLUDE_EXPENSIVE_DATA.get(),
383          INFO_CSD_DESCRIPTION_INCLUDE_EXPENSIVE_DATA.get(), Boolean.class,
384          false, false, false);
385
386
387
388  /**
389   * The task property that will be used for the include extension source flag.
390   */
391  @NotNull static final TaskProperty PROPERTY_INCLUDE_EXTENSION_SOURCE =
392     new TaskProperty(ATTR_INCLUDE_EXTENSION_SOURCE,
393          INFO_CSD_DISPLAY_NAME_INCLUDE_EXTENSION_SOURCE.get(),
394          INFO_CSD_DESCRIPTION_INCLUDE_EXTENSION_SOURCE.get(), Boolean.class,
395          false, false, false);
396
397
398
399  /**
400   * The task property that will be used for the include replication state dump
401   * flag.
402   */
403  @NotNull static final TaskProperty PROPERTY_INCLUDE_REPLICATION_STATE_DUMP =
404     new TaskProperty(ATTR_INCLUDE_REPLICATION_STATE_DUMP,
405          INFO_CSD_DISPLAY_NAME_INCLUDE_REPLICATION_STATE_DUMP.get(),
406          INFO_CSD_DESCRIPTION_INCLUDE_REPLICATION_STATE_DUMP.get(),
407          Boolean.class, false, false, false);
408
409
410
411  /**
412   * The task property that will be used for the jstack count.
413   */
414  @NotNull static final TaskProperty PROPERTY_JSTACK_COUNT =
415     new TaskProperty(ATTR_JSTACK_COUNT,
416          INFO_CSD_DISPLAY_NAME_JSTACK_COUNT.get(),
417          INFO_CSD_DESCRIPTION_JSTACK_COUNT.get(),
418          Long.class, false, false, false);
419
420
421
422  /**
423   * The task property that will be used for the log duration.
424   */
425  @NotNull static final TaskProperty PROPERTY_LOG_DURATION =
426     new TaskProperty(ATTR_LOG_DURATION,
427          INFO_CSD_DISPLAY_NAME_LOG_DURATION.get(),
428          INFO_CSD_DESCRIPTION_LOG_DURATION.get(),
429          String.class, false, false, false);
430
431
432
433  /**
434   * The task property that will be used for the log end time.
435   */
436  @NotNull static final TaskProperty PROPERTY_LOG_END_TIME =
437     new TaskProperty(ATTR_LOG_END_TIME,
438          INFO_CSD_DISPLAY_NAME_LOG_END_TIME.get(),
439          INFO_CSD_DESCRIPTION_LOG_END_TIME.get(),
440          Date.class, false, false, false);
441
442
443
444  /**
445   * The task property that will be used for the log start time.
446   */
447  @NotNull static final TaskProperty PROPERTY_LOG_START_TIME =
448     new TaskProperty(ATTR_LOG_START_TIME,
449          INFO_CSD_DISPLAY_NAME_LOG_START_TIME.get(),
450          INFO_CSD_DESCRIPTION_LOG_START_TIME.get(),
451          Date.class, false, false, false);
452
453
454
455  /**
456   * The task property that will be used for the log head size.
457   */
458  @NotNull static final TaskProperty PROPERTY_LOG_FILE_HEAD_COLLECTION_SIZE_KB =
459     new TaskProperty(ATTR_LOG_FILE_HEAD_COLLECTION_SIZE_KB,
460          INFO_CSD_DISPLAY_NAME_LOG_HEAD_SIZE_KB.get(),
461          INFO_CSD_DESCRIPTION_LOG_HEAD_SIZE_KB.get(),
462          Long.class, false, false, false);
463
464
465
466  /**
467   * The task property that will be used for the log tail size.
468   */
469  @NotNull static final TaskProperty PROPERTY_LOG_FILE_TAIL_COLLECTION_SIZE_KB =
470     new TaskProperty(ATTR_LOG_FILE_TAIL_COLLECTION_SIZE_KB,
471          INFO_CSD_DISPLAY_NAME_LOG_TAIL_SIZE_KB.get(),
472          INFO_CSD_DESCRIPTION_LOG_TAIL_SIZE_KB.get(),
473          Long.class, false, false, false);
474
475
476
477  /**
478   * The task property that will be used for the no JFR flag.
479   */
480  @NotNull static final TaskProperty PROPERTY_NO_JFR =
481     new TaskProperty(ATTR_NO_JFR,
482          INFO_CSD_DISPLAY_NAME_NO_JFR.get(),
483          INFO_CSD_DESCRIPTION_NO_JFR.get(),
484          Boolean.class, false, false, false);
485
486
487
488  /**
489   * The task property that will be used for the output path.
490   */
491  @NotNull static final TaskProperty PROPERTY_OUTPUT_PATH =
492     new TaskProperty(ATTR_OUTPUT_PATH,
493          INFO_CSD_DISPLAY_NAME_OUTPUT_PATH.get(),
494          INFO_CSD_DESCRIPTION_OUTPUT_PATH.get(),
495          String.class, false, false, false);
496
497
498
499  /**
500   * The task property that will be used for the report count.
501   */
502  @NotNull static final TaskProperty PROPERTY_REPORT_COUNT =
503     new TaskProperty(ATTR_REPORT_COUNT,
504          INFO_CSD_DISPLAY_NAME_REPORT_COUNT.get(),
505          INFO_CSD_DESCRIPTION_REPORT_COUNT.get(),
506          Long.class, false, false, false);
507
508
509
510  /**
511   * The task property that will be used for the report interval.
512   */
513  @NotNull static final TaskProperty PROPERTY_REPORT_INTERVAL_SECONDS =
514     new TaskProperty(ATTR_REPORT_INTERVAL_SECONDS,
515          INFO_CSD_DISPLAY_NAME_REPORT_INTERVAL.get(),
516          INFO_CSD_DESCRIPTION_REPORT_INTERVAL.get(),
517          Long.class, false, false, false);
518
519
520
521  /**
522   * The task property that will be used for the retain previous support data
523   * archive age.
524   */
525  @NotNull static final TaskProperty PROPERTY_RETAIN_PREVIOUS_ARCHIVE_AGE =
526     new TaskProperty(ATTR_RETAIN_PREVIOUS_ARCHIVE_AGE,
527          INFO_CSD_DISPLAY_NAME_RETAIN_PREVIOUS_ARCHIVE_AGE.get(),
528          INFO_CSD_DESCRIPTION_RETAIN_PREVIOUS_ARCHIVE_AGE.get(),
529          String.class, false, false, false);
530
531
532
533  /**
534   * The task property that will be used for the retain previous support data
535   * archive count.
536   */
537  @NotNull static final TaskProperty PROPERTY_RETAIN_PREVIOUS_ARCHIVE_COUNT =
538     new TaskProperty(ATTR_RETAIN_PREVIOUS_ARCHIVE_COUNT,
539          INFO_CSD_DISPLAY_NAME_RETAIN_PREVIOUS_ARCHIVE_COUNT.get(),
540          INFO_CSD_DESCRIPTION_RETAIN_PREVIOUS_ARCHIVE_COUNT.get(),
541          Long.class, false, false, false);
542
543
544
545  /**
546   * The task property that will be used for the security level.
547   */
548  @NotNull static final TaskProperty PROPERTY_SECURITY_LEVEL =
549     new TaskProperty(ATTR_SECURITY_LEVEL,
550          INFO_CSD_DISPLAY_NAME_SECURITY_LEVEL.get(),
551          INFO_CSD_DESCRIPTION_SECURITY_LEVEL.get(
552               CollectSupportDataSecurityLevel.NONE.getName(),
553               CollectSupportDataSecurityLevel.OBSCURE_SECRETS.getName(),
554               CollectSupportDataSecurityLevel.MAXIMUM.getName()),
555          String.class, false, false, false,
556          new Object[]
557          {
558            CollectSupportDataSecurityLevel.NONE.getName(),
559            CollectSupportDataSecurityLevel.OBSCURE_SECRETS.getName(),
560            CollectSupportDataSecurityLevel.MAXIMUM.getName()
561          });
562
563
564
565  /**
566   * The task property that will be used for the use sequential mode flag.
567   */
568  @NotNull static final TaskProperty PROPERTY_USE_SEQUENTIAL_MODE =
569     new TaskProperty(ATTR_USE_SEQUENTIAL_MODE,
570          INFO_CSD_DISPLAY_NAME_USE_SEQUENTIAL_MODE.get(),
571          INFO_CSD_DESCRIPTION_USE_SEQUENTIAL_MODE.get(),
572          Boolean.class, false, false, false);
573
574
575
576  /**
577   * The serial version UID for this serializable class.
578   */
579  private static final long serialVersionUID = -3414981969721886291L;
580
581
582
583  // Indicates whether to include binary files in the support data archive.
584  @Nullable private final Boolean includeBinaryFiles;
585
586  // Indicates whether to include expensive data in the support data archive.
587  @Nullable private final Boolean includeExpensiveData;
588
589  // Indicates whether to include third-party extension source code in the
590  // support data archive.
591  @Nullable private final Boolean includeExtensionSource;
592
593  // Indicates whether to include a replication state dump in the support data
594  // archive.
595  @Nullable private final Boolean includeReplicationStateDump;
596
597  // Indicates whether to skip the collection of Java Flight Recorder data.
598  @Nullable private final Boolean noJFR;
599
600  // Indicates whether to capture information sequentially rather than in
601  // parallel.
602  @Nullable private final Boolean useSequentialMode;
603
604  // The security level to use for data included in the support data archive.
605  @Nullable private final CollectSupportDataSecurityLevel securityLevel;
606
607  // The time at which to end collecting log data.
608  @Nullable private final Date logEndTime;
609
610  // The time at which to start collecting log data.
611  @Nullable private final Date logStartTime;
612
613  // The number of jstacks to include in the support data archive.
614  @Nullable private final Integer jstackCount;
615
616  // The amount of data in kilobytes to capture from the beginning of each log
617  // file.
618  @Nullable private final Integer logFileHeadCollectionSizeKB;
619
620  // The amount of data in kilobytes to capture from the end of each log file.
621  @Nullable private final Integer logFileTailCollectionSizeKB;
622
623  // The report count to use for sampled metrics.
624  @Nullable private final Integer reportCount;
625
626  // The report interval, in seconds, to use for sampled metrics.
627  @Nullable private final Integer reportIntervalSeconds;
628
629  // The minimum number of existing support data archives that should be
630  // retained.
631  @Nullable private final Integer retainPreviousSupportDataArchiveCount;
632
633  // A comment to include in the support data archive.
634  @Nullable private final String comment;
635
636  // The path to the encryption passphrase file.
637  @Nullable private final String encryptionPassphraseFile;
638
639  // A string representation of the log duration to capture.
640  @Nullable private final String logDuration;
641
642  // The path to which the support data archive should be written.
643  @Nullable private final String outputPath;
644
645  // The minimum age for existing support data archives that should be retained.
646  @Nullable private final String retainPreviousSupportDataArchiveAge;
647
648
649
650  /**
651   * Creates a new collect support data task instance that will use default
652   * settings for all properties.  This instance may be used to invoke the
653   * task, but it can also be used for obtaining general information about this
654   * task, including the task name, description, and supported properties.
655   */
656  public CollectSupportDataTask()
657  {
658    this(new CollectSupportDataTaskProperties());
659  }
660
661
662
663  /**
664   * Creates a new collect support data task instance using the provided
665   * properties.
666   *
667   * @param  properties  The properties to use to create the collect support
668   *                     data task.  It must not be {@code null}.
669   */
670  public CollectSupportDataTask(
671              @NotNull final CollectSupportDataTaskProperties properties)
672  {
673    super(properties.getTaskID(), COLLECT_SUPPORT_DATA_TASK_CLASS,
674         properties.getScheduledStartTime(), properties.getDependencyIDs(),
675         properties.getFailedDependencyAction(), properties.getNotifyOnStart(),
676         properties.getNotifyOnCompletion(), properties.getNotifyOnSuccess(),
677         properties.getNotifyOnError(), properties.getAlertOnStart(),
678         properties.getAlertOnSuccess(), properties.getAlertOnError());
679
680    includeBinaryFiles = properties.getIncludeBinaryFiles();
681    includeExpensiveData = properties.getIncludeExpensiveData();
682    includeExtensionSource = properties.getIncludeExtensionSource();
683    includeReplicationStateDump = properties.getIncludeReplicationStateDump();
684    noJFR = properties.getNoJFR();
685    useSequentialMode = properties.getUseSequentialMode();
686    securityLevel = properties.getSecurityLevel();
687    jstackCount = properties.getJStackCount();
688    logFileHeadCollectionSizeKB = properties.getLogFileHeadCollectionSizeKB();
689    logFileTailCollectionSizeKB = properties.getLogFileTailCollectionSizeKB();
690    reportCount = properties.getReportCount();
691    reportIntervalSeconds = properties.getReportIntervalSeconds();
692    retainPreviousSupportDataArchiveCount =
693         properties.getRetainPreviousSupportDataArchiveCount();
694    comment = properties.getComment();
695    encryptionPassphraseFile = properties.getEncryptionPassphraseFile();
696    logStartTime = properties.getLogStartTime();
697    logEndTime = properties.getLogEndTime();
698    logDuration = properties.getLogDuration();
699    outputPath = properties.getOutputPath();
700    retainPreviousSupportDataArchiveAge =
701         properties.getRetainPreviousSupportDataArchiveAge();
702  }
703
704
705
706  /**
707   * Creates a new collect support data task from the provided entry.
708   *
709   * @param  entry  The entry to use to create this collect support data task.
710   *
711   * @throws  TaskException  If the provided entry cannot be parsed as a collect
712   *                         support data task entry.
713   */
714  public CollectSupportDataTask(@NotNull final Entry entry)
715         throws TaskException
716  {
717    super(entry);
718
719    includeBinaryFiles =
720         entry.getAttributeValueAsBoolean(ATTR_INCLUDE_BINARY_FILES);
721    includeExpensiveData =
722         entry.getAttributeValueAsBoolean(ATTR_INCLUDE_EXPENSIVE_DATA);
723    includeExtensionSource =
724         entry.getAttributeValueAsBoolean(ATTR_INCLUDE_EXTENSION_SOURCE);
725    includeReplicationStateDump =
726         entry.getAttributeValueAsBoolean(ATTR_INCLUDE_REPLICATION_STATE_DUMP);
727    useSequentialMode =
728         entry.getAttributeValueAsBoolean(ATTR_USE_SEQUENTIAL_MODE);
729    noJFR = entry.getAttributeValueAsBoolean(ATTR_NO_JFR);
730
731    jstackCount = entry.getAttributeValueAsInteger(ATTR_JSTACK_COUNT);
732    logFileHeadCollectionSizeKB = entry.getAttributeValueAsInteger(
733         ATTR_LOG_FILE_HEAD_COLLECTION_SIZE_KB);
734    logFileTailCollectionSizeKB = entry.getAttributeValueAsInteger(
735         ATTR_LOG_FILE_TAIL_COLLECTION_SIZE_KB);
736    reportCount = entry.getAttributeValueAsInteger(ATTR_REPORT_COUNT);
737    reportIntervalSeconds =
738         entry.getAttributeValueAsInteger(ATTR_REPORT_INTERVAL_SECONDS);
739    retainPreviousSupportDataArchiveCount =
740         entry.getAttributeValueAsInteger(ATTR_RETAIN_PREVIOUS_ARCHIVE_COUNT);
741
742    comment = entry.getAttributeValue(ATTR_COMMENT);
743    encryptionPassphraseFile =
744         entry.getAttributeValue(ATTR_ENCRYPTION_PASSPHRASE_FILE);
745    outputPath = entry.getAttributeValue(ATTR_OUTPUT_PATH);
746
747    final String securityLevelStr =
748         entry.getAttributeValue(ATTR_SECURITY_LEVEL);
749    if (securityLevelStr == null)
750    {
751      securityLevel = null;
752    }
753    else
754    {
755      securityLevel = CollectSupportDataSecurityLevel.forName(securityLevelStr);
756      if (securityLevel == null)
757      {
758        throw new TaskException(ERR_CSD_ENTRY_INVALID_SECURITY_LEVEL.get(
759             entry.getDN(), securityLevelStr, ATTR_SECURITY_LEVEL,
760             CollectSupportDataSecurityLevel.NONE.getName(),
761             CollectSupportDataSecurityLevel.OBSCURE_SECRETS.getName(),
762             CollectSupportDataSecurityLevel.MAXIMUM.getName()));
763      }
764    }
765
766    if (entry.hasAttribute(ATTR_LOG_START_TIME))
767    {
768      logStartTime = entry.getAttributeValueAsDate(ATTR_LOG_START_TIME);
769      if (logStartTime == null)
770      {
771        throw new TaskException(
772                ERR_CSD_ENTRY_INVALID_TIMESTAMP.get(entry.getDN(),
773                        entry.getAttributeValue(ATTR_LOG_START_TIME),
774                        ATTR_LOG_START_TIME));
775      }
776    }
777    else
778    {
779      logStartTime = null;
780    }
781
782    if (entry.hasAttribute(ATTR_LOG_END_TIME))
783    {
784      logEndTime = entry.getAttributeValueAsDate(ATTR_LOG_END_TIME);
785      if (logEndTime == null)
786      {
787        throw new TaskException(
788                ERR_CSD_ENTRY_INVALID_TIMESTAMP.get(entry.getDN(),
789                        entry.getAttributeValue(ATTR_LOG_END_TIME),
790                        ATTR_LOG_END_TIME));
791      }
792    }
793    else
794    {
795      logEndTime = null;
796    }
797
798    logDuration = entry.getAttributeValue(ATTR_LOG_DURATION);
799    if (logDuration != null)
800    {
801      try
802      {
803        DurationArgument.parseDuration(logDuration, TimeUnit.MILLISECONDS);
804      }
805      catch (final Exception e)
806      {
807        Debug.debugException(e);
808        throw new TaskException(
809             ERR_CSD_ENTRY_INVALID_DURATION.get(entry.getDN(), logDuration,
810                  ATTR_LOG_DURATION),
811             e);
812      }
813    }
814
815    retainPreviousSupportDataArchiveAge =
816         entry.getAttributeValue(ATTR_RETAIN_PREVIOUS_ARCHIVE_AGE);
817    if (retainPreviousSupportDataArchiveAge != null)
818    {
819      try
820      {
821        DurationArgument.parseDuration(retainPreviousSupportDataArchiveAge,
822             TimeUnit.MILLISECONDS);
823      }
824      catch (final Exception e)
825      {
826        Debug.debugException(e);
827        throw new TaskException(
828             ERR_CSD_ENTRY_INVALID_DURATION.get(entry.getDN(),
829                  retainPreviousSupportDataArchiveAge,
830                  ATTR_RETAIN_PREVIOUS_ARCHIVE_AGE),
831             e);
832      }
833    }
834  }
835
836
837
838  /**
839   * Creates a new collect support data task from the provided set of task
840   * properties.
841   *
842   * @param  properties  The set of task properties and their corresponding
843   *                     values to use for the task.  It must not be
844   *                     {@code null}.
845   *
846   * @throws  TaskException  If the provided set of properties cannot be used to
847   *                         create a valid collect support data task.
848   */
849  public CollectSupportDataTask(
850              @NotNull final Map<TaskProperty,List<Object>> properties)
851         throws TaskException
852  {
853    super(COLLECT_SUPPORT_DATA_TASK_CLASS, properties);
854
855    Boolean includeBinary = null;
856    Boolean includeExpensive = null;
857    Boolean includeReplicationState = null;
858    Boolean includeSource = null;
859    Boolean sequentialMode = null;
860    Boolean skipJFR = null;
861    CollectSupportDataSecurityLevel secLevel = null;
862    Date logEndDate = null;
863    Date logStartDate = null;
864    Integer logHeadSizeKB = null;
865    Integer logTailSizeKB = null;
866    Integer numJStacks = null;
867    Integer numReports = null;
868    Integer reportIntervalSecs = null;
869    Integer retainCount = null;
870    String commentStr = null;
871    String encPWFile = null;
872    String logDurationStr = null;
873    String outputPathStr = null;
874    String retainAge = null;
875
876    for (final Map.Entry<TaskProperty,List<Object>> entry :
877         properties.entrySet())
878    {
879      final TaskProperty p = entry.getKey();
880      final String attrName = StaticUtils.toLowerCase(p.getAttributeName());
881      final List<Object> values = entry.getValue();
882
883      if (attrName.equals(ATTR_INCLUDE_BINARY_FILES))
884      {
885        includeBinary = parseBoolean(p, values, includeBinary);
886      }
887      else if (attrName.equals(ATTR_INCLUDE_EXPENSIVE_DATA))
888      {
889        includeExpensive = parseBoolean(p, values, includeExpensive);
890      }
891      else if (attrName.equals(ATTR_INCLUDE_REPLICATION_STATE_DUMP))
892      {
893        includeReplicationState =
894             parseBoolean(p, values, includeReplicationState);
895      }
896      else if (attrName.equals(ATTR_INCLUDE_EXTENSION_SOURCE))
897      {
898        includeSource = parseBoolean(p, values, includeSource);
899      }
900      else if (attrName.equals(ATTR_USE_SEQUENTIAL_MODE))
901      {
902        sequentialMode = parseBoolean(p, values, sequentialMode);
903      }
904      else if (attrName.equals(ATTR_NO_JFR))
905      {
906        skipJFR = parseBoolean(p, values, skipJFR);
907      }
908      else if (attrName.equals(ATTR_SECURITY_LEVEL))
909      {
910        final String secLevelStr = parseString(p, values,
911             getSecurityLevelName(secLevel));
912        secLevel = CollectSupportDataSecurityLevel.forName(secLevelStr);
913      }
914      else if (attrName.equals(ATTR_JSTACK_COUNT))
915      {
916        numJStacks = parseLong(p, values,
917             getIntegerAsLong(numJStacks)).intValue();
918      }
919      else if (attrName.equals(ATTR_LOG_FILE_HEAD_COLLECTION_SIZE_KB))
920      {
921        logHeadSizeKB = parseLong(p, values,
922             getIntegerAsLong(logHeadSizeKB)).intValue();
923      }
924      else if (attrName.equals(ATTR_LOG_FILE_TAIL_COLLECTION_SIZE_KB))
925      {
926        logTailSizeKB = parseLong(p, values,
927             getIntegerAsLong(logTailSizeKB)).intValue();
928      }
929      else if (attrName.equals(ATTR_REPORT_COUNT))
930      {
931        numReports = parseLong(p, values,
932             getIntegerAsLong(numReports)).intValue();
933      }
934      else if (attrName.equals(ATTR_REPORT_INTERVAL_SECONDS))
935      {
936        reportIntervalSecs = parseLong(p, values,
937             getIntegerAsLong(reportIntervalSecs)).intValue();
938      }
939      else if (attrName.equals(ATTR_COMMENT))
940      {
941        commentStr = parseString(p, values, commentStr);
942      }
943      else if (attrName.equals(ATTR_ENCRYPTION_PASSPHRASE_FILE))
944      {
945        encPWFile = parseString(p, values, encPWFile);
946      }
947      else if (attrName.equals(ATTR_LOG_START_TIME))
948      {
949        logStartDate = parseDate(p, values, null);
950      }
951      else if (attrName.equals(ATTR_LOG_END_TIME))
952      {
953        logEndDate = parseDate(p, values, null);
954      }
955      else if (attrName.equals(ATTR_LOG_DURATION))
956      {
957        logDurationStr = parseString(p, values, logDurationStr);
958        try
959        {
960          DurationArgument.parseDuration(logDurationStr, TimeUnit.MILLISECONDS);
961        }
962        catch (final Exception e)
963        {
964          Debug.debugException(e);
965          throw new TaskException(
966               ERR_CSD_PROPERTY_INVALID_DURATION.get(logDurationStr,
967                    ATTR_LOG_DURATION),
968               e);
969        }
970      }
971      else if (attrName.equals(ATTR_OUTPUT_PATH))
972      {
973        outputPathStr = parseString(p, values, outputPathStr);
974      }
975      else if (attrName.equals(ATTR_RETAIN_PREVIOUS_ARCHIVE_COUNT))
976      {
977        retainCount = parseLong(p, values,
978             getIntegerAsLong(retainCount)).intValue();
979      }
980      else if (attrName.equals(ATTR_RETAIN_PREVIOUS_ARCHIVE_AGE))
981      {
982        retainAge = parseString(p, values, retainAge);
983        try
984        {
985          DurationArgument.parseDuration(retainAge, TimeUnit.MILLISECONDS);
986        }
987        catch (final Exception e)
988        {
989          Debug.debugException(e);
990          throw new TaskException(
991               ERR_CSD_PROPERTY_INVALID_DURATION.get(retainAge,
992                    ATTR_RETAIN_PREVIOUS_ARCHIVE_AGE),
993               e);
994        }
995      }
996    }
997
998    includeBinaryFiles = includeBinary;
999    includeExpensiveData = includeExpensive;
1000    includeReplicationStateDump = includeReplicationState;
1001    includeExtensionSource = includeSource;
1002    useSequentialMode = sequentialMode;
1003    noJFR = skipJFR;
1004    securityLevel = secLevel;
1005    jstackCount = numJStacks;
1006    logFileHeadCollectionSizeKB = logHeadSizeKB;
1007    logFileTailCollectionSizeKB = logTailSizeKB;
1008    reportCount = numReports;
1009    reportIntervalSeconds = reportIntervalSecs;
1010    retainPreviousSupportDataArchiveCount = retainCount;
1011    comment = commentStr;
1012    encryptionPassphraseFile = encPWFile;
1013    logStartTime = logStartDate;
1014    logEndTime = logEndDate;
1015    logDuration = logDurationStr;
1016    outputPath = outputPathStr;
1017    retainPreviousSupportDataArchiveAge = retainAge;
1018  }
1019
1020
1021
1022  /**
1023   * Retrieves the name of the provided security level.
1024   *
1025   * @param  securityLevel  The security level for which to retrieve the name.
1026   *                        It may be {@code null}.
1027   *
1028   * @return  The name of the provided security level, or {@code null} if the
1029   *          provided security level is {@code null}.
1030   */
1031  @Nullable()
1032  static String getSecurityLevelName(
1033       @Nullable final CollectSupportDataSecurityLevel securityLevel)
1034  {
1035    if (securityLevel == null)
1036    {
1037      return null;
1038    }
1039    else
1040    {
1041      return securityLevel.getName();
1042    }
1043  }
1044
1045
1046
1047  /**
1048   * Retrieves the value of the provided {@code Integer} object as a
1049   * {@code Long}.
1050   *
1051   * @param  i  The {@code Integer} value to convert to a {@code Long}.  It may
1052   *            be {@code null}.
1053   *
1054   * @return  The value of the provided {@code Integer} object as a
1055   *          {@code Long}, or {@code null} if the provided value was
1056   *          {@code null}.
1057   */
1058  @Nullable()
1059  static Long getIntegerAsLong(@Nullable final Integer i)
1060  {
1061    if (i == null)
1062    {
1063      return null;
1064    }
1065    else
1066    {
1067      return i.longValue();
1068    }
1069  }
1070
1071
1072
1073  /**
1074   * {@inheritDoc}
1075   */
1076  @Override()
1077  @NotNull()
1078  public String getTaskName()
1079  {
1080    return INFO_CSD_TASK_NAME.get();
1081  }
1082
1083
1084
1085  /**
1086   * {@inheritDoc}
1087   */
1088  @Override()
1089  @NotNull()
1090  public String getTaskDescription()
1091  {
1092    return INFO_CSD_TASK_DESCRIPTION.get();
1093  }
1094
1095
1096
1097  /**
1098   * Retrieves the path on the server filesystem to which the support data
1099   * archive should be written.
1100   *
1101   * @return  The path on the server filesystem to which the support data
1102   *          archive should be written, or {@code null} if no value has been
1103   *          specified for the property.
1104   */
1105  @Nullable()
1106  public String getOutputPath()
1107  {
1108    return outputPath;
1109  }
1110
1111
1112
1113  /**
1114   * Retrieves the path on the server filesystem to a file that contains the
1115   * passphrase to use to encrypt the support data archive.
1116   *
1117   * @return  The path on the server filesystem to a file that contains the
1118   *          passphrase to use to encrypt the support data archive, or
1119   *          {@code null} if no value has been specified for the property, and
1120   *          the support data archive should not be encrypted.
1121   */
1122  @Nullable()
1123  public String getEncryptionPassphraseFile()
1124  {
1125    return encryptionPassphraseFile;
1126  }
1127
1128
1129
1130  /**
1131   * Retrieves the value of a flag that indicates whether the support data
1132   * archive may include data that is potentially expensive to collect and
1133   * could affect the performance or responsiveness of the server.
1134   *
1135   * @return  The value of a flag that indicates whether the support data
1136   *          archive may include data that is potentially expensive to collect,
1137   *          or {@code null} if the property should not be specified when the
1138   *          task is created (in which case the server will use a default
1139   *          behavior of excluding expensive data).
1140   */
1141  @Nullable()
1142  public Boolean getIncludeExpensiveData()
1143  {
1144    return includeExpensiveData;
1145  }
1146
1147
1148
1149  /**
1150   * Retrieves the value of a flag that indicates whether the support data
1151   * archive may include a replication state dump, which may be several
1152   * megabytes in size.
1153   *
1154   * @return  The value of a flag that indicates whether the support data
1155   *          archive may include a replication state dump, or {@code null} if
1156   *          the property should not be specified when the task is created (in
1157   *          which case the server will use a default behavior of excluding the
1158   *          state dump).
1159   */
1160  @Nullable()
1161  public Boolean getIncludeReplicationStateDump()
1162  {
1163    return includeReplicationStateDump;
1164  }
1165
1166
1167
1168  /**
1169   * Retrieves the value of a flag that indicates whether the support data
1170   * archive may include binary files.
1171   *
1172   * @return  The value of a flag that indicates whether the support data
1173   *          archive may include binary files, or {@code null} if the property
1174   *          should not be specified when the task is created (in which case
1175   *          the server will use a default behavior of excluding binary files).
1176   */
1177  @Nullable()
1178  public Boolean getIncludeBinaryFiles()
1179  {
1180    return includeBinaryFiles;
1181  }
1182
1183
1184
1185  /**
1186   * Retrieves the value of a flag that indicates whether the support data
1187   * archive should include source code (if available) for any third-party
1188   * extensions installed in the server.
1189   *
1190   * @return  The value of a flag that indicates whether the support data
1191   *          archive should include source code (if available) for any
1192   *          third-party extensions installed in the server, or {@code null} if
1193   *          the property should not be specified when the task is created (in
1194   *          which case the server will use a default behavior of excluding
1195   *          extension source code).
1196   */
1197  @Nullable()
1198  public Boolean getIncludeExtensionSource()
1199  {
1200    return includeExtensionSource;
1201  }
1202
1203
1204
1205  /**
1206   * Retrieves the value of a flag that indicates whether the server should
1207   * collect items for the support data archive in sequential mode rather than
1208   * in parallel.  Collecting data in sequential mode may reduce the amount of
1209   * memory consumed during the collection process, but it will take longer to
1210   * complete.
1211   *
1212   * @return  The value of a flag that indicates whether the server should
1213   *          collect items for the support data archive in sequential mode
1214   *          rather than in parallel, or {@code null} if the property should
1215   *          not be specified when the task is created (in which case the
1216   *          server will default to capturing data in parallel).
1217   */
1218  @Nullable()
1219  public Boolean getUseSequentialMode()
1220  {
1221    return useSequentialMode;
1222  }
1223
1224
1225
1226  /**
1227   * Retrieves the value of a flag that indicates whether the server should skip
1228   * the collection of Java Flight Recorder (JFR) data.
1229   *
1230   * @return  The value of a flag that indicates whether the server should skip
1231   *          the collection of Java Flight Recorder data, or {@code null} if
1232   *          the property should not be specified when the task is created (in
1233   *          which case the server will use a default behavior of collecting
1234   *          JFR data if a recording is available).
1235   */
1236  @Nullable()
1237  public Boolean getNoJFR()
1238  {
1239    return noJFR;
1240  }
1241
1242
1243
1244  /**
1245   * Retrieves the security level that should be used to indicate which data
1246   * should be obscured, redacted, or omitted from the support data archive.
1247   *
1248   * @return  The security level that should be used when creating the support
1249   *          data archive, or {@code null} if the property should not be
1250   *          specified when the task is created (in which case the server will
1251   *          use a default security level).
1252   */
1253  @Nullable()
1254  public CollectSupportDataSecurityLevel getSecurityLevel()
1255  {
1256    return securityLevel;
1257  }
1258
1259
1260
1261  /**
1262   * Retrieves the number of intervals that should be captured from tools that
1263   * use interval-based sampling (e.g., vmstat, iostat, mpstat, etc.).
1264   *
1265   * @return  The number of intervals that should be captured from tools that
1266   *          use interval-based sampling, or {@code null} if the property
1267   *          should not be specified when the task is created (in which case
1268   *          the server will use a default report count).
1269   */
1270  @Nullable()
1271  public Integer getReportCount()
1272  {
1273    return reportCount;
1274  }
1275
1276
1277
1278  /**
1279   * Retrieves the interval duration in seconds that should be used for tools
1280   * that use interval-based sampling (e.g., vmstat, iostat, mpstat, etc.).
1281   *
1282   * @return  The interval duration in seconds that should be used for tools
1283   *          that use interval-based sampling, or {@code null} if the property
1284   *          should not be specified when the task is created (in which case
1285   *          the server will use a default report interval).
1286   */
1287  @Nullable()
1288  public Integer getReportIntervalSeconds()
1289  {
1290    return reportIntervalSeconds;
1291  }
1292
1293
1294
1295  /**
1296   * Retrieves the number of times that the jstack utility should be invoked to
1297   * obtain stack traces from all threads in the server.
1298   *
1299   * @return  The number of times that the jstack utility should be invoked to
1300   *          obtain stack traces from all threads in the server, or
1301   *          {@code null} if the property should not be specified when the task
1302   *          is created (in which case the server will use a default count).
1303   */
1304  @Nullable()
1305  public Integer getJStackCount()
1306  {
1307    return jstackCount;
1308  }
1309
1310
1311
1312  /**
1313   * Retrieves the start time for the range of log messages to include in the
1314   * support data archive.
1315   *
1316   * @return  The start time for the range of log messages to include in the
1317   *          support data archive, or {@code null} if no log start time has
1318   *          been specified.
1319   */
1320  @Nullable()
1321  public Date getLogStartTime()
1322  {
1323    return logStartTime;
1324  }
1325
1326
1327
1328  /**
1329   * Retrieves the end time for the range of log messages to include in the
1330   * support data archive.
1331   *
1332   * @return  The end time for the range of log messages to include in the
1333   *          support data archive, or {@code null} if no log end time has
1334   *          been specified.
1335   */
1336  @Nullable()
1337  public Date getLogEndTime()
1338  {
1339    return logEndTime;
1340  }
1341
1342
1343
1344  /**
1345   * Retrieves a string representation of the duration (up until the time that
1346   * the collect support data task is invoked) of log content that should be
1347   * included in the support data archive.
1348   *
1349   * @return  A string representation of the duration of log content that should
1350   *          be included in the support data archive, or {@code null} if the
1351   *          property should not be specified when the task is created (in
1352   *          which case the server will use a default behavior for selecting
1353   *          the amount of log content to include).
1354   */
1355  @Nullable()
1356  public String getLogDuration()
1357  {
1358    return logDuration;
1359  }
1360
1361
1362
1363  /**
1364   * Retrieves the amount of data in kilobytes to capture from the beginning of
1365   * each log file that should be included in the support data archive.
1366   *
1367   * @return  The amount of data in kilobytes to capture from the beginning of
1368   *          each log file that should be included in the support data archive,
1369   *          or {@code null} if the property should not be specified when the
1370   *          task is created (in which case the server will determine an
1371   *          appropriate amount of log content to include).
1372   */
1373  @Nullable()
1374  public Integer getLogFileHeadCollectionSizeKB()
1375  {
1376    return logFileHeadCollectionSizeKB;
1377  }
1378
1379
1380
1381  /**
1382   * Retrieves the amount of data in kilobytes to capture from the end of each
1383   * log file that should be included in the support data archive.
1384   *
1385   * @return  The amount of data in kilobytes to capture from the end of each
1386   *          log file that should be included in the support data archive, or
1387   *          {@code null} if the property should not be specified when the task
1388   *          is created (in which case the server will determine an
1389   *          appropriate amount of log content to include).
1390   */
1391  @Nullable()
1392  public Integer getLogFileTailCollectionSizeKB()
1393  {
1394    return logFileTailCollectionSizeKB;
1395  }
1396
1397
1398
1399  /**
1400   * Retrieves a parsed value of the log duration in milliseconds.
1401   *
1402   * @return  A parsed value of the log duration in milliseconds or {@code null}
1403   *          if no log duration is set.
1404   *
1405   * @throws  TaskException  If the log duration value cannot be parsed as a
1406   *                         valid duration.
1407   */
1408  @Nullable()
1409  public Long getLogDurationMillis()
1410         throws TaskException
1411  {
1412    if (logDuration == null)
1413    {
1414      return null;
1415    }
1416
1417    try
1418    {
1419      return DurationArgument.parseDuration(logDuration, TimeUnit.MILLISECONDS);
1420    }
1421    catch (final ArgumentException e)
1422    {
1423      Debug.debugException(e);
1424      throw new TaskException(e.getMessage(), e);
1425    }
1426  }
1427
1428
1429
1430  /**
1431   * Retrieves an additional comment that should be included in the support data
1432   * archive.
1433   *
1434   * @return  An additional comment that should be included in the support data
1435   *          archive, or {@code null} if no comment should be included.
1436   */
1437  @Nullable()
1438  public String getComment()
1439  {
1440    return comment;
1441  }
1442
1443
1444
1445  /**
1446   * Retrieves the minimum number of existing support data archives that should
1447   * be retained.
1448   *
1449   * @return  The minimum number of existing support data archives that should
1450   *          be retained, or {@code null} if there is no minimum retain count.
1451   */
1452  @Nullable()
1453  public Integer getRetainPreviousSupportDataArchiveCount()
1454  {
1455    return retainPreviousSupportDataArchiveCount;
1456  }
1457
1458
1459
1460  /**
1461   * Retrieves the minimum age of existing support data archives that should be
1462   * retained.
1463   *
1464   * @return  The minimum age of existing support data archives that should
1465   *          be retained, or {@code null} if there is no minimum retain age.
1466   */
1467  @Nullable()
1468  public String getRetainPreviousSupportDataArchiveAge()
1469  {
1470    return retainPreviousSupportDataArchiveAge;
1471  }
1472
1473
1474
1475  /**
1476   * Retrieves a parsed value of the retain previous support data archive age in
1477   * milliseconds.
1478   *
1479   * @return  A parsed value of the retain previous support data archive age in
1480   *          milliseconds or {@code null} if no retain age is set.
1481   *
1482   * @throws  TaskException  If the retain age value cannot be parsed as a valid
1483   *                         duration.
1484   */
1485  @Nullable()
1486  public Long getRetainPreviousSupportDataArchiveAgeMillis()
1487         throws TaskException
1488  {
1489    if (retainPreviousSupportDataArchiveAge == null)
1490    {
1491      return null;
1492    }
1493
1494    try
1495    {
1496      return DurationArgument.parseDuration(
1497           retainPreviousSupportDataArchiveAge, TimeUnit.MILLISECONDS);
1498    }
1499    catch (final ArgumentException e)
1500    {
1501      Debug.debugException(e);
1502      throw new TaskException(e.getMessage(), e);
1503    }
1504  }
1505
1506
1507
1508  /**
1509   * {@inheritDoc}
1510   */
1511  @Override()
1512  @NotNull()
1513  protected List<String> getAdditionalObjectClasses()
1514  {
1515    return Collections.singletonList(OC_COLLECT_SUPPORT_DATA_TASK);
1516  }
1517
1518
1519
1520  /**
1521   * {@inheritDoc}
1522   */
1523  @Override()
1524  @NotNull()
1525  protected List<Attribute> getAdditionalAttributes()
1526  {
1527    final List<Attribute> attrList = new ArrayList<>(15);
1528
1529    if (outputPath != null)
1530    {
1531      attrList.add(new Attribute(ATTR_OUTPUT_PATH, outputPath));
1532    }
1533
1534    if (encryptionPassphraseFile != null)
1535    {
1536      attrList.add(new Attribute(ATTR_ENCRYPTION_PASSPHRASE_FILE,
1537           encryptionPassphraseFile));
1538    }
1539
1540    if (includeExpensiveData != null)
1541    {
1542      attrList.add(new Attribute(ATTR_INCLUDE_EXPENSIVE_DATA,
1543           includeExpensiveData ? "TRUE" : "FALSE"));
1544    }
1545
1546    if (includeReplicationStateDump != null)
1547    {
1548      attrList.add(new Attribute(ATTR_INCLUDE_REPLICATION_STATE_DUMP,
1549           includeReplicationStateDump ? "TRUE" : "FALSE"));
1550    }
1551
1552    if (includeBinaryFiles != null)
1553    {
1554      attrList.add(new Attribute(ATTR_INCLUDE_BINARY_FILES,
1555           includeBinaryFiles ? "TRUE" : "FALSE"));
1556    }
1557
1558    if (includeExtensionSource != null)
1559    {
1560      attrList.add(new Attribute(ATTR_INCLUDE_EXTENSION_SOURCE,
1561           includeExtensionSource ? "TRUE" : "FALSE"));
1562    }
1563
1564    if (useSequentialMode != null)
1565    {
1566      attrList.add(new Attribute(ATTR_USE_SEQUENTIAL_MODE,
1567           useSequentialMode ? "TRUE" : "FALSE"));
1568    }
1569
1570    if (noJFR != null)
1571    {
1572      attrList.add(new Attribute(ATTR_NO_JFR, noJFR ? "TRUE" : "FALSE"));
1573    }
1574
1575    if (securityLevel != null)
1576    {
1577      attrList.add(new Attribute(ATTR_SECURITY_LEVEL, securityLevel.getName()));
1578    }
1579
1580    if (jstackCount != null)
1581    {
1582      attrList.add(new Attribute(ATTR_JSTACK_COUNT,
1583           String.valueOf(jstackCount)));
1584    }
1585
1586    if (reportCount != null)
1587    {
1588      attrList.add(new Attribute(ATTR_REPORT_COUNT,
1589           String.valueOf(reportCount)));
1590    }
1591
1592    if (reportIntervalSeconds != null)
1593    {
1594      attrList.add(new Attribute(ATTR_REPORT_INTERVAL_SECONDS,
1595           String.valueOf(reportIntervalSeconds)));
1596    }
1597
1598    if (logStartTime != null)
1599    {
1600      attrList.add(new Attribute(ATTR_LOG_START_TIME,
1601              StaticUtils.encodeGeneralizedTime(logStartTime)));
1602    }
1603
1604    if (logEndTime != null)
1605    {
1606      attrList.add(new Attribute(ATTR_LOG_END_TIME,
1607              StaticUtils.encodeGeneralizedTime(logEndTime)));
1608    }
1609
1610    if (logDuration != null)
1611    {
1612      attrList.add(new Attribute(ATTR_LOG_DURATION, logDuration));
1613    }
1614
1615    if (logFileHeadCollectionSizeKB != null)
1616    {
1617      attrList.add(new Attribute(ATTR_LOG_FILE_HEAD_COLLECTION_SIZE_KB,
1618           String.valueOf(logFileHeadCollectionSizeKB)));
1619    }
1620
1621    if (logFileTailCollectionSizeKB != null)
1622    {
1623      attrList.add(new Attribute(ATTR_LOG_FILE_TAIL_COLLECTION_SIZE_KB,
1624           String.valueOf(logFileTailCollectionSizeKB)));
1625    }
1626
1627    if (comment != null)
1628    {
1629      attrList.add(new Attribute(ATTR_COMMENT, comment));
1630    }
1631
1632    if (retainPreviousSupportDataArchiveCount != null)
1633    {
1634      attrList.add(new Attribute(ATTR_RETAIN_PREVIOUS_ARCHIVE_COUNT,
1635           String.valueOf(retainPreviousSupportDataArchiveCount)));
1636    }
1637
1638    if (retainPreviousSupportDataArchiveAge != null)
1639    {
1640      attrList.add(new Attribute(ATTR_RETAIN_PREVIOUS_ARCHIVE_AGE,
1641           retainPreviousSupportDataArchiveAge));
1642    }
1643
1644    return attrList;
1645  }
1646
1647
1648
1649  /**
1650   * {@inheritDoc}
1651   */
1652  @Override()
1653  @NotNull()
1654  public List<TaskProperty> getTaskSpecificProperties()
1655  {
1656    return Collections.unmodifiableList(Arrays.asList(
1657         PROPERTY_OUTPUT_PATH,
1658         PROPERTY_ENCRYPTION_PASSPHRASE_FILE,
1659         PROPERTY_INCLUDE_EXPENSIVE_DATA,
1660         PROPERTY_INCLUDE_REPLICATION_STATE_DUMP,
1661         PROPERTY_INCLUDE_BINARY_FILES,
1662         PROPERTY_INCLUDE_EXTENSION_SOURCE,
1663         PROPERTY_USE_SEQUENTIAL_MODE,
1664         PROPERTY_NO_JFR,
1665         PROPERTY_SECURITY_LEVEL,
1666         PROPERTY_JSTACK_COUNT,
1667         PROPERTY_REPORT_COUNT,
1668         PROPERTY_REPORT_INTERVAL_SECONDS,
1669         PROPERTY_LOG_START_TIME,
1670         PROPERTY_LOG_END_TIME,
1671         PROPERTY_LOG_DURATION,
1672         PROPERTY_LOG_FILE_HEAD_COLLECTION_SIZE_KB,
1673         PROPERTY_LOG_FILE_TAIL_COLLECTION_SIZE_KB,
1674         PROPERTY_COMMENT,
1675         PROPERTY_RETAIN_PREVIOUS_ARCHIVE_COUNT,
1676         PROPERTY_RETAIN_PREVIOUS_ARCHIVE_AGE));
1677  }
1678
1679
1680
1681  /**
1682   * {@inheritDoc}
1683   */
1684  @Override()
1685  @NotNull()
1686  public Map<TaskProperty,List<Object>> getTaskPropertyValues()
1687  {
1688    final Map<TaskProperty,List<Object>> props =
1689         new LinkedHashMap<>(StaticUtils.computeMapCapacity(20));
1690
1691    if (outputPath != null)
1692    {
1693      props.put(PROPERTY_OUTPUT_PATH,
1694           Collections.<Object>singletonList(outputPath));
1695    }
1696
1697    if (encryptionPassphraseFile != null)
1698    {
1699      props.put(PROPERTY_ENCRYPTION_PASSPHRASE_FILE,
1700           Collections.<Object>singletonList(encryptionPassphraseFile));
1701    }
1702
1703    if (includeExpensiveData != null)
1704    {
1705      props.put(PROPERTY_INCLUDE_EXPENSIVE_DATA,
1706           Collections.<Object>singletonList(includeExpensiveData));
1707    }
1708
1709    if (includeReplicationStateDump != null)
1710    {
1711      props.put(PROPERTY_INCLUDE_REPLICATION_STATE_DUMP,
1712           Collections.<Object>singletonList(includeReplicationStateDump));
1713    }
1714
1715    if (includeBinaryFiles != null)
1716    {
1717      props.put(PROPERTY_INCLUDE_BINARY_FILES,
1718           Collections.<Object>singletonList(includeBinaryFiles));
1719    }
1720
1721    if (includeExtensionSource != null)
1722    {
1723      props.put(PROPERTY_INCLUDE_EXTENSION_SOURCE,
1724           Collections.<Object>singletonList(includeExtensionSource));
1725    }
1726
1727    if (useSequentialMode != null)
1728    {
1729      props.put(PROPERTY_USE_SEQUENTIAL_MODE,
1730           Collections.<Object>singletonList(useSequentialMode));
1731    }
1732
1733    if (noJFR != null)
1734    {
1735      props.put(PROPERTY_NO_JFR, Collections.<Object>singletonList(noJFR));
1736    }
1737
1738    if (securityLevel != null)
1739    {
1740      props.put(PROPERTY_SECURITY_LEVEL,
1741           Collections.<Object>singletonList(securityLevel.getName()));
1742    }
1743
1744    if (jstackCount != null)
1745    {
1746      props.put(PROPERTY_JSTACK_COUNT,
1747           Collections.<Object>singletonList(jstackCount.longValue()));
1748    }
1749
1750    if (reportCount != null)
1751    {
1752      props.put(PROPERTY_REPORT_COUNT,
1753           Collections.<Object>singletonList(reportCount.longValue()));
1754    }
1755
1756    if (reportIntervalSeconds != null)
1757    {
1758      props.put(PROPERTY_REPORT_INTERVAL_SECONDS,
1759           Collections.<Object>singletonList(
1760                reportIntervalSeconds.longValue()));
1761    }
1762
1763    if (logStartTime != null)
1764    {
1765      props.put(PROPERTY_LOG_START_TIME,
1766              Collections.<Object>singletonList(logStartTime));
1767    }
1768
1769    if (logEndTime != null)
1770    {
1771      props.put(PROPERTY_LOG_END_TIME,
1772              Collections.<Object>singletonList(logEndTime));
1773    }
1774
1775    if (logDuration != null)
1776    {
1777      props.put(PROPERTY_LOG_DURATION,
1778           Collections.<Object>singletonList(logDuration));
1779    }
1780
1781    if (logFileHeadCollectionSizeKB != null)
1782    {
1783      props.put(PROPERTY_LOG_FILE_HEAD_COLLECTION_SIZE_KB,
1784           Collections.<Object>singletonList(
1785                logFileHeadCollectionSizeKB.longValue()));
1786    }
1787
1788    if (logFileTailCollectionSizeKB != null)
1789    {
1790      props.put(PROPERTY_LOG_FILE_TAIL_COLLECTION_SIZE_KB,
1791           Collections.<Object>singletonList(
1792                logFileTailCollectionSizeKB.longValue()));
1793    }
1794
1795    if (comment != null)
1796    {
1797      props.put(PROPERTY_COMMENT,
1798           Collections.<Object>singletonList(comment));
1799    }
1800
1801    if (retainPreviousSupportDataArchiveCount != null)
1802    {
1803      props.put(PROPERTY_RETAIN_PREVIOUS_ARCHIVE_COUNT,
1804           Collections.<Object>singletonList(
1805                retainPreviousSupportDataArchiveCount.longValue()));
1806    }
1807
1808    if (retainPreviousSupportDataArchiveAge != null)
1809    {
1810      props.put(PROPERTY_RETAIN_PREVIOUS_ARCHIVE_AGE,
1811           Collections.<Object>singletonList(
1812                retainPreviousSupportDataArchiveAge));
1813    }
1814
1815    props.putAll(super.getTaskPropertyValues());
1816    return Collections.unmodifiableMap(props);
1817  }
1818}