From 2d5ba62ec69e7ffa4b98149a9f6fef539e38251f Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Tue, 16 Jun 2009 10:48:51 +0000
Subject: [PATCH] Fix for issue 3912 (Default automatic Backup should be offered by the control panel)
---
opends/src/server/org/opends/server/tools/tasks/TaskEntry.java | 65
opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ServerDescriptor.java | 26
opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ControlPanelInfo.java | 1
opends/src/guitools/org/opends/guitools/controlpanel/ui/MonitoringAttributesViewPanel.java | 19
opends/src/guitools/org/opends/guitools/controlpanel/util/ConfigReader.java | 15
opends/src/guitools/org/opends/guitools/controlpanel/datamodel/CustomSearchResult.java | 100 +
opends/src/guitools/org/opends/guitools/controlpanel/task/CancelTaskTask.java | 261 +++
opends/src/guitools/org/opends/guitools/controlpanel/ui/TaskToSchedulePanel.java | 1178 ++++++++++++++++
opends/src/guitools/org/opends/guitools/controlpanel/ui/components/ScheduleSummaryPanel.java | 182 ++
opends/src/guitools/org/opends/guitools/controlpanel/ui/ConnectionHandlerMonitoringPanel.java | 58
opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ScheduleType.java | 206 ++
opends/src/guitools/org/opends/guitools/controlpanel/datamodel/TaskTableModel.java | 421 +++++
opends/src/guitools/org/opends/guitools/controlpanel/util/ConfigFromDirContext.java | 122 +
opends/src/guitools/org/opends/guitools/controlpanel/ui/BackupPanel.java | 30
opends/src/guitools/org/opends/guitools/controlpanel/ui/ExportLDIFPanel.java | 31
opends/src/guitools/org/opends/guitools/controlpanel/ui/ManageTasksPanel.java | 939 ++++++++++++
opends/src/guitools/org/opends/guitools/controlpanel/ui/MainActionsPane.java | 7
opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java | 61
opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/NoLeftInsetCategoryComboBoxRenderer.java | 71
opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/TaskCellRenderer.java | 95 +
opends/src/guitools/org/opends/guitools/controlpanel/ui/components/NumericLimitedSizeDocumentFilter.java | 116 +
opends/src/guitools/org/opends/guitools/controlpanel/ui/components/TimeDocumentFilter.java | 198 ++
opends/src/server/org/opends/server/util/LDIFReader.java | 2
opends/src/messages/messages/admin_tool.properties | 130 +
opends/src/server/org/opends/server/backends/task/RecurringTask.java | 2
opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java | 6
26 files changed, 4,281 insertions(+), 61 deletions(-)
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ControlPanelInfo.java b/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ControlPanelInfo.java
index 8e037ee..648406b 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ControlPanelInfo.java
+++ b/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;
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/CustomSearchResult.java b/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/CustomSearchResult.java
index 31e756d..ad540cf 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/CustomSearchResult.java
+++ b/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);
+ }
}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ScheduleType.java b/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ScheduleType.java
new file mode 100644
index 0000000..060777b
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ScheduleType.java
@@ -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;
+ }
+}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ServerDescriptor.java b/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ServerDescriptor.java
index 7f2dfbd..072aef1 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/ServerDescriptor.java
+++ b/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
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/TaskTableModel.java b/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/TaskTableModel.java
new file mode 100644
index 0000000..bc1b7e1
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/datamodel/TaskTableModel.java
@@ -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;
+ }
+}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/task/CancelTaskTask.java b/opends/src/guitools/org/opends/guitools/controlpanel/task/CancelTaskTask.java
new file mode 100644
index 0000000..f236683
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/task/CancelTaskTask.java
@@ -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;
+ }
+ }
+}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/BackupPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/BackupPanel.java
index d0be1e1..7523175 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/BackupPanel.java
+++ b/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());
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/ConnectionHandlerMonitoringPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/ConnectionHandlerMonitoringPanel.java
index e8c7709..a6c4fab 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/ConnectionHandlerMonitoringPanel.java
+++ b/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;
- }
- }
}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/ExportLDIFPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/ExportLDIFPanel.java
index 1115fb2..1686e71 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/ExportLDIFPanel.java
+++ b/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());
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/MainActionsPane.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/MainActionsPane.java
index b9aba61..3f9f2a3 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/MainActionsPane.java
+++ b/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())
{
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/ManageTasksPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/ManageTasksPanel.java
new file mode 100644
index 0000000..f013296
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/ui/ManageTasksPanel.java
@@ -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;
+ }
+ }
+}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/MonitoringAttributesViewPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/MonitoringAttributesViewPanel.java
index c92272b..6cba7f8 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/MonitoringAttributesViewPanel.java
+++ b/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());
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java
index e763fb3..0104171 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/ui/StatusGenericPanel.java
+++ b/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);
+ }
}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/TaskToSchedulePanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/TaskToSchedulePanel.java
new file mode 100644
index 0000000..d4cccab
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/ui/TaskToSchedulePanel.java
@@ -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);
+ }
+ }
+}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/NumericLimitedSizeDocumentFilter.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/NumericLimitedSizeDocumentFilter.java
new file mode 100644
index 0000000..0111c84
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/NumericLimitedSizeDocumentFilter.java
@@ -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);
+ }
+ }
+}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/ScheduleSummaryPanel.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/ScheduleSummaryPanel.java
new file mode 100644
index 0000000..b5116c1
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/ScheduleSummaryPanel.java
@@ -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());
+ }
+ }
+}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/TimeDocumentFilter.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/TimeDocumentFilter.java
new file mode 100644
index 0000000..3481373
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/ui/components/TimeDocumentFilter.java
@@ -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);
+ }
+ }
+}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/NoLeftInsetCategoryComboBoxRenderer.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/NoLeftInsetCategoryComboBoxRenderer.java
new file mode 100644
index 0000000..bca6a96
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/NoLeftInsetCategoryComboBoxRenderer.java
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/TaskCellRenderer.java b/opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/TaskCellRenderer.java
new file mode 100644
index 0000000..5575f51
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/controlpanel/ui/renderer/TaskCellRenderer.java
@@ -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;
+ }
+}
+
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/util/ConfigFromDirContext.java b/opends/src/guitools/org/opends/guitools/controlpanel/util/ConfigFromDirContext.java
index 7f6e720..9782bf1 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/util/ConfigFromDirContext.java
+++ b/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));
+ }
+ }
}
}
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/util/ConfigReader.java b/opends/src/guitools/org/opends/guitools/controlpanel/util/ConfigReader.java
index cd7c495..869ae93 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/util/ConfigReader.java
+++ b/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
diff --git a/opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java b/opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java
index 4ad5131..4618842 100644
--- a/opends/src/guitools/org/opends/guitools/controlpanel/util/Utilities.java
+++ b/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();
+ }
}
/**
diff --git a/opends/src/messages/messages/admin_tool.properties b/opends/src/messages/messages/admin_tool.properties
index 85abcc2..91dadeb 100644
--- a/opends/src/messages/messages/admin_tool.properties
+++ b/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-
\ No newline at end of file
diff --git a/opends/src/server/org/opends/server/backends/task/RecurringTask.java b/opends/src/server/org/opends/server/backends/task/RecurringTask.java
index 5c7a893..1554835 100644
--- a/opends/src/server/org/opends/server/backends/task/RecurringTask.java
+++ b/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];
diff --git a/opends/src/server/org/opends/server/tools/tasks/TaskEntry.java b/opends/src/server/org/opends/server/tools/tasks/TaskEntry.java
index 279e541..ca1f636 100644
--- a/opends/src/server/org/opends/server/tools/tasks/TaskEntry.java
+++ b/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);
}
/**
diff --git a/opends/src/server/org/opends/server/util/LDIFReader.java b/opends/src/server/org/opends/server/util/LDIFReader.java
index 3c9a1fb..bf16869 100644
--- a/opends/src/server/org/opends/server/util/LDIFReader.java
+++ b/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(';');
--
Gitblit v1.10.0