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

jvergara
16.48.2009 1785dd375fbacdda09a9a18ef36ad4e3e56de3b9
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ControlPanelInfo.java
@@ -679,6 +679,7 @@
        desc.setAuthenticated(reader instanceof ConfigFromDirContext);
        desc.setJavaVersion(reader.getJavaVersion());
        desc.setOpenConnections(reader.getOpenConnections());
        desc.setTaskEntries(reader.getTaskEntries());
        if (reader instanceof ConfigFromDirContext)
        {
          ConfigFromDirContext rCtx = (ConfigFromDirContext)reader;
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/CustomSearchResult.java
@@ -27,9 +27,13 @@
package org.opends.guitools.controlpanel.datamodel;
import static org.opends.server.util.StaticUtils.toLowerCase;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
@@ -44,6 +48,17 @@
import javax.naming.directory.SearchResult;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.AttributeBuilder;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
import org.opends.server.types.AttributeValues;
import org.opends.server.types.ByteString;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.ObjectClass;
import org.opends.server.types.OpenDsException;
import org.opends.server.util.LDIFReader;
/**
 * This is a commodity class used to wrap the SearchResult class of JNDI.
@@ -261,4 +276,89 @@
  {
    return 23 + toString.hashCode();
  }
  /**
   * Gets the Entry object equivalent to this CustomSearchResult.
   * The method assumes that the schema in DirectoryServer has been initialized.
   * @return the Entry object equivalent to this CustomSearchResult.
   * @throws OpenDsException if there is an error parsing the DN or retrieving
   * the attributes definition and objectclasses in the schema of the server.
   */
  public Entry getEntry() throws OpenDsException
  {
    DN dn = DN.decode(this.getDN());
    Map<ObjectClass,String> objectClasses = new HashMap<ObjectClass,String>();
    Map<AttributeType,List<org.opends.server.types.Attribute>> userAttributes =
      new HashMap<AttributeType,List<org.opends.server.types.Attribute>>();
    Map<AttributeType,List<org.opends.server.types.Attribute>>
    operationalAttributes =
      new HashMap<AttributeType,List<org.opends.server.types.Attribute>>();
    for (String wholeName : this.getAttributeNames())
    {
      final org.opends.server.types.Attribute attribute =
        LDIFReader.parseAttrDescription(wholeName);
      final String attrName = attribute.getName();
      final String lowerName = toLowerCase(attrName);
      // See if this is an objectclass or an attribute.  Then get the
      // corresponding definition and add the value to the appropriate hash.
      if (lowerName.equals("objectclass"))
      {
        for (Object value : this.getAttributeValues(attrName))
        {
          String ocName = value.toString().trim();
          String lowerOCName = toLowerCase(ocName);
          ObjectClass objectClass =
            DirectoryServer.getObjectClass(lowerOCName);
          if (objectClass == null)
          {
            objectClass = DirectoryServer.getDefaultObjectClass(ocName);
          }
          objectClasses.put(objectClass, ocName);
        }
      }
      else
      {
        AttributeType attrType = DirectoryServer.getAttributeType(lowerName);
        if (attrType == null)
        {
          attrType = DirectoryServer.getDefaultAttributeType(attrName);
        }
        AttributeBuilder builder = new AttributeBuilder(attribute, true);
        for (Object value : this.getAttributeValues(attrName))
        {
          ByteString bs;
          if (value instanceof byte[])
          {
            bs = ByteString.wrap((byte[])value);
          }
          else
          {
            bs = ByteString.valueOf(value.toString());
          }
          AttributeValue attributeValue =
            AttributeValues.create(attrType, bs);
          builder.add(attributeValue);
        }
        List<org.opends.server.types.Attribute> attrList =
          new ArrayList<org.opends.server.types.Attribute>(1);
        attrList.add(builder.toAttribute());
        if (attrType.isOperational())
        {
          operationalAttributes.put(attrType, attrList);
        }
        else
        {
          userAttributes.put(attrType, attrList);
        }
      }
    }
    return new Entry(dn, objectClasses, userAttributes, operationalAttributes);
  }
}
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ScheduleType.java
New file
@@ -0,0 +1,206 @@
/*
 * 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
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.datamodel;
import java.util.Date;
/**
 * The class to be used to describe the task schedule.
 *
 */
public class ScheduleType
{
  /**
   * The different type of schedules.
   *
   */
  public enum Type
  {
    /**
     * Launch now.
     */
    LAUNCH_NOW,
    /**
     * Launch later in a specific date.
     */
    LAUNCH_LATER,
    /**
     * Launch periodically.
     */
    LAUNCH_PERIODICALLY
  }
  private Type type;
  private Date launchLaterDate;
  private String cronValue;
  private String toString;
  private int hashCode;
  private ScheduleType()
  {
  }
  /**
   * Returns a schedule instance that launches the task now.
   * @return a schedule instance that launches the task now.
   */
  public static ScheduleType createLaunchNow()
  {
    ScheduleType schedule = new ScheduleType();
    schedule.type = Type.LAUNCH_NOW;
    schedule.toString = schedule.calculateToString();
    schedule.hashCode = schedule.calculateHashCode();
    return schedule;
  }
  /**
   * Returns a schedule instance that launches the task at a given date.
   * @param date the Date at which the task must be launched.
   * @return a schedule instance that launches the task at a given date.
   */
  public static ScheduleType createLaunchLater(Date date)
  {
    ScheduleType schedule = new ScheduleType();
    schedule.type = Type.LAUNCH_LATER;
    schedule.launchLaterDate = date;
    schedule.toString = schedule.calculateToString();
    schedule.hashCode = schedule.calculateHashCode();
    return schedule;
  }
  /**
   * Returns a schedule instance that launches the task using a cron schedule.
   * @param cron the String containing the cron schedule.
   * @return a schedule instance that launches the task using a cron schedule.
   */
  public static ScheduleType createCron(String cron)
  {
    ScheduleType schedule = new ScheduleType();
    schedule.type = Type.LAUNCH_PERIODICALLY;
    schedule.cronValue = cron;
    schedule.toString = schedule.calculateToString();
    schedule.hashCode = schedule.calculateHashCode();
    return schedule;
  }
  /**
   * Returns the type of the schedule.
   * @return the type of the schedule.
   */
  public Type getType()
  {
    return type;
  }
  /**
   * Returns the date on which the task will be launched.
   * @return the date on which the task will be launched.
   */
  public Date getLaunchLaterDate()
  {
    return launchLaterDate;
  }
  /**
   * Returns the CRON String representation of the schedule.
   * @return the CRON String representation of the schedule.
   */
  public String getCronValue()
  {
    return cronValue;
  }
  /**
   * {@inheritDoc}
   */
  public boolean equals(Object o)
  {
    boolean equals;
    if (o != null)
    {
      if (o == this)
      {
        equals = true;
      }
      else
      {
        equals = toString().equals(o.toString());
      }
    }
    else
    {
      equals = false;
    }
    return equals;
  }
  /**
   * {@inheritDoc}
   */
  public String toString()
  {
    return toString;
  }
  /**
   * {@inheritDoc}
   */
  public int hashCode()
  {
    return hashCode;
  }
  /**
   * Calculates the hashCode.
   * To be called after the calculateToString is called.
   * @return the value of the hashCode.
   */
  private int calculateHashCode()
  {
    return 32 + toString.hashCode();
  }
  private String calculateToString()
  {
    String toString;
    switch (type)
    {
    case LAUNCH_NOW:
      toString = "Schedule Type: Launch Now";
      break;
    case LAUNCH_LATER:
      toString = "Schedule Type: Launch Later at date "+launchLaterDate;
      break;
    case LAUNCH_PERIODICALLY:
      toString = "Schedule Type: periodical schedule "+cronValue;
      break;
      default:
        throw new IllegalStateException("Invalid type: "+type);
    }
    return toString;
  }
}
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ServerDescriptor.java
@@ -40,6 +40,7 @@
import org.opends.guitools.controlpanel.util.ConfigFromDirContext;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.server.tools.tasks.TaskEntry;
import org.opends.server.types.AttributeType;
import org.opends.server.types.DN;
import org.opends.server.types.ObjectClass;
@@ -79,6 +80,8 @@
  private CustomSearchResult workQueue;
  private Set<TaskEntry> taskEntries = new HashSet<TaskEntry>();
  private long runningTime = -1;
  private boolean isAuthenticated;
@@ -289,6 +292,24 @@
  }
  /**
   * Returns the task entries.
   * @return the task entries.
   */
  public Set<TaskEntry> getTaskEntries()
  {
    return taskEntries;
  }
  /**
   * Sets the the task entries.
   * @param taskEntries the task entries.
   */
  public void setTaskEntries(Set<TaskEntry> taskEntries)
  {
    this.taskEntries = Collections.unmodifiableSet(taskEntries);
  }
  /**
   * {@inheritDoc}
   */
  public boolean equals(Object o)
@@ -411,6 +432,11 @@
          equals =
            desc.isWindowsServiceEnabled() == isWindowsServiceEnabled();
        }
        if (equals)
        {
          desc.getTaskEntries().equals(getTaskEntries());
        }
      }
    }
    else
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/TaskTableModel.java
New file
@@ -0,0 +1,421 @@
/*
 * 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
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.datamodel;
import static org.opends.messages.AdminToolMessages.*;
import static org.opends.messages.ToolMessages.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.opends.guitools.controlpanel.ui.ColorAndFontConstants;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.messages.Message;
import org.opends.quicksetup.util.Utils;
import org.opends.server.backends.task.TaskState;
import org.opends.server.tools.tasks.TaskEntry;
/**
 * The table used to display the tasks.
 *
 */
public class TaskTableModel  extends SortableTableModel
implements Comparator<TaskEntry>
{
  private static final long serialVersionUID = -351142550147124L;
  private Set<TaskEntry> data = new HashSet<TaskEntry>();
  private ArrayList<TaskEntry> dataSourceArray = new ArrayList<TaskEntry>();
  LinkedHashSet<Message> displayedAttributes = new LinkedHashSet<Message>();
  final LinkedHashSet<Message> defaultAttributes = new LinkedHashSet<Message>();
  {
    defaultAttributes.add(INFO_TASKINFO_FIELD_ID.get());
    defaultAttributes.add(INFO_TASKINFO_FIELD_TYPE.get());
    defaultAttributes.add(INFO_TASKINFO_FIELD_STATUS.get());
    defaultAttributes.add(INFO_CTRL_PANEL_TASK_CANCELABLE.get());
  }
  LinkedHashSet<Message> allAttributes = new LinkedHashSet<Message>();
  {
    allAttributes.addAll(defaultAttributes);
    allAttributes.add(INFO_TASKINFO_FIELD_SCHEDULED_START.get());
    allAttributes.add(INFO_TASKINFO_FIELD_ACTUAL_START.get());
    allAttributes.add(INFO_TASKINFO_FIELD_COMPLETION_TIME.get());
    allAttributes.add(INFO_TASKINFO_FIELD_DEPENDENCY.get());
    allAttributes.add(INFO_TASKINFO_FIELD_FAILED_DEPENDENCY_ACTION.get());
    allAttributes.add(INFO_TASKINFO_FIELD_NOTIFY_ON_COMPLETION.get());
    allAttributes.add(INFO_TASKINFO_FIELD_NOTIFY_ON_ERROR.get());
  }
  private String[] columnNames = {};
  /**
   * The sort column of the table.
   */
  private int sortColumn = 0;
  /**
   * Whether the sorting is ascending or descending.
   */
  private boolean sortAscending = true;
  /**
   * Default constructor.
   */
  public TaskTableModel()
  {
    super();
    setAttributes(defaultAttributes);
  }
  /**
   * Sets the data for this table model.
   * @param newData the data for this table model.
   */
  public void setData(Set<TaskEntry> newData)
  {
    if (!newData.equals(data))
    {
      data.clear();
      data.addAll(newData);
      updateDataArray();
      fireTableDataChanged();
    }
  }
  /**
   * Updates the table model contents and sorts its contents depending on the
   * sort options set by the user.
   */
  public void forceResort()
  {
    updateDataArray();
    fireTableDataChanged();
  }
  /**
   * Updates the table model contents, sorts its contents depending on the
   * sort options set by the user and updates the column structure.
   */
  public void forceDataStructureChange()
  {
    updateDataArray();
    fireTableStructureChanged();
    fireTableDataChanged();
  }
  /**
   * Updates the array data.  This includes resorting it.
   */
  private void updateDataArray()
  {
    TreeSet<TaskEntry> sortedSet = new TreeSet<TaskEntry>(this);
    sortedSet.addAll(data);
    dataSourceArray.clear();
    for (TaskEntry task : sortedSet)
    {
      dataSourceArray.add(task);
    }
  }
  /**
   * Sets the operations displayed by this table model.
   * @param attributes the attributes displayed by this table model.
   */
  public void setAttributes(LinkedHashSet<Message> attributes)
  {
    if (!allAttributes.containsAll(attributes))
    {
      throw new IllegalArgumentException(
          "Some of the provided attributes are not valid.");
    }
    this.displayedAttributes.clear();
    this.displayedAttributes.addAll(attributes);
    int columnCount = attributes.size();
    columnNames = new String[columnCount];
    int i = 0;
    for (Message attribute : attributes)
    {
      columnNames[i] = getHeader(attribute, 15);
      i++;
    }
  }
  /**
   * {@inheritDoc}
   */
  public Class<?> getColumnClass(int column)
  {
    return Message.class;
  }
  /**
   * {@inheritDoc}
   */
  public String getColumnName(int col) {
    return columnNames[col];
  }
  /**
   * {@inheritDoc}
   */
  public Object getValueAt(int row, int column)
  {
    Message value;
    column = getFixedOrderColumn(column);
    TaskEntry taskEntry = get(row);
    switch (column)
    {
    case 0:
      value = Message.raw(taskEntry.getId());
      break;
    case 1:
      value = taskEntry.getType();
      break;
    case 2:
      value = taskEntry.getState();
      break;
    case 3:
      if (taskEntry.isCancelable())
      {
        value = INFO_CTRL_PANEL_TASK_IS_CANCELABLE.get();
      }
      else
      {
        value = INFO_CTRL_PANEL_TASK_IS_NOT_CANCELABLE.get();
      }
      break;
    case 4:
      if (TaskState.isRecurring(get(row).getTaskState()))
      {
        value = taskEntry.getScheduleTab();
      } else {
        value = taskEntry.getScheduledStartTime();
        if (value == null || value.equals(Message.EMPTY))
        {
          value = INFO_TASKINFO_IMMEDIATE_EXECUTION.get();
        }
      }
      break;
    case 5:
      value = taskEntry.getActualStartTime();
      break;
    case 6:
      value = taskEntry.getCompletionTime();
      break;
    case 7:
      value = getValue(taskEntry.getDependencyIds(),
          INFO_TASKINFO_NONE_SPECIFIED.get());
      break;
    case 8:
      value = taskEntry.getFailedDependencyAction();
      if (value == null)
      {
        value = INFO_TASKINFO_NONE.get();
      }
      break;
    case 9:
      value = getValue(taskEntry.getCompletionNotificationEmailAddresses(),
          INFO_TASKINFO_NONE_SPECIFIED.get());
      break;
    case 10:
      value = getValue(taskEntry.getErrorNotificationEmailAddresses(),
          INFO_TASKINFO_NONE_SPECIFIED.get());
      break;
    default:
      throw new IllegalArgumentException("Invalid column: "+column);
    }
    return value;
  }
  /**
   * Returns the row count.
   * @return the row count.
   */
  public int getRowCount()
  {
    return dataSourceArray.size();
  }
  /**
   * Returns the column count.
   * @return the column count.
   */
  public int getColumnCount()
  {
    return columnNames.length;
  }
  /**
   * Gets the TaskDescriptor in a given row.
   * @param row the row.
   * @return the TaskDescriptor in a given row.
   */
  public TaskEntry get(int row)
  {
    return dataSourceArray.get(row);
  }
  /**
   * Returns the set of attributes ordered.
   * @return the set of attributes ordered.
   */
  public LinkedHashSet<Message> getDisplayedAttributes()
  {
    return displayedAttributes;
  }
  /**
   * Returns the set of attributes ordered.
   * @return the set of attributes ordered.
   */
  public LinkedHashSet<Message> getAllAttributes()
  {
    return allAttributes;
  }
  /**
   * {@inheritDoc}
   */
  public int compare(TaskEntry desc1, TaskEntry desc2)
  {
    int result;
    ArrayList<Integer> possibleResults = new ArrayList<Integer>();
    possibleResults.add(desc1.getId().compareTo(desc2.getId()));
    possibleResults.add(desc1.getType().compareTo(desc2.getType()));
    possibleResults.add(desc1.getState().compareTo(desc2.getState()));
    possibleResults.add(String.valueOf(desc1.isCancelable()).compareTo(
        String.valueOf(desc2.isCancelable())));
    result = possibleResults.get(getSortColumn());
    if (result == 0)
    {
      for (int i : possibleResults)
      {
        if (i != 0)
        {
          result = i;
          break;
        }
      }
    }
    if (!isSortAscending())
    {
      result = -result;
    }
    return result;
  }
  /**
   * Returns whether the sort is ascending or descending.
   * @return <CODE>true</CODE> if the sort is ascending and <CODE>false</CODE>
   * otherwise.
   */
  public boolean isSortAscending()
  {
    return sortAscending;
  }
  /**
   * Sets whether to sort ascending of descending.
   * @param sortAscending whether to sort ascending or descending.
   */
  public void setSortAscending(boolean sortAscending)
  {
    this.sortAscending = sortAscending;
  }
  /**
   * Returns the column index used to sort.
   * @return the column index used to sort.
   */
  public int getSortColumn()
  {
    return sortColumn;
  }
  /**
   * Sets the column index used to sort.
   * @param sortColumn column index used to sort..
   */
  public void setSortColumn(int sortColumn)
  {
    this.sortColumn = sortColumn;
  }
  private int getFixedOrderColumn(int column)
  {
    int fixedOrderColumn = 0;
    int i=0;
    Message colMsg = null;
    for (Message msg : displayedAttributes)
    {
      if (i == column)
      {
        colMsg = msg;
        break;
      }
      i++;
    }
    for (Message msg : allAttributes)
    {
      if (msg.equals(colMsg))
      {
        break;
      }
      fixedOrderColumn++;
    }
    return fixedOrderColumn;
  }
  private Message getValue(List<String> values, Message valueIfEmpty)
  {
    Message msg;
    if (values.isEmpty())
    {
      msg = valueIfEmpty;
    }
    else
    {
      String s = Utils.getStringFromCollection(values, "<br>");
      if (values.size() > 1)
      {
        msg = Message.raw(
            "<html>"+Utilities.applyFont(s, ColorAndFontConstants.tableFont));
      }
      else
      {
        msg = Message.raw(s);
      }
    }
    return msg;
  }
}
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/task/CancelTaskTask.java
New file
@@ -0,0 +1,261 @@
/*
 * 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
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.task;
import static org.opends.messages.AdminToolMessages.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.swing.SwingUtilities;
import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
import org.opends.guitools.controlpanel.ui.ColorAndFontConstants;
import org.opends.guitools.controlpanel.ui.ProgressDialog;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.messages.Message;
import org.opends.server.tools.ManageTasks;
import org.opends.server.tools.tasks.TaskEntry;
import org.opends.server.util.cli.CommandBuilder;
/**
 * Task used to cancel tasks in server.
 *
 */
