opends/src/messages/messages/tools.properties
@@ -2161,3 +2161,24 @@ INFO_DESCRIPTION_IO_ARGS_1466=Utility Input/Output Options INFO_DESCRIPTION_LDAP_CONNECTION_ARGS_1467=LDAP Connection Options INFO_DESCRIPTION_CONFIG_OPTIONS_ARGS_1468=Configuration Options INFO_DESCRIPTION_TASK_COMPLETION_NOTIFICATION_1469=Specifies the email address \ of a recipient to be notified when the task completes. This option may be \ specified more than once INFO_DESCRIPTION_TASK_ERROR_NOTIFICATION_1470=Specifies the email address \ of a recipient to be notified if an error occurs when this task executes. \ This option may be specified more than once INFO_DESCRIPTION_TASK_DEPENDENCY_ID_1471=Specifies the ID of a task upon which \ this task depends. A task will not start execution until all its \ dependencies have completed execution INFO_DESCRIPTION_TASK_FAILED_DEPENDENCY_ACTION_1472=Action this task will \ take should one if its dependent tasks fail. The value must be one of %s. \ If not specified defaults to %s SEVERE_ERR_TASKTOOL_OPTIONS_FOR_TASK_ONLY_1473=The option %s is only \ applicable when scheduling this operation as a task SEVERE_ERR_TASKTOOL_INVALID_EMAIL_ADDRESS_1474=The value %s for option %s is \ not a valid email address SEVERE_ERR_TASKTOOL_INVALID_FDA_1475=The failed dependency action value %s is \ invalid. The value must be one of %s SEVERE_ERR_TASKTOOL_FDA_WITH_NO_DEPENDENCY_1476=The failed dependency action \ option is to be used in conjunction with one or more dependencies opends/src/server/org/opends/server/backends/task/FailedDependencyAction.java
@@ -27,7 +27,7 @@ package org.opends.server.backends.task; import org.opends.messages.Message; import org.opends.messages.TaskMessages; import static org.opends.messages.TaskMessages.*; /** @@ -41,14 +41,14 @@ * The action that indicates that the dependent task should be processed * anyway. */ PROCESS(TaskMessages.INFO_FAILED_DEPENDENCY_ACTION_PROCESS.get()), PROCESS(INFO_FAILED_DEPENDENCY_ACTION_PROCESS.get()), /** * The action that indicates that the dependent task should be canceled. */ CANCEL(TaskMessages.INFO_FAILED_DEPENDENCY_ACTION_CANCEL.get()), CANCEL(INFO_FAILED_DEPENDENCY_ACTION_CANCEL.get()), @@ -56,9 +56,17 @@ * 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(TaskMessages.INFO_FAILED_DEPENDENCY_ACTION_DISABLE.get()); DISABLE(INFO_FAILED_DEPENDENCY_ACTION_DISABLE.get()); /** * Returns the default action. * * @return the default action */ public static FailedDependencyAction defaultValue() { return CANCEL; } /** * Retrieves the failed dependency action that corresponds to the provided @@ -73,15 +81,21 @@ public static FailedDependencyAction fromString(String s) { String lowerString = s.toLowerCase(); if (lowerString.equals("process")) if (lowerString.equals("process") || lowerString.equals(INFO_FAILED_DEPENDENCY_ACTION_PROCESS.get(). toString().toLowerCase())) { return PROCESS; } else if (lowerString.equals("cancel")) else if (lowerString.equals("cancel") || lowerString.equals(INFO_FAILED_DEPENDENCY_ACTION_CANCEL.get(). toString().toLowerCase())) { return CANCEL; } else if (lowerString.equals("disable")) else if (lowerString.equals("disable") || lowerString.equals(INFO_FAILED_DEPENDENCY_ACTION_DISABLE.get(). toString().toLowerCase())) { return DISABLE; } opends/src/server/org/opends/server/backends/task/Task.java
@@ -351,7 +351,7 @@ failedDependencyAction = FailedDependencyAction.fromString(actionString); if (failedDependencyAction == null) { failedDependencyAction = FailedDependencyAction.CANCEL; failedDependencyAction = FailedDependencyAction.defaultValue(); } } opends/src/server/org/opends/server/tools/RestoreDB.java
@@ -265,7 +265,7 @@ } if (listBackups.isPresent() && argParser.argumentsPresent()) { if (listBackups.isPresent() && argParser.connectionArgumentsPresent()) { Message message = ERR_LDAP_CONN_INCOMPATIBLE_ARGS.get( listBackups.getLongIdentifier()); err.println(wrapText(message, MAX_LINE_WIDTH)); opends/src/server/org/opends/server/tools/ToolConstants.java
@@ -832,5 +832,75 @@ * Long form of option specifying no wrapping of the command-line. */ public static final String OPTION_LONG_DONT_WRAP = "dontWrap"; /** * Long form of email notification upon completion option. */ public static final String OPTION_LONG_COMPLETION_NOTIFICATION_EMAIL = "completionNotify"; /** * Short form of email notification upon completion option. */ public static final Character OPTION_SHORT_COMPLETION_NOTIFICATION_EMAIL = null; /** * Long form of email notification upon error option. */ public static final String OPTION_LONG_ERROR_NOTIFICATION_EMAIL = "errorNotify"; /** * Short form of email notification upon error option. */ public static final Character OPTION_SHORT_ERROR_NOTIFICATION_EMAIL = null; /** * Long form of dependency option. */ public static final String OPTION_LONG_DEPENDENCY = "dependency"; /** * Short form of dependency option. */ public static final Character OPTION_SHORT_DEPENDENCY = null; /** * Long form of failed dependency action option. */ public static final String OPTION_LONG_FAILED_DEPENDENCY_ACTION = "failedDependencyAction"; /** * Short form of failed dependency action option. */ public static final Character OPTION_SHORT_FAILED_DEPENDENCY_ACTION = null; /** * Value placeholder for options taking email addresses. */ public static final String OPTION_VALUE_EMAIL_ADDRESS = "{emailAddress}"; /** * Value placeholder for options taking task IDs. */ public static final String OPTION_VALUE_TASK_ID = "{taskId}"; /** * Value placeholder for options taking actions. */ public static final String OPTION_VALUE_ACTION = "{action}"; } opends/src/server/org/opends/server/tools/tasks/TaskClient.java
@@ -59,6 +59,7 @@ import org.opends.server.types.SearchScope; import static org.opends.server.types.ResultCode.*; import org.opends.server.backends.task.TaskState; import org.opends.server.backends.task.FailedDependencyAction; import static org.opends.server.util.ServerConstants.*; import org.opends.server.util.StaticUtils; @@ -149,6 +150,55 @@ startDateValues)); } // add dependency IDs List<String> dependencyIds = information.getDependencyIds(); if (dependencyIds != null && dependencyIds.size() > 0) { ArrayList<ASN1OctetString> dependencyIdValues = new ArrayList<ASN1OctetString>(dependencyIds.size()); for (String dependencyId : dependencyIds) { dependencyIdValues.add(new ASN1OctetString(dependencyId)); } attributes.add(new LDAPAttribute(ATTR_TASK_DEPENDENCY_IDS, dependencyIdValues)); // add the dependency action FailedDependencyAction fda = information.getFailedDependencyAction(); if (fda == null) { fda = FailedDependencyAction.defaultValue(); } ArrayList<ASN1OctetString> fdaValues = new ArrayList<ASN1OctetString>(1); fdaValues.add(new ASN1OctetString(fda.name())); attributes.add(new LDAPAttribute(ATTR_TASK_FAILED_DEPENDENCY_ACTION, fdaValues)); } // add completion notification email addresses List<String> compNotifEmailAddresss = information.getNotifyUponCompletionEmailAddresses(); if (compNotifEmailAddresss != null && compNotifEmailAddresss.size() > 0) { ArrayList<ASN1OctetString> compNotifEmailAddrValues = new ArrayList<ASN1OctetString>(compNotifEmailAddresss.size()); for (String emailAddr : compNotifEmailAddresss) { compNotifEmailAddrValues.add(new ASN1OctetString(emailAddr)); } attributes.add(new LDAPAttribute(ATTR_TASK_NOTIFY_ON_COMPLETION, compNotifEmailAddrValues)); } // add error notification email addresses List<String> errNotifEmailAddresss = information.getNotifyUponErrorEmailAddresses(); if (errNotifEmailAddresss != null && errNotifEmailAddresss.size() > 0) { ArrayList<ASN1OctetString> errNotifEmailAddrValues = new ArrayList<ASN1OctetString>(errNotifEmailAddresss.size()); for (String emailAddr : errNotifEmailAddresss) { errNotifEmailAddrValues.add(new ASN1OctetString(emailAddr)); } attributes.add(new LDAPAttribute(ATTR_TASK_NOTIFY_ON_ERROR, errNotifEmailAddrValues)); } information.addTaskAttributes(attributes); AddRequestProtocolOp addRequest = new AddRequestProtocolOp(entryDN, opends/src/server/org/opends/server/tools/tasks/TaskScheduleInformation.java
@@ -28,6 +28,7 @@ package org.opends.server.tools.tasks; import org.opends.server.types.RawAttribute; import org.opends.server.backends.task.FailedDependencyAction; import java.util.List; import java.util.Date; @@ -40,6 +41,7 @@ */ public interface TaskScheduleInformation { /** * Adds utility specific attributes to <code>attributes</code> for * population of the entry that is added to the task backend. @@ -48,6 +50,7 @@ */ void addTaskAttributes(List<RawAttribute> attributes); /** * Gets the objectclass used to represent scheduled instances of this * utility in the task backend. @@ -56,6 +59,7 @@ */ String getTaskObjectclass(); /** * Gets the Class that implements the utility to execute. * @@ -63,10 +67,47 @@ */ Class getTaskClass(); /** * Gets the date at which this task should be scheduled to start. * * @return date/time at which the task should be scheduled */ Date getStartDateTime(); /** * Gets a list of task IDs upon which this task is dependent. * * @return list of task IDs */ List<String> getDependencyIds(); /** * Gets the action to take should one of the dependent task fail. * * @return action to take */ FailedDependencyAction getFailedDependencyAction(); /** * Gets a list of email address to which an email will be sent when this * task completes. * * @return list of email addresses */ List<String> getNotifyUponCompletionEmailAddresses(); /** * Gets a list of email address to which an email will be sent if this * task encounters an error during execution. * * @return list of email addresses */ List<String> getNotifyUponErrorEmailAddresses(); } opends/src/server/org/opends/server/tools/tasks/TaskTool.java
@@ -43,6 +43,7 @@ import org.opends.server.types.OpenDsException; import org.opends.server.core.DirectoryServer; import org.opends.server.backends.task.TaskState; import org.opends.server.backends.task.FailedDependencyAction; import org.opends.messages.Message; import static org.opends.messages.ToolMessages.*; @@ -52,6 +53,9 @@ import java.util.Set; import java.util.HashSet; import java.util.List; import java.util.LinkedList; import java.util.EnumSet; import java.util.Collections; import java.io.IOException; /** @@ -77,6 +81,21 @@ // Argument for describing the task's start time StringArgument startArg; // Argument for specifying completion notifications StringArgument completionNotificationArg; // Argument for specifying error notifications StringArgument errorNotificationArg; // Argument for specifying dependency StringArgument dependencyArg; // Argument for specifying a failed dependency action StringArgument failedDependencyActionArg; // Client for interacting with the task backend TaskClient taskClient; /** * Called when this utility should perform its actions locally in this * JVM. @@ -120,6 +139,42 @@ null, null, INFO_DESCRIPTION_START_DATETIME.get()); argParser.addArgument(startArg, taskGroup); completionNotificationArg = new StringArgument( OPTION_LONG_COMPLETION_NOTIFICATION_EMAIL, OPTION_SHORT_COMPLETION_NOTIFICATION_EMAIL, OPTION_LONG_COMPLETION_NOTIFICATION_EMAIL, false, true, true, OPTION_VALUE_EMAIL_ADDRESS, null, null, INFO_DESCRIPTION_TASK_COMPLETION_NOTIFICATION.get()); argParser.addArgument(completionNotificationArg, taskGroup); errorNotificationArg = new StringArgument( OPTION_LONG_ERROR_NOTIFICATION_EMAIL, OPTION_SHORT_ERROR_NOTIFICATION_EMAIL, OPTION_LONG_ERROR_NOTIFICATION_EMAIL, false, true, true, OPTION_VALUE_EMAIL_ADDRESS, null, null, INFO_DESCRIPTION_TASK_ERROR_NOTIFICATION.get()); argParser.addArgument(errorNotificationArg, taskGroup); dependencyArg = new StringArgument( OPTION_LONG_DEPENDENCY, OPTION_SHORT_DEPENDENCY, OPTION_LONG_DEPENDENCY, false, true, true, OPTION_VALUE_TASK_ID, null, null, INFO_DESCRIPTION_TASK_DEPENDENCY_ID.get()); argParser.addArgument(dependencyArg, taskGroup); Set fdaValSet = EnumSet.allOf(FailedDependencyAction.class); failedDependencyActionArg = new StringArgument( OPTION_LONG_FAILED_DEPENDENCY_ACTION, OPTION_SHORT_FAILED_DEPENDENCY_ACTION, OPTION_LONG_FAILED_DEPENDENCY_ACTION, false, true, true, OPTION_VALUE_ACTION, null, null, INFO_DESCRIPTION_TASK_FAILED_DEPENDENCY_ACTION.get( StaticUtils.collectionToString(fdaValSet, ","), FailedDependencyAction.defaultValue().name())); argParser.addArgument(failedDependencyActionArg, taskGroup); } catch (ArgumentException e) { // should never happen } @@ -142,6 +197,60 @@ throw new ArgumentException(ERR_START_DATETIME_FORMAT.get()); } } if (!processAsTask() && completionNotificationArg.isPresent()) { throw new ArgumentException(ERR_TASKTOOL_OPTIONS_FOR_TASK_ONLY.get( completionNotificationArg.getLongIdentifier())); } if (!processAsTask() && errorNotificationArg.isPresent()) { throw new ArgumentException(ERR_TASKTOOL_OPTIONS_FOR_TASK_ONLY.get( errorNotificationArg.getLongIdentifier())); } if (!processAsTask() && dependencyArg.isPresent()) { throw new ArgumentException(ERR_TASKTOOL_OPTIONS_FOR_TASK_ONLY.get( dependencyArg.getLongIdentifier())); } if (!processAsTask() && failedDependencyActionArg.isPresent()) { throw new ArgumentException(ERR_TASKTOOL_OPTIONS_FOR_TASK_ONLY.get( failedDependencyActionArg.getLongIdentifier())); } if (completionNotificationArg.isPresent()) { LinkedList<String> addrs = completionNotificationArg.getValues(); for (String addr : addrs) { if (!StaticUtils.isEmailAddress(addr)) { throw new ArgumentException(ERR_TASKTOOL_INVALID_EMAIL_ADDRESS.get( addr, completionNotificationArg.getLongIdentifier())); } } } if (errorNotificationArg.isPresent()) { LinkedList<String> addrs = errorNotificationArg.getValues(); for (String addr : addrs) { if (!StaticUtils.isEmailAddress(addr)) { throw new ArgumentException(ERR_TASKTOOL_INVALID_EMAIL_ADDRESS.get( addr, errorNotificationArg.getLongIdentifier())); } } } if (failedDependencyActionArg.isPresent()) { if (!dependencyArg.isPresent()) { throw new ArgumentException(ERR_TASKTOOL_FDA_WITH_NO_DEPENDENCY.get()); } String fda = failedDependencyActionArg.getValue(); if (null == FailedDependencyAction.fromString(fda)) { Set fdaValSet = EnumSet.allOf(FailedDependencyAction.class); throw new ArgumentException(ERR_TASKTOOL_INVALID_FDA.get(fda, StaticUtils.collectionToString(fdaValSet, ","))); } } } /** @@ -166,6 +275,51 @@ } /** * {@inheritDoc} */ public List<String> getDependencyIds() { if (dependencyArg.isPresent()) { return dependencyArg.getValues(); } else { return Collections.emptyList(); } } /** * {@inheritDoc} */ public FailedDependencyAction getFailedDependencyAction() { FailedDependencyAction fda = null; if (failedDependencyActionArg.isPresent()) { String fdaString = failedDependencyActionArg.getValue(); fda = FailedDependencyAction.fromString(fdaString); } return fda; } /** * {@inheritDoc} */ public List<String> getNotifyUponCompletionEmailAddresses() { if (completionNotificationArg.isPresent()) { return completionNotificationArg.getValues(); } else { return Collections.emptyList(); } } /** * {@inheritDoc} */ public List<String> getNotifyUponErrorEmailAddresses() { if (errorNotificationArg.isPresent()) { return errorNotificationArg.getValues(); } else { return Collections.emptyList(); } } /** * Either invokes initiates this tool's local action or schedule this * tool using the tasks interface based on user input. * @@ -181,7 +335,7 @@ PrintStream out, PrintStream err) { int ret; if (argParser.argumentsPresent()) if (processAsTask()) { if (initializeServer) { @@ -275,4 +429,8 @@ return ret; } private boolean processAsTask() { return argParser.connectionArgumentsPresent(); } } opends/src/server/org/opends/server/util/StaticUtils.java
@@ -52,6 +52,8 @@ import java.util.StringTokenizer; import java.util.Date; import java.util.TimeZone; import java.util.Collection; import java.util.Iterator; import org.opends.messages.Message; import org.opends.messages.MessageBuilder; @@ -3321,6 +3323,29 @@ } /** * Creates a string representation of the elements in the * <code>collection</code> separated by <code>separator</code>. * * @param collection to print * @param separator to use between elements * * @return String representing the collection */ static public String collectionToString(Collection<?> collection, String separator) { StringBuilder sb = new StringBuilder(); for (Iterator<?> iter = collection.iterator(); iter.hasNext();) { sb.append(iter.next()); if (iter.hasNext()) { sb.append(separator); } } return sb.toString(); } /** * Retrieves an array list containing the contents of the provided array. * * @param stringArray The string array to convert to an array list. @@ -4036,5 +4061,20 @@ return timeStr; } /** * Indicates whether or not a string represents a syntactically correct * email address. * * @param addr to validate * @return boolean where <code>true</code> indicates that the string is a * syntactically correct email address */ public static boolean isEmailAddress(String addr) { // This just does basic syntax checking. Perhaps we // might want to be stricter about this. return addr != null && addr.contains("@") && addr.contains("."); } } opends/src/server/org/opends/server/util/args/LDAPConnectionArgumentParser.java
@@ -134,7 +134,7 @@ * @return true if the user wants to perform a remote operation; * false otherwise */ public boolean argumentsPresent() { public boolean connectionArgumentsPresent() { return args != null && args.argumentsPresent(); }