mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

kenneth_suter
17.27.2007 29be609adb8377a6535926fc33c9f5906a4ec696
This commit is for supporting of task scheduling in the future (right now tasks can only be scheduled to start immediately) for tasks that support scheduling.  Start time is specified by including -t/--startTime along with a date string of format 'YYYYMMDDhhmmss'.

- import-ldif short version of templateFile arg was changed to -A to make way for the use -t as startTime
- date/string formatting and parsing code centralized in StaticUtils for consistency between task scheduling code and exiting StopDS scheduling code
- manage-task -t/--task option was changed to -i/--info
14 files modified
338 ■■■■ changed files
opends/src/messages/messages/tools.properties 10 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/backends/task/Task.java 6 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/BackUpDB.java 8 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/ExportLDIF.java 6 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/ImportLDIF.java 9 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/ManageTasks.java 2 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/RestoreDB.java 6 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/StopDS.java 37 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/ToolConstants.java 16 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/tasks/TaskClient.java 20 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/tasks/TaskEntry.java 7 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/tasks/TaskScheduleInformation.java 7 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/tools/tasks/TaskTool.java 149 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/StaticUtils.java 55 ●●●●● patch | view | raw | blame | history
opends/src/messages/messages/tools.properties
@@ -1901,7 +1901,8 @@
 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_TOOL_TASK_SCHEDULED_1319=Scheduled task %s
INFO_TASK_TOOL_TASK_SCHEDULED_NOW_1319=%s task %s scheduled to start \
  immediately
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 \
@@ -2138,4 +2139,9 @@
  cannot be canceled
SEVERE_ERR_TASK_CLIENT_TASK_STATE_UNKNOWN_1455=State for task '%s' cannot be \
  determined
INFO_DESCRIPTION_START_DATETIME_1456=Indicates the date/time at which the this \
  task will start when scheduled expressed in format 'YYYYMMDDhhmmss'. \
  Omission of this option will cause the task to be for immediate execution
SEVERE_ERR_START_DATETIME_FORMAT_1457=The start date/time must in format \
  'YYYYMMDDhhmmss'
INFO_TASK_TOOL_TASK_SCHEDULED_FUTURE_1458=%s task %s scheduled to start %s
opends/src/server/org/opends/server/backends/task/Task.java
@@ -61,6 +61,7 @@
import org.opends.server.types.Operation;
import org.opends.server.util.EMailMessage;
import org.opends.server.util.TimeThread;
import org.opends.server.util.StaticUtils;
import static org.opends.server.config.ConfigConstants.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -726,10 +727,9 @@
                    ATTR_TASK_ACTUAL_START_TIME);
      }
      SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_GMT_TIME);
      dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
      Date d = new Date(actualStartTime);
      ASN1OctetString s = new ASN1OctetString(dateFormat.format(d));
      String startTimeStr = StaticUtils.formatDateTimeString(d);
      ASN1OctetString s = new ASN1OctetString(startTimeStr);
      LinkedHashSet<AttributeValue> values =
           new LinkedHashSet<AttributeValue>();
opends/src/server/org/opends/server/tools/BackUpDB.java
@@ -177,11 +177,10 @@
    }
    // Create the command-line argument parser for use with this program.
    Message toolDescription = INFO_BACKUPDB_TOOL_DESCRIPTION.get();
    LDAPConnectionArgumentParser argParser =
         new LDAPConnectionArgumentParser("org.opends.server.tools.BackUpDB",
                                          toolDescription,
                                          false);
            createArgParser("org.opends.server.tools.BackUpDB",
                            INFO_BACKUPDB_TOOL_DESCRIPTION.get());
    // Initialize all the command-line argument types and register them with the
    // parser.