public class CancelTaskTask extends Task
{
  private Set<String> backendSet;
  private List<TaskEntry> tasks;
  /**
   * Constructor of the task.
   * @param info the control panel information.
   * @param dlg the progress dialog where the task progress will be displayed.
   * @param tasks the tasks to be canceled.
   */
  public CancelTaskTask(ControlPanelInfo info, ProgressDialog dlg,
      List<TaskEntry> tasks)
  {
    super(info, dlg);
    backendSet = new HashSet<String>();
    for (BackendDescriptor backend : info.getServerDescriptor().getBackends())
    {
      backendSet.add(backend.getBackendID());
    }
    this.tasks = new ArrayList<TaskEntry>(tasks);
  }
  /**
   * {@inheritDoc}
   */
  public Type getType()
  {
    // TODO: change this
    return Type.MODIFY_ENTRY;
  }
  /**
   * {@inheritDoc}
   */
  public Set<String> getBackends()
  {
    return backendSet;
  }
  /**
   * {@inheritDoc}
   */
  public Message getTaskDescription()
  {
    return INFO_CTRL_PANEL_CANCEL_TASK_DESCRIPTION.get();
  }
  /**
   * {@inheritDoc}
   */
  public boolean regenerateDescriptor()
  {
    return true;
  }
  /**
   * {@inheritDoc}
   */
  protected String getCommandLinePath()
  {
    return null;
  }
  /**
   * {@inheritDoc}
   */
  protected ArrayList<String> getCommandLineArguments()
  {
    return new ArrayList<String>();
  }
  /**
   * Returns the command-line arguments to be used to cancel the task.
   * @param task the task to be canceled.
   * @return the command-line arguments to be used to cancel the task.
   */
  private ArrayList<String> getCommandLineArguments(TaskEntry task)
  {
    ArrayList<String> args = new ArrayList<String>();
    args.add("--cancel");
    args.add(task.getId());
    args.addAll(getConnectionCommandLineArguments());
    args.add(getNoPropertiesFileArgument());
    return args;
  }
  /**
   * {@inheritDoc}
   */
  public boolean canLaunch(Task taskToBeLaunched,
      Collection<Message> incompatibilityReasons)
  {
    boolean canLaunch = true;
    if (!isServerRunning())
    {
      if (state == State.RUNNING)
      {
        // All the operations are incompatible if they apply to this
        // backend for safety.  This is a short operation so the limitation
        // has not a lot of impact.
        Set<String> backends =
          new TreeSet<String>(taskToBeLaunched.getBackends());
        backends.retainAll(getBackends());
        if (backends.size() > 0)
        {
          incompatibilityReasons.add(getIncompatibilityMessage(this,
              taskToBeLaunched));
          canLaunch = false;
        }
      }
    }
    return canLaunch;
  }
  /**
   * {@inheritDoc}
   */
  public void runTask()
  {
    state = State.RUNNING;
    lastException = null;
    try
    {
      final int totalNumber = tasks.size();
      int numberCanceled = 0;
      SwingUtilities.invokeLater(new Runnable()
      {
        public void run()
        {
          getProgressDialog().getProgressBar().setIndeterminate(true);
        }
      });
      for (final TaskEntry task : tasks)
      {
        final ArrayList<String> arguments = getCommandLineArguments(task);
        final boolean isFirst = numberCanceled == 0;
        SwingUtilities.invokeLater(new Runnable()
        {
          public void run()
          {
            if (isFirst)
            {
              getProgressDialog().appendProgressHtml("<br><br>");
            }
            ArrayList<String> args = new ArrayList<String>();
            args.add(getCommandLinePath("manage-tasks"));
            args.addAll(getObfuscatedCommandLineArguments(arguments));
            StringBuilder sb = new StringBuilder();
            for (String arg : args)
            {
              sb.append(" "+CommandBuilder.escapeValue(arg));
            }
            getProgressDialog().appendProgressHtml(Utilities.applyFont(
                INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_CANCEL_TASK.get(task.getId())+
                "<br><b>"+sb.toString()+"</b><br><br>",
                ColorAndFontConstants.progressFont));
          }
        });
        String[] args = new String[arguments.size()];
        arguments.toArray(args);
        returnCode = ManageTasks.mainTaskInfo(args, System.in,
            outPrintStream, errorPrintStream);
        if (returnCode != 0)
        {
          break;
        }
        else
        {
          numberCanceled ++;
          final int fNumberCanceled = numberCanceled;
          SwingUtilities.invokeLater(new Runnable()
          {
            public void run()
            {
              if (fNumberCanceled == 1)
              {
                getProgressDialog().getProgressBar().setIndeterminate(false);
              }
              getProgressDialog().getProgressBar().setValue(
                  (fNumberCanceled * 100) / totalNumber);
            }
          });
        }
      }
      if (returnCode != 0)
      {
        state = State.FINISHED_WITH_ERROR;
      }
      else
      {
        state = State.FINISHED_SUCCESSFULLY;
      }
    }
    catch (Throwable t)
    {
      lastException = t;
      state = State.FINISHED_WITH_ERROR;
    }
  }
}
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/BackupPanel.java
@@ -60,9 +60,11 @@
import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
import org.opends.guitools.controlpanel.datamodel.BackupDescriptor;
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
import org.opends.guitools.controlpanel.datamodel.ScheduleType;
import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
import org.opends.guitools.controlpanel.task.Task;
import org.opends.guitools.controlpanel.ui.components.ScheduleSummaryPanel;
import org.opends.guitools.controlpanel.util.BackgroundTask;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.messages.Message;
@@ -100,6 +102,8 @@
  private boolean backupIDInitialized = false;
  private ScheduleSummaryPanel schedulePanel;
  private static final Logger LOG =
    Logger.getLogger(BackupPanel.class.getName());
@@ -251,20 +255,27 @@
        INFO_CTRL_PANEL_BACKUP_OPTIONS_LABEL.get());
    add(lBackupOptions, gbc);
    compressData = Utilities.createCheckBox(
        INFO_CTRL_PANEL_COMPRESS_DATA_LABEL.get());
    compressData.setSelected(false);
    schedulePanel = new ScheduleSummaryPanel(
        INFO_CTRL_PANEL_BACKUP_TASK_NAME.get().toString());
    schedulePanel.setSchedule(ScheduleType.createLaunchNow());
    gbc.insets.left = 10;
    gbc.gridx = 1;
    gbc.gridwidth = 2;
    add(schedulePanel, gbc);
    compressData = Utilities.createCheckBox(
        INFO_CTRL_PANEL_COMPRESS_DATA_LABEL.get());
    compressData.setSelected(false);
    gbc.gridy ++;
    gbc.insets.top = 5;
    add(compressData, gbc);
    encryptData = Utilities.createCheckBox(
        INFO_CTRL_PANEL_ENCRYPT_DATA_LABEL.get());
    gbc.gridy ++;
    gbc.insets.top = 5;
    add(encryptData, gbc);
    encryptData.setSelected(false);
    generateMessageDigest = Utilities.createCheckBox(
@@ -351,6 +362,7 @@
    setPrimaryValid(lPath);
    setPrimaryValid(lAvailableBackups);
    setPrimaryValid(lParentID);
    setPrimaryValid(lBackupOptions);
    backupIDInitialized = false;
    final LinkedHashSet<Message> errors = new LinkedHashSet<Message>();
@@ -434,6 +446,8 @@
      }
    }
    addScheduleErrors(getSchedule(), errors, lBackupOptions);
    // Check that there is not a backup with the provided ID
    final JComponent[] components =
    {
@@ -578,6 +592,11 @@
    }
  }
  private ScheduleType getSchedule()
  {
    return schedulePanel.getSchedule();
  }
  /**
   * {@inheritDoc}
   */
@@ -586,6 +605,7 @@
    setPrimaryValid(lBackend);
    setPrimaryValid(lPath);
    setPrimaryValid(lAvailableBackups);
    setPrimaryValid(lBackupOptions);
    super.cancelClicked();
  }
@@ -824,6 +844,8 @@
      args.addAll(getConnectionCommandLineArguments());
      args.addAll(getScheduleArgs(getSchedule()));
      if (isServerRunning())
      {
        args.addAll(getConfigCommandLineArguments());
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/ConnectionHandlerMonitoringPanel.java
@@ -52,7 +52,6 @@
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
@@ -76,7 +75,8 @@
import org.opends.guitools.controlpanel.datamodel.ConnectionHandlerDescriptor.
 State;
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
import org.opends.guitools.controlpanel.ui.renderer.CustomListCellRenderer;
import org.opends.guitools.controlpanel.ui.renderer.
 NoLeftInsetCategoryComboBoxRenderer;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.guitools.controlpanel.util.ViewPositions;
import org.opends.messages.Message;
@@ -193,7 +193,7 @@
      }
    });
    connectionHandlers.setRenderer(
        new CustomComboBoxCellRenderer(connectionHandlers));
        new NoLeftInsetCategoryComboBoxRenderer(connectionHandlers));
    gbc.gridx ++;
    viewOptions.add(connectionHandlers, gbc);
    gbc.gridx ++;
@@ -313,7 +313,7 @@
          });
    for (ConnectionHandlerDescriptor ch : chs)
    {
      if (ch.getProtocol() != ConnectionHandlerDescriptor.Protocol.LDIF)
      if (protocolHasMonitoring(ch))
      {
        sortedChs.add(ch);
      }
@@ -355,7 +355,7 @@
    {
      MessageBuilder mb = new MessageBuilder();
      mb.append(INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get(
          server.getHostname()));
      server.getHostname()));
      mb.append("<br><br>"+getAuthenticateHTML());
      errorDetails = mb.toMessage();
      errorTitle = INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_SUMMARY.get();
