From 72c939b50428a2aa1f924a04ecdedee93e1383f4 Mon Sep 17 00:00:00 2001
From: kenneth_suter <kenneth_suter@localhost>
Date: Thu, 13 Sep 2007 21:14:20 +0000
Subject: [PATCH] Introduces a utility 'manage-tasks' for monitoring and some management of tasks called 'manage-tasks'. It can be used in either one-time or menu-driven execution mode to print a summary of task information, print verbose information about a particular task, or cancel a running or pending task.
---
opends/src/server/org/opends/server/tools/tasks/TaskEntry.java | 482 ++++++++
opends/src/server/org/opends/server/backends/task/TaskState.java | 40
opends/src/server/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java | 20
opends/src/server/org/opends/server/tools/tasks/TaskClientException.java | 84 +
opends/src/server/org/opends/server/tasks/InitializeTask.java | 7
opends/src/server/org/opends/server/util/args/LDAPConnectionArgumentParser.java | 346 ++---
opends/src/server/org/opends/server/backends/task/TaskScheduler.java | 11
opends/src/server/org/opends/server/tools/ManageTasks.java | 926 ++++++++++++++++
opends/src/server/org/opends/server/tasks/RebuildTask.java | 8
opends/src/server/org/opends/server/util/args/ArgumentParser.java | 24
opends/src/server/org/opends/server/tasks/DisconnectClientTask.java | 7
opends/resource/bin/manage-tasks.bat | 33
opends/src/server/org/opends/server/tasks/RestoreTask.java | 34
opends/src/server/org/opends/server/tasks/InitializeTargetTask.java | 8
opends/src/server/org/opends/server/tasks/ImportTask.java | 90 +
opends/src/server/org/opends/server/tasks/LeaveLockdownModeTask.java | 8
opends/src/server/org/opends/server/util/StaticUtils.java | 195 +-
opends/src/server/org/opends/server/tools/tasks/TaskScheduleInformation.java | 2
opends/src/server/org/opends/server/backends/task/Task.java | 42
opends/src/server/org/opends/server/tasks/BackupTask.java | 62 +
opends/src/messages/messages/tools.properties | 66 +
/dev/null | 211 ---
opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java | 7
opends/src/server/org/opends/server/tasks/ExportTask.java | 74 +
opends/src/server/org/opends/server/tasks/ShutdownTask.java | 6
opends/resource/bin/manage-tasks | 37
opends/src/server/org/opends/server/backends/task/FailedDependencyAction.java | 23
opends/src/server/org/opends/server/tools/tasks/TaskTool.java | 34
opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/DummyTask.java | 7
opends/src/messages/messages/task.properties | 70 +
opends/src/server/org/opends/server/tools/tasks/TaskClient.java | 378 ++++++
opends/src/server/org/opends/server/util/cli/ConsoleApplication.java | 10
opends/src/server/org/opends/server/tasks/EnterLockdownModeTask.java | 8
opends/src/server/org/opends/server/tasks/SetGenerationIdTask.java | 8
opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliArgs.java | 14
35 files changed, 2,846 insertions(+), 536 deletions(-)
diff --git a/opends/resource/bin/manage-tasks b/opends/resource/bin/manage-tasks
new file mode 100644
index 0000000..dc53cf2
--- /dev/null
+++ b/opends/resource/bin/manage-tasks
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at
+# trunk/opends/resource/legal-notices/OpenDS.LICENSE
+# or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at
+# trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+# add the following below this CDDL HEADER, with the fields enclosed
+# by brackets "[]" replaced with your own identifying information:
+# Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Portions Copyright 2006-2007 Sun Microsystems, Inc.
+
+
+# This script may be used to manage tasks in the Directory Server.
+OPENDS_INVOKE_CLASS="org.opends.server.tools.ManageTasks"
+export OPENDS_INVOKE_CLASS
+
+SCRIPT_NAME_ARG="-Dorg.opends.server.scriptName=manage-tasks"
+export SCRIPT_NAME_ARG
+
+SCRIPT_DIR=`dirname "${0}"`
+"${SCRIPT_DIR}/../lib/_client-script.sh" "${@}"
diff --git a/opends/resource/bin/manage-tasks.bat b/opends/resource/bin/manage-tasks.bat
new file mode 100644
index 0000000..7edaaf1
--- /dev/null
+++ b/opends/resource/bin/manage-tasks.bat
@@ -0,0 +1,33 @@
+
+@echo off
+rem CDDL HEADER START
+rem
+rem The contents of this file are subject to the terms of the
+rem Common Development and Distribution License, Version 1.0 only
+rem (the "License"). You may not use this file except in compliance
+rem with the License.
+rem
+rem You can obtain a copy of the license at
+rem trunk/opends/resource/legal-notices/OpenDS.LICENSE
+rem or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+rem See the License for the specific language governing permissions
+rem and limitations under the License.
+rem
+rem When distributing Covered Code, include this CDDL HEADER in each
+rem file and include the License file at
+rem trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+rem add the following below this CDDL HEADER, with the fields enclosed
+rem by brackets "[]" replaced with your own identifying information:
+rem Portions Copyright [yyyy] [name of copyright owner]
+rem
+rem CDDL HEADER END
+rem
+rem
+rem Portions Copyright 2006-2007 Sun Microsystems, Inc.
+
+setlocal
+
+set OPENDS_INVOKE_CLASS="org.opends.server.tools.ManageTasks"
+set SCRIPT_NAME_ARG="-Dorg.opends.server.scriptName=manage-tasks"
+for %%i in (%~sf0) do call "%%~dPsi\..\lib\_client-script.bat" %*
+
diff --git a/opends/src/messages/messages/task.properties b/opends/src/messages/messages/task.properties
index dcbcaea..a751b3a 100644
--- a/opends/src/messages/messages/task.properties
+++ b/opends/src/messages/messages/task.properties
@@ -116,3 +116,73 @@
connection with connection ID %s
INFO_TASK_DISCONNECT_MESSAGE_31=An administrator has terminated this client \
connection
+INFO_TASK_ADD_SCHEMA_FILE_NAME_32=Add Schema File
+INFO_TASK_BACKUP_NAME_33=Backup
+INFO_TASK_DISCONNECT_CLIENT_NAME_34=Disconnect Client
+INFO_TASK_ENTER_LOCKDOWN_MODE_NAME_35=Lockdown
+INFO_TASK_EXPORT_NAME_36=Export
+INFO_TASK_IMPORT_NAME_37=Import
+INFO_TASK_INITIALIZE_TARGET_NAME_38=Initialize Backend
+INFO_TASK_INITIALIZE_NAME_39=Initialize From Replica
+INFO_TASK_LEAVE_LOCKDOWN_MODE_NAME_40=Leave Lockdown
+INFO_TASK_REBUILD_NAME_41=Rebuild Index
+INFO_TASK_RESTORE_NAME_42=Restore
+INFO_TASK_SET_GENERATION_ID_NAME_43=Set Generation ID
+INFO_TASK_SHUTDOWN_NAME_44=Shutdown
+INFO_TASK_STATE_UNSCHEDULED_45=Unscheduled
+INFO_TASK_STATE_DISABLED_46=Disabled
+INFO_TASK_STATE_WAITING_ON_START_TIME_47=Waiting on start time
+INFO_TASK_STATE_WAITING_ON_DEPENDENCY_48=Waiting on dependency
+INFO_TASK_STATE_RUNNING_49=Running
+INFO_TASK_STATE_COMPLETED_SUCCESSFULLY_50=Completed successfully
+INFO_TASK_STATE_COMPLETED_WITH_ERRORS_51=Completed with errors
+INFO_TASK_STATE_STOPPED_BY_SHUTDOWN_52=Stopped by shutdown
+INFO_TASK_STATE_STOPPED_BY_ERROR_53=Stopped by error
+INFO_TASK_STATE_STOPPED_BY_ADMINISTRATOR_54=Stopped by administrator
+INFO_TASK_STATE_CANCELED_BEFORE_STARTING_55=Canceled before starting
+INFO_BACKUP_ARG_BACKUPALL_56=Backup All
+INFO_BACKUP_ARG_COMPRESS_57=Compress
+INFO_BACKUP_ARG_ENCRYPT_58=Encrypt
+INFO_BACKUP_ARG_HASH_59=Hash
+INFO_BACKUP_ARG_INCREMENTAL_60=Incremental
+INFO_BACKUP_ARG_SIGN_HASH_61=Sign Hash
+INFO_BACKUP_ARG_BACKEND_IDS_62=Backend ID(s)
+INFO_BACKUP_ARG_BACKUP_DIR_63=Backup Directory
+INFO_BACKUP_ARG_BACKUP_ID_64=Backup ID
+INFO_BACKUP_ARG_INC_BASE_ID_65=Incremental Base ID
+INFO_EXPORT_ARG_LDIF_FILE_66=LDIF File
+INFO_EXPORT_ARG_BACKEND_ID_67=Backend ID
+INFO_EXPORT_ARG_APPEND_TO_LDIF_68=Append To LDIF
+INFO_EXPORT_ARG_COMPRESS_LDIF_69=Comress LDIF
+INFO_EXPORT_ARG_ENCRYPT_LDIF_70=Encrypt LDIF
+INFO_EXPORT_ARG_SIGN_HASH_71=Sign Hash
+INFO_EXPORT_ARG_INCL_ATTR_72=Include Attribute
+INFO_EXPORT_ARG_EXCL_ATTR_73=Exclude Attribute
+INFO_EXPORT_ARG_INCL_FILTER_74=Include Filter
+INFO_EXPORT_ARG_EXCL_FILTER_75=Exclude Filter
+INFO_EXPORT_ARG_INCL_BRANCH_76=Include Branch
+INFO_EXPORT_ARG_EXCL_BRANCH_77=Exclude Branch
+INFO_EXPORT_ARG_WRAP_COLUMN_78=Wrap Column
+INFO_RESTORE_ARG_BACKUP_DIR_79=Backup Directory
+INFO_RESTORE_ARG_BACKUP_ID_80=Backup ID
+INFO_RESTORE_ARG_VERIFY_ONLY_81=Verify Only
+INFO_IMPORT_ARG_LDIF_FILE_82=LDIF File
+INFO_IMPORT_ARG_APPEND_83=Append
+INFO_IMPORT_ARG_REPLACE_EXISTING_84=Replace Existing
+INFO_IMPORT_ARG_BACKEND_ID_85=Backend ID
+INFO_IMPORT_ARG_INCL_ATTR_86=Include Attribute
+INFO_IMPORT_ARG_EXCL_ATTR_87=Exclude Attribute
+INFO_IMPORT_ARG_INCL_FILTER_88=Include Filter
+INFO_IMPORT_ARG_EXCL_FILTER_89=Exclude Filter
+INFO_IMPORT_ARG_INCL_BRANCH_90=Include Branch
+INFO_IMPORT_ARG_EXCL_BRANCH_91=Exclude Branch
+INFO_IMPORT_ARG_REJECT_FILE_92=Reject File
+INFO_IMPORT_ARG_SKIP_FILE_93=Skip File
+INFO_IMPORT_ARG_OVERWRITE_94=Overwrite
+INFO_IMPORT_ARG_SKIP_SCHEMA_VALIDATION_95=Skip Schema Validation
+INFO_IMPORT_ARG_IS_COMPRESSED_96=Is Compressed
+INFO_IMPORT_ARG_IS_ENCRYPTED_97=Is Encrypted
+INFO_IMPORT_ARG_CLEAR_BACKEND_98=Clear Backend
+INFO_FAILED_DEPENDENCY_ACTION_PROCESS_99=Process
+INFO_FAILED_DEPENDENCY_ACTION_CANCEL_100=Cancel
+INFO_FAILED_DEPENDENCY_ACTION_DISABLE_101=Disable
\ No newline at end of file
diff --git a/opends/src/messages/messages/tools.properties b/opends/src/messages/messages/tools.properties
index fc8c231..7b8efad 100644
--- a/opends/src/messages/messages/tools.properties
+++ b/opends/src/messages/messages/tools.properties
@@ -1895,13 +1895,13 @@
connection to the Directory Server was closed while waiting for a response to \
the shutdown request. This likely means that the server has started the \
shutdown process
-SEVERE_ERR_TASK_CLIENT_IO_ERROR_1316=ERROR: An I/O error occurred while \
+SEVERE_ERR_TASK_TOOL_IO_ERROR_1316=ERROR: An I/O error occurred while \
attempting to communicate with the Directory Server: %s
-SEVERE_ERR_TASK_CLIENT_DECODE_ERROR_1317=ERROR: An error occurred while \
+SEVERE_ERR_TASK_TOOL_DECODE_ERROR_1317=ERROR: An error occurred while \
trying to decode the response from the server: %s
SEVERE_ERR_TASK_CLIENT_INVALID_RESPONSE_TYPE_1318=ERROR: Expected an add \
response message but got a %s message instead
-INFO_TASK_CLIENT_TASK_SCHEDULED_1319=Scheduled task %s
+INFO_TASK_TOOL_TASK_SCHEDULED_1319=Scheduled task %s
SEVERE_ERR_LDAP_CONN_INCOMPATIBLE_ARGS_1320=ERROR: argument %s is \
incompatible with use of this tool to interact with the directory as a client
SEVERE_ERR_CREATERC_ONLY_RUNS_ON_UNIX_1321=This tool may only be used on \
@@ -2080,4 +2080,62 @@
or Start TLS (using option %s)
SEVERE_ERR_UPGRADE_INCOMPATIBLE_ARGS_1411=The argument '%s' is incompatible \
with '%s'
-
+INFO_TASKINFO_TOOL_DESCRIPTION_1412=This utility can be used to obtain a list \
+ of tasks scheduled to run within the Directory Server as well as information \
+ about individual tasks
+INFO_TASKINFO_SUMMARY_ARG_DESCRIPTION_1413=Print a summary of tasks
+INFO_TASKINFO_TASK_ARG_DESCRIPTION_1414=Specifies the ID of a particular task \
+ about which this tool will display information
+INFO_TASKINFO_CMD_REFRESH_1415=refresh
+INFO_TASKINFO_CMD_CANCEL_1416=cancel task
+INFO_TASKINFO_CMD_VIEW_LOGS_1417=view logs
+INFO_TASKINFO_MENU_PROMPT_1418=Enter a menu item or task number
+INFO_TASKINFO_CMD_CANCEL_NUMBER_PROMPT_1419=Enter the number of a task to \
+ cancel [%d]
+INFO_TASKINFO_MENU_1420=Menu
+MILD_ERR_TASKINFO_INVALID_TASK_NUMBER_1421=Task number must be between 1 and \
+ %d
+MILD_ERR_TASKINFO_INVALID_MENU_KEY_1422=Invalid menu item or task number '%s'
+INFO_TASKINFO_FIELD_ID_1423=ID
+INFO_TASKINFO_FIELD_TYPE_1424=Type
+INFO_TASKINFO_FIELD_STATUS_1425=Status
+INFO_TASKINFO_FIELD_SCHEDULED_START_1426=Scheduled Start Time
+INFO_TASKINFO_FIELD_ACTUAL_START_1427=Actual Start Time
+INFO_TASKINFO_FIELD_COMPLETION_TIME_1428=Completion Time
+INFO_TASKINFO_FIELD_DEPENDENCY_1429=Dependencies
+INFO_TASKINFO_FIELD_FAILED_DEPENDENCY_ACTION_1430=Failed Dependency Action
+INFO_TASKINFO_FIELD_LOG_1431=Log Message(s)
+INFO_TASKINFO_FIELD_LAST_LOG_1432=Last Log Message
+INFO_TASKINFO_FIELD_NOTIFY_ON_COMPLETION_1433=Email Upon Completion
+INFO_TASKINFO_FIELD_NOTIFY_ON_ERROR_1434=Email Upon Error
+INFO_TASKINFO_CMD_CANCEL_SUCCESS_1435=Task %s canceled
+SEVERE_ERR_TASKINFO_CMD_CANCEL_ERROR_1436=Error canceling task %s: %s
+SEVERE_ERR_TASKINFO_RETRIEVING_TASK_ENTRY_1437=Error retrieving task entry \
+ %s: %s
+MILD_ERR_TASKINFO_UNKNOWN_TASK_ENTRY_1438=There are no tasks with ID %s
+INFO_TASKINFO_DETAILS_1439=Task Details
+INFO_TASKINFO_OPTIONS_1440=%s Options
+INFO_TASKINFO_NO_TASKS_1441=No tasks exist
+INFO_TASKINFO_NONE_1442=None
+INFO_TASKINFO_NONE_SPECIFIED_1443=None Specified
+INFO_TASKINFO_IMMEDIATE_EXECUTION_1444=Immediate execution
+INFO_TASKINFO_LDAP_EXCEPTION_1445=Error connecting to the directory server: \
+ '%s'. Verify that the connection options are correct and that the server is \
+ running
+SEVERE_ERR_INCOMPATIBLE_ARGUMENTS_1446=Options '%s' and '%s' are incompatible \
+ with each other and cannot be used together
+INFO_TASKINFO_TASK_ARG_CANCEL_1447=Specifies the ID of a particular task \
+ to cancel
+SEVERE_ERR_TASKINFO_CANCELING_TASK_1448=Error canceling task '%s': %s
+SEVERE_ERR_TASKINFO_ACCESSING_LOGS_1449=Error accessing logs for task '%s': %s
+SEVERE_ERR_TASKINFO_NOT_CANCELABLE_TASK_INDEX_1450=Task at index %d is not \
+ cancelable
+SEVERE_ERR_TASKINFO_NOT_CANCELABLE_TASK_1451=Task %s has finished and cannot \
+ be canceled
+INFO_TASKINFO_NO_CANCELABLE_TASKS_1452=There are currently no cancelable tasks
+SEVERE_ERR_TASK_CLIENT_UNKNOWN_TASK_1453=There are no tasks defined with ID '%s'
+SEVERE_ERR_TASK_CLIENT_UNCANCELABLE_TASK_1454=Task '%s' is has finished and \
+ cannot be canceled
+SEVERE_ERR_TASK_CLIENT_TASK_STATE_UNKNOWN_1455=State for task '%s' cannot be \
+ determined
+SEVERE_ERR_XXX_1455=xxx
\ No newline at end of file
diff --git a/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliArgs.java b/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliArgs.java
index 6215e12..fe1dcb5 100644
--- a/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliArgs.java
+++ b/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliArgs.java
@@ -149,6 +149,12 @@
*/
public BooleanArgument useStartTLSArg = null;
+ /**
+ * Argument indicating a SASL option.
+ */
+ public StringArgument saslOptionArg = null;
+
+
// the trust manager.
private ApplicationTrustManager trustManager;
@@ -391,6 +397,14 @@
INFO_DESCRIPTION_BINDPASSWORDFILE.get());
set.add(bindPasswordFileArg);
+ saslOptionArg = new StringArgument(
+ "sasloption", OPTION_SHORT_SASLOPTION,
+ OPTION_LONG_SASLOPTION, false,
+ true, true,
+ OPTION_VALUE_SASLOPTION, null, null,
+ INFO_LDAP_CONN_DESCRIPTION_SASLOPTIONS.get());
+ set.add(saslOptionArg);
+
trustAllArg = new BooleanArgument("trustAll", OPTION_SHORT_TRUSTALL,
OPTION_LONG_TRUSTALL, INFO_DESCRIPTION_TRUSTALL.get());
set.add(trustAllArg);
diff --git a/opends/src/server/org/opends/server/backends/task/FailedDependencyAction.java b/opends/src/server/org/opends/server/backends/task/FailedDependencyAction.java
index aea4c64..68b38d3 100644
--- a/opends/src/server/org/opends/server/backends/task/FailedDependencyAction.java
+++ b/opends/src/server/org/opends/server/backends/task/FailedDependencyAction.java
@@ -26,6 +26,8 @@
*/
package org.opends.server.backends.task;
+import org.opends.messages.Message;
+import org.opends.messages.TaskMessages;
/**
@@ -39,14 +41,14 @@
* The action that indicates that the dependent task should be processed
* anyway.
*/
- PROCESS,
+ PROCESS(TaskMessages.INFO_FAILED_DEPENDENCY_ACTION_PROCESS.get()),
/**
* The action that indicates that the dependent task should be canceled.
*/
- CANCEL,
+ CANCEL(TaskMessages.INFO_FAILED_DEPENDENCY_ACTION_CANCEL.get()),
@@ -54,7 +56,7 @@
* The action that indicates that the dependent task should be disabled so
* that an administrator will have to re-enable it before it can start.
*/
- DISABLE;
+ DISABLE(TaskMessages.INFO_FAILED_DEPENDENCY_ACTION_DISABLE.get());
@@ -88,5 +90,20 @@
return null;
}
}
+
+ private Message name;
+
+ /**
+ * Gets the display name of this action.
+ *
+ * @return Message representing the name of this action
+ */
+ public Message getDisplayName() {
+ return name;
+ }
+
+ private FailedDependencyAction(Message name) {
+ this.name = name;
+ }
}
diff --git a/opends/src/server/org/opends/server/backends/task/Task.java b/opends/src/server/org/opends/server/backends/task/Task.java
index 1a83f2d..fde6022 100644
--- a/opends/src/server/org/opends/server/backends/task/Task.java
+++ b/opends/src/server/org/opends/server/backends/task/Task.java
@@ -144,7 +144,34 @@
// The scheduler with which this task is associated.
private TaskScheduler taskScheduler;
+ /**
+ * Gets a message that identifies this type of task suitable for
+ * presentation to humans in monitoring tools.
+ *
+ * @return name of task
+ */
+ public Message getDisplayName() {
+ // NOTE: this method is invoked via reflection. If you rename
+ // it be sure to modify the calls.
+ return null;
+ };
+ /**
+ * Given an attribute type name returns and locale sensitive
+ * representation.
+ *
+ * @param name of an attribute type associated with the object
+ * class that represents this entry in the directory
+ * @return Message diaplay name
+ */
+ public Message getAttributeDisplayName(String name) {
+ // Subclasses that are schedulable from the task interface
+ // should override this
+
+ // NOTE: this method is invoked via reflection. If you rename
+ // it be sure to modify the calls.
+ return null;
+ }
/**
* Performs generic initialization for this task based on the information in
@@ -1224,6 +1251,21 @@
public void interruptTask(TaskState interruptState, Message interruptReason)
{
// No action is performed by default.
+
+ // NOTE: if you implement this make sure to override isInterruptable
+ // to return 'true'
}
+
+
+
+ /**
+ * Indicates whether or not this task is interruptable or not.
+ *
+ * @return boolean where true indicates that this task can be interrupted.
+ */
+ public boolean isInterruptable() {
+ return false;
+ }
+
}
diff --git a/opends/src/server/org/opends/server/backends/task/TaskScheduler.java b/opends/src/server/org/opends/server/backends/task/TaskScheduler.java
index 285c8da..b835337 100644
--- a/opends/src/server/org/opends/server/backends/task/TaskScheduler.java
+++ b/opends/src/server/org/opends/server/backends/task/TaskScheduler.java
@@ -347,6 +347,10 @@
activeThreads.put(task.getTaskID(), taskThread);
taskThread.setTask(task);
}
+ else if (TaskState.isDone(state))
+ {
+ completedTasks.add(task);
+ }
else
{
pendingTasks.add(task);
@@ -871,6 +875,13 @@
*/
private TaskState shouldStart(Task task)
{
+ // If the task has finished we don't want to restart it
+ TaskState state = task.getTaskState();
+ if (state != null && TaskState.isDone(state))
+ {
+ return state;
+ }
+
if (! isRunning)
{
return TaskState.UNSCHEDULED;
diff --git a/opends/src/server/org/opends/server/backends/task/TaskState.java b/opends/src/server/org/opends/server/backends/task/TaskState.java
index e3f86b3..c0b36fc 100644
--- a/opends/src/server/org/opends/server/backends/task/TaskState.java
+++ b/opends/src/server/org/opends/server/backends/task/TaskState.java
@@ -26,6 +26,9 @@
*/
package org.opends.server.backends.task;
+import org.opends.messages.Message;
+import static org.opends.messages.TaskMessages.*;
+
/**
* This enumeration defines the various states that a task can have during its
@@ -37,7 +40,7 @@
* The task state that indicates that the task has not yet been scheduled,
* or possibly that the scheduler is currently not running.
*/
- UNSCHEDULED,
+ UNSCHEDULED(INFO_TASK_STATE_UNSCHEDULED.get()),
@@ -45,7 +48,7 @@
* The task state that indicates that the task has been disabled by an
* administrator.
*/
- DISABLED,
+ DISABLED(INFO_TASK_STATE_DISABLED.get()),
@@ -53,7 +56,7 @@
* The task state that indicates that the task's scheduled start time has not
* yet arrived.
*/
- WAITING_ON_START_TIME,
+ WAITING_ON_START_TIME(INFO_TASK_STATE_WAITING_ON_START_TIME.get()),
@@ -61,14 +64,14 @@
* The task state that indicates that at least one of the task's defined
* dependencies has not yet completed.
*/
- WAITING_ON_DEPENDENCY,
+ WAITING_ON_DEPENDENCY(INFO_TASK_STATE_WAITING_ON_DEPENDENCY.get()),
/**
* The task state that indicates that the task is currently running.
*/
- RUNNING,
+ RUNNING(INFO_TASK_STATE_RUNNING.get()),
@@ -76,7 +79,7 @@
* The task state that indicates that the task has completed without any
* errors.
*/
- COMPLETED_SUCCESSFULLY,
+ COMPLETED_SUCCESSFULLY(INFO_TASK_STATE_COMPLETED_SUCCESSFULLY.get()),
@@ -85,7 +88,7 @@
* intended goal, but that one or more errors were encountered during the
* process.
*/
- COMPLETED_WITH_ERRORS,
+ COMPLETED_WITH_ERRORS(INFO_TASK_STATE_COMPLETED_WITH_ERRORS.get()),
@@ -93,7 +96,7 @@
* The task state that indicates that the task was unable to complete because
* it was interrupted by the shutdown of the task backend.
*/
- STOPPED_BY_SHUTDOWN,
+ STOPPED_BY_SHUTDOWN(INFO_TASK_STATE_STOPPED_BY_SHUTDOWN.get()),
@@ -101,7 +104,7 @@
* The task state that indicates that one or more errors prevented the task
* from completing.
*/
- STOPPED_BY_ERROR,
+ STOPPED_BY_ERROR(INFO_TASK_STATE_STOPPED_BY_ERROR.get()),
@@ -109,7 +112,7 @@
* The task state that indicates that the task was stopped by an administrator
* after it had already started but before it was able to complete.
*/
- STOPPED_BY_ADMINISTRATOR,
+ STOPPED_BY_ADMINISTRATOR(INFO_TASK_STATE_STOPPED_BY_ADMINISTRATOR.get()),
@@ -117,7 +120,7 @@
* The task state that indicates that the task was canceled by an
* administrator before it started running.
*/
- CANCELED_BEFORE_STARTING;
+ CANCELED_BEFORE_STARTING(INFO_TASK_STATE_CANCELED_BEFORE_STARTING.get());
@@ -282,5 +285,20 @@
return null;
}
}
+
+ private Message displayName;
+
+ /**
+ * Gets a locale sensitive representation of this state.
+ *
+ * @return Message describing state
+ */
+ public Message getDisplayName() {
+ return displayName;
+ }
+
+ private TaskState(Message displayName) {
+ this.displayName = displayName;
+ }
}
diff --git a/opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java b/opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java
index 148e322..d44bd61 100644
--- a/opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java
+++ b/opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java
@@ -83,7 +83,12 @@
// The list of files to be added to the server schema.
TreeSet<String> filesToAdd;
-
+ /**
+ * {@inheritDoc}
+ */
+ public Message getDisplayName() {
+ return INFO_TASK_ADD_SCHEMA_FILE_NAME.get();
+ }
/**
* {@inheritDoc}
diff --git a/opends/src/server/org/opends/server/tasks/BackupTask.java b/opends/src/server/org/opends/server/tasks/BackupTask.java
index f04ec5d..f9aba64 100644
--- a/opends/src/server/org/opends/server/tasks/BackupTask.java
+++ b/opends/src/server/org/opends/server/tasks/BackupTask.java
@@ -60,6 +60,7 @@
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
+import java.util.HashMap;
import java.text.SimpleDateFormat;
import java.io.File;
@@ -72,6 +73,53 @@
{
+ /**
+ * Stores mapping between configuration attribute name and its label.
+ */
+ static private Map<String,Message> argDisplayMap =
+ new HashMap<String,Message>();
+ static {
+ argDisplayMap.put(
+ ATTR_TASK_BACKUP_ALL,
+ INFO_BACKUP_ARG_BACKUPALL.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_BACKUP_COMPRESS,
+ INFO_BACKUP_ARG_COMPRESS.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_BACKUP_ENCRYPT,
+ INFO_BACKUP_ARG_ENCRYPT.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_BACKUP_HASH,
+ INFO_BACKUP_ARG_HASH.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_BACKUP_INCREMENTAL,
+ INFO_BACKUP_ARG_INCREMENTAL.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_BACKUP_SIGN_HASH,
+ INFO_BACKUP_ARG_SIGN_HASH.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_BACKUP_BACKEND_ID,
+ INFO_BACKUP_ARG_BACKEND_IDS.get());
+
+ argDisplayMap.put(
+ ATTR_BACKUP_ID,
+ INFO_BACKUP_ARG_BACKUP_ID.get());
+
+ argDisplayMap.put(
+ ATTR_BACKUP_DIRECTORY_PATH,
+ INFO_BACKUP_ARG_BACKUP_DIR.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_BACKUP_INCREMENTAL_BASE_ID,
+ INFO_BACKUP_ARG_INC_BASE_ID.get());
+ }
+
// The task arguments.
private boolean backUpAll;
@@ -96,6 +144,20 @@
/**
* {@inheritDoc}
*/
+ public Message getDisplayName() {
+ return INFO_TASK_BACKUP_NAME.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Message getAttributeDisplayName(String attrName) {
+ return argDisplayMap.get(attrName);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
@Override public void initializeTask() throws DirectoryException
{
// If the client connection is available, then make sure the associated
diff --git a/opends/src/server/org/opends/server/tasks/DisconnectClientTask.java b/opends/src/server/org/opends/server/tasks/DisconnectClientTask.java
index 9298e61..f8ea940 100644
--- a/opends/src/server/org/opends/server/tasks/DisconnectClientTask.java
+++ b/opends/src/server/org/opends/server/tasks/DisconnectClientTask.java
@@ -69,7 +69,12 @@
// The disconnect message to send to the client.
private Message disconnectMessage;
-
+ /**
+ * {@inheritDoc}
+ */
+ public Message getDisplayName() {
+ return INFO_TASK_DISCONNECT_CLIENT_NAME.get();
+ }
/**
* {@inheritDoc}
diff --git a/opends/src/server/org/opends/server/tasks/EnterLockdownModeTask.java b/opends/src/server/org/opends/server/tasks/EnterLockdownModeTask.java
index 15a8a9c..270c742 100644
--- a/opends/src/server/org/opends/server/tasks/EnterLockdownModeTask.java
+++ b/opends/src/server/org/opends/server/tasks/EnterLockdownModeTask.java
@@ -50,6 +50,14 @@
public class EnterLockdownModeTask
extends Task
{
+
+ /**
+ * {@inheritDoc}
+ */
+ public Message getDisplayName() {
+ return INFO_TASK_ENTER_LOCKDOWN_MODE_NAME.get();
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/opends/src/server/org/opends/server/tasks/ExportTask.java b/opends/src/server/org/opends/server/tasks/ExportTask.java
index 8ac3217..10432f5 100644
--- a/opends/src/server/org/opends/server/tasks/ExportTask.java
+++ b/opends/src/server/org/opends/server/tasks/ExportTask.java
@@ -53,6 +53,8 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
/**
* This class provides an implementation of a Directory Server task that can
@@ -61,7 +63,64 @@
public class ExportTask extends Task
{
+ /**
+ * Stores mapping between configuration attribute name and its label.
+ */
+ static private Map<String,Message> argDisplayMap =
+ new HashMap<String,Message>();
+ static {
+ argDisplayMap.put(
+ ATTR_TASK_EXPORT_LDIF_FILE,
+ INFO_EXPORT_ARG_LDIF_FILE.get());
+ argDisplayMap.put(
+ ATTR_TASK_EXPORT_BACKEND_ID,
+ INFO_EXPORT_ARG_BACKEND_ID.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_EXPORT_APPEND_TO_LDIF,
+ INFO_EXPORT_ARG_APPEND_TO_LDIF.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_EXPORT_COMPRESS_LDIF,
+ INFO_EXPORT_ARG_COMPRESS_LDIF.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_EXPORT_ENCRYPT_LDIF,
+ INFO_EXPORT_ARG_ENCRYPT_LDIF.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_EXPORT_SIGN_HASH,
+ INFO_EXPORT_ARG_SIGN_HASH.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_EXPORT_INCLUDE_ATTRIBUTE,
+ INFO_EXPORT_ARG_INCL_ATTR.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_EXPORT_EXCLUDE_ATTRIBUTE,
+ INFO_EXPORT_ARG_EXCL_ATTR.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_EXPORT_INCLUDE_FILTER,
+ INFO_EXPORT_ARG_INCL_FILTER.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_EXPORT_EXCLUDE_FILTER,
+ INFO_EXPORT_ARG_EXCL_FILTER.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_EXPORT_INCLUDE_BRANCH,
+ INFO_EXPORT_ARG_INCL_BRANCH.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_EXPORT_EXCLUDE_BRANCH,
+ INFO_EXPORT_ARG_EXCL_BRANCH.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_EXPORT_WRAP_COLUMN,
+ INFO_EXPORT_ARG_WRAP_COLUMN.get());
+ }
private String ldifFile;
private String backendID;
@@ -77,6 +136,21 @@
private ArrayList<String> includeBranchStrings;
private ArrayList<String> excludeBranchStrings;
+
+ /**
+ * {@inheritDoc}
+ */
+ public Message getDisplayName() {
+ return INFO_TASK_EXPORT_NAME.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Message getAttributeDisplayName(String name) {
+ return argDisplayMap.get(name);
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/opends/src/server/org/opends/server/tasks/ImportTask.java b/opends/src/server/org/opends/server/tasks/ImportTask.java
index 3027835..2d451dc 100644
--- a/opends/src/server/org/opends/server/tasks/ImportTask.java
+++ b/opends/src/server/org/opends/server/tasks/ImportTask.java
@@ -59,6 +59,8 @@
import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
/**
* This class provides an implementation of a Directory Server task that can
@@ -72,6 +74,81 @@
private static final DebugTracer TRACER = getTracer();
+ /**
+ * Stores mapping between configuration attribute name and its label.
+ */
+ static private Map<String,Message> argDisplayMap =
+ new HashMap<String,Message>();
+
+ static {
+ argDisplayMap.put(
+ ATTR_IMPORT_LDIF_FILE,
+ INFO_IMPORT_ARG_LDIF_FILE.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_APPEND,
+ INFO_IMPORT_ARG_APPEND.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_REPLACE_EXISTING,
+ INFO_IMPORT_ARG_REPLACE_EXISTING.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_BACKEND_ID,
+ INFO_IMPORT_ARG_BACKEND_ID.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_INCLUDE_BRANCH,
+ INFO_IMPORT_ARG_INCL_BRANCH.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_EXCLUDE_BRANCH,
+ INFO_IMPORT_ARG_EXCL_BRANCH.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_INCLUDE_ATTRIBUTE,
+ INFO_IMPORT_ARG_INCL_ATTR.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_EXCLUDE_ATTRIBUTE,
+ INFO_IMPORT_ARG_EXCL_ATTR.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_INCLUDE_FILTER,
+ INFO_IMPORT_ARG_INCL_FILTER.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_EXCLUDE_FILTER,
+ INFO_IMPORT_ARG_EXCL_FILTER.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_REJECT_FILE,
+ INFO_IMPORT_ARG_REJECT_FILE.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_SKIP_FILE,
+ INFO_IMPORT_ARG_SKIP_FILE.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_OVERWRITE,
+ INFO_IMPORT_ARG_OVERWRITE.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_SKIP_SCHEMA_VALIDATION,
+ INFO_IMPORT_ARG_SKIP_SCHEMA_VALIDATION.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_IS_COMPRESSED,
+ INFO_IMPORT_ARG_IS_COMPRESSED.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_IS_ENCRYPTED,
+ INFO_IMPORT_ARG_IS_ENCRYPTED.get());
+
+ argDisplayMap.put(
+ ATTR_IMPORT_CLEAR_BACKEND,
+ INFO_IMPORT_ARG_CLEAR_BACKEND.get());
+ }
boolean append = false;
@@ -93,6 +170,19 @@
ArrayList<String> ldifFiles = null;
+ /**
+ * {@inheritDoc}
+ */
+ public Message getDisplayName() {
+ return INFO_TASK_IMPORT_NAME.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Message getAttributeDisplayName(String name) {
+ return argDisplayMap.get(name);
+ }
/**
* {@inheritDoc}
diff --git a/opends/src/server/org/opends/server/tasks/InitializeTargetTask.java b/opends/src/server/org/opends/server/tasks/InitializeTargetTask.java
index e98356a..2b8b8d9 100644
--- a/opends/src/server/org/opends/server/tasks/InitializeTargetTask.java
+++ b/opends/src/server/org/opends/server/tasks/InitializeTargetTask.java
@@ -39,6 +39,7 @@
import org.opends.server.backends.task.Task;
import org.opends.server.backends.task.TaskState;
import org.opends.messages.TaskMessages;
+import org.opends.messages.Message;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.replication.plugin.ReplicationDomain;
import org.opends.server.types.Attribute;
@@ -78,6 +79,13 @@
/**
* {@inheritDoc}
*/
+ public Message getDisplayName() {
+ return TaskMessages.INFO_TASK_INITIALIZE_TARGET_NAME.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
@Override public void initializeTask() throws DirectoryException
{
// FIXME -- Do we need any special authorization here?
diff --git a/opends/src/server/org/opends/server/tasks/InitializeTask.java b/opends/src/server/org/opends/server/tasks/InitializeTask.java
index 11a4fd8..5d5649f 100644
--- a/opends/src/server/org/opends/server/tasks/InitializeTask.java
+++ b/opends/src/server/org/opends/server/tasks/InitializeTask.java
@@ -80,6 +80,13 @@
/**
* {@inheritDoc}
*/
+ public Message getDisplayName() {
+ return TaskMessages.INFO_TASK_INITIALIZE_NAME.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
@Override public void initializeTask() throws DirectoryException
{
if (TaskState.isDone(getTaskState()))
diff --git a/opends/src/server/org/opends/server/tasks/LeaveLockdownModeTask.java b/opends/src/server/org/opends/server/tasks/LeaveLockdownModeTask.java
index d6433ee..0f2993c 100644
--- a/opends/src/server/org/opends/server/tasks/LeaveLockdownModeTask.java
+++ b/opends/src/server/org/opends/server/tasks/LeaveLockdownModeTask.java
@@ -50,6 +50,14 @@
public class LeaveLockdownModeTask
extends Task
{
+
+ /**
+ * {@inheritDoc}
+ */
+ public Message getDisplayName() {
+ return INFO_TASK_LEAVE_LOCKDOWN_MODE_NAME.get();
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/opends/src/server/org/opends/server/tasks/RebuildTask.java b/opends/src/server/org/opends/server/tasks/RebuildTask.java
index f2ca592..a8703e5 100644
--- a/opends/src/server/org/opends/server/tasks/RebuildTask.java
+++ b/opends/src/server/org/opends/server/tasks/RebuildTask.java
@@ -26,6 +26,7 @@
*/
package org.opends.server.tasks;
import org.opends.messages.Message;
+import org.opends.messages.TaskMessages;
import org.opends.server.backends.task.Task;
import org.opends.server.backends.task.TaskState;
@@ -95,6 +96,13 @@
/**
* {@inheritDoc}
*/
+ public Message getDisplayName() {
+ return TaskMessages.INFO_TASK_REBUILD_NAME.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
@Override public void initializeTask() throws DirectoryException
{
// If the client connection is available, then make sure the associated
diff --git a/opends/src/server/org/opends/server/tasks/RestoreTask.java b/opends/src/server/org/opends/server/tasks/RestoreTask.java
index 76bb5f3..b13858c 100644
--- a/opends/src/server/org/opends/server/tasks/RestoreTask.java
+++ b/opends/src/server/org/opends/server/tasks/RestoreTask.java
@@ -59,6 +59,8 @@
import org.opends.server.types.ResultCode;
import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
import java.io.File;
/**
@@ -73,6 +75,24 @@
private static final DebugTracer TRACER = getTracer();
+ /**
+ * Stores mapping between configuration attribute name and its label.
+ */
+ static private Map<String,Message> argDisplayMap =
+ new HashMap<String,Message>();
+ static {
+ argDisplayMap.put(
+ ATTR_BACKUP_DIRECTORY_PATH,
+ INFO_RESTORE_ARG_BACKUP_DIR.get());
+
+ argDisplayMap.put(
+ ATTR_BACKUP_ID,
+ INFO_RESTORE_ARG_BACKUP_ID.get());
+
+ argDisplayMap.put(
+ ATTR_TASK_RESTORE_VERIFY_ONLY,
+ INFO_RESTORE_ARG_VERIFY_ONLY.get());
+ }
// The task arguments.
@@ -84,6 +104,20 @@
/**
* {@inheritDoc}
*/
+ public Message getDisplayName() {
+ return INFO_TASK_RESTORE_NAME.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Message getAttributeDisplayName(String name) {
+ return argDisplayMap.get(name);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
@Override public void initializeTask() throws DirectoryException
{
// If the client connection is available, then make sure the associated
diff --git a/opends/src/server/org/opends/server/tasks/SetGenerationIdTask.java b/opends/src/server/org/opends/server/tasks/SetGenerationIdTask.java
index ba4b078..a439155 100644
--- a/opends/src/server/org/opends/server/tasks/SetGenerationIdTask.java
+++ b/opends/src/server/org/opends/server/tasks/SetGenerationIdTask.java
@@ -32,6 +32,7 @@
import org.opends.messages.MessageBuilder;
import org.opends.messages.TaskMessages;
+import org.opends.messages.Message;
import org.opends.server.backends.task.Task;
import org.opends.server.backends.task.TaskState;
import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -75,6 +76,13 @@
/**
* {@inheritDoc}
*/
+ public Message getDisplayName() {
+ return TaskMessages.INFO_TASK_SET_GENERATION_ID_NAME.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
@Override public void initializeTask() throws DirectoryException
{
if (TaskState.isDone(getTaskState()))
diff --git a/opends/src/server/org/opends/server/tasks/ShutdownTask.java b/opends/src/server/org/opends/server/tasks/ShutdownTask.java
index 58cc374..ca42629 100644
--- a/opends/src/server/org/opends/server/tasks/ShutdownTask.java
+++ b/opends/src/server/org/opends/server/tasks/ShutdownTask.java
@@ -69,6 +69,12 @@
private Message shutdownMessage;
+ /**
+ * {@inheritDoc}
+ */
+ public Message getDisplayName() {
+ return INFO_TASK_SHUTDOWN_NAME.get();
+ }
/**
* Performs any task-specific initialization that may be required before
diff --git a/opends/src/server/org/opends/server/tools/ManageTasks.java b/opends/src/server/org/opends/server/tools/ManageTasks.java
new file mode 100644
index 0000000..8f13d2f
--- /dev/null
+++ b/opends/src/server/org/opends/server/tools/ManageTasks.java
@@ -0,0 +1,926 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.tools;
+
+import org.opends.messages.Message;
+import static org.opends.messages.ToolMessages.*;
+import org.opends.server.api.ErrorLogPublisher;
+import org.opends.server.core.DirectoryServer;
+import static org.opends.server.loggers.ErrorLogger.removeErrorLogPublisher;
+import org.opends.server.protocols.asn1.ASN1Exception;
+import static org.opends.server.tools.ToolConstants.*;
+import org.opends.server.tools.tasks.TaskClient;
+import org.opends.server.tools.tasks.TaskEntry;
+import org.opends.server.types.LDAPException;
+import org.opends.server.util.StaticUtils;
+import static org.opends.server.util.StaticUtils.filterExitCode;
+import org.opends.server.util.args.ArgumentException;
+import org.opends.server.util.args.BooleanArgument;
+import org.opends.server.util.args.LDAPConnectionArgumentParser;
+import org.opends.server.util.args.StringArgument;
+import org.opends.server.util.cli.CLIException;
+import org.opends.server.util.cli.ConsoleApplication;
+import org.opends.server.util.cli.LDAPConnectionConsoleInteraction;
+import org.opends.server.util.cli.Menu;
+import org.opends.server.util.cli.MenuBuilder;
+import org.opends.server.util.cli.MenuCallback;
+import org.opends.server.util.cli.MenuResult;
+import org.opends.server.util.table.TableBuilder;
+import org.opends.server.util.table.TextTablePrinter;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Tool for getting information and managing tasks in the Directory Server.
+ */
+public class ManageTasks extends ConsoleApplication {
+
+ private static ErrorLogPublisher errorLogPublisher = null;
+
+ /**
+ * The main method for TaskInfo tool.
+ *
+ * @param args The command-line arguments provided to this program.
+ */
+ public static void main(String[] args) {
+ int retCode = mainTaskInfo(args, System.in, System.out, System.err);
+
+ if (errorLogPublisher != null) {
+ removeErrorLogPublisher(errorLogPublisher);
+ }
+
+ if (retCode != 0) {
+ System.exit(filterExitCode(retCode));
+ }
+ }
+
+ /**
+ * Processes the command-line arguments and invokes the process for
+ * displaying task information.
+ *
+ * @param args The command-line arguments provided to this program.
+ * @return int return code
+ */
+ public static int mainTaskInfo(String[] args) {
+ return mainTaskInfo(args, System.in, System.out, System.err);
+ }
+
+ /**
+ * Processes the command-line arguments and invokes the export process.
+ *
+ * @param args The command-line arguments provided to this
+ * @param in Input stream from which to solicit user input.
+ * @param out The output stream to use for standard output, or
+ * {@code null} if standard output is not needed.
+ * @param err The output stream to use for standard error, or
+ * {@code null} if standard error is not needed.
+
+ * @return int return code
+ */
+ public static int mainTaskInfo(String[] args,
+ InputStream in,
+ OutputStream out,
+ OutputStream err) {
+ ManageTasks tool = new ManageTasks(in, out, err);
+ return tool.process(args);
+ }
+
+ private static final int INDENT = 2;
+
+ /**
+ * ID of task for which to display details and exit.
+ */
+ private StringArgument task = null;
+
+ /**
+ * Indicates print summary and exit.
+ */
+ private BooleanArgument summary = null;
+
+ /**
+ * ID of task to cancel.
+ */
+ private StringArgument cancel = null;
+
+ /**
+ * Argument used to request non-interactive behavior.
+ */
+ private BooleanArgument noPrompt = null;
+
+ /**
+ * Accesses the directory's task backend.
+ */
+ private TaskClient taskClient;
+
+ /**
+ * Constructs a parameterized instance.
+ *
+ * @param in Input stream from which to solicit user input.
+ * @param out The output stream to use for standard output, or
+ * {@code null} if standard output is not needed.
+ * @param err The output stream to use for standard error, or
+ * {@code null} if standard error is not needed.
+ */
+ public ManageTasks(InputStream in, OutputStream out, OutputStream err) {
+ super(in, out, err);
+ }
+
+ /**
+ * Processes the command-line arguments and invokes the export process.
+ *
+ * @param args The command-line arguments provided to this
+ * program.
+ * @return The error code.
+ */
+ public int process(String[] args) {
+
+ DirectoryServer.bootstrapClient();
+
+ // Create the command-line argument parser for use with this program.
+ LDAPConnectionArgumentParser argParser = new LDAPConnectionArgumentParser(
+ "org.opends.server.tools.TaskInfo",
+ INFO_TASKINFO_TOOL_DESCRIPTION.get(),
+ false);
+
+ // Initialize all the command-line argument types and register them with the
+ // parser.
+ try {
+
+ task = new StringArgument(
+ "task", 't', "task",
+ false, true, "{taskID}",
+ INFO_TASKINFO_TASK_ARG_DESCRIPTION.get());
+ argParser.addArgument(task);
+
+ cancel = new StringArgument(
+ "cancel", 'c', "cancel",
+ false, true, "{taskID}",
+ INFO_TASKINFO_TASK_ARG_CANCEL.get());
+ argParser.addArgument(cancel);
+
+ summary = new BooleanArgument(
+ "summary", 's', "summary",
+ INFO_TASKINFO_SUMMARY_ARG_DESCRIPTION.get());
+ argParser.addArgument(summary);
+
+ noPrompt = new BooleanArgument(
+ OPTION_LONG_NO_PROMPT,
+ OPTION_SHORT_NO_PROMPT,
+ OPTION_LONG_NO_PROMPT,
+ INFO_DESCRIPTION_NO_PROMPT.get());
+ argParser.addArgument(noPrompt);
+
+ BooleanArgument displayUsage = new BooleanArgument(
+ "help", OPTION_SHORT_HELP,
+ OPTION_LONG_HELP,
+ INFO_DESCRIPTION_USAGE.get());
+ argParser.addArgument(displayUsage);
+ argParser.setUsageArgument(displayUsage);
+ }
+ catch (ArgumentException ae) {
+ Message message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
+ println(message);
+ return 1;
+ }
+
+ // Parse the command-line arguments provided to this program.
+ try {
+ argParser.parseArguments(args);
+ StaticUtils.checkOnlyOneArgPresent(task, summary, cancel);
+ }
+ catch (ArgumentException ae) {
+ Message message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
+ println(message);
+ println(argParser.getUsageMessage());
+ return 1;
+ }
+
+ if (!argParser.usageOrVersionDisplayed()) {
+ try {
+ LDAPConnectionConsoleInteraction ui =
+ new LDAPConnectionConsoleInteraction(
+ this, argParser.getArguments());
+
+ taskClient = new TaskClient(argParser.connect(ui,
+ getOutputStream(), getErrorStream()));
+
+ if (isMenuDrivenMode()) {
+
+ // Keep prompting the user until they specify quit of
+ // there is a fatal exception
+ while (true) {
+ println();
+ Menu<Void> menu = getSummaryMenu();
+ MenuResult<Void> result = menu.run();
+ if (result.isQuit()) {
+ return 0;
+ }
+ }
+
+ } else if (task.isPresent()) {
+ println();
+ new PrintTaskInfo(task.getValue()).invoke(this);
+ } else if (summary.isPresent()) {
+ println();
+ printSummaryTable();
+ } else if (cancel.isPresent()) {
+ new CancelTask(cancel.getValue()).invoke(this);
+ }
+
+ } catch (LDAPConnectionException lce) {
+ println(INFO_TASKINFO_LDAP_EXCEPTION.get(lce.getMessageObject()));
+ return 1;
+ } catch (Exception e) {
+ println(Message.raw(e.getMessage()));
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isAdvancedMode() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isInteractive() {
+ return !noPrompt.isPresent();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isMenuDrivenMode() {
+ return !task.isPresent() && !cancel.isPresent() && !summary.isPresent();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isQuiet() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isScriptFriendly() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isVerbose() {
+ return false;
+ }
+
+ /**
+ * Creates the summary table.
+ *
+ * @throws IOException if there is a problem with screen I/O
+ * @throws LDAPException if there is a problem getting information
+ * out to the directory
+ * @throws ASN1Exception if there is a problem with the encoding
+ */
+ private void printSummaryTable()
+ throws LDAPException, IOException, ASN1Exception {
+ List<TaskEntry> entries = taskClient.getTaskEntries();
+ if (entries.size() > 0) {
+ TableBuilder table = new TableBuilder();
+ Map<String, TaskEntry> mapIdToEntry =
+ new TreeMap<String, TaskEntry>();
+ for (TaskEntry entry : entries) {
+ String taskId = entry.getId();
+ if (taskId != null) {
+ mapIdToEntry.put(taskId, entry);
+ }
+ }
+
+ table.appendHeading(INFO_TASKINFO_FIELD_ID.get());
+ table.appendHeading(INFO_TASKINFO_FIELD_TYPE.get());
+ table.appendHeading(INFO_TASKINFO_FIELD_STATUS.get());
+ for (String taskId : mapIdToEntry.keySet()) {
+ TaskEntry entryWrapper = mapIdToEntry.get(taskId);
+ table.startRow();
+ table.appendCell(taskId);
+ table.appendCell(entryWrapper.getType());
+ table.appendCell(entryWrapper.getState());
+ }
+ StringWriter sw = new StringWriter();
+ TextTablePrinter tablePrinter = new TextTablePrinter(sw);
+ tablePrinter.setIndentWidth(INDENT);
+ tablePrinter.setTotalWidth(80);
+ table.print(tablePrinter);
+ println(Message.raw(sw.getBuffer()));
+ } else {
+ println(INFO_TASKINFO_NO_TASKS.get());
+ println();
+ }
+ }
+
+ /**
+ * Creates the summary table.
+ *
+ * @return list of strings of IDs of all the tasks in the table in order
+ * of the indexes printed in the table
+ * @throws IOException if there is a problem with screen I/O
+ * @throws LDAPException if there is a problem getting information
+ * out to the directory
+ * @throws ASN1Exception if there is a problem with the encoding
+ */
+ private Menu<Void> getSummaryMenu()
+ throws LDAPException, IOException, ASN1Exception {
+ List<String> taskIds = new ArrayList<String>();
+ List<Integer> cancelableIndices = new ArrayList<Integer>();
+ List<TaskEntry> entries = taskClient.getTaskEntries();
+ MenuBuilder<Void> menuBuilder = new MenuBuilder<Void>(this);
+ if (entries.size() > 0) {
+ Map<String, TaskEntry> mapIdToEntry =
+ new TreeMap<String, TaskEntry>();
+ for (TaskEntry entry : entries) {
+ String taskId = entry.getId();
+ if (taskId != null) {
+ mapIdToEntry.put(taskId, entry);
+ }
+ }
+
+ menuBuilder.setColumnHeadings(
+ INFO_TASKINFO_FIELD_ID.get(),
+ INFO_TASKINFO_FIELD_TYPE.get(),
+ INFO_TASKINFO_FIELD_STATUS.get());
+ menuBuilder.setColumnWidths(null, null, 0);
+ int index = 0;
+ for (final String taskId : mapIdToEntry.keySet()) {
+ taskIds.add(taskId);
+ final TaskEntry taskEntry = mapIdToEntry.get(taskId);
+ menuBuilder.addNumberedOption(
+ Message.raw(taskEntry.getId()),
+ new TaskDrilldownMenu(taskId),
+ taskEntry.getType(), taskEntry.getState());
+ index++;
+ if (taskEntry.isCancelable() && !taskEntry.isDone()) {
+ cancelableIndices.add(index);
+ }
+ }
+ } else {
+ // println();
+ println(INFO_TASKINFO_NO_TASKS.get());
+ println();
+ }
+
+ menuBuilder.addCharOption(
+ Message.raw("r"),
+ INFO_TASKINFO_CMD_REFRESH.get(),
+ new PrintSummaryTop());
+
+ if (cancelableIndices.size() > 0) {
+ menuBuilder.addCharOption(
+ Message.raw("c"),
+ INFO_TASKINFO_CMD_CANCEL.get(),
+ new CancelTaskTop(taskIds, cancelableIndices));
+ }
+ menuBuilder.addQuitOption();
+
+ return menuBuilder.toMenu();
+ }
+
+ /**
+ * Gets the client that can be used to interact with the task backend.
+ *
+ * @return TaskClient for interacting with the task backend.
+ */
+ public TaskClient getTaskClient() {
+ return this.taskClient;
+ }
+
+ /**
+ * Base for callbacks that implement top level menu items.
+ */
+ static abstract private class TopMenuCallback
+ implements MenuCallback<Void> {
+
+ /**
+ * {@inheritDoc}
+ */
+ public MenuResult<Void> invoke(ConsoleApplication app) throws CLIException {
+ return invoke((ManageTasks)app);
+ }
+
+ /**
+ * Called upon task invocation.
+ *
+ * @param app this console application
+ * @return MessageResult result of task
+ * @throws CLIException if there is a problem
+ */
+ protected abstract MenuResult<Void> invoke(ManageTasks app)
+ throws CLIException;
+
+ }
+
+ /**
+ * Base for callbacks that manage task entries.
+ */
+ static abstract private class TaskOperationCallback
+ implements MenuCallback<TaskEntry> {
+
+ /** ID of the task to manage. */
+ protected String taskId;
+
+ /**
+ * Constructs a parameterized instance.
+ *
+ * @param taskId if the task to examine
+ */
+ public TaskOperationCallback(String taskId) {
+ this.taskId = taskId;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public MenuResult<TaskEntry> invoke(ConsoleApplication app)
+ throws CLIException
+ {
+ return invoke((ManageTasks)app);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected abstract MenuResult<TaskEntry> invoke(ManageTasks app)
+ throws CLIException;
+
+ }
+
+ /**
+ * Executable for printing a task summary table.
+ */
+ static private class PrintSummaryTop extends TopMenuCallback {
+
+ public MenuResult<Void> invoke(ManageTasks app)
+ throws CLIException
+ {
+ // Since the summary table is reprinted every time the
+ // user enters the top level this task just returns
+ // 'success'
+ return MenuResult.success();
+ }
+ }
+
+ /**
+ * Exectuable for printing a particular task's details.
+ */
+ static private class TaskDrilldownMenu extends TopMenuCallback {
+
+ private String taskId;
+
+ /**
+ * Constructs a parameterized instance.
+ *
+ * @param taskId of the task for which information will be displayed
+ */
+ public TaskDrilldownMenu(String taskId) {
+ this.taskId = taskId;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public MenuResult<Void> invoke(ManageTasks app) throws CLIException {
+ MenuResult<TaskEntry> res = new PrintTaskInfo(taskId).invoke(app);
+ TaskEntry taskEntry = res.getValue();
+ if (taskEntry != null) {
+ while (true) {
+ try {
+ taskEntry = app.getTaskClient().getTaskEntry(taskId);
+
+ // Show the menu
+ MenuBuilder<TaskEntry> menuBuilder =
+ new MenuBuilder<TaskEntry>(app);
+ menuBuilder.addBackOption(true);
+ menuBuilder.addCharOption(
+ Message.raw("r"),
+ INFO_TASKINFO_CMD_REFRESH.get(),
+ new PrintTaskInfo(taskId));
+ List<Message> logs = taskEntry.getLogMessages();
+ if (logs != null && logs.size() > 0) {
+ menuBuilder.addCharOption(
+ Message.raw("l"),
+ INFO_TASKINFO_CMD_VIEW_LOGS.get(),
+ new ViewTaskLogs(taskId));
+ }
+ if (taskEntry.isCancelable() && !taskEntry.isDone()) {
+ menuBuilder.addCharOption(
+ Message.raw("c"),
+ INFO_TASKINFO_CMD_CANCEL.get(),
+ new CancelTask(taskId));
+ }
+ menuBuilder.addQuitOption();
+ Menu<TaskEntry> menu = menuBuilder.toMenu();
+ MenuResult<TaskEntry> result = menu.run();
+ if (result.isCancel()) {
+ break;
+ } else if (result.isQuit()) {
+ System.exit(0);
+ }
+ } catch (Exception e) {
+ app.println(Message.raw(e.getMessage()));
+ }
+ }
+ } else {
+ app.println(ERR_TASKINFO_UNKNOWN_TASK_ENTRY.get(taskId));
+ }
+ return MenuResult.success();
+ }
+
+ }
+
+ /**
+ * Exectuable for printing a particular task's details.
+ */
+ static private class PrintTaskInfo extends TaskOperationCallback {
+
+ /**
+ * Constructs a parameterized instance.
+ *
+ * @param taskId of the task for which information will be printed
+ */
+ public PrintTaskInfo(String taskId) {
+ super(taskId);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public MenuResult<TaskEntry> invoke(ManageTasks app)
+ throws CLIException
+ {
+ TaskEntry taskEntry = null;
+ try {
+ taskEntry = app.getTaskClient().getTaskEntry(taskId);
+
+ TableBuilder table = new TableBuilder();
+ table.appendHeading(INFO_TASKINFO_DETAILS.get());
+
+ table.startRow();
+ table.appendCell(INFO_TASKINFO_FIELD_ID.get());
+ table.appendCell(taskEntry.getId());
+
+ table.startRow();
+ table.appendCell(INFO_TASKINFO_FIELD_TYPE.get());
+ table.appendCell(taskEntry.getType());
+
+ table.startRow();
+ table.appendCell(INFO_TASKINFO_FIELD_STATUS.get());
+ table.appendCell(taskEntry.getState());
+
+ table.startRow();
+ table.appendCell(INFO_TASKINFO_FIELD_SCHEDULED_START.get());
+ Message m = taskEntry.getScheduledStartTime();
+ if (m == null || m.equals(Message.EMPTY)) {
+ table.appendCell(INFO_TASKINFO_IMMEDIATE_EXECUTION.get());
+ } else {
+ table.appendCell(m);
+ }
+
+ table.startRow();
+ table.appendCell(INFO_TASKINFO_FIELD_ACTUAL_START.get());
+ table.appendCell(taskEntry.getActualStartTime());
+
+ table.startRow();
+ table.appendCell(INFO_TASKINFO_FIELD_COMPLETION_TIME.get());
+ table.appendCell(taskEntry.getCompletionTime());
+
+ writeMultiValueCells(
+ table,
+ INFO_TASKINFO_FIELD_DEPENDENCY.get(),
+ taskEntry.getDependencyIds());
+
+ table.startRow();
+ table.appendCell(INFO_TASKINFO_FIELD_FAILED_DEPENDENCY_ACTION.get());
+ m = taskEntry.getFailedDependencyAction();
+ table.appendCell(m != null ? m : INFO_TASKINFO_NONE.get());
+
+ writeMultiValueCells(
+ table,
+ INFO_TASKINFO_FIELD_NOTIFY_ON_COMPLETION.get(),
+ taskEntry.getCompletionNotificationEmailAddresses(),
+ INFO_TASKINFO_NONE_SPECIFIED.get());
+
+ writeMultiValueCells(
+ table,
+ INFO_TASKINFO_FIELD_NOTIFY_ON_ERROR.get(),
+ taskEntry.getErrorNotificationEmailAddresses(),
+ INFO_TASKINFO_NONE_SPECIFIED.get());
+
+ StringWriter sw = new StringWriter();
+ TextTablePrinter tablePrinter = new TextTablePrinter(sw);
+ tablePrinter.setTotalWidth(80);
+ tablePrinter.setIndentWidth(INDENT);
+ tablePrinter.setColumnWidth(1, 0);
+ table.print(tablePrinter);
+ app.println();
+ app.println(Message.raw(sw.getBuffer().toString()));
+
+ // Create a table for the task options
+ table = new TableBuilder();
+ table.appendHeading(INFO_TASKINFO_OPTIONS.get(taskEntry.getType()));
+ Map<Message,List<String>> taskSpecificAttrs =
+ taskEntry.getTaskSpecificAttributeValuePairs();
+ for (Message attrName : taskSpecificAttrs.keySet()) {
+ table.startRow();
+ table.appendCell(attrName);
+ List<String> values = taskSpecificAttrs.get(attrName);
+ if (values.size() > 0) {
+ table.appendCell(values.get(0));
+ }
+ if (values.size() > 1) {
+ for (int i = 1; i < values.size(); i++) {
+ table.startRow();
+ table.appendCell();
+ table.appendCell(values.get(i));
+ }
+ }
+ }
+ sw = new StringWriter();
+ tablePrinter = new TextTablePrinter(sw);
+ tablePrinter.setTotalWidth(80);
+ tablePrinter.setIndentWidth(INDENT);
+ tablePrinter.setColumnWidth(1, 0);
+ table.print(tablePrinter);
+ app.println(Message.raw(sw.getBuffer().toString()));
+
+ // Print the last log message if any
+ List<Message> logs = taskEntry.getLogMessages();
+ if (logs != null && logs.size() > 0) {
+
+ // Create a table for the last log entry
+ table = new TableBuilder();
+ table.appendHeading(INFO_TASKINFO_FIELD_LAST_LOG.get());
+ table.startRow();
+ table.appendCell(logs.get(logs.size() - 1));
+
+ sw = new StringWriter();
+ tablePrinter = new TextTablePrinter(sw);
+ tablePrinter.setTotalWidth(80);
+ tablePrinter.setIndentWidth(INDENT);
+ tablePrinter.setColumnWidth(0, 0);
+ table.print(tablePrinter);
+ app.println(Message.raw(sw.getBuffer().toString()));
+ }
+
+ app.println();
+ } catch (Exception e) {
+ app.println(ERR_TASKINFO_RETRIEVING_TASK_ENTRY.get(
+ taskId, e.getMessage()));
+ }
+ return MenuResult.success(taskEntry);
+ }
+
+ /**
+ * Writes an attribute and associated values to the table.
+ * @param table of task details
+ * @param fieldLabel of attribute
+ * @param values of the attribute
+ */
+ private void writeMultiValueCells(TableBuilder table,
+ Message fieldLabel,
+ List<?> values) {
+ writeMultiValueCells(table, fieldLabel, values, INFO_TASKINFO_NONE.get());
+ }
+
+ /**
+ * Writes an attribute and associated values to the table.
+ *
+ * @param table of task details
+ * @param fieldLabel of attribute
+ * @param values of the attribute
+ * @param noneLabel label for the value column when there are no values
+ */
+ private void writeMultiValueCells(TableBuilder table,
+ Message fieldLabel,
+ List<?> values,
+ Message noneLabel) {
+ table.startRow();
+ table.appendCell(fieldLabel);
+ if (values.size() == 0) {
+ table.appendCell(noneLabel);
+ } else if (values.size() > 0) {
+ table.appendCell(values.get(0));
+ }
+ if (values.size() > 1) {
+ for (int i = 1; i < values.size(); i++) {
+ table.startRow();
+ table.appendCell();
+ table.appendCell(values.get(i));
+ }
+ }
+ }
+ }
+
+ /**
+ * Exectuable for printing a particular task's details.
+ */
+ static private class ViewTaskLogs extends TaskOperationCallback {
+
+ /**
+ * Constructs a parameterized instance.
+ *
+ * @param taskId of the task for which log records will be printed
+ */
+ public ViewTaskLogs(String taskId) {
+ super(taskId);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected MenuResult<TaskEntry> invoke(ManageTasks app)
+ throws CLIException
+ {
+ TaskEntry taskEntry = null;
+ try {
+ taskEntry = app.getTaskClient().getTaskEntry(taskId);
+ List<Message> logs = taskEntry.getLogMessages();
+ app.println();
+
+ // Create a table for the last log entry
+ TableBuilder table = new TableBuilder();
+ table.appendHeading(INFO_TASKINFO_FIELD_LOG.get());
+ if (logs != null && logs.size() > 0) {
+ for (Message log : logs) {
+ table.startRow();
+ table.appendCell(log);
+ }
+ } else {
+ table.startRow();
+ table.appendCell(INFO_TASKINFO_NONE.get());
+ }
+ StringWriter sw = new StringWriter();
+ TextTablePrinter tablePrinter = new TextTablePrinter(sw);
+ tablePrinter.setTotalWidth(80);
+ tablePrinter.setIndentWidth(INDENT);
+ tablePrinter.setColumnWidth(0, 0);
+ table.print(tablePrinter);
+ app.println(Message.raw(sw.getBuffer().toString()));
+ app.println();
+ } catch (Exception e) {
+ app.println(ERR_TASKINFO_ACCESSING_LOGS.get(taskId, e.getMessage()));
+ }
+ return MenuResult.success(taskEntry);
+ }
+ }
+
+ /**
+ * Executable for canceling a particular task.
+ */
+ static private class CancelTaskTop extends TopMenuCallback {
+
+ private List<String> taskIds;
+ private List<Integer> cancelableIndices;
+
+ /**
+ * Constructs a parameterized instance.
+ *
+ * @param taskIds of all known tasks
+ * @param cancelableIndices list of integers whose elements represent
+ * the indices of <code>taskIds</code> that are cancelable
+ */
+ public CancelTaskTop(List<String> taskIds,
+ List<Integer> cancelableIndices) {
+ this.taskIds = taskIds;
+ this.cancelableIndices = cancelableIndices;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public MenuResult<Void> invoke(ManageTasks app)
+ throws CLIException
+ {
+ if (taskIds != null && taskIds.size() > 0) {
+ if (cancelableIndices != null && cancelableIndices.size() > 0) {
+
+ // Prompt for the task number
+ Integer index = null;
+ String line = app.readLineOfInput(
+ INFO_TASKINFO_CMD_CANCEL_NUMBER_PROMPT.get(
+ cancelableIndices.get(0)));
+ if (line.length() == 0) {
+ line = String.valueOf(cancelableIndices.get(0));
+ }
+ try {
+ int i = Integer.parseInt(line);
+ if (!cancelableIndices.contains(i)) {
+ app.println(ERR_TASKINFO_NOT_CANCELABLE_TASK_INDEX.get(i));
+ } else {
+ index = i - 1;
+ }
+ } catch (NumberFormatException nfe) {
+ // ignore;
+ }
+ if (index != null) {
+ String taskId = taskIds.get(index);
+ try {
+ CancelTask ct = new CancelTask(taskId);
+ MenuResult<TaskEntry> result = ct.invoke(app);
+ if (result.isSuccess()) {
+ return MenuResult.success();
+ } else {
+ return MenuResult.again();
+ }
+ } catch (Exception e) {
+ app.println(ERR_TASKINFO_CANCELING_TASK.get(
+ taskId, e.getMessage()));
+ return MenuResult.again();
+ }
+ } else {
+ app.println(ERR_TASKINFO_INVALID_MENU_KEY.get(line));
+ return MenuResult.again();
+ }
+ } else {
+ app.println(INFO_TASKINFO_NO_CANCELABLE_TASKS.get());
+ return MenuResult.cancel();
+ }
+ } else {
+ app.println(INFO_TASKINFO_NO_TASKS.get());
+ return MenuResult.cancel();
+ }
+ }
+
+ }
+
+ /**
+ * Executable for canceling a particular task.
+ */
+ static private class CancelTask extends TaskOperationCallback {
+
+ /**
+ * Constructs a parameterized instance.
+ *
+ * @param taskId of the task to cancel
+ */
+ public CancelTask(String taskId) {
+ super(taskId);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public MenuResult<TaskEntry> invoke(ManageTasks app)
+ throws CLIException
+ {
+ try {
+ TaskEntry entry = app.getTaskClient().cancelTask(taskId);
+ app.println(INFO_TASKINFO_CMD_CANCEL_SUCCESS.get(taskId));
+ return MenuResult.success(entry);
+ } catch (Exception e) {
+ app.println(ERR_TASKINFO_CANCELING_TASK.get(
+ taskId, e.getMessage()));
+ return MenuResult.again();
+ }
+ }
+
+ }
+
+}
diff --git a/opends/src/server/org/opends/server/tools/tasks/TaskClient.java b/opends/src/server/org/opends/server/tools/tasks/TaskClient.java
new file mode 100644
index 0000000..b9972a1
--- /dev/null
+++ b/opends/src/server/org/opends/server/tools/tasks/TaskClient.java
@@ -0,0 +1,378 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.tools.tasks;
+
+import org.opends.messages.Message;
+import static org.opends.messages.ToolMessages.*;
+import org.opends.server.config.ConfigConstants;
+import static org.opends.server.config.ConfigConstants.*;
+import org.opends.server.protocols.asn1.ASN1Exception;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.protocols.ldap.AddRequestProtocolOp;
+import org.opends.server.protocols.ldap.AddResponseProtocolOp;
+import org.opends.server.protocols.ldap.LDAPAttribute;
+import org.opends.server.protocols.ldap.LDAPConstants;
+import org.opends.server.protocols.ldap.LDAPControl;
+import org.opends.server.protocols.ldap.LDAPFilter;
+import org.opends.server.protocols.ldap.LDAPMessage;
+import org.opends.server.protocols.ldap.LDAPModification;
+import org.opends.server.protocols.ldap.LDAPResultCode;
+import org.opends.server.protocols.ldap.ModifyRequestProtocolOp;
+import org.opends.server.protocols.ldap.ModifyResponseProtocolOp;
+import org.opends.server.protocols.ldap.SearchRequestProtocolOp;
+import org.opends.server.protocols.ldap.SearchResultEntryProtocolOp;
+import org.opends.server.tools.LDAPConnection;
+import org.opends.server.tools.LDAPReader;
+import org.opends.server.tools.LDAPWriter;
+import org.opends.server.types.DereferencePolicy;
+import org.opends.server.types.Entry;
+import org.opends.server.types.LDAPException;
+import org.opends.server.types.ModificationType;
+import org.opends.server.types.RawAttribute;
+import org.opends.server.types.RawModification;
+import org.opends.server.types.SearchResultEntry;
+import org.opends.server.types.SearchScope;
+import static org.opends.server.types.ResultCode.*;
+import org.opends.server.backends.task.TaskState;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Helper class for interacting with the task backend on behalf of utilities
+ * that are capable of being scheduled.
+ */
+public class TaskClient {
+
+ /**
+ * Connection through which task scheduling will take place.
+ */
+ protected LDAPConnection connection;
+
+ /**
+ * Keeps track of message IDs.
+ */
+ private AtomicInteger nextMessageID = new AtomicInteger(0);
+
+ /**
+ * Creates a new TaskClient for interacting with the task backend remotely.
+ * @param conn for accessing the task backend
+ */
+ public TaskClient(LDAPConnection conn) {
+ this.connection = conn;
+ }
+
+ /**
+ * Schedule a task for execution by writing an entry to the task backend.
+ *
+ * @param information to be scheduled
+ * @return String task ID assigned the new task
+ * @throws IOException if there is a stream communication problem
+ * @throws LDAPException if there is a problem getting information
+ * out to the directory
+ * @throws ASN1Exception if there is a problem with the encoding
+ */
+ public synchronized String schedule(TaskScheduleInformation information)
+ throws LDAPException, IOException, ASN1Exception
+ {
+ LDAPReader reader = connection.getLDAPReader();
+ LDAPWriter writer = connection.getLDAPWriter();
+
+ // Use a formatted time/date for the ID so that is remotely useful
+ SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmssMM");
+ String taskID = df.format(new Date());
+
+ ASN1OctetString entryDN =
+ new ASN1OctetString(ATTR_TASK_ID + "=" + taskID + "," +
+ SCHEDULED_TASK_BASE_RDN + "," + DN_TASK_ROOT);
+
+ ArrayList<LDAPControl> controls = new ArrayList<LDAPControl>();
+
+ ArrayList<RawAttribute> attributes = new ArrayList<RawAttribute>();
+
+ ArrayList<ASN1OctetString> ocValues = new ArrayList<ASN1OctetString>(3);
+ ocValues.add(new ASN1OctetString("top"));
+ ocValues.add(new ASN1OctetString(ConfigConstants.OC_TASK));
+ ocValues.add(new ASN1OctetString(information.getTaskObjectclass()));
+ attributes.add(new LDAPAttribute(ATTR_OBJECTCLASS, ocValues));
+
+ ArrayList<ASN1OctetString> taskIDValues = new ArrayList<ASN1OctetString>(1);
+ taskIDValues.add(new ASN1OctetString(taskID));
+ attributes.add(new LDAPAttribute(ATTR_TASK_ID, taskIDValues));
+
+ ArrayList<ASN1OctetString> classValues = new ArrayList<ASN1OctetString>(1);
+ classValues.add(new ASN1OctetString(information.getTaskClass().getName()));
+ attributes.add(new LDAPAttribute(ATTR_TASK_CLASS, classValues));
+
+ information.addTaskAttributes(attributes);
+
+ AddRequestProtocolOp addRequest = new AddRequestProtocolOp(entryDN,
+ attributes);
+ LDAPMessage requestMessage =
+ new LDAPMessage(nextMessageID.getAndIncrement(), addRequest, controls);
+
+ // Send the request to the server and read the response.
+ LDAPMessage responseMessage;
+ writer.writeMessage(requestMessage);
+
+ responseMessage = reader.readMessage();
+ if (responseMessage == null)
+ {
+ throw new LDAPException(
+ LDAPResultCode.CLIENT_SIDE_SERVER_DOWN,
+ ERR_TASK_CLIENT_UNEXPECTED_CONNECTION_CLOSURE.get());
+ }
+
+ if (responseMessage.getProtocolOpType() !=
+ LDAPConstants.OP_TYPE_ADD_RESPONSE)
+ {
+ throw new LDAPException(
+ LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR,
+ ERR_TASK_CLIENT_INVALID_RESPONSE_TYPE.get(
+ responseMessage.getProtocolOpName()));
+ }
+
+ AddResponseProtocolOp addResponse =
+ responseMessage.getAddResponseProtocolOp();
+ Message errorMessage = addResponse.getErrorMessage();
+ if (errorMessage != null) {
+ throw new LDAPException(
+ LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR,
+ errorMessage);
+ }
+ return taskID;
+ }
+
+ /**
+ * Gets all the ds-task entries from the task root.
+ *
+ * @return list of entries from the task root
+ * @throws IOException if there is a stream communication problem
+ * @throws LDAPException if there is a problem getting information
+ * out to the directory
+ * @throws ASN1Exception if there is a problem with the encoding
+ */
+ public synchronized List<TaskEntry> getTaskEntries()
+ throws LDAPException, IOException, ASN1Exception {
+ List<Entry> entries = new ArrayList<Entry>();
+
+ writeSearch(new SearchRequestProtocolOp(
+ new ASN1OctetString(ConfigConstants.DN_TASK_ROOT),
+ SearchScope.WHOLE_SUBTREE,
+ DereferencePolicy.NEVER_DEREF_ALIASES,
+ Integer.MAX_VALUE,
+ Integer.MAX_VALUE,
+ false,
+ LDAPFilter.decode("(objectclass=ds-task)"),
+ new LinkedHashSet<String>()));
+
+ LDAPReader reader = connection.getLDAPReader();
+ byte opType;
+ do {
+ LDAPMessage responseMessage = reader.readMessage();
+ if (responseMessage == null) {
+ throw new LDAPException(
+ LDAPResultCode.CLIENT_SIDE_SERVER_DOWN,
+ ERR_TASK_CLIENT_UNEXPECTED_CONNECTION_CLOSURE.get());
+ } else {
+ opType = responseMessage.getProtocolOpType();
+ if (opType == LDAPConstants.OP_TYPE_SEARCH_RESULT_ENTRY) {
+ SearchResultEntryProtocolOp searchEntryOp =
+ responseMessage.getSearchResultEntryProtocolOp();
+ SearchResultEntry entry = searchEntryOp.toSearchResultEntry();
+ entries.add(entry);
+ }
+ }
+ }
+ while (opType != LDAPConstants.OP_TYPE_SEARCH_RESULT_DONE);
+ List<TaskEntry> taskEntries = new ArrayList<TaskEntry>(entries.size());
+ for (Entry entry : entries) {
+ taskEntries.add(new TaskEntry(entry));
+ }
+ return Collections.unmodifiableList(taskEntries);
+ }
+
+ /**
+ * Gets the entry of the task whose ID is <code>id</code> from the directory.
+ *
+ * @param id of the entry to retrieve
+ * @return Entry for the task
+ * @throws IOException if there is a stream communication problem
+ * @throws LDAPException if there is a problem getting information
+ * out to the directory
+ * @throws ASN1Exception if there is a problem with the encoding
+ * @throws TaskClientException if there is no task with the requested id
+ */
+ public synchronized TaskEntry getTaskEntry(String id)
+ throws LDAPException, IOException, ASN1Exception, TaskClientException
+ {
+ Entry entry = null;
+
+ writeSearch(new SearchRequestProtocolOp(
+ new ASN1OctetString(ConfigConstants.DN_TASK_ROOT),
+ SearchScope.WHOLE_SUBTREE,
+ DereferencePolicy.NEVER_DEREF_ALIASES,
+ Integer.MAX_VALUE,
+ Integer.MAX_VALUE,
+ false,
+ LDAPFilter.decode("(ds-task-id=" + id + ")"),
+ new LinkedHashSet<String>()));
+
+ LDAPReader reader = connection.getLDAPReader();
+ byte opType;
+ do {
+ LDAPMessage responseMessage = reader.readMessage();
+ if (responseMessage == null) {
+ Message message = ERR_TASK_CLIENT_UNEXPECTED_CONNECTION_CLOSURE.get();
+ throw new LDAPException(UNAVAILABLE.getIntValue(), message);
+ } else {
+ opType = responseMessage.getProtocolOpType();
+ if (opType == LDAPConstants.OP_TYPE_SEARCH_RESULT_ENTRY) {
+ SearchResultEntryProtocolOp searchEntryOp =
+ responseMessage.getSearchResultEntryProtocolOp();
+ entry = searchEntryOp.toSearchResultEntry();
+ }
+ }
+ }
+ while (opType != LDAPConstants.OP_TYPE_SEARCH_RESULT_DONE);
+ if (entry == null) {
+ throw new TaskClientException(ERR_TASK_CLIENT_UNKNOWN_TASK.get(id));
+ }
+ return new TaskEntry(entry);
+ }
+
+
+ /**
+ * Changes that the state of the task in the backend to a canceled state.
+ *
+ * @param id if the task to cancel
+ * @return Entry of the task before the modification
+ * @throws IOException if there is a stream communication problem
+ * @throws LDAPException if there is a problem getting information
+ * out to the directory
+ * @throws ASN1Exception if there is a problem with the encoding
+ * @throws TaskClientException if there is no task with the requested id
+ */
+ public synchronized TaskEntry cancelTask(String id)
+ throws TaskClientException, IOException, ASN1Exception, LDAPException
+ {
+ LDAPReader reader = connection.getLDAPReader();
+ LDAPWriter writer = connection.getLDAPWriter();
+
+ TaskEntry entry = getTaskEntry(id);
+ TaskState state = entry.getTaskState();
+ if (state != null) {
+ if (!TaskState.isDone(state)) {
+
+ ASN1OctetString dn = new ASN1OctetString(entry.getDN().toString());
+
+ ArrayList<RawModification> mods = new ArrayList<RawModification>();
+
+ ArrayList<ASN1OctetString> values = new ArrayList<ASN1OctetString>();
+ String newState;
+ if (TaskState.isPending(state)) {
+ newState = TaskState.CANCELED_BEFORE_STARTING.name();
+ } else {
+ newState = TaskState.STOPPED_BY_ADMINISTRATOR.name();
+ }
+ values.add(new ASN1OctetString(newState));
+ LDAPAttribute attr = new LDAPAttribute(ATTR_TASK_STATE, values);
+ mods.add(new LDAPModification(ModificationType.REPLACE, attr));
+
+ // We have to reset the start time or the scheduler will
+ // reschedule to task.
+ // attr = new LDAPAttribute(ATTR_TASK_SCHEDULED_START_TIME);
+ // mods.add(new LDAPModification(ModificationType.DELETE, attr));
+
+ ModifyRequestProtocolOp modRequest =
+ new ModifyRequestProtocolOp(dn, mods);
+ LDAPMessage requestMessage =
+ new LDAPMessage(nextMessageID.getAndIncrement(), modRequest, null);
+
+ writer.writeMessage(requestMessage);
+
+ LDAPMessage responseMessage = reader.readMessage();
+
+ if (responseMessage == null) {
+ Message message = ERR_TASK_CLIENT_UNEXPECTED_CONNECTION_CLOSURE.get();
+ throw new LDAPException(UNAVAILABLE.getIntValue(), message);
+ }
+
+ if (responseMessage.getProtocolOpType() !=
+ LDAPConstants.OP_TYPE_MODIFY_RESPONSE)
+ {
+ throw new LDAPException(
+ LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR,
+ ERR_TASK_CLIENT_INVALID_RESPONSE_TYPE.get(
+ responseMessage.getProtocolOpName()));
+ }
+
+ ModifyResponseProtocolOp modResponse =
+ responseMessage.getModifyResponseProtocolOp();
+ Message errorMessage = modResponse.getErrorMessage();
+ if (errorMessage != null) {
+ throw new LDAPException(
+ LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR,
+ errorMessage);
+ }
+ } else {
+ throw new TaskClientException(
+ ERR_TASK_CLIENT_UNCANCELABLE_TASK.get(id));
+ }
+ } else {
+ throw new TaskClientException(
+ ERR_TASK_CLIENT_TASK_STATE_UNKNOWN.get(id));
+ }
+ return getTaskEntry(id);
+ }
+
+
+ /**
+ * Writes a search to the directory writer.
+ * @param searchRequest to write
+ * @throws IOException if there is a stream communication problem
+ */
+ private void writeSearch(SearchRequestProtocolOp searchRequest)
+ throws IOException {
+ LDAPWriter writer = connection.getLDAPWriter();
+ LDAPMessage requestMessage = new LDAPMessage(
+ nextMessageID.getAndIncrement(),
+ searchRequest,
+ new ArrayList<LDAPControl>());
+
+ // Send the request to the server and read the response.
+ writer.writeMessage(requestMessage);
+ }
+
+}
diff --git a/opends/src/server/org/opends/server/tools/tasks/TaskClientException.java b/opends/src/server/org/opends/server/tools/tasks/TaskClientException.java
new file mode 100644
index 0000000..08e0b32
--- /dev/null
+++ b/opends/src/server/org/opends/server/tools/tasks/TaskClientException.java
@@ -0,0 +1,84 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.tools.tasks;
+
+import org.opends.messages.Message;
+
+import org.opends.server.types.OpenDsException;
+
+/**
+ * Exception for problems related to interacting with the task backend.
+ */
+public class TaskClientException extends OpenDsException {
+
+ private static final long serialVersionUID = 3800881643050096416L;
+
+ /**
+ * Constructs a default instance.
+ */
+ public TaskClientException() {
+ }
+
+ /**
+ * Constructs a parameterized instance.
+ *
+ * @param cause of this exception
+ */
+ public TaskClientException(OpenDsException cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a parameterized instance.
+ *
+ * @param message for this exception
+ */
+ public TaskClientException(Message message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a parameterized instance.
+ *
+ * @param cause of this exception
+ */
+ public TaskClientException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a parameterized instance.
+ *
+ * @param message for this exception
+ * @param cause of this exception
+ */
+ public TaskClientException(Message message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/opends/src/server/org/opends/server/tools/tasks/TaskEntry.java b/opends/src/server/org/opends/server/tools/tasks/TaskEntry.java
new file mode 100644
index 0000000..4f622b1
--- /dev/null
+++ b/opends/src/server/org/opends/server/tools/tasks/TaskEntry.java
@@ -0,0 +1,482 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.tools.tasks;
+
+import org.opends.messages.Message;
+
+import org.opends.server.backends.task.Task;
+import org.opends.server.backends.task.TaskState;
+import org.opends.server.backends.task.FailedDependencyAction;
+import org.opends.server.types.Entry;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.DN;
+import static org.opends.server.util.ServerConstants.*;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.List;
+import java.util.LinkedHashSet;
+import java.util.ArrayList;
+import java.util.TimeZone;
+import java.util.Date;
+import java.util.Collections;
+import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
+import java.text.DateFormat;
+import java.text.ParseException;
+
+/**
+ * Processes information from a task entry from the directory and
+ * provides accessors for attribute information. In some cases the
+ * data is formatted into more human-friendly formats.
+ */
+public class TaskEntry {
+
+ private static Map<String, Message> mapClassToTypeName =
+ new HashMap<String, Message>();
+
+ private static Map<String, Message> mapAttrToDisplayName =
+ new HashMap<String, Message>();
+
+
+ // These attributes associated with the ds-task object
+ // class are all handled explicitly below in the constructor
+ private static Set<String> supAttrNames = new HashSet<String>();
+ static {
+ supAttrNames.add("ds-task-id");
+ supAttrNames.add("ds-task-class-name");
+ supAttrNames.add("ds-task-state");
+ supAttrNames.add("ds-task-scheduled-start-time");
+ supAttrNames.add("ds-task-actual-start-time");
+ supAttrNames.add("ds-task-completion-time");
+ supAttrNames.add("ds-task-dependency-id");
+ supAttrNames.add("ds-task-failed-dependency-action");
+ supAttrNames.add("ds-task-log-message");
+ supAttrNames.add("ds-task-notify-on-completion");
+ supAttrNames.add("ds-task-notify-on-error");
+ }
+
+ private String id;
+ private String className;
+ private String state;
+ private String schedStart;
+ private String actStart;
+ private String compTime;
+ private List<String> depends;
+ private String depFailAct;
+ private List<String> logs;
+ private List<String> notifyComp;
+ private List<String> notifyErr;
+ private DN dn;
+
+ /**
+ * Task of the same type that implements. Used for obtaining
+ * task name and attribute display information.
+ */
+ private Task task;
+
+ private Map<Message, List<String>> taskSpecificAttrValues =
+ new HashMap<Message, List<String>>();
+
+ /**
+ * Creates a parameterized instance.
+ *
+ * @param entry to wrap
+ */
+ public TaskEntry(Entry entry) {
+ dn = entry.getDN();
+
+ String p = "ds-task-";
+ id = getSingleStringValue(entry, p + "id");
+ className = getSingleStringValue(entry, p + "class-name");
+ state = getSingleStringValue(entry, p + "state");
+ schedStart = getSingleStringValue(entry, p + "scheduled-start-time");
+ actStart = getSingleStringValue(entry, p + "actual-start-time");
+ compTime = getSingleStringValue(entry, p + "completion-time");
+ depends = getMultiStringValue(entry, p + "dependency-id");
+ depFailAct = getSingleStringValue(entry, p + "failed-dependency-action");
+ logs = getMultiStringValue(entry, p + "log-message");
+ notifyErr = getMultiStringValue(entry, p + "notify-on-completion");
+ notifyComp = getMultiStringValue(entry, p + "notify-on-error");
+
+
+ // Build a map of non-superior attribute value pairs for display
+ Map<AttributeType, List<Attribute>> attrMap = entry.getUserAttributes();
+ for (AttributeType type : attrMap.keySet()) {
+ String typeName = type.getNormalizedPrimaryName();
+
+ // See if we've handled it already above
+ if (!supAttrNames.contains(typeName)) {
+ Message attrTypeName = getAttributeDisplayName(
+ type.getNormalizedPrimaryName());
+ List<Attribute> attrList = entry.getUserAttribute(type);
+ for (Attribute attr : attrList) {
+ LinkedHashSet<AttributeValue> valuesSet = attr.getValues();
+ for (AttributeValue av : valuesSet) {
+ List<String> valueList = taskSpecificAttrValues.get(attrTypeName);
+ if (valueList == null) {
+ valueList = new ArrayList<String>();
+ taskSpecificAttrValues.put(attrTypeName, valueList);
+ }
+ valueList.add(av.getStringValue());
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the DN of the wrapped entry.
+ *
+ * @return DN of entry
+ */
+ public DN getDN() {
+ return dn;
+ }
+
+ /**
+ * Gets the ID of the task.
+ *
+ * @return String ID of the task
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Gets the name of the class implementing the task represented here.
+ *
+ * @return String name of class
+ */
+ public String getClassName() {
+ return className;
+ }
+
+ /**
+ * Gets the state of the task.
+ *
+ * @return Message representing state
+ */
+ public Message getState() {
+ Message m = Message.EMPTY;
+ if (state != null) {
+ TaskState ts = TaskState.fromString(state);
+ if (ts != null) {
+ m = ts.getDisplayName();
+ }
+ }
+ return m;
+ }
+
+ /**
+ * Gets the human-friendly scheduled time.
+ *
+ * @return String time
+ */
+ public Message getScheduledStartTime() {
+ return formatTimeString(schedStart);
+ }
+
+ /**
+ * Gets the human-friendly start time.
+ *
+ * @return String time
+ */
+ public Message getActualStartTime() {
+ return formatTimeString(actStart);
+ }
+
+ /**
+ * Gets the human-friendly completion time.
+ *
+ * @return String time
+ */
+ public Message getCompletionTime() {
+ return formatTimeString(compTime);
+ }
+
+ /**
+ * Gets the IDs of tasks upon which this task depends.
+ *
+ * @return array of IDs
+ */
+ public List<String> getDependencyIds() {
+ return Collections.unmodifiableList(depends);
+ }
+
+ /**
+ * Gets the action to take if this task fails.
+ *
+ * @return String action
+ */
+ public Message getFailedDependencyAction() {
+ Message m = null;
+ if (depFailAct != null) {
+ FailedDependencyAction fda =
+ FailedDependencyAction.fromString(depFailAct);
+ if (fda != null) {
+ m = fda.getDisplayName();
+ }
+ }
+ return m;
+ }
+
+ /**
+ * Gets the logs associated with this task's execution.
+ *
+ * @return array of log messages
+ */
+ public List<Message> getLogMessages() {
+ List<Message> formattedLogs = new ArrayList<Message>();
+ for (String aLog : logs) {
+ formattedLogs.add(Message.raw(formatLogMessage(aLog)));
+ }
+ return Collections.unmodifiableList(formattedLogs);
+ }
+
+ /**
+ * Gets the email messages that will be used for notifications
+ * when the task completes.
+ *
+ * @return array of email addresses
+ */
+ public List<String> getCompletionNotificationEmailAddresses() {
+ return Collections.unmodifiableList(notifyComp);
+ }
+
+ /**
+ * Gets the email messages that will be used for notifications
+ * when the task encounters an error.
+ *
+ * @return array of email addresses
+ */
+ public List<String> getErrorNotificationEmailAddresses() {
+ return Collections.unmodifiableList(notifyErr);
+ }
+
+ /**
+ * Gets a user presentable string indicating the type of this task.
+ *
+ * @return Message type
+ */
+ public Message getType() {
+ Message type = Message.EMPTY;
+ if (className != null) {
+ type = mapClassToTypeName.get(className);
+ if (type == null) {
+ Task task = getTask();
+ if (task != null) {
+ try {
+ Method m = Task.class.getMethod("getDisplayName");
+ Object oName = m.invoke(task);
+ if (oName instanceof Message) {
+ mapClassToTypeName.put(className, (Message) oName);
+ type = (Message) oName;
+ }
+ } catch (Exception e) {
+ // ignore; this is best effort
+ }
+ }
+ }
+
+ // If we still can't get the type just resort
+ // to the class displayName
+ if (type == null) {
+ type = Message.raw(className);
+ }
+ }
+ return type;
+ }
+
+ /**
+ * Indicates whether or not this task supports a cancel operation.
+ *
+ * @return boolean where true means this task supports being canceled.
+ */
+ public boolean isCancelable() {
+ boolean cancelable = false;
+ TaskState state = getTaskState();
+ if (state != null) {
+ Task task = getTask();
+ cancelable = (TaskState.isPending(state) ||
+ (TaskState.isRunning(state) &&
+ task != null &&
+ task.isInterruptable()));
+ }
+ return cancelable;
+ }
+
+ /**
+ * Gets a mapping of attributes that are specific to the implementing
+ * task as opposed to the superior, or base, task.
+ *
+ * @return mapping of atribute field labels to lists of string values for
+ * each field.
+ */
+ public Map<Message, List<String>> getTaskSpecificAttributeValuePairs() {
+ return taskSpecificAttrValues;
+ }
+
+ /**
+ * Gets the task state.
+ *
+ * @return TaskState of task
+ */
+ public TaskState getTaskState() {
+ TaskState ts = null;
+ if (state != null) {
+ ts = TaskState.fromString(state);
+ }
+ return ts;
+ }
+
+ /**
+ * Indicates whether or not this task is done.
+ *
+ * @return boolean where true means this task is done
+ */
+ public boolean isDone() {
+ TaskState ts = getTaskState();
+ return ts != null && TaskState.isDone(ts);
+ }
+
+ private String getSingleStringValue(Entry entry, String attrName) {
+ List<Attribute> attrList = entry.getAttribute(attrName);
+ if (attrList != null && attrList.size() == 1) {
+ Set<AttributeValue> values = attrList.get(0).getValues();
+ if (values != null && values.size() == 1) {
+ return values.iterator().next().getStringValue();
+ }
+ }
+ return "";
+ }
+
+ private List<String> getMultiStringValue(Entry entry, String attrName) {
+ List<String> valuesList = new ArrayList<String>();
+ List<Attribute> attrList = entry.getAttribute(attrName);
+ if (attrList != null) {
+ for (Attribute attr : attrList) {
+ Set<AttributeValue> values = attr.getValues();
+ if (values != null) {
+ for (AttributeValue value : values) {
+ valuesList.add(value.getStringValue());
+ }
+ }
+ }
+ }
+ return valuesList;
+ }
+
+ private Message getAttributeDisplayName(String attrName) {
+ Message name = mapAttrToDisplayName.get(attrName);
+ if (name == null) {
+ Task task = getTask();
+ if (task != null) {
+ try {
+ Method m = Task.class.getMethod(
+ "getAttributeDisplayName", String.class);
+ Object o = m.invoke(task, attrName);
+ if (o != null && Message.class.isAssignableFrom(o.getClass())) {
+ name= (Message)o;
+ mapAttrToDisplayName.put(attrName, name);
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+ if (name == null) {
+ name = Message.raw(attrName);
+ }
+ return name;
+ }
+
+ /**
+ * Formats a log message for appending to the table.
+ * @param msg to format
+ * @return formatted message
+ */
+ private String formatLogMessage(String msg) {
+ // Use this to prepend to log messages. Since they
+ // are long and usually wrap, without this it is
+ // difficult to tell where one stops and another starts
+ StringBuffer sb = new StringBuffer();
+ sb.append("\u2022");
+ sb.append(" ");
+ sb.append(msg);
+ return sb.toString();
+ }
+
+ /**
+ * Formats a time string into a human friendly format.
+ * @param timeString the is human hostile
+ * @return string of time that is human friendly
+ */
+ private Message formatTimeString(String timeString) {
+ Message ret = Message.EMPTY;
+ if (timeString != null && timeString.length() > 0) {
+ try {
+ SimpleDateFormat dateFormat;
+ if (timeString.endsWith("Z")) {
+ dateFormat = new SimpleDateFormat(DATE_FORMAT_GMT_TIME);
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ } else {
+ dateFormat = new SimpleDateFormat(DATE_FORMAT_COMPACT_LOCAL_TIME);
+ }
+ Date date = dateFormat.parse(timeString);
+ DateFormat df = DateFormat.getDateTimeInstance(
+ DateFormat.FULL,
+ DateFormat.FULL);
+ ret = Message.raw(df.format(date));
+ } catch (ParseException pe){
+ ret = Message.raw(timeString);
+ }
+ }
+ return ret;
+ }
+
+ private Task getTask() {
+ if (task == null && className != null) {
+ try {
+ Class<?> clazz = Class.forName(className);
+ Object o = clazz.newInstance();
+ if (Task.class.isAssignableFrom(o.getClass())) {
+ this.task = (Task) o;
+ }
+ } catch (Exception e) {
+ // ignore; this is best effort
+ }
+ }
+ return task;
+ }
+
+}
diff --git a/opends/src/server/org/opends/server/tools/tasks/TaskScheduleInformation.java b/opends/src/server/org/opends/server/tools/tasks/TaskScheduleInformation.java
index 2318bf5..77137f0 100644
--- a/opends/src/server/org/opends/server/tools/tasks/TaskScheduleInformation.java
+++ b/opends/src/server/org/opends/server/tools/tasks/TaskScheduleInformation.java
@@ -35,7 +35,7 @@
* Interface for tools that are capable of scheduling a task remotely
* through the task backend.
*
- * @see TaskSchedulingClient
+ * @see TaskClient
*/
public interface TaskScheduleInformation {
diff --git a/opends/src/server/org/opends/server/tools/tasks/TaskSchedulingClient.java b/opends/src/server/org/opends/server/tools/tasks/TaskSchedulingClient.java
deleted file mode 100644
index 90f700f..0000000
--- a/opends/src/server/org/opends/server/tools/tasks/TaskSchedulingClient.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- * Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- * Portions Copyright 2007 Sun Microsystems, Inc.
- */
-
-package org.opends.server.tools.tasks;
-
-import org.opends.server.types.LDAPException;
-import org.opends.server.types.RawAttribute;
-import org.opends.server.types.ResultCode;
-import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.protocols.asn1.ASN1Exception;
-import org.opends.server.protocols.ldap.LDAPControl;
-import org.opends.server.protocols.ldap.AddRequestProtocolOp;
-import org.opends.server.protocols.ldap.LDAPMessage;
-import org.opends.server.protocols.ldap.LDAPResultCode;
-import org.opends.server.protocols.ldap.LDAPConstants;
-import org.opends.server.protocols.ldap.ExtendedResponseProtocolOp;
-import org.opends.server.protocols.ldap.AddResponseProtocolOp;
-import org.opends.server.protocols.ldap.LDAPAttribute;
-import static org.opends.server.config.ConfigConstants.ATTR_TASK_ID;
-import static org.opends.server.config.ConfigConstants.SCHEDULED_TASK_BASE_RDN;
-import static org.opends.server.config.ConfigConstants.DN_TASK_ROOT;
-import static org.opends.server.config.ConfigConstants.ATTR_OBJECTCLASS;
-import static org.opends.server.config.ConfigConstants.ATTR_TASK_CLASS;
-import org.opends.server.config.ConfigConstants;
-import static org.opends.server.util.ServerConstants.MAX_LINE_WIDTH;
-import static org.opends.server.util.StaticUtils.wrapText;
-import org.opends.server.tools.LDAPConnection;
-import org.opends.server.tools.LDAPReader;
-import org.opends.server.tools.LDAPWriter;
-import org.opends.messages.Message;
-import static org.opends.messages.ToolMessages.*;
-
-import java.util.UUID;
-import java.util.ArrayList;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.io.IOException;
-import java.io.PrintStream;
-
-/**
- * Helper class for interacting with the task backend on behalf of utilities
- * that are capable of being scheduled.
- */
-public class TaskSchedulingClient {
-
- /**
- * Connection through which task scheduling will take place.
- */
- protected LDAPConnection connection;
-
- /**
- * Creates a new TaskClient for interacting with the task backend remotely.
- * @param conn for accessing the task backend
- */
- public TaskSchedulingClient(LDAPConnection conn) {
- this.connection = conn;
- }
-
- /**
- * Schedule a task for execution by writing an entry to the task backend.
- *
- * @param information to be scheduled
- * @param out stream for writing error messages; may be null
- * @param err stream for writing error messages; may be null
- * @return int representing an LDAP return code
- */
- public synchronized int schedule(TaskScheduleInformation information,
- PrintStream out, PrintStream err) {
-
- // Attempt to connect and authenticate to the Directory Server.
- AtomicInteger nextMessageID = new AtomicInteger(1);
-
- LDAPReader reader = connection.getLDAPReader();
- LDAPWriter writer = connection.getLDAPWriter();
-
- // Construct the add request to send to the server.
- String taskID = UUID.randomUUID().toString();
- ASN1OctetString entryDN =
- new ASN1OctetString(ATTR_TASK_ID + "=" + taskID + "," +
- SCHEDULED_TASK_BASE_RDN + "," + DN_TASK_ROOT);
-
- ArrayList<LDAPControl> controls = new ArrayList<LDAPControl>();
-
- ArrayList<RawAttribute> attributes = new ArrayList<RawAttribute>();
-
- ArrayList<ASN1OctetString> ocValues = new ArrayList<ASN1OctetString>(3);
- ocValues.add(new ASN1OctetString("top"));
- ocValues.add(new ASN1OctetString(ConfigConstants.OC_TASK));
- ocValues.add(new ASN1OctetString(information.getTaskObjectclass()));
- attributes.add(new LDAPAttribute(ATTR_OBJECTCLASS, ocValues));
-
- ArrayList<ASN1OctetString> taskIDValues = new ArrayList<ASN1OctetString>(1);
- taskIDValues.add(new ASN1OctetString(taskID));
- attributes.add(new LDAPAttribute(ATTR_TASK_ID, taskIDValues));
-
- ArrayList<ASN1OctetString> classValues = new ArrayList<ASN1OctetString>(1);
- classValues.add(new ASN1OctetString(information.getTaskClass().getName()));
- attributes.add(new LDAPAttribute(ATTR_TASK_CLASS, classValues));
-
- information.addTaskAttributes(attributes);
-
- AddRequestProtocolOp addRequest = new AddRequestProtocolOp(entryDN,
- attributes);
- LDAPMessage requestMessage =
- new LDAPMessage(nextMessageID.getAndIncrement(), addRequest, controls);
-
- // Send the request to the server and read the response.
- LDAPMessage responseMessage;
- try
- {
- writer.writeMessage(requestMessage);
-
- responseMessage = reader.readMessage();
- if (responseMessage == null)
- {
- Message message = ERR_TASK_CLIENT_UNEXPECTED_CONNECTION_CLOSURE.get();
- if (err != null) err.println(wrapText(message, MAX_LINE_WIDTH));
- return LDAPResultCode.CLIENT_SIDE_SERVER_DOWN;
- }
- }
- catch (IOException ioe)
- {
- Message message = ERR_TASK_CLIENT_IO_ERROR.get(String.valueOf(ioe));
- if (err != null) err.println(wrapText(message, MAX_LINE_WIDTH));
- return LDAPResultCode.CLIENT_SIDE_SERVER_DOWN;
- }
- catch (ASN1Exception ae)
- {
- Message message = ERR_TASK_CLIENT_DECODE_ERROR.get(ae.getMessage());
- if (err != null) err.println(wrapText(message, MAX_LINE_WIDTH));
- return LDAPResultCode.CLIENT_SIDE_DECODING_ERROR;
- }
- catch (LDAPException le)
- {
- Message message = ERR_TASK_CLIENT_DECODE_ERROR.get(le.getMessage());
- if (err != null) err.println(wrapText(message, MAX_LINE_WIDTH));
- return LDAPResultCode.CLIENT_SIDE_DECODING_ERROR;
- }
-
- if (responseMessage.getProtocolOpType() !=
- LDAPConstants.OP_TYPE_ADD_RESPONSE)
- {
- if (responseMessage.getProtocolOpType() ==
- LDAPConstants.OP_TYPE_EXTENDED_RESPONSE)
- {
- // It's possible that this is a notice of disconnection, which we can
- // probably interpret as a "success" in this case.
- ExtendedResponseProtocolOp extendedResponse =
- responseMessage.getExtendedResponseProtocolOp();
- String responseOID = extendedResponse.getOID();
- if ((responseOID != null) &&
- (responseOID.equals(LDAPConstants.OID_NOTICE_OF_DISCONNECTION)))
- {
- Message message = extendedResponse.getErrorMessage();
- if (message != null)
- {
- if (err != null) err.println(wrapText(message, MAX_LINE_WIDTH));
- }
-
- return extendedResponse.getResultCode();
- }
- }
-
- Message message = ERR_TASK_CLIENT_INVALID_RESPONSE_TYPE.get(
- responseMessage.getProtocolOpName());
- if (err != null) err.println(wrapText(message, MAX_LINE_WIDTH));
- return LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR;
- }
-
- AddResponseProtocolOp addResponse =
- responseMessage.getAddResponseProtocolOp();
- Message errorMessage = addResponse.getErrorMessage();
- if (errorMessage != null && err != null)
- {
- err.println(wrapText(errorMessage, MAX_LINE_WIDTH));
- }
-
- if (addResponse.getResultCode() == ResultCode.SUCCESS.getIntValue() &&
- out != null)
- {
- out.println(wrapText(INFO_TASK_CLIENT_TASK_SCHEDULED.get(taskID),
- MAX_LINE_WIDTH));
- }
-
- return addResponse.getResultCode();
- }
-
-}
diff --git a/opends/src/server/org/opends/server/tools/tasks/TaskTool.java b/opends/src/server/org/opends/server/tools/tasks/TaskTool.java
index 8cd4aeb..3d6b3fa 100644
--- a/opends/src/server/org/opends/server/tools/tasks/TaskTool.java
+++ b/opends/src/server/org/opends/server/tools/tasks/TaskTool.java
@@ -31,13 +31,15 @@
import org.opends.server.util.args.ArgumentException;
import static org.opends.server.util.StaticUtils.wrapText;
import static org.opends.server.util.ServerConstants.MAX_LINE_WIDTH;
-import org.opends.server.protocols.ldap.LDAPResultCode;
+import org.opends.server.protocols.asn1.ASN1Exception;
import org.opends.server.tools.LDAPConnection;
import org.opends.server.tools.LDAPConnectionException;
+import org.opends.server.types.LDAPException;
import org.opends.messages.Message;
-import static org.opends.messages.ToolMessages.ERR_LDAP_CONN_CANNOT_CONNECT;
+import static org.opends.messages.ToolMessages.*;
import java.io.PrintStream;
+import java.io.IOException;
/**
* Base class for tools that are capable of operating either by running
@@ -61,24 +63,38 @@
boolean initializeServer,
PrintStream out, PrintStream err) {
int ret;
+ String taskId;
if (argParser.isLdapOperation())
{
try {
LDAPConnection conn = argParser.connect(out, err);
- TaskSchedulingClient tc = new TaskSchedulingClient(conn);
- ret = tc.schedule(this, out, err);
+ TaskClient tc = new TaskClient(conn);
+ taskId = tc.schedule(this);
+ out.println(wrapText(INFO_TASK_TOOL_TASK_SCHEDULED.get(taskId),
+ MAX_LINE_WIDTH));
+ ret = 0;
} catch (LDAPConnectionException e) {
Message message = ERR_LDAP_CONN_CANNOT_CONNECT.get(e.getMessage());
if (err != null) err.println(wrapText(message, MAX_LINE_WIDTH));
- ret = LDAPResultCode.CLIENT_SIDE_CONNECT_ERROR;
+ ret = 1;
} catch (ArgumentException e) {
Message message = e.getMessageObject();
if (err != null) err.println(wrapText(message, MAX_LINE_WIDTH));
- ret = LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
+ ret = 1;
+ } catch (IOException ioe) {
+ Message message = ERR_TASK_TOOL_IO_ERROR.get(String.valueOf(ioe));
+ if (err != null) err.println(wrapText(message, MAX_LINE_WIDTH));
+ ret = 1;
+ } catch (ASN1Exception ae) {
+ Message message = ERR_TASK_TOOL_DECODE_ERROR.get(ae.getMessage());
+ if (err != null) err.println(wrapText(message, MAX_LINE_WIDTH));
+ ret = 1;
+ } catch (LDAPException le) {
+ Message message = ERR_TASK_TOOL_DECODE_ERROR.get(le.getMessage());
+ if (err != null) err.println(wrapText(message, MAX_LINE_WIDTH));
+ ret = 1;
}
- }
- else
- {
+ } else {
ret = processLocal(initializeServer, out, err);
}
return ret;
diff --git a/opends/src/server/org/opends/server/util/StaticUtils.java b/opends/src/server/org/opends/server/util/StaticUtils.java
index 2976d40..adb34a6 100644
--- a/opends/src/server/org/opends/server/util/StaticUtils.java
+++ b/opends/src/server/org/opends/server/util/StaticUtils.java
@@ -29,6 +29,8 @@
import static org.opends.messages.UtilityMessages.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.util.ServerConstants.*;
+import org.opends.server.util.args.ArgumentException;
+import org.opends.server.util.args.Argument;
import java.io.BufferedReader;
import java.io.File;
@@ -50,6 +52,7 @@
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
import org.opends.messages.MessageDescriptor;
+import org.opends.messages.ToolMessages;
import org.opends.server.core.DirectoryServer;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.Attribute;
@@ -3771,79 +3774,65 @@
String padding = pb.toString();
StringBuilder buffer = new StringBuilder();
- StringTokenizer lineTokenizer = new StringTokenizer(text, "\r\n", true);
- while (lineTokenizer.hasMoreTokens())
- {
- String line = lineTokenizer.nextToken();
- if (line.equals("\r") || line.equals("\n"))
+ if (text != null) {
+ StringTokenizer lineTokenizer = new StringTokenizer(text, "\r\n", true);
+ while (lineTokenizer.hasMoreTokens())
{
- // It's an end-of-line character, so append it as-is.
- buffer.append(line);
- }
- else if (line.length() < width)
- {
- // The line fits in the specified width, so append it as-is.
- buffer.append(padding);
- buffer.append(line);
- }
- else
- {
- // The line doesn't fit in the specified width, so it needs to be
- // wrapped. Do so at space boundaries.
- StringBuilder lineBuffer = new StringBuilder();
- StringBuilder delimBuffer = new StringBuilder();
- StringTokenizer wordTokenizer = new StringTokenizer(line, " ", true);
- while (wordTokenizer.hasMoreTokens())
+ String line = lineTokenizer.nextToken();
+ if (line.equals("\r") || line.equals("\n"))
{
- String word = wordTokenizer.nextToken();
- if (word.equals(" "))
+ // It's an end-of-line character, so append it as-is.
+ buffer.append(line);
+ }
+ else if (line.length() < width)
+ {
+ // The line fits in the specified width, so append it as-is.
+ buffer.append(padding);
+ buffer.append(line);
+ }
+ else
+ {
+ // The line doesn't fit in the specified width, so it needs to be
+ // wrapped. Do so at space boundaries.
+ StringBuilder lineBuffer = new StringBuilder();
+ StringBuilder delimBuffer = new StringBuilder();
+ StringTokenizer wordTokenizer = new StringTokenizer(line, " ", true);
+ while (wordTokenizer.hasMoreTokens())
{
- // It's a space, so add it to the delim buffer only if the line
- // buffer is not empty.
- if (lineBuffer.length() > 0)
+ String word = wordTokenizer.nextToken();
+ if (word.equals(" "))
{
- delimBuffer.append(word);
- }
- }
- else if (word.length() > width)
- {
- // This is a long word that can't be wrapped, so we'll just have to
- // make do.
- if (lineBuffer.length() > 0)
- {
- buffer.append(padding);
- buffer.append(lineBuffer);
- buffer.append(EOL);
- lineBuffer = new StringBuilder();
- }
- buffer.append(padding);
- buffer.append(word);
-
- if (wordTokenizer.hasMoreTokens())
- {
- // The next token must be a space, so remove it. If there are
- // still more tokens after that, then append an EOL.
- wordTokenizer.nextToken();
- if (wordTokenizer.hasMoreTokens())
+ // It's a space, so add it to the delim buffer only if the line
+ // buffer is not empty.
+ if (lineBuffer.length() > 0)
{
- buffer.append(EOL);
+ delimBuffer.append(word);
}
}
+ else if (word.length() > width)
+ {
+ // This is a long word that can't be wrapped, so we'll just have
+ // to make do.
+ if (lineBuffer.length() > 0)
+ {
+ buffer.append(padding);
+ buffer.append(lineBuffer);
+ buffer.append(EOL);
+ lineBuffer = new StringBuilder();
+ }
+ buffer.append(padding);
+ buffer.append(word);
- if (delimBuffer.length() > 0)
- {
- delimBuffer = new StringBuilder();
- }
- }
- else
- {
- // It's not a space, so see if we can fit it on the curent line.
- int newLineLength = lineBuffer.length() + delimBuffer.length() +
- word.length();
- if (newLineLength < width)
- {
- // It does fit on the line, so add it.
- lineBuffer.append(delimBuffer).append(word);
+ if (wordTokenizer.hasMoreTokens())
+ {
+ // The next token must be a space, so remove it. If there are
+ // still more tokens after that, then append an EOL.
+ wordTokenizer.nextToken();
+ if (wordTokenizer.hasMoreTokens())
+ {
+ buffer.append(EOL);
+ }
+ }
if (delimBuffer.length() > 0)
{
@@ -3852,30 +3841,45 @@
}
else
{
- // It doesn't fit on the line, so end the current line and start
- // a new one.
- buffer.append(padding);
- buffer.append(lineBuffer);
- buffer.append(EOL);
-
- lineBuffer = new StringBuilder();
- lineBuffer.append(word);
-
- if (delimBuffer.length() > 0)
+ // It's not a space, so see if we can fit it on the curent line.
+ int newLineLength = lineBuffer.length() + delimBuffer.length() +
+ word.length();
+ if (newLineLength < width)
{
- delimBuffer = new StringBuilder();
+ // It does fit on the line, so add it.
+ lineBuffer.append(delimBuffer).append(word);
+
+ if (delimBuffer.length() > 0)
+ {
+ delimBuffer = new StringBuilder();
+ }
+ }
+ else
+ {
+ // It doesn't fit on the line, so end the current line and start
+ // a new one.
+ buffer.append(padding);
+ buffer.append(lineBuffer);
+ buffer.append(EOL);
+
+ lineBuffer = new StringBuilder();
+ lineBuffer.append(word);
+
+ if (delimBuffer.length() > 0)
+ {
+ delimBuffer = new StringBuilder();
+ }
}
}
}
- }
- // If there's anything left in the line buffer, then add it to the
- // final buffer.
- buffer.append(padding);
- buffer.append(lineBuffer);
+ // If there's anything left in the line buffer, then add it to the
+ // final buffer.
+ buffer.append(padding);
+ buffer.append(lineBuffer);
+ }
}
}
-
return buffer.toString();
}
@@ -3909,5 +3913,32 @@
return exitCode;
}
}
+
+ /**
+ * Checks that no more that one of a set of arguments is present. This
+ * utility should be used after argument parser has parsed a set of
+ * arguments.
+ *
+ * @param args to test for the presence of more than one
+ * @throws ArgumentException if more than one of <code>args</code> is
+ * present and containing an error message identifying the
+ * arguments in violation
+ */
+ public static void checkOnlyOneArgPresent(Argument... args)
+ throws ArgumentException
+ {
+ if (args != null) {
+ for (Argument arg : args) {
+ for (Argument otherArg : args) {
+ if (arg != otherArg && arg.isPresent() && otherArg.isPresent()) {
+ throw new ArgumentException(
+ ToolMessages.ERR_INCOMPATIBLE_ARGUMENTS.get(
+ arg.getName(), otherArg.getName()));
+ }
+ }
+ }
+ }
+ }
+
}
diff --git a/opends/src/server/org/opends/server/util/args/ArgumentParser.java b/opends/src/server/org/opends/server/util/args/ArgumentParser.java
index fd230c5..63ea8ab 100644
--- a/opends/src/server/org/opends/server/util/args/ArgumentParser.java
+++ b/opends/src/server/org/opends/server/util/args/ArgumentParser.java
@@ -1004,22 +1004,22 @@
String scriptName = System.getProperty(PROPERTY_SCRIPT_NAME);
if ((scriptName == null) || (scriptName.length() == 0))
{
- buffer.append("Usage: java ");
+ buffer.append("Usage: java "); // TODO: i18n
buffer.append(mainClassName);
}
else
{
- buffer.append("Usage: ");
+ buffer.append("Usage: "); // TODO: i18n
buffer.append(scriptName);
}
- buffer.append(" {options}");
+ buffer.append(" {options}"); // TODO: i18n
if (allowsTrailingArguments)
{
if (trailingArgsDisplayName == null)
{
- buffer.append(" {trailing-arguments}");
+ buffer.append(" {trailing-arguments}"); // TODO: i18n
}
else
{
@@ -1075,6 +1075,22 @@
/**
+ * Retrieves a message containing usage information based on the defined
+ * arguments.
+ *
+ * @return A string containing usage information based on the defined
+ * arguments.
+ */
+ public Message getUsageMessage()
+ {
+ StringBuilder buffer = new StringBuilder();
+ getUsage(buffer);
+
+ // TODO: rework getUsage(OutputStream) to work with messages framework
+ return Message.raw(buffer.toString());
+ }
+
+ /**
* Retrieves a string containing usage information based on the defined
* arguments.
*
diff --git a/opends/src/server/org/opends/server/util/args/LDAPConnectionArgumentParser.java b/opends/src/server/org/opends/server/util/args/LDAPConnectionArgumentParser.java
index 4444905..5482cc3 100644
--- a/opends/src/server/org/opends/server/util/args/LDAPConnectionArgumentParser.java
+++ b/opends/src/server/org/opends/server/util/args/LDAPConnectionArgumentParser.java
@@ -34,11 +34,13 @@
import org.opends.server.tools.SSLConnectionFactory;
import org.opends.server.tools.SSLConnectionException;
import org.opends.server.tools.LDAPConnectionException;
-import static org.opends.server.tools.ToolConstants.*;
import static org.opends.server.util.ServerConstants.MAX_LINE_WIDTH;
import static org.opends.server.util.StaticUtils.wrapText;
+import org.opends.server.util.cli.LDAPConnectionConsoleInteraction;
+import org.opends.server.admin.client.cli.SecureConnectionCliArgs;
import java.util.LinkedList;
+import java.util.LinkedHashSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.io.PrintStream;
@@ -48,53 +50,7 @@
*/
public class LDAPConnectionArgumentParser extends ArgumentParser {
- /** Argument indicating whether all SSL certs will be trusted. */
- protected BooleanArgument trustAll;
-
- /** Argument indicating whether or not to use SSL. */
- protected BooleanArgument useSSL;
-
- /** Argument indicating whether or not to use StartTLS. */
- protected BooleanArgument useStartTLS;
-
- /** Argument indicating location of a bind password file. */
- protected FileBasedArgument bindPWFile;
-
- /** Argument indicating the location of the keystore password file. */
- protected FileBasedArgument keyStorePWFile;
-
- /** Argument indicating the location of the trust store password file. */
- protected FileBasedArgument trustStorePWFile;
-
- /** Argument indicating the port of the directory server. */
- protected IntegerArgument port;
-
- /** Argument indicating the DN of the user with which to bind. */
- protected StringArgument bindDN;
-
- /** Argument indicating the password of the user with which to bind. */
- protected StringArgument bindPW;
-
- /** Argument indicating the nickname of the certificate to use. */
- protected StringArgument certNickname;
-
- /** Argument indicating the hostname of the directory server. */
- protected StringArgument host;
-
- /** Argument indicating the location of the keystore file. */
- protected StringArgument keyStoreFile;
-
- /** Argument indicating the password fo the keystore. */
- protected StringArgument keyStorePW;
-
- /** Argument indicating a SASL option. */
- protected StringArgument saslOption;
-
- /** Argument indicating the location of the trust store file. */
- protected StringArgument trustStoreFile;
-
- /** Argument indicating the password of the trust store. */
- protected StringArgument trustStorePW;
+ private SecureConnectionCliArgs args;
/**
* Creates a new instance of this argument parser with no arguments.
@@ -169,7 +125,9 @@
* false otherwise
*/
public boolean isLdapOperation() {
- return host.isPresent() || port.isPresent() || bindDN.isPresent();
+ return args.hostNameArg.isPresent() ||
+ args.portArg.isPresent() ||
+ args.bindDnArg.isPresent();
}
/**
@@ -188,13 +146,36 @@
public LDAPConnection connect(PrintStream out, PrintStream err)
throws LDAPConnectionException, ArgumentException
{
+ return connect(this.args, out, err);
+ }
+
+
+ /**
+ * Creates a new LDAPConnection and invokes a connect operation using
+ * information provided in the parsed set of arguments that were provided
+ * by the user.
+ *
+ * @param args with which to connect
+ * @param out stream to write messages
+ * @param err stream to write messages
+ * @return LDAPConnection created by this class from parsed arguments
+ * @throws LDAPConnectionException if there was a problem connecting
+ * to the server indicated by the input arguments
+ * @throws ArgumentException if there was a problem processing the input
+ * arguments
+ */
+ private LDAPConnection connect(SecureConnectionCliArgs args,
+ PrintStream out, PrintStream err)
+ throws LDAPConnectionException, ArgumentException
+ {
// If both a bind password and bind password file were provided, then return
// an error.
- if (bindPW.isPresent() && bindPWFile.isPresent())
+ if (args.bindPasswordArg.isPresent() &&
+ args.bindPasswordFileArg.isPresent())
{
Message message = ERR_LDAP_CONN_MUTUALLY_EXCLUSIVE_ARGUMENTS.get(
- bindPW.getLongIdentifier(),
- bindPWFile.getLongIdentifier());
+ args.bindPasswordArg.getLongIdentifier(),
+ args.bindPasswordFileArg.getLongIdentifier());
err.println(wrapText(message, MAX_LINE_WIDTH));
throw new ArgumentException(message);
}
@@ -202,22 +183,24 @@
// If both a key store password and key store password file were provided,
// then return an error.
- if (keyStorePW.isPresent() && keyStorePWFile.isPresent())
+ if (args.keyStorePasswordArg.isPresent() &&
+ args.keyStorePasswordFileArg.isPresent())
{
Message message = ERR_LDAP_CONN_MUTUALLY_EXCLUSIVE_ARGUMENTS.get(
- keyStorePW.getLongIdentifier(),
- keyStorePWFile.getLongIdentifier());
+ args.keyStorePasswordArg.getLongIdentifier(),
+ args.keyStorePasswordFileArg.getLongIdentifier());
throw new ArgumentException(message);
}
// If both a trust store password and trust store password file were
// provided, then return an error.
- if (trustStorePW.isPresent() && trustStorePWFile.isPresent())
+ if (args.trustStorePasswordArg.isPresent() &&
+ args.trustStorePasswordFileArg.isPresent())
{
Message message = ERR_LDAP_CONN_MUTUALLY_EXCLUSIVE_ARGUMENTS.get(
- trustStorePW.getLongIdentifier(),
- trustStorePWFile.getLongIdentifier());
+ args.trustStorePasswordArg.getLongIdentifier(),
+ args.trustStorePasswordFileArg.getLongIdentifier());
err.println(wrapText(message, MAX_LINE_WIDTH));
throw new ArgumentException(message);
}
@@ -231,13 +214,13 @@
// See if we should use SSL or StartTLS when establishing the connection.
// If so, then make sure only one of them was specified.
- if (useSSL.isPresent())
+ if (args.useSSLArg.isPresent())
{
- if (useStartTLS.isPresent())
+ if (args.useStartTLSArg.isPresent())
{
Message message = ERR_LDAP_CONN_MUTUALLY_EXCLUSIVE_ARGUMENTS.get(
- useSSL.getLongIdentifier(),
- useStartTLS.getLongIdentifier());
+ args.useSSLArg.getLongIdentifier(),
+ args.useSSLArg.getLongIdentifier());
err.println(wrapText(message, MAX_LINE_WIDTH));
throw new ArgumentException(message);
}
@@ -246,7 +229,7 @@
connectionOptions.setUseSSL(true);
}
}
- else if (useStartTLS.isPresent())
+ else if (args.useStartTLSArg.isPresent())
{
connectionOptions.setStartTLS(true);
}
@@ -254,14 +237,14 @@
// If we should blindly trust any certificate, then install the appropriate
// SSL connection factory.
- if (useSSL.isPresent() || useStartTLS.isPresent())
+ if (args.useSSLArg.isPresent() || args.useStartTLSArg.isPresent())
{
try
{
String clientAlias;
- if (certNickname.isPresent())
+ if (args.certNicknameArg.isPresent())
{
- clientAlias = certNickname.getValue();
+ clientAlias = args.certNicknameArg.getValue();
}
else
{
@@ -269,10 +252,12 @@
}
SSLConnectionFactory sslConnectionFactory = new SSLConnectionFactory();
- sslConnectionFactory.init(trustAll.isPresent(), keyStoreFile.getValue(),
- keyStorePW.getValue(), clientAlias,
- trustStoreFile.getValue(),
- trustStorePW.getValue());
+ sslConnectionFactory.init(args.trustAllArg.isPresent(),
+ args.keyStorePathArg.getValue(),
+ args.keyStorePasswordArg.getValue(),
+ clientAlias,
+ args.trustStorePathArg.getValue(),
+ args.trustStorePasswordArg.getValue());
connectionOptions.setSSLConnectionFactory(sslConnectionFactory);
}
@@ -287,12 +272,12 @@
// If one or more SASL options were provided, then make sure that one of
// them was "mech" and specified a valid SASL mechanism.
- if (saslOption.isPresent())
+ if (args.saslOptionArg.isPresent())
{
String mechanism = null;
LinkedList<String> options = new LinkedList<String>();
- for (String s : saslOption.getValues())
+ for (String s : args.saslOptionArg.getValues())
{
int equalPos = s.indexOf('=');
if (equalPos <= 0)
@@ -330,155 +315,100 @@
connectionOptions.addSASLProperty(option);
}
}
+ return connect(
+ args.hostNameArg.getValue(),
+ args.portArg.getIntValue(),
+ args.bindDnArg.getValue(),
+ args.bindPasswordArg.getValue(),
+ connectionOptions, out, err);
+ }
+ /**
+ * Creates a connection using a console interaction that will be used
+ * to potientially interact with the user to prompt for necessary
+ * information for establishing the connection.
+ *
+ * @param ui user interaction for prompting the user
+ * @param out stream to write messages
+ * @param err stream to write messages
+ * @return LDAPConnection created by this class from parsed arguments
+ * @throws LDAPConnectionException if there was a problem connecting
+ * to the server indicated by the input arguments
+ */
+ public LDAPConnection connect(LDAPConnectionConsoleInteraction ui,
+ PrintStream out, PrintStream err)
+ throws LDAPConnectionException
+ {
+ LDAPConnection connection = null;
+ try {
+ ui.run();
+ LDAPConnectionOptions options = new LDAPConnectionOptions();
+ options.setVersionNumber(3);
+ connection = connect(
+ ui.getHostName(),
+ ui.getPortNumber(),
+ ui.getBindDN(),
+ ui.getBindPassword(),
+ ui.populateLDAPOptions(options), out, err);
+ } catch (ArgumentException ae) {
+ err.println(ae.getMessageObject());
+ }
+ return connection;
+ }
+
+
+ /**
+ * Creates a connection from information provided.
+ *
+ * @param host of the server
+ * @param port of the server
+ * @param bindDN with which to connect
+ * @param bindPw with which to connect
+ * @param options with which to connect
+ * @param out stream to write messages
+ * @param err stream to write messages
+ * @return LDAPConnection created by this class from parsed arguments
+ * @throws LDAPConnectionException if there was a problem connecting
+ * to the server indicated by the input arguments
+ */
+ public LDAPConnection connect(String host, int port,
+ String bindDN, String bindPw,
+ LDAPConnectionOptions options,
+ PrintStream out,
+ PrintStream err)
+ throws LDAPConnectionException
+ {
// Attempt to connect and authenticate to the Directory Server.
AtomicInteger nextMessageID = new AtomicInteger(1);
LDAPConnection connection = new LDAPConnection(
- host.getValue(), port.getIntValue(),
- connectionOptions, out, err);
+ host, port, options, out, err);
- connection.connectToHost(bindDN.getValue(), bindPW.getValue(),
- nextMessageID);
+ connection.connectToHost(bindDN, bindPw, nextMessageID);
return connection;
}
+ /**
+ * Gets the arguments associated with this parser.
+ *
+ * @return arguments for this parser.
+ */
+ public SecureConnectionCliArgs getArguments() {
+ return args;
+ }
+
private void addLdapConnectionArguments() {
-
- try
- {
- host = new StringArgument(
- "host", OPTION_SHORT_HOST,
- OPTION_LONG_HOST, false, false, true,
- OPTION_VALUE_HOST, "127.0.0.1", null,
- INFO_LDAP_CONN_DESCRIPTION_HOST.get());
- addArgument(host);
-
- port = new IntegerArgument(
- "port", OPTION_SHORT_PORT,
- OPTION_LONG_PORT, false, false, true,
- OPTION_VALUE_PORT, 389, null, true, 1,
- true, 65535, INFO_LDAP_CONN_DESCRIPTION_PORT.get());
- addArgument(port);
-
- useSSL = new BooleanArgument(
- "usessl", OPTION_SHORT_USE_SSL,
- OPTION_LONG_USE_SSL,
- INFO_LDAP_CONN_DESCRIPTION_USESSL.get());
- addArgument(useSSL);
-
- useStartTLS = new BooleanArgument(
- "usestarttls", OPTION_SHORT_START_TLS,
- OPTION_LONG_START_TLS,
- INFO_LDAP_CONN_DESCRIPTION_USESTARTTLS.get());
- addArgument(useStartTLS);
-
- bindDN = new StringArgument(
- "binddn", OPTION_SHORT_BINDDN,
- OPTION_LONG_BINDDN, false, false, true,
- OPTION_VALUE_BINDDN, null, null,
- INFO_LDAP_CONN_DESCRIPTION_BINDDN.get());
- addArgument(bindDN);
-
- bindPW = new StringArgument(
- "bindpw", OPTION_SHORT_BINDPWD,
- OPTION_LONG_BINDPWD, false, false,
- true,
- OPTION_VALUE_BINDPWD, null, null,
- INFO_LDAP_CONN_DESCRIPTION_BINDPW.get());
- addArgument(bindPW);
-
- bindPWFile = new FileBasedArgument(
- "bindpwfile",
- OPTION_SHORT_BINDPWD_FILE,
- OPTION_LONG_BINDPWD_FILE,
- false, false,
- OPTION_VALUE_BINDPWD_FILE,
- null, null,
- INFO_LDAP_CONN_DESCRIPTION_BINDPWFILE.get());
- addArgument(bindPWFile);
-
- saslOption = new StringArgument(
- "sasloption", OPTION_SHORT_SASLOPTION,
- OPTION_LONG_SASLOPTION, false,
- true, true,
- OPTION_VALUE_SASLOPTION, null, null,
- INFO_LDAP_CONN_DESCRIPTION_SASLOPTIONS.get());
- addArgument(saslOption);
-
- trustAll = new BooleanArgument(
- "trustall", 'X', "trustAll",
- INFO_LDAP_CONN_DESCRIPTION_TRUST_ALL.get());
- addArgument(trustAll);
-
- keyStoreFile = new StringArgument(
- "keystorefile",
- OPTION_SHORT_KEYSTOREPATH,
- OPTION_LONG_KEYSTOREPATH,
- false, false, true,
- OPTION_VALUE_KEYSTOREPATH,
- null, null,
- INFO_LDAP_CONN_DESCRIPTION_KSFILE.get());
- addArgument(keyStoreFile);
-
- keyStorePW = new StringArgument(
- "keystorepw", OPTION_SHORT_KEYSTORE_PWD,
- OPTION_LONG_KEYSTORE_PWD,
- false, false, true,
- OPTION_VALUE_KEYSTORE_PWD,
- null, null,
- INFO_LDAP_CONN_DESCRIPTION_KSPW.get());
- addArgument(keyStorePW);
-
- keyStorePWFile = new FileBasedArgument(
- "keystorepwfile",
- OPTION_SHORT_KEYSTORE_PWD_FILE,
- OPTION_LONG_KEYSTORE_PWD_FILE,
- false, false,
- OPTION_VALUE_KEYSTORE_PWD_FILE,
- null, null,
- INFO_LDAP_CONN_DESCRIPTION_KSPWFILE.get());
- addArgument(keyStorePWFile);
-
- certNickname = new StringArgument(
- "certnickname", 'N', "certNickname",
- false, false, true, "{nickname}", null,
- null, INFO_DESCRIPTION_CERT_NICKNAME.get());
- addArgument(certNickname);
-
- trustStoreFile = new StringArgument(
- "truststorefile",
- OPTION_SHORT_TRUSTSTOREPATH,
- OPTION_LONG_TRUSTSTOREPATH,
- false, false, true,
- OPTION_VALUE_TRUSTSTOREPATH,
- null, null,
- INFO_LDAP_CONN_DESCRIPTION_TSFILE.get());
- addArgument(trustStoreFile);
-
- trustStorePW = new StringArgument(
- "truststorepw", 'T',
- OPTION_LONG_TRUSTSTORE_PWD,
- false, false,
- true, OPTION_VALUE_TRUSTSTORE_PWD, null,
- null, INFO_LDAP_CONN_DESCRIPTION_TSPW.get());
- addArgument(trustStorePW);
-
- trustStorePWFile = new FileBasedArgument(
- "truststorepwfile",
- OPTION_SHORT_TRUSTSTORE_PWD_FILE,
- OPTION_LONG_TRUSTSTORE_PWD_FILE,
- false, false,
- OPTION_VALUE_TRUSTSTORE_PWD_FILE, null, null,
- INFO_LDAP_CONN_DESCRIPTION_TSPWFILE.get());
- addArgument(trustStorePWFile);
-
+ args = new SecureConnectionCliArgs();
+ try {
+ LinkedHashSet<Argument> argSet = args.createGlobalArguments();
+ for (Argument arg : argSet) {
+ addArgument(arg);
+ }
}
- catch (ArgumentException ae)
- {
- // Should never happen
+ catch (ArgumentException ae) {
+ ae.printStackTrace(); // Should never happen
}
}
diff --git a/opends/src/server/org/opends/server/util/cli/ConsoleApplication.java b/opends/src/server/org/opends/server/util/cli/ConsoleApplication.java
index 0033045..4b9b23c 100644
--- a/opends/src/server/org/opends/server/util/cli/ConsoleApplication.java
+++ b/opends/src/server/org/opends/server/util/cli/ConsoleApplication.java
@@ -352,6 +352,16 @@
}
+ /**
+ * Displays a message to the error stream.
+ *
+ * @param msg
+ * The message.
+ */
+ public final void print(Message msg) {
+ err.print(wrapText(msg, MAX_LINE_WIDTH));
+ }
+
/**
* Displays a message to the error stream indented by the specified
diff --git a/opends/src/server/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java b/opends/src/server/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java
index ce9bce7..993ddbd 100644
--- a/opends/src/server/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java
+++ b/opends/src/server/org/opends/server/util/cli/LDAPConnectionConsoleInteraction.java
@@ -31,6 +31,7 @@
import static org.opends.messages.UtilityMessages.*;
import static org.opends.messages.ToolMessages.INFO_LDAPAUTH_PASSWORD_PROMPT;
import org.opends.server.tools.dsconfig.ArgumentExceptionFactory;
+import org.opends.server.tools.LDAPConnectionOptions;
import org.opends.server.admin.client.cli.SecureConnectionCliArgs;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.SelectableCertificateKeyManager;
@@ -1316,4 +1317,23 @@
}
}
+ /**
+ * Populates an a set of LDAP options with state from this interaction.
+ *
+ * @param options existing set of options; may be null in which case this
+ * method will create a new set of <code>LDAPConnectionOptions</code>
+ * to be returned
+ * @return used during this interaction
+ */
+ public LDAPConnectionOptions populateLDAPOptions(
+ LDAPConnectionOptions options)
+ {
+ if (options == null) {
+ options = new LDAPConnectionOptions();
+ }
+ options.setUseSSL(this.useSSL);
+ options.setStartTLS(this.useStartTLS);
+ return options;
+ }
+
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/DummyTask.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/DummyTask.java
index 2442335..6f8b98b 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/DummyTask.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/tasks/DummyTask.java
@@ -54,7 +54,12 @@
// the task gets interrupted.
private volatile TaskState interruptedState;
-
+ /**
+ * {@inheritDoc}
+ */
+ public Message getDisplayName() {
+ return Message.raw("Dummy");
+ }
/**
* {@inheritDoc}
--
Gitblit v1.10.0