/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.experimental.autoingest;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.EventQueue;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import javax.swing.DefaultListSelectionModel;
import java.awt.Color;
import java.beans.PropertyChangeEvent;
import java.io.File;
import java.util.Collections;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import org.netbeans.api.options.OptionsDisplayer;
import org.openide.DialogDisplayer;
import org.openide.LifecycleManager;
import org.openide.NotifyDescriptor;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.casemodule.CaseNewAction;
import org.sleuthkit.autopsy.casemodule.CaseOpenAction;
import org.sleuthkit.autopsy.core.ServicesMonitor;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestProgressSnapshotDialog;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.CaseDeletionResult;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestManager.JobsSnapshot;
/**
* A panel for monitoring automated ingest by a cluster, and for controlling
* automated ingest for a single node within the cluster. There can be at most
* one such panel per node.
*/
public final class AutoIngestDashboard extends JPanel implements Observer {
private static final long serialVersionUID = 1L;
private static final int GENERIC_COL_MIN_WIDTH = 30;
private static final int GENERIC_COL_MAX_WIDTH = 2000;
private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280;
private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175;
private static final int ACTIVITY_TIME_COL_MIN_WIDTH = 250;
private static final int ACTIVITY_TIME_COL_MAX_WIDTH = 450;
private static final int TIME_COL_MIN_WIDTH = 30;
private static final int TIME_COL_MAX_WIDTH = 250;
private static final int TIME_COL_PREFERRED_WIDTH = 140;
private static final int NAME_COL_MIN_WIDTH = 100;
private static final int NAME_COL_MAX_WIDTH = 250;
private static final int NAME_COL_PREFERRED_WIDTH = 140;
private static final int ACTIVITY_COL_MIN_WIDTH = 70;
private static final int ACTIVITY_COL_MAX_WIDTH = 2000;
private static final int ACTIVITY_COL_PREFERRED_WIDTH = 300;
private static final int STATUS_COL_MIN_WIDTH = 55;
private static final int STATUS_COL_MAX_WIDTH = 250;
private static final int STATUS_COL_PREFERRED_WIDTH = 55;
private static final int COMPLETED_TIME_COL_MIN_WIDTH = 30;
private static final int COMPLETED_TIME_COL_MAX_WIDTH = 2000;
private static final int COMPLETED_TIME_COL_PREFERRED_WIDTH = 280;
private static final String UPDATE_TASKS_THREAD_NAME = "AID-update-tasks-%d";
private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName();
private static final Logger SYS_LOGGER = AutoIngestSystemLogger.getLogger();
private static AutoIngestDashboard instance;
private final DefaultTableModel pendingTableModel;
private final DefaultTableModel runningTableModel;
private final DefaultTableModel completedTableModel;
private AutoIngestManager manager;
private ExecutorService updateExecutor;
private boolean isPaused;
private boolean autoIngestStarted;
private Color pendingTableBackground;
private Color pendingTablelForeground;
/*
* The enum is used in conjunction with the DefaultTableModel class to
* provide table models for the JTables used to display a view of the
* pending jobs queue, running jobs list, and completed jobs list. The enum
* allows the columns of the table model to be described by either an enum
* ordinal or a column header string.
*/
private enum JobsTableModelColumns {
CASE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Case")),
DATA_SOURCE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ImageFolder")),
HOST_NAME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.HostName")),
CREATED_TIME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CreatedTime")),
STARTED_TIME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.StartedTime")),
COMPLETED_TIME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CompletedTime")),
STAGE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Stage")),
STAGE_TIME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.StageTime")),
STATUS(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Status")),
CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder")),
IS_LOCAL_JOB(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.LocalJob")),
MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath"));
private final String header;
private JobsTableModelColumns(String header) {
this.header = header;
}
private String getColumnHeader() {
return header;
}
private static final String[] headers = {
CASE.getColumnHeader(),
DATA_SOURCE.getColumnHeader(),
HOST_NAME.getColumnHeader(),
CREATED_TIME.getColumnHeader(),
STARTED_TIME.getColumnHeader(),
COMPLETED_TIME.getColumnHeader(),
STAGE.getColumnHeader(),
STATUS.getColumnHeader(),
STAGE_TIME.getColumnHeader(),
CASE_DIRECTORY_PATH.getColumnHeader(),
IS_LOCAL_JOB.getColumnHeader(),
MANIFEST_FILE_PATH.getColumnHeader()};
}
/**
* Gets the singleton automated ingest control and monitoring panel for this
* cluster node.
*
* @return The panel.
*/
public static AutoIngestDashboard getInstance() {
if (null == instance) {
/*
* Two stage construction is used here to avoid publishing a
* reference to the panel to the Observable auto ingest manager
* before object construction is complete.
*/
instance = new AutoIngestDashboard();
}
return instance;
}
/**
* Constructs a panel for monitoring automated ingest by a cluster, and for
* controlling automated ingest for a single node within the cluster.
*/
private AutoIngestDashboard() {
disableUiMenuActions();
manager = AutoIngestManager.getInstance();
pendingTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) {
private static final long serialVersionUID = 1L;
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
runningTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) {
private static final long serialVersionUID = 1L;
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
completedTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) {
private static final long serialVersionUID = 1L;
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
initComponents(); // Generated code.
setServicesStatusMessage();
initPendingJobsTable();
initRunningJobsTable();
initCompletedJobsTable();
initButtons();
/*
* Must set this flag, otherwise pop up menus don't close properly.
*/
UIManager.put("PopupMenu.consumeEventOnClose", false);
}
private void disableUiMenuActions() {
/*
* Disable the new case action in auto ingest mode.
*/
CallableSystemAction.get(CaseNewAction.class).setEnabled(false);
/*
* Disable the new case action in auto ingest mode.
*/
CallableSystemAction.get(CaseOpenAction.class).setEnabled(false);
CallableSystemAction.get(AutoIngestCaseOpenAction.class).setEnabled(false);
/*
* Permanently delete the "Open Recent Cases" item in the "Case" menu.
* This is quite drastic, as it also affects Autopsy standalone mode on
* this machine, but we need to make sure a user can't open case in
* automated ingest mode. "Open Recent Cases" item can't be disabled via
* CallableSystemAction because of how it is defined in layer.xml, i.e.
* it is defined as "folder", not "file".
*/
FileObject root = FileUtil.getConfigRoot();
FileObject openRecentCasesMenu = root.getFileObject("Menu/Case/OpenRecentCase");
if (openRecentCasesMenu != null) {
try {
openRecentCasesMenu.delete();
} catch (IOException ignore) {
}
}
}
/**
* Queries the services monitor and sets the text for the services status
* text box.
*/
private void setServicesStatusMessage() {
new SwingWorker<Void, Void>() {
String caseDatabaseServerStatus = getServiceStatus(ServicesMonitor.Service.REMOTE_CASE_DATABASE);
String keywordSearchServiceStatus = getServiceStatus(ServicesMonitor.Service.REMOTE_CASE_DATABASE);
String messagingStatus = getServiceStatus(ServicesMonitor.Service.REMOTE_CASE_DATABASE);
@Override
protected Void doInBackground() throws Exception {
caseDatabaseServerStatus = getServiceStatus(ServicesMonitor.Service.REMOTE_CASE_DATABASE);
keywordSearchServiceStatus = getServiceStatus(ServicesMonitor.Service.REMOTE_CASE_DATABASE);
messagingStatus = getServiceStatus(ServicesMonitor.Service.REMOTE_CASE_DATABASE);
return null;
}
/**
* Gets a status string for a given service.
*
* @param service The service to test.
*
* @return The status string.
*/
private String getServiceStatus(ServicesMonitor.Service service) {
String serviceStatus = NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbServicesStatusMessage.Message.Unknown");
try {
ServicesMonitor servicesMonitor = ServicesMonitor.getInstance();
serviceStatus = servicesMonitor.getServiceStatus(service.toString());
if (serviceStatus.compareTo(ServicesMonitor.ServiceStatus.UP.toString()) == 0) {
serviceStatus = NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbServicesStatusMessage.Message.Up");
} else {
serviceStatus = NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbServicesStatusMessage.Message.Down");
}
} catch (ServicesMonitor.ServicesMonitorException ex) {
SYS_LOGGER.log(Level.SEVERE, String.format("Dashboard error getting service status for %s", service), ex);
}
return serviceStatus;
}
@Override
protected void done() {
tbServicesStatusMessage.setText(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbServicesStatusMessage.Message", caseDatabaseServerStatus, keywordSearchServiceStatus, keywordSearchServiceStatus, messagingStatus));
String upStatus = NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbServicesStatusMessage.Message.Up");
if (caseDatabaseServerStatus.compareTo(upStatus) != 0
|| keywordSearchServiceStatus.compareTo(upStatus) != 0
|| messagingStatus.compareTo(upStatus) != 0) {
tbServicesStatusMessage.setForeground(Color.RED);
} else {
tbServicesStatusMessage.setForeground(Color.BLACK);
}
}
}.execute();
}
/**
* Sets up the JTable that presents a view of the system-wide pending jobs
* queue.
*/
private void initPendingJobsTable() {
/*
* Remove some of the jobs table model columns from the JTable. This
* does not remove the columns from the model, just from this table.
*/
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.HOST_NAME.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.STARTED_TIME.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.COMPLETED_TIME.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.STAGE.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.STAGE_TIME.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.IS_LOCAL_JOB.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader()));
pendingTable.removeColumn(pendingTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader()));
/*
* Set up a column to display the cases associated with the jobs.
*/
TableColumn column;
column = pendingTable.getColumn(JobsTableModelColumns.CASE.getColumnHeader());
column.setMinWidth(GENERIC_COL_MIN_WIDTH);
column.setMaxWidth(GENERIC_COL_MAX_WIDTH);
column.setPreferredWidth(PENDING_TABLE_COL_PREFERRED_WIDTH);
column.setWidth(PENDING_TABLE_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the image folders associated with the
* jobs.
*/
column = pendingTable.getColumn(JobsTableModelColumns.DATA_SOURCE.getColumnHeader());
column.setMaxWidth(GENERIC_COL_MAX_WIDTH);
column.setPreferredWidth(PENDING_TABLE_COL_PREFERRED_WIDTH);
column.setWidth(PENDING_TABLE_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the create times of the jobs.
*/
column = pendingTable.getColumn(JobsTableModelColumns.CREATED_TIME.getColumnHeader());
column.setCellRenderer(new LongDateCellRenderer());
column.setMinWidth(TIME_COL_MIN_WIDTH);
column.setMaxWidth(TIME_COL_MAX_WIDTH);
column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH);
column.setWidth(TIME_COL_PREFERRED_WIDTH);
/**
* Prevent sorting when a column header is clicked.
*/
pendingTable.setAutoCreateRowSorter(false);
/*
* Create a row selection listener to enable/disable the prioritize
* folder and prioritize case buttons.
*/
pendingTable.getSelectionModel().addListSelectionListener((ListSelectionEvent e) -> {
if (e.getValueIsAdjusting()) {
return;
}
int row = pendingTable.getSelectedRow();
enablePendingTableButtons((row >= 0) && (row < pendingTable.getRowCount()));
});
/*
* Save the background color of the table so it can be restored on
* resume, after being grayed out on pause. Note the assumption that all
* of the tables use the same background color.
*/
pendingTableBackground = pendingTable.getBackground();
pendingTablelForeground = pendingTable.getForeground();
}
/**
* Sets up the JTable that presents a view of the system-wide running jobs
* list.
*/
private void initRunningJobsTable() {
/*
* Remove some of the jobs table model columns from the JTable. This
* does not remove the columns from the model, just from this table.
*/
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.CREATED_TIME.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.STARTED_TIME.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.COMPLETED_TIME.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.IS_LOCAL_JOB.getColumnHeader()));
runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader()));
/*
* Set up a column to display the cases associated with the jobs.
*/
TableColumn column;
column = runningTable.getColumn(JobsTableModelColumns.CASE.getColumnHeader());
column.setMinWidth(GENERIC_COL_MIN_WIDTH);
column.setMaxWidth(GENERIC_COL_MAX_WIDTH);
column.setPreferredWidth(RUNNING_TABLE_COL_PREFERRED_WIDTH);
column.setWidth(RUNNING_TABLE_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the image folders associated with the
* jobs.
*/
column = runningTable.getColumn(JobsTableModelColumns.DATA_SOURCE.getColumnHeader());
column.setMinWidth(GENERIC_COL_MIN_WIDTH);
column.setMaxWidth(GENERIC_COL_MAX_WIDTH);
column.setPreferredWidth(RUNNING_TABLE_COL_PREFERRED_WIDTH);
column.setWidth(RUNNING_TABLE_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the host names of the cluster nodes
* processing the jobs.
*/
column = runningTable.getColumn(JobsTableModelColumns.HOST_NAME.getColumnHeader());
column.setMinWidth(NAME_COL_MIN_WIDTH);
column.setMaxWidth(NAME_COL_MAX_WIDTH);
column.setPreferredWidth(NAME_COL_PREFERRED_WIDTH);
column.setWidth(NAME_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the ingest activities associated with the
* jobs.
*/
column = runningTable.getColumn(JobsTableModelColumns.STAGE.getColumnHeader());
column.setMinWidth(ACTIVITY_COL_MIN_WIDTH);
column.setMaxWidth(ACTIVITY_COL_MAX_WIDTH);
column.setPreferredWidth(ACTIVITY_COL_PREFERRED_WIDTH);
column.setWidth(ACTIVITY_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the ingest activity times associated with
* the jobs.
*/
column = runningTable.getColumn(JobsTableModelColumns.STAGE_TIME.getColumnHeader());
column.setCellRenderer(new DurationCellRenderer());
column.setMinWidth(GENERIC_COL_MIN_WIDTH);
column.setMaxWidth(ACTIVITY_TIME_COL_MAX_WIDTH);
column.setPreferredWidth(ACTIVITY_TIME_COL_MIN_WIDTH);
column.setWidth(ACTIVITY_TIME_COL_MIN_WIDTH);
/*
* Prevent sorting when a column header is clicked.
*/
runningTable.setAutoCreateRowSorter(false);
/*
* Create a row selection listener to enable/disable the cancel current
* job, cancel current module, and show progress buttons.
*/
runningTable.getSelectionModel().addListSelectionListener((ListSelectionEvent e) -> {
if (e.getValueIsAdjusting()) {
return;
}
updateRunningTableButtonsBasedOnSelectedRow();
});
}
private void updateRunningTableButtonsBasedOnSelectedRow() {
int row = runningTable.getSelectedRow();
if (row >= 0 && row < runningTable.getRowCount()) {
if ((boolean) runningTableModel.getValueAt(row, JobsTableModelColumns.IS_LOCAL_JOB.ordinal())) {
enableRunningTableButtons(true);
return;
}
}
enableRunningTableButtons(false);
}
/**
* Sets up the JTable that presents a view of the system-wide competed jobs
* list.
*/
private void initCompletedJobsTable() {
/*
* Remove some of the jobs table model columns from the JTable. This
* does not remove the columns from the model, just from this table.
*/
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STARTED_TIME.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STAGE.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STAGE_TIME.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.IS_LOCAL_JOB.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.HOST_NAME.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader()));
completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader()));
/*
* Set up a column to display the cases associated with the jobs.
*/
TableColumn column;
column = completedTable.getColumn(JobsTableModelColumns.CASE.getColumnHeader());
column.setMinWidth(COMPLETED_TIME_COL_MIN_WIDTH);
column.setMaxWidth(COMPLETED_TIME_COL_MAX_WIDTH);
column.setPreferredWidth(COMPLETED_TIME_COL_PREFERRED_WIDTH);
column.setWidth(COMPLETED_TIME_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the image folders associated with the
* jobs.
*/
column = completedTable.getColumn(JobsTableModelColumns.DATA_SOURCE.getColumnHeader());
column.setMinWidth(COMPLETED_TIME_COL_MIN_WIDTH);
column.setMaxWidth(COMPLETED_TIME_COL_MAX_WIDTH);
column.setPreferredWidth(COMPLETED_TIME_COL_PREFERRED_WIDTH);
column.setWidth(COMPLETED_TIME_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the create times of the jobs.
*/
column = completedTable.getColumn(JobsTableModelColumns.CREATED_TIME.getColumnHeader());
column.setCellRenderer(new LongDateCellRenderer());
column.setMinWidth(TIME_COL_MIN_WIDTH);
column.setMaxWidth(TIME_COL_MAX_WIDTH);
column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH);
column.setWidth(TIME_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the completed times of the jobs.
*/
column = completedTable.getColumn(JobsTableModelColumns.COMPLETED_TIME.getColumnHeader());
column.setCellRenderer(new LongDateCellRenderer());
column.setMinWidth(TIME_COL_MIN_WIDTH);
column.setMaxWidth(TIME_COL_MAX_WIDTH);
column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH);
column.setWidth(TIME_COL_PREFERRED_WIDTH);
/*
* Set up a column to display the statuses of the jobs, with a cell
* renderer that will choose an icon to represent the job status.
*/
column = completedTable.getColumn(JobsTableModelColumns.STATUS.getColumnHeader());
column.setCellRenderer(new CaseStatusIconCellRenderer());
column.setMinWidth(STATUS_COL_MIN_WIDTH);
column.setMaxWidth(STATUS_COL_MAX_WIDTH);
column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH);
column.setWidth(STATUS_COL_PREFERRED_WIDTH);
/*
* Prevent sorting when a column header is clicked.
*/
completedTable.setAutoCreateRowSorter(false);
/*
* Create a row selection listener to enable/disable the delete case and
* show log buttons.
*/
completedTable.getSelectionModel()
.addListSelectionListener((ListSelectionEvent e) -> {
if (e.getValueIsAdjusting()) {
return;
}
int row = completedTable.getSelectedRow();
boolean enabled = row >= 0 && row < completedTable.getRowCount();
bnDeleteCase.setEnabled(enabled);
bnShowCaseLog.setEnabled(enabled);
bnReprocessJob.setEnabled(enabled);
});
}
/**
* Sets the initial state of the buttons on the panel.
*/
private void initButtons() {
bnOptions.setEnabled(true);
bnDeleteCase.setEnabled(false);
enablePendingTableButtons(false);
bnShowCaseLog.setEnabled(false);
bnReprocessJob.setEnabled(false);
bnPause.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnStart.text"));
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnStart.toolTipText"));
bnPause.setEnabled(true); //initial label for bnPause is 'Start' and it's enabled for user to start the process
bnRefresh.setEnabled(false); //at initial stage, nothing to refresh
enableRunningTableButtons(false);
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnStart.startMessage"));
}
/**
* Enables or disables buttons related to the running jobs table.
*
* @param enable Enable/disable the buttons.
*/
private void enableRunningTableButtons(Boolean enable) {
bnCancelJob.setEnabled(enable);
bnCancelModule.setEnabled(enable);
bnShowProgress.setEnabled(enable);
}
/**
* Enables or disables buttons related to pending jobs table.
*
* @param enable Enable/disable the buttons.
*/
private void enablePendingTableButtons(Boolean enable) {
bnPrioritizeCase.setEnabled(enable);
bnPrioritizeJob.setEnabled(enable);
}
/**
* Starts up the auto ingest manager and adds this panel as an observer,
* subscribes to services monitor events and starts a task to populate the
* auto ingest job tables. The Refresh and Pause buttons are enabled.
*/
private void startUp() {
/*
* Starts up the auto ingest manager (AIM).
*/
try {
manager.startUp();
autoIngestStarted = true;
} catch (AutoIngestManager.AutoIngestManagerStartupException ex) {
SYS_LOGGER.log(Level.SEVERE, "Dashboard error starting up auto ingest", ex);
tbStatusMessage.setText(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.AutoIngestStartupError"));
manager = null;
JOptionPane.showMessageDialog(this,
NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.AutoIngestStartupFailed.Message"),
NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.AutoIngestStartupFailed.Title"),
JOptionPane.ERROR_MESSAGE);
bnOptions.setEnabled(true);
/*
* If the AIM cannot be started, there is nothing more to do.
*/
return;
}
/*
* Subscribe to services monitor events.
*/
ServicesMonitor.getInstance().addSubscriber((PropertyChangeEvent evt) -> {
setServicesStatusMessage();
});
/*
* Register with the AIM as an observer.
*/
manager.addObserver(this);
/*
* Populate the pending, running, and completed auto ingest job tables.
*/
updateExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(UPDATE_TASKS_THREAD_NAME).build());
updateExecutor.submit(new UpdateAllJobsTablesTask());
manager.scanInputDirsNow();
//bnPause.setEnabled(true);
bnPause.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPause.text"));
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPause.toolTipText"));
bnRefresh.setEnabled(true);
bnOptions.setEnabled(false);
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPause.running"));
}
/**
* Shuts down auto ingest by shutting down the auto ingest manager and doing
* an application exit.
*/
public void shutdown() {
/*
* Confirm that the user wants to proceed, letting him or her no that if
* there is a currently running job it will be cancelled. TODO (RC): If
* a wait cursor is provided, this could perhaps be made conditional on
* a running job check again. Or the simple check in isLocalJobRunning
* could be used. Was this previously used and I removed it thinking it
* was grabbing the monitor?
*/
Object[] options = {
NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.OK"),
NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.Cancel")};
int reply = JOptionPane.OK_OPTION;
if (null != manager && IngestManager.getInstance().isIngestRunning()) {
reply = JOptionPane.showOptionDialog(this,
NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.ExitConsequences"),
NbBundle.getMessage(AutoIngestDashboard.class, "ConfirmationDialog.ConfirmExitHeader"),
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null,
options,
options[JOptionPane.NO_OPTION]);
}
if (reply == JOptionPane.OK_OPTION) {
/*
* Provide user feedback. Call setCursor on this to ensure it
* appears (if there is time to see it).
*/
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.ExitingStatus"));
/*
* Shut down the table refresh task executor.
*/
if (null != updateExecutor) {
updateExecutor.shutdownNow();
}
/*
* Stop observing the auto ingest manager (AIM).
*/
if (null != manager) {
manager.deleteObserver(this);
}
/*
* Shut down the AIM and close.
*/
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
if (null != manager) {
manager.shutDown();
}
return null;
}
@Override
protected void done() {
AutoIngestDashboard.this.setCursor(Cursor.getDefaultCursor());
LifecycleManager.getDefault().exit();
}
}.execute();
}
}
/**
* @inheritDoc
*/
@NbBundle.Messages({
"AutoIngestDashboard.bnPause.paused=Paused",
"AutoIngestDashboard.PauseDueToDatabaseServiceDown=Paused, unable to communicate with case database service.",
"AutoIngestDashboard.PauseDueToKeywordSearchServiceDown=Paused, unable to communicate with keyword search service.",
"AutoIngestDashboard.PauseDueToCoordinationServiceDown=Paused, unable to communicate with coordination service.",
"AutoIngestDashboard.PauseDueToWriteStateFilesFailure=Paused, unable to write to shared images or cases location.",
"AutoIngestDashboard.PauseDueToSharedConfigError=Paused, unable to update shared configuration.",
"AutoIngestDashboard.PauseDueToIngestJobStartFailure=Paused, unable to start ingest job processing.",
"AutoIngestDashboard.PauseDueToFileExporterError=Paused, unable to load File Exporter settings.",
"AutoIngestDashboard.bnPause.running=Running",
"AutoIngestDashboard.bnStart.startMessage=Waiting to start",
"AutoIngestDashboard.bnStart.text=Start",
"AutoIngestDashboard.bnStart.toolTipText=Start processing auto ingest jobs"
})
@Override
public void update(Observable o, Object arg) {
if (arg instanceof AutoIngestManager.Event) {
switch ((AutoIngestManager.Event) arg) {
case INPUT_SCAN_COMPLETED:
case JOB_STARTED:
case JOB_COMPLETED:
case CASE_DELETED:
updateExecutor.submit(new UpdateAllJobsTablesTask());
break;
case PAUSED_BY_REQUEST:
EventQueue.invokeLater(() -> {
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPause.paused"));
bnOptions.setEnabled(true);
bnRefresh.setEnabled(false);
isPaused = true;
});
break;
case PAUSED_FOR_SYSTEM_ERROR:
EventQueue.invokeLater(() -> {
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.PauseDueToSystemError"));
bnOptions.setEnabled(true);
bnRefresh.setEnabled(false);
pause(false);
isPaused = true;
setServicesStatusMessage();
});
break;
case RESUMED:
EventQueue.invokeLater(() -> {
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPause.running"));
});
break;
case CASE_PRIORITIZED:
updateExecutor.submit(new UpdatePendingJobsTableTask());
break;
case JOB_STATUS_UPDATED:
updateExecutor.submit(new UpdateRunningJobsTablesTask());
break;
default:
break;
}
}
}
/**
* Requests a pause of auto ingest processing by the auto ingest manager and
* handles updates to the components that implement the pause and resume
* feature. Note that this feature is needed to get around restrictions on
* changing ingest module selections and settings while an ingest job is
* running, and that the auto ingest manager will not actually pause until
* the current auto ingest job completes.
*
* @param buttonClicked Is this pause request in response to a user gesture
* or a nofification from the auto ingest manager
* (AIM)?
*/
private void pause(boolean buttonClicked) {
/**
* Gray out the cells in the pending table to give a visual indicator of
* the pausing/paused state.
*/
pendingTable.setBackground(Color.LIGHT_GRAY);
pendingTable.setForeground(Color.DARK_GRAY);
/**
* Change the pause button text and tool tip to make it a resume button.
*/
bnPause.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnResume.text"));
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPause.toolTipTextResume"));
if (buttonClicked) {
/**
* Ask the auto ingest manager to pause when it completes the
* currently running job, if any.
*/
manager.pause();
bnRefresh.setEnabled(false);
}
}
/**
* Requests a resume of auto ingest processing by the auto ingest manager
* and handles updates to the components that implement the pause and resume
* feature. Note that this feature is needed to get around restrictions on
* changing ingest module selections and settings while an ingest job is
* running, and that the auto ingest manager will not actually pause until
* the current auto ingest job completes.
*/
private void resume() {
/**
* Change the resume button text and tool tip to make it a pause button.
*/
bnOptions.setEnabled(false);
bnPause.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPause.text"));
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPause.toolTipText"));
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPause.running"));
bnRefresh.setEnabled(true);
/**
* Remove the graying out of the pending table.
*/
pendingTable.setBackground(pendingTableBackground);
pendingTable.setForeground(pendingTablelForeground);
/**
* Ask the auto ingest manager to resume processing.
*/
manager.resume();
}
/**
* A runnable task that gets the pending auto ingest jobs list from the auto
* ingest manager and queues a components refresh task for execution in the
* EDT.
*/
private class UpdatePendingJobsTableTask implements Runnable {
/**
* @inheritDoc
*/
@Override
public void run() {
List<AutoIngestJob> pendingJobs = new ArrayList<>();
manager.getJobs(pendingJobs, null, null);
EventQueue.invokeLater(new RefreshComponentsTask(pendingJobs, null, null));
}
}
/**
* A runnable task that gets the running auto ingest jobs list from the auto
* ingest manager and queues a components refresh task for execution in the
* EDT.
*/
private class UpdateRunningJobsTablesTask implements Runnable {
/**
* @inheritDoc
*/
@Override
public void run() {
List<AutoIngestJob> runningJobs = new ArrayList<>();
manager.getJobs(null, runningJobs, null);
EventQueue.invokeLater(new RefreshComponentsTask(null, runningJobs, null));
}
}
/**
* A runnable task that gets the pending, running and completed auto ingest
* jobs lists from the auto ingest manager and queues a components refresh
* task for execution in the EDT. Note that this task is frequently used
* when only the pending and updated lists definitely need to be updated.
* This is because the cost of updating the running jobs list is both very
* small and it is beneficial to keep running job status up to date if there
* is a running job.
*/
private class UpdateAllJobsTablesTask implements Runnable {
/**
* @inheritDoc
*/
@Override
public void run() {
List<AutoIngestJob> pendingJobs = new ArrayList<>();
List<AutoIngestJob> runningJobs = new ArrayList<>();
List<AutoIngestJob> completedJobs = new ArrayList<>();
manager.getJobs(pendingJobs, runningJobs, completedJobs);
// Sort the completed jobs list by completed date
Collections.sort(completedJobs, new AutoIngestJob.ReverseDateCompletedComparator());
EventQueue.invokeLater(new RefreshComponentsTask(pendingJobs, runningJobs, completedJobs));
}
}
/**
* A runnable task that refreshes the components on this panel to reflect
* the current state of one or more auto ingest job lists obtained from the
* auto ingest manager.
*/
private class RefreshComponentsTask implements Runnable {
private final List<AutoIngestJob> pendingJobs;
private final List<AutoIngestJob> runningJobs;
private final List<AutoIngestJob> completedJobs;
/**
* Constructs a runnable task that refreshes the components on this
* panel to reflect the current state of the auto ingest jobs.
*
* @param pendingJobs A list of pending jobs, may be null if the
* pending jobs are unchanged.
* @param runningJobs A list of running jobs, may be null if the
* running jobs are unchanged.
* @param completedJobs A list of completed jobs, may be null if the
* completed jobs are unchanged.
*/
RefreshComponentsTask(List<AutoIngestJob> pendingJobs, List<AutoIngestJob> runningJobs, List<AutoIngestJob> completedJobs) {
this.pendingJobs = pendingJobs;
this.runningJobs = runningJobs;
this.completedJobs = completedJobs;
}
/**
* @inheritDoc
*/
@Override
public void run() {
/*
* NOTE: There is a problem with our approach of preserving table
* row selections - what if the number of rows has changed as result
* of calling refreshTable(). Then it is possible for what used to
* be (for example) row 1 to now be in some other row or be removed
* from the table. This code will re-set the selection back to what
* it used to be before calling refreshTable(), i.e. row 1
*/
if (null != pendingJobs) {
Path currentRow = getSelectedEntry(pendingTable, pendingTableModel);
refreshTable(pendingJobs, pendingTableModel, null);
setSelectedEntry(pendingTable, pendingTableModel, currentRow);
}
if (null != runningJobs) {
if (!isLocalJobRunning()) {
enableRunningTableButtons(false);
} else {
updateRunningTableButtonsBasedOnSelectedRow();
}
Path currentRow = getSelectedEntry(runningTable, runningTableModel);
refreshTable(runningJobs, runningTableModel, null);
setSelectedEntry(runningTable, runningTableModel, currentRow);
}
if (null != completedJobs) {
Path currentRow = getSelectedEntry(completedTable, completedTableModel);
refreshTable(completedJobs, completedTableModel, null);
setSelectedEntry(completedTable, completedTableModel, currentRow);
}
}
/**
* Checks whether there is a job that is running on local AIN.
*
* @return true is local job is found, false otherwise.
*/
private boolean isLocalJobRunning() {
for (AutoIngestJob job : runningJobs) {
if (isLocalJob(job)) {
return true;
}
}
return false;
}
/**
* Checks whether or not an automated ingest job is local to this node.
*
* @param job The job.
*
* @return True or fale.
*/
private boolean isLocalJob(AutoIngestJob job) {
return job.getNodeName().equals(LOCAL_HOST_NAME);
}
/**
* Get a path representing the current selection on the table passed in.
* If there is no selection, return null.
*
* @param table The table to get
* @param tableModel The tableModel of the table to get
*
* @return a path representing the current selection
*/
Path getSelectedEntry(JTable table, DefaultTableModel tableModel) {
try {
int currentlySelectedRow = table.getSelectedRow();
if (currentlySelectedRow >= 0 && currentlySelectedRow < table.getRowCount()) {
return Paths.get(tableModel.getValueAt(currentlySelectedRow, JobsTableModelColumns.CASE.ordinal()).toString(),
tableModel.getValueAt(currentlySelectedRow, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString());
}
} catch (Exception ignored) {
return null;
}
return null;
}
/**
* Set the selection on the table to the passed-in path's item, if that
* item exists in the table. If it does not, clears the table selection.
*
* @param table The table to set
* @param tableModel The tableModel of the table to set
* @param path The path of the item to set
*/
void setSelectedEntry(JTable table, DefaultTableModel tableModel, Path path) {
if (path != null) {
try {
for (int row = 0; row < table.getRowCount(); ++row) {
Path temp = Paths.get(tableModel.getValueAt(row, JobsTableModelColumns.CASE.ordinal()).toString(),
tableModel.getValueAt(row, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString());
if (temp.compareTo(path) == 0) { // found it
table.setRowSelectionInterval(row, row);
return;
}
}
} catch (Exception ignored) {
table.clearSelection();
}
}
table.clearSelection();
}
}
/**
* Reloads the table model for an auto ingest jobs table, refreshing the
* JTable that uses the model.
*
* @param jobs The list of auto ingest jobs.
* @param tableModel The table model.
* @param comparator An optional comparator (may be null) for sorting the
* table model.
*/
private void refreshTable(List<AutoIngestJob> jobs, DefaultTableModel tableModel, Comparator<AutoIngestJob> comparator) {
try {
if (comparator != null) {
jobs.sort(comparator);
}
tableModel.setRowCount(0);
for (AutoIngestJob job : jobs) {
AutoIngestJob.StageDetails status = job.getStageDetails();
tableModel.addRow(new Object[]{
job.getManifest().getCaseName(), // CASE
job.getManifest().getDataSourcePath().getFileName(), // DATA_SOURCE
job.getNodeName(), // HOST_NAME
job.getManifest().getDateFileCreated(), // CREATED_TIME
job.getStageStartDate(), // STARTED_TIME
job.getCompletedDate(), // COMPLETED_TIME
status.getDescription(), // ACTIVITY
job.hasErrors(), // STATUS
((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // ACTIVITY_TIME
job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH
job.getNodeName().equals(LOCAL_HOST_NAME), // IS_LOCAL_JOB
job.getManifest().getFilePath()}); // MANIFEST_FILE_PATH
}
} catch (Exception ex) {
SYS_LOGGER.log(Level.SEVERE, "Dashboard error refreshing table", ex);
}
}
/**
* Get the current lists of jobs and update the UI.
*/
private void refreshTables(){
JobsSnapshot jobsSnapshot = manager.getCurrentJobsSnapshot();
refreshTable(jobsSnapshot.getCompletedJobs(), completedTableModel, null);
refreshTable(jobsSnapshot.getPendingJobs(), pendingTableModel, null);
refreshTable(jobsSnapshot.getRunningJobs(), runningTableModel, null);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
pendingScrollPane = new javax.swing.JScrollPane();
pendingTable = new javax.swing.JTable();
runningScrollPane = new javax.swing.JScrollPane();
runningTable = new javax.swing.JTable();
completedScrollPane = new javax.swing.JScrollPane();
completedTable = new javax.swing.JTable();
bnCancelJob = new javax.swing.JButton();
bnDeleteCase = new javax.swing.JButton();
lbPending = new javax.swing.JLabel();
lbRunning = new javax.swing.JLabel();
lbCompleted = new javax.swing.JLabel();
bnRefresh = new javax.swing.JButton();
bnCancelModule = new javax.swing.JButton();
bnExit = new javax.swing.JButton();
bnOptions = new javax.swing.JButton();
bnShowProgress = new javax.swing.JButton();
bnPause = new javax.swing.JButton();
bnPrioritizeCase = new javax.swing.JButton();
bnShowCaseLog = new javax.swing.JButton();
tbStatusMessage = new javax.swing.JTextField();
lbStatus = new javax.swing.JLabel();
bnPrioritizeJob = new javax.swing.JButton();
lbServicesStatus = new javax.swing.JLabel();
tbServicesStatusMessage = new javax.swing.JTextField();
bnOpenLogDir = new javax.swing.JButton();
bnReprocessJob = new javax.swing.JButton();
pendingTable.setModel(pendingTableModel);
pendingTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.pendingTable.toolTipText")); // NOI18N
pendingTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
pendingTable.setRowHeight(20);
pendingTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L;
@Override
public void setSelectionInterval(int index0, int index1) {
if (index0 == pendingTable.getSelectedRow()) {
pendingTable.clearSelection();
} else {
super.setSelectionInterval(index0, index1);
}
}
});
pendingTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
pendingScrollPane.setViewportView(pendingTable);
runningTable.setModel(runningTableModel);
runningTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.runningTable.toolTipText")); // NOI18N
runningTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
runningTable.setRowHeight(20);
runningTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L;
@Override
public void setSelectionInterval(int index0, int index1) {
if (index0 == runningTable.getSelectedRow()) {
runningTable.clearSelection();
} else {
super.setSelectionInterval(index0, index1);
}
}
});
runningTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
runningScrollPane.setViewportView(runningTable);
completedTable.setModel(completedTableModel);
completedTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.completedTable.toolTipText")); // NOI18N
completedTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
completedTable.setRowHeight(20);
completedTable.setSelectionModel(new DefaultListSelectionModel() {
private static final long serialVersionUID = 1L;
@Override
public void setSelectionInterval(int index0, int index1) {
if (index0 == completedTable.getSelectedRow()) {
completedTable.clearSelection();
} else {
super.setSelectionInterval(index0, index1);
}
}
});
completedTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
completedScrollPane.setViewportView(completedTable);
org.openide.awt.Mnemonics.setLocalizedText(bnCancelJob, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnCancelJob.text")); // NOI18N
bnCancelJob.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnCancelJob.toolTipText")); // NOI18N
bnCancelJob.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnCancelJobActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(bnDeleteCase, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnDeleteCase.text")); // NOI18N
bnDeleteCase.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnDeleteCase.toolTipText")); // NOI18N
bnDeleteCase.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnDeleteCaseActionPerformed(evt);
}
});
lbPending.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(lbPending, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.lbPending.text")); // NOI18N
lbRunning.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(lbRunning, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.lbRunning.text")); // NOI18N
lbCompleted.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(lbCompleted, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.lbCompleted.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(bnRefresh, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnRefresh.text")); // NOI18N
bnRefresh.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnRefresh.toolTipText")); // NOI18N
bnRefresh.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnRefreshActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(bnCancelModule, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnCancelModule.text")); // NOI18N
bnCancelModule.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnCancelModule.toolTipText")); // NOI18N
bnCancelModule.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnCancelModuleActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(bnExit, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnExit.text")); // NOI18N
bnExit.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnExit.toolTipText")); // NOI18N
bnExit.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnExitActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(bnOptions, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnOptions.text")); // NOI18N
bnOptions.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnOptions.toolTipText")); // NOI18N
bnOptions.setEnabled(false);
bnOptions.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnOptionsActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(bnShowProgress, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnShowProgress.text")); // NOI18N
bnShowProgress.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnShowProgress.toolTipText")); // NOI18N
bnShowProgress.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnShowProgressActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(bnPause, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPause.text")); // NOI18N
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPause.toolTipText")); // NOI18N
bnPause.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnPauseActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(bnPrioritizeCase, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPrioritizeCase.text")); // NOI18N
bnPrioritizeCase.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPrioritizeCase.toolTipText")); // NOI18N
bnPrioritizeCase.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnPrioritizeCaseActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(bnShowCaseLog, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnShowCaseLog.text")); // NOI18N
bnShowCaseLog.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnShowCaseLog.toolTipText")); // NOI18N
bnShowCaseLog.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnShowCaseLogActionPerformed(evt);
}
});
tbStatusMessage.setEditable(false);
tbStatusMessage.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbStatusMessage.text")); // NOI18N
tbStatusMessage.setBorder(null);
lbStatus.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(lbStatus, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.lbStatus.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(bnPrioritizeJob, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPrioritizeJob.text")); // NOI18N
bnPrioritizeJob.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPrioritizeJob.toolTipText")); // NOI18N
bnPrioritizeJob.setActionCommand(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPrioritizeJob.actionCommand")); // NOI18N
bnPrioritizeJob.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnPrioritizeJobActionPerformed(evt);
}
});
lbServicesStatus.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(lbServicesStatus, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.lbServicesStatus.text")); // NOI18N
tbServicesStatusMessage.setEditable(false);
tbServicesStatusMessage.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
tbServicesStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.tbServicesStatusMessage.text")); // NOI18N
tbServicesStatusMessage.setBorder(null);
org.openide.awt.Mnemonics.setLocalizedText(bnOpenLogDir, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnOpenLogDir.text")); // NOI18N
bnOpenLogDir.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnOpenLogDirActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(bnReprocessJob, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnReprocessJob.text")); // NOI18N
bnReprocessJob.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnReprocessJobActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lbPending, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pendingScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 920, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(bnPrioritizeCase, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnPrioritizeJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(bnPause)
.addGap(18, 18, 18)
.addComponent(bnRefresh, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(bnOptions)
.addGap(18, 18, 18)
.addComponent(bnOpenLogDir)
.addGap(18, 18, 18)
.addComponent(bnExit, javax.swing.GroupLayout.PREFERRED_SIZE, 94, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 920, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 920, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(bnCancelJob, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE)
.addComponent(bnShowProgress, javax.swing.GroupLayout.DEFAULT_SIZE, 116, Short.MAX_VALUE)
.addComponent(bnCancelModule, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE)
.addComponent(bnDeleteCase, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE)
.addComponent(bnShowCaseLog, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnReprocessJob, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(layout.createSequentialGroup()
.addComponent(lbStatus)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(tbStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 861, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(lbCompleted)
.addComponent(lbRunning)
.addGroup(layout.createSequentialGroup()
.addComponent(lbServicesStatus)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(tbServicesStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 861, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {bnCancelJob, bnCancelModule, bnDeleteCase, bnExit, bnOpenLogDir, bnOptions, bnPause, bnRefresh, bnShowProgress});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lbStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(tbStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lbServicesStatus, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(tbServicesStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lbPending, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pendingScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGap(82, 82, 82)
.addComponent(bnPrioritizeCase)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnPrioritizeJob)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lbRunning)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(34, 34, 34)
.addComponent(bnShowProgress)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnCancelJob)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnCancelModule))
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(68, 68, 68)
.addComponent(bnReprocessJob)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnDeleteCase)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnShowCaseLog))
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lbCompleted)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(bnExit)
.addComponent(bnOpenLogDir))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(bnPause)
.addComponent(bnRefresh)
.addComponent(bnOptions)))))
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {bnCancelJob, bnCancelModule, bnDeleteCase, bnExit, bnOpenLogDir, bnOptions, bnRefresh, bnShowProgress});
}// </editor-fold>//GEN-END:initComponents
/**
* Handles a click on the refresh button. Requests an immediate scan of the
* input folders for new jobs and queues a refresh of all three of the jobs
* tables.
*
* @param evt - The button click event.
*/
private void bnRefreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnRefreshActionPerformed
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
manager.scanInputDirsAndWait();
refreshTables();
this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}//GEN-LAST:event_bnRefreshActionPerformed
/**
* Handles a click on the delete case button. If an entry is selected that
* can be deleted, pops up a confirmation dialog. Upon confirmation, asks
* AutoIngestManager to delete the entry and asks for an updated view.
*
* @param evt The button click event.
*/
private void bnDeleteCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnDeleteCaseActionPerformed
if (completedTableModel.getRowCount() < 0 || completedTable.getSelectedRow() < 0) {
return;
}
String caseName = (String) completedTable.getValueAt(completedTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal());
Object[] options = {
org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "ConfirmationDialog.Delete"),
org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "ConfirmationDialog.DoNotDelete")
};
Object[] msgContent = {org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "ConfirmationDialog.DeleteAreYouSure") + "\"" + caseName + "\"?"};
int reply = JOptionPane.showOptionDialog(this,
msgContent,
org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "ConfirmationDialog.ConfirmDeletionHeader"),
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null,
options,
options[JOptionPane.NO_OPTION]);
if (reply == JOptionPane.YES_OPTION) {
bnDeleteCase.setEnabled(false);
bnShowCaseLog.setEnabled(false);
if (completedTableModel.getRowCount() > 0 && completedTable.getSelectedRow() >= 0) {
Path caseDirectoryPath = (Path) completedTableModel.getValueAt(completedTable.getSelectedRow(), JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal());
completedTable.clearSelection();
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
CaseDeletionResult result = manager.deleteCase(caseName, caseDirectoryPath);
refreshTables();
this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
if (CaseDeletionResult.FAILED == result) {
JOptionPane.showMessageDialog(this,
String.format("Could not delete case %s. It may be in in use.", caseName),
org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.DeletionFailed"),
JOptionPane.INFORMATION_MESSAGE);
} else if (CaseDeletionResult.PARTIALLY_DELETED == result) {
JOptionPane.showMessageDialog(this,
String.format("Could not delete case %s. See system log for details.", caseName),
org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.DeletionFailed"),
JOptionPane.INFORMATION_MESSAGE);
}
}
}
}//GEN-LAST:event_bnDeleteCaseActionPerformed
/**
* Handles a click on the cancel auto ingest job button. Cancels the
* selected job.
*
* @param evt The button click event.
*/
private void bnCancelJobActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCancelJobActionPerformed
Object[] options = {
org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "ConfirmationDialog.CancelJob"),
org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "ConfirmationDialog.DoNotCancelJob")};
int reply = JOptionPane.showOptionDialog(this,
NbBundle.getMessage(AutoIngestDashboard.class, "ConfirmationDialog.CancelJobAreYouSure"),
NbBundle.getMessage(AutoIngestDashboard.class, "ConfirmationDialog.ConfirmCancellationHeader"),
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null,
options,
options[1]);
if (reply == 0) {
/*
* Call setCursor on this to ensure it appears (if there is time to
* see it).
*/
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
manager.cancelCurrentJob();
refreshTables();
this.setCursor(Cursor.getDefaultCursor());
}
}//GEN-LAST:event_bnCancelJobActionPerformed
/**
* Handles a click on the show auto ingest job progress button. Displays an
* ingest job progress panel.
*
* @param evt The button click event.
*/
private void bnShowProgressActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowProgressActionPerformed
IngestProgressSnapshotDialog dialog = new IngestProgressSnapshotDialog(this.getTopLevelAncestor(), true);
}//GEN-LAST:event_bnShowProgressActionPerformed
/**
* Handles a click on the pause/resume auto ingest job button. Sends a
* pause/resume request to the auto ingest manager.
*
* @param evt The button click event.
*/
private void bnPauseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPauseActionPerformed
if (!autoIngestStarted) {
//put up a wait cursor during the start up operation
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
startUp();
this.setCursor(null);
//done for startup
return;
}
if (!isPaused) {
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPause.pausing"));
pause(true);
} else {
resume();
}
isPaused = !isPaused;
}//GEN-LAST:event_bnPauseActionPerformed
/**
* Handles a click on the options button. Displays the options window.
*
* @param evt The button click event.
*/
private void bnOptionsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOptionsActionPerformed
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
OptionsDisplayer.getDefault().open();
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}//GEN-LAST:event_bnOptionsActionPerformed
/**
* Handles a click on the cancel ingest module button. Cancels the currently
* running data source level ingest module for the selected job.
*
* @param evt The button click event.
*/
private void bnCancelModuleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCancelModuleActionPerformed
Object[] options = {
org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "ConfirmationDialog.CancelModule"),
org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "ConfirmationDialog.DoNotCancelModule")};
int reply = JOptionPane.showOptionDialog(this,
NbBundle.getMessage(AutoIngestDashboard.class, "ConfirmationDialog.CancelModuleAreYouSure"),
NbBundle.getMessage(AutoIngestDashboard.class, "ConfirmationDialog.ConfirmCancellationHeader"),
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null,
options,
options[1]);
if (reply == 0) {
/*
* Call setCursor on this to ensure it appears (if there is time to
* see it).
*/
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
manager.cancelCurrentDataSourceLevelIngestModule();
refreshTables();
this.setCursor(Cursor.getDefaultCursor());
}
}//GEN-LAST:event_bnCancelModuleActionPerformed
/**
* Handles a click on the exit button. Shuts down auto ingest.
*
* @param evt The button click event.
*/
private void bnExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnExitActionPerformed
shutdown();
}//GEN-LAST:event_bnExitActionPerformed
/**
* Handle a click on the prioritize case button. Requests prioritization of
* all of the auto ingest jobs for a case.
*
* @param evt The button click event.
*/
private void bnPrioritizeCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeCaseActionPerformed
if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
String caseName = (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal())).toString();
manager.prioritizeCase(caseName);
refreshTables();
pendingTable.clearSelection();
enablePendingTableButtons(false);
AutoIngestDashboard.this.setCursor(Cursor.getDefaultCursor());
}
}//GEN-LAST:event_bnPrioritizeCaseActionPerformed
/**
* Handles a click on the show log button. Displays the auto ingest job log
* for a case in NotePad.
*
* @param evt The button click event.
*/
private void bnShowCaseLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowCaseLogActionPerformed
try {
int selectedRow = completedTable.getSelectedRow();
if (selectedRow != -1) {
Path caseDirectoryPath = (Path) completedTableModel.getValueAt(selectedRow, JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal());
if (null != caseDirectoryPath) {
Path pathToLog = AutoIngestJobLogger.getLogPath(caseDirectoryPath);
if (pathToLog.toFile().exists()) {
Desktop.getDesktop().edit(pathToLog.toFile());
} else {
JOptionPane.showMessageDialog(this, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.ShowLogFailed.Message"),
org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.ShowLogFailed.Title"), JOptionPane.ERROR_MESSAGE);
}
} else {
MessageNotifyUtil.Message.warn("The case directory for this job has been deleted.");
}
}
} catch (IOException ex) {
SYS_LOGGER.log(Level.SEVERE, "Dashboard error attempting to display case auto ingest log", ex);
Object[] options = {org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "DisplayLogDialog.okay")};
JOptionPane.showOptionDialog(this,
org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "DisplayLogDialog.cannotFindLog"),
org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "DisplayLogDialog.unableToShowLogFile"),
JOptionPane.DEFAULT_OPTION,
JOptionPane.PLAIN_MESSAGE,
null,
options,
options[0]);
}
}//GEN-LAST:event_bnShowCaseLogActionPerformed
private void bnPrioritizeJobActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeJobActionPerformed
if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
Path manifestFilePath = (Path) (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.MANIFEST_FILE_PATH.ordinal()));
manager.prioritizeJob(manifestFilePath);
refreshTables();
pendingTable.clearSelection();
enablePendingTableButtons(false);
AutoIngestDashboard.this.setCursor(Cursor.getDefaultCursor());
}
}//GEN-LAST:event_bnPrioritizeJobActionPerformed
private void bnOpenLogDirActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOpenLogDirActionPerformed
Path logDirPath = Paths.get(PlatformUtil.getUserDirectory().getAbsolutePath(), "var", "log");
File logDir = logDirPath.toFile();
try {
Desktop.getDesktop().open(logDir);
} catch (IOException ex) {
DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(
String.format("Unable to open log directory %s:\n%s", logDirPath, ex.getLocalizedMessage()),
NotifyDescriptor.ERROR_MESSAGE));
}
}//GEN-LAST:event_bnOpenLogDirActionPerformed
private void bnReprocessJobActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnReprocessJobActionPerformed
if (completedTableModel.getRowCount() < 0 || completedTable.getSelectedRow() < 0) {
return;
}
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
Path manifestPath = (Path) completedTableModel.getValueAt(completedTable.getSelectedRow(), JobsTableModelColumns.MANIFEST_FILE_PATH.ordinal());
manager.reprocessJob(manifestPath);
refreshTables();
AutoIngestDashboard.this.setCursor(Cursor.getDefaultCursor());
}//GEN-LAST:event_bnReprocessJobActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton bnCancelJob;
private javax.swing.JButton bnCancelModule;
private javax.swing.JButton bnDeleteCase;
private javax.swing.JButton bnExit;
private javax.swing.JButton bnOpenLogDir;
private javax.swing.JButton bnOptions;
private javax.swing.JButton bnPause;
private javax.swing.JButton bnPrioritizeCase;
private javax.swing.JButton bnPrioritizeJob;
private javax.swing.JButton bnRefresh;
private javax.swing.JButton bnReprocessJob;
private javax.swing.JButton bnShowCaseLog;
private javax.swing.JButton bnShowProgress;
private javax.swing.JScrollPane completedScrollPane;
private javax.swing.JTable completedTable;
private javax.swing.JLabel lbCompleted;
private javax.swing.JLabel lbPending;
private javax.swing.JLabel lbRunning;
private javax.swing.JLabel lbServicesStatus;
private javax.swing.JLabel lbStatus;
private javax.swing.JScrollPane pendingScrollPane;
private javax.swing.JTable pendingTable;
private javax.swing.JScrollPane runningScrollPane;
private javax.swing.JTable runningTable;
private javax.swing.JTextField tbServicesStatusMessage;
private javax.swing.JTextField tbStatusMessage;
// End of variables declaration//GEN-END:variables
}