@@ -555,7 +555,7 @@
        {
          for (ConnectionHandlerDescriptor ch : server.getConnectionHandlers())
          {
            if (ch.getProtocol() != Protocol.LDIF)
            if (protocolHasMonitoring(ch))
            {
              cchs.add(ch);
            }
@@ -588,6 +588,14 @@
    return cchs;
  }
  private boolean protocolHasMonitoring(ConnectionHandlerDescriptor ch)
  {
    return (ch.getProtocol() == Protocol.LDAP) ||
    (ch.getProtocol() == Protocol.LDAPS) ||
    (ch.getProtocol() == Protocol.LDAP_STARTTLS) ||
    (ch.getProtocol() == Protocol.OTHER);
  }
  /**
   * The specific menu bar of this panel.
   *
@@ -650,43 +658,5 @@
      return menu;
    }
  }
  /**
   *  This class is used simply to avoid an inset on the left for the
   *  elements of the combo box.
   *  Since this item is a CategorizedComboBoxElement of type
   *  CategorizedComboBoxElement.Type.REGULAR, it has by default an inset on
   *  the left.
   */
  class CustomComboBoxCellRenderer extends CustomListCellRenderer
  {
    /**
     * The constructor.
     * @param combo the combo box to be rendered.
     */
    CustomComboBoxCellRenderer(JComboBox combo)
    {
      super(combo);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public Component getListCellRendererComponent(JList list, Object value,
        int index, boolean isSelected, boolean cellHasFocus)
    {
      Component comp = super.getListCellRendererComponent(list, value, index,
          isSelected, cellHasFocus);
      if (value instanceof CategorizedComboBoxElement)
      {
        CategorizedComboBoxElement element = (CategorizedComboBoxElement)value;
        String name = getStringValue(element);
        ((JLabel)comp).setText(name);
      }
      comp.setFont(defaultFont);
      return comp;
    }
  }
}
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/ExportLDIFPanel.java
@@ -54,10 +54,12 @@
import javax.swing.event.DocumentListener;
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
import org.opends.guitools.controlpanel.datamodel.ScheduleType;
import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
import org.opends.guitools.controlpanel.event.BrowseActionListener;
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
import org.opends.guitools.controlpanel.task.Task;
import org.opends.guitools.controlpanel.ui.components.ScheduleSummaryPanel;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.messages.Message;
import org.opends.server.tools.ExportLDIF;
@@ -89,6 +91,8 @@
  private DocumentListener documentListener;
  private ScheduleSummaryPanel schedulePanel;
  /**
   * Default constructor.
   *
@@ -238,13 +242,21 @@
      Utilities.createPrimaryLabel(INFO_CTRL_PANEL_EXPORT_OPTIONS.get());
    add(lExportOptions, gbc);
    compressData = Utilities.createCheckBox(
        INFO_CTRL_PANEL_COMPRESS_DATA_LABEL.get());
    compressData.setSelected(false);
    schedulePanel = new ScheduleSummaryPanel(
        INFO_CTRL_PANEL_EXPORT_LDIF_TITLE.get().toString());
    schedulePanel.setSchedule(ScheduleType.createLaunchNow());
    gbc.insets.left = 10;
    gbc.gridx = 1;
    gbc.gridwidth = 3;
    add(schedulePanel, gbc);
    compressData = Utilities.createCheckBox(
        INFO_CTRL_PANEL_COMPRESS_DATA_LABEL.get());
    compressData.setSelected(false);
    gbc.gridy ++;
    gbc.insets.top = 5;
    add(compressData, gbc);
    encryptData = Utilities.createCheckBox(
@@ -384,6 +396,7 @@
      }
    }
    addScheduleErrors(getSchedule(), errors, lExportOptions);
    if (wrapText.isSelected())
    {
      String cols = wrapColumn.getText();
@@ -391,7 +404,12 @@
      int maxValue = 1000;
      Message errMsg = ERR_CTRL_PANEL_INVALID_WRAP_COLUMN.get(minValue,
      maxValue);
      int size1 = errors.size();
      checkIntValue(errors, cols, minValue, maxValue, errMsg);
      if (errors.size() > size1)
      {
        setPrimaryInvalid(lExportOptions);
      }
    }
    updateIncludeExclude(errors, backendName);
@@ -448,6 +466,11 @@
    super.cancelClicked();
  }
  private ScheduleType getSchedule()
  {
    return schedulePanel.getSchedule();
  }
  /**
   * The class that performs the export.
   *
@@ -589,6 +612,8 @@
      args.addAll(super.getCommandLineArguments());
      args.addAll(getScheduleArgs(getSchedule()));
      if (isServerRunning())
      {
        args.addAll(getConfigCommandLineArguments());
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/MainActionsPane.java
@@ -217,7 +217,8 @@
          {
            INFO_CTRL_PANEL_CATEGORY_MONITORING.get(),
            INFO_CTRL_PANEL_BROWSE_GENERAL_MONITORING.get(),
            INFO_CTRL_PANEL_CONNECTION_HANDLER_MONITORING.get()
            INFO_CTRL_PANEL_CONNECTION_HANDLER_MONITORING.get(),
            INFO_CTRL_PANEL_MANAGE_TASKS.get()
          },
          {
            INFO_CTRL_PANEL_CATEGORY_RUNTIME_OPTIONS.get(),
@@ -251,7 +252,8 @@
          {
            INFO_CTRL_PANEL_CATEGORY_MONITORING.get(),
            INFO_CTRL_PANEL_BROWSE_GENERAL_MONITORING.get(),
            INFO_CTRL_PANEL_CONNECTION_HANDLER_MONITORING.get()
            INFO_CTRL_PANEL_CONNECTION_HANDLER_MONITORING.get(),
            INFO_CTRL_PANEL_MANAGE_TASKS.get()
          },
          {
            INFO_CTRL_PANEL_CATEGORY_RUNTIME_OPTIONS.get(),
@@ -273,6 +275,7 @@
    classes.add(RebuildIndexPanel.class);
    classes.add(BrowseGeneralMonitoringPanel.class);
    classes.add(ConnectionHandlerMonitoringPanel.class);
    classes.add(ManageTasksPanel.class);
    classes.add(JavaPropertiesPanel.class);
    if (Utilities.isWindows())
    {
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/ManageTasksPanel.java
New file
@@ -0,0 +1,939 @@
/*
 * 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
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui;
import static org.opends.messages.AdminToolMessages.*;
import static org.opends.server.util.StaticUtils.toLowerCase;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
import org.opends.guitools.controlpanel.datamodel.CustomSearchResult;
import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
import org.opends.guitools.controlpanel.datamodel.TaskTableModel;
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
import org.opends.guitools.controlpanel.task.CancelTaskTask;
import org.opends.guitools.controlpanel.task.Task;
import org.opends.guitools.controlpanel.ui.renderer.TaskCellRenderer;
import org.opends.guitools.controlpanel.util.ConfigFromFile;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.messages.Message;
import org.opends.quicksetup.util.Utils;
import org.opends.server.core.DirectoryServer;
import org.opends.server.tools.tasks.TaskEntry;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeBuilder;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
import org.opends.server.types.AttributeValues;
import org.opends.server.types.ByteString;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.ObjectClass;
import org.opends.server.types.OpenDsException;
/**
 * The panel displaying the list of scheduled tasks.
 *
 */
public class ManageTasksPanel extends StatusGenericPanel
{
  private static final long serialVersionUID = -8034784684412532193L;
  private JLabel lNoTasksFound;
  /**
   * Remove task button.
   */
  private JButton cancelTask;
  /**
   * The scroll that contains the list of tasks (actually is a table).
   */
  private JScrollPane tableScroll;
  /**
   * The table of tasks.
   */
  private JTable taskTable;
  /**
   * The model of the table.
   */
  private TaskTableModel tableModel;
  private ManageTasksMenuBar menuBar;
  private MonitoringAttributesViewPanel<Message> operationViewPanel;
  private GenericDialog operationViewDlg;
  private JPanel detailsPanel;
  private JLabel noDetailsLabel;
  // The panel containing all the labels and values of the details.
  private JPanel detailsSubpanel;
  private static final Logger LOG =
    Logger.getLogger(ManageTasksPanel.class.getName());
  /**
   * Default constructor.
   *
   */
  public ManageTasksPanel()
  {
    super();
    createLayout();
  }
  /**
   * {@inheritDoc}
   */
  public Message getTitle()
  {
    return INFO_CTRL_PANEL_TASK_TO_SCHEDULE_LIST_TITLE.get();
  }
  /**
   * {@inheritDoc}
   */
  public boolean requiresScroll()
  {
    return false;
  }
  /**
   * {@inheritDoc}
   */
  public GenericDialog.ButtonType getButtonType()
  {
    return GenericDialog.ButtonType.CLOSE;
  }
  /**
   * {@inheritDoc}
   */
  public void okClicked()
  {
    // Nothing to do, it only contains a close button.
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public JMenuBar getMenuBar()
  {
    if (menuBar == null)
    {
      menuBar = new ManageTasksMenuBar(getInfo());
    }
    return menuBar;
  }
  /**
   * {@inheritDoc}
   */
  public Component getPreferredFocusComponent()
  {
    return taskTable;
  }
  /**
   * Returns the selected cancelable tasks in the list.
   * @param onlyCancelable add only the cancelable tasks.
   * @return the selected cancelable tasks in the list.
   */
  private List<TaskEntry> getSelectedTasks(boolean onlyCancelable)
  {
    ArrayList<TaskEntry> tasks = new ArrayList<TaskEntry>();
    int[] rows = taskTable.getSelectedRows();
    for (int row : rows)
    {
      if (row != -1)
      {
        TaskEntry task = tableModel.get(row);
        if (!onlyCancelable || task.isCancelable())
        {
          tasks.add(task);
        }
      }
    }
    return tasks;
  }
  /**
   * Creates the components and lays them in the panel.
   * @param gbc the grid bag constraints to be used.
   */
  private void createLayout()
  {
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.anchor = GridBagConstraints.WEST;
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.gridwidth = 2;
    addErrorPane(gbc);
    gbc.weightx = 0.0;
    gbc.gridy ++;
    gbc.anchor = GridBagConstraints.WEST;
    gbc.weightx = 0.0;
    gbc.fill = GridBagConstraints.NONE;
    gbc.gridwidth = 2;
    gbc.insets.left = 0;
    gbc.gridx = 0;
    gbc.gridy = 0;
    lNoTasksFound = Utilities.createDefaultLabel(
        INFO_CTRL_PANEL_NO_TASKS_FOUND.get());
    gbc.gridy ++;
    gbc.anchor = GridBagConstraints.CENTER;
    gbc.gridheight = 2;
    add(lNoTasksFound, gbc);
    lNoTasksFound.setVisible(false);
    gbc.gridwidth = 1;
    gbc.weightx = 1.0;
    gbc.weighty = 1.0;
    gbc.fill = GridBagConstraints.BOTH;
    gbc.insets.top = 10;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    // Done to provide a good size to the table.
    tableModel = new TaskTableModel();
    tableModel.setData(createDummyTaskList());
    taskTable =
      Utilities.createSortableTable(tableModel, new TaskCellRenderer());
    taskTable.getSelectionModel().setSelectionMode(
        ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    tableScroll = Utilities.createScrollPane(taskTable);
    gbc.anchor = GridBagConstraints.NORTHWEST;
    add(tableScroll, gbc);
    updateTableSizes();
    gbc.gridx = 1;
    gbc.gridheight = 1;
    gbc.anchor = GridBagConstraints.EAST;
    gbc.fill = GridBagConstraints.NONE;
    gbc.weightx = 0.0;
    gbc.weighty = 0.0;
    cancelTask = Utilities.createButton(
        INFO_CTRL_PANEL_CANCEL_TASK_BUTTON_LABEL.get());
    cancelTask.setOpaque(false);
    gbc.insets.left = 10;
    add(cancelTask, gbc);
    gbc.gridy ++;
    gbc.weighty = 1.0;
    gbc.fill = GridBagConstraints.VERTICAL;
    add(Box.createVerticalGlue(), gbc);
    cancelTask.addActionListener(new ActionListener()
    {
      /**
       * {@inheritDoc}
       */
      public void actionPerformed(ActionEvent ev)
      {
        cancelTaskClicked();
      }
    });
    gbc.gridy ++;
    gbc.gridx = 0;
    gbc.gridwidth = 2;
    gbc.fill = GridBagConstraints.BOTH;
    gbc.weightx = 1.0;
    gbc.weighty = 0.7;
    gbc.insets.left = 0;
    createDetailsPanel();
    add(detailsPanel, gbc);
    ListSelectionListener listener = new ListSelectionListener()
    {
      /**
       * {@inheritDoc}
       */
      public void valueChanged(ListSelectionEvent ev)
      {
        tableSelected();
      }
    };
    taskTable.getSelectionModel().addListSelectionListener(listener);
    listener.valueChanged(null);
  }
  /**
   * Creates the details panel.
   *
   */
  private void createDetailsPanel()
  {
    detailsPanel = new JPanel(new GridBagLayout());
    detailsPanel.setOpaque(false);
    detailsPanel.setBorder(Utilities.makeTitledBorder(
        INFO_CTRL_PANEL_TASK_SPECIFIC_DETAILS.get()));
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 1;
    gbc.gridy = 1;
    gbc.anchor = GridBagConstraints.CENTER;
    gbc.fill = GridBagConstraints.NONE;
    gbc.weightx = 1.0;
    gbc.weighty = 1.0;
    noDetailsLabel =
      Utilities.createDefaultLabel(INFO_CTRL_PANEL_NO_TASK_SELECTED.get());
    gbc.gridwidth = 2;
    detailsPanel.add(noDetailsLabel, gbc);
    detailsSubpanel = new JPanel(new GridBagLayout());
    detailsSubpanel.setOpaque(false);
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.fill = GridBagConstraints.BOTH;
    detailsPanel.add(Utilities.createBorderLessScrollBar(detailsSubpanel), gbc);
  }
  /**
   * Method called when the table is selected.
   *
   */
  private void tableSelected()
  {
    List<TaskEntry> tasks = getSelectedTasks(true);
    cancelTask.setEnabled(!tasks.isEmpty());
    detailsSubpanel.removeAll();
    tasks = getSelectedTasks(false);
    boolean displayContents = false;
    if (tasks.isEmpty())
    {
      noDetailsLabel.setText(INFO_CTRL_PANEL_NO_TASK_SELECTED.get().toString());
    }
    else if (tasks.size() > 1)
    {
      noDetailsLabel.setText(
          INFO_CTRL_PANEL_MULTIPLE_TASKS_SELECTED.get().toString());
    }
    else
    {
      TaskEntry taskEntry = tasks.iterator().next();
      Map<Message,List<String>> taskSpecificAttrs =
        taskEntry.getTaskSpecificAttributeValuePairs();
      if (taskSpecificAttrs.isEmpty())
      {
        noDetailsLabel.setText(
            INFO_CTRL_PANEL_NO_TASK_SPECIFIC_DETAILS.get().toString());
      }
      else
      {
        displayContents = true;
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridy = 1;
        gbc.fill = GridBagConstraints.NONE;
        gbc.anchor = GridBagConstraints.NORTHWEST;
        gbc.insets.top = 10;
        for (Message label : taskSpecificAttrs.keySet())
        {
          List<String> values = taskSpecificAttrs.get(label);
          gbc.gridx = 0;
          gbc.insets.left = 10;
          gbc.insets.right = 0;
          detailsSubpanel.add(Utilities.createPrimaryLabel(
              INFO_CTRL_PANEL_OPERATION_NAME_AS_LABEL.get(label.toString())),
              gbc);
          gbc.gridx = 1;
          gbc.insets.right = 10;
          Message msg;
          String s = Utils.getStringFromCollection(values, "<br>");
          if (values.size() > 1)
          {
            msg = Message.raw(
                "<html>"+Utilities.applyFont(s,
                    ColorAndFontConstants.defaultFont));
          }
          else
          {
            msg = Message.raw(s);
          }
          detailsSubpanel.add(Utilities.createDefaultLabel(msg), gbc);
          gbc.gridy ++;
        }
        gbc.gridx = 0;
        gbc.insets = new Insets(0, 0, 0, 0);
        detailsSubpanel.add(Box.createVerticalStrut(10), gbc);
        gbc.gridx = 1;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        detailsSubpanel.add(Box.createGlue(), gbc);
      }
    }
    noDetailsLabel.setVisible(!displayContents);
    revalidate();
    repaint();
  }
  /**
   * Creates a list with task descriptors.  This is done simply to have a good
   * initial size for the table.
   * @return a list with bogus task descriptors.
   */
  private Set<TaskEntry> createRandomTasksList()
  {
    Set<TaskEntry> list = new HashSet<TaskEntry>();
    Random r = new Random();
    int numberTasks = r.nextInt(10);
    for (int i= 0; i<numberTasks; i++)
    {
      CustomSearchResult csr =
        new CustomSearchResult("cn=mytask"+i+",cn=tasks");
      String p = "ds-task-";
      String[] attrNames =
      {
          p + "id",
          p + "class-name",
          p + "state",
          p + "scheduled-start-time",
          p + "actual-start-time",
          p + "completion-time",
          p + "dependency-id",
          p + "failed-dependency-action",
          p + "log-message",
          p + "notify-on-error",
          p + "notify-on-completion",
          p + "ds-recurring-task-schedule"
      };
      String[] values =
      {
          "ID",
          "TheClassName",
          "TheState",
          "Schedule Start Time",
          "Actual Start Time",
          "Completion Time",
          "Dependency ID",
          "Failed Dependency Action",
          "Log Message.                              Should be pretty long"+
          "Log Message.                              Should be pretty long"+
          "Log Message.                              Should be pretty long"+
          "Log Message.                              Should be pretty long"+
          "Log Message.                              Should be pretty long",
          "Notify On Error",
          "Notify On Completion",
          "Recurring Task Schedule"
      };
      for (int j=0; j < attrNames.length; j++)
      {
        Set<Object> attrValues = new HashSet<Object>(1);
        attrValues.add(values[j] + r.nextInt());
        csr.set(attrNames[j], attrValues);
      }
      try
      {
        Entry entry = getEntry(csr);
        TaskEntry task = new TaskEntry(entry);
        list.add(task);
      }
      catch (Throwable t)
      {
        LOG.log(Level.SEVERE, "Error getting entry '"+csr.getDN()+"': "+t, t);
      }
    }
    return list;
  }
  /**
   * Creates a list with task descriptors.  This is done simply to have a good
   * initial size for the table.
   * @return a list with bogus task descriptors.
   */
  private Set<TaskEntry> createDummyTaskList()
  {
    Set<TaskEntry> list = new HashSet<TaskEntry>();
    for (int i= 0; i<10; i++)
    {
      CustomSearchResult csr =
        new CustomSearchResult("cn=mytask"+i+",cn=tasks");
      String p = "ds-task-";
      String[] attrNames =
      {
          p + "id",
          p + "class-name",
          p + "state",
          p + "scheduled-start-time",
          p + "actual-start-time",
          p + "completion-time",
          p + "dependency-id",
          p + "failed-dependency-action",
          p + "log-message",
          p + "notify-on-error",
          p + "notify-on-completion",
          p + "ds-recurring-task-schedule"
      };
      String[] values =
      {
          "A very 29-backup - Sun Mar 29 00:00:00 MET 2009",
          "A long task type",
          "A very long task status",
          "Schedule Start Time",
          "Actual Start Time",
          "Completion Time",
          "Dependency ID",
          "Failed Dependency Action",
          "Log Message.                              Should be pretty long\n"+
          "Log Message.                              Should be pretty long\n"+
          "Log Message.                              Should be pretty long\n"+
          "Log Message.                              Should be pretty long\n"+
          "Log Message.                              Should be pretty long\n",
          "Notify On Error",
          "Notify On Completion",
          "Recurring Task Schedule"
      };
      for (int j=0; j < attrNames.length; j++)
      {
        Set<Object> attrValues = new HashSet<Object>(1);
        attrValues.add(values[j]);
        csr.set(attrNames[j], attrValues);
      }
      try
      {
        Entry entry = getEntry(csr);
        TaskEntry task = new TaskEntry(entry);
        list.add(task);
      }
      catch (Throwable t)
      {
        LOG.log(Level.SEVERE, "Error getting entry '"+csr.getDN()+"': "+t, t);
      }
    }
    return list;
  }
  private void cancelTaskClicked()
  {
    ArrayList<Message> errors = new ArrayList<Message>();
    ProgressDialog dlg = new ProgressDialog(
        Utilities.getParentDialog(this),
        INFO_CTRL_PANEL_CANCEL_TASK_TITLE.get(), getInfo());
    List<TaskEntry> tasks = getSelectedTasks(true);
    CancelTaskTask newTask = new CancelTaskTask(getInfo(), dlg, tasks);
    for (Task task : getInfo().getTasks())
    {
      task.canLaunch(newTask, errors);
    }
    if (errors.size() == 0)
    {
      boolean confirmed = displayConfirmationDialog(
          INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(),
          INFO_CTRL_PANEL_CANCEL_TASK_MSG.get());
      if (confirmed)
      {
        launchOperation(newTask,
            INFO_CTRL_PANEL_CANCELING_TASK_SUMMARY.get(),
            INFO_CTRL_PANEL_CANCELING_TASK_COMPLETE.get(),
            INFO_CTRL_PANEL_CANCELING_TASK_SUCCESSFUL.get(),
            ERR_CTRL_PANEL_CANCELING_TASK_ERROR_SUMMARY.get(),
            ERR_CTRL_PANEL_CANCELING_TASK_ERROR_DETAILS.get(),
            null,
            dlg);
        dlg.setVisible(true);
      }
    }
  }
  /**
   * Gets the Entry object equivalent to the provided CustomSearchResult.
   * The method assumes that the schema in DirectoryServer has been initialized.
   * @param csr the search result.
   * @return the Entry object equivalent to the provided CustomSearchResult.
   * @throws OpenDsException if there is an error parsing the DN or retrieving
   * the attributes definition and objectclasses in the schema of the server.
   * TODO: move somewhere better.
   */
  public static Entry getEntry(CustomSearchResult csr) throws OpenDsException
  {
    DN dn = DN.decode(csr.getDN());
    Map<ObjectClass,String> objectClasses = new HashMap<ObjectClass,String>();
    Map<AttributeType,List<Attribute>> userAttributes =
      new HashMap<AttributeType,List<Attribute>>();
    Map<AttributeType,List<Attribute>> operationalAttributes =
      new HashMap<AttributeType,List<Attribute>>();
    for (String wholeName : csr.getAttributeNames())
    {
      final Attribute attribute = parseAttrDescription(wholeName);
      final String attrName = attribute.getName();
      final String lowerName = toLowerCase(attrName);
      // See if this is an objectclass or an attribute.  Then get the
      // corresponding definition and add the value to the appropriate hash.
      if (lowerName.equals("objectclass"))
      {
        for (Object value : csr.getAttributeValues(attrName))
        {
          String ocName = value.toString().trim();
          String lowerOCName = toLowerCase(ocName);
          ObjectClass objectClass =
            DirectoryServer.getObjectClass(lowerOCName);
          if (objectClass == null)
          {
            objectClass = DirectoryServer.getDefaultObjectClass(ocName);
          }
          objectClasses.put(objectClass, ocName);
        }
      }
      else
      {
        AttributeType attrType = DirectoryServer.getAttributeType(lowerName);
        if (attrType == null)
        {
          attrType = DirectoryServer.getDefaultAttributeType(attrName);
        }
        AttributeBuilder builder = new AttributeBuilder(attribute, true);
        for (Object value : csr.getAttributeValues(attrName))
        {
          ByteString bs;
          if (value instanceof byte[])
          {
            bs = ByteString.wrap((byte[])value);
          }
          else
          {
            bs = ByteString.valueOf(value.toString());
          }
          AttributeValue attributeValue =
            AttributeValues.create(attrType, bs);
          builder.add(attributeValue);
        }
        List<Attribute> attrList = new ArrayList<Attribute>(1);
        attrList.add(builder.toAttribute());
        if (attrType.isOperational())
        {
          operationalAttributes.put(attrType, attrList);
        }
        else
        {
          userAttributes.put(attrType, attrList);
        }
      }
    }
    return new Entry(dn, objectClasses, userAttributes, operationalAttributes);
  }
  /**
   * Parse an AttributeDescription (an attribute type name and its
   * options).
   * TODO: make this method in LDIFReader public.
   *
   * @param attrDescr
   *          The attribute description to be parsed.
   * @return A new attribute with no values, representing the
   *         attribute type and its options.
   */
  private static Attribute parseAttrDescription(String attrDescr)
  {
    AttributeBuilder builder;
    int semicolonPos = attrDescr.indexOf(';');
    if (semicolonPos > 0)
    {
      builder = new AttributeBuilder(attrDescr.substring(0, semicolonPos));
      int nextPos = attrDescr.indexOf(';', semicolonPos + 1);
      while (nextPos > 0)
      {
        String option = attrDescr.substring(semicolonPos + 1, nextPos);
        if (option.length() > 0)
        {
          builder.setOption(option);
          semicolonPos = nextPos;
          nextPos = attrDescr.indexOf(';', semicolonPos + 1);
        }
      }
      String option = attrDescr.substring(semicolonPos + 1);
      if (option.length() > 0)
      {
        builder.setOption(option);
      }
    }
    else
    {
      builder = new AttributeBuilder(attrDescr);
    }
    if(builder.getAttributeType().isBinary())
    {
      //resetting doesn't hurt and returns false.
      builder.setOption("binary");
    }
    return builder.toAttribute();
  }
  /**
   * The main method to test this panel.
   * @param args the arguments.
   */
  public static void main(String[] args)
  {
    // This is a hack to initialize configuration
    new ConfigFromFile();
    final ManageTasksPanel p = new ManageTasksPanel();
    Thread t = new Thread(new Runnable()
    {
      public void run()
      {
        try
        {
          // To let the dialog to be displayed
          Thread.sleep(5000);
        }
        catch (Throwable t)
        {
          t.printStackTrace();
        }
        while (p.isVisible())
        {
          try
          {
            SwingUtilities.invokeLater(new Runnable(){
              public void run()
              {
                Set<TaskEntry> tasks = p.createRandomTasksList();
                p.tableModel.setData(tasks);
                boolean visible = p.tableModel.getRowCount() > 0;
                if (visible)
                {
                  p.updateTableSizes();
                }
                p.tableModel.fireTableDataChanged();
                p.lNoTasksFound.setVisible(!visible);
                p.tableScroll.setVisible(visible);
                p.cancelTask.setVisible(visible);
              }
            });
            Thread.sleep(5000);
          }
          catch (Exception ex)
          {
            ex.printStackTrace();
          }
        }
      }
    });
    t.start();
    SwingUtilities.invokeLater(new Runnable(){
      public void run()
      {
        GenericDialog dlg = new GenericDialog(new JFrame(), p);
        dlg.setModal(true);
        dlg.pack();
        dlg.setVisible(true);
      }
    });
    t = null;
  }
  /**
   * Displays a dialog allowing the user to select which operations to display.
   *
   */
  private void operationViewClicked()
  {
    if (operationViewDlg == null)
    {
      operationViewPanel = MonitoringAttributesViewPanel.createMessageInstance(
          tableModel.getAllAttributes());
      operationViewDlg = new GenericDialog(Utilities.getFrame(this),
          operationViewPanel);
      Utilities.centerGoldenMean(operationViewDlg,
          Utilities.getParentDialog(this));
      operationViewDlg.setModal(true);
    }
    operationViewPanel.setSelectedAttributes(
        tableModel.getDisplayedAttributes());
    operationViewDlg.setVisible(true);
    if (!operationViewPanel.isCancelled())
    {
      LinkedHashSet<Message> displayedAttributes =
        operationViewPanel.getAttributes();
      setAttributesToDisplay(displayedAttributes);
      updateTableSizes();
    }
  }
  /**
   * {@inheritDoc}
   */
  public void configurationChanged(ConfigurationChangeEvent ev)
  {
    updateErrorPaneIfServerRunningAndAuthRequired(ev.getNewDescriptor(),
        INFO_CTRL_PANEL_SCHEDULED_TASK_LIST_REQUIRES_SERVER_RUNNING.get(),
        INFO_CTRL_PANEL_SCHEDULED_TASK_LIST_AUTHENTICATION.get());
    ServerDescriptor server = ev.getNewDescriptor();
    final Set<TaskEntry> tasks = server.getTaskEntries();
    boolean changed = tableModel.getRowCount() != tasks.size();
    if (!changed)
    {
      for (int i=0; i<tableModel.getRowCount(); i++)
      {
        if (!tasks.contains(tableModel.get(i)))
        {
          changed = true;
          break;
        }
      }
    }
    if (changed)
    {
      SwingUtilities.invokeLater(new Runnable()
      {
        /**
         * {@inheritDoc}
         */
        public void run()
        {
          tableModel.setData(tasks);
          boolean visible = tableModel.getRowCount() > 0;
          if (visible)
          {
            updateTableSizes();
          }
          tableModel.fireTableDataChanged();
          lNoTasksFound.setVisible(!visible &&
              !errorPane.isVisible());
          tableScroll.setVisible(visible);
          cancelTask.setVisible(visible);
        }
      });
    }
  }
  private void updateTableSizes()
  {
    Utilities.updateTableSizes(taskTable, 8);
    Utilities.updateScrollMode(tableScroll, taskTable);
  }
  private void setAttributesToDisplay(LinkedHashSet<Message> attributes)
  {
    tableModel.setAttributes(attributes);
    tableModel.forceDataStructureChange();
  }
  /**
   * The specific menu bar of this panel.
   *
   */
  class ManageTasksMenuBar extends MainMenuBar
  {
    private static final long serialVersionUID = 5051878116443370L;
    /**
     * structor.
     * @param info the control panel info.
     */
    public ManageTasksMenuBar(ControlPanelInfo info)
    {
      super(info);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    protected void addMenus()
    {
      add(createViewMenuBar());
      add(createHelpMenuBar());
    }
    /**
     * Creates the view menu bar.
     * @return the view menu bar.
     */
    @Override
    protected JMenu createViewMenuBar()
    {
      JMenu menu = Utilities.createMenu(
          INFO_CTRL_PANEL_CONNECTION_HANDLER_VIEW_MENU.get(),
          INFO_CTRL_PANEL_CONNECTION_HANDLER_VIEW_MENU_DESCRIPTION.get());
      menu.setMnemonic(KeyEvent.VK_V);
      final JMenuItem viewOperations = Utilities.createMenuItem(
          INFO_CTRL_PANEL_OPERATIONS_VIEW.get());
      menu.add(viewOperations);
      viewOperations.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent ev)
        {
          operationViewClicked();
        }
      });
      return menu;
    }
  }
}
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/MonitoringAttributesViewPanel.java
@@ -91,7 +91,8 @@
  * Creates an instance of this panel that uses MonitoringAttributes as
  * attributes.
  * @param attributes the list of possible attributes.
  * @return an instance of this panel that uses String as attributes.
  * @return an instance of this panel that uses MonitoringAttributes as
  * attributes.
  */
 public static MonitoringAttributesViewPanel<MonitoringAttributes>
 createMonitoringAttributesInstance(
@@ -101,6 +102,18 @@
 }
 /**
  * Creates an instance of this panel that uses Message as
  * attributes.
  * @param attributes the list of possible attributes.
  * @return an instance of this panel that uses Message as attributes.
  */
 public static MonitoringAttributesViewPanel<Message>
 createMessageInstance(LinkedHashSet<Message> attributes)
 {
   return new MonitoringAttributesViewPanel<Message>(attributes);
 }
 /**
  * {@inheritDoc}
  */
 @Override
@@ -354,6 +367,10 @@
   {
     m = ((MonitoringAttributes)operation).getMessage();
   }
   else if (operation instanceof Message)
   {
     m = (Message)operation;
   }
   else
   {
     m = Message.raw(operation.toString());
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java
@@ -42,8 +42,11 @@
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
@@ -77,6 +80,7 @@
import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo;
import org.opends.guitools.controlpanel.datamodel.CustomSearchResult;
import org.opends.guitools.controlpanel.datamodel.MonitoringAttributes;
import org.opends.guitools.controlpanel.datamodel.ScheduleType;
import org.opends.guitools.controlpanel.datamodel.ServerDescriptor;
import org.opends.guitools.controlpanel.event.*;
import org.opends.guitools.controlpanel.task.RebuildIndexTask;
@@ -147,6 +151,9 @@
  private boolean sizeSet = false;
  private boolean focusSet = false;
  private static DateFormat taskDateFormat =
    new SimpleDateFormat("yyyyMMddHHmmss");
  /**
   * Returns the title that will be used as title of the dialog.
   * @return the title that will be used as title of the dialog.
@@ -2183,4 +2190,58 @@
    return INFO_CTRL_PANEL_OPERATION_NAME_AS_LABEL.get(
        attr.getMessage().toString());
  }
  /**
   * Returns the command-line arguments associated with the provided schedule.
   * @param schedule the schedule.
   * @return the command-line arguments associated with the provided schedule.
   */
  protected List<String> getScheduleArgs(ScheduleType schedule)
  {
    List<String> args = new ArrayList<String>(2);
    switch (schedule.getType())
    {
    case LAUNCH_LATER:
      args.add("--start");
      args.add(getStartTimeForTask(schedule.getLaunchLaterDate()));
      break;
    case LAUNCH_PERIODICALLY:
      args.add("--recurringTask");
      args.add(schedule.getCronValue());
      break;
    }
    return args;
  }
  /**
   * Checks whether the server is running or not and depending on the schedule
   * updates the list of errors with the errors found.
   * @param schedule the schedule.
   * @param errors the list of errors.
   * @param label the label to be marked as invalid if errors where encountered.
   */
  protected void addScheduleErrors(ScheduleType schedule,
      Collection<Message> errors, JLabel label)
  {
    if (!isServerRunning())
    {
      ScheduleType.Type type = schedule.getType();
      if (type == ScheduleType.Type.LAUNCH_LATER)
      {
        errors.add(ERR_CTRL_PANEL_LAUNCH_LATER_REQUIRES_SERVER_RUNNING.get());
        setPrimaryInvalid(label);
      }
      else if (type == ScheduleType.Type.LAUNCH_PERIODICALLY)
      {
        errors.add(
            ERR_CTRL_PANEL_LAUNCH_SCHEDULE_REQUIRES_SERVER_RUNNING.get());
        setPrimaryInvalid(label);
      }
    }
  }
  private String getStartTimeForTask(Date date)
  {
    return taskDateFormat.format(date);
  }
}
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/TaskToSchedulePanel.java
New file
@@ -0,0 +1,1178 @@
/*
 * 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
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui;
import static org.opends.messages.AdminToolMessages.*;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.swing.Box;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.text.PlainDocument;
import org.opends.guitools.controlpanel.datamodel.CategorizedComboBoxElement;
import org.opends.guitools.controlpanel.datamodel.ScheduleType;
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
import org.opends.guitools.controlpanel.ui.components.
 NumericLimitedSizeDocumentFilter;
import org.opends.guitools.controlpanel.ui.components.TimeDocumentFilter;
import org.opends.guitools.controlpanel.ui.renderer.
 NoLeftInsetCategoryComboBoxRenderer;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.messages.Message;
import org.opends.server.backends.task.RecurringTask;
/**
 * The panel that allows the user to specify when a task will be launched.
 *
 */
public class TaskToSchedulePanel extends StatusGenericPanel
{
  private static final long serialVersionUID = 6855081932432566784L;
  private String taskName;
  private JComboBox scheduleType;
  private JTextField time;
  private JTextField day;
  private JComboBox month;
  private JComboBox year;
  private JLabel lTime;
  private JLabel lDay;
  private JLabel lMonth;
  private JLabel lYear;
  private JLabel lDailyTime;
  private JTextField dailyTime;
  private JLabel lWeeklyTime;
  private JLabel lWeeklyDays;
  private JTextField weeklyTime;
  private JCheckBox sunday, monday, tuesday, wednesday, thursday, friday,
  saturday;
  {
    sunday =
      Utilities.createCheckBox(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_SUNDAY.get());
    monday =
      Utilities.createCheckBox(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_MONDAY.get());
    tuesday =
      Utilities.createCheckBox(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TUESDAY.get());
    wednesday =
      Utilities.createCheckBox(
          INFO_CTRL_PANEL_TASK_TO_SCHEDULE_WEDNESDAY.get());
    thursday =
      Utilities.createCheckBox(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_THURSDAY.get());
    friday =
      Utilities.createCheckBox(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_FRIDAY.get());
    saturday =
      Utilities.createCheckBox(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_SATURDAY.get());
  }
  JCheckBox[] weekDays =
  {
      sunday, monday, tuesday, wednesday, thursday, friday, saturday
  };
  private JLabel lMonthlyTime;
  private JLabel lMonthlyDays;
  private JTextField monthlyTime;
  private JCheckBox[] monthDays = new JCheckBox[31];
  private JLabel lCronMinute;
  private JLabel lCronHour;
  private JLabel lCronWeekDay;
  private JLabel lCronMonthDay;
  private JLabel lCronMonth;
  private JTextField cronMinute;
  private JTextField cronHour;
  private JTextField cronWeekDay;
  private JTextField cronMonthDay;
  private JTextField cronMonth;
  private Component launchLaterPanel;
  private Component dailyPanel;
  private Component weeklyPanel;
  private Component monthlyPanel;
  private Component cronPanel;
  private Message LAUNCH_NOW = INFO_CTRL_PANEL_LAUNCH_NOW.get();
  private Message LAUNCH_LATER = INFO_CTRL_PANEL_LAUNCH_LATER.get();
  private Message LAUNCH_DAILY = INFO_CTRL_PANEL_TASK_TO_SCHEDULE_DAILY.get();
  private Message LAUNCH_WEEKLY = INFO_CTRL_PANEL_TASK_TO_SCHEDULE_WEEKLY.get();
  private Message LAUNCH_MONTHLY =
    INFO_CTRL_PANEL_TASK_TO_SCHEDULE_MONTHLY.get();
  private Message CRON = INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON.get();
  private ScheduleType schedule;
  /**
   * Default constructor.
   * @param taskName the name of the task to be scheduled.
   */
  public TaskToSchedulePanel(String taskName)
  {
    super();
    this.taskName = taskName;
    createLayout();
  }
  /**
   * Creates the layout of the panel (but the contents are not populated here).
   */
  private void createLayout()
  {
    GridBagConstraints gbc = new GridBagConstraints();
    JEditorPane explanation = Utilities.makeHtmlPane(
        INFO_CTRL_PANEL_TASK_TO_SCHEDULE_SUMMARY.get(taskName).toString(),
        ColorAndFontConstants.defaultFont);
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    add(explanation, gbc);
    gbc.gridy ++;
    gbc.insets.top = 10;
    scheduleType = Utilities.createComboBox();
    scheduleType.setModel(new DefaultComboBoxModel());
    ArrayList<Object> newElements = new ArrayList<Object>();
    newElements.add(new CategorizedComboBoxElement(LAUNCH_NOW,
        CategorizedComboBoxElement.Type.REGULAR));
    newElements.add(COMBO_SEPARATOR);
    newElements.add(new CategorizedComboBoxElement(LAUNCH_LATER,
        CategorizedComboBoxElement.Type.REGULAR));
    newElements.add(COMBO_SEPARATOR);
    newElements.add(new CategorizedComboBoxElement(LAUNCH_DAILY,
        CategorizedComboBoxElement.Type.REGULAR));
    newElements.add(new CategorizedComboBoxElement(LAUNCH_WEEKLY,
        CategorizedComboBoxElement.Type.REGULAR));
    newElements.add(new CategorizedComboBoxElement(LAUNCH_MONTHLY,
        CategorizedComboBoxElement.Type.REGULAR));
    newElements.add(new CategorizedComboBoxElement(CRON,
        CategorizedComboBoxElement.Type.REGULAR));
    updateComboBoxModel(newElements,
        (DefaultComboBoxModel)scheduleType.getModel());
    scheduleType.setRenderer(
        new NoLeftInsetCategoryComboBoxRenderer(scheduleType));
    scheduleType.addItemListener(new IgnoreItemListener(scheduleType));
    gbc.weightx = 0.0;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.fill = GridBagConstraints.NONE;
    add(scheduleType, gbc);
    launchLaterPanel = createLaunchLaterPanel();
    dailyPanel = createDailyPanel();
    weeklyPanel = createWeeklyPanel();
    monthlyPanel = createMonthlyPanel();
    cronPanel = createCronPanel();
    scheduleType.addItemListener(new ItemListener()
    {
      public void itemStateChanged(ItemEvent ev)
      {
        Object element = scheduleType.getSelectedItem();
        boolean launchLaterVisible = false;
        boolean launchDailyVisible = false;
        boolean launchWeeklyVisible = false;
        boolean launchMonthlyVisible = false;
        boolean cronVisible = false;
        if (element != null)
        {
          if (element instanceof CategorizedComboBoxElement)
          {
            element = ((CategorizedComboBoxElement)element).getValue();
          }
          launchLaterVisible = element == LAUNCH_LATER;
          launchDailyVisible = element == LAUNCH_DAILY;
          launchWeeklyVisible = element == LAUNCH_WEEKLY;
          launchMonthlyVisible = element == LAUNCH_MONTHLY;
          cronVisible = element == CRON;
        }
        launchLaterPanel.setVisible(launchLaterVisible);
        dailyPanel.setVisible(launchDailyVisible);
        weeklyPanel.setVisible(launchWeeklyVisible);
        monthlyPanel.setVisible(launchMonthlyVisible);
        cronPanel.setVisible(cronVisible);
      }
    });
    launchLaterPanel.setVisible(false);
    dailyPanel.setVisible(false);
    weeklyPanel.setVisible(false);
    monthlyPanel.setVisible(false);
    cronPanel.setVisible(false);
    int width = 0;
    int height = 0;
    Component[] comps =
    {launchLaterPanel, dailyPanel, weeklyPanel, monthlyPanel, cronPanel};
    for (Component comp : comps)
    {
      width = Math.max(width, comp.getPreferredSize().width);
      height = Math.max(height, comp.getPreferredSize().height);
    }
    gbc.gridy ++;
    gbc.gridwidth = 1;
    gbc.gridx = 0;
    gbc.weightx = 0.0;
    gbc.insets.left = 30;
    add(launchLaterPanel, gbc);
    add(dailyPanel, gbc);
    add(weeklyPanel, gbc);
    add(monthlyPanel, gbc);
    add(cronPanel, gbc);
    add(Box.createRigidArea(new Dimension(width, height)), gbc);
    gbc.gridy ++;
    gbc.gridx = 0;
    gbc.fill = GridBagConstraints.VERTICAL;
    gbc.weighty = 1.0;
    add(Box.createVerticalGlue(), gbc);
  }
  /**
   * {@inheritDoc}
   */
  public void toBeDisplayed(boolean visible)
  {
    // Reset the schedule
    if (visible)
    {
      schedule = null;
    }
  }
  /**
   * {@inheritDoc}
   */
  public Message getTitle()
  {
    return INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TITLE.get(taskName);
  }
  /**
   * {@inheritDoc}
   */
  public void okClicked()
  {
    schedule = null;
    ArrayList<Message> errorMessages = new ArrayList<Message>();
    updateErrorMessages(errorMessages);
    if (errorMessages.size() > 0)
    {
      displayErrorDialog(errorMessages);
    }
    else
    {
      schedule = createSchedule();
      Utilities.getParentDialog(this).setVisible(false);
    }
  }
  /**
   * Checks the validity of the provided information and updates the provided
   * collection of messages with the errors that have been found.
   * @param errorMessages the collection of messages to be updated.
   */
  private void updateErrorMessages(Collection<Message> errorMessages)
  {
    Object type =
      ((CategorizedComboBoxElement)scheduleType.getSelectedItem()).getValue();
    if (type == LAUNCH_LATER)
    {
      updateLaunchLaterErrorMessages(errorMessages);
    }
    else if (type == LAUNCH_DAILY)
    {
      updateLaunchDailyErrorMessages(errorMessages);
    }
    else if (type == LAUNCH_WEEKLY)
    {
      updateLaunchWeeklyErrorMessages(errorMessages);
    }
    else if (type == LAUNCH_MONTHLY)
    {
      updateLaunchMonthlyErrorMessages(errorMessages);
    }
    else if (type == CRON)
    {
      updateCronErrorMessages(errorMessages);
    }
  }
  /**
   * Checks the validity of the launch later information and updates
   * the provided collection of messages with the errors that have been found.
   * The associated labels are also updated.
   * @param errorMessages the collection of messages to be updated.
   */
  private void updateLaunchLaterErrorMessages(Collection<Message> errorMessages)
  {
    setPrimaryValid(lTime);
    setPrimaryValid(lDay);
    setPrimaryValid(lMonth);
    setPrimaryValid(lYear);
    int previousErrorNumber = errorMessages.size();
    int y = Integer.parseInt(year.getSelectedItem().toString());
    int d = -1;
    int m = month.getSelectedIndex();
    int[] h = {-1};
    int[] min = {-1};
    checkTime(time, lTime, h, min, errorMessages);
    try
    {
      d = Integer.parseInt(day.getText().trim());
      if ((d < 0) || (d > 31))
      {
        errorMessages.add(ERR_CTRL_PANEL_INVALID_DAY.get());
        setPrimaryInvalid(lDay);
      }
    }
    catch (Exception ex)
    {
      errorMessages.add(ERR_CTRL_PANEL_INVALID_DAY.get());
      setPrimaryInvalid(lDay);
    }
    if (errorMessages.size() == previousErrorNumber)
    {
      GregorianCalendar calendar = new GregorianCalendar(y, m, d, h[0], min[0]);
      Date date = calendar.getTime();
      // Check that the actual date's month date corresponds to a valid day
      // (for instance if user specifies 30th of February, the resulting date
      // is 2nd (or 1st depending of the year) of Mars.
      if (calendar.get(Calendar.MONTH) != m)
      {
        errorMessages.add(ERR_CTRL_PANEL_INVALID_DAY_IN_MONTH.get(d,
            month.getSelectedItem().toString()));
        setPrimaryInvalid(lDay);
        setPrimaryInvalid(lMonth);
      }
      else if (date.before(new Date()))
      {
        errorMessages.add(ERR_CTRL_PANEL_DATE_ALREADY_PASSED.get());
        setPrimaryInvalid(lTime);
        setPrimaryInvalid(lDay);
        setPrimaryInvalid(lMonth);
        setPrimaryInvalid(lYear);
      }
    }
  }
  /**
   * Checks the validity of the launch daily information and updates
   * the provided collection of messages with the errors that have been found.
   * The associated labels are also updated.
   * @param errorMessages the collection of messages to be updated.
   */
  private void updateLaunchDailyErrorMessages(Collection<Message> errorMessages)
  {
    setPrimaryValid(lDailyTime);
    int[] h = {-1};
    int[] min = {-1};
    checkTime(dailyTime, lDailyTime, h, min, errorMessages);
  }
  /**
   * Checks the validity of the launch weekly information and updates
   * the provided collection of messages with the errors that have been found.
   * The associated labels are also updated.
   * @param errorMessages the collection of messages to be updated.
   */
  private void updateLaunchWeeklyErrorMessages(
      Collection<Message> errorMessages)
  {
    setPrimaryValid(lWeeklyTime);
    setPrimaryValid(lWeeklyDays);
    int[] h = {-1};
    int[] min = {-1};
    checkTime(weeklyTime, lWeeklyTime, h, min, errorMessages);
    boolean oneSelected = false;
    for (JCheckBox cb : weekDays)
    {
      if (cb.isSelected())
      {
        oneSelected = true;
        break;
      }
    }
    if (!oneSelected)
    {
      errorMessages.add(ERR_CTRL_PANEL_NO_WEEK_DAY_SELECTED.get());
      setPrimaryInvalid(lWeeklyDays);
    }
  }
  /**
   * Checks the validity of the launch monthly information and updates
   * the provided collection of messages with the errors that have been found.
   * The associated labels are also updated.
   * @param errorMessages the collection of messages to be updated.
   */
  private void updateLaunchMonthlyErrorMessages(
      Collection<Message> errorMessages)
  {
    setPrimaryValid(lMonthlyTime);
    setPrimaryValid(lMonthlyDays);
    int[] h = {-1};
    int[] min = {-1};
    checkTime(monthlyTime, lMonthlyTime, h, min, errorMessages);
    boolean oneSelected = false;
    for (JCheckBox cb : monthDays)
    {
      if (cb.isSelected())
      {
        oneSelected = true;
        break;
      }
    }
    if (!oneSelected)
    {
      errorMessages.add(ERR_CTRL_PANEL_NO_MONTH_DAY_SELECTED.get());
      setPrimaryInvalid(lMonthlyDays);
    }
  }
  /**
   * Checks the validity of the cron schedule information and updates
   * the provided collection of messages with the errors that have been found.
   * The associated labels are also updated.
   * @param errorMessages the collection of messages to be updated.
   */
  private void updateCronErrorMessages(Collection<Message> errorMessages)
  {
    setPrimaryValid(lCronMinute);
    setPrimaryValid(lCronHour);
    setPrimaryValid(lCronMonthDay);
    setPrimaryValid(lCronMonth);
    setPrimaryValid(lCronWeekDay);
    String minute = cronMinute.getText().trim();
    String hour = cronHour.getText().trim();
    String monthDay = cronMonthDay.getText().trim();
    String month = cronMonth.getText().trim();
    String weekDay = cronWeekDay.getText().trim();
    updateCronErrorMessages(minute, lCronMinute,
        ERR_CTRL_PANEL_NO_CRON_MINUTE_PROVIDED.get(),
        ERR_CTRL_PANEL_NOT_VALID_CRON_MINUTE_PROVIDED.get(),
        0, 59,
        errorMessages);
    updateCronErrorMessages(hour, lCronHour,
        ERR_CTRL_PANEL_NO_CRON_HOUR_PROVIDED.get(),
        ERR_CTRL_PANEL_NOT_VALID_CRON_HOUR_PROVIDED.get(),
        0, 23,
        errorMessages);
    updateCronErrorMessages(weekDay, lCronWeekDay,
        ERR_CTRL_PANEL_NO_CRON_WEEK_DAY_PROVIDED.get(),
        ERR_CTRL_PANEL_NOT_VALID_CRON_WEEK_DAY_PROVIDED.get(),
        0, 6,
        errorMessages);
    updateCronErrorMessages(monthDay, lCronMonthDay,
        ERR_CTRL_PANEL_NO_CRON_MONTH_DAY_PROVIDED.get(),
        ERR_CTRL_PANEL_NOT_VALID_CRON_MONTH_DAY_PROVIDED.get(),
        1, 31,
        errorMessages);
    updateCronErrorMessages(month, lCronMonth,
        ERR_CTRL_PANEL_NO_CRON_MONTH_PROVIDED.get(),
        ERR_CTRL_PANEL_NOT_VALID_CRON_MONTH_PROVIDED.get(),
        1, 12,
        errorMessages);
  }
  /**
   * Checks the validity of the cron schedule information tab and updates
   * the provided collection of messages with the errors that have been found.
   * The associated labels are also updated.
   * @param value the value of the cron schedule tab.
   * @param label the label associated with the cron schedule tab.
   * @param errorIfEmpty the message to be displayed if the value tab is empty.
   * @param contentError the message to be displayed if the value tab is not
   * valid.
   * @param minValue the minimum value accepted.
   * @param maxValue the maximum value accepted.
   * @param errorMessages the collection of messages to be updated.
   */
  private void updateCronErrorMessages(String value, JLabel label,
      Message errorIfEmpty, Message contentError, int minValue, int maxValue,
      Collection<Message> errorMessages)
  {
    if (value.length() == 0)
    {
      errorMessages.add(errorIfEmpty);
      setPrimaryInvalid(label);
    }
    else
    {
      try
      {
        RecurringTask.parseTaskTabField(value, minValue, maxValue);
      }
      catch (Exception ex)
      {
        errorMessages.add(contentError);
        setPrimaryInvalid(label);
      }
    }
  }
  /**
   * Returns the schedule type corresponding to the input provided by user.
   * This method assumes that all the date provided by the user has been
   * validated.
   * @return the schedule type corresponding to the input provided by user.
   */
  private ScheduleType createSchedule()
  {
    ScheduleType schedule;
    Object type =
      ((CategorizedComboBoxElement)scheduleType.getSelectedItem()).getValue();
    if (type == LAUNCH_NOW)
    {
      schedule = ScheduleType.createLaunchNow();
    }
    else if (type == LAUNCH_LATER)
    {
      int y = Integer.parseInt(year.getSelectedItem().toString());
      int d = Integer.parseInt(day.getText().trim());
      int m = month.getSelectedIndex();
      String sTime = time.getText().trim();
      int index = sTime.indexOf(':');
      int h = Integer.parseInt(sTime.substring(0, index).trim());
      int min = Integer.parseInt(sTime.substring(index+1).trim());
      GregorianCalendar calendar = new GregorianCalendar(y, m, d, h, min);
      schedule = ScheduleType.createLaunchLater(calendar.getTime());
    }
    else if (type == LAUNCH_DAILY)
    {
      String sTime = dailyTime.getText().trim();
      int index = sTime.indexOf(':');
      int h = Integer.parseInt(sTime.substring(0, index).trim());
      int m = Integer.parseInt(sTime.substring(index+1).trim());
      String cron = m+" "+h+" * * *";
      schedule = ScheduleType.createCron(cron);
    }
    else if (type == LAUNCH_WEEKLY)
    {
      String sTime = weeklyTime.getText().trim();
      int index = sTime.indexOf(':');
      int h = Integer.parseInt(sTime.substring(0, index).trim());
      int m = Integer.parseInt(sTime.substring(index+1).trim());
      StringBuilder sb = new StringBuilder();
      sb.append(m+" "+h+" * * ");
      boolean oneDayAdded = false;
      for (int i=0; i<weekDays.length; i++)
      {
        if (weekDays[i].isSelected())
        {
          if (oneDayAdded)
          {
            sb.append(',');
          }
          sb.append(i);
          oneDayAdded = true;
        }
      }
      schedule = ScheduleType.createCron(sb.toString());
    }
    else if (type == LAUNCH_MONTHLY)
    {
      String sTime = monthlyTime.getText().trim();
      int index = sTime.indexOf(':');
      int h = Integer.parseInt(sTime.substring(0, index).trim());
      int m = Integer.parseInt(sTime.substring(index+1).trim());
      StringBuilder sb = new StringBuilder();
      sb.append(m+" "+h+" ");
      boolean oneDayAdded = false;
      for (int i=0; i<monthDays.length; i++)
      {
        if (monthDays[i].isSelected())
        {
          if (oneDayAdded)
          {
            sb.append(',');
          }
          sb.append(i+1);
          oneDayAdded = true;
        }
      }
      sb.append(" * *");
      schedule = ScheduleType.createCron(sb.toString());
    }
    else if (type == CRON)
    {
      String cron = cronMinute.getText().trim() + " "+
      cronHour.getText().trim() + " "+
      cronMonthDay.getText().trim() + " "+
      cronMonth.getText().trim() + " "+
      cronWeekDay.getText().trim();
      schedule = ScheduleType.createCron(cron);
    }
    else
    {
      throw new IllegalStateException("Unknown schedule type: "+type);
    }
    return schedule;
  }
  /**
   * Convenience method to retrieve the time specified by the user.
   * @param time the text field where the user specifies time.
   * @param lTime the label associated with the text field.
   * @param h an integer array of size 1 where the value of the hour specified
   * by the user will be set.
   * @param m an integer array of size 1 where the value of the minute specified
   * by the user will be set.
   * @param errorMessages the collection of error messages that will be updated
   * with the encountered problems.
   */
  private void checkTime(JTextField time, JLabel lTime, int[] h, int[] m,
      Collection<Message> errorMessages)
  {
    String sTime = time.getText().trim();
    int index = sTime.indexOf(':');
    try
    {
      h[0] = Integer.parseInt(sTime.substring(0, index).trim());
      m[0] = Integer.parseInt(sTime.substring(index+1).trim());
      if (h[0] < 0 || h[0] > 23)
      {
        errorMessages.add(ERR_CTRL_PANEL_INVALID_HOUR.get());
        setPrimaryInvalid(lTime);
      }
      if (m[0] < 0 || m[0] > 59)
      {
        errorMessages.add(ERR_CTRL_PANEL_INVALID_MINUTE.get());
        setPrimaryInvalid(lTime);
      }
    }
    catch (Exception ex)
    {
      errorMessages.add(ERR_CTRL_PANEL_INVALID_TIME.get());
      setPrimaryInvalid(lTime);
    }
  }
  /**
   * Tells whether the user chose to close the dialog discarding the provided
   * input.
   * @return <CODE>true</CODE> if the user chose to close the dialog discarding
   * the provided input and <CODE>false</CODE> otherwise.
   */
  public boolean isCancelled()
  {
    return schedule == null;
  }
  /**
   * {@inheritDoc}
   */
  public void configurationChanged(ConfigurationChangeEvent ev)
  {
  }
  /**
   * {@inheritDoc}
   */
  public Component getPreferredFocusComponent()
  {
    return scheduleType;
  }
  /**
   * Returns the schedule provided by the user.
   * @return the schedule provided by the user.
   */
  public ScheduleType getSchedule()
  {
    return schedule;
  }
  private Component createLaunchLaterPanel()
  {
    JPanel panel = new JPanel(new GridBagLayout());
    panel.setOpaque(false);
    GridBagConstraints gbc = new GridBagConstraints();
    Calendar calendar = Calendar.getInstance();
    int currentYear = calendar.get(Calendar.YEAR);
    int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
    int currentMinute = calendar.get(Calendar.MINUTE);
    int currentDay = calendar.get(Calendar.DAY_OF_MONTH);
    int currentMonth = calendar.get(Calendar.MONTH);
    time = Utilities.createShortTextField();
    PlainDocument plainTextDocument = new PlainDocument();
    time.setDocument(plainTextDocument);
    String sHour = currentHour >= 10 ?
        String.valueOf(currentHour) : "0"+currentHour;
    String sMinute = currentMinute >= 10 ?
        String.valueOf(currentMinute) : "0"+currentMinute;
    time.setText(sHour+":"+sMinute);
    plainTextDocument.setDocumentFilter(new TimeDocumentFilter(time));
    day = Utilities.createShortTextField();
    day.setColumns(4);
    plainTextDocument = new PlainDocument();
    day.setDocument(plainTextDocument);
    day.setText(String.valueOf(currentDay));
    plainTextDocument.setDocumentFilter(
        new NumericLimitedSizeDocumentFilter(day, 2));
    month = Utilities.createComboBox();
    year = Utilities.createComboBox();
    int[][] maxMin =
    {
        {currentYear, currentYear + 5}
    };
    JComboBox[] numericBoxes =
    {
        year
    };
    int[] currentValues =
    {
        currentYear
    };
    for (int i=0; i<maxMin.length; i++)
    {
      int min = maxMin[i][0];
      int max = maxMin[i][1];
      DefaultComboBoxModel model = new DefaultComboBoxModel();
      int selectedIndex = 0;
      int index = 0;
      for (int j=min; j<=max; j++)
      {
        String s;
        if (j < 10)
        {
          s = "0"+j;
        }
        else
        {
          s = String.valueOf(j);
        }
        model.addElement(s);
        if (j == currentValues[i])
        {
          selectedIndex= index;
        }
        index++;
      }
      numericBoxes[i].setModel(model);
      if (selectedIndex != 0)
      {
        numericBoxes[i].setSelectedIndex(selectedIndex);
      }
    }
    DefaultComboBoxModel model = new DefaultComboBoxModel();
    month.setModel(model);
    Message[] monthMessages =
    {
        INFO_CTRL_PANEL_JANUARY.get(),
        INFO_CTRL_PANEL_FEBRUARY.get(),
        INFO_CTRL_PANEL_MARS.get(),
        INFO_CTRL_PANEL_APRIL.get(),
        INFO_CTRL_PANEL_MAY.get(),
        INFO_CTRL_PANEL_JUNE.get(),
        INFO_CTRL_PANEL_JULY.get(),
        INFO_CTRL_PANEL_AUGUST.get(),
        INFO_CTRL_PANEL_SEPTEMBER.get(),
        INFO_CTRL_PANEL_OCTOBER.get(),
        INFO_CTRL_PANEL_NOVEMBER.get(),
        INFO_CTRL_PANEL_DECEMBER.get(),
    };
    for (Message msg : monthMessages)
    {
      model.addElement(msg.toString());
    }
    month.setSelectedIndex(currentMonth);
    lTime = Utilities.createPrimaryLabel(
        INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TIME.get());
    lDay = Utilities.createPrimaryLabel(
        INFO_CTRL_PANEL_TASK_TO_SCHEDULE_DAY.get());
    lMonth = Utilities.createPrimaryLabel(
        INFO_CTRL_PANEL_TASK_TO_SCHEDULE_MONTH.get());
    lYear = Utilities.createPrimaryLabel(
        INFO_CTRL_PANEL_TASK_TO_SCHEDULE_YEAR.get());
    gbc.gridy = 0;
    JLabel[] labels = {lTime, lDay, lMonth, lYear};
    Component[] comps = {time, day, month, year};
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    for (int i=0; i<labels.length; i++)
    {
      gbc.gridx = 0;
      gbc.weightx = 0.0;
      panel.add(labels[i], gbc);
      gbc.gridx = 1;
      gbc.insets.left = 10;
      panel.add(comps[i], gbc);
      gbc.gridx = 2;
      gbc.weightx = 1.0;
      gbc.insets.left = 0;
      panel.add(Box.createHorizontalGlue(), gbc);
      gbc.insets.top = 10;
      gbc.gridy ++;
    }
    gbc.insets.top = 0;
    gbc.weighty = 1.0;
    gbc.fill = GridBagConstraints.VERTICAL;
    panel.add(Box.createVerticalGlue(), gbc);
    return panel;
  }
  private Component createDailyPanel()
  {
    JPanel panel = new JPanel(new GridBagLayout());
    panel.setOpaque(false);
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.weightx = 0.0;
    lDailyTime =
      Utilities.createPrimaryLabel(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TIME.get());
    dailyTime = Utilities.createShortTextField();
    PlainDocument plainTextDocument = new PlainDocument();
    dailyTime.setDocument(plainTextDocument);
    dailyTime.setColumns(4);
    dailyTime.setText("00:00");
    plainTextDocument.setDocumentFilter(new TimeDocumentFilter(dailyTime));
    panel.add(lDailyTime, gbc);
    gbc.gridx = 1;
    gbc.insets.left = 10;
    gbc.fill = GridBagConstraints.NONE;
    panel.add(dailyTime, gbc);
    gbc.gridx = 2;
    gbc.weightx = 1.0;
    gbc.insets.left = 0;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    panel.add(Box.createHorizontalGlue(), gbc);
    return panel;
  }
  private Component createWeeklyPanel()
  {
    JPanel panel = new JPanel(new GridBagLayout());
    panel.setOpaque(false);
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.weightx = 0.0;
    lWeeklyTime =
      Utilities.createPrimaryLabel(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TIME.get());
    weeklyTime = Utilities.createShortTextField();
    PlainDocument plainTextDocument = new PlainDocument();
    weeklyTime.setDocument(plainTextDocument);
    weeklyTime.setColumns(4);
    weeklyTime.setText("00:00");
    plainTextDocument.setDocumentFilter(new TimeDocumentFilter(weeklyTime));
    lWeeklyDays = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_DAYS.get());
    for (JCheckBox cb : weekDays)
    {
      cb.setFont(ColorAndFontConstants.inlineHelpFont);
    }
    sunday.setSelected(true);
    wednesday.setSelected(true);
    gbc.anchor = GridBagConstraints.WEST;
    panel.add(lWeeklyTime, gbc);
    gbc.gridx = 1;
    gbc.insets.left = 10;
    gbc.gridwidth = weekDays.length;
    gbc.fill = GridBagConstraints.NONE;
    panel.add(weeklyTime, gbc);
    gbc.gridx = 2;
    gbc.weightx = 1.0;
    gbc.insets.left = 0;
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    panel.add(Box.createHorizontalGlue(), gbc);
    gbc.gridx = 0;
    gbc.gridy ++;
    gbc.insets.top = 10;
    gbc.weightx = 1.0;
    panel.add(lWeeklyDays, gbc);
    gbc.insets.left = 10;
    gbc.gridwidth = 1;
    for (JCheckBox cb : weekDays)
    {
      gbc.gridx ++;
      panel.add(cb, gbc);
    }
    gbc.weightx = 1.0;
    gbc.insets.left = 0;
    gbc.gridwidth = 1;
    gbc.gridx ++;
    panel.add(Box.createHorizontalGlue(), gbc);
    return panel;
  }
  private Component createMonthlyPanel()
  {
    JPanel panel = new JPanel(new GridBagLayout());
    panel.setOpaque(false);
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.weightx = 0.0;
    lMonthlyTime =
      Utilities.createPrimaryLabel(INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TIME.get());
    monthlyTime = Utilities.createShortTextField();
    PlainDocument plainTextDocument = new PlainDocument();
    monthlyTime.setDocument(plainTextDocument);
    monthlyTime.setColumns(4);
    monthlyTime.setText("00:00");
    plainTextDocument.setDocumentFilter(new TimeDocumentFilter(monthlyTime));
    lMonthlyDays = Utilities.createPrimaryLabel(INFO_CTRL_PANEL_DAYS.get());
    gbc.anchor = GridBagConstraints.WEST;
    panel.add(lMonthlyTime, gbc);
    gbc.gridx = 1;
    gbc.insets.left = 10;
    gbc.fill = GridBagConstraints.NONE;
    gbc.gridwidth = 7;
    panel.add(monthlyTime, gbc);
    gbc.gridx = 2;
    gbc.weightx = 1.0;
    gbc.insets.left = 0;
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    panel.add(Box.createHorizontalGlue(), gbc);
    gbc.gridx = 0;
    gbc.gridy ++;
    gbc.insets.top = 10;
    gbc.weightx = 1.0;
    gbc.gridwidth = 1;
    panel.add(lMonthlyDays, gbc);
    gbc.insets.left = 10;
    gbc.gridwidth = 1;
    for (int i=0 ; i<monthDays.length; i++)
    {
      monthDays[i] = Utilities.createCheckBox(Message.raw(String.valueOf(i+1)));
      monthDays[i].setFont(ColorAndFontConstants.inlineHelpFont);
      int x = i % 7;
      if (x == 0 && i != 0)
      {
        gbc.gridy ++;
        gbc.insets.top = 5;
      }
      if (x != 0)
      {
        gbc.insets.left = 5;
      }
      else
      {
        gbc.insets.left = 10;
      }
      gbc.gridx = x + 1;
      panel.add(monthDays[i], gbc);
    }
    monthDays[0].setSelected(true);
    gbc.weightx = 1.0;
    gbc.insets.left = 0;
    gbc.gridwidth = 1;
    gbc.gridx ++;
    panel.add(Box.createHorizontalGlue(), gbc);
    return panel;
  }
  private Component createCronPanel()
  {
    JPanel panel = new JPanel(new GridBagLayout());
    panel.setOpaque(false);
    GridBagConstraints gbc = new GridBagConstraints();
    JEditorPane explanation = Utilities.makeHtmlPane(
        INFO_CTRL_PANEL_CRON_HELP.get().toString(),
        ColorAndFontConstants.inlineHelpFont);
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.gridwidth = 2;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    panel.add(explanation, gbc);
    gbc.gridy ++;
    gbc.insets.top = 10;
    gbc.gridwidth = 1;
    lCronMinute = Utilities.createPrimaryLabel(
        INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_MINUTE.get());
    lCronHour = Utilities.createPrimaryLabel(
        INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_HOUR.get());
    lCronWeekDay = Utilities.createPrimaryLabel(
        INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_WEEK_DAY.get());
    lCronMonthDay = Utilities.createPrimaryLabel(
        INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_MONTH_DAY.get());
    lCronMonth = Utilities.createPrimaryLabel(
        INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_MONTH.get());
    cronMinute = Utilities.createShortTextField();
    cronMinute.setText("*");
    cronHour = Utilities.createShortTextField();
    cronHour.setText("*");
    cronWeekDay = Utilities.createShortTextField();
    cronWeekDay.setText("*");
    cronMonthDay = Utilities.createShortTextField();
    cronMonthDay.setText("*");
    cronMonth = Utilities.createShortTextField();
    cronMonth.setText("*");
    JLabel[] labels = {lCronMinute, lCronHour, lCronWeekDay, lCronMonthDay,
        lCronMonth};
    Component[] comps = {cronMinute, cronHour, cronWeekDay, cronMonthDay,
        cronMonth};
    Message[] help =
    {
      INFO_CTRL_PANEL_CRON_MINUTE_HELP.get(),
      INFO_CTRL_PANEL_CRON_HOUR_HELP.get(),
      INFO_CTRL_PANEL_CRON_WEEK_DAY_HELP.get(),
      INFO_CTRL_PANEL_CRON_MONTH_DAY_HELP.get(),
      INFO_CTRL_PANEL_CRON_MONTH_HELP.get(),
    };
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    for (int i=0; i<labels.length; i++)
    {
      gbc.gridx = 0;
      gbc.weightx = 0.0;
      gbc.insets.left = 0;
      panel.add(labels[i], gbc);
      gbc.gridx = 1;
      gbc.insets.left = 10;
      panel.add(comps[i], gbc);
      gbc.gridx = 2;
      gbc.weightx = 1.0;
      gbc.insets.left = 0;
      panel.add(Box.createHorizontalGlue(), gbc);
      if (help[i] != null)
      {
        gbc.insets.top = 3;
        gbc.insets.left = 10;
        gbc.gridy ++;
        gbc.gridx = 1;
        panel.add(Utilities.createInlineHelpLabel(help[i]), gbc);
      }
      gbc.insets.top = 10;
      gbc.gridy ++;
    }
    gbc.insets.top = 0;
    gbc.weighty = 1.0;
    gbc.fill = GridBagConstraints.VERTICAL;
    panel.add(Box.createVerticalGlue(), gbc);
    return panel;
  }
  /**
   * The main method to test this panel.
   * @param args the arguments.
   */
  public static void main(String[] args)
  {
    while (true)
    {
      TaskToSchedulePanel p = new TaskToSchedulePanel("TEST TASK");
      GenericDialog dlg = new GenericDialog(new JFrame(), p);
      dlg.setModal(true);
      dlg.setVisible(true);
    }
  }
}
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/NumericLimitedSizeDocumentFilter.java
New file
@@ -0,0 +1,116 @@
/*
 * 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
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui.components;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.JTextComponent;
/**
 * Document filter used to update properly a text component displaying a
 * numeric field with a limited size.
 */
