From a89c4f6538a6799437849b5cc28c18d8016b37f4 Mon Sep 17 00:00:00 2001 From: Andrew Ziehl Date: Thu, 29 Mar 2018 17:56:55 -0700 Subject: [PATCH] re-work child factories to have better model inheritance. Need to update package locations, fix sqlWhereClause --- .../commonfilesearch/AllCommonFiles.java | 6 +- .../commonfilesearch/CommonFilesChildren.java | 39 +++-------- .../CommonFilesDescendants.java | 2 +- .../commonfilesearch/CommonFilesMetaData.java | 61 +++++++----------- .../commonfilesearch/CommonFilesPanel.java | 64 +++++++++++++++++-- .../CommonFilesSearchNode.java | 5 +- .../SingleDataSourceCommonFiles.java | 6 +- .../datamodel/CommonFileParentNode.java | 17 +++-- 8 files changed, 114 insertions(+), 86 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllCommonFiles.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllCommonFiles.java index 9175e80837..004a706e9b 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllCommonFiles.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllCommonFiles.java @@ -20,7 +20,9 @@ package org.sleuthkit.autopsy.commonfilesearch; import java.sql.SQLException; +import java.util.List; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.TskCoreException; /** @@ -28,8 +30,8 @@ import org.sleuthkit.datamodel.TskCoreException; */ public class AllCommonFiles extends CommonFilesMetaData { - AllCommonFiles() throws TskCoreException, SQLException, NoCurrentCaseException{ - super(); + AllCommonFiles(String md5, List childNodes) throws TskCoreException, SQLException, NoCurrentCaseException{ + super(md5, childNodes); } private final String whereClause = "md5 in (select md5 from tsk_files where (known != 1 OR known IS NULL) GROUP BY md5 HAVING COUNT(*) > 1) order by md5"; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesChildren.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesChildren.java index 3773f21c95..025c9a4952 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesChildren.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesChildren.java @@ -32,51 +32,30 @@ import org.sleuthkit.autopsy.datamodel.CommonFileParentNode; /** * Makes nodes for common files search results. */ -final class CommonFilesChildren extends ChildFactory { +public final class CommonFilesChildren extends ChildFactory { - private CommonFilesMetaData metaData; + private List metaDataList; - CommonFilesChildren(CommonFilesMetaData theMetaData) { + public CommonFilesChildren(List theMetaDataList) { super(); - this.metaData = theMetaData; + this.metaDataList = theMetaDataList; } protected void removeNotify() { - metaData = null; + metaDataList = null; } @Override - protected Node createNodeForKey(String md5) { + protected Node createNodeForKey(CommonFilesMetaData metaData) { - List children = this.metaData.getChildrenForFile(md5); - - int instanceCount = children.size(); - String dataSources = selectDataSources(children); - - return new CommonFileParentNode(Children.create(new CommonFilesDescendants(children, this.metaData.getDataSourceIdToNameMap()), true), md5, instanceCount, dataSources); + return new CommonFileParentNode(metaData); } @Override - protected boolean createKeys(List toPopulate) { - final Map> filesMap = this.metaData.getFilesMap(); - Collection files = filesMap.keySet(); - toPopulate.addAll(files); + protected boolean createKeys(List toPopulate) { + toPopulate.addAll(metaDataList); return true; } - private String selectDataSources(List children) { - Map dataSources = this.metaData.getDataSourceIdToNameMap(); - - Set dataSourceStrings = new HashSet<>(); - - for (AbstractFile child : children) { - - String dataSource = dataSources.get(child.getDataSourceObjectId()); - - dataSourceStrings.add(dataSource); - } - - return String.join(", ", dataSourceStrings); - } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesDescendants.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesDescendants.java index d22f6bb866..c3ba7cdee1 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesDescendants.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesDescendants.java @@ -34,7 +34,7 @@ public class CommonFilesDescendants extends ChildFactory { private final List descendants; private Map dataSourceMap; - CommonFilesDescendants(List descendants, Map dataSourceMap){ + public CommonFilesDescendants(List descendants, Map dataSourceMap){ super(); this.descendants = descendants; this.dataSourceMap = dataSourceMap; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetaData.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetaData.java index c0b4ba660c..58a049ebdd 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetaData.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetaData.java @@ -24,8 +24,10 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.datamodel.AbstractFile; @@ -36,15 +38,17 @@ import org.sleuthkit.datamodel.TskCoreException; * Utility and wrapper around data required for Common Files Search results. * Subclass this to implement different selections of files from the case. */ -abstract class CommonFilesMetaData { +public abstract class CommonFilesMetaData { - private final Map> parentNodes; + private final String parentMd5; + private final List children; private final Map dataSourceIdToNameMap; private final SleuthkitCase sleuthkitCase; - CommonFilesMetaData() throws TskCoreException, SQLException, NoCurrentCaseException { - parentNodes = new HashMap<>(); + CommonFilesMetaData(String md5, List childNodes) throws TskCoreException, SQLException, NoCurrentCaseException { + parentMd5 = md5; + children = childNodes; dataSourceIdToNameMap = new HashMap<>(); this.sleuthkitCase = Case.getOpenCase().getSleuthkitCase(); @@ -66,40 +70,31 @@ abstract class CommonFilesMetaData { } } } - - Map> getFilesMap() { - return Collections.unmodifiableMap(this.parentNodes); + public String getMd5() { + return parentMd5; + } + public List getChildren() { + return Collections.unmodifiableList(this.children); } - Map getDataSourceIdToNameMap() { + public Map getDataSourceIdToNameMap() { return Collections.unmodifiableMap(dataSourceIdToNameMap); } - /** - * Sorts files in selection into a parent/child hierarchy where actual files - * are nested beneath a parent node which represents the common match. - * - * @return returns a reference to itself for ease of use. - * @throws TskCoreException - */ - CommonFilesMetaData collateFiles() throws TskCoreException { + public String selectDataSources() { - List files = this.sleuthkitCase.findAllFilesWhere(getSqlWhereClause()); + Map dataSources = this.getDataSourceIdToNameMap(); - for (AbstractFile file : files) { + Set dataSourceStrings = new HashSet<>(); - String currentMd5 = file.getMd5Hash(); - - if(parentNodes.containsKey(currentMd5)){ - parentNodes.get(currentMd5).add(file); - } else { - List children = new ArrayList<>(); - children.add(file); - parentNodes.put(currentMd5, children); - } + for (AbstractFile child : getChildren()) { + + String dataSource = dataSources.get(child.getDataSourceObjectId()); + + dataSourceStrings.add(dataSource); } - - return this; + + return String.join(", ", dataSourceStrings); } /** @@ -112,12 +107,4 @@ abstract class CommonFilesMetaData { */ protected abstract String getSqlWhereClause(); - /** - * - * @param t - * @return - */ - List getChildrenForFile(String md5) { - return this.parentNodes.get(md5); - } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java index 0f02c77738..4b7a751c97 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java @@ -21,7 +21,9 @@ package org.sleuthkit.autopsy.commonfilesearch; import java.awt.event.ActionListener; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ExecutionException; @@ -30,6 +32,7 @@ import javax.swing.AbstractListModel; import javax.swing.ComboBoxModel; import javax.swing.SwingWorker; import javax.swing.event.ListDataListener; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -39,6 +42,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery; import org.sleuthkit.datamodel.TskCoreException; @@ -114,6 +118,47 @@ public final class CommonFilesPanel extends javax.swing.JPanel { void addListenerToAll(ActionListener l) { //TODO double click the button this.searchButton.addActionListener(l); } + + /** + * Sorts files in selection into a parent/child hierarchy where actual files + * are nested beneath a parent node which represents the common match. + * + * @return returns a reference to itself for ease of use. + * @throws TskCoreException + */ + private List collateFiles() throws TskCoreException, SQLException { + + SleuthkitCase sleuthkitCase; + List metaDataModels = new ArrayList<>(); + try { + sleuthkitCase = Case.getOpenCase().getSleuthkitCase(); + String whereClause = "md5 in (select md5 from tsk_files where (known != 1 OR known IS NULL) GROUP BY md5 HAVING COUNT(*) > 1) order by md5"; + + List files = sleuthkitCase.findAllFilesWhere(whereClause); + Map> parentNodes = new HashMap<>(); + for (AbstractFile file : files) { + + String currentMd5 = file.getMd5Hash(); + + if (parentNodes.containsKey(currentMd5)) { + parentNodes.get(currentMd5).add(file); + } else { + List children = new ArrayList<>(); + children.add(file); + parentNodes.put(currentMd5, children); + } + } + for (String key : parentNodes.keySet()) { + metaDataModels.add(new AllCommonFiles(key, parentNodes.get(key))); + } + } catch (NoCurrentCaseException ex) { + Exceptions.printStackTrace(ex); + } + + + + return metaDataModels; + } @NbBundle.Messages({ "CommonFilesPanel.search.results.title=Common Files", @@ -128,11 +173,11 @@ public final class CommonFilesPanel extends javax.swing.JPanel { String title = Bundle.CommonFilesPanel_search_results_title(); String pathText = Bundle.CommonFilesPanel_search_results_pathText(); - new SwingWorker() { + new SwingWorker, Void>() { @Override @SuppressWarnings("FinallyDiscardsException") - protected CommonFilesMetaData doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException { + protected List doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException { //TODO cleanup - encapsulate business logic if(singleDataSource) { @@ -143,9 +188,11 @@ public final class CommonFilesPanel extends javax.swing.JPanel { break; } } - return new SingleDataSourceCommonFiles(selectedObjId).collateFiles(); + //return new SingleDataSourceCommonFiles(selectedObjId).collateFiles(); + return collateFiles(); } else { - return new AllCommonFiles().collateFiles(); + //return new AllCommonFiles().collateFiles(); + return collateFiles(); } } @@ -154,7 +201,7 @@ public final class CommonFilesPanel extends javax.swing.JPanel { try { super.done(); - CommonFilesMetaData metadata = get(); + List metadata = get(); CommonFilesSearchNode commonFilesNode = new CommonFilesSearchNode(metadata); @@ -165,8 +212,11 @@ public final class CommonFilesPanel extends javax.swing.JPanel { DataResultTopComponent component = DataResultTopComponent.createInstance(title); //component.enableTreeMode(); - - DataResultTopComponent.initInstance(pathText, tableFilterWithDescendantsNode, metadata.getFilesMap().size(), component); + int totalNodes = 0; + for(CommonFilesMetaData meta : metadata) { + totalNodes += meta.getChildren().size(); + } + DataResultTopComponent.initInstance(pathText, tableFilterWithDescendantsNode, totalNodes, component); } catch (InterruptedException ex) { LOGGER.log(Level.SEVERE, "Interrupted while loading Common Files", ex); diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesSearchNode.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesSearchNode.java index 4de7206c01..c2cb71e219 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesSearchNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesSearchNode.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.commonfilesearch; +import java.util.List; import org.openide.nodes.Children; import org.openide.util.NbBundle; import org.openide.util.lookup.Lookups; @@ -30,8 +31,8 @@ import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; */ final public class CommonFilesSearchNode extends DisplayableItemNode { - CommonFilesSearchNode(CommonFilesMetaData metaData) { - super(Children.create(new CommonFilesChildren(metaData), true), Lookups.singleton(metaData)); + CommonFilesSearchNode(List metaDataList) { + super(Children.create(new CommonFilesChildren(metaDataList), true), Lookups.singleton(metaDataList)); } @NbBundle.Messages({ diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleDataSourceCommonFiles.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleDataSourceCommonFiles.java index 31b7b67967..c64bdcfb7b 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleDataSourceCommonFiles.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleDataSourceCommonFiles.java @@ -20,7 +20,9 @@ package org.sleuthkit.autopsy.commonfilesearch; import java.sql.SQLException; +import java.util.List; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.TskCoreException; /** @@ -30,8 +32,8 @@ public class SingleDataSourceCommonFiles extends CommonFilesMetaData { private final String whereClause; - SingleDataSourceCommonFiles(long dataSourceId) throws TskCoreException, SQLException, NoCurrentCaseException{ - super(); + SingleDataSourceCommonFiles(String md5, List childNodes, long dataSourceId) throws TskCoreException, SQLException, NoCurrentCaseException{ + super(md5, childNodes); Object[] args = new String[] {Long.toString(dataSourceId), Long.toString(dataSourceId)}; this.whereClause = String.format( diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/CommonFileParentNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/CommonFileParentNode.java index c3dfb10d34..f28424ff0c 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/CommonFileParentNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/CommonFileParentNode.java @@ -24,6 +24,10 @@ import java.util.Map; import org.openide.nodes.Children; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.lookup.Lookups; +import org.sleuthkit.autopsy.commonfilesearch.CommonFilesChildren; +import org.sleuthkit.autopsy.commonfilesearch.CommonFilesDescendants; +import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetaData; /** * Represents a common files match - two or more files which appear to be the @@ -35,11 +39,14 @@ public class CommonFileParentNode extends DisplayableItemNode { private final int commonFileCount; private final String dataSources; - public CommonFileParentNode(Children children, String md5Hash, int commonFileCount, String dataSources) { - super(children); - this.commonFileCount = commonFileCount; - this.dataSources = dataSources; - this.md5Hash = md5Hash; + public CommonFileParentNode(CommonFilesMetaData metaData) { + super(Children.create( + new CommonFilesDescendants(metaData.getChildren(), + metaData.getDataSourceIdToNameMap()), true), + Lookups.singleton(metaData)); + this.commonFileCount = metaData.getChildren().size(); + this.dataSources = metaData.selectDataSources(); + this.md5Hash = metaData.getMd5(); this.setDisplayName(md5Hash); }