From 8feec32e9d5532434b472a0d3f51f73ba840adad Mon Sep 17 00:00:00 2001 From: Jeff Wallace Date: Mon, 16 Sep 2013 12:36:52 -0400 Subject: [PATCH 1/5] Loading large amounts of Nodes no longer blocks the UI. --- .../corecomponents/DataResultPanel.java | 2 +- .../corecomponents/DataResultViewerTable.java | 90 +++++++++++++++---- .../datamodel/FileSearchFilterChildren.java | 15 ++-- 3 files changed, 81 insertions(+), 26 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java index 18a13ec560..4f21a1ce5a 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java @@ -287,7 +287,7 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C public void setNode(Node selectedNode) { this.rootNode = selectedNode; if (selectedNode != null) { - int childrenCount = selectedNode.getChildren().getNodesCount(true); + int childrenCount = selectedNode.getChildren().getNodesCount(); this.numberMatchLabel.setText(Integer.toString(childrenCount)); } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 36ccb8715d..3fc82abb00 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -22,14 +22,17 @@ import java.awt.Cursor; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.dnd.DnDConstants; +import java.beans.PropertyChangeEvent; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.JTable; import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; import org.netbeans.swing.outline.DefaultOutlineModel; import org.openide.explorer.ExplorerManager; import org.openide.explorer.view.OutlineView; @@ -38,6 +41,10 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Node.Property; import org.openide.nodes.Node.PropertySet; +import org.openide.nodes.NodeEvent; +import org.openide.nodes.NodeListener; +import org.openide.nodes.NodeMemberEvent; +import org.openide.nodes.NodeReorderEvent; import org.openide.nodes.Sheet; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; @@ -53,6 +60,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { private String firstColumnLabel = "Name"; private Set propertiesAcc = new LinkedHashSet<>(); private static final Logger logger = Logger.getLogger(DataResultViewerTable.class.getName()); + private final DummyNodeListener dummyNodeListener = new DummyNodeListener(); /** * Creates a DataResultViewerTable object that is compatible with node @@ -246,11 +254,38 @@ public class DataResultViewerTable extends AbstractDataResultViewer { hasChildren = selectedNode.getChildren().getNodesCount() > 0; } - + Node oldNode = this.em.getRootContext(); + if (oldNode != null) { + oldNode.removeNodeListener(dummyNodeListener); + } + // if there's no selection node, do nothing if (hasChildren) { Node root = selectedNode; - + root.addNodeListener(dummyNodeListener); + setupTable(root); + } else { + final OutlineView ov = ((OutlineView) this.tableScrollPanel); + Node emptyNode = new AbstractNode(Children.LEAF); + em.setRootContext(emptyNode); // make empty node + ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + ov.setPropertyColumns(); // set the empty property header + } + } finally { + this.setCursor(null); + } + } + + /** + * Create Column Headers based on the Content represented by the Nodes in + * the table. + * + * @param root The parent Node of the ContentNodes + */ + private void setupTable(final Node root) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { //wrap to filter out children //note: this breaks the tree view mode in this generic viewer, //so wrap nodes earlier if want 1 level view @@ -261,11 +296,11 @@ public class DataResultViewerTable extends AbstractDataResultViewer { em.setRootContext(root); - final OutlineView ov = ((OutlineView) this.tableScrollPanel); + final OutlineView ov = ((OutlineView) DataResultViewerTable.this.tableScrollPanel); propertiesAcc.clear(); - this.getAllChildPropertyHeadersRec(selectedNode, 100); + DataResultViewerTable.this.getAllChildPropertyHeadersRec(root, 100); List props = new ArrayList(propertiesAcc); if (props.size() > 0) { Node.Property prop = props.remove(0); @@ -315,7 +350,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { // get first 100 rows values for the table Object[][] content = null; - content = getRowValues(selectedNode, 100); + content = getRowValues(root, 100); if (content != null) { @@ -341,17 +376,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer { // turn on the auto resize ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); } - - } else { - final OutlineView ov = ((OutlineView) this.tableScrollPanel); - Node emptyNode = new AbstractNode(Children.LEAF); - em.setRootContext(emptyNode); // make empty node - ov.getOutline().setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); - ov.setPropertyColumns(); // set the empty property header } - } finally { - this.setCursor(null); - } + }); } private static Object[][] getRowValues(Node node, int rows) { @@ -454,4 +480,38 @@ public class DataResultViewerTable extends AbstractDataResultViewer { super.clearComponent(); } + + private class DummyNodeListener implements NodeListener { + private static final String DUMMY_NODE_DISPLAY_NAME = "Please Wait..."; + + @Override + public void childrenAdded(NodeMemberEvent nme) { + } + + @Override + public void childrenRemoved(NodeMemberEvent nme) { + Node removed = nme.getDelta()[0]; + if (! removed.getDisplayName().equals(DUMMY_NODE_DISPLAY_NAME)) { + // If it's not the dummy waiting node, we don't want + // to reload the table headers + return; + } + + // dummy node removed. Reset the table headers. + Node node = nme.getNode(); + setupTable(node); + } + + @Override + public void childrenReordered(NodeReorderEvent nre) { + } + + @Override + public void nodeDestroyed(NodeEvent ne) { + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterChildren.java index cc4f6309f0..0b351ea5bc 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterChildren.java @@ -25,7 +25,6 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.openide.nodes.AbstractNode; import org.openide.nodes.ChildFactory; import org.openide.nodes.Node; -import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentVisitor; import org.sleuthkit.datamodel.DerivedFile; @@ -45,7 +44,7 @@ class FileSearchFilterChildren extends ChildFactory { private SleuthkitCase skCase; private SearchFilters.SearchFilterInterface filter; private static final Logger logger = Logger.getLogger(FileSearchFilterChildren.class.getName()); - //private final static int MAX_OBJECTS = 2000; +// private final static int MAX_OBJECTS = 2000; public FileSearchFilterChildren(SearchFilters.SearchFilterInterface filter, SleuthkitCase skCase) { this.filter = filter; @@ -57,7 +56,6 @@ class FileSearchFilterChildren extends ChildFactory { list.addAll(runQuery()); return true; } - private String createQuery(){ String query = "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")" @@ -66,18 +64,15 @@ class FileSearchFilterChildren extends ChildFactory { query += " OR name LIKE '%" + s + "'"; } query += ')'; - //query += " LIMIT " + MAX_OBJECTS; +// query += " LIMIT " + MAX_OBJECTS; return query; } - private List runQuery(){ - List list = new ArrayList(); + private List runQuery(){ + List list = new ArrayList<>(); try { - List res = skCase.findAllFilesWhere(createQuery()); - for(AbstractFile c : res){ - list.add(c); - } + list = skCase.findAllFilesWhere(createQuery()); } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Couldn't get search results", ex); } From 260776a2910f6a3b4cd47c16045bdaf6ee0aa8d6 Mon Sep 17 00:00:00 2001 From: Jeff Wallace Date: Tue, 17 Sep 2013 12:12:13 -0400 Subject: [PATCH 2/5] Added cap to number of Nodes generated in DeletedContent --- Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java index 72f8bd451c..5b6d47906c 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java @@ -213,6 +213,8 @@ public class DeletedContent implements AutopsyVisitableItem { private SleuthkitCase skCase; private DeletedContent.DeletedContentFilter filter; private final Logger logger = Logger.getLogger(DeletedContentChildren.class.getName()); + + private static final int MAX_OBJECTS = 2000; DeletedContentChildren(DeletedContent.DeletedContentFilter filter, SleuthkitCase skCase) { this.skCase = skCase; @@ -258,6 +260,7 @@ public class DeletedContent implements AutopsyVisitableItem { } + query += " LIMIT " + MAX_OBJECTS; return query; } From 7e896c073123c453320ae375ca25373dd4d87ecd Mon Sep 17 00:00:00 2001 From: Jeff Wallace Date: Tue, 17 Sep 2013 12:35:13 -0400 Subject: [PATCH 3/5] DataResultPanel now checks which DRV are supported for the current Node when the children are done loading. --- .../corecomponents/DataResultPanel.java | 57 ++++++++++++++++--- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java index 4f21a1ce5a..bc2e4f9282 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.corecomponents; import java.awt.Cursor; +import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.ArrayList; @@ -29,6 +30,10 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.openide.explorer.ExplorerManager; import org.openide.nodes.Node; +import org.openide.nodes.NodeEvent; +import org.openide.nodes.NodeListener; +import org.openide.nodes.NodeMemberEvent; +import org.openide.nodes.NodeReorderEvent; import org.openide.util.Lookup; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponentinterfaces.DataContent; @@ -58,6 +63,7 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C private DataContent customContentViewer; private boolean isMain; private String title; + private final DummyNodeListener dummyNodeListener = new DummyNodeListener(); private static final Logger logger = Logger.getLogger(DataResultPanel.class.getName() ); @@ -285,7 +291,16 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C @Override public void setNode(Node selectedNode) { + if (this.rootNode != null) { + this.rootNode.removeNodeListener(dummyNodeListener); + } this.rootNode = selectedNode; + if (this.rootNode != null) { + this.rootNode.addNodeListener(dummyNodeListener); + } + + setupTabs(selectedNode); + if (selectedNode != null) { int childrenCount = selectedNode.getChildren().getNodesCount(); this.numberMatchLabel.setText(Integer.toString(childrenCount)); @@ -295,7 +310,16 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C this.numberMatchLabel.setVisible(true); resetTabs(selectedNode); - + + // set the display on the current active tab + int currentActiveTab = this.dataResultTabbedPanel.getSelectedIndex(); + if (currentActiveTab != -1) { + UpdateWrapper drv = viewers.get(currentActiveTab); + drv.setNode(selectedNode); + } + } + + private void setupTabs(Node selectedNode) { //update/disable tabs based on if supported for this node int drvC = 0; for (UpdateWrapper drv : viewers) { @@ -307,13 +331,6 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C } ++drvC; } - - // set the display on the current active tab - int currentActiveTab = this.dataResultTabbedPanel.getSelectedIndex(); - if (currentActiveTab != -1) { - UpdateWrapper drv = viewers.get(currentActiveTab); - drv.setNode(selectedNode); - } } @Override @@ -499,4 +516,28 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C public void setNumMatches(int numMatches) { this.numberMatchLabel.setText(Integer.toString(numMatches)); } + + private class DummyNodeListener implements NodeListener { + + @Override + public void childrenAdded(NodeMemberEvent nme) { + setupTabs(nme.getNode()); + } + + @Override + public void childrenRemoved(NodeMemberEvent nme) { + } + + @Override + public void childrenReordered(NodeReorderEvent nre) { + } + + @Override + public void nodeDestroyed(NodeEvent ne) { + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + } + } } From 4b0fe6dd63e75d6e4cddc54423f4f332ba3b807e Mon Sep 17 00:00:00 2001 From: Jeff Wallace Date: Wed, 18 Sep 2013 16:13:02 -0400 Subject: [PATCH 4/5] Moved adding of jdkhome property to the windows installer targets. --- build-windows.xml | 11 +++++++++++ build.xml | 1 - 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/build-windows.xml b/build-windows.xml index 330321f372..f048ee98b2 100644 --- a/build-windows.xml +++ b/build-windows.xml @@ -27,6 +27,17 @@ + + + + + + + + + + + diff --git a/build.xml b/build.xml index 11f80417cb..417487251e 100644 --- a/build.xml +++ b/build.xml @@ -78,7 +78,6 @@ - From 393f9180fbe648e1e50c6ea39ab4e870b75cf000 Mon Sep 17 00:00:00 2001 From: Jeff Wallace Date: Thu, 19 Sep 2013 10:55:20 -0400 Subject: [PATCH 5/5] Corrected gstreamer env variable in build script. --- build-windows.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-windows.xml b/build-windows.xml index f048ee98b2..dc7cec7600 100644 --- a/build-windows.xml +++ b/build-windows.xml @@ -185,7 +185,7 @@ - +