public class NumericLimitedSizeDocumentFilter extends DocumentFilter
{
  private JTextComponent tf;
  private int maxSize;
  /**
   * Constructor.
   * @param tf the text component associated with the document.
   * @param maxSize the maximum size.
   */
  public NumericLimitedSizeDocumentFilter(JTextComponent tf, int maxSize)
  {
    this.tf = tf;
    this.maxSize = maxSize;
  }
  /**
   * {@inheritDoc}
   */
  public void insertString(DocumentFilter.FilterBypass fb, int offset,
      String text, AttributeSet attr)
  throws BadLocationException
  {
    int previousLength = fb.getDocument().getLength();
    String newText = text.replaceAll("[^0-9]", "");
    if (newText.length() > maxSize)
    {
      newText = newText.substring(0, maxSize);
    }
    if (newText.length() + previousLength > maxSize)
    {
      if (offset + newText.length() > maxSize)
      {
        int newOffset = offset + newText.length() - maxSize;
        fb.remove(0, newOffset);
        fb.insertString(newOffset, newText, attr);
      }
      else
      {
        fb.insertString(offset, newText, attr);
        fb.remove(maxSize, newText.length() + previousLength - maxSize);
      }
    }
    else
    {
      fb.insertString(offset, newText, attr);
    }
    updateCaretPosition(fb);
  }
  /**
   * {@inheritDoc}
   */
  public void replace(DocumentFilter.FilterBypass fb, int offset,
      int length, String text, AttributeSet attr)
  throws BadLocationException
  {
    if (length > 0)
    {
      fb.remove(offset, length);
    }
    insertString(fb, offset, text, attr);
  }
  private void updateCaretPosition(DocumentFilter.FilterBypass fb)
  throws BadLocationException
  {
    int totalLength = fb.getDocument().getLength();
    int caretPosition = tf.getCaretPosition();
    if ((totalLength >= maxSize) &&
        (caretPosition == fb.getDocument().getLength()))
    {
      tf.setCaretPosition(0);
    }
  }
}
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/ScheduleSummaryPanel.java
New file
@@ -0,0 +1,182 @@
/*
 * 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
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui.components;
import static org.opends.messages.AdminToolMessages.*;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.util.Date;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.opends.guitools.controlpanel.datamodel.ScheduleType;
import org.opends.guitools.controlpanel.ui.GenericDialog;
import org.opends.guitools.controlpanel.ui.TaskToSchedulePanel;
import org.opends.guitools.controlpanel.util.Utilities;
/**
 * A class used as component displaying the string representation of a schedule
 * and the possibility of updating it clicking a button.
 */
