mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-14 17:06:16 +00:00
Merge pull request #3054 from dgrove727/Aid20_FixedBundleMessages
Aid20 fixed bundle messages
This commit is contained in:
commit
f00a9e52f1
@ -53,13 +53,9 @@ import org.netbeans.api.options.OptionsDisplayer;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.LifecycleManager;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.openide.filesystems.FileObject;
|
||||
import org.openide.filesystems.FileUtil;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.casemodule.CaseNewAction;
|
||||
import org.sleuthkit.autopsy.casemodule.CaseOpenAction;
|
||||
import org.sleuthkit.autopsy.core.ServicesMonitor;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
||||
@ -119,20 +115,33 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
* allows the columns of the table model to be described by either an enum
|
||||
* ordinal or a column header string.
|
||||
*/
|
||||
@Messages({
|
||||
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.Case=Case",
|
||||
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.ImageFolder=Data Source",
|
||||
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.HostName=Host Name",
|
||||
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.CreatedTime=Job Created",
|
||||
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.StartedTime=Stage Started",
|
||||
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.CompletedTime=Job Completed",
|
||||
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.Stage=Stage",
|
||||
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.Status=Status",
|
||||
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.CaseFolder=Case Folder",
|
||||
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob= Local Job?",
|
||||
"AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath= Manifest File Path"
|
||||
})
|
||||
private enum JobsTableModelColumns {
|
||||
|
||||
CASE(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Case")),
|
||||
DATA_SOURCE(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ImageFolder")),
|
||||
HOST_NAME(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.HostName")),
|
||||
CREATED_TIME(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CreatedTime")),
|
||||
STARTED_TIME(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.StartedTime")),
|
||||
COMPLETED_TIME(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CompletedTime")),
|
||||
STAGE(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Stage")),
|
||||
STAGE_TIME(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.StageTime")),
|
||||
STATUS(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Status")),
|
||||
CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder")),
|
||||
IS_LOCAL_JOB(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.LocalJob")),
|
||||
MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath"));
|
||||
CASE(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Case")),
|
||||
DATA_SOURCE(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ImageFolder")),
|
||||
HOST_NAME(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.HostName")),
|
||||
CREATED_TIME(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.CreatedTime")),
|
||||
STARTED_TIME(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.StartedTime")),
|
||||
COMPLETED_TIME(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.CompletedTime")),
|
||||
STAGE(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Stage")),
|
||||
STAGE_TIME(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.StageTime")),
|
||||
STATUS(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Status")),
|
||||
CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.CaseFolder")),
|
||||
IS_LOCAL_JOB(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.LocalJob")),
|
||||
MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath"));
|
||||
|
||||
private final String header;
|
||||
|
||||
@ -182,6 +191,14 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
* controlling automated ingest for a single node within the cluster.
|
||||
*/
|
||||
private AutoIngestControlPanel() {
|
||||
//DLG: Temporary code for troubleshooting. Remove when done!
|
||||
manager = null;
|
||||
pendingTableModel = null;
|
||||
runningTableModel = null;
|
||||
completedTableModel = null;
|
||||
//////////////////////////////////////////////////////////////
|
||||
try {
|
||||
|
||||
//Disable the main window so they can only use the dashboard (if we used setVisible the taskBar icon would go away)
|
||||
WindowManager.getDefault().getMainWindow().setEnabled(false);
|
||||
|
||||
@ -213,6 +230,10 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} catch (Throwable ex) {
|
||||
//DLG: Temporary code for troubleshooting.
|
||||
SYS_LOGGER.log(Level.SEVERE, "AutoIngestControlPanel() error:", ex);
|
||||
}
|
||||
|
||||
initComponents(); // Generated code.
|
||||
setServicesStatusMessage();
|
||||
@ -231,6 +252,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
* Queries the services monitor and sets the text for the services status
|
||||
* text box.
|
||||
*/
|
||||
@Messages({
|
||||
"AutoIngestControlPanel.tbServicesStatusMessage.Message=Case databases {0}, keyword search {1}, coordination {2}, messaging {3} ",
|
||||
"AutoIngestControlPanel.tbServicesStatusMessage.Message.Up=up",
|
||||
"AutoIngestControlPanel.tbServicesStatusMessage.Message.Down=down",
|
||||
"AutoIngestControlPanel.tbServicesStatusMessage.Message.Unknown=unknown"
|
||||
})
|
||||
private void setServicesStatusMessage() {
|
||||
new SwingWorker<Void, Void>() {
|
||||
|
||||
@ -254,14 +281,14 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
* @return The status string.
|
||||
*/
|
||||
private String getServiceStatus(ServicesMonitor.Service service) {
|
||||
String serviceStatus = NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.tbServicesStatusMessage.Message.Unknown");
|
||||
String serviceStatus = NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.tbServicesStatusMessage.Message.Unknown");
|
||||
try {
|
||||
ServicesMonitor servicesMonitor = ServicesMonitor.getInstance();
|
||||
serviceStatus = servicesMonitor.getServiceStatus(service.toString());
|
||||
if (serviceStatus.compareTo(ServicesMonitor.ServiceStatus.UP.toString()) == 0) {
|
||||
serviceStatus = NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.tbServicesStatusMessage.Message.Up");
|
||||
serviceStatus = NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.tbServicesStatusMessage.Message.Up");
|
||||
} else {
|
||||
serviceStatus = NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.tbServicesStatusMessage.Message.Down");
|
||||
serviceStatus = NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.tbServicesStatusMessage.Message.Down");
|
||||
}
|
||||
} catch (ServicesMonitor.ServicesMonitorException ex) {
|
||||
SYS_LOGGER.log(Level.SEVERE, String.format("Dashboard error getting service status for %s", service), ex);
|
||||
@ -271,8 +298,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
tbServicesStatusMessage.setText(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.tbServicesStatusMessage.Message", caseDatabaseServerStatus, keywordSearchServiceStatus, keywordSearchServiceStatus, messagingStatus));
|
||||
String upStatus = NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.tbServicesStatusMessage.Message.Up");
|
||||
tbServicesStatusMessage.setText(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.tbServicesStatusMessage.Message", caseDatabaseServerStatus, keywordSearchServiceStatus, keywordSearchServiceStatus, messagingStatus));
|
||||
String upStatus = NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.tbServicesStatusMessage.Message.Up");
|
||||
if (caseDatabaseServerStatus.compareTo(upStatus) != 0
|
||||
|| keywordSearchServiceStatus.compareTo(upStatus) != 0
|
||||
|| messagingStatus.compareTo(upStatus) != 0) {
|
||||
@ -554,12 +581,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
enablePendingTableButtons(false);
|
||||
bnShowCaseLog.setEnabled(false);
|
||||
bnReprocessJob.setEnabled(false);
|
||||
bnPause.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.bnStart.text"));
|
||||
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.bnStart.toolTipText"));
|
||||
bnPause.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnStart.text"));
|
||||
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnStart.toolTipText"));
|
||||
bnPause.setEnabled(true); //initial label for bnPause is 'Start' and it's enabled for user to start the process
|
||||
bnRefresh.setEnabled(false); //at initial stage, nothing to refresh
|
||||
enableRunningTableButtons(false);
|
||||
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.bnStart.startMessage"));
|
||||
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnStart.startMessage"));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -598,12 +625,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
autoIngestStarted = true;
|
||||
} catch (AutoIngestManager.AutoIngestManagerStartupException ex) {
|
||||
SYS_LOGGER.log(Level.SEVERE, "Dashboard error starting up auto ingest", ex);
|
||||
tbStatusMessage.setText(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.AutoIngestStartupError"));
|
||||
tbStatusMessage.setText(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.AutoIngestStartupError"));
|
||||
manager = null;
|
||||
|
||||
JOptionPane.showMessageDialog(this,
|
||||
NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.AutoIngestStartupFailed.Message"),
|
||||
NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.AutoIngestStartupFailed.Title"),
|
||||
NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.AutoIngestStartupFailed.Message"),
|
||||
NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.AutoIngestStartupFailed.Title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
bnOptions.setEnabled(true);
|
||||
|
||||
@ -633,12 +660,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
manager.scanInputDirsNow();
|
||||
|
||||
//bnPause.setEnabled(true);
|
||||
bnPause.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.bnPause.text"));
|
||||
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.bnPause.toolTipText"));
|
||||
bnPause.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.text"));
|
||||
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.toolTipText"));
|
||||
bnRefresh.setEnabled(true);
|
||||
bnOptions.setEnabled(false);
|
||||
|
||||
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.bnPause.running"));
|
||||
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.running"));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -655,13 +682,13 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
* was grabbing the monitor?
|
||||
*/
|
||||
Object[] options = {
|
||||
NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.OK"),
|
||||
NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.Cancel")};
|
||||
NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.OK"),
|
||||
NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.Cancel")};
|
||||
int reply = JOptionPane.OK_OPTION;
|
||||
|
||||
if (null != manager && IngestManager.getInstance().isIngestRunning()) {
|
||||
reply = JOptionPane.showOptionDialog(this,
|
||||
NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.ExitConsequences"),
|
||||
NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.ExitConsequences"),
|
||||
NbBundle.getMessage(AutoIngestControlPanel.class, "ConfirmationDialog.ConfirmExitHeader"),
|
||||
JOptionPane.DEFAULT_OPTION,
|
||||
JOptionPane.WARNING_MESSAGE,
|
||||
@ -675,7 +702,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
* appears (if there is time to see it).
|
||||
*/
|
||||
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.ExitingStatus"));
|
||||
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.ExitingStatus"));
|
||||
|
||||
/*
|
||||
* Shut down the table refresh task executor.
|
||||
@ -716,7 +743,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
@Messages({
|
||||
"AutoIngestControlPanel.bnPause.paused=Paused",
|
||||
"AutoIngestControlPanel.PauseDueToDatabaseServiceDown=Paused, unable to communicate with case database service.",
|
||||
"AutoIngestControlPanel.PauseDueToKeywordSearchServiceDown=Paused, unable to communicate with keyword search service.",
|
||||
@ -743,7 +770,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
break;
|
||||
case PAUSED_BY_REQUEST:
|
||||
EventQueue.invokeLater(() -> {
|
||||
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.paused"));
|
||||
tbStatusMessage.setText(Bundle.AutoIngestControlPanel_bnPause_paused());
|
||||
bnOptions.setEnabled(true);
|
||||
bnRefresh.setEnabled(false);
|
||||
isPaused = true;
|
||||
@ -799,8 +826,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
/**
|
||||
* Change the pause button text and tool tip to make it a resume button.
|
||||
*/
|
||||
bnPause.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.bnResume.text"));
|
||||
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.bnPause.toolTipTextResume"));
|
||||
bnPause.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnResume.text"));
|
||||
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.toolTipTextResume"));
|
||||
|
||||
if (buttonClicked) {
|
||||
/**
|
||||
@ -825,9 +852,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
* Change the resume button text and tool tip to make it a pause button.
|
||||
*/
|
||||
bnOptions.setEnabled(false);
|
||||
bnPause.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.bnPause.text"));
|
||||
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.bnPause.toolTipText"));
|
||||
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.bnPause.running"));
|
||||
bnPause.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.text"));
|
||||
bnPause.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.toolTipText"));
|
||||
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.running"));
|
||||
bnRefresh.setEnabled(true);
|
||||
|
||||
/**
|
||||
@ -1061,7 +1088,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
tableModel.setRowCount(0);
|
||||
for (AutoIngestJob job : jobs) {
|
||||
AutoIngestJob.StageDetails status = job.getStageDetails();
|
||||
ManifestNodeData nodeData = job.getNodeData();
|
||||
AutoIngestJobNodeData nodeData = job.getNodeData();
|
||||
tableModel.addRow(new Object[]{
|
||||
nodeData.getCaseName(), // CASE
|
||||
nodeData.getDataSourcePath().getFileName(), // DATA_SOURCE
|
||||
@ -1449,6 +1476,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
*
|
||||
* @param evt The button click event.
|
||||
*/
|
||||
@Messages({
|
||||
"AutoIngestControlPanel.DeletionFailed=Deletion failed for job"
|
||||
})
|
||||
private void bnDeleteCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnDeleteCaseActionPerformed
|
||||
if (completedTableModel.getRowCount() < 0 || completedTable.getSelectedRow() < 0) {
|
||||
return;
|
||||
@ -1481,12 +1511,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
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(AutoIngestControlPanel.class, "AutoIngestDashboard.DeletionFailed"),
|
||||
org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.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(AutoIngestControlPanel.class, "AutoIngestDashboard.DeletionFailed"),
|
||||
org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.DeletionFailed"),
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
}
|
||||
@ -1539,6 +1569,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
*
|
||||
* @param evt The button click event.
|
||||
*/
|
||||
@Messages({
|
||||
"AutoIngestControlPanel.bnPause.pausing=Pausing after current job completes..."
|
||||
})
|
||||
private void bnPauseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPauseActionPerformed
|
||||
|
||||
if (!autoIngestStarted) {
|
||||
@ -1552,7 +1585,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
return;
|
||||
}
|
||||
if (!isPaused) {
|
||||
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.bnPause.pausing"));
|
||||
tbStatusMessage.setText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.bnPause.pausing"));
|
||||
pause(true);
|
||||
} else {
|
||||
resume();
|
||||
@ -1634,6 +1667,10 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
*
|
||||
* @param evt The button click event.
|
||||
*/
|
||||
@Messages({
|
||||
"AutoIngestControlPanel.ShowLogFailed.Title=Unable to display case log",
|
||||
"AutoIngestControlPanel.ShowLogFailed.Message=Case log file does not exist"
|
||||
})
|
||||
private void bnShowCaseLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowCaseLogActionPerformed
|
||||
try {
|
||||
int selectedRow = completedTable.getSelectedRow();
|
||||
@ -1644,8 +1681,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer {
|
||||
if (pathToLog.toFile().exists()) {
|
||||
Desktop.getDesktop().edit(pathToLog.toFile());
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(this, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.ShowLogFailed.Message"),
|
||||
org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.ShowLogFailed.Title"), JOptionPane.ERROR_MESSAGE);
|
||||
JOptionPane.showMessageDialog(this, org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.ShowLogFailed.Message"),
|
||||
org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.ShowLogFailed.Title"), JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
} else {
|
||||
MessageNotifyUtil.Message.warn("The case directory for this job has been deleted.");
|
||||
|
@ -16,10 +16,11 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="pendingScrollPane" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lbPending" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbCompleted" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
@ -37,7 +38,6 @@
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="pendingScrollPane" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="runningScrollPane" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="completedScrollPane" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
@ -55,13 +55,13 @@
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lbPending" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
|
||||
<Component id="pendingScrollPane" min="-2" pref="215" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="lbRunning" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
|
||||
<Component id="runningScrollPane" min="-2" pref="133" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="lbCompleted" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="completedScrollPane" min="-2" pref="179" max="-2" attributes="0"/>
|
||||
@ -186,7 +186,6 @@
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="AutoIngestDashboard.refreshButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="refreshButtonActionPerformed"/>
|
||||
|
@ -18,7 +18,6 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.experimental.autoingest;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.EventQueue;
|
||||
import java.nio.file.Path;
|
||||
@ -28,12 +27,11 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.DefaultListSelectionModel;
|
||||
import java.awt.Color;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.util.Collections;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingWorker;
|
||||
@ -42,8 +40,10 @@ import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import javax.swing.table.TableColumn;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.core.ServicesMonitor;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.JobsSnapshot;
|
||||
|
||||
/**
|
||||
@ -73,13 +73,11 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
private static final int COMPLETED_TIME_COL_MIN_WIDTH = 30;
|
||||
private static final int COMPLETED_TIME_COL_MAX_WIDTH = 2000;
|
||||
private static final int COMPLETED_TIME_COL_PREFERRED_WIDTH = 280;
|
||||
private static final String UPDATE_TASKS_THREAD_NAME = "AID-update-tasks-%d";
|
||||
private static final Logger logger = Logger.getLogger(AutoIngestDashboard.class.getName());
|
||||
private final DefaultTableModel pendingTableModel;
|
||||
private final DefaultTableModel runningTableModel;
|
||||
private final DefaultTableModel completedTableModel;
|
||||
private AutoIngestMonitor autoIngestMonitor;
|
||||
private ExecutorService updateExecutor;
|
||||
|
||||
// DLG: The Viking code needs to be updated, too. See VikingStartupWindow,
|
||||
// which should be using the AutoIngestControlPanel, not the AutoIngestDashboard.
|
||||
@ -253,16 +251,16 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
pendingTable.setAutoCreateRowSorter(false);
|
||||
|
||||
/*
|
||||
* Create a row selection listener to enable/disable the prioritize
|
||||
* folder and prioritize case buttons.
|
||||
* Create a row selection listener to enable/disable the Prioritize
|
||||
* button.
|
||||
*/
|
||||
pendingTable.getSelectionModel().addListSelectionListener((ListSelectionEvent e) -> {
|
||||
if (e.getValueIsAdjusting()) {
|
||||
return;
|
||||
}
|
||||
int row = pendingTable.getSelectedRow();
|
||||
this.prioritizeButton.setEnabled(row >= 0 && row < pendingTable.getRowCount());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -409,19 +407,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
* Prevent sorting when a column header is clicked.
|
||||
*/
|
||||
completedTable.setAutoCreateRowSorter(false);
|
||||
|
||||
/*
|
||||
* Create a row selection listener to enable/disable the delete case and
|
||||
* show log buttons.
|
||||
*/
|
||||
completedTable.getSelectionModel()
|
||||
.addListSelectionListener((ListSelectionEvent e) -> {
|
||||
if (e.getValueIsAdjusting()) {
|
||||
return;
|
||||
}
|
||||
int row = completedTable.getSelectedRow();
|
||||
boolean enabled = row >= 0 && row < completedTable.getRowCount();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -430,18 +415,19 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
* auto ingest job tables.
|
||||
*/
|
||||
private void startUp() throws AutoIngestMonitor.AutoIngestMonitorException {
|
||||
autoIngestMonitor = AutoIngestMonitor.createMonitor();
|
||||
autoIngestMonitor.addObserver(this);
|
||||
updateExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(UPDATE_TASKS_THREAD_NAME).build());
|
||||
updateExecutor.submit(new GetJobsSnapshotTask());
|
||||
setServicesStatusMessage();
|
||||
ServicesMonitor.getInstance().addSubscriber((PropertyChangeEvent evt) -> {
|
||||
setServicesStatusMessage();
|
||||
});
|
||||
autoIngestMonitor = new AutoIngestMonitor();
|
||||
autoIngestMonitor.addObserver(this);
|
||||
autoIngestMonitor.startUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Observable observable, Object argument) {
|
||||
updateExecutor.submit(new GetJobsSnapshotTask());
|
||||
JobsSnapshot jobsSnapshot = (JobsSnapshot) argument;
|
||||
EventQueue.invokeLater(new RefreshComponentsTask(jobsSnapshot));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -454,7 +440,11 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
List<AutoIngestJob> pendingJobs = jobsSnapshot.getPendingJobs();
|
||||
List<AutoIngestJob> runningJobs = jobsSnapshot.getRunningJobs();
|
||||
List<AutoIngestJob> completedJobs = jobsSnapshot.getCompletedJobs();
|
||||
// DLG: Do the appropriate sorts.
|
||||
|
||||
// DLG: DONE! Do the appropriate sorts for each table.
|
||||
Collections.sort(pendingJobs, new AutoIngestJob.PriorityComparator());
|
||||
runningJobs.sort(new AutoIngestJob.AlphabeticalComparator());
|
||||
|
||||
refreshTable(pendingJobs, pendingTable, pendingTableModel);
|
||||
refreshTable(runningJobs, runningTable, runningTableModel);
|
||||
refreshTable(completedJobs, completedTable, completedTableModel);
|
||||
@ -480,7 +470,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
continue;
|
||||
}
|
||||
AutoIngestJob.StageDetails status = job.getStageDetails();
|
||||
ManifestNodeData nodeData = job.getNodeData();
|
||||
AutoIngestJobNodeData nodeData = job.getNodeData();
|
||||
tableModel.addRow(new Object[]{
|
||||
nodeData.getCaseName(), // CASE
|
||||
nodeData.getDataSourcePath().getFileName(), // DATA_SOURCE
|
||||
@ -557,7 +547,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
*/
|
||||
private enum JobsTableModelColumns {
|
||||
|
||||
// DLG: Go through the bundles.properties file and delete and unused key-value pairs.
|
||||
// DLG: Go through the bundles.properties file and delete any unused key-value pairs.
|
||||
CASE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Case")),
|
||||
DATA_SOURCE(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ImageFolder")),
|
||||
HOST_NAME(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.HostName")),
|
||||
@ -580,6 +570,15 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
return header;
|
||||
}
|
||||
|
||||
/*
|
||||
* DLG: We need to add the AutoIngestJob object for the row to the
|
||||
* table. As a model you can look in AutoIngestControlPanel to see how a
|
||||
* boolean is stored in a hidden IS_LOCAL_JOB column and do something
|
||||
* similar for the job. Once youy hjave done that, you can change the
|
||||
* button event handler for the Prioritize button to make it pass the
|
||||
* AutoIngestJob to the AutoIngestMonitor instead of the manifest file
|
||||
* path.
|
||||
*/
|
||||
private static final String[] headers = {
|
||||
CASE.getColumnHeader(),
|
||||
DATA_SOURCE.getColumnHeader(),
|
||||
@ -594,25 +593,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
MANIFEST_FILE_PATH.getColumnHeader()};
|
||||
}
|
||||
|
||||
/**
|
||||
* A task that gets the current snapshot of the pending, running and
|
||||
* completed auto ingest jobs lists for an auto ingest cluster from the auto
|
||||
* ingest monitor, sorts them, and queues a UI components refresh task for
|
||||
* execution in the EDT.
|
||||
*/
|
||||
private class GetJobsSnapshotTask implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
AutoIngestMonitor.JobsSnapshot jobsSnapshot = autoIngestMonitor.getJobsSnapshot();
|
||||
List<AutoIngestJob> pendingJobs = jobsSnapshot.getPendingJobs();
|
||||
List<AutoIngestJob> runningJobs = jobsSnapshot.getRunningJobs();
|
||||
List<AutoIngestJob> completedJobs = jobsSnapshot.getCompletedJobs();
|
||||
// DLG: Do the appropriate sorts in this background task.
|
||||
EventQueue.invokeLater(new RefreshComponentsTask(pendingJobs, runningJobs, completedJobs));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A task that refreshes the UI components on this panel to reflect a
|
||||
* snapshot of the pending, running and completed auto ingest jobs lists of
|
||||
@ -620,31 +600,22 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
*/
|
||||
private class RefreshComponentsTask implements Runnable {
|
||||
|
||||
private final List<AutoIngestJob> pendingJobs;
|
||||
private final List<AutoIngestJob> runningJobs;
|
||||
private final List<AutoIngestJob> completedJobs;
|
||||
private final JobsSnapshot jobsSnapshot;
|
||||
|
||||
/**
|
||||
* Constructs a task that refreshes the UI components on this panel to
|
||||
* reflect a snapshot of the pending, running and completed auto ingest
|
||||
* jobs lists of an auto ingest cluster.
|
||||
*
|
||||
* @param pendingJobs The pending jobs list.
|
||||
* @param runningJobs The running jobs list.
|
||||
* @param completedJobs The completed jobs list.
|
||||
* @param jobsSnapshot The jobs snapshot.
|
||||
*/
|
||||
RefreshComponentsTask(List<AutoIngestJob> pendingJobs, List<AutoIngestJob> runningJobs, List<AutoIngestJob> completedJobs) {
|
||||
this.pendingJobs = pendingJobs;
|
||||
this.runningJobs = runningJobs;
|
||||
this.completedJobs = completedJobs;
|
||||
RefreshComponentsTask(JobsSnapshot jobsSnapshot) {
|
||||
this.jobsSnapshot = jobsSnapshot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
refreshTable(pendingJobs, pendingTable, pendingTableModel);
|
||||
refreshTable(runningJobs, runningTable, runningTableModel);
|
||||
refreshTable(completedJobs, completedTable, completedTableModel);
|
||||
refreshButton.setEnabled(true);
|
||||
refreshTables(jobsSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
@ -767,7 +738,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(refreshButton, org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.refreshButton.text")); // NOI18N
|
||||
refreshButton.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.refreshButton.toolTipText")); // NOI18N
|
||||
refreshButton.setEnabled(false);
|
||||
refreshButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
refreshButtonActionPerformed(evt);
|
||||
@ -795,10 +765,11 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(pendingScrollPane)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lbPending)
|
||||
.addComponent(lbCompleted)
|
||||
@ -812,9 +783,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(prioritizeButton, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addComponent(pendingScrollPane, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(runningScrollPane)
|
||||
.addComponent(completedScrollPane))
|
||||
.addComponent(runningScrollPane, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(completedScrollPane, javax.swing.GroupLayout.Alignment.LEADING))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
@ -826,13 +796,13 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
.addComponent(tbServicesStatusMessage, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lbPending, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGap(1, 1, 1)
|
||||
.addComponent(pendingScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 215, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(lbRunning)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGap(1, 1, 1)
|
||||
.addComponent(runningScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(lbCompleted)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(completedScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
@ -858,6 +828,9 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
}//GEN-LAST:event_refreshButtonActionPerformed
|
||||
|
||||
@Messages({
|
||||
"AutoIngestDashboard.PrioritizeError=Failed to prioritize job \"%s\"."
|
||||
})
|
||||
private void prioritizeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prioritizeButtonActionPerformed
|
||||
if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
@ -867,8 +840,11 @@ public final class AutoIngestDashboard extends JPanel implements Observer {
|
||||
jobsSnapshot = autoIngestMonitor.prioritizeJob(manifestFilePath);
|
||||
refreshTables(jobsSnapshot);
|
||||
} catch (AutoIngestMonitor.AutoIngestMonitorException ex) {
|
||||
// DLG: Log the exception and do a popup with a user-friendly
|
||||
// DLG: DONE! Log the exception and do a popup with a user-friendly
|
||||
// message explaining that the operation failed
|
||||
String errorMessage = String.format(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.PrioritizeError"), manifestFilePath);
|
||||
logger.log(Level.SEVERE, errorMessage, ex);
|
||||
MessageNotifyUtil.Message.error(errorMessage);
|
||||
}
|
||||
setCursor(Cursor.getDefaultCursor());
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import org.openide.windows.Mode;
|
||||
import org.openide.windows.TopComponent;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
|
||||
/**
|
||||
* Top component which displays the Auto Ingest Dashboard interface.
|
||||
@ -41,11 +42,18 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
"CTL_AutoIngestDashboardTopComponent=Auto Ingest Dashboard"})
|
||||
public final class AutoIngestDashboardTopComponent extends TopComponent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
public final static String PREFERRED_ID = "AutoIngestDashboardTopComponent"; // NON-NLS
|
||||
private static final Logger logger = Logger.getLogger(AutoIngestDashboardTopComponent.class.getName());
|
||||
private static boolean topComponentInitialized = false;
|
||||
|
||||
@Messages({
|
||||
"AutoIngestDashboardTopComponent.exceptionMessage.failedToCreateDashboard=Failed to create Auto Ingest Dashboard.",})
|
||||
public static void openTopComponent() {
|
||||
/*
|
||||
* DLG: Please make the top component initial size big enough to show
|
||||
* the whole dashboard.
|
||||
*/
|
||||
final AutoIngestDashboardTopComponent tc = (AutoIngestDashboardTopComponent) WindowManager.getDefault().findTopComponent(PREFERRED_ID);
|
||||
if (tc != null) {
|
||||
topComponentInitialized = true;
|
||||
@ -59,15 +67,15 @@ public final class AutoIngestDashboardTopComponent extends TopComponent {
|
||||
try {
|
||||
dashboard = AutoIngestDashboard.createDashboard();
|
||||
tc.add(dashboard);
|
||||
dashboard.setSize(dashboard.getPreferredSize());
|
||||
dashboard.setSize(992, 744);
|
||||
if (tc.isOpened() == false) {
|
||||
tc.open();
|
||||
}
|
||||
tc.toFront();
|
||||
tc.requestActive();
|
||||
} catch (AutoIngestDashboard.AutoIngestDashboardException ex) {
|
||||
// DLG: Catch the exception, log it, and pop up an error dialog
|
||||
// with a user-friendly message
|
||||
logger.log(Level.SEVERE, "Unable to create auto ingest dashboard", ex);
|
||||
MessageNotifyUtil.Message.error(Bundle.AutoIngestDashboardTopComponent_exceptionMessage_failedToCreateDashboard());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -129,5 +137,4 @@ public final class AutoIngestDashboardTopComponent extends TopComponent {
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
}
|
||||
|
@ -41,10 +41,10 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName();
|
||||
private final ManifestNodeData nodeData;
|
||||
private final AutoIngestJobNodeData nodeData;
|
||||
private final String nodeName;
|
||||
@GuardedBy("this")
|
||||
private String caseDirectoryPath; // DLG: Replace with ManifestNodeData.caseDirectoryPath
|
||||
private String caseDirectoryPath; // DLG: Replace with AutoIngestJobNodeData.caseDirectoryPath
|
||||
@GuardedBy("this")
|
||||
private Stage stage;
|
||||
@GuardedBy("this")
|
||||
@ -73,7 +73,14 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
* processing, otherwise the locla host.
|
||||
* @param stage The processing stage for display purposes.
|
||||
*/
|
||||
AutoIngestJob(ManifestNodeData nodeData, Path caseDirectoryPath, String nodeName, Stage stage) {
|
||||
/*
|
||||
* DLG: We need a contrucotr that takes just the node data. When we have
|
||||
* added the case dierectory path, the host name and the stage data to the
|
||||
* ZK nodes, we probably cna use that constructor only. I'm thinking this
|
||||
* because we will creater node data with initial values when we first
|
||||
* discover the nodes, and then we will continue to update it.
|
||||
*/
|
||||
AutoIngestJob(AutoIngestJobNodeData nodeData, Path caseDirectoryPath, String nodeName, Stage stage) {
|
||||
this.nodeData = nodeData;
|
||||
if (null != caseDirectoryPath) {
|
||||
this.caseDirectoryPath = caseDirectoryPath.toString();
|
||||
@ -90,7 +97,7 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
*
|
||||
* @return The node data.
|
||||
*/
|
||||
ManifestNodeData getNodeData() {
|
||||
AutoIngestJobNodeData getNodeData() {
|
||||
return this.nodeData;
|
||||
}
|
||||
|
||||
@ -256,6 +263,11 @@ public final class AutoIngestJob implements Comparable<AutoIngestJob>, Serializa
|
||||
}
|
||||
|
||||
// DLG: Add a toString override
|
||||
@Override
|
||||
public String toString() {
|
||||
// DLG: FINISH ME!
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom comparator that allows us to sort List<AutoIngestJob> on reverse
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -26,34 +26,60 @@ import java.util.Date;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* A coordination service node data transfer object for an auto ingest job.
|
||||
*/
|
||||
final class ManifestNodeData implements Serializable {
|
||||
|
||||
private static final int NODE_DATA_VERSION = 2;
|
||||
private static final int MAX_POSSIBLE_NODE_DATA_SIZE = 65831;
|
||||
final class AutoIngestJobNodeData implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final int NODE_DATA_VERSION = 1;
|
||||
private static final int MAX_POSSIBLE_NODE_DATA_SIZE = 131493;
|
||||
private static final int DEFAULT_PRIORITY = 0;
|
||||
private final boolean coordSvcNodeDataWasSet;
|
||||
|
||||
/*
|
||||
* Version 0 fields.
|
||||
*/
|
||||
private final boolean coordSvcNodeDataWasSet;
|
||||
private ProcessingStatus status;
|
||||
private int priority;
|
||||
private int numberOfCrashes;
|
||||
private long completedDate;
|
||||
private boolean errorsOccurred;
|
||||
|
||||
// These are not used by version '1' nodes.
|
||||
/*
|
||||
* Version 1 fields.
|
||||
*/
|
||||
private int version;
|
||||
private String deviceId;
|
||||
private String caseName;
|
||||
private String caseDirectoryPath;
|
||||
private long manifestFileDate;
|
||||
private String manifestFilePath;
|
||||
private String dataSourcePath;
|
||||
//DLG: Add caseDirectoryPath from AutoIngestJob
|
||||
private String processingStage;
|
||||
private long processingStageStartDate;
|
||||
private String processingHost;
|
||||
|
||||
//DLG: Add caseDirectoryPath from AutoIngestJob
|
||||
/*
|
||||
* DLG: Rename class to AutoIngestJobNodeData - Add String
|
||||
* caseDirectoryPath. Needed to locate case auto ingest log and later, for
|
||||
* case deletion
|
||||
*
|
||||
* Add String processingStage, long processingStageStartDate, String
|
||||
* processingHost fields. These three fields are needed to populate running
|
||||
* jobs table; use of auto ingest job data is not enough, because there
|
||||
* would be no data until a status event was received by the auto ingest
|
||||
* monitor.
|
||||
*
|
||||
* Update the AutoIngestManager code that creates ZK nodes for auto ingest
|
||||
* jobs to write the new fields described above to new nodes
|
||||
*
|
||||
* Update the AutoIngestManager code that publishes auto ingest status
|
||||
* events for the current job to update the the processing status fields
|
||||
* described above in addition to publishing AutoIngestJobStatusEvents.
|
||||
* Probably also need to write this data initially when a jo becomes the
|
||||
* current job.
|
||||
*/
|
||||
/**
|
||||
* Constructs a coordination service node data data transfer object for an
|
||||
* auto ingest manifest from the raw bytes obtained from the coordination
|
||||
@ -61,7 +87,7 @@ final class ManifestNodeData implements Serializable {
|
||||
*
|
||||
* @param nodeData The raw bytes received from the coordination service.
|
||||
*/
|
||||
ManifestNodeData(byte[] nodeData) throws ManifestNodeDataException {
|
||||
AutoIngestJobNodeData(byte[] nodeData) throws AutoIngestJobNodeDataException {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(nodeData);
|
||||
this.coordSvcNodeDataWasSet = buffer.hasRemaining();
|
||||
if (this.coordSvcNodeDataWasSet) {
|
||||
@ -89,26 +115,34 @@ final class ManifestNodeData implements Serializable {
|
||||
}
|
||||
|
||||
if (buffer.hasRemaining()) {
|
||||
// Version is greater than 1
|
||||
/*
|
||||
* There are more than 24 bytes in the buffer, so we assume the
|
||||
* version is greater than '0'.
|
||||
*/
|
||||
this.version = buffer.getInt();
|
||||
if (this.version > NODE_DATA_VERSION) {
|
||||
throw new ManifestNodeDataException(String.format(
|
||||
"Node data version %d is not suppored.",
|
||||
this.version));
|
||||
throw new AutoIngestJobNodeDataException(String.format("Node data version %d is not suppored.", this.version));
|
||||
}
|
||||
this.deviceId = getStringFromBuffer(buffer, TypeKind.BYTE);
|
||||
this.caseName = getStringFromBuffer(buffer, TypeKind.BYTE);
|
||||
//DLG: this.caseDirectoryPath = getStringFromBuffer(buffer, TypeKind.SHORT);
|
||||
this.manifestFileDate = buffer.getLong();
|
||||
this.manifestFilePath = getStringFromBuffer(buffer, TypeKind.SHORT);
|
||||
this.dataSourcePath = getStringFromBuffer(buffer, TypeKind.SHORT);
|
||||
}
|
||||
else {
|
||||
this.version = 1;
|
||||
//DLG: this.processingStage = getStringFromBuffer(buffer, TypeKind.BYTE);
|
||||
//DLG: this.processingStageStartDate = buffer.getLong();
|
||||
//DLG: this.processingHost = getStringFromBuffer(buffer, TypeKind.SHORT);
|
||||
} else {
|
||||
this.version = 0;
|
||||
this.deviceId = "";
|
||||
this.caseName = "";
|
||||
this.caseDirectoryPath = "";
|
||||
this.manifestFileDate = 0L;
|
||||
this.manifestFilePath = "";
|
||||
this.dataSourcePath = "";
|
||||
this.processingStage = "";
|
||||
this.processingStageStartDate = 0L;
|
||||
this.processingHost = "";
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,7 +159,7 @@ final class ManifestNodeData implements Serializable {
|
||||
* completed.
|
||||
* @param errorsOccurred Boolean to determine if errors have occurred.
|
||||
*/
|
||||
ManifestNodeData(Manifest manifest, ProcessingStatus status, int priority, int numberOfCrashes, Date completedDate, boolean errorOccurred) {
|
||||
AutoIngestJobNodeData(Manifest manifest, ProcessingStatus status, int priority, int numberOfCrashes, Date completedDate, boolean errorOccurred) {
|
||||
this.coordSvcNodeDataWasSet = false;
|
||||
this.status = status;
|
||||
this.priority = priority;
|
||||
@ -406,9 +440,13 @@ final class ManifestNodeData implements Serializable {
|
||||
// Write data
|
||||
putStringIntoBuffer(deviceId, buffer, TypeKind.BYTE);
|
||||
putStringIntoBuffer(caseName, buffer, TypeKind.BYTE);
|
||||
//DLG: putStringIntoBuffer(caseDirectoryPath, buffer, TypeKind.SHORT);
|
||||
buffer.putLong(this.manifestFileDate);
|
||||
putStringIntoBuffer(manifestFilePath, buffer, TypeKind.SHORT);
|
||||
putStringIntoBuffer(dataSourcePath, buffer, TypeKind.SHORT);
|
||||
//DLG: putStringIntoBuffer(processingStage, buffer, TypeKind.BYTE);
|
||||
//DLG: buffer.putLong(this.processingStageStartDate);
|
||||
//DLG: putStringIntoBuffer(processingHost, buffer, TypeKind.SHORT);
|
||||
}
|
||||
|
||||
// Prepare the array
|
@ -21,7 +21,7 @@ package org.sleuthkit.autopsy.experimental.autoingest;
|
||||
/**
|
||||
* Exception thrown when a manifest node contains incompatible data.
|
||||
*/
|
||||
public class ManifestNodeDataException extends Exception {
|
||||
public class AutoIngestJobNodeDataException extends Exception {
|
||||
|
||||
/**
|
||||
* Constructs an exception thrown when a manifest node contains incompatible
|
||||
@ -29,7 +29,7 @@ public class ManifestNodeDataException extends Exception {
|
||||
*
|
||||
* @param message An error message.
|
||||
*/
|
||||
public ManifestNodeDataException(String message) {
|
||||
public AutoIngestJobNodeDataException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ public class ManifestNodeDataException extends Exception {
|
||||
* @param message An error message.
|
||||
* @param cause An exception that caused this exception to be thrown.
|
||||
*/
|
||||
public ManifestNodeDataException(String message, Throwable cause) {
|
||||
public AutoIngestJobNodeDataException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@ -84,11 +84,11 @@ import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestAlertFile.AutoIng
|
||||
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobLogger.AutoIngestJobLoggerException;
|
||||
import org.sleuthkit.autopsy.experimental.autoingest.FileExporter.FileExportException;
|
||||
import org.sleuthkit.autopsy.experimental.autoingest.ManifestFileParser.ManifestFileParserException;
|
||||
import org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus;
|
||||
import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.COMPLETED;
|
||||
import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.DELETED;
|
||||
import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.PENDING;
|
||||
import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.PROCESSING;
|
||||
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobNodeData.ProcessingStatus;
|
||||
import static org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobNodeData.ProcessingStatus.COMPLETED;
|
||||
import static org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobNodeData.ProcessingStatus.DELETED;
|
||||
import static org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobNodeData.ProcessingStatus.PENDING;
|
||||
import static org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobNodeData.ProcessingStatus.PROCESSING;
|
||||
import org.sleuthkit.autopsy.experimental.configuration.AutoIngestUserPreferences;
|
||||
import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration;
|
||||
import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration.SharedConfigurationException;
|
||||
@ -543,10 +543,10 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
for (AutoIngestJob job : prioritizedJobs) {
|
||||
String manifestNodePath = job.getNodeData().getManifestFilePath().toString();
|
||||
try {
|
||||
ManifestNodeData nodeData = new ManifestNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath));
|
||||
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath));
|
||||
nodeData.setPriority(maxPriority);
|
||||
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, nodeData.toArray());
|
||||
} catch (ManifestNodeDataException ex) {
|
||||
} catch (AutoIngestJobNodeDataException ex) {
|
||||
SYS_LOGGER.log(Level.WARNING, String.format("Unable to use node data for %s", manifestNodePath), ex);
|
||||
} catch (CoordinationServiceException ex) {
|
||||
SYS_LOGGER.log(Level.SEVERE, String.format("Coordination service error while prioritizing %s", manifestNodePath), ex);
|
||||
@ -592,10 +592,10 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
++maxPriority;
|
||||
String manifestNodePath = prioritizedJob.getNodeData().getManifestFilePath().toString();
|
||||
try {
|
||||
ManifestNodeData nodeData = new ManifestNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath));
|
||||
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath));
|
||||
nodeData.setPriority(maxPriority);
|
||||
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, nodeData.toArray());
|
||||
} catch (ManifestNodeDataException ex) {
|
||||
} catch (AutoIngestJobNodeDataException ex) {
|
||||
SYS_LOGGER.log(Level.WARNING, String.format("Unable to use node data for %s", manifestPath), ex);
|
||||
} catch (CoordinationServiceException ex) {
|
||||
SYS_LOGGER.log(Level.SEVERE, String.format("Coordination service error while prioritizing %s", manifestNodePath), ex);
|
||||
@ -636,7 +636,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
|
||||
if (null != completedJob && null != completedJob.getCaseDirectoryPath()) {
|
||||
try {
|
||||
ManifestNodeData nodeData = completedJob.getNodeData();
|
||||
AutoIngestJobNodeData nodeData = completedJob.getNodeData();
|
||||
nodeData.setStatus(PENDING);
|
||||
nodeData.setPriority(DEFAULT_JOB_PRIORITY);
|
||||
nodeData.setNumberOfCrashes(0);
|
||||
@ -733,10 +733,10 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
*/
|
||||
for (Path manifestPath : manifestPaths) {
|
||||
try {
|
||||
ManifestNodeData nodeData = new ManifestNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
|
||||
nodeData.setStatus(ManifestNodeData.ProcessingStatus.DELETED);
|
||||
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
|
||||
nodeData.setStatus(AutoIngestJobNodeData.ProcessingStatus.DELETED);
|
||||
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString(), nodeData.toArray());
|
||||
} catch (ManifestNodeDataException ex) {
|
||||
} catch (AutoIngestJobNodeDataException ex) {
|
||||
SYS_LOGGER.log(Level.WARNING, String.format("Unable to use node data for %s", manifestPath), ex);
|
||||
} catch (InterruptedException | CoordinationServiceException ex) {
|
||||
SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set delete flag on manifest data for %s for case %s at %s", manifestPath, caseName, caseDirectoryPath), ex);
|
||||
@ -1027,7 +1027,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
byte[] rawData = coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString());
|
||||
if (null != rawData) {
|
||||
try {
|
||||
ManifestNodeData nodeData = new ManifestNodeData(rawData);
|
||||
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(rawData);
|
||||
if (nodeData.coordSvcNodeDataWasSet()) {
|
||||
ProcessingStatus processingStatus = nodeData.getStatus();
|
||||
switch (processingStatus) {
|
||||
@ -1050,7 +1050,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
} else {
|
||||
addNewPendingJob(manifest);
|
||||
}
|
||||
} catch(ManifestNodeDataException ex) {
|
||||
} catch(AutoIngestJobNodeDataException ex) {
|
||||
SYS_LOGGER.log(Level.WARNING, String.format("Unable to use node data for %s", manifestPath), ex);
|
||||
}
|
||||
} else {
|
||||
@ -1078,7 +1078,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* @param nodeData The data stored in the coordination service node for
|
||||
* the manifest.
|
||||
*/
|
||||
private void addPendingJob(ManifestNodeData nodeData) {
|
||||
private void addPendingJob(AutoIngestJobNodeData nodeData) {
|
||||
Path caseDirectory = PathUtils.findCaseDirectory(rootOutputDirectory, nodeData.getCaseName());
|
||||
nodeData.setCompletedDate(new Date(0));
|
||||
nodeData.setErrorsOccurred(false);
|
||||
@ -1100,7 +1100,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
// Is use of Curator.create().forPath() possible instead?
|
||||
try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) {
|
||||
if (null != manifestLock) {
|
||||
ManifestNodeData newNodeData = new ManifestNodeData(manifest, PENDING, DEFAULT_JOB_PRIORITY, 0, new Date(0), false);
|
||||
AutoIngestJobNodeData newNodeData = new AutoIngestJobNodeData(manifest, PENDING, DEFAULT_JOB_PRIORITY, 0, new Date(0), false);
|
||||
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString(), newNodeData.toArray());
|
||||
newPendingJobsList.add(new AutoIngestJob(newNodeData, null, LOCAL_HOST_NAME, AutoIngestJob.Stage.PENDING));
|
||||
}
|
||||
@ -1124,7 +1124,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* blocked, i.e., if auto ingest is
|
||||
* shutting down.
|
||||
*/
|
||||
private void doRecoveryIfCrashed(ManifestNodeData nodeData) throws InterruptedException {
|
||||
private void doRecoveryIfCrashed(AutoIngestJobNodeData nodeData) throws InterruptedException {
|
||||
String manifestPath = nodeData.getManifestFilePath().toString();
|
||||
if (nodeData.coordSvcNodeDataWasSet() && ProcessingStatus.PROCESSING == nodeData.getStatus()) {
|
||||
SYS_LOGGER.log(Level.SEVERE, "Attempting crash recovery for {0}", manifestPath);
|
||||
@ -1180,7 +1180,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* @param nodeData The data stored in the coordination service node for
|
||||
* the manifest.
|
||||
*/
|
||||
private void addCompletedJob(ManifestNodeData nodeData) {
|
||||
private void addCompletedJob(AutoIngestJobNodeData nodeData) {
|
||||
Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, nodeData.getCaseName());
|
||||
if (null != caseDirectoryPath) {
|
||||
newCompletedJobsList.add(new AutoIngestJob(nodeData, caseDirectoryPath, LOCAL_HOST_NAME, AutoIngestJob.Stage.COMPLETED));
|
||||
@ -1518,7 +1518,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
return;
|
||||
}
|
||||
processJob();
|
||||
} catch (ManifestNodeDataException ex) {
|
||||
} catch (AutoIngestJobNodeDataException ex) {
|
||||
SYS_LOGGER.log(Level.WARNING, String.format("Unable to use node data"), ex);
|
||||
} finally {
|
||||
manifestLock.release();
|
||||
@ -1619,7 +1619,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
}
|
||||
|
||||
try {
|
||||
ManifestNodeData nodeData = new ManifestNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
|
||||
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
|
||||
if (!nodeData.getStatus().equals(PENDING)) {
|
||||
/*
|
||||
* Due to a timing issue or a missed event, a
|
||||
@ -1646,7 +1646,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
iterator.remove();
|
||||
currentJob = job;
|
||||
break;
|
||||
} catch (ManifestNodeDataException ex) {
|
||||
} catch (AutoIngestJobNodeDataException ex) {
|
||||
SYS_LOGGER.log(Level.WARNING, String.format("Unable to use node data for %s", manifestPath), ex);
|
||||
}
|
||||
}
|
||||
@ -1692,9 +1692,9 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* i.e., if auto ingest is
|
||||
* shutting down.
|
||||
*/
|
||||
private void processJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, ManifestNodeDataException {
|
||||
private void processJob() throws CoordinationServiceException, SharedConfigurationException, ServicesMonitorException, DatabaseServerDownException, KeywordSearchServerDownException, CaseManagementException, AnalysisStartupException, FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException, AutoIngestJobNodeDataException {
|
||||
Path manifestPath = currentJob.getNodeData().getManifestFilePath();
|
||||
ManifestNodeData nodeData = new ManifestNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
|
||||
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
|
||||
nodeData.setStatus(PROCESSING);
|
||||
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString(), nodeData.toArray());
|
||||
SYS_LOGGER.log(Level.INFO, "Started processing of {0}", manifestPath);
|
||||
@ -1713,7 +1713,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
currentJob.cancel();
|
||||
}
|
||||
|
||||
nodeData = new ManifestNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
|
||||
nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
|
||||
if (currentJob.isCompleted() || currentJob.isCanceled()) {
|
||||
nodeData.setStatus(COMPLETED);
|
||||
Date completedDate = new Date();
|
||||
@ -1799,7 +1799,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
try {
|
||||
Case.closeCurrentCase();
|
||||
} catch (CaseActionException ex) {
|
||||
ManifestNodeData nodeData = currentJob.getNodeData();
|
||||
AutoIngestJobNodeData nodeData = currentJob.getNodeData();
|
||||
throw new CaseManagementException(String.format("Error closing case %s for %s", nodeData.getCaseName(), nodeData.getManifestFilePath()), ex);
|
||||
}
|
||||
}
|
||||
@ -1882,7 +1882,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* if auto ingest is shutting down.
|
||||
*/
|
||||
private Case openCase() throws CoordinationServiceException, CaseManagementException, InterruptedException {
|
||||
ManifestNodeData nodeData = currentJob.getNodeData();
|
||||
AutoIngestJobNodeData nodeData = currentJob.getNodeData();
|
||||
String caseName = nodeData.getCaseName();
|
||||
SYS_LOGGER.log(Level.INFO, "Opening case {0} for {1}", new Object[]{caseName, nodeData.getManifestFilePath()});
|
||||
currentJob.setStage(AutoIngestJob.Stage.OPENING_CASE);
|
||||
@ -2051,7 +2051,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* if auto ingest is shutting down.
|
||||
*/
|
||||
private DataSource identifyDataSource(Case caseForJob) throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException {
|
||||
ManifestNodeData nodeData = currentJob.getNodeData();
|
||||
AutoIngestJobNodeData nodeData = currentJob.getNodeData();
|
||||
Path manifestPath = nodeData.getManifestFilePath();
|
||||
SYS_LOGGER.log(Level.INFO, "Identifying data source for {0} ", manifestPath);
|
||||
currentJob.setStage(AutoIngestJob.Stage.IDENTIFYING_DATA_SOURCE);
|
||||
@ -2087,7 +2087,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* ingest is shutting down.
|
||||
*/
|
||||
private void runDataSourceProcessor(Case caseForJob, DataSource dataSource) throws InterruptedException, AutoIngestAlertFileException, AutoIngestJobLoggerException, AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException {
|
||||
ManifestNodeData nodeData = currentJob.getNodeData();
|
||||
AutoIngestJobNodeData nodeData = currentJob.getNodeData();
|
||||
Path manifestPath = nodeData.getManifestFilePath();
|
||||
SYS_LOGGER.log(Level.INFO, "Adding data source for {0} ", manifestPath);
|
||||
currentJob.setStage(AutoIngestJob.Stage.ADDING_DATA_SOURCE);
|
||||
@ -2180,7 +2180,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* ingest is shutting down.
|
||||
*/
|
||||
private void logDataSourceProcessorResult(DataSource dataSource) throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException {
|
||||
ManifestNodeData nodeData = currentJob.getNodeData();
|
||||
AutoIngestJobNodeData nodeData = currentJob.getNodeData();
|
||||
Path manifestPath = nodeData.getManifestFilePath();
|
||||
Path caseDirectoryPath = currentJob.getCaseDirectoryPath();
|
||||
AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, nodeData.getDataSourceFileName(), caseDirectoryPath);
|
||||
@ -2252,7 +2252,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* ingest is shutting down.
|
||||
*/
|
||||
private void analyze(DataSource dataSource) throws AnalysisStartupException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException {
|
||||
ManifestNodeData nodeData = currentJob.getNodeData();
|
||||
AutoIngestJobNodeData nodeData = currentJob.getNodeData();
|
||||
Path manifestPath = nodeData.getManifestFilePath();
|
||||
SYS_LOGGER.log(Level.INFO, "Starting ingest modules analysis for {0} ", manifestPath);
|
||||
currentJob.setStage(AutoIngestJob.Stage.ANALYZING_DATA_SOURCE);
|
||||
@ -2351,7 +2351,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
|
||||
* ingest is shutting down.
|
||||
*/
|
||||
private void exportFiles(DataSource dataSource) throws FileExportException, AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException {
|
||||
ManifestNodeData nodeData = currentJob.getNodeData();
|
||||
AutoIngestJobNodeData nodeData = currentJob.getNodeData();
|
||||
Path manifestPath = nodeData.getManifestFilePath();
|
||||
SYS_LOGGER.log(Level.INFO, "Exporting files for {0}", manifestPath);
|
||||
currentJob.setStage(AutoIngestJob.Stage.EXPORTING_FILES);
|
||||
|
@ -64,28 +64,15 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang
|
||||
@GuardedBy("jobsLock")
|
||||
private JobsSnapshot jobsSnapshot;
|
||||
|
||||
/**
|
||||
* Creates an auto ingest monitor responsible for monitoring and reporting
|
||||
* the processing of auto ingest jobs.
|
||||
*
|
||||
* @return The auto ingest monitor.
|
||||
*
|
||||
* @throws AutoIngestMonitorException If the monitor cannot be created.
|
||||
*/
|
||||
static AutoIngestMonitor createMonitor() throws AutoIngestMonitorException {
|
||||
AutoIngestMonitor monitor = new AutoIngestMonitor();
|
||||
monitor.startUp();
|
||||
return monitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an auto ingest monitor responsible for monitoring and
|
||||
* reporting the processing of auto ingest jobs.
|
||||
*/
|
||||
private AutoIngestMonitor() {
|
||||
AutoIngestMonitor() {
|
||||
eventPublisher = new AutopsyEventPublisher();
|
||||
coordSvcQueryExecutor = new ScheduledThreadPoolExecutor(NUM_COORD_SVC_QUERY_THREADS, new ThreadFactoryBuilder().setNameFormat(COORD_SVC_QUERY_THREAD_NAME).build());
|
||||
jobsLock = new Object();
|
||||
jobsSnapshot = new JobsSnapshot();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,7 +81,7 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang
|
||||
* @throws AutoIngestMonitorException If there is a problem starting the
|
||||
* auto ingest monitor.
|
||||
*/
|
||||
private void startUp() throws AutoIngestMonitor.AutoIngestMonitorException {
|
||||
void startUp() throws AutoIngestMonitor.AutoIngestMonitorException {
|
||||
try {
|
||||
coordinationService = CoordinationService.getInstance();
|
||||
} catch (CoordinationServiceException ex) {
|
||||
@ -152,10 +139,12 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang
|
||||
* @param event A auto ingest job started event.
|
||||
*/
|
||||
private void handleJobStartedEvent(AutoIngestJobStartedEvent event) {
|
||||
// DLG: Remove job from event from pending queue, if present
|
||||
synchronized (jobsLock) {
|
||||
// DLG: Remove job from pending queue, if present
|
||||
// DLG: Add job to running jobs list
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
notifyObservers(jobsSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -164,9 +153,11 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang
|
||||
* @param event A auto ingest job status event.
|
||||
*/
|
||||
private void handleJobStatusEvent(AutoIngestJobStatusEvent event) {
|
||||
synchronized (jobsLock) {
|
||||
// DLG: Replace job in running list with job from event
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
notifyObservers(jobsSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -175,10 +166,12 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang
|
||||
* @param event A auto ingest job completed event.
|
||||
*/
|
||||
private void handleJobCompletedEvent(AutoIngestJobCompletedEvent event) {
|
||||
synchronized (jobsLock) {
|
||||
// DLG: Remove job from event from running list, if present
|
||||
// DLG: Add job to completed list
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
notifyObservers(jobsSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,9 +180,11 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang
|
||||
* @param event A job/case prioritization event.
|
||||
*/
|
||||
private void handleCasePrioritizationEvent(AutoIngestCasePrioritizedEvent event) {
|
||||
synchronized (jobsLock) {
|
||||
// DLG: Replace job in pending queue with job from event
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
notifyObservers(jobsSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -241,7 +236,7 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang
|
||||
List<String> nodeList = coordinationService.getNodeList(CoordinationService.CategoryNode.MANIFESTS);
|
||||
for (String node : nodeList) {
|
||||
// DLG: Do not need a lock here
|
||||
// DLG: Get the node data and construct a AutoIngestJobNodeData object (rename ManifestNodeData => AutoIngestJobData)
|
||||
// DLG: Get the node data and construct a AutoIngestJobNodeData object (rename AutoIngestJobNodeData => AutoIngestJobData)
|
||||
// DLG: Construct an AutoIngestJob object from the AutoIngestJobNodeData object, need new AutoIngestJob constructor
|
||||
}
|
||||
return newJobsSnapshot;
|
||||
@ -281,10 +276,10 @@ public final class AutoIngestMonitor extends Observable implements PropertyChang
|
||||
++highestPriority;
|
||||
String manifestNodePath = prioritizedJob.getNodeData().getManifestFilePath().toString();
|
||||
try {
|
||||
ManifestNodeData nodeData = new ManifestNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath));
|
||||
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath));
|
||||
nodeData.setPriority(highestPriority);
|
||||
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, nodeData.toArray());
|
||||
} catch (ManifestNodeDataException | CoordinationServiceException | InterruptedException ex) {
|
||||
} catch (AutoIngestJobNodeDataException | CoordinationServiceException | InterruptedException ex) {
|
||||
throw new AutoIngestMonitorException("Error bumping priority for job " + prioritizedJob.toString(), ex);
|
||||
}
|
||||
prioritizedJob.getNodeData().setPriority(highestPriority);
|
||||
|
@ -202,7 +202,7 @@ ReviewModeCasePanel.OutputFolderHeaderText=Output Folder
|
||||
ReviewModeCasePanel.LastAccessedTimeHeaderText=Last Accessed Time
|
||||
CopyFilesPanel.bnOptions.text=&Options
|
||||
AutoIngestDashboard.lbServicesStatus.text=Services Status:
|
||||
AutoIngestDashboard.tbServicesStatusMessage.text=
|
||||
AutoIngestDashboard.tbServicesStatusMessage.text=Connecting...
|
||||
FileExporterSettingsPanel.ChooseRootDirectory=Choose a root directory for file output
|
||||
FileExporterSettingsPanel.ChooseReportDirectory=Choose a report directory
|
||||
FileExporterSettingsPanel.RuleName=Rule Name
|
||||
@ -271,47 +271,7 @@ AutoIngestCasePanel.bnOpen.text=&Open
|
||||
AutoIngestCasePanel.bnShowLog.toolTipText=Display case log file for selected case
|
||||
AutoIngestCasePanel.bnShowLog.text=&Show Log
|
||||
AutoIngestCasePanel.rbGroupLabel.text=Show cases accessed in the last 10:
|
||||
AutoIngestControlPanel.tbStatusMessage.text=
|
||||
AutoIngestControlPanel.bnShowCaseLog.toolTipText=Display case log file for selected case
|
||||
AutoIngestControlPanel.bnShowCaseLog.text=Show Case &Log
|
||||
AutoIngestControlPanel.bnDeleteCase.toolTipText=Delete the selected Case in its entirety
|
||||
AutoIngestControlPanel.bnDeleteCase.text=&Delete Case
|
||||
AutoIngestControlPanel.bnCancelJob.toolTipText=Cancel processing of the current Job and move on to the next Job. This functionality is only available for jobs running on current AIM node.
|
||||
AutoIngestControlPanel.bnCancelJob.text=&Cancel Job
|
||||
AutoIngestControlPanel.completedTable.toolTipText=The Completed table shows all Jobs that have been processed already
|
||||
AutoIngestControlPanel.runningTable.toolTipText=The Running table displays the currently running Job and information about it
|
||||
AutoIngestControlPanel.pendingTable.toolTipText=The Pending table displays the order upcoming Jobs will be processed with the top of the list first
|
||||
AutoIngestControlPanel.bnPrioritizeCase.toolTipText=Move all images associated with a case to top of Pending queue.
|
||||
AutoIngestControlPanel.bnPrioritizeCase.text=Prioriti&ze Case
|
||||
AutoIngestControlPanel.bnPause.toolTipText=Suspend processing of Pending Jobs
|
||||
AutoIngestControlPanel.bnPause.text=Pause
|
||||
AutoIngestControlPanel.bnShowProgress.toolTipText=Show the progress of the currently running Job. This functionality is only available for jobs running on current AIM node.
|
||||
AutoIngestControlPanel.bnShowProgress.text=Ingest Progress
|
||||
AutoIngestControlPanel.bnOptions.toolTipText=Display options panel. All processing must be paused to open the options panel.
|
||||
AutoIngestControlPanel.bnOptions.text=&Options
|
||||
AutoIngestControlPanel.bnExit.toolTipText=Exit Application
|
||||
AutoIngestControlPanel.bnExit.text=&Exit
|
||||
AutoIngestControlPanel.bnCancelModule.toolTipText=Cancel processing of the current module within the Job and move on to the next module within the Job. This functionality is only available for jobs running on current AIM node.
|
||||
AutoIngestControlPanel.bnCancelModule.text=Cancel &Module
|
||||
AutoIngestControlPanel.bnRefresh.toolTipText=Refresh displayed tables
|
||||
AutoIngestControlPanel.bnRefresh.text=&Refresh
|
||||
AutoIngestControlPanel.lbCompleted.text=Completed Jobs
|
||||
AutoIngestControlPanel.lbRunning.text=Running Jobs
|
||||
AutoIngestControlPanel.lbPending.text=Pending Jobs
|
||||
AutoIngestControlPanel.bnReprocessJob.text=Reprocess Job
|
||||
AutoIngestControlPanel.bnOpenLogDir.text=Open System Logs Directory
|
||||
AutoIngestControlPanel.tbServicesStatusMessage.text=
|
||||
AutoIngestControlPanel.lbServicesStatus.text=Services Status:
|
||||
AutoIngestControlPanel.bnPrioritizeJob.actionCommand=<AutoIngestDashboard.bnPrioritizeJob.text>
|
||||
AutoIngestControlPanel.bnPrioritizeJob.toolTipText=Move this folder to the top of the Pending queue.
|
||||
AutoIngestControlPanel.bnPrioritizeJob.text=Prioritize Job
|
||||
<<<<<<< HEAD
|
||||
AutoIngestControlPanel.lbStatus.text=Status:
|
||||
AutoIngestControlPanel.PauseDueToSystemError=Paused due to system error, please consult the auto ingest system log
|
||||
AutoIngestDashboard.prioritizeButton.toolTipText=Prioritizes the selected job
|
||||
AutoIngestDashboard.prioritizeButton.text=&Prioritize
|
||||
AutoIngestDashboard.refreshButton.toolTipText=Refresh displayed tables
|
||||
AutoIngestDashboard.refreshButton.text=&Refresh
|
||||
=======
|
||||
AutoIngestControlPanel.lbStatus.text=Status:
|
||||
>>>>>>> upstream/develop
|
||||
|
@ -1,5 +1,5 @@
|
||||
#Updated by build script
|
||||
#Thu, 22 Jun 2017 08:50:21 -0400
|
||||
#Thu, 07 Sep 2017 13:53:53 -0400
|
||||
LBL_splash_window_title=Starting Autopsy
|
||||
SPLASH_HEIGHT=314
|
||||
SPLASH_WIDTH=538
|
||||
@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18
|
||||
SplashRunningTextColor=0x0
|
||||
SplashRunningTextFontSize=19
|
||||
|
||||
currentVersion=Autopsy 4.4.1
|
||||
currentVersion=Autopsy 4.4.2
|
||||
|
@ -1,4 +1,4 @@
|
||||
#Updated by build script
|
||||
#Thu, 22 Jun 2017 08:50:21 -0400
|
||||
CTL_MainWindow_Title=Autopsy 4.4.1
|
||||
CTL_MainWindow_Title_No_Project=Autopsy 4.4.1
|
||||
#Thu, 07 Sep 2017 13:53:53 -0400
|
||||
CTL_MainWindow_Title=Autopsy 4.4.2
|
||||
CTL_MainWindow_Title_No_Project=Autopsy 4.4.2
|
||||
|
Loading…
x
Reference in New Issue
Block a user