From 9b69a2a75a62c75d824bfc109d7308917751cedd Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 23 Oct 2017 14:53:24 -0400 Subject: [PATCH 01/18] 3153 enabled sorting of of AID tables and added Priority column to pending jobs --- .../autoingest/AutoIngestControlPanel.form | 3 - .../autoingest/AutoIngestControlPanel.java | 105 ++++++++++-------- 2 files changed, 57 insertions(+), 51 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.form b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.form index ad525e92ee..cec9d21492 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.form +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.form @@ -169,7 +169,6 @@ - @@ -193,7 +192,6 @@ - @@ -217,7 +215,6 @@ - diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 891975223a..d87efb41ff 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -49,6 +49,7 @@ import javax.swing.UIManager; import javax.swing.event.ListSelectionEvent; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; import org.netbeans.api.options.OptionsDisplayer; import org.openide.DialogDisplayer; import org.openide.LifecycleManager; @@ -138,6 +139,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { private static final int GENERIC_COL_MAX_WIDTH = 2000; private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280; private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175; + private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 50; + private static final int PRIORITY_COLUMN_MAX_WIDTH=150; private static final int ACTIVITY_TIME_COL_MIN_WIDTH = 250; private static final int ACTIVITY_TIME_COL_MAX_WIDTH = 450; private static final int TIME_COL_MIN_WIDTH = 30; @@ -177,6 +180,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { * ordinal or a column header string. */ @Messages({ + "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority=Priority", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Case=Case", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ImageFolder=Data Source", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.HostName=Host Name", @@ -203,8 +207,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { 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")); - + MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ManifestFilePath")), + PRIORITY(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority")); private final String header; private JobsTableModelColumns(String header) { @@ -227,7 +231,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { STAGE_TIME.getColumnHeader(), CASE_DIRECTORY_PATH.getColumnHeader(), IS_LOCAL_JOB.getColumnHeader(), - MANIFEST_FILE_PATH.getColumnHeader()}; + MANIFEST_FILE_PATH.getColumnHeader(), + PRIORITY.getColumnHeader()}; } /** @@ -411,11 +416,16 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { column.setMaxWidth(TIME_COL_MAX_WIDTH); column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH); column.setWidth(TIME_COL_PREFERRED_WIDTH); + + column = pendingTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()); + column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH); + column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); + column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); /** * Prevent sorting when a column header is clicked. */ - pendingTable.setAutoCreateRowSorter(false); + pendingTable.setAutoCreateRowSorter(true); /* * Create a row selection listener to enable/disable the prioritize @@ -454,7 +464,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { 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())); - + runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader())); /* * Set up a column to display the cases associated with the jobs. */ @@ -524,9 +534,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { } private void updateRunningTableButtonsBasedOnSelectedRow() { - int row = runningTable.getSelectedRow(); + int row = runningTable.convertRowIndexToModel(runningTable.getSelectedRow()); if (row >= 0 && row < runningTable.getRowCount()) { - if ((boolean) runningTableModel.getValueAt(row, JobsTableModelColumns.IS_LOCAL_JOB.ordinal())) { + if ((boolean) runningTable.getModel().getValueAt(row, JobsTableModelColumns.IS_LOCAL_JOB.ordinal())) { enableRunningTableButtons(true); return; } @@ -550,7 +560,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { 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())); - + completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader())); /* * Set up a column to display the cases associated with the jobs. */ @@ -605,7 +615,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { /* * Prevent sorting when a column header is clicked. */ - completedTable.setAutoCreateRowSorter(false); + completedTable.setAutoCreateRowSorter(true); /* * Create a row selection listener to enable/disable the delete case and @@ -1030,9 +1040,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { */ if (null != pendingJobs) { - Path currentRow = getSelectedEntry(pendingTable, pendingTableModel); - refreshTable(pendingJobs, pendingTableModel, null); - setSelectedEntry(pendingTable, pendingTableModel, currentRow); + Path currentRow = getSelectedEntry(pendingTable); + refreshTable(pendingJobs, (DefaultTableModel)pendingTable.getModel(), null); + setSelectedEntry(pendingTable, currentRow); } if (null != runningJobs) { @@ -1041,15 +1051,15 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { } else { updateRunningTableButtonsBasedOnSelectedRow(); } - Path currentRow = getSelectedEntry(runningTable, runningTableModel); - refreshTable(runningJobs, runningTableModel, null); - setSelectedEntry(runningTable, runningTableModel, currentRow); + Path currentRow = getSelectedEntry(runningTable); + refreshTable(runningJobs, (DefaultTableModel)runningTable.getModel(), null); + setSelectedEntry(runningTable, currentRow); } if (null != completedJobs) { - Path currentRow = getSelectedEntry(completedTable, completedTableModel); - refreshTable(completedJobs, completedTableModel, null); - setSelectedEntry(completedTable, completedTableModel, currentRow); + Path currentRow = getSelectedEntry(completedTable); + refreshTable(completedJobs, (DefaultTableModel)completedTable.getModel(), null); + setSelectedEntry(completedTable, currentRow); } } @@ -1087,12 +1097,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { * * @return a path representing the current selection */ - Path getSelectedEntry(JTable table, DefaultTableModel tableModel) { + Path getSelectedEntry(JTable table) { try { - int currentlySelectedRow = table.getSelectedRow(); + int currentlySelectedRow = table.convertRowIndexToModel(table.getSelectedRow()); if (currentlySelectedRow >= 0 && currentlySelectedRow < table.getRowCount()) { - return Paths.get(tableModel.getValueAt(currentlySelectedRow, JobsTableModelColumns.CASE.ordinal()).toString(), - tableModel.getValueAt(currentlySelectedRow, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString()); + return Paths.get(table.getModel().getValueAt(currentlySelectedRow, JobsTableModelColumns.CASE.ordinal()).toString(), + table.getModel().getValueAt(currentlySelectedRow, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString()); } } catch (Exception ignored) { return null; @@ -1108,12 +1118,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { * @param tableModel The tableModel of the table to set * @param path The path of the item to set */ - void setSelectedEntry(JTable table, DefaultTableModel tableModel, Path path) { + void setSelectedEntry(JTable table, Path path) { if (path != null) { try { for (int row = 0; row < table.getRowCount(); ++row) { - Path temp = Paths.get(tableModel.getValueAt(row, JobsTableModelColumns.CASE.ordinal()).toString(), - tableModel.getValueAt(row, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString()); + Path temp = Paths.get(table.getModel().getValueAt(row, JobsTableModelColumns.CASE.ordinal()).toString(), + table.getModel().getValueAt(row, JobsTableModelColumns.DATA_SOURCE.ordinal()).toString()); if (temp.compareTo(path) == 0) { // found it table.setRowSelectionInterval(row, row); return; @@ -1156,7 +1166,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { ((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // ACTIVITY_TIME job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH job.getProcessingHostName().equals(LOCAL_HOST_NAME), // IS_LOCAL_JOB - job.getManifest().getFilePath()}); // MANIFEST_FILE_PATH + job.getManifest().getFilePath(), + job.getPriority()}); // MANIFEST_FILE_PATH } } catch (Exception ex) { SYS_LOGGER.log(Level.SEVERE, "Dashboard error refreshing table", ex); @@ -1168,9 +1179,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { */ private void refreshTables() { JobsSnapshot jobsSnapshot = manager.getCurrentJobsSnapshot(); - refreshTable(jobsSnapshot.getCompletedJobs(), completedTableModel, null); - refreshTable(jobsSnapshot.getPendingJobs(), pendingTableModel, null); - refreshTable(jobsSnapshot.getRunningJobs(), runningTableModel, null); + refreshTable(jobsSnapshot.getCompletedJobs(), (DefaultTableModel)completedTable.getModel(), null); + refreshTable(jobsSnapshot.getPendingJobs(), (DefaultTableModel)pendingTable.getModel(), null); + refreshTable(jobsSnapshot.getRunningJobs(), (DefaultTableModel)runningTable.getModel(), null); } /** @@ -1211,7 +1222,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { pendingTable.setModel(pendingTableModel); pendingTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.pendingTable.toolTipText")); // NOI18N - pendingTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS); pendingTable.setRowHeight(20); pendingTable.setSelectionModel(new DefaultListSelectionModel() { private static final long serialVersionUID = 1L; @@ -1229,7 +1239,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { runningTable.setModel(runningTableModel); runningTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.runningTable.toolTipText")); // NOI18N - runningTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS); runningTable.setRowHeight(20); runningTable.setSelectionModel(new DefaultListSelectionModel() { private static final long serialVersionUID = 1L; @@ -1247,7 +1256,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { completedTable.setModel(completedTableModel); completedTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestControlPanel.completedTable.toolTipText")); // NOI18N - completedTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS); completedTable.setRowHeight(20); completedTable.setSelectionModel(new DefaultListSelectionModel() { private static final long serialVersionUID = 1L; @@ -1425,10 +1433,10 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { .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(bnCancelJob, javax.swing.GroupLayout.PREFERRED_SIZE, 117, Short.MAX_VALUE) + .addComponent(bnShowProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 116, Short.MAX_VALUE) + .addComponent(bnCancelModule, javax.swing.GroupLayout.PREFERRED_SIZE, 117, Short.MAX_VALUE) + .addComponent(bnDeleteCase, javax.swing.GroupLayout.PREFERRED_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() @@ -1535,11 +1543,11 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { "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) { + if (completedTable.getModel().getRowCount() < 0 || completedTable.getSelectedRow() < 0) { return; } - String caseName = (String) completedTable.getValueAt(completedTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal()); + String caseName = (String) completedTable.getModel().getValueAt(completedTable.convertRowIndexToModel(completedTable.getSelectedRow()), JobsTableModelColumns.CASE.ordinal()); Object[] options = { org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "ConfirmationDialog.Delete"), org.openide.util.NbBundle.getMessage(AutoIngestControlPanel.class, "ConfirmationDialog.DoNotDelete") @@ -1556,8 +1564,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { 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()); + if (completedTable.getModel().getRowCount() > 0 && completedTable.getSelectedRow() >= 0) { + Path caseDirectoryPath = (Path) completedTable.getModel().getValueAt(completedTable.convertRowIndexToModel(completedTable.getSelectedRow()), JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal()); completedTable.clearSelection(); this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); CaseDeletionResult result = manager.deleteCase(caseName, caseDirectoryPath); @@ -1703,9 +1711,10 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { */ @Messages({"AutoIngestControlPanel.casePrioritization.errorMessage=An error occurred when prioritizing the case. Some or all jobs may not have been prioritized."}) private void bnPrioritizeCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeCaseActionPerformed - if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) { + if (pendingTable.getModel().getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) { this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - String caseName = (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.CASE.ordinal())).toString(); + + String caseName = (pendingTable.getModel().getValueAt(pendingTable.convertRowIndexToModel(pendingTable.getSelectedRow()), JobsTableModelColumns.CASE.ordinal())).toString(); try { manager.prioritizeCase(caseName); } catch (AutoIngestManager.AutoIngestManagerException ex) { @@ -1731,9 +1740,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { }) private void bnShowCaseLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnShowCaseLogActionPerformed try { - int selectedRow = completedTable.getSelectedRow(); + int selectedRow = completedTable.convertRowIndexToModel(completedTable.getSelectedRow()); if (selectedRow != -1) { - Path caseDirectoryPath = (Path) completedTableModel.getValueAt(selectedRow, JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal()); + Path caseDirectoryPath = (Path) completedTable.getModel().getValueAt(selectedRow, JobsTableModelColumns.CASE_DIRECTORY_PATH.ordinal()); if (null != caseDirectoryPath) { Path pathToLog = AutoIngestJobLogger.getLogPath(caseDirectoryPath); if (pathToLog.toFile().exists()) { @@ -1762,9 +1771,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { @Messages({"AutoIngestControlPanel.jobPrioritization.errorMessage=An error occurred when prioritizing the job."}) private void bnPrioritizeJobActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeJobActionPerformed - if (pendingTableModel.getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) { + if (pendingTable.getModel().getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) { this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - Path manifestFilePath = (Path) (pendingTableModel.getValueAt(pendingTable.getSelectedRow(), JobsTableModelColumns.MANIFEST_FILE_PATH.ordinal())); + Path manifestFilePath = (Path) (pendingTable.getModel().getValueAt(pendingTable.convertRowIndexToModel(pendingTable.getSelectedRow()), JobsTableModelColumns.MANIFEST_FILE_PATH.ordinal())); try { manager.prioritizeJob(manifestFilePath); } catch (AutoIngestManager.AutoIngestManagerException ex) { @@ -1791,11 +1800,11 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { }//GEN-LAST:event_bnOpenLogDirActionPerformed private void bnReprocessJobActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnReprocessJobActionPerformed - if (completedTableModel.getRowCount() < 0 || completedTable.getSelectedRow() < 0) { + if (completedTable.getModel().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()); + Path manifestPath = (Path) completedTable.getModel().getValueAt(completedTable.convertRowIndexToModel(completedTable.getSelectedRow()), JobsTableModelColumns.MANIFEST_FILE_PATH.ordinal()); manager.reprocessJob(manifestPath); refreshTables(); AutoIngestControlPanel.this.setCursor(Cursor.getDefaultCursor()); From 9b5dca32ae6604ef941b8096d3ad12308fb28e4c Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 23 Oct 2017 18:18:03 -0400 Subject: [PATCH 02/18] 3153 fixed issue with completed jobs re-ordering upon reprocess --- .../autoingest/AutoIngestControlPanel.java | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index d87efb41ff..22b758f2fc 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -39,17 +39,19 @@ import javax.swing.DefaultListSelectionModel; import java.awt.Color; import java.beans.PropertyChangeEvent; import java.io.File; -import java.util.Collections; + import java.util.logging.Logger; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTable; +import javax.swing.RowSorter; +import static javax.swing.SortOrder.DESCENDING; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.event.ListSelectionEvent; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; -import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; import org.netbeans.api.options.OptionsDisplayer; import org.openide.DialogDisplayer; import org.openide.LifecycleManager; @@ -140,7 +142,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280; private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175; private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 50; - private static final int PRIORITY_COLUMN_MAX_WIDTH=150; + private static final int PRIORITY_COLUMN_MAX_WIDTH = 150; private static final int ACTIVITY_TIME_COL_MIN_WIDTH = 250; private static final int ACTIVITY_TIME_COL_MAX_WIDTH = 450; private static final int TIME_COL_MIN_WIDTH = 30; @@ -290,7 +292,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { return false; } }; - initComponents(); // Generated code. setServicesStatusMessage(); initPendingJobsTable(); @@ -298,6 +299,13 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { initCompletedJobsTable(); initButtons(); + @SuppressWarnings("unchecked") + TableRowSorter sorter = (TableRowSorter) completedTable.getRowSorter(); + List list = new ArrayList<>(); + list.add(new RowSorter.SortKey(JobsTableModelColumns.COMPLETED_TIME.ordinal(), DESCENDING)); + sorter.setSortKeys(list); + sorter.sort(); + /* * Must set this flag, otherwise pop up menus don't close properly. */ @@ -416,7 +424,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { column.setMaxWidth(TIME_COL_MAX_WIDTH); column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH); column.setWidth(TIME_COL_PREFERRED_WIDTH); - + column = pendingTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()); column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH); column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); @@ -554,10 +562,10 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { * does not remove the columns from the model, just from this table. */ completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STARTED_TIME.getColumnHeader())); + completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.HOST_NAME.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STAGE.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.STAGE_TIME.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.IS_LOCAL_JOB.getColumnHeader())); - completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.HOST_NAME.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader())); @@ -992,7 +1000,6 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { List completedJobs = new ArrayList<>(); manager.getJobs(pendingJobs, runningJobs, completedJobs); // Sort the completed jobs list by completed date - Collections.sort(completedJobs, new AutoIngestJob.CompletedDateDescendingComparator()); EventQueue.invokeLater(new RefreshComponentsTask(pendingJobs, runningJobs, completedJobs)); } } @@ -1041,7 +1048,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { if (null != pendingJobs) { Path currentRow = getSelectedEntry(pendingTable); - refreshTable(pendingJobs, (DefaultTableModel)pendingTable.getModel(), null); + refreshTable(pendingJobs, (DefaultTableModel) pendingTable.getModel(), null); setSelectedEntry(pendingTable, currentRow); } @@ -1052,14 +1059,14 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { updateRunningTableButtonsBasedOnSelectedRow(); } Path currentRow = getSelectedEntry(runningTable); - refreshTable(runningJobs, (DefaultTableModel)runningTable.getModel(), null); - setSelectedEntry(runningTable, currentRow); + refreshTable(runningJobs, (DefaultTableModel) runningTable.getModel(), null); + setSelectedEntry(runningTable, currentRow); } if (null != completedJobs) { Path currentRow = getSelectedEntry(completedTable); - refreshTable(completedJobs, (DefaultTableModel)completedTable.getModel(), null); - setSelectedEntry(completedTable, currentRow); + refreshTable(completedJobs, (DefaultTableModel) completedTable.getModel(), null); + setSelectedEntry(completedTable, currentRow); } } @@ -1179,9 +1186,9 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { */ private void refreshTables() { JobsSnapshot jobsSnapshot = manager.getCurrentJobsSnapshot(); - refreshTable(jobsSnapshot.getCompletedJobs(), (DefaultTableModel)completedTable.getModel(), null); - refreshTable(jobsSnapshot.getPendingJobs(), (DefaultTableModel)pendingTable.getModel(), null); - refreshTable(jobsSnapshot.getRunningJobs(), (DefaultTableModel)runningTable.getModel(), null); + refreshTable(jobsSnapshot.getCompletedJobs(), (DefaultTableModel) completedTable.getModel(), null); + refreshTable(jobsSnapshot.getPendingJobs(), (DefaultTableModel) pendingTable.getModel(), null); + refreshTable(jobsSnapshot.getRunningJobs(), (DefaultTableModel) runningTable.getModel(), null); } /** @@ -1713,7 +1720,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { private void bnPrioritizeCaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnPrioritizeCaseActionPerformed if (pendingTable.getModel().getRowCount() > 0 && pendingTable.getSelectedRow() >= 0) { this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - + String caseName = (pendingTable.getModel().getValueAt(pendingTable.convertRowIndexToModel(pendingTable.getSelectedRow()), JobsTableModelColumns.CASE.ordinal())).toString(); try { manager.prioritizeCase(caseName); From 71dfdca9b13aa05751c9a1e3d98ed86ec586e7ae Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 24 Oct 2017 17:28:24 -0400 Subject: [PATCH 03/18] 3153 change priority column to prioritized flag column, fix priority saving bug --- .../autoingest/AutoIngestControlPanel.java | 64 +++++++++++-------- .../autoingest/AutoIngestManager.java | 19 ++++-- .../PrioritizedIconCellRenderer.java | 58 +++++++++++++++++ 3 files changed, 107 insertions(+), 34 deletions(-) create mode 100644 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 22b758f2fc..fa0ec8e065 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -141,7 +141,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { private static final int GENERIC_COL_MAX_WIDTH = 2000; private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280; private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175; - private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 50; + private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 60; private static final int PRIORITY_COLUMN_MAX_WIDTH = 150; private static final int ACTIVITY_TIME_COL_MIN_WIDTH = 250; private static final int ACTIVITY_TIME_COL_MAX_WIDTH = 450; @@ -182,7 +182,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { * ordinal or a column header string. */ @Messages({ - "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority=Priority", + "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Priority=Prioritized", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.Case=Case", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.ImageFolder=Data Source", "AutoIngestControlPanel.JobsTableModel.ColumnHeader.HostName=Host Name", @@ -266,32 +266,12 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { manager = AutoIngestManager.getInstance(); - pendingTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) { - private static final long serialVersionUID = 1L; + pendingTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0); - @Override - public boolean isCellEditable(int row, int column) { - return false; - } - }; + runningTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0); - runningTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) { - private static final long serialVersionUID = 1L; + completedTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0); - @Override - public boolean isCellEditable(int row, int column) { - return false; - } - }; - - completedTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) { - private static final long serialVersionUID = 1L; - - @Override - public boolean isCellEditable(int row, int column) { - return false; - } - }; initComponents(); // Generated code. setServicesStatusMessage(); initPendingJobsTable(); @@ -426,12 +406,13 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { column.setWidth(TIME_COL_PREFERRED_WIDTH); column = pendingTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()); + column.setCellRenderer(new PrioritizedIconCellRenderer()); column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH); column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); /** - * Prevent sorting when a column header is clicked. + * Allow sorting when a column header is clicked. */ pendingTable.setAutoCreateRowSorter(true); @@ -621,7 +602,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { column.setWidth(STATUS_COL_PREFERRED_WIDTH); /* - * Prevent sorting when a column header is clicked. + * Allow sorting when a column header is clicked. */ completedTable.setAutoCreateRowSorter(true); @@ -1846,4 +1827,33 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { private javax.swing.JTextField tbStatusMessage; // End of variables declaration//GEN-END:variables + private class AutoIngestTableModel extends DefaultTableModel { + + private static final long serialVersionUID = 1L; + + private AutoIngestTableModel(String[] headers, int i) { + super(headers, i); + } + + @Override + public boolean isCellEditable(int row, int column) { + return false; + } + + @Override + public Class getColumnClass(int columnIndex) { + if (columnIndex == JobsTableModelColumns.PRIORITY.ordinal()) { + return Integer.class; + } else if (columnIndex == JobsTableModelColumns.CREATED_TIME.ordinal() + || columnIndex == JobsTableModelColumns.COMPLETED_TIME.ordinal() + || columnIndex == JobsTableModelColumns.STARTED_TIME.ordinal() + || columnIndex == JobsTableModelColumns.STAGE_TIME.ordinal()) { + return Date.class; + } else if (columnIndex == JobsTableModelColumns.STATUS.ordinal()) { + return Boolean.class; + } else { + return super.getColumnClass(columnIndex); + } + } + } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index c5f43a8f1f..9f43879b55 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -503,6 +503,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang } SYS_LOGGER.log(Level.INFO, "Starting input scan of {0}", rootInputDirectory); InputDirScanner scanner = new InputDirScanner(); + scanner.scan(); SYS_LOGGER.log(Level.INFO, "Completed input scan of {0}", rootInputDirectory); } @@ -558,10 +559,12 @@ public final class AutoIngestManager extends Observable implements PropertyChang if (!prioritizedJobs.isEmpty()) { ++maxPriority; for (AutoIngestJob job : prioritizedJobs) { + int oldPriority = job.getPriority(); + job.setPriority(maxPriority); try { this.updateCoordinationServiceNode(job); - job.setPriority(maxPriority); } catch (CoordinationServiceException | InterruptedException ex) { + job.setPriority(oldPriority); throw new AutoIngestManagerException("Error updating case priority", ex); } } @@ -612,12 +615,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang */ if (null != prioritizedJob) { ++maxPriority; + int oldPriority = prioritizedJob.getPriority(); + prioritizedJob.setPriority(maxPriority); try { this.updateCoordinationServiceNode(prioritizedJob); } catch (CoordinationServiceException | InterruptedException ex) { + prioritizedJob.setPriority(oldPriority); throw new AutoIngestManagerException("Error updating job priority", ex); } - prioritizedJob.setPriority(maxPriority); } Collections.sort(pendingJobs, new AutoIngestJob.PriorityComparator()); @@ -1046,8 +1051,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang if (null != manifest) { /* - * Update the mapping of case names to manifest paths that is - * used for case deletion. + * Update the mapping of case names to manifest paths that + * is used for case deletion. */ String caseName = manifest.getCaseName(); Path manifestPath = manifest.getFilePath(); @@ -1061,8 +1066,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang } /* - * Add a job to the pending jobs queue, the completed jobs list, - * or do crashed job recovery, as required. + * Add a job to the pending jobs queue, the completed jobs + * list, or do crashed job recovery, as required. */ try { byte[] rawData = coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()); @@ -1082,7 +1087,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang break; case DELETED: /* - * Ignore jobs marked as "deleted." + * Ignore jobs marked as "deleted." */ break; default: diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java new file mode 100644 index 0000000000..11127093ac --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java @@ -0,0 +1,58 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2017 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.experimental.autoingest; + +import java.awt.Component; +import javax.swing.ImageIcon; +import javax.swing.JTable; +import static javax.swing.SwingConstants.CENTER; +import org.openide.util.ImageUtilities; +import org.openide.util.NbBundle.Messages; + +/** + * A JTable cell renderer that represents whether the priority value of a job + * has ever been increased, tick if prioritized nothing if not. + */ +class PrioritizedIconCellRenderer extends GrayableCellRenderer { + + + @Messages({ + "PrioritizedIconCellRenderer.prioritized.tooltiptext=This job has been prioritised. The most recently prioritised job should be processed next.", + "PrioritizedIconCellRenderer.notPrioritized.tooltiptext=This job has not been prioritized." + }) + private static final long serialVersionUID = 1L; + static final ImageIcon checkedIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/tick.png", false)); + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + setHorizontalAlignment(CENTER); + if ((value instanceof Integer)) { + if ((int) value == 0) { + setIcon(null); + setToolTipText(org.openide.util.NbBundle.getMessage(CaseStatusIconCellRenderer.class, "PrioritizedIconCellRenderer.notPrioritized.tooltiptext")); + } else { + setIcon(checkedIcon); + setToolTipText(org.openide.util.NbBundle.getMessage(CaseStatusIconCellRenderer.class, "PrioritizedIconCellRenderer.prioritized.tooltiptext")); + } + } + grayCellIfTableNotEnabled(table, isSelected); + + return this; + } +} From 1402e683b59db69de50bc77dc93ab669865e2f17 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 24 Oct 2017 17:41:13 -0400 Subject: [PATCH 04/18] 3153 fix spelling of prioritized --- .../experimental/autoingest/PrioritizedIconCellRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java index 11127093ac..8452e0fc22 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PrioritizedIconCellRenderer.java @@ -33,7 +33,7 @@ class PrioritizedIconCellRenderer extends GrayableCellRenderer { @Messages({ - "PrioritizedIconCellRenderer.prioritized.tooltiptext=This job has been prioritised. The most recently prioritised job should be processed next.", + "PrioritizedIconCellRenderer.prioritized.tooltiptext=This job has been prioritized. The most recently prioritized job should be processed next.", "PrioritizedIconCellRenderer.notPrioritized.tooltiptext=This job has not been prioritized." }) private static final long serialVersionUID = 1L; From 5b080df30f945de7fffbc93b3686cc356c5b9c68 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 24 Oct 2017 19:08:29 -0400 Subject: [PATCH 05/18] 3153 put comment on correct line --- .../experimental/autoingest/AutoIngestControlPanel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index fa0ec8e065..7499a770d7 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -1154,8 +1154,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { ((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // ACTIVITY_TIME job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH job.getProcessingHostName().equals(LOCAL_HOST_NAME), // IS_LOCAL_JOB - job.getManifest().getFilePath(), - job.getPriority()}); // MANIFEST_FILE_PATH + job.getManifest().getFilePath(), // MANIFEST_FILE_PATH + job.getPriority()}); // PRIORITY } } catch (Exception ex) { SYS_LOGGER.log(Level.SEVERE, "Dashboard error refreshing table", ex); From 0f5fb4cb5248312212b5fa1584a185b3fa379a66 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 24 Oct 2017 19:10:16 -0400 Subject: [PATCH 06/18] 3166 Sortable columns and prioritized column added to Aid 2.0 --- .../autoingest/AutoIngestDashboard.form | 3 -- .../autoingest/AutoIngestDashboard.java | 32 ++++++++++++------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.form b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.form index 4a943b4924..2ab9f9051c 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.form +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.form @@ -103,7 +103,6 @@ - @@ -127,7 +126,6 @@ - @@ -151,7 +149,6 @@ - diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java index 2d10dff258..edbefe51d7 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java @@ -55,6 +55,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer { private static final int GENERIC_COL_MAX_WIDTH = 2000; private static final int PENDING_TABLE_COL_PREFERRED_WIDTH = 280; private static final int RUNNING_TABLE_COL_PREFERRED_WIDTH = 175; + private static final int PRIORITY_COLUMN_PREFERRED_WIDTH = 60; + private static final int PRIORITY_COLUMN_MAX_WIDTH = 150; private static final int STAGE_TIME_COL_MIN_WIDTH = 250; private static final int STAGE_TIME_COL_MAX_WIDTH = 450; private static final int TIME_COL_MIN_WIDTH = 30; @@ -243,10 +245,15 @@ public final class AutoIngestDashboard extends JPanel implements Observer { column.setPreferredWidth(TIME_COL_PREFERRED_WIDTH); column.setWidth(TIME_COL_PREFERRED_WIDTH); + column = pendingTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader()); + column.setCellRenderer(new PrioritizedIconCellRenderer()); + column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH); + column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); + column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); /** - * Prevent sorting when a column header is clicked. + * Allow sorting when a column header is clicked. */ - pendingTable.setAutoCreateRowSorter(false); + pendingTable.setAutoCreateRowSorter(true); /* * Create a row selection listener to enable/disable the Prioritize @@ -257,8 +264,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer { return; } int row = pendingTable.getSelectedRow(); - - boolean enablePrioritizeButtons = (row >= 0 && row < pendingTable.getRowCount()); + + boolean enablePrioritizeButtons = (row >= 0 && row < pendingTable.getRowCount()); this.prioritizeJobButton.setEnabled(enablePrioritizeButtons); this.prioritizeCaseButton.setEnabled(enablePrioritizeButtons); }); @@ -280,7 +287,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer { runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.JOB.getColumnHeader())); - + runningTable.removeColumn(runningTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader())); /* * Set up a column to display the cases associated with the jobs. */ @@ -354,7 +361,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer { completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.CASE_DIRECTORY_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.MANIFEST_FILE_PATH.getColumnHeader())); completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.JOB.getColumnHeader())); - + completedTable.removeColumn(completedTable.getColumn(JobsTableModelColumns.PRIORITY.getColumnHeader())); /* * Set up a column to display the cases associated with the jobs. */ @@ -407,9 +414,9 @@ public final class AutoIngestDashboard extends JPanel implements Observer { column.setWidth(STATUS_COL_PREFERRED_WIDTH); /* - * Prevent sorting when a column header is clicked. + * Allow sorting when a column header is clicked. */ - completedTable.setAutoCreateRowSorter(false); + completedTable.setAutoCreateRowSorter(true); } /** @@ -476,6 +483,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer { ((Date.from(Instant.now()).getTime()) - (status.getStartDate().getTime())), // STAGE_TIME job.getCaseDirectoryPath(), // CASE_DIRECTORY_PATH job.getManifest().getFilePath(), // MANIFEST_FILE_PATH + job.getPriority(), // PRIORITY job }); } @@ -541,7 +549,8 @@ public final class AutoIngestDashboard extends JPanel implements Observer { * described by either an enum ordinal or a column header string. */ private enum JobsTableModelColumns { - + @Messages({"AutoIngestDashboard.JobsTableModel.ColumnHeader.Priority=Prioritized"}) + 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")), @@ -553,6 +562,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer { STATUS(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Status")), CASE_DIRECTORY_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.CaseFolder")), MANIFEST_FILE_PATH(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.ManifestFilePath")), + PRIORITY(NbBundle.getMessage(AutoIngestControlPanel.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Priority")), JOB(NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.JobsTableModel.ColumnHeader.Job")); private final String header; @@ -577,6 +587,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer { STAGE_TIME.getColumnHeader(), CASE_DIRECTORY_PATH.getColumnHeader(), MANIFEST_FILE_PATH.getColumnHeader(), + PRIORITY.getColumnHeader(), JOB.getColumnHeader() }; }; @@ -667,7 +678,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer { pendingTable.setModel(pendingTableModel); pendingTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.pendingTable.toolTipText")); // NOI18N - pendingTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS); pendingTable.setRowHeight(20); pendingTable.setSelectionModel(new DefaultListSelectionModel() { private static final long serialVersionUID = 1L; @@ -685,7 +695,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer { runningTable.setModel(runningTableModel); runningTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.runningTable.toolTipText")); // NOI18N - runningTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS); runningTable.setRowHeight(20); runningTable.setSelectionModel(new DefaultListSelectionModel() { private static final long serialVersionUID = 1L; @@ -703,7 +712,6 @@ public final class AutoIngestDashboard extends JPanel implements Observer { completedTable.setModel(completedTableModel); completedTable.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestDashboard.class, "AutoIngestDashboard.completedTable.toolTipText")); // NOI18N - completedTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS); completedTable.setRowHeight(20); completedTable.setSelectionModel(new DefaultListSelectionModel() { private static final long serialVersionUID = 1L; From 6d42d16191f50b8f6200fe5977c3d15f8b2bb98e Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 25 Oct 2017 17:28:47 -0400 Subject: [PATCH 07/18] 3153 - Date Columns in AID now sort by descending order first --- .../autoingest/AutoIngestControlPanel.java | 45 ++++++++++++++----- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 7499a770d7..26dcabff58 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -45,7 +45,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTable; import javax.swing.RowSorter; -import static javax.swing.SortOrder.DESCENDING; +import javax.swing.SortOrder; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.event.ListSelectionEvent; @@ -278,14 +278,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { initRunningJobsTable(); initCompletedJobsTable(); initButtons(); - - @SuppressWarnings("unchecked") - TableRowSorter sorter = (TableRowSorter) completedTable.getRowSorter(); - List list = new ArrayList<>(); - list.add(new RowSorter.SortKey(JobsTableModelColumns.COMPLETED_TIME.ordinal(), DESCENDING)); - sorter.setSortKeys(list); - sorter.sort(); - + completedTable.getRowSorter().toggleSortOrder(JobsTableModelColumns.COMPLETED_TIME.ordinal()); /* * Must set this flag, otherwise pop up menus don't close properly. */ @@ -414,7 +407,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { /** * Allow sorting when a column header is clicked. */ - pendingTable.setAutoCreateRowSorter(true); + pendingTable.setRowSorter(new AutoIngestTableRowSorter<>(pendingTableModel)); /* * Create a row selection listener to enable/disable the prioritize @@ -604,7 +597,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { /* * Allow sorting when a column header is clicked. */ - completedTable.setAutoCreateRowSorter(true); + completedTable.setRowSorter(new AutoIngestTableRowSorter<>(completedTableModel)); /* * Create a row selection listener to enable/disable the delete case and @@ -1856,4 +1849,34 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { } } } + + /** + * RowSorter which makes columns whose type is Date to be sorted first in + * Descending order then in Ascending order + */ + private class AutoIngestTableRowSorter extends TableRowSorter { + + private AutoIngestTableRowSorter(M tModel) { + super(tModel); + } + + @Override + public void toggleSortOrder(int column) { + if (!this.getModel().getColumnClass(column).equals(Date.class)) { + super.toggleSortOrder(column); //if it isn't a date perform the regular sorting + } else { + ArrayList sortKeys = new ArrayList<>(getSortKeys()); + if (sortKeys.isEmpty() || sortKeys.get(0).getColumn() != column) { //sort descending + sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.DESCENDING)); + } else if (sortKeys.get(0).getSortOrder() == SortOrder.ASCENDING) { + sortKeys.removeIf(key -> key.getColumn() == column); + sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.DESCENDING)); + } else { + sortKeys.removeIf(key -> key.getColumn() == column); + sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.ASCENDING)); + } + setSortKeys(sortKeys); + } + } + } } From 34c705252769d36cb5a6cafd92a39df692087fad Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 25 Oct 2017 18:18:50 -0400 Subject: [PATCH 08/18] 3166 Applied the date column sorting chages from 3153 to AID 2.0 and AutoIngestCasePanel --- .../autoingest/AutoIngestCasePanel.form | 2 - .../autoingest/AutoIngestCasePanel.java | 4 +- .../autoingest/AutoIngestControlPanel.java | 34 ---------- .../autoingest/AutoIngestDashboard.java | 67 ++++++++++--------- .../autoingest/AutoIngestRowSorter.java | 56 ++++++++++++++++ 5 files changed, 94 insertions(+), 69 deletions(-) create mode 100644 Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form index cb0f275809..f5963ff59d 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.form @@ -99,11 +99,9 @@ - - diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java index 9b6b3ddefa..0a847dbd0e 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java @@ -150,7 +150,7 @@ public final class AutoIngestCasePanel extends JPanel { theColumn.setWidth(STATUS_COL_PREFERRED_WIDTH); casesTable.removeColumn(casesTable.getColumn(OUTPUT_FOLDER_HEADER)); - + casesTable.setRowSorter(new AutoIngestTableRowSorter<>(caseTableModel)); /* * Listen for row selection changes and set button state for the current * selection. @@ -408,9 +408,7 @@ public final class AutoIngestCasePanel extends JPanel { } }); - casesTable.setAutoCreateRowSorter(true); casesTable.setModel(caseTableModel); - casesTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS); casesTable.setRowHeight(20); casesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); casesTable.addMouseListener(new java.awt.event.MouseAdapter() { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 26dcabff58..aa47fb3271 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -39,19 +39,15 @@ import javax.swing.DefaultListSelectionModel; import java.awt.Color; import java.beans.PropertyChangeEvent; import java.io.File; - import java.util.logging.Logger; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTable; -import javax.swing.RowSorter; -import javax.swing.SortOrder; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.event.ListSelectionEvent; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; -import javax.swing.table.TableRowSorter; import org.netbeans.api.options.OptionsDisplayer; import org.openide.DialogDisplayer; import org.openide.LifecycleManager; @@ -1849,34 +1845,4 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { } } } - - /** - * RowSorter which makes columns whose type is Date to be sorted first in - * Descending order then in Ascending order - */ - private class AutoIngestTableRowSorter extends TableRowSorter { - - private AutoIngestTableRowSorter(M tModel) { - super(tModel); - } - - @Override - public void toggleSortOrder(int column) { - if (!this.getModel().getColumnClass(column).equals(Date.class)) { - super.toggleSortOrder(column); //if it isn't a date perform the regular sorting - } else { - ArrayList sortKeys = new ArrayList<>(getSortKeys()); - if (sortKeys.isEmpty() || sortKeys.get(0).getColumn() != column) { //sort descending - sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.DESCENDING)); - } else if (sortKeys.get(0).getSortOrder() == SortOrder.ASCENDING) { - sortKeys.removeIf(key -> key.getColumn() == column); - sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.DESCENDING)); - } else { - sortKeys.removeIf(key -> key.getColumn() == column); - sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.ASCENDING)); - } - setSortKeys(sortKeys); - } - } - } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java index edbefe51d7..8222ccc1a6 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestDashboard.java @@ -48,7 +48,7 @@ import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMonitor.JobsSnaps /** * A dashboard for monitoring an automated ingest cluster. */ -public final class AutoIngestDashboard extends JPanel implements Observer { +final class AutoIngestDashboard extends JPanel implements Observer { private static final long serialVersionUID = 1L; private static final int GENERIC_COL_MIN_WIDTH = 30; @@ -102,32 +102,11 @@ public final class AutoIngestDashboard extends JPanel implements Observer { * Constructs a panel for monitoring an automated ingest cluster. */ private AutoIngestDashboard() { - pendingTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) { - private static final long serialVersionUID = 1L; + pendingTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0); - @Override - public boolean isCellEditable(int row, int column) { - return false; - } - }; + runningTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0); - runningTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) { - private static final long serialVersionUID = 1L; - - @Override - public boolean isCellEditable(int row, int column) { - return false; - } - }; - - completedTableModel = new DefaultTableModel(JobsTableModelColumns.headers, 0) { - private static final long serialVersionUID = 1L; - - @Override - public boolean isCellEditable(int row, int column) { - return false; - } - }; + completedTableModel = new AutoIngestTableModel(JobsTableModelColumns.headers, 0); initComponents(); setServicesStatusMessage(); @@ -250,10 +229,10 @@ public final class AutoIngestDashboard extends JPanel implements Observer { column.setMaxWidth(PRIORITY_COLUMN_MAX_WIDTH); column.setPreferredWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); column.setWidth(PRIORITY_COLUMN_PREFERRED_WIDTH); - /** + /* * Allow sorting when a column header is clicked. */ - pendingTable.setAutoCreateRowSorter(true); + pendingTable.setRowSorter(new AutoIngestRowSorter<>(pendingTableModel)); /* * Create a row selection listener to enable/disable the Prioritize @@ -412,11 +391,10 @@ public final class AutoIngestDashboard extends JPanel implements Observer { column.setMaxWidth(STATUS_COL_MAX_WIDTH); column.setPreferredWidth(STATUS_COL_PREFERRED_WIDTH); column.setWidth(STATUS_COL_PREFERRED_WIDTH); - /* * Allow sorting when a column header is clicked. */ - completedTable.setAutoCreateRowSorter(true); + completedTable.setRowSorter(new AutoIngestRowSorter<>(completedTableModel)); } /** @@ -550,7 +528,7 @@ public final class AutoIngestDashboard extends JPanel implements Observer { */ private enum JobsTableModelColumns { @Messages({"AutoIngestDashboard.JobsTableModel.ColumnHeader.Priority=Prioritized"}) - + 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")), @@ -898,4 +876,33 @@ public final class AutoIngestDashboard extends JPanel implements Observer { private javax.swing.JTextField tbServicesStatusMessage; // End of variables declaration//GEN-END:variables + private class AutoIngestTableModel extends DefaultTableModel { + + private static final long serialVersionUID = 1L; + + private AutoIngestTableModel(String[] headers, int i) { + super(headers, i); + } + + @Override + public boolean isCellEditable(int row, int column) { + return false; + } + + @Override + public Class getColumnClass(int columnIndex) { + if (columnIndex == JobsTableModelColumns.PRIORITY.ordinal()) { + return Integer.class; + } else if (columnIndex == JobsTableModelColumns.CREATED_TIME.ordinal() + || columnIndex == JobsTableModelColumns.COMPLETED_TIME.ordinal() + || columnIndex == JobsTableModelColumns.STARTED_TIME.ordinal() + || columnIndex == JobsTableModelColumns.STAGE_TIME.ordinal()) { + return Date.class; + } else if (columnIndex == JobsTableModelColumns.STATUS.ordinal()) { + return Boolean.class; + } else { + return super.getColumnClass(columnIndex); + } + } + } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java new file mode 100644 index 0000000000..c866b2d7f6 --- /dev/null +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java @@ -0,0 +1,56 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2017 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.experimental.autoingest; + +import java.util.ArrayList; +import java.util.Date; +import javax.swing.RowSorter; +import javax.swing.SortOrder; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableRowSorter; + +/** + * RowSorter which makes columns whose type is Date to be sorted first in + * Descending order then in Ascending order + */ +final class AutoIngestTableRowSorter extends TableRowSorter { + + AutoIngestTableRowSorter(M tModel) { + super(tModel); + } + + @Override + public void toggleSortOrder(int column) { + if (!this.getModel().getColumnClass(column).equals(Date.class)) { + super.toggleSortOrder(column); //if it isn't a date perform the regular sorting + } else { + ArrayList sortKeys = new ArrayList<>(getSortKeys()); + if (sortKeys.isEmpty() || sortKeys.get(0).getColumn() != column) { //sort descending + sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.DESCENDING)); + } else if (sortKeys.get(0).getSortOrder() == SortOrder.ASCENDING) { + sortKeys.removeIf(key -> key.getColumn() == column); + sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.DESCENDING)); + } else { + sortKeys.removeIf(key -> key.getColumn() == column); + sortKeys.add(0, new RowSorter.SortKey(column, SortOrder.ASCENDING)); + } + setSortKeys(sortKeys); + } + } +} From 8a759d26fe83a1f069b00f8cdc05d85ccd584cc6 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 25 Oct 2017 18:41:26 -0400 Subject: [PATCH 09/18] 3166 fix incorrect rename of some methods from AutoIngestRowSorter refactor --- .../autopsy/experimental/autoingest/AutoIngestCasePanel.java | 2 +- .../experimental/autoingest/AutoIngestControlPanel.java | 4 ++-- .../autopsy/experimental/autoingest/AutoIngestRowSorter.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java index 0a847dbd0e..1be3430910 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePanel.java @@ -150,7 +150,7 @@ public final class AutoIngestCasePanel extends JPanel { theColumn.setWidth(STATUS_COL_PREFERRED_WIDTH); casesTable.removeColumn(casesTable.getColumn(OUTPUT_FOLDER_HEADER)); - casesTable.setRowSorter(new AutoIngestTableRowSorter<>(caseTableModel)); + casesTable.setRowSorter(new AutoIngestRowSorter<>(caseTableModel)); /* * Listen for row selection changes and set button state for the current * selection. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index aa47fb3271..b299b89e01 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -403,7 +403,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { /** * Allow sorting when a column header is clicked. */ - pendingTable.setRowSorter(new AutoIngestTableRowSorter<>(pendingTableModel)); + pendingTable.setRowSorter(new AutoIngestRowSorter<>(pendingTableModel)); /* * Create a row selection listener to enable/disable the prioritize @@ -593,7 +593,7 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { /* * Allow sorting when a column header is clicked. */ - completedTable.setRowSorter(new AutoIngestTableRowSorter<>(completedTableModel)); + completedTable.setRowSorter(new AutoIngestRowSorter<>(completedTableModel)); /* * Create a row selection listener to enable/disable the delete case and diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java index c866b2d7f6..7334e31229 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestRowSorter.java @@ -29,9 +29,9 @@ import javax.swing.table.TableRowSorter; * RowSorter which makes columns whose type is Date to be sorted first in * Descending order then in Ascending order */ -final class AutoIngestTableRowSorter extends TableRowSorter { +class AutoIngestRowSorter extends TableRowSorter { - AutoIngestTableRowSorter(M tModel) { + AutoIngestRowSorter(M tModel) { super(tModel); } From 3c66cc242b3e417570f08499292e01ccb185c57f Mon Sep 17 00:00:00 2001 From: millmanorama Date: Thu, 26 Oct 2017 17:11:11 +0200 Subject: [PATCH 10/18] set initial sort to Priority and initialize toolbar from GroupManager --- .../autopsy/imagegallery/datamodel/grouping/GroupManager.java | 4 ++-- .../src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java index ae9e17bb4a..8a934cda98 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java @@ -122,7 +122,7 @@ public class GroupManager { /* * --- current grouping/sorting attributes --- */ - private volatile GroupSortBy sortBy = GroupSortBy.NONE; + private volatile GroupSortBy sortBy = GroupSortBy.PRIORITY; private volatile DrawableAttribute groupBy = DrawableAttribute.PATH; private volatile SortOrder sortOrder = SortOrder.ASCENDING; @@ -466,7 +466,7 @@ public class GroupManager { } } - public Comparator getSortBy() { + public GroupSortBy getSortBy() { return sortBy; } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java index 2dc85cbfd9..90c739287e 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java @@ -189,7 +189,7 @@ public class Toolbar extends ToolBar { }); sortChooser.sortOrderProperty().addListener(queryInvalidationListener); - sortChooser.setComparator(GroupSortBy.PRIORITY); + sortChooser.setComparator(controller.getGroupManager().getSortBy()); getItems().add(1, sortChooser); sortHelpImageView.setCursor(Cursor.HAND); From 13f16c417de559662561418861ab87863d315f2d Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 27 Oct 2017 13:44:28 -0400 Subject: [PATCH 11/18] 3153 - sort Priority column in descending order --- .../experimental/autoingest/AutoIngestControlPanel.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java index 26dcabff58..25b29e3665 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestControlPanel.java @@ -1862,8 +1862,8 @@ public final class AutoIngestControlPanel extends JPanel implements Observer { @Override public void toggleSortOrder(int column) { - if (!this.getModel().getColumnClass(column).equals(Date.class)) { - super.toggleSortOrder(column); //if it isn't a date perform the regular sorting + if (!this.getModel().getColumnClass(column).equals(Date.class) && !(this.getModel().getColumnName(column).equals(JobsTableModelColumns.PRIORITY.getColumnHeader()))) { + super.toggleSortOrder(column); //if it isn't a date or the Priority column perform the regular sorting } else { ArrayList sortKeys = new ArrayList<>(getSortKeys()); if (sortKeys.isEmpty() || sortKeys.get(0).getColumn() != column) { //sort descending From a19b32e3893278034f22b9cd1b925abc45a27e2e Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 1 Nov 2017 16:25:15 -0400 Subject: [PATCH 12/18] Rewrote portions of 'doRecoveryIfCrashed()' to fix bugs. --- .../autoingest/AutoIngestManager.java | 248 +++++------------- 1 file changed, 63 insertions(+), 185 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 9f43879b55..a779085813 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -37,7 +37,6 @@ import java.time.Duration; import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.EnumSet; @@ -59,13 +58,11 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.stream.Collectors; import javax.annotation.concurrent.GuardedBy; -import javax.annotation.concurrent.Immutable; -import javax.annotation.concurrent.ThreadSafe; -import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case.CaseType; import org.sleuthkit.autopsy.casemodule.CaseActionException; +import org.sleuthkit.autopsy.casemodule.CaseDetails; import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; @@ -101,7 +98,6 @@ import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobStartResult; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestModuleError; -import org.sleuthkit.datamodel.Content; /** * An auto ingest manager is responsible for processing auto ingest jobs defined @@ -503,7 +499,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang } SYS_LOGGER.log(Level.INFO, "Starting input scan of {0}", rootInputDirectory); InputDirScanner scanner = new InputDirScanner(); - scanner.scan(); SYS_LOGGER.log(Level.INFO, "Completed input scan of {0}", rootInputDirectory); } @@ -559,12 +554,10 @@ public final class AutoIngestManager extends Observable implements PropertyChang if (!prioritizedJobs.isEmpty()) { ++maxPriority; for (AutoIngestJob job : prioritizedJobs) { - int oldPriority = job.getPriority(); - job.setPriority(maxPriority); try { this.updateCoordinationServiceNode(job); + job.setPriority(maxPriority); } catch (CoordinationServiceException | InterruptedException ex) { - job.setPriority(oldPriority); throw new AutoIngestManagerException("Error updating case priority", ex); } } @@ -615,14 +608,12 @@ public final class AutoIngestManager extends Observable implements PropertyChang */ if (null != prioritizedJob) { ++maxPriority; - int oldPriority = prioritizedJob.getPriority(); - prioritizedJob.setPriority(maxPriority); try { this.updateCoordinationServiceNode(prioritizedJob); } catch (CoordinationServiceException | InterruptedException ex) { - prioritizedJob.setPriority(oldPriority); throw new AutoIngestManagerException("Error updating job priority", ex); } + prioritizedJob.setPriority(maxPriority); } Collections.sort(pendingJobs, new AutoIngestJob.PriorityComparator()); @@ -1051,8 +1042,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang if (null != manifest) { /* - * Update the mapping of case names to manifest paths that - * is used for case deletion. + * Update the mapping of case names to manifest paths that is + * used for case deletion. */ String caseName = manifest.getCaseName(); Path manifestPath = manifest.getFilePath(); @@ -1066,8 +1057,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang } /* - * Add a job to the pending jobs queue, the completed jobs - * list, or do crashed job recovery, as required. + * Add a job to the pending jobs queue, the completed jobs list, + * or do crashed job recovery, as required. */ try { byte[] rawData = coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()); @@ -1087,7 +1078,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang break; case DELETED: /* - * Ignore jobs marked as "deleted." + * Ignore jobs marked as "deleted." */ break; default: @@ -1247,48 +1238,38 @@ public final class AutoIngestManager extends Observable implements PropertyChang if (null != manifestLock) { SYS_LOGGER.log(Level.SEVERE, "Attempting crash recovery for {0}", manifestPath); try { + Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName()); + /* * Create the recovery job. */ AutoIngestJob job = new AutoIngestJob(nodeData); int numberOfCrashes = job.getNumberOfCrashes(); - ++numberOfCrashes; - job.setNumberOfCrashes(numberOfCrashes); - job.setCompletedDate(new Date(0)); - Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName()); + if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { + ++numberOfCrashes; + job.setNumberOfCrashes(numberOfCrashes); + if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { + job.setCompletedDate(new Date(0)); + } else { + job.setCompletedDate(Date.from(Instant.now())); + } + } + if (null != caseDirectoryPath) { job.setCaseDirectoryPath(caseDirectoryPath); job.setErrorsOccurred(true); - } else { - job.setErrorsOccurred(false); - } - - /* - * Update the coordination service node for the job. If - * this fails, leave the recovery to another host. - */ - try { - updateCoordinationServiceNode(job); - if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { - newPendingJobsList.add(job); - } else { - newCompletedJobsList.add(new AutoIngestJob(nodeData)); - } - } catch (CoordinationServiceException ex) { - SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifestPath), ex); - return; - } - - /* - * Write the alert file and do the logging. - */ - if (null != caseDirectoryPath) { try { - AutoIngestAlertFile.create(nodeData.getCaseDirectoryPath()); + /* + * Write the alert file and do the logging. + */ + AutoIngestAlertFile.create(caseDirectoryPath); } catch (AutoIngestAlertFileException ex) { SYS_LOGGER.log(Level.SEVERE, String.format("Error creating alert file for crashed job for %s", manifestPath), ex); } + } else { + job.setErrorsOccurred(false); } + if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { job.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING); if (null != caseDirectoryPath) { @@ -1302,13 +1283,32 @@ public final class AutoIngestManager extends Observable implements PropertyChang job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED); if (null != caseDirectoryPath) { try { - new AutoIngestJobLogger(manifest.getFilePath(), manifest.getDataSourceFileName(), nodeData.getCaseDirectoryPath()).logCrashRecoveryNoRetry(); + new AutoIngestJobLogger(manifest.getFilePath(), manifest.getDataSourceFileName(), caseDirectoryPath).logCrashRecoveryNoRetry(); } catch (AutoIngestJobLoggerException ex) { SYS_LOGGER.log(Level.SEVERE, String.format("Error creating case auto ingest log entry for crashed job for %s", manifestPath), ex); } } } + /* + * Update the coordination service node for the job. If + * this fails, leave the recovery to another host. + */ + try { + updateCoordinationServiceNode(job); + } catch (CoordinationServiceException ex) { + SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifestPath), ex); + return; + } + + nodeData = new AutoIngestJobNodeData(job); + + if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { + newPendingJobsList.add(job); + } else { + newCompletedJobsList.add(new AutoIngestJob(nodeData)); + } + } finally { try { manifestLock.release(); @@ -1459,7 +1459,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang */ private final class JobProcessingTask implements Runnable { - private static final String AUTO_INGEST_MODULE_OUTPUT_DIR = "AutoIngest"; private final Object ingestLock; private final Object pauseLock; @GuardedBy("pauseLock") @@ -2126,7 +2125,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang Case.openAsCurrentCase(metadataFilePath.toString()); } else { caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName); - Case.createAsCurrentCase(caseDirectoryPath.toString(), caseName, "", "", CaseType.MULTI_USER_CASE); + CaseDetails caseDetails = new CaseDetails(caseName, "", "", "", "", ""); + Case.createAsCurrentCase(CaseType.MULTI_USER_CASE, caseDirectoryPath.toString(), caseDetails); /* * Sleep a bit before releasing the lock to ensure * that the new case folder is visible on the @@ -2222,7 +2222,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang return; } - DataSource dataSource = identifyDataSource(caseForJob); + DataSource dataSource = identifyDataSource(); if (null == dataSource) { currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED, Date.from(Instant.now())); return; @@ -2275,7 +2275,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang * interrupted while blocked, i.e., * if auto ingest is shutting down. */ - private DataSource identifyDataSource(Case caseForJob) throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { + private DataSource identifyDataSource() throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { Manifest manifest = currentJob.getManifest(); Path manifestPath = manifest.getFilePath(); SYS_LOGGER.log(Level.INFO, "Identifying data source for {0} ", manifestPath); @@ -2294,7 +2294,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang String deviceId = manifest.getDeviceId(); return new DataSource(deviceId, dataSourcePath); } - + /** * Passes the data source for the current job through a data source * processor that adds it to the case database. @@ -2317,28 +2317,21 @@ public final class AutoIngestManager extends Observable implements PropertyChang SYS_LOGGER.log(Level.INFO, "Adding data source for {0} ", manifestPath); currentJob.setProcessingStage(AutoIngestJob.Stage.ADDING_DATA_SOURCE, Date.from(Instant.now())); UUID taskId = UUID.randomUUID(); - DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId); + DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId, ingestLock); DataSourceProcessorProgressMonitor progressMonitor = new DoNothingDSPProgressMonitor(); Path caseDirectoryPath = currentJob.getCaseDirectoryPath(); AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath); try { caseForJob.notifyAddingDataSource(taskId); - // lookup all AutomatedIngestDataSourceProcessors - Collection processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class); - - Map validDataSourceProcessorsMap = new HashMap<>(); - for (AutoIngestDataSourceProcessor processor : processorCandidates) { - try { - int confidence = processor.canProcess(dataSource.getPath()); - if (confidence > 0) { - validDataSourceProcessorsMap.put(processor, confidence); - } - } catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) { - SYS_LOGGER.log(Level.SEVERE, "Exception while determining whether data source processor {0} can process {1}", new Object[]{processor.getDataSourceType(), dataSource.getPath()}); - // rethrow the exception. It will get caught & handled upstream and will result in AIM auto-pause. - throw ex; - } + Map validDataSourceProcessorsMap; + try { + // lookup all AutomatedIngestDataSourceProcessors and poll which ones are able to process the current data source + validDataSourceProcessorsMap = DataSourceProcessorUtility.getDataSourceProcessor(dataSource.getPath()); + } catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) { + SYS_LOGGER.log(Level.SEVERE, "Exception while determining best data source processor for {0}", dataSource.getPath()); + // rethrow the exception. It will get caught & handled upstream and will result in AIM auto-pause. + throw ex; } // did we find a data source processor that can process the data source @@ -2595,80 +2588,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang jobLogger.logFileExportError(); } } - - /** - * A "callback" that collects the results of running a data source - * processor on a data source and unblocks the job processing thread - * when the data source processor finishes running in its own thread. - */ - @Immutable - class AddDataSourceCallback extends DataSourceProcessorCallback { - - private final Case caseForJob; - private final DataSource dataSourceInfo; - private final UUID taskId; - - /** - * Constructs a "callback" that collects the results of running a - * data source processor on a data source and unblocks the job - * processing thread when the data source processor finishes running - * in its own thread. - * - * @param caseForJob The case for the current job. - * @param dataSourceInfo The data source - * @param taskId The task id to associate with ingest job - * events. - */ - AddDataSourceCallback(Case caseForJob, DataSource dataSourceInfo, UUID taskId) { - this.caseForJob = caseForJob; - this.dataSourceInfo = dataSourceInfo; - this.taskId = taskId; - } - - /** - * Called by the data source processor when it finishes running in - * its own thread. - * - * @param result The result code for the processing of - * the data source. - * @param errorMessages Any error messages generated during the - * processing of the data source. - * @param dataSourceContent The content produced by processing the - * data source. - */ - @Override - public void done(DataSourceProcessorCallback.DataSourceProcessorResult result, List errorMessages, List dataSourceContent) { - if (!dataSourceContent.isEmpty()) { - caseForJob.notifyDataSourceAdded(dataSourceContent.get(0), taskId); - } else { - caseForJob.notifyFailedAddingDataSource(taskId); - } - dataSourceInfo.setDataSourceProcessorOutput(result, errorMessages, dataSourceContent); - dataSourceContent.addAll(dataSourceContent); - synchronized (ingestLock) { - ingestLock.notify(); - } - } - - /** - * Called by the data source processor when it finishes running in - * its own thread, if that thread is the AWT (Abstract Window - * Toolkit) event dispatch thread (EDT). - * - * @param result The result code for the processing of - * the data source. - * @param errorMessages Any error messages generated during the - * processing of the data source. - * @param dataSourceContent The content produced by processing the - * data source. - */ - @Override - public void doneEDT(DataSourceProcessorCallback.DataSourceProcessorResult result, List errorMessages, List dataSources) { - done(result, errorMessages, dataSources); - } - - } - + /** * A data source processor progress monitor does nothing. There is * currently no mechanism for showing or recording data source processor @@ -3008,49 +2928,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang PARTIALLY_DELETED, FULLY_DELETED } - - @ThreadSafe - private static final class DataSource { - - private final String deviceId; - private final Path path; - private DataSourceProcessorResult resultCode; - private List errorMessages; - private List content; - - DataSource(String deviceId, Path path) { - this.deviceId = deviceId; - this.path = path; - } - - String getDeviceId() { - return deviceId; - } - - Path getPath() { - return this.path; - } - - synchronized void setDataSourceProcessorOutput(DataSourceProcessorResult result, List errorMessages, List content) { - this.resultCode = result; - this.errorMessages = new ArrayList<>(errorMessages); - this.content = new ArrayList<>(content); - } - - synchronized DataSourceProcessorResult getResultDataSourceProcessorResultCode() { - return resultCode; - } - - synchronized List getDataSourceProcessorErrorMessages() { - return new ArrayList<>(errorMessages); - } - - synchronized List getContent() { - return new ArrayList<>(content); - } - - } - + static final class AutoIngestManagerException extends Exception { private static final long serialVersionUID = 1L; From 29c25d71e6cbd59a64831a6ee0997091b81261cd Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 1 Nov 2017 16:35:44 -0400 Subject: [PATCH 13/18] Minor revision --- .../autopsy/experimental/autoingest/AutoIngestManager.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index a779085813..cf41d00df2 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -62,7 +62,6 @@ import org.openide.util.Lookup; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case.CaseType; import org.sleuthkit.autopsy.casemodule.CaseActionException; -import org.sleuthkit.autopsy.casemodule.CaseDetails; import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; @@ -2125,8 +2124,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang Case.openAsCurrentCase(metadataFilePath.toString()); } else { caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName); - CaseDetails caseDetails = new CaseDetails(caseName, "", "", "", "", ""); - Case.createAsCurrentCase(CaseType.MULTI_USER_CASE, caseDirectoryPath.toString(), caseDetails); + Case.createAsCurrentCase(caseDirectoryPath.toString(), caseName, "", "", CaseType.MULTI_USER_CASE); /* * Sleep a bit before releasing the lock to ensure * that the new case folder is visible on the From d0e5f9d50b7c7f5c961e0611b93d38fdcce2deee Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 1 Nov 2017 16:40:55 -0400 Subject: [PATCH 14/18] Minor revision --- .../autoingest/AutoIngestManager.java | 177 +++++++++++++++--- 1 file changed, 155 insertions(+), 22 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index cf41d00df2..3f28487394 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -37,6 +37,7 @@ import java.time.Duration; import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.EnumSet; @@ -58,6 +59,9 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.stream.Collectors; import javax.annotation.concurrent.GuardedBy; +import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.ThreadSafe; +import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case.CaseType; @@ -97,6 +101,7 @@ import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobStartResult; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestModuleError; +import org.sleuthkit.datamodel.Content; /** * An auto ingest manager is responsible for processing auto ingest jobs defined @@ -498,6 +503,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang } SYS_LOGGER.log(Level.INFO, "Starting input scan of {0}", rootInputDirectory); InputDirScanner scanner = new InputDirScanner(); + scanner.scan(); SYS_LOGGER.log(Level.INFO, "Completed input scan of {0}", rootInputDirectory); } @@ -553,10 +559,12 @@ public final class AutoIngestManager extends Observable implements PropertyChang if (!prioritizedJobs.isEmpty()) { ++maxPriority; for (AutoIngestJob job : prioritizedJobs) { + int oldPriority = job.getPriority(); + job.setPriority(maxPriority); try { this.updateCoordinationServiceNode(job); - job.setPriority(maxPriority); } catch (CoordinationServiceException | InterruptedException ex) { + job.setPriority(oldPriority); throw new AutoIngestManagerException("Error updating case priority", ex); } } @@ -607,12 +615,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang */ if (null != prioritizedJob) { ++maxPriority; + int oldPriority = prioritizedJob.getPriority(); + prioritizedJob.setPriority(maxPriority); try { this.updateCoordinationServiceNode(prioritizedJob); } catch (CoordinationServiceException | InterruptedException ex) { + prioritizedJob.setPriority(oldPriority); throw new AutoIngestManagerException("Error updating job priority", ex); } - prioritizedJob.setPriority(maxPriority); } Collections.sort(pendingJobs, new AutoIngestJob.PriorityComparator()); @@ -1041,8 +1051,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang if (null != manifest) { /* - * Update the mapping of case names to manifest paths that is - * used for case deletion. + * Update the mapping of case names to manifest paths that + * is used for case deletion. */ String caseName = manifest.getCaseName(); Path manifestPath = manifest.getFilePath(); @@ -1056,8 +1066,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang } /* - * Add a job to the pending jobs queue, the completed jobs list, - * or do crashed job recovery, as required. + * Add a job to the pending jobs queue, the completed jobs + * list, or do crashed job recovery, as required. */ try { byte[] rawData = coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()); @@ -1077,7 +1087,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang break; case DELETED: /* - * Ignore jobs marked as "deleted." + * Ignore jobs marked as "deleted." */ break; default: @@ -1458,6 +1468,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang */ private final class JobProcessingTask implements Runnable { + private static final String AUTO_INGEST_MODULE_OUTPUT_DIR = "AutoIngest"; private final Object ingestLock; private final Object pauseLock; @GuardedBy("pauseLock") @@ -2220,7 +2231,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang return; } - DataSource dataSource = identifyDataSource(); + DataSource dataSource = identifyDataSource(caseForJob); if (null == dataSource) { currentJob.setProcessingStage(AutoIngestJob.Stage.COMPLETED, Date.from(Instant.now())); return; @@ -2273,7 +2284,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang * interrupted while blocked, i.e., * if auto ingest is shutting down. */ - private DataSource identifyDataSource() throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { + private DataSource identifyDataSource(Case caseForJob) throws AutoIngestAlertFileException, AutoIngestJobLoggerException, InterruptedException { Manifest manifest = currentJob.getManifest(); Path manifestPath = manifest.getFilePath(); SYS_LOGGER.log(Level.INFO, "Identifying data source for {0} ", manifestPath); @@ -2292,7 +2303,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang String deviceId = manifest.getDeviceId(); return new DataSource(deviceId, dataSourcePath); } - + /** * Passes the data source for the current job through a data source * processor that adds it to the case database. @@ -2315,21 +2326,28 @@ public final class AutoIngestManager extends Observable implements PropertyChang SYS_LOGGER.log(Level.INFO, "Adding data source for {0} ", manifestPath); currentJob.setProcessingStage(AutoIngestJob.Stage.ADDING_DATA_SOURCE, Date.from(Instant.now())); UUID taskId = UUID.randomUUID(); - DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId, ingestLock); + DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId); DataSourceProcessorProgressMonitor progressMonitor = new DoNothingDSPProgressMonitor(); Path caseDirectoryPath = currentJob.getCaseDirectoryPath(); AutoIngestJobLogger jobLogger = new AutoIngestJobLogger(manifestPath, manifest.getDataSourceFileName(), caseDirectoryPath); try { caseForJob.notifyAddingDataSource(taskId); - Map validDataSourceProcessorsMap; - try { - // lookup all AutomatedIngestDataSourceProcessors and poll which ones are able to process the current data source - validDataSourceProcessorsMap = DataSourceProcessorUtility.getDataSourceProcessor(dataSource.getPath()); - } catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) { - SYS_LOGGER.log(Level.SEVERE, "Exception while determining best data source processor for {0}", dataSource.getPath()); - // rethrow the exception. It will get caught & handled upstream and will result in AIM auto-pause. - throw ex; + // lookup all AutomatedIngestDataSourceProcessors + Collection processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class); + + Map validDataSourceProcessorsMap = new HashMap<>(); + for (AutoIngestDataSourceProcessor processor : processorCandidates) { + try { + int confidence = processor.canProcess(dataSource.getPath()); + if (confidence > 0) { + validDataSourceProcessorsMap.put(processor, confidence); + } + } catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) { + SYS_LOGGER.log(Level.SEVERE, "Exception while determining whether data source processor {0} can process {1}", new Object[]{processor.getDataSourceType(), dataSource.getPath()}); + // rethrow the exception. It will get caught & handled upstream and will result in AIM auto-pause. + throw ex; + } } // did we find a data source processor that can process the data source @@ -2586,7 +2604,80 @@ public final class AutoIngestManager extends Observable implements PropertyChang jobLogger.logFileExportError(); } } - + + /** + * A "callback" that collects the results of running a data source + * processor on a data source and unblocks the job processing thread + * when the data source processor finishes running in its own thread. + */ + @Immutable + class AddDataSourceCallback extends DataSourceProcessorCallback { + + private final Case caseForJob; + private final DataSource dataSourceInfo; + private final UUID taskId; + + /** + * Constructs a "callback" that collects the results of running a + * data source processor on a data source and unblocks the job + * processing thread when the data source processor finishes running + * in its own thread. + * + * @param caseForJob The case for the current job. + * @param dataSourceInfo The data source + * @param taskId The task id to associate with ingest job + * events. + */ + AddDataSourceCallback(Case caseForJob, DataSource dataSourceInfo, UUID taskId) { + this.caseForJob = caseForJob; + this.dataSourceInfo = dataSourceInfo; + this.taskId = taskId; + } + + /** + * Called by the data source processor when it finishes running in + * its own thread. + * + * @param result The result code for the processing of + * the data source. + * @param errorMessages Any error messages generated during the + * processing of the data source. + * @param dataSourceContent The content produced by processing the + * data source. + */ + @Override + public void done(DataSourceProcessorCallback.DataSourceProcessorResult result, List errorMessages, List dataSourceContent) { + if (!dataSourceContent.isEmpty()) { + caseForJob.notifyDataSourceAdded(dataSourceContent.get(0), taskId); + } else { + caseForJob.notifyFailedAddingDataSource(taskId); + } + dataSourceInfo.setDataSourceProcessorOutput(result, errorMessages, dataSourceContent); + dataSourceContent.addAll(dataSourceContent); + synchronized (ingestLock) { + ingestLock.notify(); + } + } + + /** + * Called by the data source processor when it finishes running in + * its own thread, if that thread is the AWT (Abstract Window + * Toolkit) event dispatch thread (EDT). + * + * @param result The result code for the processing of + * the data source. + * @param errorMessages Any error messages generated during the + * processing of the data source. + * @param dataSourceContent The content produced by processing the + * data source. + */ + @Override + public void doneEDT(DataSourceProcessorCallback.DataSourceProcessorResult result, List errorMessages, List dataSources) { + done(result, errorMessages, dataSources); + } + + } + /** * A data source processor progress monitor does nothing. There is * currently no mechanism for showing or recording data source processor @@ -2926,7 +3017,49 @@ public final class AutoIngestManager extends Observable implements PropertyChang PARTIALLY_DELETED, FULLY_DELETED } - + + @ThreadSafe + private static final class DataSource { + + private final String deviceId; + private final Path path; + private DataSourceProcessorResult resultCode; + private List errorMessages; + private List content; + + DataSource(String deviceId, Path path) { + this.deviceId = deviceId; + this.path = path; + } + + String getDeviceId() { + return deviceId; + } + + Path getPath() { + return this.path; + } + + synchronized void setDataSourceProcessorOutput(DataSourceProcessorResult result, List errorMessages, List content) { + this.resultCode = result; + this.errorMessages = new ArrayList<>(errorMessages); + this.content = new ArrayList<>(content); + } + + synchronized DataSourceProcessorResult getResultDataSourceProcessorResultCode() { + return resultCode; + } + + synchronized List getDataSourceProcessorErrorMessages() { + return new ArrayList<>(errorMessages); + } + + synchronized List getContent() { + return new ArrayList<>(content); + } + + } + static final class AutoIngestManagerException extends Exception { private static final long serialVersionUID = 1L; @@ -2941,4 +3074,4 @@ public final class AutoIngestManager extends Observable implements PropertyChang } -} +} \ No newline at end of file From 536056f415b018924a35114b03f1adc1989ccd2a Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 1 Nov 2017 16:49:49 -0400 Subject: [PATCH 15/18] Removed unused import and variable. --- .../autopsy/experimental/autoingest/AutoIngestManager.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 3f28487394..c169223396 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -61,7 +61,6 @@ import java.util.stream.Collectors; import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; -import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case.CaseType; @@ -122,7 +121,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang private static final int NUM_INPUT_SCAN_SCHEDULING_THREADS = 1; private static final String INPUT_SCAN_SCHEDULER_THREAD_NAME = "AIM-input-scan-scheduler-%d"; private static final String INPUT_SCAN_THREAD_NAME = "AIM-input-scan-%d"; - private static int DEFAULT_JOB_PRIORITY = 0; private static final String AUTO_INGEST_THREAD_NAME = "AIM-job-processing-%d"; private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName(); private static final String EVENT_CHANNEL_NAME = "Auto-Ingest-Manager-Events"; From 35ce34137239fff2c8eb97719b44c3e88f8c2208 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Wed, 8 Nov 2017 17:41:10 -0500 Subject: [PATCH 16/18] Workaround for JComponent.addPropertyChangeListener calls in ctor --- .../autopsy/ingest/IngestOptionsPanel.java | 32 +++++++++++++++++-- .../autopsy/ingest/ProfilePanel.java | 24 +++++++++++++- .../GlobalListSettingsPanel.java | 27 ++++++++++++++-- .../KeywordSearchGlobalSettingsPanel.java | 31 ++++++++++++++++-- 4 files changed, 105 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java index 1c761e8578..edd98b5034 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java @@ -140,9 +140,35 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen @Override public void addPropertyChangeListener(PropertyChangeListener l) { - filterPanel.addPropertyChangeListener(l); - settingsPanel.addPropertyChangeListener(l); - profilePanel.addPropertyChangeListener(l); + super.addPropertyChangeListener(l); + /* + * There is at least one look and feel library that follows the bad + * practice of calling overrideable methods in a constructor, e.g.: + * + * at + * javax.swing.plaf.synth.SynthPanelUI.installListeners(SynthPanelUI.java:83) + * at + * javax.swing.plaf.synth.SynthPanelUI.installUI(SynthPanelUI.java:63) + * at javax.swing.JComponent.setUI(JComponent.java:666) at + * javax.swing.JPanel.setUI(JPanel.java:153) at + * javax.swing.JPanel.updateUI(JPanel.java:126) at + * javax.swing.JPanel.(JPanel.java:86) at + * javax.swing.JPanel.(JPanel.java:109) at + * javax.swing.JPanel.(JPanel.java:117) + * + * When this happens, the following child components of this panel have + * not been constructed yet, since this panel's constructor has not been + * called yet. + */ + if (null != filterPanel) { + filterPanel.addPropertyChangeListener(l); + } + if (null != settingsPanel) { + settingsPanel.addPropertyChangeListener(l); + } + if (null != profilePanel) { + profilePanel.addPropertyChangeListener(l); + } } @Override diff --git a/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java b/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java index 3110947488..250435ae38 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java @@ -174,7 +174,29 @@ class ProfilePanel extends IngestModuleGlobalSettingsPanel { @Override public void addPropertyChangeListener(PropertyChangeListener l) { - ingestSettingsPanel.addPropertyChangeListener(l); + super.addPropertyChangeListener(l); + /* + * There is at least one look and feel library that follows the bad + * practice of calling overrideable methods in a constructor, e.g.: + * + * at + * javax.swing.plaf.synth.SynthPanelUI.installListeners(SynthPanelUI.java:83) + * at + * javax.swing.plaf.synth.SynthPanelUI.installUI(SynthPanelUI.java:63) + * at javax.swing.JComponent.setUI(JComponent.java:666) at + * javax.swing.JPanel.setUI(JPanel.java:153) at + * javax.swing.JPanel.updateUI(JPanel.java:126) at + * javax.swing.JPanel.(JPanel.java:86) at + * javax.swing.JPanel.(JPanel.java:109) at + * javax.swing.JPanel.(JPanel.java:117) + * + * When this happens, the following child components of this panel have + * not been constructed yet, since this panel's constructor has not been + * called yet. + */ + if (null != ingestSettingsPanel) { + ingestSettingsPanel.addPropertyChangeListener(l); + } } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JPanel jPanel1; diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java index e28cd75654..f5294db294 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java @@ -139,8 +139,31 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option @Override public void addPropertyChangeListener(PropertyChangeListener l) { super.addPropertyChangeListener(l); - listsManagementPanel.addPropertyChangeListener(l); - editListPanel.addPropertyChangeListener(l); + /* + * There is at least one look and feel library that follows the bad + * practice of calling overrideable methods in a constructor, e.g.: + * + * at + * javax.swing.plaf.synth.SynthPanelUI.installListeners(SynthPanelUI.java:83) + * at + * javax.swing.plaf.synth.SynthPanelUI.installUI(SynthPanelUI.java:63) + * at javax.swing.JComponent.setUI(JComponent.java:666) at + * javax.swing.JPanel.setUI(JPanel.java:153) at + * javax.swing.JPanel.updateUI(JPanel.java:126) at + * javax.swing.JPanel.(JPanel.java:86) at + * javax.swing.JPanel.(JPanel.java:109) at + * javax.swing.JPanel.(JPanel.java:117) + * + * When this happens, the following child components of this panel have + * not been constructed yet, since this panel's constructor has not been + * called yet. + */ + if (null != listsManagementPanel) { + listsManagementPanel.addPropertyChangeListener(l); + } + if (null != editListPanel) { + editListPanel.addPropertyChangeListener(l); + } } @Override diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java index 8e820b4c74..bd2dc11a43 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java @@ -52,9 +52,34 @@ final class KeywordSearchGlobalSettingsPanel extends IngestModuleGlobalSettingsP @Override public void addPropertyChangeListener(PropertyChangeListener l) { super.addPropertyChangeListener(l); - listsPanel.addPropertyChangeListener(l); - languagesPanel.addPropertyChangeListener(l); - generalPanel.addPropertyChangeListener(l); + /* + * There is at least one look and feel library that follows the bad + * practice of calling overrideable methods in a constructor, e.g.: + * + * at + * javax.swing.plaf.synth.SynthPanelUI.installListeners(SynthPanelUI.java:83) + * at + * javax.swing.plaf.synth.SynthPanelUI.installUI(SynthPanelUI.java:63) + * at javax.swing.JComponent.setUI(JComponent.java:666) at + * javax.swing.JPanel.setUI(JPanel.java:153) at + * javax.swing.JPanel.updateUI(JPanel.java:126) at + * javax.swing.JPanel.(JPanel.java:86) at + * javax.swing.JPanel.(JPanel.java:109) at + * javax.swing.JPanel.(JPanel.java:117) + * + * When this happens, the following child components of this panel have + * not been constructed yet, since this panel's constructor has not been + * called yet. + */ + if (null != listsPanel) { + listsPanel.addPropertyChangeListener(l); + } + if (null != languagesPanel) { + languagesPanel.addPropertyChangeListener(l); + } + if (null != generalPanel) { + generalPanel.addPropertyChangeListener(l); + } } @Override From b4d2cbd447de2759c94d588dee40b012827ec62f Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Wed, 8 Nov 2017 17:45:39 -0500 Subject: [PATCH 17/18] Update comment in some JPanel subclasses --- .../org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java | 6 +++--- Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java | 6 +++--- .../autopsy/keywordsearch/GlobalListSettingsPanel.java | 6 +++--- .../keywordsearch/KeywordSearchGlobalSettingsPanel.java | 6 +++--- .../core.jar/org/netbeans/core/startup/Bundle.properties | 4 ++-- .../org/netbeans/core/windows/view/ui/Bundle.properties | 6 +++--- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java index edd98b5034..40f3d1c298 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestOptionsPanel.java @@ -156,9 +156,9 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen * javax.swing.JPanel.(JPanel.java:109) at * javax.swing.JPanel.(JPanel.java:117) * - * When this happens, the following child components of this panel have - * not been constructed yet, since this panel's constructor has not been - * called yet. + * When this happens, the following child components of this JPanel + * subclass have not been constructed yet, since this panel's + * constructor has not been called yet. */ if (null != filterPanel) { filterPanel.addPropertyChangeListener(l); diff --git a/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java b/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java index 250435ae38..75588d5ab1 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/ProfilePanel.java @@ -190,9 +190,9 @@ class ProfilePanel extends IngestModuleGlobalSettingsPanel { * javax.swing.JPanel.(JPanel.java:109) at * javax.swing.JPanel.(JPanel.java:117) * - * When this happens, the following child components of this panel have - * not been constructed yet, since this panel's constructor has not been - * called yet. + * When this happens, the following child components of this JPanel + * subclass have not been constructed yet, since this panel's + * constructor has not been called yet. */ if (null != ingestSettingsPanel) { ingestSettingsPanel.addPropertyChangeListener(l); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java index f5294db294..862635ad4a 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/GlobalListSettingsPanel.java @@ -154,9 +154,9 @@ final class GlobalListSettingsPanel extends javax.swing.JPanel implements Option * javax.swing.JPanel.(JPanel.java:109) at * javax.swing.JPanel.(JPanel.java:117) * - * When this happens, the following child components of this panel have - * not been constructed yet, since this panel's constructor has not been - * called yet. + * When this happens, the following child components of this JPanel + * subclass have not been constructed yet, since this panel's + * constructor has not been called yet. */ if (null != listsManagementPanel) { listsManagementPanel.addPropertyChangeListener(l); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java index bd2dc11a43..c34e672a1c 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchGlobalSettingsPanel.java @@ -67,9 +67,9 @@ final class KeywordSearchGlobalSettingsPanel extends IngestModuleGlobalSettingsP * javax.swing.JPanel.(JPanel.java:109) at * javax.swing.JPanel.(JPanel.java:117) * - * When this happens, the following child components of this panel have - * not been constructed yet, since this panel's constructor has not been - * called yet. + * When this happens, the following child components of this JPanel + * subclass have not been constructed yet, since this panel's + * constructor has not been called yet. */ if (null != listsPanel) { listsPanel.addPropertyChangeListener(l); diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index 2922cd2054..0de39782ca 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Thu, 07 Sep 2017 13:53:53 -0400 +#Wed, 08 Nov 2017 17:45:11 -0500 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.2 +currentVersion=Autopsy 4.5.0 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 2ac51b0cbd..fa55dddb62 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,4 +1,4 @@ #Updated by build script -#Thu, 07 Sep 2017 13:53:53 -0400 -CTL_MainWindow_Title=Autopsy 4.4.2 -CTL_MainWindow_Title_No_Project=Autopsy 4.4.2 +#Wed, 08 Nov 2017 17:45:11 -0500 +CTL_MainWindow_Title=Autopsy 4.5.0 +CTL_MainWindow_Title_No_Project=Autopsy 4.5.0 From e1770f5fdfefb9c8549230cef48010c3a7363bfb Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Thu, 9 Nov 2017 16:53:29 -0500 Subject: [PATCH 18/18] 3198 change storage of knownStatus for TagNameDefinition from String to enum --- .../casemodule/services/TagNameDefiniton.java | 22 +++++++++---------- .../casemodule/services/TagOptionsPanel.java | 3 ++- .../casemodule/services/TagsManager.java | 11 +++++----- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java index 171d673cb6..e4987fb207 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java @@ -27,6 +27,7 @@ import java.util.Set; import javax.annotation.concurrent.Immutable; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.datamodel.TagName; +import org.sleuthkit.datamodel.TskData; /** * A tag name definition consisting of a display name, description and color. @@ -36,13 +37,12 @@ final class TagNameDefiniton implements Comparable { private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS - private static final String DEFAULT_BAD_TAGS = "Evidence,Notable Item," + private static final String STANDARD_NOTABLE_TAG_DISPLAY_NAMES = "Evidence,Notable Item," + "CAT-1: Child Exploitation (Illegal),CAT-2: Child Exploitation (Non-Illegal/Age Difficult),CAT-3: Child Exploitive"; // NON-NLS - static final String NOTABLE = "(Notable)"; private final String displayName; private final String description; private final TagName.HTML_COLOR color; - private final String knownStatusDenoted; + private final TskData.FileKnown knownStatusDenoted; /** * Constructs a tag name definition consisting of a display name, @@ -52,11 +52,11 @@ final class TagNameDefiniton implements Comparable { * @param description The description for the tag name. * @param color The color for the tag name. */ - TagNameDefiniton(String displayName, String description, TagName.HTML_COLOR color, String notable) { + TagNameDefiniton(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown status) { this.displayName = displayName; this.description = description; this.color = color; - this.knownStatusDenoted = notable; + this.knownStatusDenoted = status; } /** @@ -90,7 +90,7 @@ final class TagNameDefiniton implements Comparable { * */ boolean isNotable(){ - return knownStatusDenoted.equals(NOTABLE); + return knownStatusDenoted == TskData.FileKnown.BAD; } /** * Compares this tag name definition with the specified tag name definition @@ -152,7 +152,7 @@ final class TagNameDefiniton implements Comparable { * that is used by the tags settings file. */ private String toSettingsFormat() { - return displayName + "," + description + "," + color.name() + "," + knownStatusDenoted; + return displayName + "," + description + "," + color.name() + "," + knownStatusDenoted.toString(); } /** @@ -172,7 +172,7 @@ final class TagNameDefiniton implements Comparable { if (badTags == null) { String badTagsStr = ModuleSettings.getConfigSetting("CentralRepository", "db.badTags"); // NON-NLS if (badTagsStr == null) { - badTagsStr = DEFAULT_BAD_TAGS; + badTagsStr = STANDARD_NOTABLE_TAG_DISPLAY_NAMES; } if (badTagsStr.isEmpty()) { badTags = new ArrayList<>(); @@ -181,12 +181,12 @@ final class TagNameDefiniton implements Comparable { } } if (badTags.contains(tagNameAttributes[0])) { - tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), NOTABLE)); + tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.BAD)); } else { - tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), "")); //add the default value for that tag + tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.UNKNOWN)); //add the default value for that tag } } else if (tagNameAttributes.length == 4) { - tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), tagNameAttributes[3])); + tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.valueOf(tagNameAttributes[3]))); } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java index 8fc6a5ff4d..681cc95472 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java @@ -27,6 +27,7 @@ import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.datamodel.TagName; +import org.sleuthkit.datamodel.TskData; /** * A panel to allow the user to create and delete custom tag types. @@ -190,7 +191,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { NewTagNameDialog.BUTTON_PRESSED result = dialog.getResult(); if (result == NewTagNameDialog.BUTTON_PRESSED.OK) { String newTagDisplayName = dialog.getTagName(); - TagNameDefiniton newTagType = new TagNameDefiniton(newTagDisplayName, DEFAULT_DESCRIPTION, DEFAULT_COLOR, ""); + TagNameDefiniton newTagType = new TagNameDefiniton(newTagDisplayName, DEFAULT_DESCRIPTION, DEFAULT_COLOR, TskData.FileKnown.UNKNOWN); /* * If tag name already exists, don't add the tag name. */ diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index f66b195073..8c87475785 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -38,6 +38,7 @@ import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; /** * A per case Autopsy service that manages the addition of content and artifact @@ -198,7 +199,7 @@ public class TagsManager implements Closeable { * name to the case database. */ public synchronized TagName addTagName(String displayName) throws TagNameAlreadyExistsException, TskCoreException { - return addTagName(displayName, "", TagName.HTML_COLOR.NONE, ""); + return addTagName(displayName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN); } /** @@ -217,7 +218,7 @@ public class TagsManager implements Closeable { * name to the case database. */ public synchronized TagName addTagName(String displayName, String description) throws TagNameAlreadyExistsException, TskCoreException { - return addTagName(displayName, description, TagName.HTML_COLOR.NONE, ""); + return addTagName(displayName, description, TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN); } /** @@ -236,9 +237,9 @@ public class TagsManager implements Closeable { * name to the case database. */ public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color) throws TagNameAlreadyExistsException, TskCoreException { - String knownStatus = ""; + TskData.FileKnown knownStatus = TskData.FileKnown.UNKNOWN; if (getNotableTagDisplayNames().contains(displayName)) { - knownStatus = TagNameDefiniton.NOTABLE; + knownStatus = TskData.FileKnown.BAD; } return addTagName(displayName, description, color, knownStatus); } @@ -260,7 +261,7 @@ public class TagsManager implements Closeable { * @throws TskCoreException If there is an error adding the tag * name to the case database. */ - public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color, String knownStatus) throws TagNameAlreadyExistsException, TskCoreException { + public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus) throws TagNameAlreadyExistsException, TskCoreException { try { TagName tagName = caseDb.addTagName(displayName, description, color); if (!STANDARD_TAG_DISPLAY_NAMES.contains(displayName)) {