/* * The contents of this file are subject to the terms of the Common Development and * Distribution License (the License). You may not use this file except in compliance with the * License. * * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the * specific language governing permission and limitations under the License. * * When distributing Covered Software, include this CDDL Header Notice in each file and include * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL * Header, with the fields enclosed by brackets [] replaced by your own identifying * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2010 Sun Microsystems, Inc. * Portions Copyright 2014-2016 ForgeRock AS. */ package org.opends.server.admin.client.cli; import static org.opends.messages.ToolMessages.*; import static com.forgerock.opendj.cli.ArgumentConstants.*; import java.text.ParseException; import java.util.Collections; import java.util.Date; import java.util.EnumSet; import java.util.List; import java.util.Set; import org.forgerock.util.Utils; import org.opends.server.backends.task.FailedDependencyAction; import org.opends.server.backends.task.RecurringTask; import org.opends.server.types.DirectoryException; import org.opends.server.util.StaticUtils; import com.forgerock.opendj.cli.Argument; import com.forgerock.opendj.cli.ArgumentException; import com.forgerock.opendj.cli.ReturnCode; import com.forgerock.opendj.cli.StringArgument; import com.forgerock.opendj.cli.ClientException; /** * A class that contains all the arguments related to the task scheduling. * */ public class TaskScheduleArgs { /** * Magic value used to indicate that the user would like to schedule * this operation to run immediately as a task as opposed to running * the operation in the local VM. */ public static final String NOW = "0"; /** * Argument for describing the task's start time. */ public StringArgument startArg; /** * Argument to indicate a recurring task. */ public StringArgument recurringArg; /** * Argument for specifying completion notifications. */ public StringArgument completionNotificationArg; /** * Argument for specifying error notifications. */ public StringArgument errorNotificationArg; /** * Argument for specifying dependency. */ public StringArgument dependencyArg; /** * Argument for specifying a failed dependency action. */ public StringArgument failedDependencyActionArg; /** * Default constructor. */ public TaskScheduleArgs() { try { createTaskArguments(); } catch (ArgumentException ae) { // This is a bug. throw new RuntimeException("Unexpected error: "+ae, ae); } } private void createTaskArguments() throws ArgumentException { startArg = StringArgument.builder(OPTION_LONG_START_DATETIME) .shortIdentifier(OPTION_SHORT_START_DATETIME) .description(INFO_DESCRIPTION_START_DATETIME.get()) .valuePlaceholder(INFO_START_DATETIME_PLACEHOLDER.get()) .buildArgument(); recurringArg = StringArgument.builder(OPTION_LONG_RECURRING_TASK) .shortIdentifier(OPTION_SHORT_RECURRING_TASK) .description(INFO_DESCRIPTION_RECURRING_TASK.get()) .valuePlaceholder(INFO_RECURRING_TASK_PLACEHOLDER.get()) .buildArgument(); completionNotificationArg = StringArgument.builder(OPTION_LONG_COMPLETION_NOTIFICATION_EMAIL) .shortIdentifier(OPTION_SHORT_COMPLETION_NOTIFICATION_EMAIL) .description(INFO_DESCRIPTION_TASK_COMPLETION_NOTIFICATION.get()) .multiValued() .valuePlaceholder(INFO_EMAIL_ADDRESS_PLACEHOLDER.get()) .buildArgument(); errorNotificationArg = StringArgument.builder(OPTION_LONG_ERROR_NOTIFICATION_EMAIL) .shortIdentifier(OPTION_SHORT_ERROR_NOTIFICATION_EMAIL) .description(INFO_DESCRIPTION_TASK_ERROR_NOTIFICATION.get()) .multiValued() .valuePlaceholder(INFO_EMAIL_ADDRESS_PLACEHOLDER.get()) .buildArgument(); dependencyArg = StringArgument.builder(OPTION_LONG_DEPENDENCY) .shortIdentifier(OPTION_SHORT_DEPENDENCY) .description(INFO_DESCRIPTION_TASK_DEPENDENCY_ID.get()) .multiValued() .valuePlaceholder(INFO_TASK_ID_PLACEHOLDER.get()) .buildArgument(); final Set fdaValSet = EnumSet.allOf(FailedDependencyAction.class); failedDependencyActionArg = StringArgument.builder(OPTION_LONG_FAILED_DEPENDENCY_ACTION) .shortIdentifier(OPTION_SHORT_FAILED_DEPENDENCY_ACTION) .description(INFO_DESCRIPTION_TASK_FAILED_DEPENDENCY_ACTION.get( Utils.joinAsString(",", fdaValSet), FailedDependencyAction.defaultValue().name())) .multiValued() .valuePlaceholder(INFO_ACTION_PLACEHOLDER.get()) .buildArgument(); } /** * Returns all the task schedule related arguments. * @return all the task schedule related arguments. */ public Argument[] getArguments() { return new Argument[] {startArg, recurringArg, completionNotificationArg, errorNotificationArg, dependencyArg, failedDependencyActionArg}; } /** * Validates arguments related to task scheduling. This should be * called after the ArgumentParser.parseArguments has * been called. *
* Note that this method does only validation that is not dependent on whether * the operation will be launched as a task or not. If the operation is not * to be launched as a task, the method {@link #validateArgsIfOffline()} * should be called instead of this method. * @throws ArgumentException if there is a problem with the arguments. * @throws ClientException if there is a problem with one of the values provided * by the user. */ public void validateArgs() throws ArgumentException, ClientException { if (startArg.isPresent() && !NOW.equals(startArg.getValue())) { try { Date date = StaticUtils.parseDateTimeString(startArg.getValue()); // Check that the provided date is not previous to the current date. Date currentDate = new Date(System.currentTimeMillis()); if (currentDate.after(date)) { throw new ClientException(ReturnCode.ERROR_USER_DATA, ERR_START_DATETIME_ALREADY_PASSED.get( startArg.getValue())); } } catch (ParseException pe) { throw new ArgumentException(ERR_START_DATETIME_FORMAT.get()); } } if (recurringArg.isPresent()) { try { RecurringTask.parseTaskTab(recurringArg.getValue()); } catch (DirectoryException de) { throw new ArgumentException(ERR_RECURRING_SCHEDULE_FORMAT_ERROR.get( de.getMessageObject()), de); } } checkEmailArgument(completionNotificationArg); checkEmailArgument(errorNotificationArg); 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, Utils.joinAsString(",", fdaValSet))); } } } private void checkEmailArgument(final StringArgument argument) throws ArgumentException { if (argument.isPresent()) { for (final String email : argument.getValues()) { if (!StaticUtils.isEmailAddress(email)) { throw new ArgumentException(ERR_TASKTOOL_INVALID_EMAIL_ADDRESS.get(email, argument.getLongIdentifier())); } } } } /** * Validates arguments related to task scheduling. This should be * called after the ArgumentParser.parseArguments has * been called. *
* This method assumes that the operation is not to be launched as a task. * This method covers all the checks done by {@link #validateArgs()}, so it * is not necessary to call that method if this method is being called. * @throws ArgumentException if there is a problem with the arguments. * @throws ClientException if there is a problem with one of the values provided * by the user. */ public void validateArgsIfOffline() throws ArgumentException, ClientException { Argument[] incompatibleArgs = {startArg, recurringArg, completionNotificationArg, errorNotificationArg, dependencyArg, failedDependencyActionArg}; for (Argument arg : incompatibleArgs) { if (arg.isPresent()) { throw new ArgumentException(ERR_TASKTOOL_OPTIONS_FOR_TASK_ONLY.get( arg.getLongIdentifier())); } } validateArgs(); } /** * Gets the date at which the associated task should be scheduled to start. * * @return date/time at which the task should be scheduled */ public Date getStartDateTime() { Date start = null; // If the start time arg is present parse its value if (startArg != null && startArg.isPresent()) { if (NOW.equals(startArg.getValue())) { start = new Date(); } else { try { start = StaticUtils.parseDateTimeString(startArg.getValue()); } catch (ParseException pe) { // ignore; validated in validateTaskArgs() } } } return start; } /** * Whether the arguments provided by the user, indicate that the task should * be executed immediately. *
* This method assumes that the arguments have already been parsed and * validated. * @return {@code true} if the task must be executed immediately and * {@code false} otherwise. */ public boolean isStartNow() { boolean isStartNow = true; if (startArg != null && startArg.isPresent()) { isStartNow = NOW.equals(startArg.getValue()); } return isStartNow; } /** * Gets the date/time pattern for recurring task schedule. * * @return recurring date/time pattern at which the task * should be scheduled. */ public String getRecurringDateTime() { String pattern = null; // If the recurring task arg is present parse its value if (recurringArg != null && recurringArg.isPresent()) { pattern = recurringArg.getValue(); } return pattern; } /** * Gets a list of task IDs upon which the associated task is dependent. * * @return list of task IDs */ public List getDependencyIds() { if (dependencyArg.isPresent()) { return dependencyArg.getValues(); } else { return Collections.emptyList(); } } /** * Gets the action to take should one of the dependent task fail. * * @return action to take */ public FailedDependencyAction getFailedDependencyAction() { FailedDependencyAction fda = null; if (failedDependencyActionArg.isPresent()) { String fdaString = failedDependencyActionArg.getValue(); fda = FailedDependencyAction.fromString(fdaString); } return fda; } /** * Gets a list of email address to which an email will be sent when this * task completes. * * @return list of email addresses */ public List getNotifyUponCompletionEmailAddresses() { if (completionNotificationArg.isPresent()) { return completionNotificationArg.getValues(); } else { return Collections.emptyList(); } } /** * 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 */ public List getNotifyUponErrorEmailAddresses() { if (errorNotificationArg.isPresent()) { return errorNotificationArg.getValues(); } else { return Collections.emptyList(); } } }