public class ScheduleSummaryPanel extends JPanel
{
  private static final long serialVersionUID = 3111141404599060028L;
  private ScheduleType schedule = ScheduleType.createLaunchNow();
  private JLabel label;
  private JButton change;
  private TaskToSchedulePanel schedulePanel;
  private GenericDialog scheduleDlg;
  private String taskName;
  private DateFormat formatter =
    DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.SHORT);
  /**
   * Default constructor.
   * @param taskName the name of the task to be scheduled.
   */
  public ScheduleSummaryPanel(String taskName)
  {
    super(new GridBagLayout());
    setOpaque(false);
    this.taskName = taskName;
    createLayout();
  }
  /**
   * Returns the schedule represented by this panel.
   * @return the schedule represented by this panel.
   */
  public ScheduleType getSchedule()
  {
    return schedule;
  }
  /**
   * Sets the schedule represented by this panel.
   * @param schedule the schedule represented by this panel.
   */
  public void setSchedule(ScheduleType schedule)
  {
    this.schedule = schedule;
    updateLabel(schedule);
  }
  /**
   * Returns whether the change button is enabled or not.
   * @return <CODE>true</CODE> if the change button is enabled and
   * <CODE>false</CODE> otherwise.
   */
  public boolean isChangeEnabled()
  {
    return change.isEnabled();
  }
  /**
   * Sets the enable state of the change button.
   * @param enable whether the change button must be enabled or not.
   */
  public void setChangeEnabled(boolean enable)
  {
    change.setEnabled(enable);
  }
  private void createLayout()
  {
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 0;
    label = Utilities.createDefaultLabel();
    change = Utilities.createButton(INFO_CTRL_PANEL_CHANGE_SCHEDULE.get());
    change.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent ev)
      {
        changeButtonClicked();
      }
    });
    updateLabel(schedule);
    gbc.fill = GridBagConstraints.NONE;
    add(label, gbc);
    gbc.gridx ++;
    gbc.insets.left = 10;
    add(change, gbc);
    gbc.gridx ++;
    gbc.weightx = 1.0;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.insets.left = 0;
    add(Box.createHorizontalGlue(), gbc);
  }
  private void updateLabel(ScheduleType schedule)
  {
    ScheduleType.Type type = schedule.getType();
    if (type == ScheduleType.Type.LAUNCH_NOW)
    {
      label.setText(INFO_CTRL_PANEL_LAUNCH_NOW_SUMMARY.get().toString());
    }
    else if (type == ScheduleType.Type.LAUNCH_LATER)
    {
      Date date = schedule.getLaunchLaterDate();
      String sDate = formatter.format(date);
      label.setText(INFO_CTRL_PANEL_LAUNCH_LATER_SUMMARY.get(sDate).toString());
    }
    else if (type == ScheduleType.Type.LAUNCH_PERIODICALLY)
    {
      String cron = schedule.getCronValue();
      label.setText(
          INFO_CTRL_PANEL_LAUNCH_PERIODICALLY_SUMMARY.get(cron).toString());
    }
    else
    {
      throw new IllegalStateException("Unknown schedule type: "+type);
    }
  }
  private void changeButtonClicked()
  {
    if (schedulePanel == null)
    {
      schedulePanel = new TaskToSchedulePanel(taskName);
      scheduleDlg = new GenericDialog(Utilities.getFrame(this), schedulePanel);
      Utilities.centerGoldenMean(scheduleDlg, Utilities.getParentDialog(this));
      scheduleDlg.setModal(true);
    }
    scheduleDlg.setVisible(true);
    if (!schedulePanel.isCancelled())
    {
      setSchedule(schedulePanel.getSchedule());
    }
  }
}
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/TimeDocumentFilter.java
New file
@@ -0,0 +1,198 @@
/*
 * 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
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui.components;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.JTextComponent;
/**
 * Document filter used to update properly a text component displaying a
 * time.
 */
