/*
|
* 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 legal-notices/CDDLv1_0.txt
|
* or http://forgerock.org/license/CDDLv1.0.html.
|
* 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 legal-notices/CDDLv1_0.txt.
|
* 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
|
*
|
*
|
* Copyright 2010 Sun Microsystems, Inc.
|
* Portions Copyright 2014 ForgeRock AS
|
*/
|
package org.opends.server.admin.client.cli;
|
|
import static org.opends.messages.ToolMessages.*;
|
import static org.opends.server.tools.ToolConstants.*;
|
|
import java.text.ParseException;
|
import java.util.Collections;
|
import java.util.Date;
|
import java.util.EnumSet;
|
import java.util.LinkedList;
|
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.StringArgument;
|
import com.forgerock.opendj.cli.CLIException;
|
|
/**
|
* 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 = new StringArgument(OPTION_LONG_START_DATETIME,
|
OPTION_SHORT_START_DATETIME, OPTION_LONG_START_DATETIME, false, false,
|
true, INFO_START_DATETIME_PLACEHOLDER.get(), null, null,
|
INFO_DESCRIPTION_START_DATETIME.get());
|
|
recurringArg = new StringArgument(OPTION_LONG_RECURRING_TASK,
|
OPTION_SHORT_RECURRING_TASK, OPTION_LONG_RECURRING_TASK, false, false,
|
true, INFO_RECURRING_TASK_PLACEHOLDER.get(), null, null,
|
INFO_DESCRIPTION_RECURRING_TASK.get());
|
|
completionNotificationArg = new StringArgument(
|
OPTION_LONG_COMPLETION_NOTIFICATION_EMAIL,
|
OPTION_SHORT_COMPLETION_NOTIFICATION_EMAIL,
|
OPTION_LONG_COMPLETION_NOTIFICATION_EMAIL, false, true, true,
|
INFO_EMAIL_ADDRESS_PLACEHOLDER.get(), null, null,
|
INFO_DESCRIPTION_TASK_COMPLETION_NOTIFICATION.get());
|
|
errorNotificationArg = new StringArgument(
|
OPTION_LONG_ERROR_NOTIFICATION_EMAIL,
|
OPTION_SHORT_ERROR_NOTIFICATION_EMAIL,
|
OPTION_LONG_ERROR_NOTIFICATION_EMAIL, false, true, true,
|
INFO_EMAIL_ADDRESS_PLACEHOLDER.get(), null, null,
|
INFO_DESCRIPTION_TASK_ERROR_NOTIFICATION.get());
|
|
dependencyArg = new StringArgument(OPTION_LONG_DEPENDENCY,
|
OPTION_SHORT_DEPENDENCY, OPTION_LONG_DEPENDENCY, false, true, true,
|
INFO_TASK_ID_PLACEHOLDER.get(), null, null,
|
INFO_DESCRIPTION_TASK_DEPENDENCY_ID.get());
|
|
Set<FailedDependencyAction> 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,
|
INFO_ACTION_PLACEHOLDER.get(), null, null,
|
INFO_DESCRIPTION_TASK_FAILED_DEPENDENCY_ACTION.get(
|
Utils.joinAsString(",", fdaValSet),
|
FailedDependencyAction.defaultValue().name()));
|
|
for (Argument arg : getArguments())
|
{
|
arg.setPropertyName(arg.getLongIdentifier());
|
}
|
}
|
|
/**
|
* 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 <code>ArgumentParser.parseArguments</code> has
|
* been called.
|
* <br>
|
* 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 CLIException if there is a problem with one of the values provided
|
* by the user.
|
*/
|
public void validateArgs()
|
throws ArgumentException, CLIException {
|
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 CLIException(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);
|
}
|
}
|
|
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<FailedDependencyAction> fdaValSet =
|
EnumSet.allOf(FailedDependencyAction.class);
|
throw new ArgumentException(ERR_TASKTOOL_INVALID_FDA.get(fda,
|
Utils.joinAsString(",", fdaValSet)));
|
}
|
}
|
}
|
|
/**
|
* Validates arguments related to task scheduling. This should be
|
* called after the <code>ArgumentParser.parseArguments</code> has
|
* been called.
|
* <br>
|
* 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 CLIException if there is a problem with one of the values provided
|
* by the user.
|
*/
|
public void validateArgsIfOffline()
|
throws ArgumentException, CLIException
|
{
|
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.
|
* <br>
|
* 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<String> 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<String> 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<String> getNotifyUponErrorEmailAddresses() {
|
if (errorNotificationArg.isPresent()) {
|
return errorNotificationArg.getValues();
|
} else {
|
return Collections.emptyList();
|
}
|
}
|
}
|