@@ -298,6 +297,7 @@
    try
    {
      argParser.parseArguments(args);
      validateTaskArgs();
    }
    catch (ArgumentException ae)
    {
opends/src/server/org/opends/server/tools/ExportLDIF.java
@@ -178,10 +178,9 @@
    }
    // Create the command-line argument parser for use with this program.
    Message toolDescription = INFO_LDIFEXPORT_TOOL_DESCRIPTION.get();
    LDAPConnectionArgumentParser argParser =
         new LDAPConnectionArgumentParser("org.opends.server.tools.ExportLDIF",
                                          toolDescription, false);
            createArgParser("org.opends.server.tools.ExportLDIF",
                            INFO_LDIFEXPORT_TOOL_DESCRIPTION.get());
    // Initialize all the command-line argument types and register them with the
@@ -323,6 +322,7 @@
    try
    {
      argParser.parseArguments(args);
      validateTaskArgs();
    }
    catch (ArgumentException ae)
    {
opends/src/server/org/opends/server/tools/ImportLDIF.java
@@ -199,11 +199,9 @@
    // Create the command-line argument parser for use with this program.
    Message toolDescription = INFO_LDIFIMPORT_TOOL_DESCRIPTION.get();
    LDAPConnectionArgumentParser argParser =
         new LDAPConnectionArgumentParser("org.opends.server.tools.ImportLDIF",
                                          toolDescription, false);
            createArgParser("org.opends.server.tools.ImportLDIF",
                            INFO_LDIFIMPORT_TOOL_DESCRIPTION.get());
    // Initialize all the command-line argument types and register them with the
    // parser.
@@ -236,7 +234,7 @@
      templateFile =
           new StringArgument("templatefile", 't', "templateFile", false, false,
           new StringArgument("templatefile", 'A', "templateFile", false, false,
                              true, "{templateFile}", null, null,
                              INFO_LDIFIMPORT_DESCRIPTION_TEMPLATE_FILE.get());
      argParser.addArgument(templateFile);
@@ -390,6 +388,7 @@
    try
    {
      argParser.parseArguments(args);
      validateTaskArgs();
    }
    catch (ArgumentException ae)
    {
opends/src/server/org/opends/server/tools/ManageTasks.java
@@ -180,7 +180,7 @@
    try {
      task = new StringArgument(
              "task", 't', "task",
              "info", 'i', "info",
              false, true, "{taskID}",
              INFO_TASKINFO_TASK_ARG_DESCRIPTION.get());
      argParser.addArgument(task);
opends/src/server/org/opends/server/tools/RestoreDB.java
@@ -172,10 +172,9 @@
    }
    // Create the command-line argument parser for use with this program.
    Message toolDescription = INFO_RESTOREDB_TOOL_DESCRIPTION.get();
    LDAPConnectionArgumentParser argParser =
         new LDAPConnectionArgumentParser("org.opends.server.tools.RestoreDB",
                                          toolDescription, false);
            createArgParser("org.opends.server.tools.RestoreDB",
                            INFO_RESTOREDB_TOOL_DESCRIPTION.get());
    // Initialize all the command-line argument types and register them with the
@@ -246,6 +245,7 @@
    try
    {
      argParser.parseArguments(args);
      validateTaskArgs();
    }
    catch (ArgumentException ae)
    {
opends/src/server/org/opends/server/tools/StopDS.java
@@ -480,40 +480,15 @@
    if (stopTimeStr.isPresent())
    {
      String timeStr = stopTimeStr.getValue();
      if (timeStr.endsWith("Z"))
      try
      {
        SimpleDateFormat dateFormat =
            new SimpleDateFormat(DATE_FORMAT_GENERALIZED_TIME);
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        dateFormat.setLenient(true);
        try
        {
          stopTime = dateFormat.parse(timeStr);
        }
        catch (Exception e)
        {
          Message message = ERR_STOPDS_CANNOT_DECODE_STOP_TIME.get();
          err.println(wrapText(message, MAX_LINE_WIDTH));
          return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
        }
        stopTime = parseDateTimeString(timeStr);
      }
      else
      catch (Exception e)
      {
        SimpleDateFormat dateFormat =
            new SimpleDateFormat(DATE_FORMAT_COMPACT_LOCAL_TIME);
        dateFormat.setLenient(true);
        try
        {
          stopTime = dateFormat.parse(timeStr);
        }
        catch (Exception e)
        {
          Message message = ERR_STOPDS_CANNOT_DECODE_STOP_TIME.get();
          err.println(wrapText(message, MAX_LINE_WIDTH));
          return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
        }
        Message message = ERR_STOPDS_CANNOT_DECODE_STOP_TIME.get();
        err.println(wrapText(message, MAX_LINE_WIDTH));
        return LDAPResultCode.CLIENT_SIDE_PARAM_ERROR;
      }
    }
opends/src/server/org/opends/server/tools/ToolConstants.java
@@ -706,5 +706,21 @@
   * Value for verbose option long form.
   */
  public static final String OPTION_LONG_VERBOSE = "verbose";
  /**
   * Scheduled start date/time option long form.
   */
  public static final String OPTION_LONG_START_DATETIME = "start";
  /**
   * Scheduled start date/time option short form.
   */
  public static final Character OPTION_SHORT_START_DATETIME = 't';
  /**
   * Placeholder string for the usage statement.
   */
  public static final String OPTION_VALUE_START_DATETIME = "{startTime}";
}
opends/src/server/org/opends/server/tools/tasks/TaskClient.java
@@ -59,6 +59,8 @@
import org.opends.server.types.SearchScope;
import static org.opends.server.types.ResultCode.*;
import org.opends.server.backends.task.TaskState;
import static org.opends.server.util.ServerConstants.*;
import org.opends.server.util.StaticUtils;
import java.io.IOException;
import java.text.SimpleDateFormat;
@@ -102,9 +104,10 @@
   * @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 a problem with the task entry
   */
  public synchronized String schedule(TaskScheduleInformation information)
          throws LDAPException, IOException, ASN1Exception
  public synchronized TaskEntry schedule(TaskScheduleInformation information)
          throws LDAPException, IOException, ASN1Exception, TaskClientException
  {
    LDAPReader reader = connection.getLDAPReader();
    LDAPWriter writer = connection.getLDAPWriter();
@@ -135,6 +138,17 @@
    classValues.add(new ASN1OctetString(information.getTaskClass().getName()));
    attributes.add(new LDAPAttribute(ATTR_TASK_CLASS, classValues));
    // add the start time if necessary
    Date startDate = information.getStartDateTime();
    if (startDate != null) {
      String startTimeString = StaticUtils.formatDateTimeString(startDate);
      ArrayList<ASN1OctetString> startDateValues =
              new ArrayList<ASN1OctetString>(1);
      startDateValues.add(new ASN1OctetString(startTimeString));
      attributes.add(new LDAPAttribute(ATTR_TASK_SCHEDULED_START_TIME,
              startDateValues));
    }
    information.addTaskAttributes(attributes);
    AddRequestProtocolOp addRequest = new AddRequestProtocolOp(entryDN,
@@ -171,7 +185,7 @@
              LDAPResultCode.CLIENT_SIDE_LOCAL_ERROR,
              errorMessage);
    }
    return taskID;
    return getTaskEntry(taskID);
  }
  /**
opends/src/server/org/opends/server/tools/tasks/TaskEntry.java
@@ -454,9 +454,10 @@
        }
        Date date = dateFormat.parse(timeString);
        DateFormat df = DateFormat.getDateTimeInstance(
                DateFormat.FULL,
                DateFormat.FULL);
        ret = Message.raw(df.format(date));
                DateFormat.MEDIUM,
                DateFormat.LONG);
        String dateString = df.format(date);
        ret = Message.raw(dateString);
      } catch (ParseException pe){
        ret = Message.raw(timeString);
      }
opends/src/server/org/opends/server/tools/tasks/TaskScheduleInformation.java
@@ -30,6 +30,7 @@
import org.opends.server.types.RawAttribute;
import java.util.List;
import java.util.Date;
/**
 * Interface for tools that are capable of scheduling a task remotely
@@ -62,4 +63,10 @@
   */
  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();
}
opends/src/server/org/opends/server/tools/tasks/TaskTool.java
@@ -29,16 +29,24 @@
import org.opends.server.util.args.LDAPConnectionArgumentParser;
import org.opends.server.util.args.ArgumentException;
import org.opends.server.util.args.StringArgument;
import static org.opends.server.util.StaticUtils.wrapText;
import static org.opends.server.util.StaticUtils.getExceptionMessage;
import static org.opends.server.util.ServerConstants.MAX_LINE_WIDTH;
import org.opends.server.util.StaticUtils;
import org.opends.server.protocols.asn1.ASN1Exception;
import org.opends.server.tools.LDAPConnection;
import org.opends.server.tools.LDAPConnectionException;
import static org.opends.server.tools.ToolConstants.*;
import org.opends.server.types.LDAPException;
import org.opends.server.types.OpenDsException;
import org.opends.server.core.DirectoryServer;
import org.opends.messages.Message;
import static org.opends.messages.ToolMessages.*;
import java.io.PrintStream;
import java.text.ParseException;
import java.util.Date;
import java.io.IOException;
/**
@@ -48,6 +56,87 @@
 */
public abstract class TaskTool implements TaskScheduleInformation {
  LDAPConnectionArgumentParser argParser;
  StringArgument startArg;
  /**
   * Called when this utility should perform its actions locally in this
   * JVM.
   *
   * @param initializeServer indicates whether or not to initialize the
   *        directory server in the case of a local action
   * @param out stream to write messages; may be null
   * @param err stream to write messages; may be null
   * @return int indicating the result of this action
   */
  abstract protected int processLocal(boolean initializeServer,
                                      PrintStream out,
                                      PrintStream err);
  /**
   * Creates an argument parser prepopulated with arguments for processing
   * input for scheduling tasks with the task backend.
   *
   * @param className of this tool
   * @param toolDescription of this tool
   * @return LDAPConnectionArgumentParser for processing CLI input
   */
  protected LDAPConnectionArgumentParser createArgParser(String className,
                                           Message toolDescription)
  {
    LDAPConnectionArgumentParser argParser = new LDAPConnectionArgumentParser(
            className, toolDescription, false);
    try {
      startArg =
           new StringArgument(
                   OPTION_LONG_START_DATETIME,
                   OPTION_SHORT_START_DATETIME,
                   OPTION_LONG_START_DATETIME, false, false,
                   true, OPTION_VALUE_START_DATETIME,
                   null, null,
                   INFO_DESCRIPTION_START_DATETIME.get());
      argParser.addArgument(startArg);
    } catch (ArgumentException e) {
      // should never happen
    }
    return argParser;
  }
  /**
   * Validates arguments related to task scheduling.  This should be
   * called after the <code>ArgumentParser.parseArguments</code> has
   * been called.
   *
   * @throws ArgumentException if there is a problem with the arguments
   */
  protected void validateTaskArgs() throws ArgumentException {
    if (startArg.isPresent()) {
      try {
        StaticUtils.parseDateTimeString(startArg.getValue());
      } catch (ParseException pe) {
        throw new ArgumentException(ERR_START_DATETIME_FORMAT.get());
      }
    }
  }
  /**
   * {@inheritDoc}
   */
  public Date getStartDateTime() {
    Date start = null;
    if (startArg != null && startArg.isPresent()) {
      try {
        start = StaticUtils.parseDateTimeString(startArg.getValue());
      } catch (ParseException pe) {
        // ignore; valiidated in validateTaskArgs()
      }
    }
    return start;
  }
  /**
   * Either invokes initiates this tool's local action or schedule this
   * tool using the tasks interface based on user input.
@@ -63,24 +152,50 @@
                        boolean initializeServer,
                        PrintStream out, PrintStream err) {
    int ret;
    String taskId;
    if (argParser.isLdapOperation())
    {
      if (initializeServer)
      {
        try
        {
          DirectoryServer.bootstrapClient();
          DirectoryServer.initializeJMX();
        }
        catch (Exception e)
        {
          Message message = ERR_SERVER_BOOTSTRAP_ERROR.get(
                  getExceptionMessage(e));
          err.println(wrapText(message, MAX_LINE_WIDTH));
          return 1;
        }
      }
      try {
        LDAPConnection conn = argParser.connect(out, err);
        TaskClient tc = new TaskClient(conn);
        taskId = tc.schedule(this);
        out.println(wrapText(INFO_TASK_TOOL_TASK_SCHEDULED.get(taskId),
                MAX_LINE_WIDTH));
        TaskEntry taskEntry = tc.schedule(this);
        Message startTime = taskEntry.getScheduledStartTime();
        if (startTime == null || startTime.length() == 0) {
          out.println(
                  wrapText(INFO_TASK_TOOL_TASK_SCHEDULED_NOW.get(
                          taskEntry.getType(),
                          taskEntry.getId()),
                  MAX_LINE_WIDTH));
        } else {
          out.println(
                  wrapText(INFO_TASK_TOOL_TASK_SCHEDULED_FUTURE.get(
                          taskEntry.getType(),
                          taskEntry.getId(),
                          taskEntry.getScheduledStartTime()),
                  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 = 1;
      } catch (ArgumentException e) {
        Message message = e.getMessageObject();
        if (err != null) err.println(wrapText(message, MAX_LINE_WIDTH));
        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));
@@ -93,6 +208,10 @@
        Message message = ERR_TASK_TOOL_DECODE_ERROR.get(le.getMessage());
        if (err != null) err.println(wrapText(message, MAX_LINE_WIDTH));
        ret = 1;
      } catch (OpenDsException e) {
        Message message = e.getMessageObject();
        if (err != null) err.println(wrapText(message, MAX_LINE_WIDTH));
        ret = 1;
      }
    } else {
      ret = processLocal(initializeServer, out, err);
@@ -100,18 +219,4 @@
    return ret;
  }
  /**
   * Called when this utility should perform its actions locally in this
   * JVM.
   *
   * @param initializeServer indicates whether or not to initialize the
   *        directory server in the case of a local action
   * @param out stream to write messages; may be null
   * @param err stream to write messages; may be null
   * @return int indicating the result of this action
   */
  abstract protected int processLocal(boolean initializeServer,
                                      PrintStream out,
                                      PrintStream err);
}
opends/src/server/org/opends/server/util/StaticUtils.java
@@ -41,6 +41,7 @@
import java.lang.reflect.InvocationTargetException;
import java.nio.ByteBuffer;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -48,6 +49,8 @@
import java.util.Map;
import java.util.RandomAccess;
import java.util.StringTokenizer;
import java.util.Date;
import java.util.TimeZone;
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
@@ -66,7 +69,6 @@
import org.opends.server.types.RDN;
/**
 * This class defines a number of static utility methods that may be used
 * throughout the server.  Note that because of the frequency with which these
@@ -3952,5 +3954,56 @@
    }
  }
  /**
   * Converts a string representing a time in "yyyyMMddHHmmss.SSS'Z'" or
   * "yyyyMMddHHmmss" to a <code>Date</code>.
   *
   * @param timeStr string formatted appropriately
   * @return Date object; null if <code>timeStr</code> is null
   * @throws ParseException if there was a problem converting the string to
   *         a <code>Date</code>.
   */
  static public Date parseDateTimeString(String timeStr) throws ParseException
  {
    Date dateTime = null;
    if (timeStr != null)
    {
      if (timeStr.endsWith("Z"))
      {
        SimpleDateFormat dateFormat =
            new SimpleDateFormat(DATE_FORMAT_GENERALIZED_TIME);
        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        dateFormat.setLenient(true);
        dateTime = dateFormat.parse(timeStr);
      }
      else
      {
        SimpleDateFormat dateFormat =
            new SimpleDateFormat(DATE_FORMAT_COMPACT_LOCAL_TIME);
        dateFormat.setLenient(true);
        dateTime = dateFormat.parse(timeStr);
      }
    }
    return dateTime;
  }
  /**
   * Formats a Date to String representation in "yyyyMMddHHmmss'Z'".
   *
   * @param date to format; null if <code>date</code> is null
   * @return string representation of the date
   */
  static public String formatDateTimeString(Date date)
  {
    String timeStr = null;
    if (date != null)
    {
      SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_GMT_TIME);
      dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
      timeStr = dateFormat.format(date);
    }
    return timeStr;
  }
}