public class TimeDocumentFilter extends DocumentFilter
{
  private JTextComponent tf;
  /**
   * Constructor.
   * @param tf the text component associated with the document.
   */
  public TimeDocumentFilter(JTextComponent tf)
  {
    this.tf = tf;
  }
  /**
   * {@inheritDoc}
   */
  public void insertString(DocumentFilter.FilterBypass fb, int offset,
      String text, AttributeSet attr)
  throws BadLocationException
  {
    int previousLength = fb.getDocument().getLength();
    fb.insertString(offset, text.replaceAll("[^0-9]", ""), attr);
    trimPosition(fb, text, offset, previousLength);
  }
  /**
   * {@inheritDoc}
   */
  public void remove(DocumentFilter.FilterBypass fb, int offset,
      int length)
  throws BadLocationException
  {
    String text = fb.getDocument().getText(offset, length);
    int index = text.indexOf(":");
    if (index == -1)
    {
      fb.remove(offset, length);
    }
    else
    {
      // index value is relative to offset
      if (index > 0)
      {
        fb.remove(offset, index);
      }
      if (index < length - 1)
      {
        fb.remove(offset + index + 1, length - index -1);
      }
    }
    updateCaretPosition(fb);
  }
  /**
   * {@inheritDoc}
   */
  public void replace(DocumentFilter.FilterBypass fb, int offset,
      int length, String text, AttributeSet attr)
  throws BadLocationException
  {
    int previousLength = fb.getDocument().getLength();
    String t = fb.getDocument().getText(offset, length);
    int index = t.indexOf(":");
    fb.replace(offset, length, text.replaceAll("[^0-9]", ""), attr);
    if (index != -1)
    {
      if (fb.getDocument().getLength() >= 2)
      {
        fb.insertString(2, ":", attr);
      }
      else
      {
        fb.insertString(fb.getDocument().getLength(), ":", attr);
      }
    }
    trimPosition(fb, text, offset, previousLength);
  }
  private void trimPosition(DocumentFilter.FilterBypass fb, String newText,
      int offset, int previousLength)
  throws BadLocationException
  {
    String allText =
      fb.getDocument().getText(0, fb.getDocument().getLength());
    int index = allText.indexOf(':');
    if ((index != -1) && (newText.length() == 1))
    {
      int minuteLength = allText.length() - index - 1;
      int hourLength = index;
      if ((minuteLength > 2) || (hourLength > 2))
      {
        if (offset < previousLength)
        {
          fb.remove(offset + 1, 1);
        }
        else
        {
          fb.remove(previousLength, 1);
        }
      }
    }
    updateCaretPosition(fb);
  }
  private void updateCaretPosition(DocumentFilter.FilterBypass fb)
  throws BadLocationException
  {
    String allText =
      fb.getDocument().getText(0, fb.getDocument().getLength());
    int index = allText.indexOf(':');
    if (index != -1)
    {
      int minuteLength = allText.length() - index - 1;
      int hourLength = index;
      int caretPosition = tf.getCaretPosition();
      if ((minuteLength >= 2) &&
          (caretPosition == allText.length()))
      {
        tf.setCaretPosition(0);
      }
      else if (hourLength == caretPosition)
      {
        if (hourLength >= 2)
        {
          tf.setCaretPosition(3);
        }
        else if (hourLength == 1)
        {
          char c = allText.charAt(0);
          if (c != '0' && c != '1' && c != '2')
          {
            tf.setCaretPosition(2);
          }
        }
      }
      else if (hourLength + 1 == caretPosition)
      {
        if (hourLength == 1)
        {
          char c = allText.charAt(0);
          if (c == '0' || c == '1' || c == '2')
          {
            tf.setCaretPosition(caretPosition - 1);
          }
        }
        else if (hourLength == 0)
        {
          tf.setCaretPosition(caretPosition - 1);
        }
      }
    }
    if (allText.length() == 1)
    {
      tf.setCaretPosition(0);
    }
  }
}
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/NoLeftInsetCategoryComboBoxRenderer.java
New file
@@ -0,0 +1,71 @@
/*
 * 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
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui.renderer;
import java.awt.Component;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import org.opends.guitools.controlpanel.datamodel.CategorizedComboBoxElement;
/**
 *  This class is used simply to avoid an inset on the left for the
 *  elements of the combo box.
 *  Since this item is a CategorizedComboBoxElement of type
 *  CategorizedComboBoxElement.Type.REGULAR, it has by default an inset on
 *  the left.
 */
