mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 10:17:41 +00:00
First cut at merging latest AIM
This commit is contained in:
parent
efed6a333b
commit
885aba8daf
@ -28,8 +28,6 @@ import java.util.logging.Level;
|
||||
* Utility for creating and checking for the existence of an automated ingest
|
||||
* alert file. The purpose of the file is to put a marker in the case directory
|
||||
* when an error or warning occurs in connection with an automated ingest job.
|
||||
* If there is an error creating an alert file, it is logged to the auto ingest
|
||||
* system log.
|
||||
*/
|
||||
final class AutoIngestAlertFile {
|
||||
|
||||
@ -54,7 +52,7 @@ final class AutoIngestAlertFile {
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
static void create(Path caseDirectoryPath) {
|
||||
static void create(Path caseDirectoryPath) throws AutoIngestAlertFileException {
|
||||
try {
|
||||
Files.createFile(caseDirectoryPath.resolve(ERROR_FILE_NAME));
|
||||
} catch (FileAlreadyExistsException ignored) {
|
||||
@ -67,15 +65,44 @@ final class AutoIngestAlertFile {
|
||||
* for that case.
|
||||
*/
|
||||
if (!exists(caseDirectoryPath)) {
|
||||
AutoIngestSystemLogger.getLogger().log(Level.SEVERE, String.format("Error creating automated ingest alert file in %s", caseDirectoryPath), ex);
|
||||
throw new AutoIngestAlertFileException(String.format("Error creating automated ingest alert file in %s", caseDirectoryPath), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when there is a problem creating an alert file.
|
||||
*/
|
||||
final static class AutoIngestAlertFileException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Constructs an exception to throw when there is a problem creating an
|
||||
* alert file.
|
||||
*
|
||||
* @param message The exception message.
|
||||
*/
|
||||
private AutoIngestAlertFileException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an exception to throw when there is a problem creating an
|
||||
* alert file.
|
||||
*
|
||||
* @param message The exception message.
|
||||
* @param cause The cause of the exception, if it was an exception.
|
||||
*/
|
||||
private AutoIngestAlertFileException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents instantiation of this utility class.
|
||||
*/
|
||||
private AutoIngestAlertFile() {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -24,23 +24,23 @@ import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
/**
|
||||
* Event published when a case is deleted by the automated ingest manager.
|
||||
*/
|
||||
public final class AutoIngestCaseDeletedEvent extends AutopsyEvent implements Serializable {
|
||||
@Immutable
|
||||
final class AutoIngestCaseDeletedEvent extends AutopsyEvent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final AutoIngestManager.CaseDeletionResult result;
|
||||
private final String caseName;
|
||||
private final String nodeName;
|
||||
|
||||
/**
|
||||
* Constructs an event that is published when a case is deleted by the
|
||||
* automated ingest manager.
|
||||
*
|
||||
* @param result The deletion result // RJCTODO: Get rid of logical
|
||||
* deletion
|
||||
* @param caseName The case name.
|
||||
* @param nodeName The host name of the node that deleted the case.
|
||||
*/
|
||||
public AutoIngestCaseDeletedEvent(AutoIngestManager.CaseDeletionResult result, String nodeName) {
|
||||
AutoIngestCaseDeletedEvent(String caseName, String nodeName) {
|
||||
super(AutoIngestManager.Event.CASE_DELETED.toString(), null, null);
|
||||
this.result = result;
|
||||
this.caseName = caseName;
|
||||
this.nodeName = nodeName;
|
||||
}
|
||||
|
||||
@ -49,8 +49,8 @@ public final class AutoIngestCaseDeletedEvent extends AutopsyEvent implements Se
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getNodeName() {
|
||||
return nodeName;
|
||||
String getCaseName() {
|
||||
return caseName;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -58,8 +58,8 @@ public final class AutoIngestCaseDeletedEvent extends AutopsyEvent implements Se
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public AutoIngestManager.CaseDeletionResult getResult() {
|
||||
return result;
|
||||
String getNodeName() {
|
||||
return nodeName;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
* Event published when an automated ingest manager prioritizes all or part of a
|
||||
* case.
|
||||
*/
|
||||
public final class AutoIngestCasePrioritizedEvent extends AutopsyEvent implements Serializable {
|
||||
public final class AutoIngestCasePrioritizedEvent extends AutopsyEvent implements Serializable { // RJCTODO: Rename to AutoIngestPrioritizationEvent
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final String caseName;
|
||||
|
@ -19,67 +19,62 @@
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="lbPending" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pendingScrollPane" min="-2" pref="920" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="bnPrioritizeCase" max="32767" attributes="0"/>
|
||||
<Component id="bnPrioritizeJob" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="lbPending" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pendingScrollPane" min="-2" pref="920" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="bnPause" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
|
||||
<Component id="bnRefresh" linkSize="1" min="-2" pref="100" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
|
||||
<Component id="bnOptions" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
|
||||
<Component id="bnOpenLogDir" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
|
||||
<Component id="bnExit" linkSize="1" min="-2" pref="94" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="bnPrioritizeCase" min="-2" pref="117" max="-2" attributes="0"/>
|
||||
<Component id="bnPrioritizeFolder" min="-2" pref="117" max="-2" attributes="0"/>
|
||||
<Component id="runningScrollPane" min="-2" pref="920" max="-2" attributes="0"/>
|
||||
<Component id="completedScrollPane" min="-2" pref="920" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="bnCancelJob" linkSize="1" pref="117" max="32767" attributes="0"/>
|
||||
<Component id="bnShowProgress" linkSize="1" pref="116" max="32767" attributes="0"/>
|
||||
<Component id="bnCancelModule" linkSize="1" alignment="0" pref="117" max="32767" attributes="0"/>
|
||||
<Component id="bnDeleteCase" linkSize="1" alignment="0" pref="117" max="32767" attributes="0"/>
|
||||
<Component id="bnShowCaseLog" max="32767" attributes="0"/>
|
||||
<Component id="bnReprocessJob" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="50" max="-2" attributes="0"/>
|
||||
<Component id="bnPause" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="50" max="-2" attributes="0"/>
|
||||
<Component id="bnRefresh" linkSize="1" min="-2" pref="100" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="50" max="-2" attributes="0"/>
|
||||
<Component id="bnOptions" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="50" max="-2" attributes="0"/>
|
||||
<Component id="bnOpenLogDir" linkSize="1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="50" max="-2" attributes="0"/>
|
||||
<Component id="bnExit" linkSize="1" min="-2" pref="94" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="runningScrollPane" min="-2" pref="920" max="-2" attributes="0"/>
|
||||
<Component id="completedScrollPane" min="-2" pref="920" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="bnCancelJob" linkSize="1" pref="117" max="32767" attributes="0"/>
|
||||
<Component id="bnShowProgress" linkSize="1" pref="116" max="32767" attributes="0"/>
|
||||
<Component id="bnCancelModule" linkSize="1" alignment="0" pref="117" max="32767" attributes="0"/>
|
||||
<Component id="bnDeleteCase" linkSize="1" alignment="0" pref="117" max="32767" attributes="0"/>
|
||||
<Component id="bnShowCaseLog" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lbStatus" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="tbStatusMessage" min="-2" pref="861" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="lbCompleted" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbRunning" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lbStatus" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="tbStatusMessage" min="-2" pref="861" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="lbCompleted" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbRunning" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lbServicesStatus" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="tbServicesStatusMessage" min="-2" pref="861" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lbServicesStatus" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="tbServicesStatusMessage" min="-2" pref="861" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -106,7 +101,7 @@
|
||||
<EmptySpace min="-2" pref="82" max="-2" attributes="0"/>
|
||||
<Component id="bnPrioritizeCase" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="bnPrioritizeFolder" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="bnPrioritizeJob" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
@ -127,9 +122,11 @@
|
||||
</Group>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="102" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="68" max="-2" attributes="0"/>
|
||||
<Component id="bnReprocessJob" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="bnDeleteCase" linkSize="2" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="bnShowCaseLog" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
@ -461,5 +458,15 @@
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnOpenLogDirActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="bnReprocessJob">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.bnReprocessJob.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnReprocessJobActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -54,10 +54,13 @@ import org.openide.LifecycleManager;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.openide.util.NbBundle;
|
||||
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.AutoIngestManager.CaseDeletionResult;
|
||||
import org.sleuthkit.autopsy.experimental.AutoIngestManager.JobsSnapshot;
|
||||
import org.sleuthkit.autopsy.experimental.configuration.OptionsDialog;
|
||||
|
||||
/**
|
||||
@ -91,7 +94,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
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 LOGGER = AutoIngestSystemLogger.getLogger();
|
||||
private static final Logger SYS_LOGGER = AutoIngestSystemLogger.getLogger();
|
||||
private static AutoIngestDashboard instance;
|
||||
private final DefaultTableModel pendingTableModel;
|
||||
private final DefaultTableModel runningTableModel;
|
||||
@ -121,7 +124,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
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"));
|
||||
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;
|
||||
|
||||
@ -144,7 +148,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
STATUS.getColumnHeader(),
|
||||
STAGE_TIME.getColumnHeader(),
|
||||
CASE_DIRECTORY_PATH.getColumnHeader(),
|
||||
IS_LOCAL_JOB.getColumnHeader()};
|
||||
IS_LOCAL_JOB.getColumnHeader(),
|
||||
MANIFEST_FILE_PATH.getColumnHeader()};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -232,6 +237,29 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
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));
|
||||
@ -249,30 +277,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a status string for a given service.
|
||||
*
|
||||
* @param service The service to test.
|
||||
*
|
||||
* @return up, down, or unknown
|
||||
*/
|
||||
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) {
|
||||
LOGGER.log(Level.SEVERE, String.format("Dashboard error getting service status for %s", service), ex);
|
||||
}
|
||||
return serviceStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the JTable that presents a view of the
|
||||
* Sets up the JTable that presents a view of the system-wide pending jobs
|
||||
* queue.
|
||||
*/
|
||||
private void initPendingJobsTable() {
|
||||
/*
|
||||
@ -287,6 +293,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
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.
|
||||
@ -344,7 +351,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the header and columns for the running auto ingest jobs table.
|
||||
* Sets up the JTable that presents a view of the system-wide running jobs
|
||||
* list.
|
||||
*/
|
||||
private void initRunningJobsTable() {
|
||||
/*
|
||||
@ -357,6 +365,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
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.
|
||||
@ -438,8 +447,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the header, columns, and selection listener for the completed
|
||||
* auto ingest jobs table.
|
||||
* Sets up the JTable that presents a view of the system-wide competed jobs
|
||||
* list.
|
||||
*/
|
||||
private void initCompletedJobsTable() {
|
||||
/*
|
||||
@ -452,6 +461,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
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.
|
||||
@ -558,11 +568,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
* @param enable Enable/disable the buttons.
|
||||
*/
|
||||
private void enablePendingTableButtons(Boolean enable) {
|
||||
// RJCTODO: Restore prioritization feature
|
||||
// bnPrioritizeCase.setEnabled(enable);
|
||||
// bnPrioritizeFolder.setEnabled(enable);
|
||||
bnPrioritizeCase.setEnabled(false);
|
||||
bnPrioritizeFolder.setEnabled(false);
|
||||
bnPrioritizeCase.setEnabled(enable);
|
||||
bnPrioritizeJob.setEnabled(enable);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -573,12 +580,12 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
private void startUp() {
|
||||
|
||||
/*
|
||||
* Start up the auto ingest manager (AIM).
|
||||
* Starts up the auto ingest manager (AIM).
|
||||
*/
|
||||
try {
|
||||
manager.startUp();
|
||||
} catch (AutoIngestManager.AutoIngestManagerStartupException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Dashboard error starting up auto ingest", ex);
|
||||
SYS_LOGGER.log(Level.SEVERE, "Dashboard error starting up auto ingest", ex);
|
||||
tbStatusMessage.setText(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.AutoIngestStartupError"));
|
||||
manager = null;
|
||||
|
||||
@ -594,20 +601,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to connect the AIM to any other auto ingest nodes (AINs) if
|
||||
* this is a cluster.
|
||||
*/
|
||||
try {
|
||||
manager.establishRemoteCommunications();
|
||||
} catch (Exception ex) {
|
||||
LOGGER.log(Level.SEVERE, "Dashboard error establishing remote communications for auto ingest", ex);
|
||||
JOptionPane.showMessageDialog(this,
|
||||
NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.AutoIngestStartupWarning.Message"),
|
||||
NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.AutoIngestStartupWarning.Title"),
|
||||
JOptionPane.WARNING_MESSAGE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Subscribe to services monitor events.
|
||||
*/
|
||||
@ -621,18 +614,10 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
manager.addObserver(this);
|
||||
|
||||
/*
|
||||
* Populate the pending, running, and completed auto ingest tables.
|
||||
* 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());
|
||||
|
||||
/*
|
||||
* TODO (RC): This does not seem right, given that the AIM does its
|
||||
* first image folder scan on start up. I think it could actually delay
|
||||
* the population of the auto ingest job tables, since the table refresh
|
||||
* and the scan both acquire the job lists manager. Does the AIM send an
|
||||
* event after a scan? Need to check this.
|
||||
*/
|
||||
manager.scanInputDirsNow();
|
||||
|
||||
bnPause.setEnabled(true);
|
||||
@ -743,7 +728,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
isPaused = true;
|
||||
});
|
||||
break;
|
||||
case PAUSED_FOR_SYSTEM_ERROR: // RJCTODO: Consider making this more detailed again, probably not, too much maintenance and is iverkill
|
||||
case PAUSED_FOR_SYSTEM_ERROR:
|
||||
EventQueue.invokeLater(() -> {
|
||||
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.PauseDueToSystemError"));
|
||||
bnOptions.setEnabled(true);
|
||||
@ -777,9 +762,9 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
* running, and that the auto ingest manager will not actually pause until
|
||||
* the current auto ingest job completes.
|
||||
*
|
||||
* @param buttonClicked Is this pause requests in response to a user gesture
|
||||
* @param buttonClicked Is this pause request in response to a user gesture
|
||||
* or a nofification from the auto ingest manager
|
||||
* (AMI)?
|
||||
* (AIM)?
|
||||
*/
|
||||
private void pause(boolean buttonClicked) {
|
||||
/**
|
||||
@ -1058,15 +1043,16 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
job.getNodeName(), // HOST_NAME
|
||||
job.getManifest().getDateFileCreated(), // CREATED_TIME
|
||||
job.getStageStartDate(), // STARTED_TIME
|
||||
job.getStageStartDate(), // COMPLETED_TIME
|
||||
job.getCompletedDate(), // COMPLETED_TIME
|
||||
status.getDescription(), // ACTIVITY
|
||||
(null != job.getCaseDirectoryPath()) ? AutoIngestAlertFile.exists(job.getCaseDirectoryPath()) : false, // STATUS // RJCTODO: awkward?
|
||||
job.hasErrors(), // STATUS
|
||||
((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // ACTIVITY_TIME
|
||||
job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH // RJCTODO: What about nulls?
|
||||
job.getNodeName().equals(LOCAL_HOST_NAME)}); // IS_LOCAL_JOB // RJCTODO: move method that also does this
|
||||
job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH
|
||||
job.getNodeName().equals(LOCAL_HOST_NAME), // IS_LOCAL_JOB
|
||||
job.getManifest().getFilePath()}); // MANIFEST_FILE_PATH
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOGGER.log(Level.SEVERE, "Dashboard error refreshing table", ex); // NON-NLS // RJCTODO: Consider AID log
|
||||
SYS_LOGGER.log(Level.SEVERE, "Dashboard error refreshing table", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1100,10 +1086,11 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
bnShowCaseLog = new javax.swing.JButton();
|
||||
tbStatusMessage = new javax.swing.JTextField();
|
||||
lbStatus = new javax.swing.JLabel();
|
||||
bnPrioritizeFolder = new javax.swing.JButton();
|
||||
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
|
||||
@ -1257,11 +1244,11 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
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(bnPrioritizeFolder, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPrioritizeFolder.text")); // NOI18N
|
||||
bnPrioritizeFolder.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.bnPrioritizeFolder.toolTipText")); // NOI18N
|
||||
bnPrioritizeFolder.addActionListener(new java.awt.event.ActionListener() {
|
||||
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.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
bnPrioritizeFolderActionPerformed(evt);
|
||||
bnPrioritizeJobActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
@ -1280,6 +1267,13 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
}
|
||||
});
|
||||
|
||||
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(
|
||||
@ -1287,53 +1281,50 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
.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()
|
||||
.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.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(bnPrioritizeCase, javax.swing.GroupLayout.PREFERRED_SIZE, 117, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(bnPrioritizeFolder, javax.swing.GroupLayout.PREFERRED_SIZE, 117, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.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)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(50, 50, 50)
|
||||
.addComponent(bnPause)
|
||||
.addGap(50, 50, 50)
|
||||
.addComponent(bnRefresh, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(50, 50, 50)
|
||||
.addComponent(bnOptions)
|
||||
.addGap(50, 50, 50)
|
||||
.addComponent(bnOpenLogDir)
|
||||
.addGap(50, 50, 50)
|
||||
.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)))
|
||||
.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))
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(lbServicesStatus)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(tbServicesStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 861, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
|
||||
.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});
|
||||
@ -1358,7 +1349,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
.addGap(82, 82, 82)
|
||||
.addComponent(bnPrioritizeCase)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(bnPrioritizeFolder)))
|
||||
.addComponent(bnPrioritizeJob)))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lbRunning)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -1374,9 +1365,11 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
.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(102, 102, 102)
|
||||
.addGap(68, 68, 68)
|
||||
.addComponent(bnReprocessJob)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(bnDeleteCase)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(bnShowCaseLog))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
@ -1419,55 +1412,47 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
* @param evt The button click event.
|
||||
*/
|
||||
private void bnDeleteCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnDeleteCaseActionPerformed
|
||||
// RJCTODO: Re-implement
|
||||
// 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")
|
||||
// };
|
||||
//
|
||||
// // Add checkbox to allow user to delete images in input folder as well
|
||||
// JCheckBox deleteInputChk = new JCheckBox("Delete input images for this case in shared input folder");
|
||||
// Object[] msgContent = {org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "ConfirmationDialog.DeleteAreYouSure") + "\"" + caseName + "\"?", deleteInputChk};
|
||||
// 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) {
|
||||
// String caseOutputFolderPath = completedTableModel.getValueAt(completedTable.getSelectedRow(), JobsTableModelColumns.CASE_FOLDER.ordinal()).toString();
|
||||
// String caseAutFilePath = completedTableModel.getValueAt(completedTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal()).toString() + CaseMetadata.getFileExtension();
|
||||
// completedTable.clearSelection();
|
||||
// this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
// AutoIngestManager.CaseDeletionResult deletionResult = manager.deleteCase(Paths.get(caseOutputFolderPath), deleteInputChk.isSelected(), caseAutFilePath);
|
||||
// this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
// if (deletionResult.getCaseDeletionStatus() == AutoIngestManager.CaseDeletionResult.Status.FAILED) {
|
||||
// JOptionPane.showMessageDialog(this, "Could not delete case " + caseName + " because it is in use",
|
||||
// org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.DeletionFailed"), JOptionPane.INFORMATION_MESSAGE);
|
||||
// } else if (deletionResult.getCaseDeletionStatus() == AutoIngestManager.CaseDeletionResult.Status.PARTIALLY_COMPLETED) {
|
||||
// String str = "Deleted case \"" + caseName + "\", but not all files could be deleted.\nTo delete these files, stop automated ingest and delete \n"
|
||||
// + caseOutputFolderPath + "\nand \n" + deletionResult.getCaseImageFolderPath() + "\nif present.";
|
||||
// JOptionPane.showMessageDialog(this, str,
|
||||
// org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.DeletionFailed"), JOptionPane.INFORMATION_MESSAGE);
|
||||
// }
|
||||
// /**
|
||||
// * Need to update both the pending jobs table and the completed
|
||||
// * jobs table since pending jobs for the deleted case are also
|
||||
// * deleted.
|
||||
// */
|
||||
// updateExecutor.submit(new UpdateAllJobsTablesTask());
|
||||
// }
|
||||
// }
|
||||
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);
|
||||
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);
|
||||
}
|
||||
updateExecutor.submit(new UpdateAllJobsTablesTask());
|
||||
}
|
||||
}
|
||||
}//GEN-LAST:event_bnDeleteCaseActionPerformed
|
||||
|
||||
/**
|
||||
@ -1583,22 +1568,15 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
* @param evt The button click event.
|
||||
*/
|
||||
private void bnPrioritizeCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeCaseActionPerformed
|
||||
// RJCTODO: Re-implement
|
||||
// if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
|
||||
// this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
// String caseName = (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal())).toString();
|
||||
// try {
|
||||
// List<AutoIngestJob> prioritizedQueue = manager.prioritizeCase(caseName);
|
||||
// refreshTable(prioritizedQueue, pendingTableModel, null);
|
||||
// } catch (IOException ex) {
|
||||
// logger.log(Level.SEVERE, String.format("Error while prioritizing case %s", caseName), ex);
|
||||
// MessageNotifyUtil.Message.error("An error occurred while prioritizing the case.");
|
||||
// } finally {
|
||||
// pendingTable.clearSelection();
|
||||
// enablePendingTableButtons(false);
|
||||
// AutoIngestDashboard.this.setCursor(Cursor.getDefaultCursor());
|
||||
// }
|
||||
// }
|
||||
if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
|
||||
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
String caseName = (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal())).toString();
|
||||
List<AutoIngestJob> prioritizedQueue = manager.prioritizeCase(caseName);
|
||||
refreshTable(prioritizedQueue, pendingTableModel, null);
|
||||
pendingTable.clearSelection();
|
||||
enablePendingTableButtons(false);
|
||||
AutoIngestDashboard.this.setCursor(Cursor.getDefaultCursor());
|
||||
}
|
||||
}//GEN-LAST:event_bnPrioritizeCaseActionPerformed
|
||||
|
||||
/**
|
||||
@ -1612,16 +1590,20 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
int selectedRow = completedTable.getSelectedRow();
|
||||
if (selectedRow != -1) {
|
||||
Path caseDirectoryPath = (Path) completedTableModel.getValueAt(selectedRow, JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal());
|
||||
Path pathToLog = AutoIngestJobLogger.getLogPath(caseDirectoryPath);
|
||||
if (pathToLog.toFile().exists()) {
|
||||
Desktop.getDesktop().edit(pathToLog.toFile());
|
||||
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 {
|
||||
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);
|
||||
MessageNotifyUtil.Message.warn("The case directory for this job has been deleted.");
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Dashboard error attempting to display case auto ingest log", 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"),
|
||||
@ -1634,25 +1616,17 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
}
|
||||
}//GEN-LAST:event_bnShowCaseLogActionPerformed
|
||||
|
||||
private void bnPrioritizeFolderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeFolderActionPerformed
|
||||
// RJCTODO: Re-implement
|
||||
// if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
|
||||
// this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
// String caseName = (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal())).toString();
|
||||
// String folderName = (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.DATA_SOURCE.ordinal())).toString();
|
||||
// try {
|
||||
// List<AutoIngestJob> prioritizedQueue = manager.prioritizeJob(caseName, folderName);
|
||||
// refreshTable(prioritizedQueue, pendingTableModel, null);
|
||||
// } catch (IOException ex) {
|
||||
// logger.log(Level.SEVERE, String.format("Error while prioritizing folder %s", folderName), ex);
|
||||
// MessageNotifyUtil.Message.error("An error occurred while prioritizing the folder.");
|
||||
// } finally {
|
||||
// pendingTable.clearSelection();
|
||||
// enablePendingTableButtons(false);
|
||||
// AutoIngestDashboard.this.setCursor(Cursor.getDefaultCursor());
|
||||
// }
|
||||
// }
|
||||
}//GEN-LAST:event_bnPrioritizeFolderActionPerformed
|
||||
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()));
|
||||
List<AutoIngestJob> prioritizedQueue = manager.prioritizeJob(manifestFilePath);
|
||||
refreshTable(prioritizedQueue, pendingTableModel, null);
|
||||
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");
|
||||
@ -1661,11 +1635,24 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
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()), // RJCTODO: Localize
|
||||
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());
|
||||
JobsSnapshot jobsSnapshot = manager.reprocessJob(manifestPath);
|
||||
refreshTable(jobsSnapshot.getCompletedJobs(), completedTableModel, null);
|
||||
refreshTable(jobsSnapshot.getPendingJobs(), pendingTableModel, null);
|
||||
refreshTable(jobsSnapshot.getRunningJobs(), runningTableModel, null);
|
||||
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;
|
||||
@ -1675,8 +1662,9 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
private javax.swing.JButton bnOptions;
|
||||
private javax.swing.JButton bnPause;
|
||||
private javax.swing.JButton bnPrioritizeCase;
|
||||
private javax.swing.JButton bnPrioritizeFolder;
|
||||
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;
|
||||
|
@ -27,13 +27,13 @@ import java.util.Date;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJob;
|
||||
|
||||
/**
|
||||
* An automated ingest job auto ingest jobs associated with a manifest file. A
|
||||
* manifest file specifies a co-located data source and a case to which the data
|
||||
* source is to be added.
|
||||
* An automated ingest job for a manifest. The manifest specifies a co-located
|
||||
* data source and a case to which the data source is to be added.
|
||||
*/
|
||||
@ThreadSafe
|
||||
public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializable {
|
||||
@ -51,14 +51,38 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
@GuardedBy("this")
|
||||
private Date stageStartDate;
|
||||
@GuardedBy("this")
|
||||
transient private DataSourceProcessor dataSourceProcessor;
|
||||
@GuardedBy("this")
|
||||
transient private IngestJob ingestJob;
|
||||
@GuardedBy("this")
|
||||
transient private boolean cancelled; // RJCTODO: Document
|
||||
@GuardedBy("this")
|
||||
transient private boolean completed; // RJCTODO: Document
|
||||
@GuardedBy("this")
|
||||
private Date completedDate;
|
||||
@GuardedBy("this")
|
||||
private boolean errorsOccurred;
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Constructs an automated ingest job for a manifest. The manifest specifies
|
||||
* a co-located data source and a case to which the data source is to be
|
||||
* added.
|
||||
*
|
||||
* @param manifest
|
||||
* @param manifest The manifest
|
||||
* @param caseDirectoryPath The path to the case directory for the job, may
|
||||
* be null.
|
||||
* @param priority The priority of the job. The higher the number,
|
||||
* the higher the priority.
|
||||
* @param nodeName If the job is in progress, the node doing the
|
||||
* processing, otherwise the locla host.
|
||||
* @param stage The processing stage for display purposes.
|
||||
* @param completedDate The date when the job was completed. Use the
|
||||
* epoch (January 1, 1970, 00:00:00 GMT) to
|
||||
* indicate the the job is not completed, i.e., new
|
||||
* Date(0L).
|
||||
*/
|
||||
AutoIngestJob(Manifest manifest, Path caseDirectoryPath, int priority, String nodeName, Stage stage) {
|
||||
// RJCTODO: The null case directory is error-prone and the nodeName is confusing.
|
||||
AutoIngestJob(Manifest manifest, Path caseDirectoryPath, int priority, String nodeName, Stage stage, Date completedDate, boolean errorsOccurred) {
|
||||
this.manifest = manifest;
|
||||
if (null != caseDirectoryPath) {
|
||||
this.caseDirectoryPath = caseDirectoryPath.toString();
|
||||
@ -69,12 +93,14 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
this.nodeName = nodeName;
|
||||
this.stage = stage;
|
||||
this.stageStartDate = manifest.getDateFileCreated();
|
||||
this.completedDate = completedDate;
|
||||
this.errorsOccurred = errorsOccurred;
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Gets the auto ingest jobmanifest.
|
||||
*
|
||||
* @return
|
||||
* @return The manifest.
|
||||
*/
|
||||
Manifest getManifest() {
|
||||
return this.manifest;
|
||||
@ -86,6 +112,7 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
*
|
||||
* @return True or false
|
||||
*/
|
||||
// RJCTODO: Use this or lose this
|
||||
synchronized boolean hasCaseDirectoryPath() {
|
||||
return (false == this.caseDirectoryPath.isEmpty());
|
||||
}
|
||||
@ -114,14 +141,21 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the priority of the job. A higher number indicates a higher
|
||||
* priority.
|
||||
*
|
||||
* @param priority The priority.
|
||||
*/
|
||||
synchronized void setPriority(Integer priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Gets the priority of the job. A higher number indicates a higher
|
||||
* priority.
|
||||
*
|
||||
* @return
|
||||
* @return The priority.
|
||||
*/
|
||||
synchronized Integer getPriority() {
|
||||
return this.priority;
|
||||
@ -143,11 +177,7 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
* @param stateStartedDate
|
||||
*/
|
||||
synchronized void setStage(Stage newState, Date stateStartedDate) {
|
||||
if (Stage.CANCELLED == this.stage && Stage.COMPLETED != newState) {
|
||||
/**
|
||||
* Do not overwrite canceling status with anything other than
|
||||
* completed status.
|
||||
*/
|
||||
if (Stage.CANCELLING == this.stage && Stage.COMPLETED != newState) {
|
||||
return;
|
||||
}
|
||||
this.stage = newState;
|
||||
@ -214,10 +244,12 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
return new StageDetails(description, startDate);
|
||||
}
|
||||
|
||||
synchronized void setDataSourceProcessor(DataSourceProcessor dataSourceProcessor) {
|
||||
this.dataSourceProcessor = dataSourceProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
*
|
||||
* @param ingestStatus
|
||||
*/
|
||||
// RJCTODO: Consider moving this class into AIM and making this private
|
||||
synchronized void setIngestJob(IngestJob ingestJob) {
|
||||
@ -226,8 +258,6 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
// RJCTODO: Consider moving this class into AIM and making this private.
|
||||
// Or move the AID into a separate package. Or do not worry about it.
|
||||
@ -235,6 +265,83 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
return this.ingestJob;
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
*/
|
||||
synchronized void cancel() {
|
||||
setStage(Stage.CANCELLING);
|
||||
cancelled = true;
|
||||
errorsOccurred = true;
|
||||
if (null != dataSourceProcessor) {
|
||||
dataSourceProcessor.cancel();
|
||||
}
|
||||
if (null != ingestJob) {
|
||||
ingestJob.cancel(IngestJob.CancellationReason.USER_CANCELLED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
*/
|
||||
synchronized boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
*/
|
||||
synchronized void setCompleted() {
|
||||
setStage(Stage.COMPLETED);
|
||||
completed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
synchronized boolean isCompleted() {
|
||||
return completed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the date the job was completed, with or without cancellation or
|
||||
* errors.
|
||||
*
|
||||
* @param completedDate The completion date.
|
||||
*/
|
||||
synchronized void setCompletedDate(Date completedDate) {
|
||||
this.completedDate = completedDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the date the job was completed, with or without cancellation or
|
||||
* errors.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
synchronized Date getCompletedDate() {
|
||||
return completedDate; // RJCTODO: Consider returning null if == 0 (epoch)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not erros occurred during the processing of the job.
|
||||
*
|
||||
* @param errorsOccurred True or false;
|
||||
*/
|
||||
synchronized void setErrorsOccurred(boolean errorsOccurred) {
|
||||
this.errorsOccurred = errorsOccurred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries whether or not erros occurred during the processing of the job.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
synchronized boolean hasErrors() {
|
||||
return this.errorsOccurred;
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO Gets name of the node associated with the job, possibly a remote
|
||||
* hose if the job is in progress.
|
||||
@ -309,30 +416,21 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom comparator that sorts the pending list with prioritized cases
|
||||
* first, then nonprioritized cases. Prioritized cases are last in, first
|
||||
* out. Nonprioritized cases are first in, first out. Prioritized times are
|
||||
* from the creation time of the "prioritized" state file. Non prioritized
|
||||
* are from the folder creation time.
|
||||
* Comparator that sorts auto ingest jobs by priority in descending order.
|
||||
*/
|
||||
public static class PriorityComparator implements Comparator<AutoIngestJob> {
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
*
|
||||
* @param o1
|
||||
* @param o2
|
||||
* @param job
|
||||
* @param anotherJob
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int compare(AutoIngestJob o1, AutoIngestJob o2) {
|
||||
Integer result = o1.getPriority().compareTo(o2.getPriority());
|
||||
if (0 != result) {
|
||||
return result;
|
||||
} else {
|
||||
return o1.getManifest().getDateFileCreated().compareTo(o2.getManifest().getDateFileCreated());
|
||||
}
|
||||
public int compare(AutoIngestJob job, AutoIngestJob anotherJob) {
|
||||
return -(job.getPriority().compareTo(anotherJob.getPriority()));
|
||||
}
|
||||
|
||||
}
|
||||
@ -364,6 +462,10 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
*/
|
||||
// RJCTODO: Combine this enum with StageDetails to make a single class.
|
||||
enum Stage {
|
||||
|
||||
PENDING("Pending"),
|
||||
@ -377,8 +479,7 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
ANALYZING_FILES("Analyzing files"),
|
||||
EXPORTING_FILES("Exporting files"),
|
||||
CANCELLING_MODULE("Cancelling module"),
|
||||
CANCELLED("Cancelled"),
|
||||
INTERRUPTED("Cancelled"),
|
||||
CANCELLING("Cancelling"),
|
||||
COMPLETED("Completed");
|
||||
|
||||
private final String displayText;
|
||||
|
@ -28,7 +28,6 @@ import java.nio.file.Paths;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
||||
import org.sleuthkit.autopsy.experimental.coordinationservice.CoordinationService;
|
||||
import org.sleuthkit.autopsy.experimental.coordinationservice.CoordinationService.Lock;
|
||||
@ -59,6 +58,7 @@ final class AutoIngestJobLogger {
|
||||
private static final String DATE_FORMAT_STRING = "yyyy/MM/dd HH:mm:ss";
|
||||
private static final SimpleDateFormat logDateFormat = new SimpleDateFormat(DATE_FORMAT_STRING);
|
||||
private final Path manifestPath;
|
||||
private final String manifestFileName;
|
||||
private final String dataSourceFileName;
|
||||
private final Path caseDirectoryPath;
|
||||
private final String hostName;
|
||||
@ -73,7 +73,7 @@ final class AutoIngestJobLogger {
|
||||
*/
|
||||
INFO,
|
||||
/**
|
||||
* Qualifies a log message about an unexpected event or condition during
|
||||
* Qualifies a log message about an unexpected event or condtion during
|
||||
* automated ingest processing.
|
||||
*/
|
||||
WARNING,
|
||||
@ -111,6 +111,7 @@ final class AutoIngestJobLogger {
|
||||
*/
|
||||
AutoIngestJobLogger(Path manifestPath, String dataSourceFileName, Path caseDirectoryPath) {
|
||||
this.manifestPath = manifestPath;
|
||||
manifestFileName = manifestPath.getFileName().toString();
|
||||
this.dataSourceFileName = dataSourceFileName;
|
||||
this.caseDirectoryPath = caseDirectoryPath;
|
||||
hostName = NetworkUtils.getLocalHostName();
|
||||
@ -119,151 +120,146 @@ final class AutoIngestJobLogger {
|
||||
/**
|
||||
* Logs the cancellation of an auto ingest job during processing.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logJobCancelled() throws InterruptedException {
|
||||
void logJobCancelled() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.WARNING, "Auto ingest job cancelled during processing");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the presence of a manifest file without a matching data source.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logMissingDataSource() throws InterruptedException {
|
||||
log(MessageCategory.ERROR, "Data source file not found"); // RJCTODO: Check for this
|
||||
void logMissingDataSource() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.ERROR, "Data source file not found");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an error identifying the type of a data source.
|
||||
* Logs a failure to extract an archived data source.
|
||||
*
|
||||
* @param dataSource The data source.
|
||||
* @param errorMessage The error.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file
|
||||
* path.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logDataSourceTypeIdError(String errorMessage) throws InterruptedException {
|
||||
log(MessageCategory.ERROR, String.format("Error identifying data source type: %s", errorMessage));
|
||||
void logFailedToExtractDataSource() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.ERROR, "Failed to extract data source from archive");
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Logs a failure to parse a Cellebrite logical report data source.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logFailedToIdentifyDataSource() throws InterruptedException {
|
||||
log(MessageCategory.ERROR, String.format("Failed to identifying data source type, cannot ingest"));
|
||||
void logFailedToParseLogicalReportDataSource() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.ERROR, "Failed to parse Cellebrite logical report data source");
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Logs a failure to identify an image data source as either a drive or
|
||||
* phone image.
|
||||
*
|
||||
* @param dataSourceType
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logDataSourceTypeId(String dataSourceType) throws InterruptedException {
|
||||
log(MessageCategory.INFO, String.format("Identified data source as %s", dataSourceType));
|
||||
void logFailedToIdentifyImageDataSource() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.ERROR, String.format("Failed to identifying data source as drive or phone image"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs cancellation of the addition of a data source to the case database.
|
||||
*
|
||||
* @param dataSourceType The data source type.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logDataSourceProcessorCancelled(String dataSourceType) throws InterruptedException { // RJCTODO: Is this used now?
|
||||
log(MessageCategory.WARNING, String.format("Cancelled adding data source to case as %s", dataSourceType));
|
||||
void logDataSourceProcessorCancelled() throws AutoIngestJobLoggerException, InterruptedException { // RJCTODO: Is this used now?
|
||||
log(MessageCategory.WARNING, "Cancelled adding data source to case");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the addition of a data source to the case database.
|
||||
*
|
||||
* @param dataSourceType The data source type.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logDataSourceAdded(String dataSourceType) throws InterruptedException {
|
||||
log(MessageCategory.INFO, String.format("Added data source to case as %s", dataSourceType));
|
||||
void logDataSourceAdded() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.INFO, "Added data source to case");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a critical error reported by a data source processor when adding a
|
||||
* data source to the case database.
|
||||
* Logs an failure adding a data source to the case database.
|
||||
*
|
||||
* @param dataSourceType The data source type.
|
||||
* @param errorMessage The error message.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logDataSourceProcessorError(String dataSourceType, String errorMessage) throws InterruptedException {
|
||||
log(MessageCategory.ERROR, String.format("Critical error adding data source to case as %s: %s", dataSourceType, errorMessage));
|
||||
void logFailedToAddDataSource() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.ERROR, "Failed to add data source to case");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a non-critical error reported by a data source processor when adding
|
||||
* a data source to the case database.
|
||||
* Logs failure of a data source to produce content.
|
||||
*
|
||||
* @param dataSourceType The data source type.
|
||||
* @param errorMessage The error message.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logDataSourceProcessorWarning(String dataSourceType, String errorMessage) throws InterruptedException {
|
||||
log(MessageCategory.WARNING, String.format("Critical error adding data source to case as %s: %s", dataSourceType, errorMessage));
|
||||
void logNoDataSourceContent() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.ERROR, "Data source failed to produce content");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an error adding a data source to the case database.
|
||||
* Logs failure to analyze a data source due to ingest job settings errors.
|
||||
*
|
||||
* @param dataSourceType The data source type.
|
||||
* @param dataSource The data source.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logFailedToAddDataSource(String dataSourceType) throws InterruptedException { // RJCTODO: Why this and logDataSourceProcessorError? Bd handling of critical vs. non-critical?
|
||||
log(MessageCategory.ERROR, String.format("Failed to add data source to case as %s", dataSourceType));
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO: Document and homogenize messages
|
||||
*
|
||||
* @param errors
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
*/
|
||||
void logIngestJobSettingsErrors(List<String> errors) throws InterruptedException {
|
||||
for (String error : errors) {
|
||||
log(MessageCategory.ERROR, String.format("Settings error, analysis of data source by ingest modules not started: %s", error));
|
||||
}
|
||||
void logIngestJobSettingsErrors() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.ERROR, "Failed to analyze data source due to settings errors");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs failure to analyze a data source due to ingest module startup
|
||||
* errors.
|
||||
*
|
||||
* @param errors The ingest module errors.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logIngestModuleStartupErrors(List<IngestModuleError> errors) throws InterruptedException {
|
||||
for (IngestModuleError error : errors) {
|
||||
log(MessageCategory.ERROR, String.format("Analysis of data source by ingest modules not started, %s startup error: %s", error.getModuleDisplayName(), error.getThrowable().getLocalizedMessage()));
|
||||
}
|
||||
void logIngestModuleStartupErrors() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.ERROR, "Failed to analyze data source due to ingest module startup errors");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -272,21 +268,27 @@ final class AutoIngestJobLogger {
|
||||
*
|
||||
* @param ex The ingest manager exception.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logAnalysisStartupError(IngestManagerException ex) throws InterruptedException {
|
||||
log(MessageCategory.ERROR, String.format("Analysis of data source by ingest modules not started: %s", ex.getLocalizedMessage()));
|
||||
void logAnalysisStartupError() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.ERROR, "Failed to analyze data source due to ingest job startup error");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the completion of analysis of a data source by the ingest modules.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logAnalysisCompleted() throws InterruptedException {
|
||||
log(MessageCategory.INFO, "Analysis of data source by ingest modules completed");
|
||||
void logAnalysisCompleted() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.INFO, "Analysis of data source completed");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -296,67 +298,79 @@ final class AutoIngestJobLogger {
|
||||
* @param cancelledModuleName The display name of the cancelled ingest
|
||||
* module.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logIngestModuleCancelled(String cancelledModuleName) throws InterruptedException {
|
||||
void logIngestModuleCancelled(String cancelledModuleName) throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.WARNING, String.format("%s analysis of data source cancelled", cancelledModuleName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the cancellation of analysis of a data source by the ingest modules.
|
||||
*
|
||||
* @param reason The reason for cancellation.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logAnalysisCancelled(String reason) throws InterruptedException {
|
||||
log(MessageCategory.WARNING, String.format("Analysis of data source by ingest modules cancelled: %s", reason));
|
||||
void logAnalysisCancelled() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.WARNING, "Analysis of data source cancelled");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs that automated file export is not enabled.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logFileExportDisabled() throws InterruptedException {
|
||||
void logFileExportDisabled() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.WARNING, "Automated file export is not enabled");
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Logs completion of file export.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logFileExportCompleted() throws InterruptedException {
|
||||
void logFileExportCompleted() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.INFO, "Automated file export completed");
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Logs failure to complete file export.
|
||||
*
|
||||
* @param ex
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logFileExportError(Exception ex) throws InterruptedException {
|
||||
log(MessageCategory.ERROR, String.format("Error exporting files: %s", ex.getMessage()));
|
||||
void logFileExportError() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.ERROR, "Error exporting files");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs discovery of a crashed auto ingest job for which recovery will be
|
||||
* attempted.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logCrashRecoveryWithRetry() throws InterruptedException {
|
||||
void logCrashRecoveryWithRetry() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.ERROR, "Detected crash while processing, reprocessing");
|
||||
}
|
||||
|
||||
@ -364,24 +378,16 @@ final class AutoIngestJobLogger {
|
||||
* Logs discovery of a crashed auto ingest job for which recovery will not
|
||||
* be attempted because the retry limit for the job has been reached.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
void logCrashRecoveryNoRetry() throws InterruptedException {
|
||||
void logCrashRecoveryNoRetry() throws AutoIngestJobLoggerException, InterruptedException {
|
||||
log(MessageCategory.ERROR, "Detected crash while processing, reached retry limit for processing");
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an unexpected runtime exception, e.g., an exception caught by the
|
||||
* automated ingest job processing exception firewall.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
*/
|
||||
void logErrorCondition(String message) throws InterruptedException {
|
||||
log(MessageCategory.ERROR, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a message to the case auto ingest log.
|
||||
* <p>
|
||||
@ -392,25 +398,55 @@ final class AutoIngestJobLogger {
|
||||
* @param category The message category.
|
||||
* @param message The message.
|
||||
*
|
||||
* @throws InterruptedException if interrupted while blocked waiting to
|
||||
* acquire an exclusive lock on the log file.
|
||||
* @throws AutoIngestJobLoggerException if there is an error writing the log
|
||||
* message.
|
||||
* @throws InterruptedException if interrupted while blocked waiting
|
||||
* to acquire an exclusive lock on the
|
||||
* log file.
|
||||
*/
|
||||
private void log(MessageCategory category, String message) throws InterruptedException {
|
||||
String prefix = String.format("Failed to write case auto ingest message (\"%s\") for %s", message, manifestPath);
|
||||
private void log(MessageCategory category, String message) throws AutoIngestJobLoggerException, InterruptedException {
|
||||
try (Lock lock = CoordinationService.getInstance(CoordinationServiceNamespace.getRoot()).tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, getLogPath(caseDirectoryPath).toString(), LOCK_TIME_OUT, LOCK_TIME_OUT_UNIT)) {
|
||||
if (null != lock) {
|
||||
File logFile = getLogPath(caseDirectoryPath).toFile();
|
||||
try (PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(logFile, logFile.exists())), true)) {
|
||||
writer.println(String.format("%s %s: %s\\%s: %-8s: %s", logDateFormat.format((Date.from(Instant.now()).getTime())), hostName, manifestPath, dataSourceFileName, category.toString(), message));
|
||||
writer.println(String.format("%s %s: %s: %s: %-8s: %s", logDateFormat.format((Date.from(Instant.now()).getTime())), hostName, manifestFileName, dataSourceFileName, category.toString(), message));
|
||||
} catch (IOException ex) {
|
||||
AutoIngestSystemLogger.getLogger().log(Level.SEVERE, String.format("%s due to I/O error", prefix), ex);
|
||||
throw new AutoIngestJobLoggerException(String.format("Failed to write case auto ingest log message (\"%s\") for %s", message, manifestPath), ex);
|
||||
}
|
||||
} else {
|
||||
AutoIngestSystemLogger.getLogger().log(Level.SEVERE, String.format("%s due to lock timeout", prefix));
|
||||
throw new AutoIngestJobLoggerException(String.format("Failed to write case auto ingest log message (\"%s\") for %s due to time out acquiring log lock", message, manifestPath));
|
||||
}
|
||||
|
||||
} catch (CoordinationServiceException ex) {
|
||||
AutoIngestSystemLogger.getLogger().log(Level.SEVERE, String.format("%s due to coordination service error", prefix), ex);
|
||||
throw new AutoIngestJobLoggerException(String.format("Failed to write case auto ingest log message (\"%s\") for %s", message, manifestPath), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when there is a problem writing a log message.
|
||||
*/
|
||||
final static class AutoIngestJobLoggerException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Constructs an exception to throw when there is a problem writing a
|
||||
* log message.
|
||||
*
|
||||
* @param message The exception message.
|
||||
*/
|
||||
private AutoIngestJobLoggerException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an exception to throw when there is a problem writing a
|
||||
* log message.
|
||||
*
|
||||
* @param message The exception message.
|
||||
* @param cause The cause of the exception, if it was an exception.
|
||||
*/
|
||||
private AutoIngestJobLoggerException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,20 @@
|
||||
AutoIngestDashboard.bnRefresh.text=&Refresh
|
||||
AutoIngestDashboard.lbCompleted.text=Completed
|
||||
AutoIngestDashboard.lbRunning.text=Running
|
||||
AutoIngestDashboard.lbPending.text=Pending
|
||||
AutoIngestDashboard.lbCompleted.text=Completed Jobs
|
||||
AutoIngestDashboard.lbRunning.text=Running Jobs
|
||||
AutoIngestDashboard.lbPending.text=Pending Jobs
|
||||
AutoIngestDashboard.bnCancelModule.text=Cancel &Module
|
||||
AutoIngestDashboard.bnExit.text=&Exit
|
||||
AutoIngestDashboard.bnOptions.text=&Options
|
||||
AutoIngestDashboard.JobsTableModel.ColumnHeader.Case=Case
|
||||
AutoIngestDashboard.JobsTableModel.ColumnHeader.ImageFolder=Data Source
|
||||
AutoIngestDashboard.JobsTableModel.ColumnHeader.HostName=Host Name
|
||||
AutoIngestDashboard.JobsTableModel.ColumnHeader.CreatedTime=Created Time
|
||||
AutoIngestDashboard.JobsTableModel.ColumnHeader.StartedTime=Started Time
|
||||
AutoIngestDashboard.JobsTableModel.ColumnHeader.CompletedTime=Completed Time
|
||||
AutoIngestDashboard.JobsTableModel.ColumnHeader.CreatedTime=Job Created
|
||||
AutoIngestDashboard.JobsTableModel.ColumnHeader.StartedTime=Stage Started
|
||||
AutoIngestDashboard.JobsTableModel.ColumnHeader.CompletedTime=Job Completed
|
||||
AutoIngestDashboard.JobsTableModel.ColumnHeader.Stage=Stage
|
||||
AutoIngestDashboard.JobsTableModel.ColumnHeader.Status=Status
|
||||
AutoIngestDashboard.bnShowProgress.text=&Show Progress
|
||||
AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath= Manifest File Path
|
||||
AutoIngestDashboard.bnShowProgress.text=Ingest Progress
|
||||
AutoIngestDashboard.bnResume.text=Resume
|
||||
AutoIngestDashboard.bnPause.text=Pause
|
||||
AutoIngestDashboard.bnPause.confirmHeader=Are you sure you want to pause?
|
||||
@ -42,7 +43,7 @@ AutoIngestDashboard.ExitConsequences=This will cancel any currently running job
|
||||
AutoIngestDashboard.ExitingStatus=Exiting...
|
||||
AutoIngestDashboard.OK=OK
|
||||
AutoIngestDashboard.Cancel=Cancel
|
||||
AutoIngestDashboard.AutoIngestStartupFailed.Message=Failed to start automated ingest.\nPlease see application log for details.
|
||||
AutoIngestDashboard.AutoIngestStartupFailed.Message=Failed to start automated ingest.\nPlease see auto ingest system log for details.
|
||||
AutoIngestDashboard.AutoIngestStartupFailed.Title=Automated Ingest Error
|
||||
AutoIngestDashboard.AutoIngestStartupError=Failed to start automated ingest. Verify Multi-user Settings.
|
||||
AutoIngestDashboard.AutoIngestStartupWarning.Title=Automated Ingest Warning
|
||||
@ -60,7 +61,7 @@ AutoIngestDashboard.tbServicesStatusMessage.Message=Case databases {0}, keyword
|
||||
AutoIngestDashboard.tbServicesStatusMessage.Message.Up=up
|
||||
AutoIngestDashboard.tbServicesStatusMessage.Message.Down=down
|
||||
AutoIngestDashboard.tbServicesStatusMessage.Message.Unknown=unknown
|
||||
AutoIngestDashboard.PauseDueToSystemError=Paused due to system error, please consult the auto ingest system log"
|
||||
AutoIngestDashboard.PauseDueToSystemError=Paused due to system error, please consult the auto ingest system log
|
||||
ConfirmationDialog.DoNotDelete=Do not delete
|
||||
ConfirmationDialog.Delete=Permanently delete
|
||||
ConfirmationDialog.DeleteAreYouSure=The entire case will be removed. Are you sure you want to delete case
|
||||
@ -166,7 +167,7 @@ ReviewModeCasePanel.bnShowLog.text=&Show Log
|
||||
AutoIngestDashboard.bnPrioritizeCase.toolTipText=Move all images associated with a case to top of Pending queue.
|
||||
AutoIngestDashboard.bnPrioritizeCase.text=Prioriti&ze Case
|
||||
AutoIngestDashboard.bnShowCaseLog.toolTipText=Display case log file for selected case
|
||||
AutoIngestDashboard.bnShowCaseLog.text=Show &Log
|
||||
AutoIngestDashboard.bnShowCaseLog.text=Show Case &Log
|
||||
ReviewModeCasePanel.bnShowLog.toolTipText=Display case log file for selected case
|
||||
CopyFilesPanel.bnCancelPendingJob.text=Ca&ncel
|
||||
CopyFilesPanel.tbDestinationCase.text=
|
||||
@ -197,8 +198,6 @@ CaseImportPanel.Complete=Complete
|
||||
CaseImportPanel.Blank=
|
||||
CaseImportPanel.DeleteWarning=Make sure no important files are in the case source directory
|
||||
AutoIngestDashboard.lbStatus.text=Status:
|
||||
AutoIngestDashboard.bnPrioritizeFolder.text=Prioritize &Folder
|
||||
AutoIngestDashboard.bnPrioritizeFolder.toolTipText=Move this folder to the top of the Pending queue.
|
||||
SingleUserCaseImporter.NonUniqueOutputFolder=Output folder not unique. Skipping
|
||||
SingleUserCaseImporter.WillImport=Will import:
|
||||
SingleUserCaseImporter.None=None
|
||||
@ -283,4 +282,7 @@ FileExporterSettingsPanel.BrowseReportTooltip_1=Browse for the Reports Folder
|
||||
FileExporterSettingsPanel.NewRuleTooltip_1=Clear the rule editor to begin a new rule
|
||||
FileExporterSettingsPanel.DeleteTooltip_1=Delete the selected rule
|
||||
FileExporterSettingsPanel.SaveTooltip_1=Save the current rule
|
||||
AutoIngestDashboard.bnOpenLogDir.text=Open Log Directory
|
||||
AutoIngestDashboard.bnOpenLogDir.text=Open System Logs Directory
|
||||
AutoIngestDashboard.bnPrioritizeJob.text=Prioritize Job
|
||||
AutoIngestDashboard.bnPrioritizeJob.toolTipText=Move this folder to the top of the Pending queue.
|
||||
AutoIngestDashboard.bnReprocessJob.text=Reprocess Job
|
||||
|
@ -19,13 +19,13 @@
|
||||
package org.sleuthkit.autopsy.experimental.autoingest;
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Namespace elements for auto ingest coordination service nodes.
|
||||
*/
|
||||
final class CoordinationServiceNamespace {
|
||||
static final String ROOT_COORD_SCV_NAMESPACE = "autopsy"; // RJCTODO: Move this elsewhere
|
||||
private static final String ROOT = "autopsy";
|
||||
|
||||
static String getRoot() {
|
||||
return ROOT_COORD_SCV_NAMESPACE;
|
||||
return ROOT;
|
||||
}
|
||||
|
||||
private CoordinationServiceNamespace() {
|
||||
|
@ -19,34 +19,35 @@
|
||||
package org.sleuthkit.autopsy.experimental.autoingest;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* A coordination service node data transfer object for an auto ingest job
|
||||
* manifest. The data include: processing status, priority, the number of times
|
||||
* the auto ingest job for the manifest has crashed during processing, and the
|
||||
* date the auto ingest job for the manifest was completed.
|
||||
*/
|
||||
// RJCTODO: Consider making this encapsulate the locking as well, and to set the data as well
|
||||
final class ManifestNodeData {
|
||||
|
||||
enum ProcessingStatus {
|
||||
PENDING,
|
||||
PROCESSING,
|
||||
COMPLETED,
|
||||
}
|
||||
|
||||
private static final int DEFAULT_PRIORITY = 0;
|
||||
private final boolean nodeDataIsSet;
|
||||
private final boolean coordSvcNodeDataWasSet;
|
||||
private ProcessingStatus status;
|
||||
private int priority;
|
||||
private int numberOfCrashes;
|
||||
private long completedDate;
|
||||
private boolean errorsOccurred;
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Constructs a coordination service node data data transfer object for an
|
||||
* auto ingest manifest from the raw bytes obtained from the coordination
|
||||
* service.
|
||||
*
|
||||
* @param nodeData
|
||||
* @param nodeData The raw bytes received from the coordination service.
|
||||
*/
|
||||
ManifestNodeData(byte[] nodeData) {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(nodeData);
|
||||
this.nodeDataIsSet = buffer.hasRemaining();
|
||||
if (this.nodeDataIsSet) {
|
||||
this.coordSvcNodeDataWasSet = buffer.hasRemaining();
|
||||
if (this.coordSvcNodeDataWasSet) {
|
||||
int rawStatus = buffer.getInt();
|
||||
if (ProcessingStatus.PENDING.ordinal() == rawStatus) {
|
||||
this.status = ProcessingStatus.PENDING;
|
||||
@ -54,97 +55,183 @@ final class ManifestNodeData {
|
||||
this.status = ProcessingStatus.PROCESSING;
|
||||
} else if (ProcessingStatus.COMPLETED.ordinal() == rawStatus) {
|
||||
this.status = ProcessingStatus.COMPLETED;
|
||||
}else if (ProcessingStatus.DELETED.ordinal() == rawStatus) {
|
||||
this.status = ProcessingStatus.DELETED;
|
||||
}
|
||||
this.priority = buffer.getInt();
|
||||
this.numberOfCrashes = buffer.getInt();
|
||||
this.completedDate = buffer.getLong();
|
||||
int errorFlag = buffer.getInt();
|
||||
this.errorsOccurred = (1 == errorFlag);
|
||||
} else {
|
||||
this.status = ProcessingStatus.PENDING;
|
||||
this.priority = DEFAULT_PRIORITY;
|
||||
this.numberOfCrashes = 0;
|
||||
this.completedDate = 0L;
|
||||
this.errorsOccurred = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Constructs a coordination service node data data transfer object for an
|
||||
* auto ingest manifest from values provided by the auto ingest system.
|
||||
*
|
||||
* @param status The processing status of the manifest.
|
||||
* @param priority The priority of the manifest.
|
||||
* @param numberOfCrashes The number of times auto ingest jobs for the
|
||||
* manifest have crashed during processing.
|
||||
* @param completedDate The date the auto ingest job for the manifest was
|
||||
* completed.
|
||||
*/
|
||||
ManifestNodeData(ProcessingStatus status, int priority, int numberOfCrashes) {
|
||||
this.nodeDataIsSet = false;
|
||||
ManifestNodeData(ProcessingStatus status, int priority, int numberOfCrashes, Date completedDate, boolean errorOccurred) {
|
||||
this.coordSvcNodeDataWasSet = false;
|
||||
this.status = status;
|
||||
this.priority = priority;
|
||||
this.numberOfCrashes = numberOfCrashes;
|
||||
this.completedDate = completedDate.getTime();
|
||||
this.errorsOccurred = errorOccurred;
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Indicates whether or not the coordination service node data was set,
|
||||
* i.e., this object was constructed from raw bytes from the ccordination
|
||||
* service node for the manifest.
|
||||
*
|
||||
* @return
|
||||
* @return True or false.
|
||||
*/
|
||||
boolean isSet() {
|
||||
return this.nodeDataIsSet;
|
||||
// RJCTODO: This is confusing, consider changing the API so that the use case is to
|
||||
// check the length of the node data from the coordination service before
|
||||
// constructing an instance of this object. That would be much more clear!
|
||||
boolean coordSvcNodeDataWasSet() {
|
||||
return this.coordSvcNodeDataWasSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Gets the processing status of the manifest
|
||||
*
|
||||
* @return
|
||||
* @return The processing status of the manifest.
|
||||
*/
|
||||
ProcessingStatus getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the processing status of the manifest
|
||||
*
|
||||
* @param status
|
||||
* @param status The processing status of the manifest.
|
||||
*/
|
||||
void setStatus(ProcessingStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the priority of the manifest.
|
||||
*
|
||||
* @return
|
||||
* @return The priority of the manifest.
|
||||
*/
|
||||
int getPriority() {
|
||||
return this.priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the priority of the manifest. A higher number indicates a higheer
|
||||
* priority.
|
||||
*
|
||||
* @param priority
|
||||
* @param priority The priority of the manifest.
|
||||
*/
|
||||
void setPriority(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Gets the number of times auto ingest jobs for the manifest have crashed
|
||||
* during processing.
|
||||
*
|
||||
* @return
|
||||
* @return The number of times auto ingest jobs for the manifest have
|
||||
* crashed during processing.
|
||||
*/
|
||||
int getNumberOfCrashes() {
|
||||
return this.numberOfCrashes;
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Sets the number of times auto ingest jobs for the manifest have crashed
|
||||
* during processing.
|
||||
*
|
||||
* @param attempts
|
||||
* @param numberOfCrashes The number of times auto ingest jobs for the
|
||||
* manifest have crashed during processing.
|
||||
*/
|
||||
void setNumberOfCrashes(int attempts) {
|
||||
this.numberOfCrashes = attempts;
|
||||
void setNumberOfCrashes(int numberOfCrashes) {
|
||||
this.numberOfCrashes = numberOfCrashes;
|
||||
}
|
||||
|
||||
/**
|
||||
* RJCTODO
|
||||
* Gets the date the auto ingest job for the manifest was completed.
|
||||
*
|
||||
* @return
|
||||
* @return The date the auto ingest job for the manifest was completed. The
|
||||
* epoch (January 1, 1970, 00:00:00 GMT) indicates the date is not
|
||||
* set, i.e., Date.getTime() returns 0L.
|
||||
*/
|
||||
Date getCompletedDate() {
|
||||
return new Date(this.completedDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the date the auto ingest job for the manifest was completed.
|
||||
*
|
||||
* @param completedDate The date the auto ingest job for the manifest was
|
||||
* completed. Use the epoch (January 1, 1970, 00:00:00
|
||||
* GMT) to indicate the date is not set, i.e., new
|
||||
* Date(0L).
|
||||
*/
|
||||
void setCompletedDate(Date completedDate) {
|
||||
this.completedDate = completedDate.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries whether or not any errors occurred during the processing of the
|
||||
* auto ingest job for the manifest.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
boolean getErrorsOccurred() {
|
||||
return this.errorsOccurred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not any errors occurred during the processing of the auto
|
||||
* ingest job for the manifest.
|
||||
*
|
||||
* @param errorsOccurred True or false.
|
||||
*/
|
||||
void setErrorsOccurred(boolean errorsOccurred) {
|
||||
this.errorsOccurred = errorsOccurred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node data as raw bytes that can be sent to the coordination
|
||||
* service.
|
||||
*
|
||||
* @return The manifest node data as a byte array.
|
||||
*/
|
||||
byte[] toArray() {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES * 3);
|
||||
ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES * 4 + Long.BYTES);
|
||||
buffer.putInt(this.status.ordinal());
|
||||
buffer.putInt(this.priority);
|
||||
buffer.putInt(this.numberOfCrashes);
|
||||
buffer.putLong(this.completedDate);
|
||||
buffer.putInt(this.errorsOccurred ? 1 : 0);
|
||||
return buffer.array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processing status for the auto ingest job for the manifest.
|
||||
*/
|
||||
enum ProcessingStatus {
|
||||
PENDING,
|
||||
PROCESSING,
|
||||
COMPLETED,
|
||||
DELETED
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,11 +28,9 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
|
||||
import org.sleuthkit.autopsy.casemodule.GeneralFilter;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
final class PathUtils {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(PathUtils.class.getName());
|
||||
private static final List<String> CASE_METADATA_FILE_EXTS = Arrays.asList(new String[]{CaseMetadata.getFileExtension()});
|
||||
private static final GeneralFilter caseMetadataFileFilter = new GeneralFilter(CASE_METADATA_FILE_EXTS, "Autopsy Case File");
|
||||
|
||||
@ -71,7 +69,7 @@ final class PathUtils {
|
||||
*
|
||||
* @return A list of the output case folder paths.
|
||||
*/
|
||||
static List<Path> findCaseFolders(Path folderToSearch) {
|
||||
static List<Path> findCaseFolders(Path folderToSearch) { // RJCTODO: Rename
|
||||
File searchFolder = new File(folderToSearch.toString());
|
||||
if (!searchFolder.isDirectory()) {
|
||||
return Collections.emptyList();
|
||||
@ -112,32 +110,6 @@ final class PathUtils {
|
||||
return caseDataFiles.length != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the path to the case images folder path from an image folder
|
||||
* path.
|
||||
*
|
||||
* @param rootImageFoldersPath The root image folders path.
|
||||
* @param imageFolderPath The image folder path.
|
||||
*
|
||||
* @return The root input folder path for a case.
|
||||
*/
|
||||
static Path caseImagesPathFromImageFolderPath(Path rootImageFoldersPath, Path imageFolderPath) {
|
||||
return rootImageFoldersPath.resolve(imageFolderPath.subpath(0, rootImageFoldersPath.getNameCount() + 1).getFileName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the case name from an image folder path.
|
||||
*
|
||||
* @param rootImageFoldersPath The root image folders path.
|
||||
* @param imageFolderPath The image folder path.
|
||||
*
|
||||
* @return The case name.
|
||||
*/
|
||||
static String caseNameFromImageFolderPath(Path rootImageFoldersPath, Path imageFolderPath) {
|
||||
Path caseImagesPath = PathUtils.caseImagesPathFromImageFolderPath(rootImageFoldersPath, imageFolderPath);
|
||||
return caseImagesPath.getFileName().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the case name from a case folder path.
|
||||
*
|
||||
@ -163,7 +135,7 @@ final class PathUtils {
|
||||
*
|
||||
* @return A case folder path with a time stamp suffix.
|
||||
*/
|
||||
static Path createCaseFolderPath(Path caseFoldersPath, String caseName) {
|
||||
static Path createCaseFolderPath(Path caseFoldersPath, String caseName) { // RJCTODO: Rename
|
||||
String folderName = caseName + "_" + TimeStampUtils.createTimeStamp();
|
||||
return Paths.get(caseFoldersPath.toString(), folderName);
|
||||
}
|
||||
|
@ -61,8 +61,8 @@ public final class ReviewModeCasePanel extends JPanel {
|
||||
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 = 60;
|
||||
private static final int MILLISECONDS_TO_WAIT_BEFORE_STARTING = 500;
|
||||
private static final int MILLISECONDS_TO_WAIT_BETWEEN_UPDATES = 30000;
|
||||
private static final int MILLISECONDS_TO_WAIT_BEFORE_STARTING = 500; // RJCTODO: Shorten name
|
||||
private static final int MILLISECONDS_TO_WAIT_BETWEEN_UPDATES = 30000; // RJCTODO: Shorten name
|
||||
private ScheduledThreadPoolExecutor casesTableRefreshExecutor;
|
||||
|
||||
/*
|
||||
@ -84,7 +84,7 @@ public final class ReviewModeCasePanel extends JPanel {
|
||||
CREATEDTIME,
|
||||
COMPLETEDTIME,
|
||||
STATUS_ICON,
|
||||
OUTPUTFOLDER
|
||||
OUTPUTFOLDER // RJCTODO: Change name
|
||||
}
|
||||
private final String[] columnNames = {CASE_HEADER, CREATEDTIME_HEADER, COMPLETEDTIME_HEADER, STATUS_ICON_HEADER, OUTPUT_FOLDER_HEADER};
|
||||
private DefaultTableModel caseTableModel;
|
||||
@ -325,7 +325,7 @@ public final class ReviewModeCasePanel extends JPanel {
|
||||
autoIngestCase.getCaseName(),
|
||||
autoIngestCase.getCreationDate(),
|
||||
autoIngestCase.getLastAccessedDate(),
|
||||
autoIngestCase.getStatus(),
|
||||
(AutoIngestCase.CaseStatus.OK != autoIngestCase.getStatus()),
|
||||
autoIngestCase.getCaseDirectoryPath().toString()});
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user