From b495209baa1311f5771cfb1c988a7cbefc091844 Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Tue, 19 Jun 2018 18:22:03 -0700 Subject: [PATCH 01/40] added Callable, PropertyChangeListener --- .../autopsy/commonfilesearch/Md5Metadata.java | 16 ++++++ .../autopsy/datamodel/InstanceCountNode.java | 40 ++++++++++++-- .../sleuthkit/autopsy/datamodel/Md5Node.java | 52 +++++++++++++++++-- 3 files changed, 100 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java index 39c2cf8040..74891151fe 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java @@ -19,6 +19,9 @@ */ package org.sleuthkit.autopsy.commonfilesearch; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -32,10 +35,12 @@ final public class Md5Metadata { private final String md5; private final List fileInstances; + private final PropertyChangeSupport pss; Md5Metadata(String md5, List fileInstances){ this.md5 = md5; this.fileInstances = fileInstances; + this.pss = new PropertyChangeSupport(this); } public String getMd5(){ @@ -65,4 +70,15 @@ final public class Md5Metadata { } return String.join(", ", sources); } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + this.pss.addPropertyChangeListener(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + this.pss.removePropertyChangeListener(listener); + } + + + } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java index cc7f23eda7..1bf2ef896f 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java @@ -19,17 +19,21 @@ */ package org.sleuthkit.autopsy.datamodel; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.Callable; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.commonfilesearch.Md5Metadata; /** @@ -41,13 +45,35 @@ final public class InstanceCountNode extends DisplayableItemNode { final private List metadataList; public InstanceCountNode(int instanceCount, List md5Metadata) { - super(Children.create(new Md5NodeFactory(md5Metadata), true)); + super(Children.createLazy(new InstanceCountChildCallable(md5Metadata)), Lookups.singleton(instanceCount)); this.instanceCount = instanceCount; this.metadataList = md5Metadata; this.setDisplayName(Integer.toString(instanceCount)); } + + /** + * Callable wrapper to further delay lazy ChildFactory creation + * and createNodes() call once lazy loading is functional. + */ + private static class InstanceCountChildCallable implements Callable { + private final List key; + private InstanceCountChildCallable(List key) { + this.key = key; + } + @Override + public Children call() throws Exception { + return Children.create(new Md5NodeFactory(key), true); + + } + } + + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("ADD")) { + setChildren(Children.create(new Md5NodeFactory(metadataList), false)); + } + } int getInstanceCount() { return this.instanceCount; @@ -127,7 +153,7 @@ final public class InstanceCountNode extends DisplayableItemNode { * ChildFactory which builds CommonFileParentNodes from the * CommonFilesMetaaData models. */ - static class Md5NodeFactory extends ChildFactory { + static class Md5NodeFactory extends ChildFactory implements PropertyChangeListener { /** * List of models, each of which is a parent node matching a single md5, @@ -137,7 +163,7 @@ final public class InstanceCountNode extends DisplayableItemNode { Md5NodeFactory(List metadata) { this.metadata = new HashMap<>(); - + Iterator iterator = metadata.iterator(); while (iterator.hasNext()) { Md5Metadata md5Metadata = iterator.next(); @@ -156,5 +182,13 @@ final public class InstanceCountNode extends DisplayableItemNode { list.addAll(this.metadata.keySet()); return true; } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("ADD") || evt.getPropertyName().equals("REMOVE")) { + this.refresh(true); + } + } + } } \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java b/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java index 4ef47605b4..fc06be3d77 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java @@ -19,15 +19,19 @@ */ package org.sleuthkit.autopsy.datamodel; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.Callable; import java.util.logging.Level; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.commonfilesearch.FileInstanceMetadata; @@ -43,24 +47,53 @@ import org.sleuthkit.datamodel.TskCoreException; * the MD5 of the matched files, the data sources those files were found within, * and a count of the instances represented by the md5. */ -public class Md5Node extends DisplayableItemNode { +public class Md5Node extends DisplayableItemNode implements PropertyChangeListener { private static final Logger LOGGER = Logger.getLogger(Md5Node.class.getName()); private final String md5Hash; private final int commonFileCount; private final String dataSources; + private final Md5Metadata metaData; public Md5Node(Md5Metadata data) { - super(Children.create( - new FileInstanceNodeFactory(data), true)); + super(Children.createLazy(new Md5ChildCallable(data)), Lookups.singleton(data.getMd5())); + this.commonFileCount = data.size(); this.dataSources = String.join(", ", data.getDataSources()); this.md5Hash = data.getMd5(); - + this.metaData = data; + metaData.addPropertyChangeListener(this); this.setDisplayName(this.md5Hash); } + + /** + * Callable wrapper to further delay lazy ChildFactory creation + * and createNodes() call once lazy loading is functional. + */ + private static class Md5ChildCallable implements Callable { + private final Md5Metadata key; + private Md5ChildCallable(Md5Metadata key) { + this.key = key; + } + @Override + public Children call() throws Exception { + //Check that the key has children, + //if it doesn't have children, return a leaf: + if (key.getMetadata().isEmpty()) { + return Children.LEAF; + } else { + return Children.create(new FileInstanceNodeFactory(key), true); + } + } + } + + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("ADD")) { + setChildren(Children.create(new FileInstanceNodeFactory(metaData), false)); + } + } int getCommonFileCount() { return this.commonFileCount; @@ -125,12 +158,13 @@ public class Md5Node extends DisplayableItemNode { /** * Child generator for FileInstanceNode of Md5Node. */ - static class FileInstanceNodeFactory extends ChildFactory { + static class FileInstanceNodeFactory extends ChildFactory implements PropertyChangeListener { private final Md5Metadata descendants; FileInstanceNodeFactory(Md5Metadata descendants) { this.descendants = descendants; + descendants.addPropertyChangeListener(this); } @Override @@ -152,6 +186,13 @@ public class Md5Node extends DisplayableItemNode { list.addAll(this.descendants.getMetadata()); return true; } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("ADD") || evt.getPropertyName().equals("REMOVE")) { + this.refresh(true); + } + } } @NbBundle.Messages({ @@ -175,4 +216,5 @@ public class Md5Node extends DisplayableItemNode { return this.displayString; } } + } From 06cbc75032949ff0f0fe3660c1de3c276c63ce7c Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Wed, 20 Jun 2018 10:56:40 -0700 Subject: [PATCH 02/40] delayed Md5Node creation. --- .../commonfilesearch/CommonFilesMetadata.java | 26 ++++--- .../CommonFilesMetadataBuilder.java | 10 +-- .../commonfilesearch/CommonFilesNode.java | 28 ++++++-- .../commonfilesearch/CommonFilesPanel.java | 2 +- .../autopsy/commonfilesearch/Md5Metadata.java | 2 +- .../commonfilesearch/Md5MetadataList.java | 62 ++++++++++++++++ .../corecomponents/DataResultViewerTable.java | 70 +++++++++++++++++++ .../MultiLayerTableFilterNode.java | 6 ++ .../autopsy/datamodel/InstanceCountNode.java | 70 +++++++++++++------ .../directorytree/DataResultFilterNode.java | 7 ++ 10 files changed, 241 insertions(+), 42 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5MetadataList.java diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java index b04792fb6b..c755b7a12a 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java @@ -20,7 +20,7 @@ package org.sleuthkit.autopsy.commonfilesearch; import java.util.Collections; -import java.util.List; +import java.util.HashMap; import java.util.Map; /** @@ -29,7 +29,8 @@ import java.util.Map; */ final public class CommonFilesMetadata { - private final Map> metadata; + private final Map metadata; + private final Map hiddenMetaData; /** * Create a metadata object which can be handed off to the node @@ -37,8 +38,13 @@ final public class CommonFilesMetadata { * * @param metadata list of Md5Metadata indexed by size of Md5Metadata */ - CommonFilesMetadata(Map> metadata){ - this.metadata = metadata; + CommonFilesMetadata(Map metadata){ + Map tempMetadata = new HashMap<>(); + for(Integer key : metadata.keySet()) { + tempMetadata.put(key, new Md5MetadataList()); + } + this.metadata = tempMetadata; + this.hiddenMetaData = metadata; } /** @@ -50,11 +56,15 @@ final public class CommonFilesMetadata { * @param md5 key * @return */ - List getMetadataForMd5(Integer instanceCount) { + Md5MetadataList getMetadataForMd5(Integer instanceCount) { return this.metadata.get(instanceCount); } + + public void displayHiddenMetadata() { + this.metadata.putAll(this.hiddenMetaData); + } - public Map> getMetadata() { + public Map getMetadata() { return Collections.unmodifiableMap(this.metadata); } @@ -65,8 +75,8 @@ final public class CommonFilesMetadata { public int size() { int count = 0; - for (List data : this.metadata.values()) { - for(Md5Metadata md5 : data){ + for (Md5MetadataList data : this.metadata.values()) { + for(Md5Metadata md5 : data.getMetadataList()){ count += md5.size(); } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadataBuilder.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadataBuilder.java index 9c04abd9c5..3865c7a7e6 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadataBuilder.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadataBuilder.java @@ -200,17 +200,17 @@ public abstract class CommonFilesMetadataBuilder { } } - Map> instanceCollatedCommonFiles = new TreeMap<>(); + Map instanceCollatedCommonFiles = new TreeMap<>(); for(Md5Metadata md5Metadata : commonFiles.values()){ Integer size = md5Metadata.size(); if(instanceCollatedCommonFiles.containsKey(size)){ - instanceCollatedCommonFiles.get(size).add(md5Metadata); + instanceCollatedCommonFiles.get(size).addMetadataToList(md5Metadata); } else { - ArrayList value = new ArrayList(); - value.add(md5Metadata); - instanceCollatedCommonFiles.put(size, value); + Md5MetadataList metaList = new Md5MetadataList(); + metaList.addMetadataToList(md5Metadata); + instanceCollatedCommonFiles.put(size, metaList); } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java index aa6d310219..2c72b0c804 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java @@ -18,6 +18,8 @@ */ package org.sleuthkit.autopsy.commonfilesearch; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import org.sleuthkit.autopsy.datamodel.InstanceCountNode; import java.util.List; import org.openide.nodes.ChildFactory; @@ -33,9 +35,12 @@ import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; */ final public class CommonFilesNode extends DisplayableItemNode { - + private final CommonFilesMetadata metadataList; + CommonFilesNode(CommonFilesMetadata metadataList) { super(Children.create(new InstanceCountNodeFactory(metadataList), true)); + this.metadataList = metadataList; + this.refresh(); } @NbBundle.Messages({ @@ -59,8 +64,16 @@ final public class CommonFilesNode extends DisplayableItemNode { public String getItemType() { return getClass().getName(); } + + public void setCleanRefreshNeeded(boolean b) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + public void refresh() { + metadataList.displayHiddenMetadata(); + } - static class InstanceCountNodeFactory extends ChildFactory{ + static class InstanceCountNodeFactory extends ChildFactory implements PropertyChangeListener { private final CommonFilesMetadata metadata; @@ -76,8 +89,15 @@ final public class CommonFilesNode extends DisplayableItemNode { @Override protected Node createNodeForKey(Integer instanceCount){ - List md5Metadata = this.metadata.getMetadataForMd5(instanceCount); + Md5MetadataList md5Metadata = this.metadata.getMetadataForMd5(instanceCount); return new InstanceCountNode(instanceCount, md5Metadata); - } + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("ADD") || evt.getPropertyName().equals("REMOVE")) { + this.refresh(true); + } + } } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java index 5cf77ffd58..8b3004637a 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java @@ -247,7 +247,7 @@ public final class CommonFilesPanel extends javax.swing.JPanel { MultiLayerTableFilterNode tableFilterWithDescendantsNode = new MultiLayerTableFilterNode(dataResultFilterNode, 3); - DataResultViewerTable table = new DataResultViewerTable(); + DataResultViewerTable table = new DataResultViewerTable(true); Collection viewers = new ArrayList<>(1); viewers.add(table); diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java index 74891151fe..9e19cce9ae 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java @@ -19,9 +19,9 @@ */ package org.sleuthkit.autopsy.commonfilesearch; -import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5MetadataList.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5MetadataList.java new file mode 100644 index 0000000000..d24df739eb --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5MetadataList.java @@ -0,0 +1,62 @@ +/* + * + * Autopsy Forensic Browser + * + * Copyright 2018 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.commonfilesearch; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Utility and wrapper model around data required for Common Files Search results. + * Subclass this to implement different selections of files from the case. + */ +final public class Md5MetadataList { + + private final List metadataList; + private final List delayedMetadataList; + + /** + * Create a metadata object containing the list of metadata which can be handed off to the node + * factories. + * + * @param metadata list of Md5Metadata indexed by size of Md5Metadata + */ + Md5MetadataList(List metadata){ + this.metadataList = new ArrayList(); + this.delayedMetadataList = metadata; + } + + Md5MetadataList(){ + this.metadataList = new ArrayList<>(); + this.delayedMetadataList = new ArrayList<>(); + } + + public List getMetadataList() { + return Collections.unmodifiableList(this.metadataList); + } + + public void displayDelayedMetadata() { + this.metadataList.addAll(this.delayedMetadataList); + } + + public void addMetadataToList(Md5Metadata metadata) { + delayedMetadataList.add(metadata); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 9e27700481..732347d85d 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -44,9 +44,11 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; +import javax.swing.event.TreeExpansionEvent; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; +import javax.swing.event.TreeExpansionListener; import org.netbeans.swing.etable.ETableColumn; import org.netbeans.swing.etable.ETableColumnModel; import org.netbeans.swing.outline.DefaultOutlineCellRenderer; @@ -54,6 +56,7 @@ import org.netbeans.swing.outline.DefaultOutlineModel; import org.netbeans.swing.outline.Outline; import org.openide.explorer.ExplorerManager; import org.openide.explorer.view.OutlineView; +import org.openide.explorer.view.Visualizer; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Node; @@ -61,10 +64,13 @@ import org.openide.nodes.Node.Property; import org.openide.util.NbBundle; import org.openide.util.NbPreferences; import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.commonfilesearch.CommonFilesNode; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; +import org.sleuthkit.autopsy.datamodel.InstanceCountNode; import org.sleuthkit.autopsy.datamodel.NodeSelectionInfo; +import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; /** * A tabular result viewer that displays the children of the given root node @@ -102,6 +108,70 @@ public final class DataResultViewerTable extends AbstractDataResultViewer { public DataResultViewerTable() { this(null, Bundle.DataResultViewerTable_title()); } + /** + * Constructs a tabular result viewer that displays the children of the + * given root node using an OutlineView. The viewer should have an ancestor + * top component to connect the lookups of the nodes displayed in the + * OutlineView to the actions global context. The explorer manager will be + * discovered at runtime. + */ + public DataResultViewerTable(boolean addListener) { + this(null, Bundle.DataResultViewerTable_title()); + outlineView.addTreeExpansionListener(new LazyLoadChildNodesOnTreeExpansion()); + } + + /** + * A tree expansion listener that will trigger a recreation of childs through its + * child factory on re-expansion of a node (causes to recreate the ChildFactory for + * this purpose.). + */ + private class LazyLoadChildNodesOnTreeExpansion implements TreeExpansionListener { + + /** + * A flag for avoiding endless recursion inside the expansion listener that could + * trigger collapsing and (re-)expanding nodes again. + */ + private boolean inRecursion = false; + + @Override + public synchronized void treeCollapsed(final TreeExpansionEvent event) { + Node eventNode = Visualizer.findNode(event.getPath().getLastPathComponent()); + if (!inRecursion && eventNode instanceof CommonFilesNode) { // avoid endless + // recursion + final CommonFilesNode node = (CommonFilesNode) eventNode; + node.setCleanRefreshNeeded(true); + } + } + + @Override + public synchronized void treeExpanded(final TreeExpansionEvent event) { + Node eventNode = Visualizer.findNode(event.getPath().getLastPathComponent()); + if (!inRecursion && eventNode instanceof MultiLayerTableFilterNode) { + final MultiLayerTableFilterNode node = (MultiLayerTableFilterNode) eventNode; + Node innerNode = node.getInnerNode(); + if(innerNode instanceof DataResultFilterNode) { + + final DataResultFilterNode drNode = (DataResultFilterNode) innerNode; + Node innerInnerNode = drNode.getInnerNode(); + if(innerInnerNode instanceof InstanceCountNode) { + final InstanceCountNode cfNode = (InstanceCountNode) innerInnerNode; + cfNode.refresh(); + }} + + if (!outlineView.isExpanded(node)) { + // Seems that the refresh caused to collapse, re-expand again and + // avoid recursion in this listener! + inRecursion = true; + try { + outlineView.expandNode(node); + } finally { + inRecursion = false; + } + } + } + + } + } /** * Constructs a tabular result viewer that displays the children of a given diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiLayerTableFilterNode.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiLayerTableFilterNode.java index c74f02f32d..b83d045c91 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiLayerTableFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiLayerTableFilterNode.java @@ -36,6 +36,7 @@ public class MultiLayerTableFilterNode extends FilterNode implements TableFilter private final boolean createChildren; private final boolean forceUseWrappedDisplayName; private static final String columnOrderKey = "NONE"; + private final Node innerNode; /** * Constructs a filter node that generates children using @@ -49,6 +50,11 @@ public class MultiLayerTableFilterNode extends FilterNode implements TableFilter super(node, TableFilterChildrenWithDescendants.createInstance(node, true, childLayerDepth), Lookups.proxy(node)); this.createChildren = true; this.forceUseWrappedDisplayName = true; + this.innerNode = node; + } + + public Node getInnerNode() { + return innerNode; } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java index 1bf2ef896f..cf86f7a613 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java @@ -20,8 +20,6 @@ package org.sleuthkit.autopsy.datamodel; import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; @@ -31,10 +29,15 @@ import java.util.concurrent.Callable; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; 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.nodes.Sheet; import org.openide.util.NbBundle; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.commonfilesearch.Md5Metadata; +import org.sleuthkit.autopsy.commonfilesearch.Md5MetadataList; /** * @@ -42,9 +45,9 @@ import org.sleuthkit.autopsy.commonfilesearch.Md5Metadata; final public class InstanceCountNode extends DisplayableItemNode { final private int instanceCount; - final private List metadataList; + final private Md5MetadataList metadataList; - public InstanceCountNode(int instanceCount, List md5Metadata) { + public InstanceCountNode(int instanceCount, Md5MetadataList md5Metadata) { super(Children.createLazy(new InstanceCountChildCallable(md5Metadata)), Lookups.singleton(instanceCount)); this.instanceCount = instanceCount; @@ -58,20 +61,20 @@ final public class InstanceCountNode extends DisplayableItemNode { * and createNodes() call once lazy loading is functional. */ private static class InstanceCountChildCallable implements Callable { - private final List key; - private InstanceCountChildCallable(List key) { + private final Md5MetadataList key; + private InstanceCountChildCallable(Md5MetadataList key) { this.key = key; } @Override public Children call() throws Exception { - return Children.create(new Md5NodeFactory(key), true); + return Children.create(new Md5NodeFactory(key.getMetadataList()), true); } } public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals("ADD")) { - setChildren(Children.create(new Md5NodeFactory(metadataList), false)); + setChildren(Children.create(new Md5NodeFactory(metadataList.getMetadataList()), false)); } } @@ -80,7 +83,7 @@ final public class InstanceCountNode extends DisplayableItemNode { } List getMetadata() { - return Collections.unmodifiableList(this.metadataList); + return this.metadataList.getMetadataList(); } @Override @@ -92,6 +95,16 @@ final public class InstanceCountNode extends DisplayableItemNode { public boolean isLeafTypeNode() { return false; } + + public void setCleanRefreshNeeded(boolean b) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + public void refresh() { + metadataList.displayDelayedMetadata(); + //firePropertyChange(PROP_NAME, this, this); + setChildren(Children.create(new Md5NodeFactory(metadataList.getMetadataList()), false)); + } @Override public String getItemType() { @@ -153,33 +166,26 @@ final public class InstanceCountNode extends DisplayableItemNode { * ChildFactory which builds CommonFileParentNodes from the * CommonFilesMetaaData models. */ - static class Md5NodeFactory extends ChildFactory implements PropertyChangeListener { + static class Md5NodeFactory extends ChildFactory implements NodeListener { /** * List of models, each of which is a parent node matching a single md5, * containing children FileNodes. */ - private final Map metadata; + private final List metadata; Md5NodeFactory(List metadata) { - this.metadata = new HashMap<>(); - - Iterator iterator = metadata.iterator(); - while (iterator.hasNext()) { - Md5Metadata md5Metadata = iterator.next(); - this.metadata.put(md5Metadata.getMd5(), md5Metadata); - } + this.metadata = metadata; } @Override - protected Node createNodeForKey(String md5) { - Md5Metadata md5Metadata = this.metadata.get(md5); - return new Md5Node(md5Metadata); + protected Node createNodeForKey(Md5Metadata metadataKey) { + return new Md5Node(metadataKey); } @Override - protected boolean createKeys(List list) { - list.addAll(this.metadata.keySet()); + protected boolean createKeys(List list) { + list.addAll(metadata); return true; } @@ -189,6 +195,24 @@ final public class InstanceCountNode extends DisplayableItemNode { this.refresh(true); } } + + @Override + public void childrenAdded(NodeMemberEvent nme) { + } + @Override + public void childrenRemoved(NodeMemberEvent nme) { + } + + @Override + public void childrenReordered(NodeReorderEvent nre) { + + } + + @Override + public void nodeDestroyed(NodeEvent ne) { + + } + } } \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index a23f045f48..a9e841abb3 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -98,6 +98,7 @@ public class DataResultFilterNode extends FilterNode { private static boolean filterKnownFromViews = UserPreferences.hideKnownFilesInViewsTree(); private static boolean filterSlackFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree(); private static boolean filterSlackFromViews = UserPreferences.hideSlackFilesInViewsTree(); + private Node innerNode; static { UserPreferences.addChangeListener(new PreferenceChangeListener() { @@ -138,6 +139,11 @@ public class DataResultFilterNode extends FilterNode { public DataResultFilterNode(Node node, ExplorerManager em) { super(node, new DataResultFilterChildren(node, em)); this.sourceEm = em; + this.innerNode = node; + } + + public Node getInnerNode() { + return innerNode; } /** @@ -156,6 +162,7 @@ public class DataResultFilterNode extends FilterNode { private DataResultFilterNode(Node node, ExplorerManager em, boolean filterKnown, boolean filterSlack) { super(node, new DataResultFilterChildren(node, em, filterKnown, filterSlack)); this.sourceEm = em; + this.innerNode = node; } /** From 9aae3b4a1cf91487d7a2bef8e08f0ac24313c501 Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Wed, 20 Jun 2018 18:03:35 -0700 Subject: [PATCH 03/40] Cleanup, and polish to minimal changeset. Unused callables. --- .../commonfilesearch/CommonFilesMetadata.java | 12 +--- .../commonfilesearch/CommonFilesNode.java | 21 +----- .../commonfilesearch/CommonFilesPanel.java | 5 +- .../autopsy/commonfilesearch/Md5Metadata.java | 14 +--- .../commonfilesearch/Md5MetadataList.java | 29 ++++---- .../corecomponents/DataResultViewerTable.java | 58 ++------------- .../DelayedLoadChildNodesOnTreeExpansion.java | 70 +++++++++++++++++++ .../MultiLayerTableFilterNode.java | 9 ++- .../autopsy/datamodel/InstanceCountNode.java | 46 +----------- .../sleuthkit/autopsy/datamodel/Md5Node.java | 27 +------ .../directorytree/DataResultFilterNode.java | 49 +++++++------ 11 files changed, 133 insertions(+), 207 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java index c755b7a12a..90995ca00d 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java @@ -30,7 +30,6 @@ import java.util.Map; final public class CommonFilesMetadata { private final Map metadata; - private final Map hiddenMetaData; /** * Create a metadata object which can be handed off to the node @@ -39,12 +38,7 @@ final public class CommonFilesMetadata { * @param metadata list of Md5Metadata indexed by size of Md5Metadata */ CommonFilesMetadata(Map metadata){ - Map tempMetadata = new HashMap<>(); - for(Integer key : metadata.keySet()) { - tempMetadata.put(key, new Md5MetadataList()); - } - this.metadata = tempMetadata; - this.hiddenMetaData = metadata; + this.metadata = metadata; } /** @@ -59,10 +53,6 @@ final public class CommonFilesMetadata { Md5MetadataList getMetadataForMd5(Integer instanceCount) { return this.metadata.get(instanceCount); } - - public void displayHiddenMetadata() { - this.metadata.putAll(this.hiddenMetaData); - } public Map getMetadata() { return Collections.unmodifiableMap(this.metadata); diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java index 2c72b0c804..07074d1885 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java @@ -35,12 +35,8 @@ import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; */ final public class CommonFilesNode extends DisplayableItemNode { - private final CommonFilesMetadata metadataList; - CommonFilesNode(CommonFilesMetadata metadataList) { super(Children.create(new InstanceCountNodeFactory(metadataList), true)); - this.metadataList = metadataList; - this.refresh(); } @NbBundle.Messages({ @@ -64,16 +60,8 @@ final public class CommonFilesNode extends DisplayableItemNode { public String getItemType() { return getClass().getName(); } - - public void setCleanRefreshNeeded(boolean b) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - - public void refresh() { - metadataList.displayHiddenMetadata(); - } - static class InstanceCountNodeFactory extends ChildFactory implements PropertyChangeListener { + static class InstanceCountNodeFactory extends ChildFactory { private final CommonFilesMetadata metadata; @@ -92,12 +80,5 @@ final public class CommonFilesNode extends DisplayableItemNode { Md5MetadataList md5Metadata = this.metadata.getMetadataForMd5(instanceCount); return new InstanceCountNode(instanceCount, md5Metadata); } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals("ADD") || evt.getPropertyName().equals("REMOVE")) { - this.refresh(true); - } - } } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java index 8b3004637a..2bb9bbdd1e 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java @@ -34,6 +34,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable; +import org.sleuthkit.autopsy.corecomponents.DelayedLoadChildNodesOnTreeExpansion; import org.sleuthkit.autopsy.corecomponents.MultiLayerTableFilterNode; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; @@ -242,12 +243,12 @@ public final class CommonFilesPanel extends javax.swing.JPanel { CommonFilesNode commonFilesNode = new CommonFilesNode(metadata); - //TODO this could be enumerating the children!!! + //TODO this could be enumerating the children!!! Instead delay enumeration by dynamically loading nodes with DelayedLoadChildNodesOnTreeExpansion() DataResultFilterNode dataResultFilterNode = new DataResultFilterNode(commonFilesNode, ExplorerManager.find(CommonFilesPanel.this)); MultiLayerTableFilterNode tableFilterWithDescendantsNode = new MultiLayerTableFilterNode(dataResultFilterNode, 3); - DataResultViewerTable table = new DataResultViewerTable(true); + DataResultViewerTable table = new DataResultViewerTable(new DelayedLoadChildNodesOnTreeExpansion()); Collection viewers = new ArrayList<>(1); viewers.add(table); diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java index 9e19cce9ae..501a70e09b 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5Metadata.java @@ -19,9 +19,6 @@ */ package org.sleuthkit.autopsy.commonfilesearch; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -35,12 +32,11 @@ final public class Md5Metadata { private final String md5; private final List fileInstances; - private final PropertyChangeSupport pss; Md5Metadata(String md5, List fileInstances){ this.md5 = md5; this.fileInstances = fileInstances; - this.pss = new PropertyChangeSupport(this); + } public String getMd5(){ @@ -70,14 +66,6 @@ final public class Md5Metadata { } return String.join(", ", sources); } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - this.pss.addPropertyChangeListener(listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - this.pss.removePropertyChangeListener(listener); - } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5MetadataList.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5MetadataList.java index d24df739eb..5d297b8cd0 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5MetadataList.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5MetadataList.java @@ -24,26 +24,27 @@ import java.util.Collections; import java.util.List; /** - * Utility and wrapper model around data required for Common Files Search results. - * Subclass this to implement different selections of files from the case. + * Utility and wrapper model around data required for Common Files Search + * results. Subclass this to implement different selections of files from the + * case. */ final public class Md5MetadataList { - + private final List metadataList; private final List delayedMetadataList; - + /** - * Create a metadata object containing the list of metadata which can be handed off to the node - * factories. - * + * Create a metadata object containing the list of metadata which can be + * handed off to the node factories. + * * @param metadata list of Md5Metadata indexed by size of Md5Metadata */ - Md5MetadataList(List metadata){ + Md5MetadataList(List metadata) { this.metadataList = new ArrayList(); this.delayedMetadataList = metadata; } - - Md5MetadataList(){ + + Md5MetadataList() { this.metadataList = new ArrayList<>(); this.delayedMetadataList = new ArrayList<>(); } @@ -51,11 +52,13 @@ final public class Md5MetadataList { public List getMetadataList() { return Collections.unmodifiableList(this.metadataList); } - + public void displayDelayedMetadata() { - this.metadataList.addAll(this.delayedMetadataList); + if(metadataList.isEmpty()) { + this.metadataList.addAll(this.delayedMetadataList); + } } - + public void addMetadataToList(Md5Metadata metadata) { delayedMetadataList.add(metadata); } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 732347d85d..9863a98174 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -114,64 +114,14 @@ public final class DataResultViewerTable extends AbstractDataResultViewer { * top component to connect the lookups of the nodes displayed in the * OutlineView to the actions global context. The explorer manager will be * discovered at runtime. + * @param listener */ - public DataResultViewerTable(boolean addListener) { + public DataResultViewerTable(TreeExpansionListener listener) { this(null, Bundle.DataResultViewerTable_title()); - outlineView.addTreeExpansionListener(new LazyLoadChildNodesOnTreeExpansion()); + outlineView.addTreeExpansionListener(listener); } - /** - * A tree expansion listener that will trigger a recreation of childs through its - * child factory on re-expansion of a node (causes to recreate the ChildFactory for - * this purpose.). - */ - private class LazyLoadChildNodesOnTreeExpansion implements TreeExpansionListener { - - /** - * A flag for avoiding endless recursion inside the expansion listener that could - * trigger collapsing and (re-)expanding nodes again. - */ - private boolean inRecursion = false; - - @Override - public synchronized void treeCollapsed(final TreeExpansionEvent event) { - Node eventNode = Visualizer.findNode(event.getPath().getLastPathComponent()); - if (!inRecursion && eventNode instanceof CommonFilesNode) { // avoid endless - // recursion - final CommonFilesNode node = (CommonFilesNode) eventNode; - node.setCleanRefreshNeeded(true); - } - } - - @Override - public synchronized void treeExpanded(final TreeExpansionEvent event) { - Node eventNode = Visualizer.findNode(event.getPath().getLastPathComponent()); - if (!inRecursion && eventNode instanceof MultiLayerTableFilterNode) { - final MultiLayerTableFilterNode node = (MultiLayerTableFilterNode) eventNode; - Node innerNode = node.getInnerNode(); - if(innerNode instanceof DataResultFilterNode) { - - final DataResultFilterNode drNode = (DataResultFilterNode) innerNode; - Node innerInnerNode = drNode.getInnerNode(); - if(innerInnerNode instanceof InstanceCountNode) { - final InstanceCountNode cfNode = (InstanceCountNode) innerInnerNode; - cfNode.refresh(); - }} - - if (!outlineView.isExpanded(node)) { - // Seems that the refresh caused to collapse, re-expand again and - // avoid recursion in this listener! - inRecursion = true; - try { - outlineView.expandNode(node); - } finally { - inRecursion = false; - } - } - } - - } - } + /** * Constructs a tabular result viewer that displays the children of a given diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java new file mode 100644 index 0000000000..bdc7e4b7c7 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java @@ -0,0 +1,70 @@ +/* + * + * Autopsy Forensic Browser + * + * Copyright 2018 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.corecomponents; + +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import org.openide.explorer.view.Visualizer; +import org.openide.nodes.Node; + +/** + * A tree expansion listener that will trigger a recreation of childs through + * its child factory on re-expansion of a node (causes to recreate the + * ChildFactory for this purpose.). + */ +public final class DelayedLoadChildNodesOnTreeExpansion implements TreeExpansionListener { + + /** + * A flag for avoiding endless recursion inside the expansion listener that + * could trigger collapsing and (re-)expanding nodes again. + * @param event + */ + //private boolean inRecursion = false; + + @Override + public synchronized void treeCollapsed(final TreeExpansionEvent event) { + Node eventNode = Visualizer.findNode(event.getPath().getLastPathComponent()); +// if (eventNode instanceof CommonFilesNode) { // avoid endless //!inRecursion && +// // recursion +// final CommonFilesNode node = (CommonFilesNode) eventNode; +// node.setCleanRefreshNeeded(true); +// } + } + + @Override + public synchronized void treeExpanded(final TreeExpansionEvent event) { + Node eventNode = Visualizer.findNode(event.getPath().getLastPathComponent()); + if (eventNode instanceof MultiLayerTableFilterNode) { //!inRecursion && + final MultiLayerTableFilterNode node = (MultiLayerTableFilterNode) eventNode; + node.refresh(); +// if (!outlineView.isExpanded(node)) { +// // Seems that the refresh caused to collapse, re-expand again and +// // avoid recursion in this listener! +// inRecursion = true; +// try { +// outlineView.expandNode(node); +// } finally { +// inRecursion = false; +// } +// } + } + + } +} diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiLayerTableFilterNode.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiLayerTableFilterNode.java index b83d045c91..b5399ca2bc 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiLayerTableFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiLayerTableFilterNode.java @@ -52,9 +52,12 @@ public class MultiLayerTableFilterNode extends FilterNode implements TableFilter this.forceUseWrappedDisplayName = true; this.innerNode = node; } - - public Node getInnerNode() { - return innerNode; + + void refresh() { + if (innerNode instanceof DataResultFilterNode) { + final DataResultFilterNode drNode = (DataResultFilterNode) innerNode; + drNode.refresh(); + } } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java index cf86f7a613..7a092a91da 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java @@ -19,9 +19,6 @@ */ package org.sleuthkit.autopsy.datamodel; -import java.beans.PropertyChangeEvent; -import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -29,13 +26,8 @@ import java.util.concurrent.Callable; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; 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.nodes.Sheet; import org.openide.util.NbBundle; -import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.commonfilesearch.Md5Metadata; import org.sleuthkit.autopsy.commonfilesearch.Md5MetadataList; @@ -48,7 +40,7 @@ final public class InstanceCountNode extends DisplayableItemNode { final private Md5MetadataList metadataList; public InstanceCountNode(int instanceCount, Md5MetadataList md5Metadata) { - super(Children.createLazy(new InstanceCountChildCallable(md5Metadata)), Lookups.singleton(instanceCount)); + super(Children.create(new Md5NodeFactory(md5Metadata.getMetadataList()), true)); //Children.createLazy(new InstanceCountChildCallable(md5Metadata)), Lookups.singleton(instanceCount)); this.instanceCount = instanceCount; this.metadataList = md5Metadata; @@ -71,12 +63,6 @@ final public class InstanceCountNode extends DisplayableItemNode { } } - - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals("ADD")) { - setChildren(Children.create(new Md5NodeFactory(metadataList.getMetadataList()), false)); - } - } int getInstanceCount() { return this.instanceCount; @@ -95,10 +81,6 @@ final public class InstanceCountNode extends DisplayableItemNode { public boolean isLeafTypeNode() { return false; } - - public void setCleanRefreshNeeded(boolean b) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } public void refresh() { metadataList.displayDelayedMetadata(); @@ -166,7 +148,7 @@ final public class InstanceCountNode extends DisplayableItemNode { * ChildFactory which builds CommonFileParentNodes from the * CommonFilesMetaaData models. */ - static class Md5NodeFactory extends ChildFactory implements NodeListener { + static class Md5NodeFactory extends ChildFactory { /** * List of models, each of which is a parent node matching a single md5, @@ -188,30 +170,6 @@ final public class InstanceCountNode extends DisplayableItemNode { list.addAll(metadata); return true; } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals("ADD") || evt.getPropertyName().equals("REMOVE")) { - this.refresh(true); - } - } - - @Override - public void childrenAdded(NodeMemberEvent nme) { - } - @Override - public void childrenRemoved(NodeMemberEvent nme) { - } - - @Override - public void childrenReordered(NodeReorderEvent nre) { - - } - - @Override - public void nodeDestroyed(NodeEvent ne) { - - } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java b/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java index fc06be3d77..47cd19e9af 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java @@ -19,8 +19,6 @@ */ package org.sleuthkit.autopsy.datamodel; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -31,7 +29,6 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; -import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.commonfilesearch.FileInstanceMetadata; @@ -47,24 +44,21 @@ import org.sleuthkit.datamodel.TskCoreException; * the MD5 of the matched files, the data sources those files were found within, * and a count of the instances represented by the md5. */ -public class Md5Node extends DisplayableItemNode implements PropertyChangeListener { +public class Md5Node extends DisplayableItemNode { private static final Logger LOGGER = Logger.getLogger(Md5Node.class.getName()); private final String md5Hash; private final int commonFileCount; private final String dataSources; - private final Md5Metadata metaData; public Md5Node(Md5Metadata data) { - super(Children.createLazy(new Md5ChildCallable(data)), Lookups.singleton(data.getMd5())); + super(Children.create(new FileInstanceNodeFactory(data), true)); //Children.createLazy(new Md5ChildCallable(data)), Lookups.singleton(data.getMd5())); this.commonFileCount = data.size(); this.dataSources = String.join(", ", data.getDataSources()); this.md5Hash = data.getMd5(); - this.metaData = data; - metaData.addPropertyChangeListener(this); this.setDisplayName(this.md5Hash); } @@ -88,13 +82,6 @@ public class Md5Node extends DisplayableItemNode implements PropertyChangeListen } } } - - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals("ADD")) { - setChildren(Children.create(new FileInstanceNodeFactory(metaData), false)); - } - } - int getCommonFileCount() { return this.commonFileCount; } @@ -158,13 +145,12 @@ public class Md5Node extends DisplayableItemNode implements PropertyChangeListen /** * Child generator for FileInstanceNode of Md5Node. */ - static class FileInstanceNodeFactory extends ChildFactory implements PropertyChangeListener { + static class FileInstanceNodeFactory extends ChildFactory { private final Md5Metadata descendants; FileInstanceNodeFactory(Md5Metadata descendants) { this.descendants = descendants; - descendants.addPropertyChangeListener(this); } @Override @@ -186,13 +172,6 @@ public class Md5Node extends DisplayableItemNode implements PropertyChangeListen list.addAll(this.descendants.getMetadata()); return true; } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals("ADD") || evt.getPropertyName().equals("REMOVE")) { - this.refresh(true); - } - } } @NbBundle.Messages({ diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index a9e841abb3..ed0cf41bae 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -133,17 +133,20 @@ public class DataResultFilterNode extends FilterNode { * wrapped node and may filter out some of its children. * * @param node The node to wrap. - * @param em The ExplorerManager for the component that is creating the - * node. + * @param em The ExplorerManager for the component that is creating the + * node. */ public DataResultFilterNode(Node node, ExplorerManager em) { super(node, new DataResultFilterChildren(node, em)); this.sourceEm = em; this.innerNode = node; } - - public Node getInnerNode() { - return innerNode; + + public void refresh() { + if (innerNode instanceof InstanceCountNode) { + final InstanceCountNode cfNode = (InstanceCountNode) innerNode; + cfNode.refresh(); + } } /** @@ -151,18 +154,18 @@ public class DataResultFilterNode extends FilterNode { * result viewers. The wrapper node defines the actions associated with the * wrapped node and may filter out some of its children. * - * @param node The node to wrap. - * @param em The ExplorerManager for the component that is creating - * the node. + * @param node The node to wrap. + * @param em The ExplorerManager for the component that is creating the + * node. * @param filterKnown Whether or not to filter out children that represent - * known files. + * known files. * @param filterSlack Whether or not to filter out children that represent - * virtual slack space files. + * virtual slack space files. */ private DataResultFilterNode(Node node, ExplorerManager em, boolean filterKnown, boolean filterSlack) { super(node, new DataResultFilterChildren(node, em, filterKnown, filterSlack)); this.sourceEm = em; - this.innerNode = node; + this.innerNode = node; } /** @@ -268,7 +271,7 @@ public class DataResultFilterNode extends FilterNode { * selected. * * @return The child node selection information, or null if no child should - * be selected. + * be selected. */ public NodeSelectionInfo getChildNodeSelectionInfo() { if (getOriginal() instanceof DisplayableItemNode) { @@ -397,14 +400,14 @@ public class DataResultFilterNode extends FilterNode { NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewFileInDir.text"), c)); } // action to go to the source file of the artifact - // action to go to the source file of the artifact + // action to go to the source file of the artifact Content fileContent = ban.getLookup().lookup(AbstractFile.class); if (fileContent == null) { Content content = ban.getLookup().lookup(Content.class); actionsList.add(new ViewContextAction("View Source Content in Directory", content)); } else { actionsList.add(new ViewContextAction( - NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewSrcFileInDir.text"), ban)); + NbBundle.getMessage(this.getClass(), "DataResultFilterNode.action.viewSrcFileInDir.text"), ban)); } } Content c = ban.getLookup().lookup(File.class); @@ -537,21 +540,21 @@ public class DataResultFilterNode extends FilterNode { */ private class GetPreferredActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default { - @Override - public AbstractAction visit(InstanceCountNode icn){ - return new NoAction(); - } - @Override - public AbstractAction visit(Md5Node md5n){ + public AbstractAction visit(InstanceCountNode icn) { return new NoAction(); } - + @Override - public AbstractAction visit(FileInstanceNode fin){ + public AbstractAction visit(Md5Node md5n) { return new NoAction(); } - + + @Override + public AbstractAction visit(FileInstanceNode fin) { + return new NoAction(); + } + @Override public AbstractAction visit(BlackboardArtifactNode ban) { BlackboardArtifact artifact = ban.getArtifact(); From 629f00980ea44ffb6ae2d7319c62effb73231b26 Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Wed, 20 Jun 2018 18:05:09 -0700 Subject: [PATCH 04/40] Remove callables. Format files. --- .../commonfilesearch/CommonFilesNode.java | 20 ++++----- .../commonfilesearch/Md5MetadataList.java | 4 +- .../autopsy/datamodel/InstanceCountNode.java | 38 +++++------------ .../sleuthkit/autopsy/datamodel/Md5Node.java | 41 +++++-------------- 4 files changed, 31 insertions(+), 72 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java index 07074d1885..67c8c096bc 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java @@ -18,8 +18,6 @@ */ package org.sleuthkit.autopsy.commonfilesearch; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; import org.sleuthkit.autopsy.datamodel.InstanceCountNode; import java.util.List; import org.openide.nodes.ChildFactory; @@ -34,7 +32,7 @@ import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; * results in the top right pane. Calls Md5NodeFactory. */ final public class CommonFilesNode extends DisplayableItemNode { - + CommonFilesNode(CommonFilesMetadata metadataList) { super(Children.create(new InstanceCountNodeFactory(metadataList), true)); } @@ -60,25 +58,25 @@ final public class CommonFilesNode extends DisplayableItemNode { public String getItemType() { return getClass().getName(); } - + static class InstanceCountNodeFactory extends ChildFactory { private final CommonFilesMetadata metadata; - - InstanceCountNodeFactory(CommonFilesMetadata metadata){ + + InstanceCountNodeFactory(CommonFilesMetadata metadata) { this.metadata = metadata; } - + @Override protected boolean createKeys(List list) { list.addAll(this.metadata.getMetadata().keySet()); return true; } - + @Override - protected Node createNodeForKey(Integer instanceCount){ - Md5MetadataList md5Metadata = this.metadata.getMetadataForMd5(instanceCount); + protected Node createNodeForKey(Integer instanceCount) { + Md5MetadataList md5Metadata = this.metadata.getMetadataForMd5(instanceCount); return new InstanceCountNode(instanceCount, md5Metadata); - } + } } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5MetadataList.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5MetadataList.java index 5d297b8cd0..3e57ec7d55 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5MetadataList.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Md5MetadataList.java @@ -40,7 +40,7 @@ final public class Md5MetadataList { * @param metadata list of Md5Metadata indexed by size of Md5Metadata */ Md5MetadataList(List metadata) { - this.metadataList = new ArrayList(); + this.metadataList = new ArrayList<>(); this.delayedMetadataList = metadata; } @@ -54,7 +54,7 @@ final public class Md5MetadataList { } public void displayDelayedMetadata() { - if(metadataList.isEmpty()) { + if (metadataList.isEmpty()) { this.metadataList.addAll(this.delayedMetadataList); } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java index 7a092a91da..9283de6026 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java @@ -22,7 +22,6 @@ package org.sleuthkit.autopsy.datamodel; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.Callable; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; @@ -44,25 +43,9 @@ final public class InstanceCountNode extends DisplayableItemNode { this.instanceCount = instanceCount; this.metadataList = md5Metadata; - + this.setDisplayName(Integer.toString(instanceCount)); } - - /** - * Callable wrapper to further delay lazy ChildFactory creation - * and createNodes() call once lazy loading is functional. - */ - private static class InstanceCountChildCallable implements Callable { - private final Md5MetadataList key; - private InstanceCountChildCallable(Md5MetadataList key) { - this.key = key; - } - @Override - public Children call() throws Exception { - return Children.create(new Md5NodeFactory(key.getMetadataList()), true); - - } - } int getInstanceCount() { return this.instanceCount; @@ -124,22 +107,22 @@ final public class InstanceCountNode extends DisplayableItemNode { static private void fillPropertyMap(Map map, InstanceCountNode node) { map.put(InstanceCountNodePropertyType.Match.toString(), node.getInstanceCount()); } - + @NbBundle.Messages({ "InstanceCountNodeProeprtyType.matchCountColLbl1=Match" }) - public enum InstanceCountNodePropertyType{ - + public enum InstanceCountNodePropertyType { + Match(Bundle.InstanceCountNodeProeprtyType_matchCountColLbl1()); - + final private String displayString; - - private InstanceCountNodePropertyType(String displayName){ + + private InstanceCountNodePropertyType(String displayName) { this.displayString = displayName; } - + @Override - public String toString(){ + public String toString() { return this.displayString; } } @@ -171,6 +154,5 @@ final public class InstanceCountNode extends DisplayableItemNode { return true; } - } -} \ No newline at end of file +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java b/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java index 47cd19e9af..9ebc81a076 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java @@ -22,7 +22,6 @@ package org.sleuthkit.autopsy.datamodel; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.Callable; import java.util.logging.Level; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; @@ -40,14 +39,14 @@ import org.sleuthkit.datamodel.TskCoreException; /** * Represents a common files match - two or more files which appear to be the - * same file and appear as children of this node. This node will simply contain + * same file and appear as children of this node. This node will simply contain * the MD5 of the matched files, the data sources those files were found within, * and a count of the instances represented by the md5. */ public class Md5Node extends DisplayableItemNode { - - private static final Logger LOGGER = Logger.getLogger(Md5Node.class.getName()); - + + private static final Logger LOGGER = Logger.getLogger(Md5Node.class.getName()); + private final String md5Hash; private final int commonFileCount; private final String dataSources; @@ -55,33 +54,12 @@ public class Md5Node extends DisplayableItemNode { public Md5Node(Md5Metadata data) { super(Children.create(new FileInstanceNodeFactory(data), true)); //Children.createLazy(new Md5ChildCallable(data)), Lookups.singleton(data.getMd5())); - this.commonFileCount = data.size(); this.dataSources = String.join(", ", data.getDataSources()); this.md5Hash = data.getMd5(); this.setDisplayName(this.md5Hash); } - - /** - * Callable wrapper to further delay lazy ChildFactory creation - * and createNodes() call once lazy loading is functional. - */ - private static class Md5ChildCallable implements Callable { - private final Md5Metadata key; - private Md5ChildCallable(Md5Metadata key) { - this.key = key; - } - @Override - public Children call() throws Exception { - //Check that the key has children, - //if it doesn't have children, return a leaf: - if (key.getMetadata().isEmpty()) { - return Children.LEAF; - } else { - return Children.create(new FileInstanceNodeFactory(key), true); - } - } - } + int getCommonFileCount() { return this.commonFileCount; } @@ -143,7 +121,8 @@ public class Md5Node extends DisplayableItemNode { } /** - * Child generator for FileInstanceNode of Md5Node. + * Child generator for FileInstanceNode of + * Md5Node. */ static class FileInstanceNodeFactory extends ChildFactory { @@ -159,7 +138,7 @@ public class Md5Node extends DisplayableItemNode { Case currentCase = Case.getCurrentCaseThrows(); SleuthkitCase tskDb = currentCase.getSleuthkitCase(); AbstractFile abstractFile = tskDb.findAllFilesWhere(String.format("obj_id in (%s)", file.getObjectId())).get(0); - + return new FileInstanceNode(abstractFile, file.getDataSourceName()); } catch (NoCurrentCaseException | TskCoreException ex) { LOGGER.log(Level.SEVERE, String.format("Unable to create node for file with obj_id: %s.", new Object[]{file.getObjectId()}), ex); @@ -168,7 +147,7 @@ public class Md5Node extends DisplayableItemNode { } @Override - protected boolean createKeys(List list) { + protected boolean createKeys(List list) { list.addAll(this.descendants.getMetadata()); return true; } @@ -195,5 +174,5 @@ public class Md5Node extends DisplayableItemNode { return this.displayString; } } - + } From 94ad39dd5900dfb577238faefc3c35cdeb8f1bdb Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Wed, 20 Jun 2018 18:12:59 -0700 Subject: [PATCH 05/40] Remove unused imports. --- .../autopsy/corecomponents/DataResultViewerTable.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 9863a98174..a9b7beaec2 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -44,7 +44,6 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; -import javax.swing.event.TreeExpansionEvent; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; @@ -56,7 +55,6 @@ import org.netbeans.swing.outline.DefaultOutlineModel; import org.netbeans.swing.outline.Outline; import org.openide.explorer.ExplorerManager; import org.openide.explorer.view.OutlineView; -import org.openide.explorer.view.Visualizer; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Node; @@ -64,13 +62,10 @@ import org.openide.nodes.Node.Property; import org.openide.util.NbBundle; import org.openide.util.NbPreferences; import org.openide.util.lookup.ServiceProvider; -import org.sleuthkit.autopsy.commonfilesearch.CommonFilesNode; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; -import org.sleuthkit.autopsy.datamodel.InstanceCountNode; import org.sleuthkit.autopsy.datamodel.NodeSelectionInfo; -import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; /** * A tabular result viewer that displays the children of the given root node @@ -200,6 +195,7 @@ public final class DataResultViewerTable extends AbstractDataResultViewer { /** * Gets the title of this tabular result viewer. + * @return */ @Override @NbBundle.Messages("DataResultViewerTable.title=Table") From 332a174b0a63b5022f2e6d981c59117b94c56b72 Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Wed, 20 Jun 2018 19:49:28 -0700 Subject: [PATCH 06/40] remove excess comments. --- .../DelayedLoadChildNodesOnTreeExpansion.java | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java index bdc7e4b7c7..8dd71af77d 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java @@ -36,16 +36,10 @@ public final class DelayedLoadChildNodesOnTreeExpansion implements TreeExpansion * could trigger collapsing and (re-)expanding nodes again. * @param event */ - //private boolean inRecursion = false; @Override public synchronized void treeCollapsed(final TreeExpansionEvent event) { - Node eventNode = Visualizer.findNode(event.getPath().getLastPathComponent()); -// if (eventNode instanceof CommonFilesNode) { // avoid endless //!inRecursion && -// // recursion -// final CommonFilesNode node = (CommonFilesNode) eventNode; -// node.setCleanRefreshNeeded(true); -// } + } @Override @@ -54,16 +48,6 @@ public final class DelayedLoadChildNodesOnTreeExpansion implements TreeExpansion if (eventNode instanceof MultiLayerTableFilterNode) { //!inRecursion && final MultiLayerTableFilterNode node = (MultiLayerTableFilterNode) eventNode; node.refresh(); -// if (!outlineView.isExpanded(node)) { -// // Seems that the refresh caused to collapse, re-expand again and -// // avoid recursion in this listener! -// inRecursion = true; -// try { -// outlineView.expandNode(node); -// } finally { -// inRecursion = false; -// } -// } } } From 987eb9a63b6272c75eb0e4438963b742c9408963 Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Thu, 21 Jun 2018 11:04:10 -0700 Subject: [PATCH 07/40] Remove unused, commented out code. --- .../sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java | 1 - Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java | 1 - 2 files changed, 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java index 90995ca00d..0341662ffa 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.commonfilesearch; import java.util.Collections; -import java.util.HashMap; import java.util.Map; /** diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java index 9283de6026..97cd1b112d 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java @@ -67,7 +67,6 @@ final public class InstanceCountNode extends DisplayableItemNode { public void refresh() { metadataList.displayDelayedMetadata(); - //firePropertyChange(PROP_NAME, this, this); setChildren(Children.create(new Md5NodeFactory(metadataList.getMetadataList()), false)); } From 5281c381523c63f6e90fe5bb34514795930bc452 Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Thu, 21 Jun 2018 11:06:11 -0700 Subject: [PATCH 08/40] more comment removal cleanup. --- Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java | 2 +- Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java index 97cd1b112d..3389284d20 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/InstanceCountNode.java @@ -39,7 +39,7 @@ final public class InstanceCountNode extends DisplayableItemNode { final private Md5MetadataList metadataList; public InstanceCountNode(int instanceCount, Md5MetadataList md5Metadata) { - super(Children.create(new Md5NodeFactory(md5Metadata.getMetadataList()), true)); //Children.createLazy(new InstanceCountChildCallable(md5Metadata)), Lookups.singleton(instanceCount)); + super(Children.create(new Md5NodeFactory(md5Metadata.getMetadataList()), true)); this.instanceCount = instanceCount; this.metadataList = md5Metadata; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java b/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java index 9ebc81a076..b5092432a4 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Md5Node.java @@ -52,7 +52,7 @@ public class Md5Node extends DisplayableItemNode { private final String dataSources; public Md5Node(Md5Metadata data) { - super(Children.create(new FileInstanceNodeFactory(data), true)); //Children.createLazy(new Md5ChildCallable(data)), Lookups.singleton(data.getMd5())); + super(Children.create(new FileInstanceNodeFactory(data), true)); this.commonFileCount = data.size(); this.dataSources = String.join(", ", data.getDataSources()); From 80373241894b0354f61bc665d3002badbe65d3d5 Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Thu, 21 Jun 2018 15:12:53 -0700 Subject: [PATCH 09/40] Swap reflection for lookups instead. --- .../corecomponents/MultiLayerTableFilterNode.java | 12 +++++------- .../autopsy/directorytree/DataResultFilterNode.java | 9 +++------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiLayerTableFilterNode.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiLayerTableFilterNode.java index b5399ca2bc..53f705b7b4 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiLayerTableFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiLayerTableFilterNode.java @@ -36,7 +36,7 @@ public class MultiLayerTableFilterNode extends FilterNode implements TableFilter private final boolean createChildren; private final boolean forceUseWrappedDisplayName; private static final String columnOrderKey = "NONE"; - private final Node innerNode; + //private final Node innerNode; /** * Constructs a filter node that generates children using @@ -50,14 +50,12 @@ public class MultiLayerTableFilterNode extends FilterNode implements TableFilter super(node, TableFilterChildrenWithDescendants.createInstance(node, true, childLayerDepth), Lookups.proxy(node)); this.createChildren = true; this.forceUseWrappedDisplayName = true; - this.innerNode = node; + //this.innerNode = node; } - void refresh() { - if (innerNode instanceof DataResultFilterNode) { - final DataResultFilterNode drNode = (DataResultFilterNode) innerNode; - drNode.refresh(); - } + void refresh() { + DataResultFilterNode innerNode = getLookup().lookup(DataResultFilterNode.class); + innerNode.refresh(); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index ed0cf41bae..00da91813c 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -98,7 +98,6 @@ public class DataResultFilterNode extends FilterNode { private static boolean filterKnownFromViews = UserPreferences.hideKnownFilesInViewsTree(); private static boolean filterSlackFromDataSources = UserPreferences.hideSlackFilesInDataSourcesTree(); private static boolean filterSlackFromViews = UserPreferences.hideSlackFilesInViewsTree(); - private Node innerNode; static { UserPreferences.addChangeListener(new PreferenceChangeListener() { @@ -139,13 +138,12 @@ public class DataResultFilterNode extends FilterNode { public DataResultFilterNode(Node node, ExplorerManager em) { super(node, new DataResultFilterChildren(node, em)); this.sourceEm = em; - this.innerNode = node; } public void refresh() { - if (innerNode instanceof InstanceCountNode) { - final InstanceCountNode cfNode = (InstanceCountNode) innerNode; - cfNode.refresh(); + if (getOriginal() instanceof InstanceCountNode) { + InstanceCountNode innerNode = getLookup().lookup(InstanceCountNode.class); + innerNode.refresh(); } } @@ -165,7 +163,6 @@ public class DataResultFilterNode extends FilterNode { private DataResultFilterNode(Node node, ExplorerManager em, boolean filterKnown, boolean filterSlack) { super(node, new DataResultFilterChildren(node, em, filterKnown, filterSlack)); this.sourceEm = em; - this.innerNode = node; } /** From 4d3fc1f23d5748b914afd4ac0c2f284b82e9f09a Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Mon, 6 Aug 2018 14:10:22 -0700 Subject: [PATCH 10/40] Fix instance count --- .../autopsy/commonfilesearch/CommonAttributeValueList.java | 4 ++++ .../sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValueList.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValueList.java index 6f9d7d796e..f86f4c23ff 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValueList.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValueList.java @@ -52,6 +52,10 @@ final public class CommonAttributeValueList { public List getMetadataList() { return Collections.unmodifiableList(this.metadataList); } + + public int getCommonAttributeListSize() { + return this.delayedMetadataList.size(); + } public void displayDelayedMetadata() { if (metadataList.isEmpty()) { diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java index da418c6213..878b51bdbc 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java @@ -57,7 +57,7 @@ final public class InstanceCountNode extends DisplayableItemNode { this.instanceCount = instanceCount; this.attributeValues = attributeValues; - this.setDisplayName(String.format(Bundle.InstanceCountNode_displayName(), Integer.toString(instanceCount), attributeValues.getMetadataList().size())); + this.setDisplayName(String.format(Bundle.InstanceCountNode_displayName(), Integer.toString(instanceCount), attributeValues.getCommonAttributeListSize())); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/fileset-icon-16.png"); //NON-NLS } From 7df29a843c06fab8ede271dfe8dfb45f40a73e50 Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Fri, 10 Aug 2018 11:26:01 -0700 Subject: [PATCH 11/40] Remove comment --- .../corecomponents/DelayedLoadChildNodesOnTreeExpansion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java index dc47eba7cc..a66f4a876a 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java @@ -45,7 +45,7 @@ public final class DelayedLoadChildNodesOnTreeExpansion implements TreeExpansion @Override public synchronized void treeExpanded(final TreeExpansionEvent event) { Node eventNode = Visualizer.findNode(event.getPath().getLastPathComponent()); - if (eventNode instanceof TableFilterNode) { //!inRecursion && + if (eventNode instanceof TableFilterNode) { final TableFilterNode node = (TableFilterNode) eventNode; node.refresh(); } From 948ed2aa00ab9d2a04fa214b82c2a53138fe588f Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Fri, 10 Aug 2018 16:31:55 -0600 Subject: [PATCH 12/40] first pass at filtering results by frequency threshold --- .../CommonAttributeSearchResults.java | 67 +++++++++++++++---- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java index 8ff13e87f1..e404790cb7 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java @@ -22,23 +22,27 @@ package org.sleuthkit.autopsy.commonfilesearch; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; /** * Stores the results from the various types of common attribute searching * Stores results based on how they are currently displayed in the UI */ final public class CommonAttributeSearchResults { - + // maps instance count to list of attribute values. private final Map> instanceCountToAttributeValues; - + /** * Create a values object which can be handed off to the node factories. - * - * @param values list of CommonAttributeValue indexed by size of + * + * @param values list of CommonAttributeValue indexed by size of * CommonAttributeValue */ - CommonAttributeSearchResults(Map> metadata){ + CommonAttributeSearchResults(Map> metadata) { this.instanceCountToAttributeValues = metadata; } @@ -55,25 +59,64 @@ final public class CommonAttributeSearchResults { return this.instanceCountToAttributeValues.get(instanceCount); } - /** - * Get an unmodifiable collection of values, indexed by number of - * grandchildren, which represents the common attributes found in the + /** + * Get an unmodifiable collection of values, indexed by number of + * grandchildren, which represents the common attributes found in the * search. + * * @return map of sizes of children to list of matches - */ -public Map> getMetadata() { + */ + public Map> getMetadata() { + return Collections.unmodifiableMap(this.instanceCountToAttributeValues); + } + + /** + * Get an unmodifiable collection of values, indexed by number of + * grandchildren, which represents the common attributes found in the + * search. + * + * Remove results which are not found in the portion of available data + * sources described by minimumPercentageThreshold. + * + * @return + */ + public Map> getMetadata(int minimumPercentageThreshold) throws EamDbException { + + CorrelationAttribute.Type fileAttributeType = CorrelationAttribute + .getDefaultCorrelationTypes() + .stream() + .filter(t -> t.getId() == CorrelationAttribute.FILES_TYPE_ID) + .findFirst().get(); + + EamDb eamDb = EamDb.getInstance(); + + for(Entry> listOfValues : Collections.unmodifiableMap(this.instanceCountToAttributeValues).entrySet()){ + + Integer key = listOfValues.getKey(); + + for(CommonAttributeValue value : listOfValues.getValue()){ + + int frequencyPercentage = eamDb.getFrequencyPercentage(new CorrelationAttribute(fileAttributeType, value.getValue())); + + if(frequencyPercentage < minimumPercentageThreshold){ + this.instanceCountToAttributeValues.get(key).remove(value); + } + } + } + return Collections.unmodifiableMap(this.instanceCountToAttributeValues); } /** * How many distinct common files exist for this search results? + * * @return number of common files */ public int size() { - + int count = 0; for (List data : this.instanceCountToAttributeValues.values()) { - for(CommonAttributeValue md5 : data){ + for (CommonAttributeValue md5 : data) { count += md5.getInstanceCount(); } } From 08b7e113c92858828382e06911582f24f5844c91 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Wed, 15 Aug 2018 08:07:24 -0600 Subject: [PATCH 13/40] percentagethreshold ui stuff --- .../AbstractCommonAttributeSearcher.java | 2 +- .../AllInterCaseCommonAttributeSearcher.java | 4 +- .../AllIntraCaseCommonAttributeSearcher.java | 4 +- .../commonfilesearch/Bundle.properties | 19 +-- .../CommonAttributePanel.form | 101 +++++++++------ .../CommonAttributePanel.java | 117 ++++++++++++------ .../CommonAttributeSearchResultRootNode.java | 12 +- .../CommonAttributeSearchResults.java | 26 +++- .../InterCaseCommonAttributeSearcher.java | 4 +- .../IntraCaseCommonAttributeSearcher.java | 4 +- ...ingleInterCaseCommonAttributeSearcher.java | 4 +- ...ingleIntraCaseCommonAttributeSearcher.java | 4 +- 12 files changed, 201 insertions(+), 100 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AbstractCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AbstractCommonAttributeSearcher.java index 97456bda04..3742f73562 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AbstractCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AbstractCommonAttributeSearcher.java @@ -43,7 +43,7 @@ public abstract class AbstractCommonAttributeSearcher { private boolean filterByMedia; private boolean filterByDoc; - AbstractCommonAttributeSearcher(Map dataSourceIdMap, boolean filterByMedia, boolean filterByDoc){ + AbstractCommonAttributeSearcher(Map dataSourceIdMap, boolean filterByMedia, boolean filterByDoc, int percentageThreshold){ this.filterByDoc = filterByDoc; this.filterByMedia = filterByMedia; this.dataSourceIdToNameMap = dataSourceIdMap; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllInterCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllInterCaseCommonAttributeSearcher.java index ca436b7809..c12e1dbca6 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllInterCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllInterCaseCommonAttributeSearcher.java @@ -41,8 +41,8 @@ public class AllInterCaseCommonAttributeSearcher extends InterCaseCommonAttribut * broadly categorized as document types * @throws EamDbException */ - public AllInterCaseCommonAttributeSearcher(Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) throws EamDbException { - super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType); + public AllInterCaseCommonAttributeSearcher(Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType, int percentageThreshold) throws EamDbException { + super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType, percentageThreshold); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllIntraCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllIntraCaseCommonAttributeSearcher.java index eed61b0fc1..35a5c70452 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllIntraCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllIntraCaseCommonAttributeSearcher.java @@ -37,8 +37,8 @@ final public class AllIntraCaseCommonAttributeSearcher extends IntraCaseCommonAt * @param filterByMediaMimeType match only on files whose mime types can be broadly categorized as media types * @param filterByDocMimeType match only on files whose mime types can be broadly categorized as document types */ - public AllIntraCaseCommonAttributeSearcher(Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) { - super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType); + public AllIntraCaseCommonAttributeSearcher(Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType, int percentageThreshold) { + super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType, percentageThreshold); } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties index 23598648ea..8864d4a73a 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties @@ -9,13 +9,6 @@ IntraCasePanel.withinDataSourceRadioButton.text=At least one match must appear i IntraCasePanel.selectDataSourceComboBox.actionCommand= InterCasePanel.specificCentralRepoCaseRadio.text=Matches must be from the following Central Repo case: InterCasePanel.anyCentralRepoCaseRadio.text=Matches may be from any Central Repo case -CommonAttributePanel.selectedFileCategoriesButton.toolTipText=Select from the options below... -CommonAttributePanel.selectedFileCategoriesButton.text=Only the selected file types: -CommonAttributePanel.allFileCategoriesRadioButton.toolTipText=No filtering applied to results... -CommonAttributePanel.allFileCategoriesRadioButton.text=All file types -CommonAttributePanel.cancelButton.actionCommand=Cancel -CommonAttributePanel.cancelButton.text=Cancel -CommonAttributePanel.searchButton.text=Search CommonAttributePanel.commonFilesSearchLabel2.text=Scope of Search CommonAttributePanel.intraCaseRadio.text=Within current case CommonAttributePanel.commonFilesSearchLabel1.text=Find common files to correlate data soures or cases. @@ -23,3 +16,15 @@ CommonAttributePanel.errorText.text=In order to search, you must select a file c CommonAttributePanel.categoriesLabel.text=File Types To Include: CommonAttributePanel.documentsCheckbox.text=Documents CommonAttributePanel.pictureVideoCheckbox.text=Pictures and Videos +CommonAttributePanel.selectedFileCategoriesButton.toolTipText=Select from the options below... +CommonAttributePanel.selectedFileCategoriesButton.text=Only the selected file types: +CommonAttributePanel.allFileCategoriesRadioButton.toolTipText=No filtering applied to results... +CommonAttributePanel.allFileCategoriesRadioButton.text=All file types +CommonAttributePanel.cancelButton.actionCommand=Cancel +CommonAttributePanel.cancelButton.text=Cancel +CommonAttributePanel.searchButton.text=Search +CommonAttributePanel.jCheckBox1.text=Hide files found in over +CommonAttributePanel.jLabel1.text=% of data sources in central repository. +CommonAttributePanel.percentageThreshold.text=20 +CommonAttributePanel.jLabel1.text_1=% of data sources in central repository. +CommonAttributePanel.percentageThresholdCheck.text_1=Hide files found in over diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form index c08c3c2d78..4bf83be1da 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form @@ -29,7 +29,7 @@ - + @@ -50,47 +50,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -104,7 +102,9 @@ - + + + @@ -115,19 +115,18 @@ + + + + + + - - - - - - - - + @@ -295,6 +294,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java index bf1765e310..1cf1dbf7ca 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java @@ -80,8 +80,10 @@ public final class CommonAttributePanel extends javax.swing.JDialog { if (CommonAttributePanel.isEamDbAvailable()) { this.setupCases(); + this.enablePercentageOptions(); } else { this.disableIntercaseSearch(); + this.disablePercentageOptions(); } } @@ -157,21 +159,27 @@ public final class CommonAttributePanel extends javax.swing.JDialog { filterByDocuments = true; } } + + int percentageThreshold = 0; + if(CommonAttributePanel.this.percentageThresholdCheck.isSelected()){ + String percentageThresholdAsString = CommonAttributePanel.this.percentageThreshold.getText(); + percentageThreshold = Integer.parseInt(percentageThresholdAsString); + } if (CommonAttributePanel.this.interCaseRadio.isSelected()) { if (caseId == InterCasePanel.NO_CASE_SELECTED) { - builder = new AllInterCaseCommonAttributeSearcher(intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments); + builder = new AllInterCaseCommonAttributeSearcher(intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold); } else { - builder = new SingleInterCaseCommonAttributeSearcher(caseId, intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments); + builder = new SingleInterCaseCommonAttributeSearcher(caseId, intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold); } } else { if (dataSourceId == CommonAttributePanel.NO_DATA_SOURCE_SELECTED) { - builder = new AllIntraCaseCommonAttributeSearcher(intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments); + builder = new AllIntraCaseCommonAttributeSearcher(intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold); setTitleForAllDataSources(); } else { - builder = new SingleIntraCaseCommonAttributeSearcher(dataSourceId, intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments); + builder = new SingleIntraCaseCommonAttributeSearcher(dataSourceId, intraCasePanel.getDataSourceMap(), filterByMedia, filterByDocuments, percentageThreshold); setTitleForSingleSource(dataSourceId); } @@ -405,9 +413,11 @@ public final class CommonAttributePanel extends javax.swing.JDialog { layoutPanel = new java.awt.Panel(); intraCasePanel = new org.sleuthkit.autopsy.commonfilesearch.IntraCasePanel(); interCasePanel = new org.sleuthkit.autopsy.commonfilesearch.InterCasePanel(); + percentageThresholdCheck = new javax.swing.JCheckBox(); + percentageThreshold = new javax.swing.JTextField(); + jLabel1 = new javax.swing.JLabel(); setMinimumSize(new java.awt.Dimension(412, 350)); - setPreferredSize(new java.awt.Dimension(412, 350)); setResizable(false); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosed(java.awt.event.WindowEvent evt) { @@ -503,42 +513,53 @@ public final class CommonAttributePanel extends javax.swing.JDialog { layoutPanel.add(intraCasePanel, "card3"); layoutPanel.add(interCasePanel, "card2"); + org.openide.awt.Mnemonics.setLocalizedText(percentageThresholdCheck, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.percentageThresholdCheck.text_1")); // NOI18N + percentageThresholdCheck.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + percentageThresholdCheckActionPerformed(evt); + } + }); + + percentageThreshold.setText(org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.percentageThreshold.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.jLabel1.text_1")); // NOI18N + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(commonFilesSearchLabel2) + .addComponent(intraCaseRadio) + .addComponent(interCaseRadio) + .addComponent(commonFilesSearchLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(categoriesLabel) + .addComponent(selectedFileCategoriesButton) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(29, 29, 29) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(documentsCheckbox) + .addComponent(pictureVideoCheckbox))) + .addComponent(allFileCategoriesRadioButton) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() + .addGap(10, 10, 10) + .addComponent(layoutPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(percentageThresholdCheck) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(percentageThreshold, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel1)) .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() .addComponent(searchButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(cancelButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(errorText)) - .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(commonFilesSearchLabel2) - .addComponent(intraCaseRadio) - .addComponent(interCaseRadio) - .addComponent(commonFilesSearchLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(categoriesLabel) - .addComponent(selectedFileCategoriesButton))) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(35, 35, 35) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(documentsCheckbox) - .addComponent(pictureVideoCheckbox))) - .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addComponent(allFileCategoriesRadioButton))) + .addComponent(errorText))) .addContainerGap()) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(20, 20, 20) - .addComponent(layoutPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(10, 10, 10))) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -551,7 +572,9 @@ public final class CommonAttributePanel extends javax.swing.JDialog { .addComponent(intraCaseRadio) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(interCaseRadio) - .addGap(79, 79, 79) + .addGap(2, 2, 2) + .addComponent(layoutPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(categoriesLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(selectedFileCategoriesButton) @@ -562,16 +585,16 @@ public final class CommonAttributePanel extends javax.swing.JDialog { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(allFileCategoriesRadioButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(percentageThresholdCheck) + .addComponent(percentageThreshold, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel1)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(searchButton) .addComponent(cancelButton) .addComponent(errorText)) - .addContainerGap()) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() - .addGap(98, 98, 98) - .addComponent(layoutPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(180, 180, 180))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER); @@ -628,6 +651,14 @@ public final class CommonAttributePanel extends javax.swing.JDialog { SwingUtilities.windowForComponent(this).dispose(); }//GEN-LAST:event_formWindowClosed + private void percentageThresholdCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_percentageThresholdCheckActionPerformed + if(this.percentageThresholdCheck.isSelected()){ + + } else { + + } + }//GEN-LAST:event_percentageThresholdCheckActionPerformed + public void handleInterCaseSearchCriteriaChanged() { if (this.areInterCaseSearchCriteriaMet()) { this.searchButton.setEnabled(true); @@ -685,8 +716,11 @@ public final class CommonAttributePanel extends javax.swing.JDialog { private javax.swing.ButtonGroup interIntraButtonGroup; private org.sleuthkit.autopsy.commonfilesearch.IntraCasePanel intraCasePanel; private javax.swing.JRadioButton intraCaseRadio; + private javax.swing.JLabel jLabel1; private javax.swing.JPanel jPanel1; private java.awt.Panel layoutPanel; + private javax.swing.JTextField percentageThreshold; + private javax.swing.JCheckBox percentageThresholdCheck; private javax.swing.JCheckBox pictureVideoCheckbox; private javax.swing.JButton searchButton; private javax.swing.JRadioButton selectedFileCategoriesButton; @@ -717,4 +751,15 @@ public final class CommonAttributePanel extends javax.swing.JDialog { this.errorText.setText(this.interCasePanel.getErrorMessage()); this.errorText.setVisible(true); } + + private void enablePercentageOptions() { + this.percentageThreshold.setEnabled(true); + this.percentageThresholdCheck.setEnabled(true); + this.percentageThresholdCheck.setEnabled(true); + } + + private void disablePercentageOptions() { + this.percentageThreshold.setEnabled(false); + this.percentageThresholdCheck.setEnabled(false); + } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResultRootNode.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResultRootNode.java index 8e33401af7..ef36025d8d 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResultRootNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResultRootNode.java @@ -19,10 +19,14 @@ package org.sleuthkit.autopsy.commonfilesearch; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; @@ -65,6 +69,8 @@ final public class CommonAttributeSearchResultRootNode extends DisplayableItemNo */ static class InstanceCountNodeFactory extends ChildFactory{ + private static final Logger LOGGER = Logger.getLogger(InstanceCountNodeFactory.class.getName()); + private final CommonAttributeSearchResults searchResults; /** @@ -78,7 +84,11 @@ final public class CommonAttributeSearchResultRootNode extends DisplayableItemNo @Override protected boolean createKeys(List list) { - list.addAll(this.searchResults.getMetadata().keySet()); + try { + list.addAll(this.searchResults.getMetadata().keySet()); + } catch (EamDbException ex) { + LOGGER.log(Level.SEVERE, "Unable to create keys.", ex); + } return true; } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java index e404790cb7..35b64e17b2 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java @@ -36,6 +36,8 @@ final public class CommonAttributeSearchResults { // maps instance count to list of attribute values. private final Map> instanceCountToAttributeValues; + private final int percentageThreshold; + /** * Create a values object which can be handed off to the node factories. * @@ -44,6 +46,18 @@ final public class CommonAttributeSearchResults { */ CommonAttributeSearchResults(Map> metadata) { this.instanceCountToAttributeValues = metadata; + this.percentageThreshold = 0; + } + + /** + * Create a values object which can be handed off to the node factories. + * + * @param values list of CommonAttributeValue indexed by size of + * CommonAttributeValue + */ + CommonAttributeSearchResults(Map> metadata, int percentageThreshold) { + this.instanceCountToAttributeValues = metadata; + this.percentageThreshold = percentageThreshold; } /** @@ -52,7 +66,7 @@ final public class CommonAttributeSearchResults { * This is a convenience method - you can also iterate over * getValues(). * - * @param isntanceCound key + * @param instanceCount key * @return list of values which represent matches */ List getAttributeValuesForInstanceCount(Integer instanceCount) { @@ -66,8 +80,12 @@ final public class CommonAttributeSearchResults { * * @return map of sizes of children to list of matches */ - public Map> getMetadata() { - return Collections.unmodifiableMap(this.instanceCountToAttributeValues); + public Map> getMetadata() throws EamDbException { + if(this.percentageThreshold == 0){ + return Collections.unmodifiableMap(this.instanceCountToAttributeValues); + } else { + return this.getMetadata(this.percentageThreshold); + } } /** @@ -80,7 +98,7 @@ final public class CommonAttributeSearchResults { * * @return */ - public Map> getMetadata(int minimumPercentageThreshold) throws EamDbException { + private Map> getMetadata(int minimumPercentageThreshold) throws EamDbException { CorrelationAttribute.Type fileAttributeType = CorrelationAttribute .getDefaultCorrelationTypes() diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCaseCommonAttributeSearcher.java index 2c745b5271..d1bff54c99 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCaseCommonAttributeSearcher.java @@ -43,8 +43,8 @@ abstract class InterCaseCommonAttributeSearcher extends AbstractCommonAttributeS * * @throws EamDbException */ - InterCaseCommonAttributeSearcher(Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) throws EamDbException { - super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType); + InterCaseCommonAttributeSearcher(Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType, int percentageThreshold) throws EamDbException { + super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType, percentageThreshold); dbManager = EamDb.getInstance(); } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCaseCommonAttributeSearcher.java index 172108d5ef..bd26648196 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCaseCommonAttributeSearcher.java @@ -55,8 +55,8 @@ public abstract class IntraCaseCommonAttributeSearcher extends AbstractCommonAtt * @param filterByDocMimeType match only on files whose mime types can be * broadly categorized as document types */ - IntraCaseCommonAttributeSearcher(Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) { - super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType); + IntraCaseCommonAttributeSearcher(Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType, int percentageThreshold) { + super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType, percentageThreshold); } /** diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleInterCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleInterCaseCommonAttributeSearcher.java index 6c06da8b38..9289bd8f90 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleInterCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleInterCaseCommonAttributeSearcher.java @@ -44,8 +44,8 @@ public class SingleInterCaseCommonAttributeSearcher extends InterCaseCommonAttri * @param filterByDocMimeType * @throws EamDbException */ - public SingleInterCaseCommonAttributeSearcher(int correlationCaseId, Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) throws EamDbException { - super(dataSourceIdMap,filterByMediaMimeType, filterByDocMimeType); + public SingleInterCaseCommonAttributeSearcher(int correlationCaseId, Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType, int percentageThreshold) throws EamDbException { + super(dataSourceIdMap,filterByMediaMimeType, filterByDocMimeType, percentageThreshold); this.corrleationCaseId = correlationCaseId; this.correlationCaseName = ""; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleIntraCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleIntraCaseCommonAttributeSearcher.java index 02bd480093..f28f0d0bf0 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleIntraCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleIntraCaseCommonAttributeSearcher.java @@ -41,8 +41,8 @@ final public class SingleIntraCaseCommonAttributeSearcher extends IntraCaseCommo * @param filterByDocMimeType match only on files whose mime types can be * broadly categorized as document types */ - public SingleIntraCaseCommonAttributeSearcher(Long dataSourceId, Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) { - super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType); + public SingleIntraCaseCommonAttributeSearcher(Long dataSourceId, Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType, int percentageThreshold) { + super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType, percentageThreshold); this.selectedDataSourceId = dataSourceId; this.dataSourceName = dataSourceIdMap.get(this.selectedDataSourceId); } From 11b36391916151f7385e5d1a51a09cbe834a1f37 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Thu, 16 Aug 2018 09:23:40 -0600 Subject: [PATCH 14/40] ui error message stuff --- .../CommonAttributePanel.form | 3 ++ .../CommonAttributePanel.java | 32 ++++++++++++++--- .../commonfilesearch/PanelErrorMessages.java | 34 +++++++++++++++++++ .../netbeans/core/startup/Bundle.properties | 2 +- .../core/windows/view/ui/Bundle.properties | 2 +- 5 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/commonfilesearch/PanelErrorMessages.java diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form index 4bf83be1da..30afda0b70 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form @@ -310,6 +310,9 @@ + + + diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java index 1cf1dbf7ca..8e32c072f0 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java @@ -54,13 +54,16 @@ import org.sleuthkit.datamodel.TskCoreException; @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives public final class CommonAttributePanel extends javax.swing.JDialog { + private static final Logger LOGGER = Logger.getLogger(CommonAttributePanel.class.getName()); private static final long serialVersionUID = 1L; - + private static final Long NO_DATA_SOURCE_SELECTED = -1L; - private static final Logger LOGGER = Logger.getLogger(CommonAttributePanel.class.getName()); private boolean pictureViewCheckboxState; + private boolean documentsCheckboxState; + + private int percentageThresholdValue = 20; /** * Creates new form CommonFilesPanel @@ -521,6 +524,11 @@ public final class CommonAttributePanel extends javax.swing.JDialog { }); percentageThreshold.setText(org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.percentageThreshold.text")); // NOI18N + percentageThreshold.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + percentageThresholdActionPerformed(evt); + } + }); org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.jLabel1.text_1")); // NOI18N @@ -653,12 +661,27 @@ public final class CommonAttributePanel extends javax.swing.JDialog { private void percentageThresholdCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_percentageThresholdCheckActionPerformed if(this.percentageThresholdCheck.isSelected()){ + this.percentageThreshold.setEnabled(true); } else { - + this.percentageThreshold.setEnabled(false); } }//GEN-LAST:event_percentageThresholdCheckActionPerformed + private void percentageThresholdActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_percentageThresholdActionPerformed + String percentageString = this.percentageThreshold.getText(); + + Integer percentage; + + try{ + percentage = Integer.parseInt(percentageString); + this.percentageThresholdValue = percentage; + } catch(Exception e){ + this.percentageThresholdValue = -1; + } + + }//GEN-LAST:event_percentageThresholdActionPerformed + public void handleInterCaseSearchCriteriaChanged() { if (this.areInterCaseSearchCriteriaMet()) { this.searchButton.setEnabled(true); @@ -755,11 +778,12 @@ public final class CommonAttributePanel extends javax.swing.JDialog { private void enablePercentageOptions() { this.percentageThreshold.setEnabled(true); this.percentageThresholdCheck.setEnabled(true); - this.percentageThresholdCheck.setEnabled(true); + this.percentageThresholdCheck.setSelected(true); } private void disablePercentageOptions() { this.percentageThreshold.setEnabled(false); this.percentageThresholdCheck.setEnabled(false); + this.percentageThresholdCheck.setSelected(false); } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/PanelErrorMessages.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/PanelErrorMessages.java new file mode 100644 index 0000000000..fb23b9da14 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/PanelErrorMessages.java @@ -0,0 +1,34 @@ +/* + * + * Autopsy Forensic Browser + * + * Copyright 2018 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.commonfilesearch; + +/** + * + * @author bsweeney + */ +class PanelErrorMessages { + + private class ErrorMessage{ + int id; + String message; + boolean showMessage; + } + +} 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 693f4b9f89..af8cf7f30a 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 -#Mon, 25 Jun 2018 17:19:36 -0400 +#Thu, 16 Aug 2018 08:52:27 -0600 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 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 3de464ea54..9f3352a25c 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 -#Mon, 25 Jun 2018 17:19:36 -0400 +#Thu, 16 Aug 2018 08:52:27 -0600 CTL_MainWindow_Title=Autopsy 4.8.0 CTL_MainWindow_Title_No_Project=Autopsy 4.8.0 From adc5e9c53b8beb140ad4dd411168cdc91287daf5 Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Fri, 17 Aug 2018 12:17:33 -0700 Subject: [PATCH 15/40] Fix columns, add swing worker to prevent complete UI lockup on refresh() --- ...monAttributesSearchResultsViewerTable.java | 2 +- .../commonfilesearch/InstanceCountNode.java | 59 ++++++++++++++----- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributesSearchResultsViewerTable.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributesSearchResultsViewerTable.java index 5630c56b89..0e051d5111 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributesSearchResultsViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributesSearchResultsViewerTable.java @@ -56,7 +56,7 @@ public class CommonAttributesSearchResultsViewerTable extends DataResultViewerTa map.put(Bundle.CommonFilesSearchResultsViewerTable_dataSourceColLbl(), 200); map.put(Bundle.CommonFilesSearchResultsViewerTable_hashsetHitsColLbl(), 100); map.put(Bundle.CommonFilesSearchResultsViewerTable_mimeTypeColLbl(), 130); - map.put(Bundle.CommonFilesSearchResultsViewerTable_tagsColLbl1(), 300);; + map.put(Bundle.CommonFilesSearchResultsViewerTable_tagsColLbl1(), 300); COLUMN_WIDTHS = Collections.unmodifiableMap(map); } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java index 878b51bdbc..b662102fc9 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java @@ -19,34 +19,40 @@ */ package org.sleuthkit.autopsy.commonfilesearch; -import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import javax.swing.SwingWorker; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.NodeProperty; /** - * Node used to indicate the number of matches found with the MD5 children - * of this Node. + * Node used to indicate the number of matches found with the MD5 children of + * this Node. */ final public class InstanceCountNode extends DisplayableItemNode { + private static final Logger logger = Logger.getLogger(InstanceCountNode.class.getName()); + final private int instanceCount; final private CommonAttributeValueList attributeValues; /** - * Create a node with the given number of instances, and the given - * selection of metadata. + * Create a node with the given number of instances, and the given selection + * of metadata. + * * @param instanceCount - * @param attributeValues + * @param attributeValues */ @NbBundle.Messages({ "InstanceCountNode.displayName=Files with %s instances (%s)" @@ -56,26 +62,45 @@ final public class InstanceCountNode extends DisplayableItemNode { this.instanceCount = instanceCount; this.attributeValues = attributeValues; - + this.setDisplayName(String.format(Bundle.InstanceCountNode_displayName(), Integer.toString(instanceCount), attributeValues.getCommonAttributeListSize())); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/fileset-icon-16.png"); //NON-NLS } /** * Number of matches found for each of the MD5 children. + * * @return int match count */ int getInstanceCount() { return this.instanceCount; } - + public void refresh() { - attributeValues.displayDelayedMetadata(); - setChildren(Children.create(new CommonAttributeValueNodeFactory(attributeValues.getMetadataList()), false)); + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { + attributeValues.displayDelayedMetadata(); + setChildren(Children.create(new CommonAttributeValueNodeFactory(attributeValues.getMetadataList()), false)); + return null; + } + + @Override + protected void done() { + super.done(); + try { + get(); + } catch (InterruptedException | ExecutionException ex) { + logger.log(Level.SEVERE, "Unexpected exception while loading common search result instances", ex); //NON-NLS + } + } + }.execute(); } /** * Get a list of metadata for the MD5s which are children of this object. + * * @return List */ CommonAttributeValueList getAttributeValues() { @@ -106,14 +131,20 @@ final public class InstanceCountNode extends DisplayableItemNode { sheetSet = Sheet.createPropertiesSet(); sheet.put(sheetSet); } - + final String NO_DESCR = Bundle.InstanceCountNode_createSheet_noDescription(); sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), NO_DESCR, "")); sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_instancesColLbl(), Bundle.CommonFilesSearchResultsViewerTable_instancesColLbl(), NO_DESCR, this.getInstanceCount())); + sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_pathColLbl(), Bundle.CommonFilesSearchResultsViewerTable_pathColLbl(), NO_DESCR, "")); + sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_caseColLbl1(), Bundle.CommonFilesSearchResultsViewerTable_caseColLbl1(), NO_DESCR, "")); + sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_dataSourceColLbl(), Bundle.CommonFilesSearchResultsViewerTable_dataSourceColLbl(), NO_DESCR, "")); + sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_hashsetHitsColLbl(), Bundle.CommonFilesSearchResultsViewerTable_hashsetHitsColLbl(), NO_DESCR, "")); + sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_mimeTypeColLbl(), Bundle.CommonFilesSearchResultsViewerTable_mimeTypeColLbl(), NO_DESCR, "")); + sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_tagsColLbl1(), Bundle.CommonFilesSearchResultsViewerTable_tagsColLbl1(), NO_DESCR, "")); + return sheet; } - /** * ChildFactory which builds CommonFileParentNodes from the * CommonFilesMetaaData models. @@ -143,11 +174,11 @@ final public class InstanceCountNode extends DisplayableItemNode { list.addAll(this.metadata.keySet()); return true; } - + @Override protected Node createNodeForKey(String attributeValue) { CommonAttributeValue md5Metadata = this.metadata.get(attributeValue); return new CommonAttributeValueNode(md5Metadata); } } -} \ No newline at end of file +} From 71d933698188652489a402217ea9cf5cfe6085a5 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Mon, 20 Aug 2018 09:07:55 -0600 Subject: [PATCH 16/40] resize dialog and add checkbox/text field for frequency feature --- .../commonfilesearch/CommonAttributePanel.form | 15 ++++++++++++--- .../commonfilesearch/CommonAttributePanel.java | 7 +++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form index 30afda0b70..f926dfdafa 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form @@ -9,7 +9,10 @@ - + + + + @@ -29,15 +32,21 @@ - + + + + + + + - + diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java index 8e32c072f0..737d33de7d 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java @@ -420,7 +420,8 @@ public final class CommonAttributePanel extends javax.swing.JDialog { percentageThreshold = new javax.swing.JTextField(); jLabel1 = new javax.swing.JLabel(); - setMinimumSize(new java.awt.Dimension(412, 350)); + setMinimumSize(new java.awt.Dimension(412, 375)); + setPreferredSize(new java.awt.Dimension(412, 375)); setResizable(false); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosed(java.awt.event.WindowEvent evt) { @@ -428,7 +429,9 @@ public final class CommonAttributePanel extends javax.swing.JDialog { } }); - jPanel1.setPreferredSize(new java.awt.Dimension(412, 350)); + jPanel1.setMaximumSize(new java.awt.Dimension(412, 375)); + jPanel1.setMinimumSize(new java.awt.Dimension(412, 375)); + jPanel1.setPreferredSize(new java.awt.Dimension(412, 375)); org.openide.awt.Mnemonics.setLocalizedText(commonFilesSearchLabel2, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.commonFilesSearchLabel2.text")); // NOI18N commonFilesSearchLabel2.setFocusable(false); From addb312dc044763b36503f0b521a51a625a26ac7 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Tue, 21 Aug 2018 10:51:31 -0600 Subject: [PATCH 17/40] renames and usage or error manager --- .../CommonAttributePanel.java | 46 +++++-- .../commonfilesearch/PanelErrorMessages.java | 34 ------ .../UserInputErrorManager.java | 115 ++++++++++++++++++ 3 files changed, 152 insertions(+), 43 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/commonfilesearch/PanelErrorMessages.java create mode 100644 Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java index 737d33de7d..016bc0f2ff 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java @@ -58,6 +58,8 @@ public final class CommonAttributePanel extends javax.swing.JDialog { private static final long serialVersionUID = 1L; private static final Long NO_DATA_SOURCE_SELECTED = -1L; + + private final UserInputErrorManager errorManager; private boolean pictureViewCheckboxState; @@ -88,6 +90,8 @@ public final class CommonAttributePanel extends javax.swing.JDialog { this.disableIntercaseSearch(); this.disablePercentageOptions(); } + + this.errorManager = new UserInputErrorManager(); } private static boolean isEamDbAvailable() { @@ -621,20 +625,20 @@ public final class CommonAttributePanel extends javax.swing.JDialog { }//GEN-LAST:event_cancelButtonActionPerformed private void allFileCategoriesRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allFileCategoriesRadioButtonActionPerformed - this.manageCheckBoxState(); - this.toggleErrorTextAndSearchBox(); + this.manageFileTypeCheckBoxState(); + this.updateErrorTextAndSearchBox(); }//GEN-LAST:event_allFileCategoriesRadioButtonActionPerformed private void selectedFileCategoriesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectedFileCategoriesButtonActionPerformed - this.manageCheckBoxState(); + this.manageFileTypeCheckBoxState(); }//GEN-LAST:event_selectedFileCategoriesButtonActionPerformed private void pictureVideoCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pictureVideoCheckboxActionPerformed - this.toggleErrorTextAndSearchBox(); + this.updateErrorTextAndSearchBox(); }//GEN-LAST:event_pictureVideoCheckboxActionPerformed private void documentsCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_documentsCheckboxActionPerformed - this.toggleErrorTextAndSearchBox(); + this.updateErrorTextAndSearchBox(); }//GEN-LAST:event_documentsCheckboxActionPerformed private void intraCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_intraCaseRadioActionPerformed @@ -669,12 +673,14 @@ public final class CommonAttributePanel extends javax.swing.JDialog { } else { this.percentageThreshold.setEnabled(false); } + + this.handleFrequencyPercentageCriteriaMet(); }//GEN-LAST:event_percentageThresholdCheckActionPerformed private void percentageThresholdActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_percentageThresholdActionPerformed String percentageString = this.percentageThreshold.getText(); - Integer percentage; + Integer percentage = null; try{ percentage = Integer.parseInt(percentageString); @@ -683,6 +689,9 @@ public final class CommonAttributePanel extends javax.swing.JDialog { this.percentageThresholdValue = -1; } + this.percentageThresholdValue = percentage.intValue(); + + this.handleFrequencyPercentageCriteriaMet(); }//GEN-LAST:event_percentageThresholdActionPerformed public void handleInterCaseSearchCriteriaChanged() { @@ -696,7 +705,18 @@ public final class CommonAttributePanel extends javax.swing.JDialog { } } - private void toggleErrorTextAndSearchBox() { + private void updateErrorTextAndSearchBox() { + + if(this.errorManager.anyErrors()){ + this.searchButton.setEnabled(false); + //grab the first error error and show it + this.errorText.setText(this.errorManager.getErrors().get(0)); + this.errorText.setVisible(true); + } else { + this.searchButton.setEnabled(true); + this.errorText.setVisible(false); + } + if (!this.pictureVideoCheckbox.isSelected() && !this.documentsCheckbox.isSelected() && !this.allFileCategoriesRadioButton.isSelected()) { this.searchButton.setEnabled(false); this.errorText.setVisible(true); @@ -706,7 +726,7 @@ public final class CommonAttributePanel extends javax.swing.JDialog { } } - private void manageCheckBoxState() { + private void manageFileTypeCheckBoxState() { this.pictureViewCheckboxState = this.pictureVideoCheckbox.isSelected(); this.documentsCheckboxState = this.documentsCheckbox.isSelected(); @@ -724,7 +744,7 @@ public final class CommonAttributePanel extends javax.swing.JDialog { this.pictureVideoCheckbox.setEnabled(true); this.documentsCheckbox.setEnabled(true); - this.toggleErrorTextAndSearchBox(); + this.updateErrorTextAndSearchBox(); } } @@ -789,4 +809,12 @@ public final class CommonAttributePanel extends javax.swing.JDialog { this.percentageThresholdCheck.setEnabled(false); this.percentageThresholdCheck.setSelected(false); } + + private void handleFrequencyPercentageCriteriaMet() { + if(this.percentageThresholdValue > 0 && this.percentageThresholdValue<= 100){ + this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, false); + } else { + this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, true); + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/PanelErrorMessages.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/PanelErrorMessages.java deleted file mode 100644 index fb23b9da14..0000000000 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/PanelErrorMessages.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * - * Autopsy Forensic Browser - * - * Copyright 2018 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.commonfilesearch; - -/** - * - * @author bsweeney - */ -class PanelErrorMessages { - - private class ErrorMessage{ - int id; - String message; - boolean showMessage; - } - -} diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java new file mode 100644 index 0000000000..7490cb440a --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java @@ -0,0 +1,115 @@ +/* + * + * Autopsy Forensic Browser + * + * Copyright 2018 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.commonfilesearch; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Manager for present state of errors on the Common Files Search. + */ +class UserInputErrorManager { + + static final int FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY = 1; + + private final Map currentErrors; + + UserInputErrorManager (){ + this.currentErrors = new HashMap<>(); + this.currentErrors.put(FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, new ErrorMessage("Frequency percentage must be greater than zero and less than or equal to 100.")); + } + + /** + * Toggle the given error message on, or off + * @param errorId the error to toggle + * @param errorState true for on, false for off + */ + void setError(int errorId, boolean errorState){ + if(this.currentErrors.containsKey(errorId)){ + this.currentErrors.get(errorId).setStatus(errorState); + } else { + throw new IllegalArgumentException(String.format("The given errorId is not mapped to an ErrorMessage: %s.", errorId)); + } + } + + /** + * Are any user settings presently in an error state? + * @return true for yes, else false + */ + boolean anyErrors(){ + return this.currentErrors.values().stream().anyMatch(errorMessage -> errorMessage.getStatus() == true); + } + + /** + * Get a list of distinct string messages describing the various error states. + */ + List getErrors(){ + return this.currentErrors.values().stream() + .filter(errorMessage -> errorMessage.getStatus() == true) + .map(ErrorMessage::getMessage) + .collect(Collectors.toList()); + } + + /** + * Represents an error message for the CommonFilesSearch panel, it's + * uniqueId, and it's status. + */ + private class ErrorMessage { + + private final String message; + private boolean status; + + /** + * Create a message with a unique uniqueId. Default status is false (off). + * @param uniqueId unique uniqueId + * @param message message to display + */ + ErrorMessage(String message){ + this.message = message; + this.status = false; + } + + /** + * Update the status of this message + * @param status + */ + void setStatus(boolean status){ + this.status = status; + } + + /** + * Return the message + * @return + */ + String getMessage(){ + return this.message; + } + + /** + * Return the status (true for error status, false for no error) + * @return + */ + boolean getStatus(){ + return this.status; + } + } +} From 0946d96b9433e258c206ef71da39b5c31d910c06 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Tue, 21 Aug 2018 12:37:22 -0600 Subject: [PATCH 18/40] superior error state management --- .../CommonAttributePanel.form | 3 - .../CommonAttributePanel.java | 179 +++++++----------- .../commonfilesearch/InterCasePanel.java | 22 +-- .../commonfilesearch/IntraCasePanel.java | 21 -- .../UserInputErrorManager.java | 13 +- 5 files changed, 77 insertions(+), 161 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form index f926dfdafa..bc520796f3 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form @@ -11,9 +11,6 @@ - - - diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java index 016bc0f2ff..91d32c441b 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java @@ -52,19 +52,19 @@ import org.sleuthkit.datamodel.TskCoreException; * logic. Nested within CommonFilesDialog. */ @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives -public final class CommonAttributePanel extends javax.swing.JDialog { +public final class CommonAttributePanel extends javax.swing.JDialog { private static final Logger LOGGER = Logger.getLogger(CommonAttributePanel.class.getName()); private static final long serialVersionUID = 1L; - + private static final Long NO_DATA_SOURCE_SELECTED = -1L; - + private final UserInputErrorManager errorManager; private boolean pictureViewCheckboxState; - + private boolean documentsCheckboxState; - + private int percentageThresholdValue = 20; /** @@ -90,18 +90,18 @@ public final class CommonAttributePanel extends javax.swing.JDialog { this.disableIntercaseSearch(); this.disablePercentageOptions(); } - + this.errorManager = new UserInputErrorManager(); } private static boolean isEamDbAvailable() { try { - return EamDb.isEnabled() && - EamDb.getInstance() != null && - EamDb.getInstance().getCases().size() > 1 && - Case.isCaseOpen() && - Case.getCurrentCase() != null && - EamDb.getInstance().getCase(Case.getCurrentCase()) != null; + return EamDb.isEnabled() + && EamDb.getInstance() != null + && EamDb.getInstance().getCases().size() > 1 + && Case.isCaseOpen() + && Case.getCurrentCase() != null + && EamDb.getInstance().getCase(Case.getCurrentCase()) != null; } catch (EamDbException ex) { LOGGER.log(Level.SEVERE, "Unexpected exception while checking for EamDB enabled.", ex); } @@ -166,9 +166,10 @@ public final class CommonAttributePanel extends javax.swing.JDialog { filterByDocuments = true; } } + + int percentageThreshold = CommonAttributePanel.this.percentageThresholdValue; - int percentageThreshold = 0; - if(CommonAttributePanel.this.percentageThresholdCheck.isSelected()){ + if (CommonAttributePanel.this.percentageThresholdCheck.isSelected()) { String percentageThresholdAsString = CommonAttributePanel.this.percentageThreshold.getText(); percentageThreshold = Integer.parseInt(percentageThresholdAsString); } @@ -245,7 +246,6 @@ public final class CommonAttributePanel extends javax.swing.JDialog { }.execute(); } - /** * Sets up the data sources dropdown and returns the data sources map for * future usage. @@ -278,8 +278,7 @@ public final class CommonAttributePanel extends javax.swing.JDialog { boolean multipleDataSources = this.caseHasMultipleSources(); CommonAttributePanel.this.intraCasePanel.rigForMultipleDataSources(multipleDataSources); - //TODO this should be attached to the intra/inter radio buttons - CommonAttributePanel.this.setSearchButtonEnabled(true); + CommonAttributePanel.this.updateErrorTextAndSearchBox(); } } @@ -625,41 +624,27 @@ public final class CommonAttributePanel extends javax.swing.JDialog { }//GEN-LAST:event_cancelButtonActionPerformed private void allFileCategoriesRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allFileCategoriesRadioButtonActionPerformed - this.manageFileTypeCheckBoxState(); - this.updateErrorTextAndSearchBox(); + this.handleFileTypeCheckBoxState(); }//GEN-LAST:event_allFileCategoriesRadioButtonActionPerformed private void selectedFileCategoriesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectedFileCategoriesButtonActionPerformed - this.manageFileTypeCheckBoxState(); + this.handleFileTypeCheckBoxState(); }//GEN-LAST:event_selectedFileCategoriesButtonActionPerformed private void pictureVideoCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pictureVideoCheckboxActionPerformed - this.updateErrorTextAndSearchBox(); + this.handleFileTypeCheckBoxState(); }//GEN-LAST:event_pictureVideoCheckboxActionPerformed private void documentsCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_documentsCheckboxActionPerformed - this.updateErrorTextAndSearchBox(); + this.handleFileTypeCheckBoxState(); }//GEN-LAST:event_documentsCheckboxActionPerformed private void intraCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_intraCaseRadioActionPerformed ((java.awt.CardLayout) this.layoutPanel.getLayout()).first(this.layoutPanel); - handleIntraCaseSearchCriteriaChanged(); }//GEN-LAST:event_intraCaseRadioActionPerformed - public void handleIntraCaseSearchCriteriaChanged() { - if (this.areIntraCaseSearchCriteriaMet()) { - this.searchButton.setEnabled(true); - this.hideErrorMessages(); - } else { - this.searchButton.setEnabled(false); - this.hideErrorMessages(); - this.showIntraCaseErrorMessage(); - } - } - private void interCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_interCaseRadioActionPerformed ((java.awt.CardLayout) this.layoutPanel.getLayout()).last(this.layoutPanel); - handleInterCaseSearchCriteriaChanged(); }//GEN-LAST:event_interCaseRadioActionPerformed private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed @@ -667,47 +652,35 @@ public final class CommonAttributePanel extends javax.swing.JDialog { }//GEN-LAST:event_formWindowClosed private void percentageThresholdCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_percentageThresholdCheckActionPerformed - if(this.percentageThresholdCheck.isSelected()){ + if (this.percentageThresholdCheck.isSelected()) { this.percentageThreshold.setEnabled(true); - } else { this.percentageThreshold.setEnabled(false); } - - this.handleFrequencyPercentageCriteriaMet(); + + this.handleFrequencyPercentageState(); }//GEN-LAST:event_percentageThresholdCheckActionPerformed private void percentageThresholdActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_percentageThresholdActionPerformed String percentageString = this.percentageThreshold.getText(); - + Integer percentage = null; - - try{ + + try { percentage = Integer.parseInt(percentageString); this.percentageThresholdValue = percentage; - } catch(Exception e){ + } catch (Exception e) { this.percentageThresholdValue = -1; } - + this.percentageThresholdValue = percentage.intValue(); - - this.handleFrequencyPercentageCriteriaMet(); + + this.handleFrequencyPercentageState(); }//GEN-LAST:event_percentageThresholdActionPerformed - public void handleInterCaseSearchCriteriaChanged() { - if (this.areInterCaseSearchCriteriaMet()) { - this.searchButton.setEnabled(true); - this.hideErrorMessages(); - } else { - this.searchButton.setEnabled(false); - this.hideErrorMessages(); - this.showInterCaseErrorMessage(); - } - } - private void updateErrorTextAndSearchBox() { - - if(this.errorManager.anyErrors()){ + + if (this.errorManager.anyErrors()) { this.searchButton.setEnabled(false); //grab the first error error and show it this.errorText.setText(this.errorManager.getErrors().get(0)); @@ -716,17 +689,21 @@ public final class CommonAttributePanel extends javax.swing.JDialog { this.searchButton.setEnabled(true); this.errorText.setVisible(false); } - - if (!this.pictureVideoCheckbox.isSelected() && !this.documentsCheckbox.isSelected() && !this.allFileCategoriesRadioButton.isSelected()) { - this.searchButton.setEnabled(false); - this.errorText.setVisible(true); - } else { - this.searchButton.setEnabled(true); - this.errorText.setVisible(false); - } } - private void manageFileTypeCheckBoxState() { + private void enablePercentageOptions() { + this.percentageThreshold.setEnabled(true); + this.percentageThresholdCheck.setEnabled(true); + this.percentageThresholdCheck.setSelected(true); + } + + private void disablePercentageOptions() { + this.percentageThreshold.setEnabled(false); + this.percentageThresholdCheck.setEnabled(false); + this.percentageThresholdCheck.setSelected(false); + } + + private void handleFileTypeCheckBoxState() { this.pictureViewCheckboxState = this.pictureVideoCheckbox.isSelected(); this.documentsCheckboxState = this.documentsCheckbox.isSelected(); @@ -734,6 +711,8 @@ public final class CommonAttributePanel extends javax.swing.JDialog { if (this.allFileCategoriesRadioButton.isSelected()) { this.pictureVideoCheckbox.setEnabled(false); this.documentsCheckbox.setEnabled(false); + + this.errorManager.setError(UserInputErrorManager.NO_FILE_CATEGORIES_SELECTED_KEY, false); } if (this.selectedFileCategoriesButton.isSelected()) { @@ -744,8 +723,24 @@ public final class CommonAttributePanel extends javax.swing.JDialog { this.pictureVideoCheckbox.setEnabled(true); this.documentsCheckbox.setEnabled(true); - this.updateErrorTextAndSearchBox(); + if (!this.pictureVideoCheckbox.isSelected() && !this.documentsCheckbox.isSelected() && !this.allFileCategoriesRadioButton.isSelected()) { + this.errorManager.setError(UserInputErrorManager.NO_FILE_CATEGORIES_SELECTED_KEY, true); + } else { + this.errorManager.setError(UserInputErrorManager.NO_FILE_CATEGORIES_SELECTED_KEY, false); + } } + + this.updateErrorTextAndSearchBox(); + } + + private void handleFrequencyPercentageState() { + if (this.percentageThresholdValue > 0 && this.percentageThresholdValue <= 100) { + this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, false); + } else { + this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, true); + } + + this.updateErrorTextAndSearchBox(); } // Variables declaration - do not modify//GEN-BEGIN:variables @@ -771,50 +766,4 @@ public final class CommonAttributePanel extends javax.swing.JDialog { private javax.swing.JButton searchButton; private javax.swing.JRadioButton selectedFileCategoriesButton; // End of variables declaration//GEN-END:variables - - void setSearchButtonEnabled(boolean enabled) { - this.searchButton.setEnabled(enabled); - } - - private boolean areIntraCaseSearchCriteriaMet() { - return this.intraCasePanel.areSearchCriteriaMet(); - } - - private boolean areInterCaseSearchCriteriaMet() { - return this.interCasePanel.areSearchCriteriaMet(); - } - - private void hideErrorMessages() { - this.errorText.setVisible(false); - } - - private void showIntraCaseErrorMessage() { - this.errorText.setText(this.intraCasePanel.getErrorMessage()); - this.errorText.setVisible(true); - } - - private void showInterCaseErrorMessage() { - this.errorText.setText(this.interCasePanel.getErrorMessage()); - this.errorText.setVisible(true); - } - - private void enablePercentageOptions() { - this.percentageThreshold.setEnabled(true); - this.percentageThresholdCheck.setEnabled(true); - this.percentageThresholdCheck.setSelected(true); - } - - private void disablePercentageOptions() { - this.percentageThreshold.setEnabled(false); - this.percentageThresholdCheck.setEnabled(false); - this.percentageThresholdCheck.setSelected(false); - } - - private void handleFrequencyPercentageCriteriaMet() { - if(this.percentageThresholdValue > 0 && this.percentageThresholdValue<= 100){ - this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, false); - } else { - this.errorManager.setError(UserInputErrorManager.FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, true); - } - } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.java index 67aa40134b..8fc4efd01e 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.java @@ -24,7 +24,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import javax.swing.ComboBoxModel; -import org.openide.util.NbBundle; /** * UI controls for Common Files Search scenario where the user intends to find @@ -39,9 +38,7 @@ public class InterCasePanel extends javax.swing.JPanel { private ComboBoxModel casesList = new DataSourceComboBoxModel(); private final Map caseMap; - - private String errorMessage; - + //True if we are looking in any or all cases, // false if we must find matches in a given case plus the current case private boolean anyCase; @@ -51,7 +48,6 @@ public class InterCasePanel extends javax.swing.JPanel { */ public InterCasePanel() { initComponents(); - this.errorMessage = ""; this.caseMap = new HashMap<>(); this.anyCase = true; } @@ -64,10 +60,6 @@ public class InterCasePanel extends javax.swing.JPanel { } } - String getErrorMessage(){ - return this.errorMessage; - } - /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -189,16 +181,4 @@ public class InterCasePanel extends javax.swing.JPanel { return InterCasePanel.NO_CASE_SELECTED; } - - @NbBundle.Messages({ - "InterCasePanel.showInterCaseErrorMessage.message=Cannot run intercase correlation search: no cases in Central Repository." - }) - boolean areSearchCriteriaMet() { - if(this.caseMap.isEmpty()){ - this.errorMessage = Bundle.InterCasePanel_showInterCaseErrorMessage_message(); - return false; - } else { - return true; - } - } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.java index c62552082b..babbbd4096 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.java @@ -24,8 +24,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import javax.swing.ComboBoxModel; -import org.openide.util.NbBundle; - /** * UI controls for Common Files Search scenario where the user intends to find * common files between datasources. It is an inner panel which provides the ability @@ -40,15 +38,12 @@ public class IntraCasePanel extends javax.swing.JPanel { private boolean singleDataSource; private ComboBoxModel dataSourcesList = new DataSourceComboBoxModel(); private final Map dataSourceMap; - - private String errorMessage; /** * Creates new form IntraCasePanel */ public IntraCasePanel() { initComponents(); - this.errorMessage = ""; this.dataSourceMap = new HashMap<>(); this.singleDataSource = true; } @@ -175,20 +170,4 @@ public class IntraCasePanel extends javax.swing.JPanel { this.dataSourceMap.clear(); this.dataSourceMap.putAll(dataSourceMap); } - - @NbBundle.Messages({ - "IntraCasePanel.areSearchCriteriaMet.message=Cannot run intra-case correlation search." - }) - boolean areSearchCriteriaMet() { - if(this.dataSourceMap.isEmpty()){ - this.errorMessage = Bundle.IntraCasePanel_areSearchCriteriaMet_message(); - return false; - } else { - return true; - } - } - - String getErrorMessage() { - return this.errorMessage; - } } \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java index 7490cb440a..11c22a3aec 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java @@ -29,13 +29,24 @@ import java.util.stream.Collectors; */ class UserInputErrorManager { - static final int FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY = 1; + static final int FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY = 1; + static final int NO_FILE_CATEGORIES_SELECTED_KEY = 2; private final Map currentErrors; + /** + * Construct a new ErrorManager which can be used to track the status + * of all known error states, retrieve error messages, and determine if + * anything is in an error state. + */ UserInputErrorManager (){ + + //when new errors are needed for the dialog, define a key and a value + // and add them to the map. + this.currentErrors = new HashMap<>(); this.currentErrors.put(FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, new ErrorMessage("Frequency percentage must be greater than zero and less than or equal to 100.")); + this.currentErrors.put(NO_FILE_CATEGORIES_SELECTED_KEY, new ErrorMessage("No file categories are included in the search.")); } /** From 5cf4d7d8495d371ce1ee4900efc0707a132c98ec Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Tue, 21 Aug 2018 15:13:07 -0600 Subject: [PATCH 19/40] text field should not resize --- .../CommonAttributePanel.form | 9 ++-- .../CommonAttributePanel.java | 44 ++++++++++++------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form index bc520796f3..be96989e91 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form @@ -315,10 +315,13 @@ + + + + + + - - - diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java index 91d32c441b..7116ebd2ba 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java @@ -29,6 +29,8 @@ import java.util.logging.Level; import javax.swing.JFrame; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; import org.netbeans.api.progress.ProgressHandle; import org.openide.explorer.ExplorerManager; import org.openide.util.NbBundle; @@ -79,6 +81,7 @@ public final class CommonAttributePanel extends javax.swing.JDialog { super(new JFrame(Bundle.CommonFilesPanel_frame_title()), Bundle.CommonFilesPanel_frame_msg(), true); initComponents(); + this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); this.errorText.setVisible(false); this.setupDataSources(); @@ -92,6 +95,23 @@ public final class CommonAttributePanel extends javax.swing.JDialog { } this.errorManager = new UserInputErrorManager(); + + this.percentageThreshold.getDocument().addDocumentListener(new DocumentListener(){ + @Override + public void insertUpdate(DocumentEvent e) { + CommonAttributePanel.this.percentageThresholdChanged(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + CommonAttributePanel.this.percentageThresholdChanged(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + CommonAttributePanel.this.percentageThresholdChanged(); + } + }); } private static boolean isEamDbAvailable() { @@ -424,7 +444,6 @@ public final class CommonAttributePanel extends javax.swing.JDialog { jLabel1 = new javax.swing.JLabel(); setMinimumSize(new java.awt.Dimension(412, 375)); - setPreferredSize(new java.awt.Dimension(412, 375)); setResizable(false); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosed(java.awt.event.WindowEvent evt) { @@ -530,11 +549,8 @@ public final class CommonAttributePanel extends javax.swing.JDialog { }); percentageThreshold.setText(org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.percentageThreshold.text")); // NOI18N - percentageThreshold.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - percentageThresholdActionPerformed(evt); - } - }); + percentageThreshold.setMaximumSize(new java.awt.Dimension(28, 24)); + percentageThreshold.setMinimumSize(new java.awt.Dimension(28, 24)); org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.jLabel1.text_1")); // NOI18N @@ -661,23 +677,19 @@ public final class CommonAttributePanel extends javax.swing.JDialog { this.handleFrequencyPercentageState(); }//GEN-LAST:event_percentageThresholdCheckActionPerformed - private void percentageThresholdActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_percentageThresholdActionPerformed + private void percentageThresholdChanged(){ String percentageString = this.percentageThreshold.getText(); - Integer percentage = null; - try { - percentage = Integer.parseInt(percentageString); - this.percentageThresholdValue = percentage; + this.percentageThresholdValue = Integer.parseInt(percentageString); + } catch (Exception e) { this.percentageThresholdValue = -1; } - this.percentageThresholdValue = percentage.intValue(); - - this.handleFrequencyPercentageState(); - }//GEN-LAST:event_percentageThresholdActionPerformed - + this.handleFrequencyPercentageState(); + } + private void updateErrorTextAndSearchBox() { if (this.errorManager.anyErrors()) { From 56989e022c826dacd2ba5ca1fecca322b0ffce23 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Tue, 21 Aug 2018 15:39:47 -0600 Subject: [PATCH 20/40] text field stays the same size --- .../CommonAttributePanel.form | 9 ++++++--- .../CommonAttributePanel.java | 20 +++++++++++++++---- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form index be96989e91..329de08aef 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form @@ -81,7 +81,7 @@ - + @@ -316,10 +316,13 @@ - + - + + + + diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java index 7116ebd2ba..e8fa60ec2d 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.commonfilesearch; +import java.awt.Dimension; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; @@ -97,18 +98,28 @@ public final class CommonAttributePanel extends javax.swing.JDialog { this.errorManager = new UserInputErrorManager(); this.percentageThreshold.getDocument().addDocumentListener(new DocumentListener(){ + + private Dimension preferredSize = CommonAttributePanel.this.percentageThreshold.getPreferredSize(); + + private void maintainSize(){ + CommonAttributePanel.this.percentageThreshold.setSize(preferredSize); + } + @Override - public void insertUpdate(DocumentEvent e) { + public void insertUpdate(DocumentEvent e) { + this.maintainSize(); CommonAttributePanel.this.percentageThresholdChanged(); } @Override public void removeUpdate(DocumentEvent e) { + this.maintainSize(); CommonAttributePanel.this.percentageThresholdChanged(); } @Override public void changedUpdate(DocumentEvent e) { + this.maintainSize(); CommonAttributePanel.this.percentageThresholdChanged(); } }); @@ -549,8 +560,9 @@ public final class CommonAttributePanel extends javax.swing.JDialog { }); percentageThreshold.setText(org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.percentageThreshold.text")); // NOI18N - percentageThreshold.setMaximumSize(new java.awt.Dimension(28, 24)); - percentageThreshold.setMinimumSize(new java.awt.Dimension(28, 24)); + percentageThreshold.setMaximumSize(new java.awt.Dimension(40, 24)); + percentageThreshold.setMinimumSize(new java.awt.Dimension(40, 24)); + percentageThreshold.setPreferredSize(new java.awt.Dimension(40, 24)); org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.jLabel1.text_1")); // NOI18N @@ -580,7 +592,7 @@ public final class CommonAttributePanel extends javax.swing.JDialog { .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(percentageThresholdCheck) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(percentageThreshold, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(percentageThreshold, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel1)) .addGroup(jPanel1Layout.createSequentialGroup() From 4cbf9d10e7f137480dbae202182255839dce7870 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Tue, 21 Aug 2018 16:53:01 -0600 Subject: [PATCH 21/40] had forgotten to hook up the percentage value to the search results --- .../commonfilesearch/AbstractCommonAttributeSearcher.java | 2 ++ .../AllInterCaseCommonAttributeSearcher.java | 2 +- .../autopsy/commonfilesearch/CommonAttributePanel.java | 6 +++--- .../commonfilesearch/IntraCaseCommonAttributeSearcher.java | 2 +- .../SingleInterCaseCommonAttributeSearcher.java | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AbstractCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AbstractCommonAttributeSearcher.java index 3742f73562..0813b59711 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AbstractCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AbstractCommonAttributeSearcher.java @@ -42,11 +42,13 @@ public abstract class AbstractCommonAttributeSearcher { private final Map dataSourceIdToNameMap; private boolean filterByMedia; private boolean filterByDoc; + final int frequencyPercentageThreshold; AbstractCommonAttributeSearcher(Map dataSourceIdMap, boolean filterByMedia, boolean filterByDoc, int percentageThreshold){ this.filterByDoc = filterByDoc; this.filterByMedia = filterByMedia; this.dataSourceIdToNameMap = dataSourceIdMap; + this.frequencyPercentageThreshold = percentageThreshold; } Map getDataSourceIdToNameMap(){ diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllInterCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllInterCaseCommonAttributeSearcher.java index c12e1dbca6..595d739504 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllInterCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllInterCaseCommonAttributeSearcher.java @@ -49,7 +49,7 @@ public class AllInterCaseCommonAttributeSearcher extends InterCaseCommonAttribut public CommonAttributeSearchResults findFiles() throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException { InterCaseSearchResultsProcessor eamDbAttrInst = new InterCaseSearchResultsProcessor(this.getDataSourceIdToNameMap()); Map> interCaseCommonFiles = eamDbAttrInst.findInterCaseCommonAttributeValues(Case.getCurrentCase()); - return new CommonAttributeSearchResults(interCaseCommonFiles); + return new CommonAttributeSearchResults(interCaseCommonFiles, this.frequencyPercentageThreshold); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java index e8fa60ec2d..8635694b88 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java @@ -200,9 +200,9 @@ public final class CommonAttributePanel extends javax.swing.JDialog { int percentageThreshold = CommonAttributePanel.this.percentageThresholdValue; - if (CommonAttributePanel.this.percentageThresholdCheck.isSelected()) { - String percentageThresholdAsString = CommonAttributePanel.this.percentageThreshold.getText(); - percentageThreshold = Integer.parseInt(percentageThresholdAsString); + if (!CommonAttributePanel.this.percentageThresholdCheck.isSelected()) { + //0 has the effect of disabling the feature + percentageThreshold = 0; } if (CommonAttributePanel.this.interCaseRadio.isSelected()) { diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCaseCommonAttributeSearcher.java index bd26648196..94bd3b061e 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCaseCommonAttributeSearcher.java @@ -130,7 +130,7 @@ public abstract class IntraCaseCommonAttributeSearcher extends AbstractCommonAtt Map> instanceCollatedCommonFiles = collateMatchesByNumberOfInstances(commonFiles); - return new CommonAttributeSearchResults(instanceCollatedCommonFiles); + return new CommonAttributeSearchResults(instanceCollatedCommonFiles, this.frequencyPercentageThreshold); } /** diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleInterCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleInterCaseCommonAttributeSearcher.java index 9289bd8f90..d6f566b8f8 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleInterCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleInterCaseCommonAttributeSearcher.java @@ -74,7 +74,7 @@ public class SingleInterCaseCommonAttributeSearcher extends InterCaseCommonAttri InterCaseSearchResultsProcessor eamDbAttrInst = new InterCaseSearchResultsProcessor(this.getDataSourceIdToNameMap()); Map> interCaseCommonFiles = eamDbAttrInst.findSingleInterCaseCommonAttributeValues(Case.getCurrentCase(), correlationCase); - return new CommonAttributeSearchResults(interCaseCommonFiles); + return new CommonAttributeSearchResults(interCaseCommonFiles, this.frequencyPercentageThreshold); } @Override From 2c32fe42e8d4ae3ce54bf13494091c3111aa0980 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Tue, 21 Aug 2018 17:03:33 -0600 Subject: [PATCH 22/40] fixed all the tests --- ...stedWithHashAndFileTypeInterCaseTests.java | 4 +- ...stedWithHashAndFileTypeIntraCaseTests.java | 18 +-- ...IngestedWithNoFileTypesIntraCaseTests.java | 4 +- .../commonfilessearch/InterCaseTestUtils.java | 104 +++++++++--------- .../commonfilessearch/IntraCaseTestUtils.java | 21 ++-- ...chesInAtLeastTwoSourcesIntraCaseTests.java | 2 +- .../UningestedCasesIntraCaseTests.java | 5 +- 7 files changed, 85 insertions(+), 73 deletions(-) diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java index 74a42172cb..a28d53302a 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java @@ -86,7 +86,7 @@ public class IngestedWithHashAndFileTypeInterCaseTests extends NbTestCase { Map dataSources = this.utils.getDataSourceMap(); //note that the params false and false are presently meaningless because that feature is not supported yet - AbstractCommonAttributeSearcher builder = new AllInterCaseCommonAttributeSearcher(dataSources, false, false); + AbstractCommonAttributeSearcher builder = new AllInterCaseCommonAttributeSearcher(dataSources, false, false, 0); CommonAttributeSearchResults metadata = builder.findFiles(); @@ -139,7 +139,7 @@ public class IngestedWithHashAndFileTypeInterCaseTests extends NbTestCase { int matchesMustAlsoBeFoundInThisCase = this.utils.getCaseMap().get(CASE2); - AbstractCommonAttributeSearcher builder = new SingleInterCaseCommonAttributeSearcher(matchesMustAlsoBeFoundInThisCase, dataSources, false, false); + AbstractCommonAttributeSearcher builder = new SingleInterCaseCommonAttributeSearcher(matchesMustAlsoBeFoundInThisCase, dataSources, false, false, 0); CommonAttributeSearchResults metadata = builder.findFiles(); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeIntraCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeIntraCaseTests.java index d1a004d281..2d8299eab2 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeIntraCaseTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeIntraCaseTests.java @@ -99,7 +99,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase { try { Map dataSources = this.utils.getDataSourceMap(); - AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, false); + AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, false, 0); CommonAttributeSearchResults metadata = allSourcesBuilder.findFiles(); Map objectIdToDataSource = IntraCaseTestUtils.mapFileInstancesToDataSources(metadata); @@ -140,7 +140,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase { try { Map dataSources = this.utils.getDataSourceMap(); - AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, true, false); + AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, true, false, 0); CommonAttributeSearchResults metadata = allSourcesBuilder.findFiles(); Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); @@ -181,7 +181,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase { try { Map dataSources = this.utils.getDataSourceMap(); - AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, true); + AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, true, 0); CommonAttributeSearchResults metadata = allSourcesBuilder.findFiles(); Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); @@ -223,7 +223,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase { Map dataSources = this.utils.getDataSourceMap(); Long first = getDataSourceIdByName(SET1, dataSources); - AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, false, false); + AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, false, false, 0); CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles(); Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); @@ -265,7 +265,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase { Map dataSources = this.utils.getDataSourceMap(); Long first = getDataSourceIdByName(SET1, dataSources); - AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, true, false); + AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, true, false, 0); CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles(); Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); @@ -307,7 +307,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase { Map dataSources = this.utils.getDataSourceMap(); Long first = getDataSourceIdByName(SET1, dataSources); - AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, false, true); + AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, false, true, 0); CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles(); Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); @@ -349,7 +349,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase { Map dataSources = this.utils.getDataSourceMap(); Long second = getDataSourceIdByName(SET2, dataSources); - AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(second, dataSources, false, false); + AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(second, dataSources, false, false, 0); CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles(); Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); @@ -390,7 +390,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase { Map dataSources = this.utils.getDataSourceMap(); Long last = getDataSourceIdByName(SET4, dataSources); - AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(last, dataSources, false, false); + AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(last, dataSources, false, false, 0); CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles(); Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); @@ -431,7 +431,7 @@ public class IngestedWithHashAndFileTypeIntraCaseTests extends NbTestCase { Map dataSources = this.utils.getDataSourceMap(); Long third = getDataSourceIdByName(SET3, dataSources); - AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(third, dataSources, false, false); + AbstractCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(third, dataSources, false, false, 0); CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles(); Map objectIdToDataSource = mapFileInstancesToDataSources(metadata); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithNoFileTypesIntraCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithNoFileTypesIntraCaseTests.java index d51dfda2fa..c48462929e 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithNoFileTypesIntraCaseTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithNoFileTypesIntraCaseTests.java @@ -101,7 +101,7 @@ public class IngestedWithNoFileTypesIntraCaseTests extends NbTestCase { try { Map dataSources = this.utils.getDataSourceMap(); - IntraCaseCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, true, false); + IntraCaseCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, true, false, 0); CommonAttributeSearchResults metadata = allSourcesBuilder.findFiles(); Map objectIdToDataSource = IntraCaseTestUtils.mapFileInstancesToDataSources(metadata); @@ -125,7 +125,7 @@ public class IngestedWithNoFileTypesIntraCaseTests extends NbTestCase { Map dataSources = this.utils.getDataSourceMap(); Long third = IntraCaseTestUtils.getDataSourceIdByName(IntraCaseTestUtils.SET3, dataSources); - IntraCaseCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(third, dataSources, true, false); + IntraCaseCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(third, dataSources, true, false, 0); CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles(); Map objectIdToDataSource = IntraCaseTestUtils.mapFileInstancesToDataSources(metadata); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java index cf6bd36fbc..b2d8b57299 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java @@ -307,67 +307,73 @@ class InterCaseTestUtils { //TODO refactor static boolean verifyInstanceExistanceAndCount(CommonAttributeSearchResults searchDomain, String fileName, String dataSource, String crCase, int instanceCount){ - int tally = 0; - - for(Map.Entry> entry : searchDomain.getMetadata().entrySet()){ + try { + int tally = 0; - for(CommonAttributeValue value : entry.getValue()){ + for(Map.Entry> entry : searchDomain.getMetadata().entrySet()){ - for(AbstractCommonAttributeInstance commonAttribute : value.getInstances()){ + for(CommonAttributeValue value : entry.getValue()){ - if(commonAttribute instanceof CentralRepoCommonAttributeInstance){ - CentralRepoCommonAttributeInstance results = (CentralRepoCommonAttributeInstance) commonAttribute; - for (DisplayableItemNode din : results.generateNodes()){ - - if(din instanceof CentralRepoCommonAttributeInstanceNode){ + for(AbstractCommonAttributeInstance commonAttribute : value.getInstances()){ + + if(commonAttribute instanceof CentralRepoCommonAttributeInstance){ + CentralRepoCommonAttributeInstance results = (CentralRepoCommonAttributeInstance) commonAttribute; + for (DisplayableItemNode din : results.generateNodes()){ - CentralRepoCommonAttributeInstanceNode node = (CentralRepoCommonAttributeInstanceNode) din; - CorrelationAttributeInstance instance = node.getCorrelationAttributeInstance(); + if(din instanceof CentralRepoCommonAttributeInstanceNode){ + + CentralRepoCommonAttributeInstanceNode node = (CentralRepoCommonAttributeInstanceNode) din; + CorrelationAttributeInstance instance = node.getCorrelationAttributeInstance(); + + final String fullPath = instance.getFilePath(); + final File testFile = new File(fullPath); + + final String testCaseName = instance.getCorrelationCase().getDisplayName(); + + final String testFileName = testFile.getName(); + + final String testDataSource = instance.getCorrelationDataSource().getName(); + + boolean sameFileName = testFileName.equalsIgnoreCase(fileName); + boolean sameDataSource = testDataSource.equalsIgnoreCase(dataSource); + boolean sameCrCase = testCaseName.equalsIgnoreCase(crCase); + + if( sameFileName && sameDataSource && sameCrCase){ + tally++; + } + } - final String fullPath = instance.getFilePath(); - final File testFile = new File(fullPath); - - final String testCaseName = instance.getCorrelationCase().getDisplayName(); - - final String testFileName = testFile.getName(); - - final String testDataSource = instance.getCorrelationDataSource().getName(); - - boolean sameFileName = testFileName.equalsIgnoreCase(fileName); - boolean sameDataSource = testDataSource.equalsIgnoreCase(dataSource); - boolean sameCrCase = testCaseName.equalsIgnoreCase(crCase); - - if( sameFileName && sameDataSource && sameCrCase){ - tally++; - } - } - - if(din instanceof CaseDBCommonAttributeInstanceNode){ - - CaseDBCommonAttributeInstanceNode node = (CaseDBCommonAttributeInstanceNode) din; - AbstractFile file = node.getContent(); - - final String testFileName = file.getName(); - final String testCaseName = node.getCase(); - final String testDataSource = node.getDataSource(); - - boolean sameFileName = testFileName.equalsIgnoreCase(fileName); - boolean sameCaseName = testCaseName.equalsIgnoreCase(crCase); - boolean sameDataSource = testDataSource.equalsIgnoreCase(dataSource); - - if(sameFileName && sameDataSource && sameCaseName){ - tally++; + if(din instanceof CaseDBCommonAttributeInstanceNode){ + + CaseDBCommonAttributeInstanceNode node = (CaseDBCommonAttributeInstanceNode) din; + AbstractFile file = node.getContent(); + + final String testFileName = file.getName(); + final String testCaseName = node.getCase(); + final String testDataSource = node.getDataSource(); + + boolean sameFileName = testFileName.equalsIgnoreCase(fileName); + boolean sameCaseName = testCaseName.equalsIgnoreCase(crCase); + boolean sameDataSource = testDataSource.equalsIgnoreCase(dataSource); + + if(sameFileName && sameDataSource && sameCaseName){ + tally++; + } } } + } else { + Assert.fail("Unable to cast AbstractCommonAttributeInstanceNode to InterCaseCommonAttributeSearchResults."); } - } else { - Assert.fail("Unable to cast AbstractCommonAttributeInstanceNode to InterCaseCommonAttributeSearchResults."); } } } + + return tally == instanceCount; + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return false; } - - return tally == instanceCount; } /** diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java index 82c38cdf56..1ee4799956 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java @@ -33,6 +33,7 @@ import org.python.icu.impl.Assert; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.ImageDSProcessor; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.autopsy.commonfilesearch.AbstractCommonAttributeInstance; import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeSearchResults; import org.sleuthkit.autopsy.commonfilesearch.DataSourceLoader; @@ -204,16 +205,22 @@ class IntraCaseTestUtils { */ static Map mapFileInstancesToDataSources(CommonAttributeSearchResults metadata) { Map instanceIdToDataSource = new HashMap<>(); - - for (Map.Entry> entry : metadata.getMetadata().entrySet()) { - for (CommonAttributeValue md : entry.getValue()) { - for (AbstractCommonAttributeInstance fim : md.getInstances()) { - instanceIdToDataSource.put(fim.getAbstractFileObjectId(), fim.getDataSource()); + + try { + for (Map.Entry> entry : metadata.getMetadata().entrySet()) { + for (CommonAttributeValue md : entry.getValue()) { + for (AbstractCommonAttributeInstance fim : md.getInstances()) { + instanceIdToDataSource.put(fim.getAbstractFileObjectId(), fim.getDataSource()); + } } } + + return instanceIdToDataSource; + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + return instanceIdToDataSource; } - - return instanceIdToDataSource; } diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/MatchesInAtLeastTwoSourcesIntraCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/MatchesInAtLeastTwoSourcesIntraCaseTests.java index f4c397af8d..e0670d9b77 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/MatchesInAtLeastTwoSourcesIntraCaseTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/MatchesInAtLeastTwoSourcesIntraCaseTests.java @@ -105,7 +105,7 @@ public class MatchesInAtLeastTwoSourcesIntraCaseTests extends NbTestCase { try { Map dataSources = this.utils.getDataSourceMap(); - AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, false); + AbstractCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, false, 0); CommonAttributeSearchResults metadata = allSourcesBuilder.findFiles(); Map objectIdToDataSource = IntraCaseTestUtils.mapFileInstancesToDataSources(metadata); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/UningestedCasesIntraCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/UningestedCasesIntraCaseTests.java index b55707c771..b581f0d4ed 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/UningestedCasesIntraCaseTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/UningestedCasesIntraCaseTests.java @@ -28,7 +28,6 @@ import org.netbeans.junit.NbTestCase; import org.openide.util.Exceptions; import org.python.icu.impl.Assert; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.autopsy.commonfilesearch.AllIntraCaseCommonAttributeSearcher; import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeSearchResults; import org.sleuthkit.autopsy.commonfilesearch.IntraCaseCommonAttributeSearcher; @@ -81,7 +80,7 @@ public class UningestedCasesIntraCaseTests extends NbTestCase { try { Map dataSources = this.utils.getDataSourceMap(); - IntraCaseCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, false); + IntraCaseCommonAttributeSearcher allSourcesBuilder = new AllIntraCaseCommonAttributeSearcher(dataSources, false, false, 0); CommonAttributeSearchResults metadata = allSourcesBuilder.findFiles(); int resultCount = metadata.size(); @@ -101,7 +100,7 @@ public class UningestedCasesIntraCaseTests extends NbTestCase { Map dataSources = this.utils.getDataSourceMap(); Long first = getDataSourceIdByName(SET1, dataSources); - IntraCaseCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, false, false); + IntraCaseCommonAttributeSearcher singleSourceBuilder = new SingleIntraCaseCommonAttributeSearcher(first, dataSources, false, false, 0); CommonAttributeSearchResults metadata = singleSourceBuilder.findFiles(); int resultCount = metadata.size(); From 92605055b5113cbc8ee6b4fa62f66015a958acc4 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Wed, 22 Aug 2018 08:34:15 -0600 Subject: [PATCH 23/40] typo in tests --- .../sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java index 1ee4799956..c25abbceaf 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java @@ -173,7 +173,7 @@ class IntraCaseTestUtils { String dataSourceName = objectIdToDataSourceMap.get(objectId); - if (name.equals(name) && dataSourceName.equals(dataSource)) { + if (name.equals(fileName) && dataSourceName.equals(dataSource)) { tally++; } } From 4a68eb7e57265d3e185f35555a37ed7b39dbe0ef Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Wed, 22 Aug 2018 17:19:42 -0600 Subject: [PATCH 24/40] updated comments with info pertinent to frequency search tests --- .../commonfilessearch/InterCaseTestUtils.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java index b2d8b57299..9e41d6f199 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java @@ -101,6 +101,20 @@ import org.sleuthkit.datamodel.AbstractFile; - Hash-C.jpg - Hash-C.pdf - Hash-D.doc + * + * Frequency Breakdown + * (ratio of datasources a given file appears in to total number of datasources): + * + * Hash-0.dat - moot; these are always excluded + * Hash-A.jpg - 4/6 + * Hash-A.pdf - 4/6 + * Hash-B.jpg - 1/6 + * Hash-B.pdf - 1/6 + * Hash-C.jpg - 2/6 + * Hash-C.pdf - 2/6 + * Hash_D.doc - 2/6 + * Hash-D.jpg - 1/6 + * */ class InterCaseTestUtils { @@ -304,7 +318,6 @@ class InterCaseTestUtils { } } - //TODO refactor static boolean verifyInstanceExistanceAndCount(CommonAttributeSearchResults searchDomain, String fileName, String dataSource, String crCase, int instanceCount){ try { From ac31962c959190edc619589ab1e02e38dbf1b578 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Wed, 22 Aug 2018 17:20:34 -0600 Subject: [PATCH 25/40] frequency search tests --- ...stedWithHashAndFileTypeInterCaseTests.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java index a28d53302a..12277aafba 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java @@ -182,4 +182,56 @@ public class IngestedWithHashAndFileTypeInterCaseTests extends NbTestCase { Assert.fail(ex); } } + + /** + * We should be able to observe that certain files o no longer returned + * in the result set since they do not appear frequently enough. + */ + public void testThree(){ + try { + Map dataSources = this.utils.getDataSourceMap(); + + //note that the params false and false are presently meaningless because that feature is not supported yet + AbstractCommonAttributeSearcher builder = new AllInterCaseCommonAttributeSearcher(dataSources, false, false, 50); + + CommonAttributeSearchResults metadata = builder.findFiles(); + + assertTrue("Results should not be empty", metadata.size() != 0); + + //case 1 data set 1 + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_0_DAT, CASE1_DATASET_1, CASE1, 0)); + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_PDF, CASE1_DATASET_1, CASE1, 1)); + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_JPG, CASE1_DATASET_1, CASE1, 1)); + + //case 1 data set 2 + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_0_DAT, CASE1_DATASET_2, CASE1, 0)); + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_PDF, CASE1_DATASET_2, CASE1, 1)); + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_JPG, CASE1_DATASET_2, CASE1, 1)); + + //case 2 data set 1 + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_B_PDF, CASE2_DATASET_1, CASE2, 0)); + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_B_JPG, CASE2_DATASET_1, CASE2, 0)); + + //case 2 data set 2 + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_PDF, CASE2_DATASET_2, CASE2, 1)); + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_JPG, CASE2_DATASET_2, CASE2, 1)); + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_D_DOC, CASE2_DATASET_2, CASE2, 0)); + + //case 3 data set 1 + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_JPG, CASE3_DATASET_1, CASE3, 1)); + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_A_PDF, CASE3_DATASET_1, CASE3, 1)); + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_C_JPG, CASE3_DATASET_1, CASE3, 0)); + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_C_PDF, CASE3_DATASET_1, CASE3, 0)); + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_D_JPG, CASE3_DATASET_1, CASE3, 0)); + + //case 3 data set 2 + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_C_JPG, CASE3_DATASET_2, CASE3, 0)); + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_C_PDF, CASE3_DATASET_2, CASE3, 0)); + assertTrue(verifyInstanceExistanceAndCount(metadata, HASH_D_DOC, CASE3_DATASET_2, CASE3, 0)); + + } catch (TskCoreException | NoCurrentCaseException | SQLException | EamDbException ex) { + Exceptions.printStackTrace(ex); + Assert.fail(ex); + } + } } From 6fa58b9ca70fcbf7500ac97b2dde1f5ca4cd0287 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Wed, 22 Aug 2018 17:21:05 -0600 Subject: [PATCH 26/40] fixed a concurrentmodificationexception when pruning results for frequency percentage search --- .../CommonAttributeSearchResults.java | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java index 35b64e17b2..7539419b14 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java @@ -19,7 +19,9 @@ */ package org.sleuthkit.autopsy.commonfilesearch; +import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -96,10 +98,14 @@ final public class CommonAttributeSearchResults { * Remove results which are not found in the portion of available data * sources described by minimumPercentageThreshold. * - * @return + * @return metadata */ private Map> getMetadata(int minimumPercentageThreshold) throws EamDbException { + if(minimumPercentageThreshold == 0){ + return Collections.unmodifiableMap(this.instanceCountToAttributeValues); + } + CorrelationAttribute.Type fileAttributeType = CorrelationAttribute .getDefaultCorrelationTypes() .stream() @@ -108,20 +114,39 @@ final public class CommonAttributeSearchResults { EamDb eamDb = EamDb.getInstance(); + Map> itemsToRemove = new HashMap<>(); + for(Entry> listOfValues : Collections.unmodifiableMap(this.instanceCountToAttributeValues).entrySet()){ - Integer key = listOfValues.getKey(); + final Integer key = listOfValues.getKey(); + final List values = listOfValues.getValue(); - for(CommonAttributeValue value : listOfValues.getValue()){ + for(CommonAttributeValue value : values){ int frequencyPercentage = eamDb.getFrequencyPercentage(new CorrelationAttribute(fileAttributeType, value.getValue())); if(frequencyPercentage < minimumPercentageThreshold){ - this.instanceCountToAttributeValues.get(key).remove(value); + if(itemsToRemove.containsKey(key)){ + itemsToRemove.get(key).add(value); + } else { + List toRemove = new ArrayList<>(); + toRemove.add(value); + itemsToRemove.put(key, toRemove); + } } } } + for(Entry> valuesToRemove : itemsToRemove.entrySet()){ + + final Integer key = valuesToRemove.getKey(); + final List values = valuesToRemove.getValue(); + + for (CommonAttributeValue value : values){ + this.instanceCountToAttributeValues.get(key).remove(value); + } + } + return Collections.unmodifiableMap(this.instanceCountToAttributeValues); } From 41797943c2db8e01c67ad4dfaa8d6ba435cc17cf Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Wed, 22 Aug 2018 17:21:37 -0600 Subject: [PATCH 27/40] improved conditions for enabling frequency percentage search --- .../CommonAttributePanel.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java index 8635694b88..b48cca309a 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java @@ -87,11 +87,15 @@ public final class CommonAttributePanel extends javax.swing.JDialog { this.errorText.setVisible(false); this.setupDataSources(); - if (CommonAttributePanel.isEamDbAvailable()) { + if (CommonAttributePanel.isEamDbAvailableForIntercaseSearch()) { this.setupCases(); - this.enablePercentageOptions(); } else { this.disableIntercaseSearch(); + } + + if(CommonAttributePanel.isEamDbAvailableForPercentageFrequencyCalculations()){ + this.enablePercentageOptions(); + } else { this.disablePercentageOptions(); } @@ -125,7 +129,7 @@ public final class CommonAttributePanel extends javax.swing.JDialog { }); } - private static boolean isEamDbAvailable() { + private static boolean isEamDbAvailableForIntercaseSearch() { try { return EamDb.isEnabled() && EamDb.getInstance() != null @@ -138,6 +142,17 @@ public final class CommonAttributePanel extends javax.swing.JDialog { } return false; } + + private static boolean isEamDbAvailableForPercentageFrequencyCalculations(){ + try { + return EamDb.isEnabled() + && EamDb.getInstance() != null + && EamDb.getInstance().getCases().size() > 0; + } catch (EamDbException ex) { + LOGGER.log(Level.SEVERE, "Unexpected exception while checking for EamDB enabled.", ex); + } + return false; + } private void disableIntercaseSearch() { this.intraCaseRadio.setSelected(true); From 4be4c67de1556c15d3be6dd686885efc58e61413 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Wed, 22 Aug 2018 17:32:55 -0600 Subject: [PATCH 28/40] remove nodes with no children from ui --- .../commonfilesearch/CommonAttributeSearchResults.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java index 7539419b14..76f96a36b5 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java @@ -143,7 +143,12 @@ final public class CommonAttributeSearchResults { final List values = valuesToRemove.getValue(); for (CommonAttributeValue value : values){ - this.instanceCountToAttributeValues.get(key).remove(value); + final List instanceCountValue = this.instanceCountToAttributeValues.get(key); + instanceCountValue.remove(value); + + if(instanceCountValue.isEmpty()){ + this.instanceCountToAttributeValues.remove(key); + } } } From e70fc3210c592bb4e9359bc8c264d757ea127ad6 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Thu, 23 Aug 2018 10:47:12 -0600 Subject: [PATCH 29/40] assertion api changed slightly --- .../IngestedWithHashAndFileTypeInterCaseTests.java | 2 +- .../sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java | 2 +- .../sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java index a35a6c7273..a425ecbcc8 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java @@ -231,7 +231,7 @@ public class IngestedWithHashAndFileTypeInterCaseTests extends NbTestCase { } catch (TskCoreException | NoCurrentCaseException | SQLException | EamDbException ex) { Exceptions.printStackTrace(ex); - Assert.fail(ex); + Assert.fail(ex.getMessage()); } } } diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java index 1ecc6ff216..b4f6302d61 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java @@ -384,7 +384,7 @@ class InterCaseTestUtils { return tally == instanceCount; } catch (EamDbException ex) { Exceptions.printStackTrace(ex); - Assert.fail(ex); + Assert.fail(ex.getMessage()); return false; } } diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java index 6311543b9d..f2a06d01f1 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java @@ -218,7 +218,7 @@ class IntraCaseTestUtils { return instanceIdToDataSource; } catch (EamDbException ex) { Exceptions.printStackTrace(ex); - Assert.fail(ex); + Assert.fail(ex.getMessage()); return instanceIdToDataSource; } } From 4bd5fc4c9139c1bfc5b75d1ce15e40c29ef740e2 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Thu, 23 Aug 2018 11:58:03 -0600 Subject: [PATCH 30/40] protect against occasional use of unmodifiable collections --- .../CommonAttributeSearchResults.java | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java index 76f96a36b5..4374e11091 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java @@ -40,17 +40,6 @@ final public class CommonAttributeSearchResults { private final int percentageThreshold; - /** - * Create a values object which can be handed off to the node factories. - * - * @param values list of CommonAttributeValue indexed by size of - * CommonAttributeValue - */ - CommonAttributeSearchResults(Map> metadata) { - this.instanceCountToAttributeValues = metadata; - this.percentageThreshold = 0; - } - /** * Create a values object which can be handed off to the node factories. * @@ -58,7 +47,8 @@ final public class CommonAttributeSearchResults { * CommonAttributeValue */ CommonAttributeSearchResults(Map> metadata, int percentageThreshold) { - this.instanceCountToAttributeValues = metadata; + //wrap in a new object in case any client code has used an unmodifiable collection + this.instanceCountToAttributeValues = new HashMap<>(metadata); this.percentageThreshold = percentageThreshold; } From 656b4464d4922bc23ffb1d4cd9ad1b07edb90b86 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Thu, 23 Aug 2018 12:59:08 -0600 Subject: [PATCH 31/40] codacy stuff --- .../autopsy/commonfilesearch/CommonAttributePanel.java | 8 ++++---- .../CommonAttributeSearchResultRootNode.java | 1 - .../commonfilesearch/CommonAttributeSearchResults.java | 2 +- .../autopsy/commonfilesearch/UserInputErrorManager.java | 6 +++--- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java index b48cca309a..f9a5c114bc 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java @@ -110,19 +110,19 @@ public final class CommonAttributePanel extends javax.swing.JDialog { } @Override - public void insertUpdate(DocumentEvent e) { + public void insertUpdate(DocumentEvent event) { this.maintainSize(); CommonAttributePanel.this.percentageThresholdChanged(); } @Override - public void removeUpdate(DocumentEvent e) { + public void removeUpdate(DocumentEvent event) { this.maintainSize(); CommonAttributePanel.this.percentageThresholdChanged(); } @Override - public void changedUpdate(DocumentEvent e) { + public void changedUpdate(DocumentEvent event) { this.maintainSize(); CommonAttributePanel.this.percentageThresholdChanged(); } @@ -710,7 +710,7 @@ public final class CommonAttributePanel extends javax.swing.JDialog { try { this.percentageThresholdValue = Integer.parseInt(percentageString); - } catch (Exception e) { + } catch (NumberFormatException exception) { this.percentageThresholdValue = -1; } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResultRootNode.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResultRootNode.java index ef36025d8d..b44e79aa68 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResultRootNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResultRootNode.java @@ -24,7 +24,6 @@ import java.util.logging.Logger; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java index 4374e11091..82089fead9 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java @@ -99,7 +99,7 @@ final public class CommonAttributeSearchResults { CorrelationAttribute.Type fileAttributeType = CorrelationAttribute .getDefaultCorrelationTypes() .stream() - .filter(t -> t.getId() == CorrelationAttribute.FILES_TYPE_ID) + .filter(filterType -> filterType.getId() == CorrelationAttribute.FILES_TYPE_ID) .findFirst().get(); EamDb eamDb = EamDb.getInstance(); diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java index 11c22a3aec..5b3e806bd4 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java @@ -67,7 +67,7 @@ class UserInputErrorManager { * @return true for yes, else false */ boolean anyErrors(){ - return this.currentErrors.values().stream().anyMatch(errorMessage -> errorMessage.getStatus() == true); + return this.currentErrors.values().stream().anyMatch(errorMessage -> errorMessage.isErrorSet() == true); } /** @@ -75,7 +75,7 @@ class UserInputErrorManager { */ List getErrors(){ return this.currentErrors.values().stream() - .filter(errorMessage -> errorMessage.getStatus() == true) + .filter(errorMessage -> errorMessage.isErrorSet() == true) .map(ErrorMessage::getMessage) .collect(Collectors.toList()); } @@ -119,7 +119,7 @@ class UserInputErrorManager { * Return the status (true for error status, false for no error) * @return */ - boolean getStatus(){ + boolean isErrorSet(){ return this.status; } } From f4c253f1ae384a37c46466734d3b94215dc02395 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 27 Aug 2018 16:34:50 -0400 Subject: [PATCH 32/40] Removed a duplicate scan of the output directory for each manifest file --- .../autopsy/experimental/autoingest/AutoIngestManager.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 8dddd2a3e6..ebf1bda7b8 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -1431,10 +1431,6 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen sysLogger.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex); } } - Path caseDirectory = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName()); - if (null != caseDirectory) { - job.setCaseDirectoryPath(caseDirectory); - } newPendingJobsList.add(job); } From 46bb667bf3dbb8fb99b9fa219dada4aca42c0eb8 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Mon, 27 Aug 2018 16:52:26 -0400 Subject: [PATCH 33/40] No longer trying to find case output directory for each job while doing an input scan --- .../autoingest/AutoIngestManager.java | 80 +++++++++---------- 1 file changed, 38 insertions(+), 42 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index ebf1bda7b8..6239be509b 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -1398,10 +1398,6 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen AutoIngestJob job; if (nodeData.getVersion() == AutoIngestJobNodeData.getCurrentVersion()) { job = new AutoIngestJob(nodeData); - Path caseDirectory = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName()); - if (null != caseDirectory) { - job.setCaseDirectoryPath(caseDirectory); - } } else { job = new AutoIngestJob(manifest); job.setPriority(nodeData.getPriority()); // Retain priority, present in all versions of the node data. @@ -1591,54 +1587,53 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen * @throws InterruptedException */ private void addCompletedJob(Manifest manifest, AutoIngestJobNodeData nodeData) throws CoordinationServiceException, InterruptedException, AutoIngestJobException { - Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName()); - if (null != caseDirectoryPath) { - AutoIngestJob job; - if (nodeData.getVersion() == AutoIngestJobNodeData.getCurrentVersion()) { - job = new AutoIngestJob(nodeData); - job.setCaseDirectoryPath(caseDirectoryPath); - } else { - /** - * Use the manifest rather than the node data here to create - * a new AutoIngestJob instance because the AutoIngestJob - * constructor that takes a node data object expects the - * node data to have fields that do not exist in earlier - * versions. - */ - job = new AutoIngestJob(manifest); - job.setCaseDirectoryPath(caseDirectoryPath); + Path caseDirectoryPath = nodeData.getCaseDirectoryPath(); + if (!caseDirectoryPath.toFile().exists()) { + sysLogger.log(Level.WARNING, String.format("Job completed for %s, but cannot find case directory, ignoring job", nodeData.getManifestFilePath())); + return; + } - /** - * Update the job with the fields that exist in all versions - * of the nodeData. - */ - job.setCompletedDate(nodeData.getCompletedDate()); - job.setErrorsOccurred(nodeData.getErrorsOccurred()); - job.setPriority(nodeData.getPriority()); - job.setNumberOfCrashes(nodeData.getNumberOfCrashes()); - job.setProcessingStage(AutoIngestJob.Stage.COMPLETED, nodeData.getCompletedDate()); - job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED); + AutoIngestJob job; + if (nodeData.getVersion() == AutoIngestJobNodeData.getCurrentVersion()) { + job = new AutoIngestJob(nodeData); + job.setCaseDirectoryPath(caseDirectoryPath); + } else { + /** + * Use the manifest rather than the node data here to create a + * new AutoIngestJob instance because the AutoIngestJob + * constructor that takes a node data object expects the node + * data to have fields that do not exist in earlier versions. + */ + job = new AutoIngestJob(manifest); + job.setCaseDirectoryPath(caseDirectoryPath); - /* + /** + * Update the job with the fields that exist in all versions of + * the nodeData. + */ + job.setCompletedDate(nodeData.getCompletedDate()); + job.setErrorsOccurred(nodeData.getErrorsOccurred()); + job.setPriority(nodeData.getPriority()); + job.setNumberOfCrashes(nodeData.getNumberOfCrashes()); + job.setProcessingStage(AutoIngestJob.Stage.COMPLETED, nodeData.getCompletedDate()); + job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED); + + /* * Try to upgrade/update the coordination service manifest * node data for the job. It is possible that two hosts will * both try to obtain the lock to do the upgrade operation * at the same time. If this happens, the host that is * holding the lock will complete the upgrade operation. - */ - try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) { - if (null != manifestLock) { - updateCoordinationServiceManifestNode(job); - } - } catch (CoordinationServiceException ex) { - sysLogger.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex); + */ + try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) { + if (null != manifestLock) { + updateCoordinationServiceManifestNode(job); } + } catch (CoordinationServiceException ex) { + sysLogger.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifest.getFilePath()), ex); } - newCompletedJobsList.add(job); - - } else { - sysLogger.log(Level.WARNING, String.format("Job completed for %s, but cannot find case directory, ignoring job", nodeData.getManifestFilePath())); } + newCompletedJobsList.add(job); } /** @@ -2452,6 +2447,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen Thread.sleep(AutoIngestUserPreferences.getSecondsToSleepBetweenCases() * 1000); } currentJob.setCaseDirectoryPath(caseDirectoryPath); + updateCoordinationServiceManifestNode(currentJob); // update case directory path Case caseForJob = Case.getCurrentCase(); sysLogger.log(Level.INFO, "Opened case {0} for {1}", new Object[]{caseForJob.getName(), manifest.getFilePath()}); return caseForJob; From b5dcd2bd37862c5d18d5981463d37ea0657c21e8 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 28 Aug 2018 10:37:07 -0400 Subject: [PATCH 34/40] Additional logging --- .../autopsy/experimental/autoingest/AutoIngestManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 6239be509b..e8500e6ba2 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -1589,7 +1589,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen private void addCompletedJob(Manifest manifest, AutoIngestJobNodeData nodeData) throws CoordinationServiceException, InterruptedException, AutoIngestJobException { Path caseDirectoryPath = nodeData.getCaseDirectoryPath(); if (!caseDirectoryPath.toFile().exists()) { - sysLogger.log(Level.WARNING, String.format("Job completed for %s, but cannot find case directory, ignoring job", nodeData.getManifestFilePath())); + sysLogger.log(Level.WARNING, String.format("Job completed for %s, but cannot find case directory %s, ignoring job", nodeData.getManifestFilePath(), caseDirectoryPath.toString())); return; } From 120b3db105afc799bf5bccc7e8fe05c15cae6d65 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Tue, 28 Aug 2018 11:37:19 -0600 Subject: [PATCH 35/40] comparison was backwards --- .../commonfilesearch/CommonAttributeSearchResults.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java index e8efefa6f4..388dca1bab 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java @@ -86,13 +86,13 @@ final public class CommonAttributeSearchResults { * search. * * Remove results which are not found in the portion of available data - * sources described by minimumPercentageThreshold. + sources described by maximumPercentageThreshold. * * @return metadata */ - private Map> getMetadata(int minimumPercentageThreshold) throws EamDbException { + private Map> getMetadata(int maximumPercentageThreshold) throws EamDbException { - if(minimumPercentageThreshold == 0){ + if(maximumPercentageThreshold == 0){ return Collections.unmodifiableMap(this.instanceCountToAttributeValues); } @@ -115,7 +115,7 @@ final public class CommonAttributeSearchResults { int frequencyPercentage = eamDb.getFrequencyPercentage(new CorrelationAttributeInstance(fileAttributeType, value.getValue())); - if(frequencyPercentage < minimumPercentageThreshold){ + if(frequencyPercentage > maximumPercentageThreshold){ if(itemsToRemove.containsKey(key)){ itemsToRemove.get(key).add(value); } else { From ea29efccf3aa8cd6a8de0eea88f6f7ff77af675f Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Tue, 28 Aug 2018 13:24:03 -0700 Subject: [PATCH 36/40] Address PR feedback --- .../CommonAttributeValueList.java | 32 +++++++++++++++++-- .../commonfilesearch/InstanceCountNode.java | 31 +++++------------- .../DelayedLoadChildNodesOnTreeExpansion.java | 2 +- .../corecomponents/TableFilterNode.java | 4 +++ .../directorytree/DataResultFilterNode.java | 5 +++ .../commonfilessearch/InterCaseTestUtils.java | 7 ++-- .../commonfilessearch/IntraCaseTestUtils.java | 6 ++-- 7 files changed, 56 insertions(+), 31 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValueList.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValueList.java index f86f4c23ff..4797dbfd94 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValueList.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValueList.java @@ -30,7 +30,15 @@ import java.util.List; */ final public class CommonAttributeValueList { + /** + * The list of value nodes, which begins empty. + */ private final List metadataList; + + /** + * The backing list of value nodes, which will be dynamically loaded + * when requested. + */ private final List delayedMetadataList; /** @@ -49,21 +57,41 @@ final public class CommonAttributeValueList { this.delayedMetadataList = new ArrayList<>(); } + /** + * Get the list of value nodes. Will be empty if + * displayDelayedMetadata() has not been called for the + * parent InstanceCountNode + * @return metadataList the list of nodes + */ public List getMetadataList() { return Collections.unmodifiableList(this.metadataList); } - public int getCommonAttributeListSize() { + /** + * Return the size of the backing list, in case + * displayDelayedMetadata() has not be called yet. + * @return int the number of matches for this value + */ + int getCommonAttributeListSize() { return this.delayedMetadataList.size(); } + /** + * Dynamically load the list CommonAttributeValue when called. Until called + * metadataList should be empty. The parent node, InstanceCountNode, will + * trigger the factory call and refresh. + */ public void displayDelayedMetadata() { if (metadataList.isEmpty()) { this.metadataList.addAll(this.delayedMetadataList); } } - public void addMetadataToList(CommonAttributeValue metadata) { + /** + * A a value node to the list, to be loaded later. + * @param metadata the node to add + */ + void addMetadataToList(CommonAttributeValue metadata) { delayedMetadataList.add(metadata); } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java index b662102fc9..fa298c121d 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java @@ -23,9 +23,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.logging.Level; -import javax.swing.SwingWorker; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; @@ -76,26 +73,14 @@ final public class InstanceCountNode extends DisplayableItemNode { return this.instanceCount; } + /** + * Refresh the node, by dynamically loading in the children when called, and + * calling the CommonAttributeValueNodeFactory to generate nodes for the + * children in attributeValues. + */ public void refresh() { - new SwingWorker() { - - @Override - protected Void doInBackground() throws Exception { - attributeValues.displayDelayedMetadata(); - setChildren(Children.create(new CommonAttributeValueNodeFactory(attributeValues.getMetadataList()), false)); - return null; - } - - @Override - protected void done() { - super.done(); - try { - get(); - } catch (InterruptedException | ExecutionException ex) { - logger.log(Level.SEVERE, "Unexpected exception while loading common search result instances", ex); //NON-NLS - } - } - }.execute(); + attributeValues.displayDelayedMetadata(); + setChildren(Children.create(new CommonAttributeValueNodeFactory(attributeValues.getMetadataList()), true)); } /** @@ -147,7 +132,7 @@ final public class InstanceCountNode extends DisplayableItemNode { /** * ChildFactory which builds CommonFileParentNodes from the - * CommonFilesMetaaData models. + * CommonAttributeValue metadata models. */ static class CommonAttributeValueNodeFactory extends ChildFactory { diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java index a66f4a876a..6e6d28af2a 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DelayedLoadChildNodesOnTreeExpansion.java @@ -39,7 +39,7 @@ public final class DelayedLoadChildNodesOnTreeExpansion implements TreeExpansion @Override public synchronized void treeCollapsed(final TreeExpansionEvent event) { - + // Do nothing on collapse. Netbeans should manage nodes falling out of scope and GC. } @Override diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterNode.java b/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterNode.java index 890fb4ace3..2ba02f694a 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/TableFilterNode.java @@ -129,6 +129,10 @@ public class TableFilterNode extends FilterNode { } } + /** + * Refreshes the inner node, which depending on the actual node type that was wrapped + * could trigger a dynamic refresh of the children, if supported. + */ void refresh() { DataResultFilterNode innerNode = getLookup().lookup(DataResultFilterNode.class); innerNode.refresh(); diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index c639a96672..c94ad57094 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -140,6 +140,11 @@ public class DataResultFilterNode extends FilterNode { this.sourceEm = em; } + /** + * Refreshes the inner node. If the actual underlying node is an InstanceCountNode, + * refresh() that node, which refreshes the children. + * + */ public void refresh() { if (getOriginal() instanceof InstanceCountNode) { InstanceCountNode innerNode = getLookup().lookup(InstanceCountNode.class); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java index cf6bd36fbc..0feb32ee4c 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java @@ -57,6 +57,7 @@ import org.sleuthkit.autopsy.commonfilesearch.CentralRepoCommonAttributeInstance import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeSearchResults; import org.sleuthkit.autopsy.commonfilesearch.DataSourceLoader; import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeValue; +import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeValueList; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.datamodel.AbstractFile; @@ -309,9 +310,9 @@ class InterCaseTestUtils { int tally = 0; - for(Map.Entry> entry : searchDomain.getMetadata().entrySet()){ - - for(CommonAttributeValue value : entry.getValue()){ + for(Map.Entry entry : searchDomain.getMetadata().entrySet()){ + entry.getValue().displayDelayedMetadata(); + for(CommonAttributeValue value : entry.getValue().getMetadataList()) { for(AbstractCommonAttributeInstance commonAttribute : value.getInstances()){ diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java index 82c38cdf56..b03e6b2dfa 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java @@ -37,6 +37,7 @@ import org.sleuthkit.autopsy.commonfilesearch.AbstractCommonAttributeInstance; import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeSearchResults; import org.sleuthkit.autopsy.commonfilesearch.DataSourceLoader; import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeValue; +import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeValueList; import org.sleuthkit.autopsy.testutils.CaseUtils; import org.sleuthkit.autopsy.testutils.IngestUtils; import org.sleuthkit.datamodel.AbstractFile; @@ -205,8 +206,9 @@ class IntraCaseTestUtils { static Map mapFileInstancesToDataSources(CommonAttributeSearchResults metadata) { Map instanceIdToDataSource = new HashMap<>(); - for (Map.Entry> entry : metadata.getMetadata().entrySet()) { - for (CommonAttributeValue md : entry.getValue()) { + for (Map.Entry entry : metadata.getMetadata().entrySet()) { + entry.getValue().displayDelayedMetadata(); + for (CommonAttributeValue md : entry.getValue().getMetadataList()) { for (AbstractCommonAttributeInstance fim : md.getInstances()) { instanceIdToDataSource.put(fim.getAbstractFileObjectId(), fim.getDataSource()); } From e5f1936e1f0345272bfda1cbee1063cc301ff93b Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Tue, 28 Aug 2018 15:10:51 -0700 Subject: [PATCH 37/40] Make outlineView protected so that CommonAttributesSearchResultsViewerTable can add the treelistener itself. --- ...ommonAttributesSearchResultsViewerTable.java | 12 ++++++++++-- .../corecomponents/DataResultViewerTable.form | 1 + .../corecomponents/DataResultViewerTable.java | 17 ++--------------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributesSearchResultsViewerTable.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributesSearchResultsViewerTable.java index 0e051d5111..97a41b27be 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributesSearchResultsViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributesSearchResultsViewerTable.java @@ -60,9 +60,17 @@ public class CommonAttributesSearchResultsViewerTable extends DataResultViewerTa COLUMN_WIDTHS = Collections.unmodifiableMap(map); } - + /** + * Implements a DataResultViewerTable which constructs a tabular result viewer that + * displays the children of the given root node using an OutlineView. The explorer + * manager will be discovered at runtime. + * + * Adds a TreeExpansionsListener to the outlineView to receive tree expansion events + * which dynamically loads children nodes when requested. + */ public CommonAttributesSearchResultsViewerTable() { - super(new DelayedLoadChildNodesOnTreeExpansion()); + super(); + outlineView.addTreeExpansionListener(new DelayedLoadChildNodesOnTreeExpansion()); } @NbBundle.Messages({ diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.form index d6c32623a4..8ad47b32c7 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.form @@ -29,6 +29,7 @@ + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 1ef52568e1..024686e26f 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -47,7 +47,6 @@ import javax.swing.event.TableColumnModelListener; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; -import javax.swing.event.TreeExpansionListener; import org.netbeans.swing.etable.ETableColumn; import org.netbeans.swing.etable.ETableColumnModel; import org.netbeans.swing.outline.DefaultOutlineCellRenderer; @@ -103,20 +102,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { public DataResultViewerTable() { this(null, Bundle.DataResultViewerTable_title()); } - /** - * Constructs a tabular result viewer that displays the children of the - * given root node using an OutlineView. The viewer should have an ancestor - * top component to connect the lookups of the nodes displayed in the - * OutlineView to the actions global context. The explorer manager will be - * discovered at runtime. - * @param listener - */ - public DataResultViewerTable(TreeExpansionListener listener) { - this(null, Bundle.DataResultViewerTable_title()); - outlineView.addTreeExpansionListener(listener); - } - /** * Constructs a tabular result viewer that displays the children of a given @@ -201,6 +187,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { public String getTitle() { return title; } + /** * Indicates whether a given node is supported as a root node for this @@ -852,7 +839,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables - private org.openide.explorer.view.OutlineView outlineView; + protected org.openide.explorer.view.OutlineView outlineView; // End of variables declaration//GEN-END:variables } From c202db7261e24a526969906d783c8b538f84b343 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Tue, 28 Aug 2018 17:49:46 -0600 Subject: [PATCH 38/40] error messages truncated --- .../commonfilesearch/Bundle.properties | 14 +- .../CommonAttributePanel.form | 137 +++++++----- .../CommonAttributePanel.java | 195 ++++++++++-------- .../UserInputErrorManager.java | 2 +- 4 files changed, 206 insertions(+), 142 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties index 8864d4a73a..b8f2e3e0d7 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties @@ -9,10 +9,14 @@ IntraCasePanel.withinDataSourceRadioButton.text=At least one match must appear i IntraCasePanel.selectDataSourceComboBox.actionCommand= InterCasePanel.specificCentralRepoCaseRadio.text=Matches must be from the following Central Repo case: InterCasePanel.anyCentralRepoCaseRadio.text=Matches may be from any Central Repo case -CommonAttributePanel.commonFilesSearchLabel2.text=Scope of Search +CommonAttributePanel.jCheckBox1.text=Hide files found in over +CommonAttributePanel.jLabel1.text=% of data sources in central repository. +CommonAttributePanel.percentageThresholdTextTwo.text_1=% of data sources in central repository. +CommonAttributePanel.percentageThresholdTextOne.text=20 +CommonAttributePanel.percentageThresholdCheck.text_1=Hide files found in over CommonAttributePanel.intraCaseRadio.text=Within current case CommonAttributePanel.commonFilesSearchLabel1.text=Find common files to correlate data soures or cases. -CommonAttributePanel.errorText.text=In order to search, you must select a file category. +CommonAttributePanel.errorText.text=In order to search, you must select a file category. CommonAttributePanel.categoriesLabel.text=File Types To Include: CommonAttributePanel.documentsCheckbox.text=Documents CommonAttributePanel.pictureVideoCheckbox.text=Pictures and Videos @@ -23,8 +27,4 @@ CommonAttributePanel.allFileCategoriesRadioButton.text=All file types CommonAttributePanel.cancelButton.actionCommand=Cancel CommonAttributePanel.cancelButton.text=Cancel CommonAttributePanel.searchButton.text=Search -CommonAttributePanel.jCheckBox1.text=Hide files found in over -CommonAttributePanel.jLabel1.text=% of data sources in central repository. -CommonAttributePanel.percentageThreshold.text=20 -CommonAttributePanel.jLabel1.text_1=% of data sources in central repository. -CommonAttributePanel.percentageThresholdCheck.text_1=Hide files found in over +CommonAttributePanel.commonFilesSearchLabel2.text=Scope of Search diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form index 329de08aef..20cbb33fe9 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form @@ -8,8 +8,11 @@ + + + - + @@ -29,7 +32,7 @@ - + @@ -37,14 +40,15 @@ - + - + - + + @@ -55,45 +59,57 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -123,16 +139,22 @@ - - + + - - - - + + + + + + + + + + - + @@ -243,6 +265,7 @@ + @@ -310,10 +333,10 @@ - + - + @@ -326,13 +349,33 @@ - + - + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java index f9a5c114bc..1955b17ac9 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java @@ -84,7 +84,7 @@ public final class CommonAttributePanel extends javax.swing.JDialog { initComponents(); this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); - this.errorText.setVisible(false); + //this.errorText.setVisible(false); this.setupDataSources(); if (CommonAttributePanel.isEamDbAvailableForIntercaseSearch()) { @@ -101,12 +101,12 @@ public final class CommonAttributePanel extends javax.swing.JDialog { this.errorManager = new UserInputErrorManager(); - this.percentageThreshold.getDocument().addDocumentListener(new DocumentListener(){ + this.percentageThresholdTextOne.getDocument().addDocumentListener(new DocumentListener(){ - private Dimension preferredSize = CommonAttributePanel.this.percentageThreshold.getPreferredSize(); + private Dimension preferredSize = CommonAttributePanel.this.percentageThresholdTextOne.getPreferredSize(); private void maintainSize(){ - CommonAttributePanel.this.percentageThreshold.setSize(preferredSize); + CommonAttributePanel.this.percentageThresholdTextOne.setSize(preferredSize); } @Override @@ -466,10 +466,13 @@ public final class CommonAttributePanel extends javax.swing.JDialog { intraCasePanel = new org.sleuthkit.autopsy.commonfilesearch.IntraCasePanel(); interCasePanel = new org.sleuthkit.autopsy.commonfilesearch.InterCasePanel(); percentageThresholdCheck = new javax.swing.JCheckBox(); - percentageThreshold = new javax.swing.JTextField(); - jLabel1 = new javax.swing.JLabel(); + percentageThresholdTextOne = new javax.swing.JTextField(); + percentageThresholdTextTwo = new javax.swing.JLabel(); + filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 32767)); + filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 32767)); - setMinimumSize(new java.awt.Dimension(412, 375)); + setMaximumSize(new java.awt.Dimension(450, 375)); + setMinimumSize(new java.awt.Dimension(450, 375)); setResizable(false); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosed(java.awt.event.WindowEvent evt) { @@ -477,9 +480,10 @@ public final class CommonAttributePanel extends javax.swing.JDialog { } }); - jPanel1.setMaximumSize(new java.awt.Dimension(412, 375)); - jPanel1.setMinimumSize(new java.awt.Dimension(412, 375)); - jPanel1.setPreferredSize(new java.awt.Dimension(412, 375)); + jPanel1.setMaximumSize(new java.awt.Dimension(450, 375)); + jPanel1.setMinimumSize(new java.awt.Dimension(450, 375)); + jPanel1.setPreferredSize(new java.awt.Dimension(450, 375)); + jPanel1.setRequestFocusEnabled(false); org.openide.awt.Mnemonics.setLocalizedText(commonFilesSearchLabel2, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.commonFilesSearchLabel2.text")); // NOI18N commonFilesSearchLabel2.setFocusable(false); @@ -542,6 +546,7 @@ public final class CommonAttributePanel extends javax.swing.JDialog { errorText.setForeground(new java.awt.Color(255, 0, 0)); org.openide.awt.Mnemonics.setLocalizedText(errorText, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.errorText.text")); // NOI18N + errorText.setVerticalAlignment(javax.swing.SwingConstants.TOP); org.openide.awt.Mnemonics.setLocalizedText(commonFilesSearchLabel1, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.commonFilesSearchLabel1.text")); // NOI18N commonFilesSearchLabel1.setFocusable(false); @@ -574,12 +579,12 @@ public final class CommonAttributePanel extends javax.swing.JDialog { } }); - percentageThreshold.setText(org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.percentageThreshold.text")); // NOI18N - percentageThreshold.setMaximumSize(new java.awt.Dimension(40, 24)); - percentageThreshold.setMinimumSize(new java.awt.Dimension(40, 24)); - percentageThreshold.setPreferredSize(new java.awt.Dimension(40, 24)); + percentageThresholdTextOne.setText(org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.percentageThresholdTextOne.text")); // NOI18N + percentageThresholdTextOne.setMaximumSize(new java.awt.Dimension(40, 24)); + percentageThresholdTextOne.setMinimumSize(new java.awt.Dimension(40, 24)); + percentageThresholdTextOne.setPreferredSize(new java.awt.Dimension(40, 24)); - org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.jLabel1.text_1")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(percentageThresholdTextTwo, org.openide.util.NbBundle.getMessage(CommonAttributePanel.class, "CommonAttributePanel.percentageThresholdTextTwo.text_1")); // NOI18N javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); @@ -588,35 +593,43 @@ public final class CommonAttributePanel extends javax.swing.JDialog { .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(commonFilesSearchLabel2) - .addComponent(intraCaseRadio) - .addComponent(interCaseRadio) - .addComponent(commonFilesSearchLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(categoriesLabel) - .addComponent(selectedFileCategoriesButton) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(29, 29, 29) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(documentsCheckbox) - .addComponent(pictureVideoCheckbox))) - .addComponent(allFileCategoriesRadioButton) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() - .addGap(10, 10, 10) - .addComponent(layoutPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(percentageThresholdCheck) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(percentageThreshold, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jLabel1)) - .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addComponent(searchButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(cancelButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(errorText))) - .addContainerGap()) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(80, 80, 80) + .addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(errorText))) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(commonFilesSearchLabel2) + .addComponent(intraCaseRadio) + .addComponent(interCaseRadio) + .addComponent(commonFilesSearchLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(categoriesLabel) + .addComponent(selectedFileCategoriesButton) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(29, 29, 29) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(documentsCheckbox) + .addComponent(pictureVideoCheckbox))) + .addComponent(allFileCategoriesRadioButton) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() + .addGap(10, 10, 10) + .addComponent(layoutPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(percentageThresholdCheck) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(percentageThresholdTextOne, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(percentageThresholdTextTwo))) + .addContainerGap(9, Short.MAX_VALUE)))) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -644,68 +657,72 @@ public final class CommonAttributePanel extends javax.swing.JDialog { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(percentageThresholdCheck) - .addComponent(percentageThreshold, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jLabel1)) + .addComponent(percentageThresholdTextOne, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(percentageThresholdTextTwo)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(searchButton) - .addComponent(cancelButton) - .addComponent(errorText)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(filler2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(searchButton) + .addComponent(cancelButton) + .addComponent(errorText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap()) ); getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER); }// //GEN-END:initComponents - private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchButtonActionPerformed - search(); - SwingUtilities.windowForComponent(this).dispose(); - }//GEN-LAST:event_searchButtonActionPerformed - - private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed - SwingUtilities.windowForComponent(this).dispose(); - }//GEN-LAST:event_cancelButtonActionPerformed - - private void allFileCategoriesRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allFileCategoriesRadioButtonActionPerformed - this.handleFileTypeCheckBoxState(); - }//GEN-LAST:event_allFileCategoriesRadioButtonActionPerformed - - private void selectedFileCategoriesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectedFileCategoriesButtonActionPerformed - this.handleFileTypeCheckBoxState(); - }//GEN-LAST:event_selectedFileCategoriesButtonActionPerformed - - private void pictureVideoCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pictureVideoCheckboxActionPerformed - this.handleFileTypeCheckBoxState(); - }//GEN-LAST:event_pictureVideoCheckboxActionPerformed - - private void documentsCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_documentsCheckboxActionPerformed - this.handleFileTypeCheckBoxState(); - }//GEN-LAST:event_documentsCheckboxActionPerformed - - private void intraCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_intraCaseRadioActionPerformed - ((java.awt.CardLayout) this.layoutPanel.getLayout()).first(this.layoutPanel); - }//GEN-LAST:event_intraCaseRadioActionPerformed - - private void interCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_interCaseRadioActionPerformed - ((java.awt.CardLayout) this.layoutPanel.getLayout()).last(this.layoutPanel); - }//GEN-LAST:event_interCaseRadioActionPerformed - private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed SwingUtilities.windowForComponent(this).dispose(); }//GEN-LAST:event_formWindowClosed private void percentageThresholdCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_percentageThresholdCheckActionPerformed if (this.percentageThresholdCheck.isSelected()) { - this.percentageThreshold.setEnabled(true); + this.percentageThresholdTextOne.setEnabled(true); } else { - this.percentageThreshold.setEnabled(false); + this.percentageThresholdTextOne.setEnabled(false); } this.handleFrequencyPercentageState(); }//GEN-LAST:event_percentageThresholdCheckActionPerformed + private void interCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_interCaseRadioActionPerformed + ((java.awt.CardLayout) this.layoutPanel.getLayout()).last(this.layoutPanel); + }//GEN-LAST:event_interCaseRadioActionPerformed + + private void intraCaseRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_intraCaseRadioActionPerformed + ((java.awt.CardLayout) this.layoutPanel.getLayout()).first(this.layoutPanel); + }//GEN-LAST:event_intraCaseRadioActionPerformed + + private void documentsCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_documentsCheckboxActionPerformed + this.handleFileTypeCheckBoxState(); + }//GEN-LAST:event_documentsCheckboxActionPerformed + + private void pictureVideoCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pictureVideoCheckboxActionPerformed + this.handleFileTypeCheckBoxState(); + }//GEN-LAST:event_pictureVideoCheckboxActionPerformed + + private void selectedFileCategoriesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectedFileCategoriesButtonActionPerformed + this.handleFileTypeCheckBoxState(); + }//GEN-LAST:event_selectedFileCategoriesButtonActionPerformed + + private void allFileCategoriesRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allFileCategoriesRadioButtonActionPerformed + this.handleFileTypeCheckBoxState(); + }//GEN-LAST:event_allFileCategoriesRadioButtonActionPerformed + + private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed + SwingUtilities.windowForComponent(this).dispose(); + }//GEN-LAST:event_cancelButtonActionPerformed + + private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchButtonActionPerformed + search(); + SwingUtilities.windowForComponent(this).dispose(); + }//GEN-LAST:event_searchButtonActionPerformed + private void percentageThresholdChanged(){ - String percentageString = this.percentageThreshold.getText(); + String percentageString = this.percentageThresholdTextOne.getText(); try { this.percentageThresholdValue = Integer.parseInt(percentageString); @@ -731,15 +748,17 @@ public final class CommonAttributePanel extends javax.swing.JDialog { } private void enablePercentageOptions() { - this.percentageThreshold.setEnabled(true); + this.percentageThresholdTextOne.setEnabled(true); this.percentageThresholdCheck.setEnabled(true); this.percentageThresholdCheck.setSelected(true); + this.percentageThresholdTextTwo.setEnabled(true); } private void disablePercentageOptions() { - this.percentageThreshold.setEnabled(false); + this.percentageThresholdTextOne.setEnabled(false); this.percentageThresholdCheck.setEnabled(false); this.percentageThresholdCheck.setSelected(false); + this.percentageThresholdTextTwo.setEnabled(false); } private void handleFileTypeCheckBoxState() { @@ -791,16 +810,18 @@ public final class CommonAttributePanel extends javax.swing.JDialog { private javax.swing.JCheckBox documentsCheckbox; private javax.swing.JLabel errorText; private javax.swing.ButtonGroup fileTypeFilterButtonGroup; + private javax.swing.Box.Filler filler1; + private javax.swing.Box.Filler filler2; private org.sleuthkit.autopsy.commonfilesearch.InterCasePanel interCasePanel; private javax.swing.JRadioButton interCaseRadio; private javax.swing.ButtonGroup interIntraButtonGroup; private org.sleuthkit.autopsy.commonfilesearch.IntraCasePanel intraCasePanel; private javax.swing.JRadioButton intraCaseRadio; - private javax.swing.JLabel jLabel1; private javax.swing.JPanel jPanel1; private java.awt.Panel layoutPanel; - private javax.swing.JTextField percentageThreshold; private javax.swing.JCheckBox percentageThresholdCheck; + private javax.swing.JTextField percentageThresholdTextOne; + private javax.swing.JLabel percentageThresholdTextTwo; private javax.swing.JCheckBox pictureVideoCheckbox; private javax.swing.JButton searchButton; private javax.swing.JRadioButton selectedFileCategoriesButton; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java index 5b3e806bd4..358891da38 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java @@ -45,7 +45,7 @@ class UserInputErrorManager { // and add them to the map. this.currentErrors = new HashMap<>(); - this.currentErrors.put(FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, new ErrorMessage("Frequency percentage must be greater than zero and less than or equal to 100.")); + this.currentErrors.put(FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, new ErrorMessage("Invalid Frequency Percentage: 0 < % < 100.")); this.currentErrors.put(NO_FILE_CATEGORIES_SELECTED_KEY, new ErrorMessage("No file categories are included in the search.")); } From 59efa9bf0e8003abcdcf16b1aa48e4b27f6e8db3 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Tue, 28 Aug 2018 17:53:30 -0600 Subject: [PATCH 39/40] removed dead code --- .../sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java index 1955b17ac9..21f2b72624 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java @@ -84,7 +84,6 @@ public final class CommonAttributePanel extends javax.swing.JDialog { initComponents(); this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); - //this.errorText.setVisible(false); this.setupDataSources(); if (CommonAttributePanel.isEamDbAvailableForIntercaseSearch()) { From 333060bebb07eb7cd4d0654dbfba742ba5bbd5dd Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Tue, 28 Aug 2018 18:15:35 -0600 Subject: [PATCH 40/40] ui text added to bundles --- .../autopsy/commonfilesearch/UserInputErrorManager.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java index 358891da38..3e09e32193 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import org.openide.util.NbBundle; /** * Manager for present state of errors on the Common Files Search. @@ -39,14 +40,17 @@ class UserInputErrorManager { * of all known error states, retrieve error messages, and determine if * anything is in an error state. */ + @NbBundle.Messages({ + "UserInputErrorManager.frequency=Invalid Frequency Percentage: 0 < % < 100.", + "UserInputErrorManager.categories=No file categories are included in the search."}) UserInputErrorManager (){ //when new errors are needed for the dialog, define a key and a value // and add them to the map. this.currentErrors = new HashMap<>(); - this.currentErrors.put(FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, new ErrorMessage("Invalid Frequency Percentage: 0 < % < 100.")); - this.currentErrors.put(NO_FILE_CATEGORIES_SELECTED_KEY, new ErrorMessage("No file categories are included in the search.")); + this.currentErrors.put(FREQUENCY_PERCENTAGE_OUT_OF_RANGE_KEY, new ErrorMessage(Bundle.UserInputErrorManager_frequency())); + this.currentErrors.put(NO_FILE_CATEGORIES_SELECTED_KEY, new ErrorMessage(Bundle.UserInputErrorManager_categories())); } /**