public class NoLeftInsetCategoryComboBoxRenderer extends CustomListCellRenderer
{
  /**
   * The constructor.
   * @param combo the combo box to be rendered.
   */
  public NoLeftInsetCategoryComboBoxRenderer(JComboBox combo)
  {
    super(combo);
  }
  /**
   * {@inheritDoc}
   */
  public Component getListCellRendererComponent(JList list, Object value,
      int index, boolean isSelected, boolean cellHasFocus)
  {
    Component comp = super.getListCellRendererComponent(list, value, index,
        isSelected, cellHasFocus);
    if (value instanceof CategorizedComboBoxElement)
    {
      CategorizedComboBoxElement element = (CategorizedComboBoxElement)value;
      String name = getStringValue(element);
      ((JLabel)comp).setText(name);
    }
    comp.setFont(defaultFont);
    return comp;
  }
}
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/TaskCellRenderer.java
New file
@@ -0,0 +1,95 @@
/*
 * 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
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 */
package org.opends.guitools.controlpanel.ui.renderer;
import java.awt.Component;
import javax.swing.BorderFactory;
import javax.swing.JTable;
import javax.swing.border.Border;
import javax.swing.table.DefaultTableCellRenderer;
import org.opends.guitools.controlpanel.ui.ColorAndFontConstants;
/**
 * Class used to render the task tables.
 */
public class TaskCellRenderer extends DefaultTableCellRenderer
{
  private static final long serialVersionUID = -84332267021523835L;
  /**
   * The border of the first column.
   * TODO: modify CustomCellRenderer to make this public.
   */
  protected final static Border column0Border =
    BorderFactory.createCompoundBorder(
      BorderFactory.createMatteBorder(0, 1, 0, 0,
          ColorAndFontConstants.gridColor),
          BorderFactory.createEmptyBorder(4, 4, 4, 4));
  /**
   * The default border.
   */
  public final static Border defaultBorder = CustomCellRenderer.defaultBorder;
  /**
   * Default constructor.
   */
  public TaskCellRenderer()
  {
    setFont(ColorAndFontConstants.tableFont);
    setOpaque(true);
    setBackground(ColorAndFontConstants.treeBackground);
    setForeground(ColorAndFontConstants.treeForeground);
  }
  /**
   * {@inheritDoc}
   */
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
        row, column);
    if (hasFocus)
    {
      setBorder(
          CustomCellRenderer.getDefaultFocusBorder(table, value, isSelected,
              row, column));
    }
    else if (column == 0)
    {
      setBorder(column0Border);
    }
    else
    {
      setBorder(defaultBorder);
    }
    return this;
  }
}
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/util/ConfigFromDirContext.java
@@ -33,6 +33,7 @@
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -67,7 +68,9 @@
import org.opends.server.admin.client.ldap.LDAPManagementContext;
import org.opends.server.admin.std.client.*;
import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn.IndexType;
import org.opends.server.config.ConfigConstants;
import org.opends.server.core.DirectoryServer;
import org.opends.server.tools.tasks.TaskEntry;
import org.opends.server.types.DN;
import org.opends.server.types.OpenDsException;
import org.opends.server.util.ServerConstants;
@@ -238,6 +241,7 @@
      new HashSet<ConnectionHandlerDescriptor>();
    Set<BackendDescriptor> bs = new HashSet<BackendDescriptor>();
    Set<DN> as = new HashSet<DN>();
    Set<TaskEntry> ts = new HashSet<TaskEntry>();
    rootMonitor = null;
    jvmMemoryUsage = null;
@@ -528,11 +532,23 @@
    }
    catch (Throwable t)
    {
      LOG.log(Level.WARNING, "Error reading configuration: "+t, t);
      LOG.log(Level.WARNING, "Error reading monitoring: "+t, t);
      OnlineUpdateException oupe = new OnlineUpdateException(
          ERR_READING_CONFIG_LDAP.get(t.toString()), t);
      ex.add(oupe);
    }
    try
    {
      updateTaskInformation(ctx, ex, ts);
    }
    catch (Throwable t)
    {
      LOG.log(Level.WARNING, "Error reading task information: "+t, t);
      OnlineUpdateException oupe = new OnlineUpdateException(
          ERR_READING_CONFIG_LDAP.get(t.toString()), t);
      ex.add(oupe);
    }
    taskEntries = Collections.unmodifiableSet(ts);
    for (ConnectionHandlerDescriptor ch : getConnectionHandlers())
    {
      ch.setMonitoringEntries(getMonitoringEntries(ch));
@@ -762,6 +778,33 @@
    }
  }
  /**
   * Takes the provided search result and updates the task information
   * accordingly.
   * @param sr the search result.
   * @param searchBaseDN the base search.
   * @param taskEntries the collection of TaskEntries to be updated.
   * @throws NamingException if there is an error retrieving the values of the
   * search result.
   */
  protected void handleTaskSearchResult(SearchResult sr, String searchBaseDN,
      Collection<TaskEntry> taskEntries)
  throws NamingException
  {
    CustomSearchResult csr = new CustomSearchResult(sr, searchBaseDN);
    try
    {
      if (isTaskEntry(csr))
      {
        taskEntries.add(new TaskEntry(csr.getEntry()));
      }
    }
    catch (OpenDsException ode)
    {
      exceptions.add(ode);
    }
  }
  private void updateMonitorInformation(InitialLdapContext ctx,
      List<OpenDsException> ex)
  {
@@ -796,6 +839,37 @@
    }
  }
  private void updateTaskInformation(InitialLdapContext ctx,
      List<OpenDsException> ex, Collection<TaskEntry> ts)
  {
    // Read monitoring information: since it is computed, it is faster
    // to get everything in just one request.
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    ctls.setReturningAttributes(
        getMonitoringAttributes());
    String filter = "(objectclass=ds-task)";
    try
    {
      LdapName jndiName = new LdapName(ConfigConstants.DN_TASK_ROOT);
      NamingEnumeration taskEntries = ctx.search(jndiName, filter, ctls);
      while (taskEntries.hasMore())
      {
        SearchResult sr = (SearchResult)taskEntries.next();
        handleTaskSearchResult(sr, ConfigConstants.DN_TASK_ROOT, ts);
      }
    }
    catch (NamingException ne)
    {
      OnlineUpdateException oue = new OnlineUpdateException(
          ERR_READING_CONFIG_LDAP.get(ne.getMessage().toString()), ne);
      ex.add(oue);
    }
  }
  private ConnectionHandlerDescriptor getConnectionHandler(
      ConnectionHandlerCfgClient connHandler, String name)
  throws OpenDsException
