3408 clean up and bug fixes for MultiUserCasePanel

This commit is contained in:
William Schaefer 2018-01-09 18:50:11 -05:00
parent 978f37620b
commit b2915ef4f8
3 changed files with 96 additions and 98 deletions

View File

@ -23,11 +23,13 @@ import java.lang.reflect.InvocationTargetException;
import javax.swing.ListSelectionModel; import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableCellRenderer; import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel;
import org.netbeans.swing.etable.ETableColumn;
import org.netbeans.swing.etable.ETableColumnModel;
import org.netbeans.swing.outline.DefaultOutlineModel; import org.netbeans.swing.outline.DefaultOutlineModel;
import org.netbeans.swing.outline.Outline; import org.netbeans.swing.outline.Outline;
import org.openide.explorer.ExplorerManager; import org.openide.explorer.ExplorerManager;
import org.sleuthkit.autopsy.datamodel.NodeProperty; import org.openide.nodes.Node;
/** /**
* A Swing JPanel with a JTabbedPane child component. The tabbed pane contains * A Swing JPanel with a JTabbedPane child component. The tabbed pane contains
@ -56,10 +58,10 @@ class CaseBrowser extends javax.swing.JPanel {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private Outline outline; private final Outline outline;
private ExplorerManager em; private ExplorerManager em;
private org.openide.explorer.view.OutlineView outlineView; private final org.openide.explorer.view.OutlineView outlineView;
private int originalPathColumnIndex = 0;
/** /**
* Creates new form CaseBrowser * Creates new form CaseBrowser
*/ */
@ -71,13 +73,28 @@ class CaseBrowser extends javax.swing.JPanel {
outlineView.setPropertyColumns( outlineView.setPropertyColumns(
Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(),
Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(),
Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath() Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath());
); customize();
}
private void customize() {
TableColumnModel columnModel = outline.getColumnModel();
int dateColumnIndex = 0;
for (int index = 0; index < columnModel.getColumnCount(); index++) { //get indexes for hidden column and default sorting column
if (columnModel.getColumn(index).getHeaderValue().toString().equals(Bundle.CaseNode_column_metadataFilePath())) {
originalPathColumnIndex = index;
} else if (columnModel.getColumn(index).getHeaderValue().toString().equals(Bundle.CaseNode_column_createdTime())) {
dateColumnIndex = index;
}
}
ETableColumn column = (ETableColumn) columnModel.getColumn(originalPathColumnIndex);
((ETableColumnModel) columnModel).setColumnHidden(column, true);
outline.setRootVisible(false); outline.setRootVisible(false);
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.CaseNode_column_name()); ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.CaseNode_column_name());
outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
outline.setColumnSorted(1, false, 1); //it would be nice if the column index wasn't hardcoded outline.setColumnSorted(dateColumnIndex, false, 1); //it would be nice if the column index wasn't hardcoded
} }
/** /**
@ -102,37 +119,28 @@ class CaseBrowser extends javax.swing.JPanel {
this.setVisible(true); this.setVisible(true);
} }
public void addListSelectionListener(ListSelectionListener listener) { void setRowSelectionAllowed(boolean allowed) {
outline.setRowSelectionAllowed(allowed);
}
void addListSelectionListener(ListSelectionListener listener) {
outline.getSelectionModel().addListSelectionListener(listener); outline.getSelectionModel().addListSelectionListener(listener);
} }
String getCasePath() { String getCasePath() {
int[] selectedRows = outline.getSelectedRows(); int[] selectedRows = outline.getSelectedRows();
System.out.println("Explored Context: " + em.getExploredContext());
System.out.println("EM ROOT NODe: " + em.getRootContext().getDisplayName());
if (selectedRows.length == 1) { if (selectedRows.length == 1) {
System.out.println("Selected Row: " + selectedRows[0]);
for (int colIndex = 0; colIndex < outline.getColumnCount(); colIndex++) {
TableColumn col = outline.getColumnModel().getColumn(colIndex);
System.out.println("COL: " + col.getHeaderValue().toString());
if (col.getHeaderValue().toString().equals(Bundle.CaseNode_column_metadataFilePath())) {
try { try {
return ((NodeProperty)outline.getValueAt(selectedRows[0], colIndex)).getValue().toString(); return ((Node.Property) outline.getModel().getValueAt(outline.convertRowIndexToModel(selectedRows[0]), originalPathColumnIndex)).getValue().toString();
} catch (IllegalAccessException ex) { } catch (IllegalAccessException | InvocationTargetException ex) {
System.out.println("THROW");
} catch (InvocationTargetException ex) {
} }
} }
}
}
return null; return null;
} }
boolean isRowSelected() { boolean isRowSelected() {
System.out.println("SELECTED ROWS: " + outline.getSelectedRows().length); return outline.getRowSelectionAllowed() && outline.getSelectedRows().length > 0;
return outline.getSelectedRows().length > 0;
} }
private void setColumnWidths() { private void setColumnWidths() {
@ -141,8 +149,8 @@ class CaseBrowser extends javax.swing.JPanel {
final int rows = Math.min(100, outline.getRowCount()); final int rows = Math.min(100, outline.getRowCount());
for (int column = 0; column < outline.getModel().getColumnCount(); column++) { for (int column = 0; column < outline.getColumnModel().getColumnCount(); column++) {
int columnWidthLimit = 500; int columnWidthLimit = 800;
int columnWidth = 0; int columnWidth = 0;
// find the maximum width needed to fit the values for the first 100 rows, at most // find the maximum width needed to fit the values for the first 100 rows, at most

View File

@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -38,6 +37,7 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
import org.sleuthkit.autopsy.datamodel.NodeProperty; import org.sleuthkit.autopsy.datamodel.NodeProperty;
/** /**
* Provides a root node for the results views with a single child node that * Provides a root node for the results views with a single child node that
* displays a message as the sole item in its property sheet, useful for * displays a message as the sole item in its property sheet, useful for
@ -66,18 +66,17 @@ public final class CaseNode extends AbstractNode {
static class CaseNodeChildren extends ChildFactory<Entry<CaseMetadata, Boolean>> { static class CaseNodeChildren extends ChildFactory<Entry<CaseMetadata, Boolean>> {
Map<CaseMetadata, Boolean> caseList; private final Map<CaseMetadata, Boolean> caseMap;
public CaseNodeChildren(Map<CaseMetadata, Boolean> caseList) { CaseNodeChildren(Map<CaseMetadata, Boolean> caseMap) {
this.caseList = caseList; this.caseMap = caseMap;
} }
@Override @Override
protected boolean createKeys(List<Entry<CaseMetadata, Boolean>> list) { protected boolean createKeys(List<Entry<CaseMetadata, Boolean>> list) {
if (caseList != null && caseList.size() > 0) { if (caseMap != null && caseMap.size() > 0) {
list.addAll(caseList.entrySet()); list.addAll(caseMap.entrySet());
} }
System.out.println("NUM OF KEYS: " + list.size());
return true; return true;
} }
@ -94,18 +93,20 @@ public final class CaseNode extends AbstractNode {
*/ */
public static final class CaseNameNode extends DisplayableItemNode { public static final class CaseNameNode extends DisplayableItemNode {
CaseMetadata multiUserCase; private final String caseName;
String caseMetadataFilePath; private final String caseCreatedDate;
boolean caseHasAlert; private final String caseMetadataFilePath;
private final boolean caseHasAlert;
CaseNameNode(Entry<CaseMetadata, Boolean> userCase) { CaseNameNode(Entry<CaseMetadata, Boolean> userCase) {
super(Children.LEAF); super(Children.LEAF);
multiUserCase = userCase.getKey(); caseName = userCase.getKey().getCaseDisplayName();
caseCreatedDate = userCase.getKey().getCreatedDate();
caseHasAlert = userCase.getValue(); caseHasAlert = userCase.getValue();
super.setName(multiUserCase.getCaseDisplayName()); super.setName(caseName);
setName(multiUserCase.getCaseDisplayName()); setName(caseName);
setDisplayName(multiUserCase.getCaseDisplayName()); setDisplayName(caseName);
caseMetadataFilePath = multiUserCase.getFilePath().toString(); caseMetadataFilePath = userCase.getKey().getFilePath().toString();
} }
@Override @Override
@ -136,9 +137,9 @@ public final class CaseNode extends AbstractNode {
s.put(ss); s.put(ss);
} }
ss.put(new NodeProperty<>(Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(), ss.put(new NodeProperty<>(Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(),
multiUserCase.getCaseDisplayName())); caseName));
ss.put(new NodeProperty<>(Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), ss.put(new NodeProperty<>(Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(),
multiUserCase.getCreatedDate())); caseCreatedDate));
ss.put(new NodeProperty<>(Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), ss.put(new NodeProperty<>(Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(), Bundle.CaseNode_column_status(),
(caseHasAlert == true ? "Alert" : ""))); (caseHasAlert == true ? "Alert" : "")));
ss.put(new NodeProperty<>(Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), ss.put(new NodeProperty<>(Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(),
@ -150,7 +151,7 @@ public final class CaseNode extends AbstractNode {
public Action[] getActions(boolean context) { public Action[] getActions(boolean context) {
List<Action> actions = new ArrayList<>(); List<Action> actions = new ArrayList<>();
actions.addAll(Arrays.asList(super.getActions(context))); actions.addAll(Arrays.asList(super.getActions(context)));
actions.add(new OpenMultiUserCaseAction(multiUserCase.getFilePath())); actions.add(new OpenMultiUserCaseAction(caseMetadataFilePath));
return actions.toArray(new Action[actions.size()]); return actions.toArray(new Action[actions.size()]);
} }
} }
@ -162,9 +163,9 @@ public final class CaseNode extends AbstractNode {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final Path caseMetadataFilePath; private final String caseMetadataFilePath;
public OpenMultiUserCaseAction(Path path) { OpenMultiUserCaseAction(String path) {
super("Open Case"); super("Open Case");
caseMetadataFilePath = path; caseMetadataFilePath = path;
} }
@ -172,16 +173,10 @@ public final class CaseNode extends AbstractNode {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
StartupWindowProvider.getInstance().close(); StartupWindowProvider.getInstance().close();
openCaseThread(caseMetadataFilePath);
}
}
private static void openCaseThread(Path caseMetadataFilePath) {
new Thread( new Thread(
() -> { () -> {
try { try {
Case.openAsCurrentCase(caseMetadataFilePath.toString()); Case.openAsCurrentCase(caseMetadataFilePath);
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) { if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
// LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS // LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
@ -200,4 +195,10 @@ public final class CaseNode extends AbstractNode {
).start(); ).start();
} }
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //To change body of generated methods, choose Tools | Templates.
}
}
} }

View File

@ -45,13 +45,12 @@ import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.autopsy.datamodel.EmptyNode;
import org.sleuthkit.datamodel.TskCoreException;
/** /**
* A panel that allows a user to open cases created by auto ingest. * A panel that allows a user to open cases created by auto ingest.
*/ */
@NbBundle.Messages({"MultiUSerCasesPanel.caseListLoading.message=Retrieving list of cases, please wait..."}) @NbBundle.Messages({"MultiUserCasesPanel.caseListLoading.message=Please wait..."})
final class MultiUserCasesPanel extends TopComponent implements ExplorerManager.Provider { final class MultiUserCasesPanel extends TopComponent implements ExplorerManager.Provider {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -73,7 +72,7 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager.
caseListPanel = new CaseBrowser(); caseListPanel = new CaseBrowser();
caseListPanel.open(); caseListPanel.open();
caseListPanel.setRowSelectionAllowed(false);
caseExplorerScrollPane.add(caseListPanel); caseExplorerScrollPane.add(caseListPanel);
caseExplorerScrollPane.setViewportView(caseListPanel); caseExplorerScrollPane.setViewportView(caseListPanel);
/* /*
@ -92,11 +91,13 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager.
*/ */
void refresh() { void refresh() {
if (tableWorker == null || tableWorker.isDone()) { if (tableWorker == null || tableWorker.isDone()) {
caseListPanel.setRowSelectionAllowed(false);
//create a new TableWorker to and execute it in a background thread if one is not currently working //create a new TableWorker to and execute it in a background thread if one is not currently working
//set the table to display text informing the user that the list is being retreived and disable case selection //set the table to display text informing the user that the list is being retreived and disable case selection
EmptyNode emptyNode = new EmptyNode(Bundle.MultiUserCasesPanel_caseListLoading_message());
explorerManager.setRootContext(emptyNode);
tableWorker = new LoadCaseListWorker(); tableWorker = new LoadCaseListWorker();
tableWorker.execute(); tableWorker.execute();
} }
} }
@ -117,7 +118,6 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager.
*/ */
private void openCase(String caseMetadataFilePath) { private void openCase(String caseMetadataFilePath) {
if (caseMetadataFilePath != null) { if (caseMetadataFilePath != null) {
System.out.println("OPENENING CASE: " + caseMetadataFilePath);
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
StartupWindowProvider.getInstance().close(); StartupWindowProvider.getInstance().close();
@ -296,7 +296,7 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager.
* @throws CoordinationServiceException * @throws CoordinationServiceException
*/ */
private Map<CaseMetadata, Boolean> getCases() throws CoordinationService.CoordinationServiceException { private Map<CaseMetadata, Boolean> getCases() throws CoordinationService.CoordinationServiceException {
Map<CaseMetadata, Boolean> cases = new HashMap<>(); Map<CaseMetadata, Boolean> casesMap = new HashMap<>();
List<String> nodeList = CoordinationService.getInstance().getNodeList(CoordinationService.CategoryNode.CASES); List<String> nodeList = CoordinationService.getInstance().getNodeList(CoordinationService.CategoryNode.CASES);
for (String node : nodeList) { for (String node : nodeList) {
@ -352,7 +352,7 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager.
} }
CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFilePath)); CaseMetadata caseMetadata = new CaseMetadata(Paths.get(autFilePath));
cases.put(caseMetadata, hasAlertStatus); casesMap.put(caseMetadata, hasAlertStatus);
} catch (CaseMetadata.CaseMetadataException ex) { } catch (CaseMetadata.CaseMetadataException ex) {
LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex); LOGGER.log(Level.SEVERE, String.format("Error reading case metadata file '%s'.", autFilePath), ex);
} catch (InterruptedException | CaseNodeData.InvalidDataException ex) { } catch (InterruptedException | CaseNodeData.InvalidDataException ex) {
@ -361,7 +361,7 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager.
} }
} }
} }
return cases; return casesMap;
} }
@Override @Override
@ -381,18 +381,7 @@ final class MultiUserCasesPanel extends TopComponent implements ExplorerManager.
EventQueue.invokeLater(() -> { EventQueue.invokeLater(() -> {
CaseNode caseListNode = new CaseNode(cases); CaseNode caseListNode = new CaseNode(cases);
explorerManager.setRootContext(caseListNode); explorerManager.setRootContext(caseListNode);
String displayName = ""; caseListPanel.setRowSelectionAllowed(true);
Content content = caseListNode.getLookup().lookup(Content.class);
if (content != null) {
try {
displayName = content.getUniquePath();
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Exception while calling Content.getUniquePath() for node: {0}", caseListNode); //NON-NLS
}
} else if (caseListNode.getLookup().lookup(String.class) != null) {
displayName = caseListNode.getLookup().lookup(String.class);
}
System.out.println("GET CASES DONE");
setButtons(); setButtons();
}); });
} }