diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index ab2b5c12dc..2d87cd9a06 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -229,5 +229,5 @@ CueBannerPanel.openCaseButton.text= CueBannerPanel.openCaseLabel.text=Open Case MultiUserCasesPanel.bnOpenSingleUserCase.text=Open Single-User Case... CueBannerPanel.newCaseButton.text= -MultiUserCasesPanel.searchLabel.text=Start typing to search by case name +MultiUserCasesPanel.searchLabel.text=Select any case and start typing to search by case name MultiUserCasesPanel.cancelButton.text=Cancel diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java index 9440ca1356..24aaf70d2e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseBrowser.java @@ -18,11 +18,9 @@ */ package org.sleuthkit.autopsy.casemodule; -import java.awt.Component; import java.lang.reflect.InvocationTargetException; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionListener; -import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumnModel; import org.netbeans.swing.etable.ETableColumn; import org.netbeans.swing.etable.ETableColumnModel; @@ -33,14 +31,12 @@ import java.awt.EventQueue; import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.logging.Level; import javax.swing.SwingWorker; import org.openide.explorer.ExplorerManager; import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.coordinationservice.CaseNodeData; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.EmptyNode; @@ -61,7 +57,7 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider private final org.openide.explorer.view.OutlineView outlineView; private int originalPathColumnIndex = 0; private static final Logger LOGGER = Logger.getLogger(CaseBrowser.class.getName()); - private LoadCaseMapWorker tableWorker; + private LoadCaseListWorker tableWorker; @Override public ExplorerManager getExplorerManager() { @@ -78,7 +74,6 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider outline = outlineView.getOutline(); outlineView.setPropertyColumns( Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), - Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath()); ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.CaseNode_column_name()); customize(); @@ -100,7 +95,7 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider dateColumnIndex = index; } } - //Hide path column by default will need to + //Hide path column by default (user can unhide it) ETableColumn column = (ETableColumn) columnModel.getColumn(originalPathColumnIndex); ((ETableColumnModel) columnModel).setColumnHidden(column, true); outline.setRootVisible(false); @@ -124,6 +119,11 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider outline.getSelectionModel().addListSelectionListener(listener); } + /** + * Get the path to the .aut file for the selected case. + * + * @return the full path to the selected case's .aut file + */ String getCasePath() { int[] selectedRows = outline.getSelectedRows(); if (selectedRows.length == 1) { @@ -157,7 +157,7 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider //set the table to display text informing the user that the list is being retreived and disable case selection EmptyNode emptyNode = new EmptyNode(Bundle.CaseBrowser_caseListLoading_message()); em.setRootContext(emptyNode); - tableWorker = new LoadCaseMapWorker(); + tableWorker = new LoadCaseListWorker(); tableWorker.execute(); } @@ -189,13 +189,11 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider // End of variables declaration//GEN-END:variables /** - * Swingworker to fetch the updated map of cases and their status in a - * background thread + * Swingworker to fetch the updated List of cases in a background thread */ - private class LoadCaseMapWorker extends SwingWorker { + private class LoadCaseListWorker extends SwingWorker { - private static final String ALERT_FILE_NAME = "autoingest.alert"; - private Map cases; + private List cases; /** * Gets a list of the cases in the top level case folder @@ -204,8 +202,8 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider * * @throws CoordinationServiceException */ - private Map getCases() throws CoordinationService.CoordinationServiceException { - Map casesMap = new HashMap<>(); + private List getCases() throws CoordinationService.CoordinationServiceException { + List caseList = new ArrayList<>(); List nodeList = CoordinationService.getInstance().getNodeList(CoordinationService.CategoryNode.CASES); for (String node : nodeList) { @@ -213,64 +211,27 @@ class CaseBrowser extends javax.swing.JPanel implements ExplorerManager.Provider File caseFolder = casePath.toFile(); if (caseFolder.exists()) { /* - * Search for '*.aut' and 'autoingest.alert' files. + * Search for '*.aut' files. */ File[] fileArray = caseFolder.listFiles(); if (fileArray == null) { continue; } String autFilePath = null; - boolean alertFileFound = false; for (File file : fileArray) { String name = file.getName().toLowerCase(); if (autFilePath == null && name.endsWith(".aut")) { - autFilePath = file.getAbsolutePath(); - if (!alertFileFound) { - continue; + try { + caseList.add(new CaseMetadata(Paths.get(file.getAbsolutePath()))); + } catch (CaseMetadata.CaseMetadataException ex) { + LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex); } - } - if (!alertFileFound && name.endsWith(ALERT_FILE_NAME)) { - alertFileFound = true; - } - if (autFilePath != null && alertFileFound) { break; } } - - if (autFilePath != null) { - try { - boolean hasAlertStatus = false; - if (alertFileFound) { - /* - * When an alert file exists, ignore the node - * data and use the ALERT status. - */ - hasAlertStatus = true; - } else { - byte[] rawData = CoordinationService.getInstance().getNodeData(CoordinationService.CategoryNode.CASES, node); - if (rawData != null && rawData.length > 0) { - /* - * When node data exists, use the status - * stored in the node data. - */ - CaseNodeData caseNodeData = new CaseNodeData(rawData); - if (caseNodeData.getErrorsOccurred()) { - hasAlertStatus = true; - } - } - } - - CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFilePath)); - casesMap.put(caseMetadata, hasAlertStatus); - } catch (CaseMetadata.CaseMetadataException ex) { - LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex); - } catch (InterruptedException | CaseNodeData.InvalidDataException ex) { - LOGGER.log(Level.SEVERE, String.format("Error reading case node data for '%s'.", node), ex); - } - } } } - return casesMap; + return caseList; } @Override diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form index 3f897d70c0..beb38e312e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.form @@ -27,13 +27,13 @@ - - - - + + + + - + @@ -52,7 +52,7 @@ - + @@ -64,6 +64,15 @@ + + + + + + + + + @@ -74,6 +83,12 @@ + + + + + + @@ -84,6 +99,15 @@ + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java index a2a2ec13ad..a5a1f32879 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserCasesPanel.java @@ -165,6 +165,9 @@ final class MultiUserCasesPanel extends JPanel{ org.openide.awt.Mnemonics.setLocalizedText(bnOpen, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnOpen.text")); // NOI18N bnOpen.setEnabled(false); + bnOpen.setMaximumSize(new java.awt.Dimension(80, 23)); + bnOpen.setMinimumSize(new java.awt.Dimension(80, 23)); + bnOpen.setPreferredSize(new java.awt.Dimension(80, 23)); bnOpen.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnOpenActionPerformed(evt); @@ -172,6 +175,8 @@ final class MultiUserCasesPanel extends JPanel{ }); org.openide.awt.Mnemonics.setLocalizedText(bnOpenSingleUserCase, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.bnOpenSingleUserCase.text")); // NOI18N + bnOpenSingleUserCase.setMinimumSize(new java.awt.Dimension(156, 23)); + bnOpenSingleUserCase.setPreferredSize(new java.awt.Dimension(156, 23)); bnOpenSingleUserCase.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnOpenSingleUserCaseActionPerformed(evt); @@ -179,6 +184,9 @@ final class MultiUserCasesPanel extends JPanel{ }); org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(MultiUserCasesPanel.class, "MultiUserCasesPanel.cancelButton.text")); // NOI18N + cancelButton.setMaximumSize(new java.awt.Dimension(80, 23)); + cancelButton.setMinimumSize(new java.awt.Dimension(80, 23)); + cancelButton.setPreferredSize(new java.awt.Dimension(80, 23)); cancelButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { cancelButtonActionPerformed(evt); @@ -196,15 +204,18 @@ final class MultiUserCasesPanel extends JPanel{ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(caseExplorerScrollPane) .addGroup(layout.createSequentialGroup() - .addComponent(searchLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 555, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 175, Short.MAX_VALUE) - .addComponent(bnOpen, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(searchLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 120, Short.MAX_VALUE) + .addComponent(bnOpenSingleUserCase, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(226, 226, 226) + .addComponent(bnOpen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(bnOpenSingleUserCase) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cancelButton))) + .addComponent(cancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) .addContainerGap()) ); + + layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {bnOpen, cancelButton}); + layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() @@ -212,11 +223,11 @@ final class MultiUserCasesPanel extends JPanel{ .addComponent(caseExplorerScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 450, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cancelButton) - .addComponent(bnOpen) - .addComponent(bnOpenSingleUserCase) + .addComponent(cancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(bnOpen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(bnOpenSingleUserCase, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(searchLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) ); }// //GEN-END:initComponents diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java index 9443ae35e9..fa125e6a32 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java @@ -25,8 +25,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.Action; @@ -49,7 +47,6 @@ final class MultiUserNode extends AbstractNode { @Messages({"CaseNode.column.name=Name", "CaseNode.column.createdTime=Created Time", - "CaseNode.column.status=Status", "CaseNode.column.metadataFilePath=Path"}) private static final Logger LOGGER = Logger.getLogger(MultiUserNode.class.getName()); private static final String LOG_FILE_NAME = "auto_ingest_log.txt"; @@ -57,31 +54,30 @@ final class MultiUserNode extends AbstractNode { /** * Provides a root node with children which each represent a case. * - * @param caseMap the map of cases and a boolean indicating if they have an - * alert + * @param caseList the list of CaseMetadata objects representing the cases */ - MultiUserNode(Map caseMap) { - super(Children.create(new MultiUserNodeChildren(caseMap), true)); + MultiUserNode(List caseList) { + super(Children.create(new MultiUserNodeChildren(caseList), true)); } - static class MultiUserNodeChildren extends ChildFactory> { + static class MultiUserNodeChildren extends ChildFactory { - private final Map caseMap; + private final List caseList; - MultiUserNodeChildren(Map caseMap) { - this.caseMap = caseMap; + MultiUserNodeChildren(List caseList) { + this.caseList = caseList; } @Override - protected boolean createKeys(List> list) { - if (caseMap != null && caseMap.size() > 0) { - list.addAll(caseMap.entrySet()); + protected boolean createKeys(List list) { + if (caseList != null && caseList.size() > 0) { + list.addAll(caseList); } return true; } @Override - protected Node createNodeForKey(Entry key) { + protected Node createNodeForKey(CaseMetadata key) { return new MultiUserCaseNode(key); } @@ -95,19 +91,17 @@ final class MultiUserNode extends AbstractNode { private final String caseName; private final String caseCreatedDate; private final String caseMetadataFilePath; - private final boolean caseHasAlert; private final Path caseLogFilePath; - MultiUserCaseNode(Entry multiUserCase) { + MultiUserCaseNode(CaseMetadata multiUserCase) { super(Children.LEAF); - caseName = multiUserCase.getKey().getCaseDisplayName(); - caseCreatedDate = multiUserCase.getKey().getCreatedDate(); - caseHasAlert = multiUserCase.getValue(); + caseName = multiUserCase.getCaseDisplayName(); + caseCreatedDate = multiUserCase.getCreatedDate(); super.setName(caseName); setName(caseName); setDisplayName(caseName); - caseMetadataFilePath = multiUserCase.getKey().getFilePath().toString(); - caseLogFilePath = Paths.get(multiUserCase.getKey().getCaseDirectory(), LOG_FILE_NAME); + caseMetadataFilePath = multiUserCase.getFilePath().toString(); + caseLogFilePath = Paths.get(multiUserCase.getCaseDirectory(), LOG_FILE_NAME); } /** @@ -119,7 +113,6 @@ final class MultiUserNode extends AbstractNode { return new OpenMultiUserCaseAction(caseMetadataFilePath); } - @Messages({"MultiUserNode.AlertColumn.text=Alert"}) //text to display when there is an alert present @Override protected Sheet createSheet() { Sheet s = super.createSheet(); @@ -132,8 +125,6 @@ final class MultiUserNode extends AbstractNode { caseName)); ss.put(new NodeProperty<>(Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), caseCreatedDate)); - ss.put(new NodeProperty<>(Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), - (caseHasAlert == true ? Bundle.MultiUserNode_AlertColumn_text() : ""))); ss.put(new NodeProperty<>(Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), caseMetadataFilePath)); return s;