@@ -962,6 +1036,24 @@
    return isConnectionHandler;
  }
  private boolean isTaskEntry(CustomSearchResult csr) throws OpenDsException
  {
    boolean isTaskEntry = false;
    Set<Object> vs = csr.getAttributeValues("objectclass");
    if ((vs != null) && !vs.isEmpty())
    {
      for (Object oc : vs)
      {
        if (oc.toString().equalsIgnoreCase("ds-task"))
        {
          isTaskEntry = true;
          break;
        }
      }
    }
    return isTaskEntry;
  }
  /**
   * Commodity method to get the string representation to be used in the
   * hash maps as key.
@@ -977,11 +1069,33 @@
      ConnectionHandlerDescriptor ch)
  {
    Set<CustomSearchResult> monitorEntries = new HashSet<CustomSearchResult>();
    for (String key : hmConnectionHandlersMonitor.keySet())
    if (ch.getState() == ConnectionHandlerDescriptor.State.ENABLED)
    {
      if (key.indexOf(getKey(ch.getName())) != -1)
      for (String key : hmConnectionHandlersMonitor.keySet())
      {
        monitorEntries.add(hmConnectionHandlersMonitor.get(key));
        // The name of the connection handler does not appear necessarily in the
        // key (which is based on the DN of the monitoring entry).  In general
        // the DN contains the String specified in
        // LDAPConnectionHandler.DEFAULT_FRIENDLY_NAME, so we have to check that
        // this connection handler is the right one.
        // See org.opends.server.protocols.ldap.LDAPConnectionHandler to see
        // how the DN of the monitoring entry is generated.
        if (key.indexOf(getKey("port "+ch.getPort())) != -1)
        {
          boolean hasAllAddresses = true;
          for (InetAddress a : ch.getAddresses())
          {
            if (key.indexOf(getKey(a.getHostAddress())) == -1)
            {
              hasAllAddresses = false;
              break;
            }
          }
          if (hasAllAddresses)
          {
            monitorEntries.add(hmConnectionHandlersMonitor.get(key));
          }
        }
      }
    }
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/util/ConfigReader.java
@@ -46,6 +46,7 @@
import org.opends.server.admin.std.meta.AdministrationConnectorCfgDefn;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.tools.tasks.TaskEntry;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryEnvironmentConfig;
import org.opends.server.types.DirectoryException;
@@ -166,6 +167,11 @@
  protected Schema schema;
  /**
   * The task entries.
   **/
  protected Set<TaskEntry> taskEntries = Collections.emptySet();
  /**
   * Returns the Administrative User DNs found in the config.ldif.  The set
   * must be unmodifiable (the inheriting classes must take care of this).
   * @return the Administrative User DNs found in the config.ldif.
@@ -280,6 +286,15 @@
  }
  /**
   * Returns the task entries.
   * @return the task entries.
   */
  public Set<TaskEntry> getTaskEntries()
  {
    return taskEntries;
  }
  /**
   * Reads the schema from the files.
   * @throws ConfigException if an error occurs reading the schema.
   * @throws InitializationException if an error occurs initializing
opendj-sdk/opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java
@@ -993,6 +993,12 @@
    }
    JEditorPane pane2 = makeHtmlPane(wrappedText, font);
    pane.setPreferredSize(pane2.getPreferredSize());
    JFrame frame = getFrame(pane);
    if ((frame != null) && frame.isVisible())
    {
      frame.getRootPane().revalidate();
      frame.getRootPane().repaint();
    }
  }
  /**
opendj-sdk/opends/src/messages/messages/admin_tool.properties
@@ -1325,6 +1325,7 @@
MILD_ERR_CTRL_PANEL_RUN_BACKUP_ERROR_SUMMARY=Error during Backup
MILD_ERR_CTRL_PANEL_RUN_BACKUP_ERROR_DETAILS=An error occurred during the \
 backup.  Error code: %d.
INFO_CTRL_PANEL_BACKUP_TASK_NAME=Backup
INFO_CTRL_PANEL_OTHER_BASE_DN_TITLE=Other Base DN
MILD_ERR_CTRL_PANEL_NO_BASE_DN_PROVIDED=You must provide a base DN.
@@ -2551,3 +2552,132 @@
SEVERE_ERR_VERSION_IN_REMOTE_SERVER_NOT_FOUND=Could not find version \
 information in the remote server.  The remote LDAP server does not seem to be \
 manageable remotely by the control panel.
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TITLE='%s' Task Schedule
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_SUMMARY=Specify when the task '%s' will be \
 launched.
INFO_CTRL_PANEL_LAUNCH_NOW=Launch Now
INFO_CTRL_PANEL_LAUNCH_LATER=Launch Later
INFO_CTRL_PANEL_DAYS=Days:
INFO_CTRL_PANEL_JANUARY=January
INFO_CTRL_PANEL_FEBRUARY=February
INFO_CTRL_PANEL_MARS=Mars
INFO_CTRL_PANEL_APRIL=April
INFO_CTRL_PANEL_MAY=May
INFO_CTRL_PANEL_JUNE=June
INFO_CTRL_PANEL_JULY=July
INFO_CTRL_PANEL_AUGUST=August
INFO_CTRL_PANEL_SEPTEMBER=September
INFO_CTRL_PANEL_OCTOBER=October
INFO_CTRL_PANEL_NOVEMBER=November
INFO_CTRL_PANEL_DECEMBER=December
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TIME=Time:
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_DAY=Day:
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_MONTH=Month:
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_YEAR=Year:
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_DAILY=Launch Periodically using a Daily \
 Schedule
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_WEEKLY=Launch Periodically using a Weekly \
 Schedule
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_MONTHLY=Launch Periodically using a Monthly \
 Schedule
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_SUNDAY=Sun
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_MONDAY=Mon
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_TUESDAY=Tue
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_WEDNESDAY=Wed
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_THURSDAY=Thu
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_FRIDAY=Fri
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_SATURDAY=Sat
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON=Launch Periodically using a CRON \
 Schedule
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_MINUTE=Minute:
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_HOUR=Hour:
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_WEEK_DAY=Day of Week:
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_MONTH_DAY=Day of Month:
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_CRON_MONTH=Month:
INFO_CTRL_PANEL_CRON_MINUTE_HELP=Valid values from 0 to 59
INFO_CTRL_PANEL_CRON_HOUR_HELP=Valid values from 0 to 23
INFO_CTRL_PANEL_CRON_WEEK_DAY_HELP=Valid values from 0 to 6 (0 is Sunday, \
 1 is Monday...)
INFO_CTRL_PANEL_CRON_MONTH_DAY_HELP=From 1 to 31
INFO_CTRL_PANEL_CRON_MONTH_HELP=Valid values from 1 to 12 (1 is January, \
 2 is February...)
#
# Note that the following property contains line breaks in HTML format (<br>).
#
INFO_CTRL_PANEL_CRON_HELP=Use ',' to separate values. For example: \
 '1,4,5'.<br>Use '-' to indicate intervals.  For example '1-5'.\<br>Use '*' to \
 indicate any value.
SEVERE_ERR_CTRL_PANEL_INVALID_HOUR=The provided hour value is not valid.
SEVERE_ERR_CTRL_PANEL_INVALID_MINUTE=The provided minute value is not valid.
SEVERE_ERR_CTRL_PANEL_INVALID_DAY=The provided day value is not valid.
SEVERE_ERR_CTRL_PANEL_INVALID_TIME=The provided time value is not valid.
SEVERE_ERR_CTRL_PANEL_INVALID_DAY_IN_MONTH=The day '%d' does not exist in \
 %s.
SEVERE_ERR_CTRL_PANEL_NO_WEEK_DAY_SELECTED=You must select at least one \
 day of the week.
SEVERE_ERR_CTRL_PANEL_NO_MONTH_DAY_SELECTED=You must select at least one \
 day of the month.
SEVERE_ERR_CTRL_PANEL_DATE_ALREADY_PASSED=The provided date already passed.
SEVERE_ERR_CTRL_PANEL_NO_CRON_MINUTE_PROVIDED=No minute provided.  Use '*' \
 to indicate any value.
SEVERE_ERR_CTRL_PANEL_NO_CRON_HOUR_PROVIDED=No hour provided.  Use '*' \
 to indicate any value.
SEVERE_ERR_CTRL_PANEL_NO_CRON_MONTH_DAY_PROVIDED=No day of month \
 provided.  Use '*' to indicate any value.
SEVERE_ERR_CTRL_PANEL_NO_CRON_MONTH_PROVIDED=No month provided.  Use '*' \
 to indicate any value.
SEVERE_ERR_CTRL_PANEL_NO_CRON_WEEK_DAY_PROVIDED=No day of week provided.  \
 Use '*' to indicate any value.
SEVERE_ERR_CTRL_PANEL_NOT_VALID_CRON_MINUTE_PROVIDED=The minute value \
 provided is not valid.
SEVERE_ERR_CTRL_PANEL_NOT_VALID_CRON_HOUR_PROVIDED=The hour value \
 provided is not valid.
SEVERE_ERR_CTRL_PANEL_NOT_VALID_CRON_MONTH_DAY_PROVIDED=The day of month \
 value provided is not valid.
SEVERE_ERR_CTRL_PANEL_NOT_VALID_CRON_MONTH_PROVIDED=The month value \
 provided is not valid.
SEVERE_ERR_CTRL_PANEL_NOT_VALID_CRON_WEEK_DAY_PROVIDED=The day of week \
 value provided is not valid.
INFO_CTRL_PANEL_TASK_TO_SCHEDULE_LIST_TITLE=Scheduled Tasks
INFO_CTRL_PANEL_NO_TASKS_FOUND=- No Tasks Found -
INFO_CTRL_PANEL_CANCEL_TASK_BUTTON_LABEL=Cancel Task
INFO_CTRL_PANEL_SCHEDULED_TASK_LIST_REQUIRES_SERVER_RUNNING=To see the \
 list of scheduled tasks the server must be running and you must provide \
 authentication.
INFO_CTRL_PANEL_SCHEDULED_TASK_LIST_AUTHENTICATION=To see the list of \
 scheduled tasks you must provide authentication.
INFO_CTRL_PANEL_CANCEL_TASK_MSG=Are you sure you want to cancel the \
 selected tasks?
INFO_CTRL_PANEL_CANCEL_TASK_DESCRIPTION=Cancel Selected Tasks.
INFO_CTRL_PANEL_EQUIVALENT_CMD_TO_CANCEL_TASK=Equivalent command-line to \
 cancel task '%s':
INFO_CTRL_PANEL_TASK_CANCELABLE=Is Cancelable
INFO_CTRL_PANEL_CANCELING_TASK_SUMMARY=Canceling Tasks...
INFO_CTRL_PANEL_CANCELING_TASK_COMPLETE=The tasks were successfully \
 canceled.
INFO_CTRL_PANEL_CANCELING_TASK_SUCCESSFUL=The tasks were successfully \
 canceled.
MILD_ERR_CTRL_PANEL_CANCELING_TASK_ERROR_SUMMARY=Error canceling task
MILD_ERR_CTRL_PANEL_CANCELING_TASK_ERROR_DETAILS=An error occurred \
 canceling the selected tasks.
INFO_CTRL_PANEL_CANCEL_TASK_TITLE=Cancel Tasks
INFO_CTRL_PANEL_TASK_IS_CANCELABLE=Cancelable
INFO_CTRL_PANEL_TASK_IS_NOT_CANCELABLE=Not Cancelable
INFO_CTRL_PANEL_MANAGE_TASKS=Manage Tasks
INFO_CTRL_PANEL_CHANGE_SCHEDULE=Change...
INFO_CTRL_PANEL_LAUNCH_NOW_SUMMARY=Launch now
INFO_CTRL_PANEL_LAUNCH_LATER_SUMMARY=Launch on %s
INFO_CTRL_PANEL_LAUNCH_PERIODICALLY_SUMMARY=Launch periodically with CRON \
 schedule '%s'
MILD_ERR_CTRL_PANEL_LAUNCH_LATER_REQUIRES_SERVER_RUNNING=To be able to launch \
 tasks on a future date, the server must be running.
MILD_ERR_CTRL_PANEL_LAUNCH_SCHEDULE_REQUIRES_SERVER_RUNNING=To be able to \
 launch tasks periodically, the server must be running.
INFO_CTRL_PANEL_TASK_SPECIFIC_DETAILS=Task Specific Details
INFO_CTRL_PANEL_NO_TASK_SELECTED=-No Task Selected-
INFO_CTRL_PANEL_MULTIPLE_TASKS_SELECTED=-Multiple Tasks Selected-
INFO_CTRL_PANEL_NO_TASK_SPECIFIC_DETAILS=-No Task Specific Details-
opendj-sdk/opends/src/server/org/opends/server/backends/task/RecurringTask.java
@@ -521,7 +521,7 @@
   *         the schedule field.
   * @throws IllegalArgumentException if tab field is invalid.
   */
  private boolean[] parseTaskTabField(String tabField,
  public static boolean[] parseTaskTabField(String tabField,
    int minValue, int maxValue) throws IllegalArgumentException
  {
    boolean[] valueList = new boolean[maxValue + 1];
opendj-sdk/opends/src/server/org/opends/server/tools/tasks/TaskEntry.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2008 Sun Microsystems, Inc.
 *      Copyright 2008-2009 Sun Microsystems, Inc.
 */
package org.opends.server.tools.tasks;
@@ -66,6 +66,7 @@
  private static Map<String, Message> mapAttrToDisplayName =
          new HashMap<String, Message>();
  private int hashCode;
  // These attributes associated with the ds-task object
  // class are all handled explicitly below in the constructor
@@ -154,6 +155,68 @@
        }
      }
    }
    hashCode += id.hashCode();
    hashCode += className.hashCode();
    hashCode += state.hashCode();
    hashCode += schedStart.hashCode();
    hashCode += actStart.hashCode();
    hashCode += compTime.hashCode();
    hashCode += depends.hashCode();
    hashCode += depFailAct.hashCode();
    hashCode += logs.hashCode();
    hashCode += notifyErr.hashCode();
    hashCode += notifyComp.hashCode();
    hashCode += schedTab.hashCode();
    hashCode += taskSpecificAttrValues.hashCode();
  }
  /**
   * Retrieves a hash code for this task entry.
   *
   * @return  The hash code for this task entry.
   */
  @Override()
  public int hashCode()
  {
    return hashCode;
  }
  /**
   * {@inheritDoc}
   */
  @Override()
  public boolean equals(Object o)
  {
    if (this == o)
    {
      return true;
    }
    if (o == null)
    {
      return false;
    }
    if (! (o instanceof TaskEntry))
    {
      return false;
    }
    TaskEntry e = (TaskEntry) o;
    return e.id.equals(id) &&
    e.className.equals(className) &&
    e.state.equals(state) &&
    e.schedStart.equals(schedStart) &&
    e.actStart.equals(actStart) &&
    e.compTime.equals(compTime) &&
    e.depends.equals(depends) &&
    e.depFailAct.equals(depFailAct) &&
    e.logs.equals(logs) &&
    e.notifyErr.equals(notifyErr) &&
    e.notifyComp.equals(notifyComp) &&
    e.schedTab.equals(schedTab) &&
    e.taskSpecificAttrValues.equals(taskSpecificAttrValues);
  }
  /**
opendj-sdk/opends/src/server/org/opends/server/util/LDIFReader.java
@@ -1235,7 +1235,7 @@
   * @return A new attribute with no values, representing the
   *         attribute type and its options.
   */
  private static Attribute parseAttrDescription(String attrDescr)
  public static Attribute parseAttrDescription(String attrDescr)
  {
    AttributeBuilder builder;
    int semicolonPos = attrDescr.indexOf(';');