re-work child factories to have better model inheritance. Need to update package locations, fix sqlWhereClause

This commit is contained in:
Andrew Ziehl 2018-03-29 17:56:55 -07:00 committed by Brian Sweeney
parent 4a7fbdae59
commit a89c4f6538
8 changed files with 114 additions and 86 deletions

View File

@ -20,7 +20,9 @@
package org.sleuthkit.autopsy.commonfilesearch; package org.sleuthkit.autopsy.commonfilesearch;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
@ -28,8 +30,8 @@ import org.sleuthkit.datamodel.TskCoreException;
*/ */
public class AllCommonFiles extends CommonFilesMetaData { public class AllCommonFiles extends CommonFilesMetaData {
AllCommonFiles() throws TskCoreException, SQLException, NoCurrentCaseException{ AllCommonFiles(String md5, List<AbstractFile> childNodes) throws TskCoreException, SQLException, NoCurrentCaseException{
super(); 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"; 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";

View File

@ -32,51 +32,30 @@ import org.sleuthkit.autopsy.datamodel.CommonFileParentNode;
/** /**
* Makes nodes for common files search results. * Makes nodes for common files search results.
*/ */
final class CommonFilesChildren extends ChildFactory<String> { public final class CommonFilesChildren extends ChildFactory<CommonFilesMetaData> {
private CommonFilesMetaData metaData; private List<CommonFilesMetaData> metaDataList;
CommonFilesChildren(CommonFilesMetaData theMetaData) { public CommonFilesChildren(List<CommonFilesMetaData> theMetaDataList) {
super(); super();
this.metaData = theMetaData; this.metaDataList = theMetaDataList;
} }
protected void removeNotify() { protected void removeNotify() {
metaData = null; metaDataList = null;
} }
@Override @Override
protected Node createNodeForKey(String md5) { protected Node createNodeForKey(CommonFilesMetaData metaData) {
List<AbstractFile> children = this.metaData.getChildrenForFile(md5); return new CommonFileParentNode(metaData);
int instanceCount = children.size();
String dataSources = selectDataSources(children);
return new CommonFileParentNode(Children.create(new CommonFilesDescendants(children, this.metaData.getDataSourceIdToNameMap()), true), md5, instanceCount, dataSources);
} }
@Override @Override
protected boolean createKeys(List<String> toPopulate) { protected boolean createKeys(List<CommonFilesMetaData> toPopulate) {
final Map<String, List<org.sleuthkit.datamodel.AbstractFile>> filesMap = this.metaData.getFilesMap(); toPopulate.addAll(metaDataList);
Collection<String> files = filesMap.keySet();
toPopulate.addAll(files);
return true; return true;
} }
private String selectDataSources(List<AbstractFile> children) {
Map<Long, String> dataSources = this.metaData.getDataSourceIdToNameMap();
Set<String> dataSourceStrings = new HashSet<>();
for (AbstractFile child : children) {
String dataSource = dataSources.get(child.getDataSourceObjectId());
dataSourceStrings.add(dataSource);
}
return String.join(", ", dataSourceStrings);
}
} }

View File

@ -34,7 +34,7 @@ public class CommonFilesDescendants extends ChildFactory<AbstractFile> {
private final List<AbstractFile> descendants; private final List<AbstractFile> descendants;
private Map<Long, String> dataSourceMap; private Map<Long, String> dataSourceMap;
CommonFilesDescendants(List<AbstractFile> descendants, Map<Long, String> dataSourceMap){ public CommonFilesDescendants(List<AbstractFile> descendants, Map<Long, String> dataSourceMap){
super(); super();
this.descendants = descendants; this.descendants = descendants;
this.dataSourceMap = dataSourceMap; this.dataSourceMap = dataSourceMap;

View File

@ -24,8 +24,10 @@ import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.datamodel.AbstractFile; 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. * Utility and wrapper around data required for Common Files Search results.
* Subclass this to implement different selections of files from the case. * Subclass this to implement different selections of files from the case.
*/ */
abstract class CommonFilesMetaData { public abstract class CommonFilesMetaData {
private final Map<String, List<AbstractFile>> parentNodes; private final String parentMd5;
private final List<AbstractFile> children;
private final Map<Long, String> dataSourceIdToNameMap; private final Map<Long, String> dataSourceIdToNameMap;
private final SleuthkitCase sleuthkitCase; private final SleuthkitCase sleuthkitCase;
CommonFilesMetaData() throws TskCoreException, SQLException, NoCurrentCaseException { CommonFilesMetaData(String md5, List<AbstractFile> childNodes) throws TskCoreException, SQLException, NoCurrentCaseException {
parentNodes = new HashMap<>(); parentMd5 = md5;
children = childNodes;
dataSourceIdToNameMap = new HashMap<>(); dataSourceIdToNameMap = new HashMap<>();
this.sleuthkitCase = Case.getOpenCase().getSleuthkitCase(); this.sleuthkitCase = Case.getOpenCase().getSleuthkitCase();
@ -66,40 +70,31 @@ abstract class CommonFilesMetaData {
} }
} }
} }
public String getMd5() {
Map<String, List<AbstractFile>> getFilesMap() { return parentMd5;
return Collections.unmodifiableMap(this.parentNodes); }
public List<AbstractFile> getChildren() {
return Collections.unmodifiableList(this.children);
} }
Map<Long, String> getDataSourceIdToNameMap() { public Map<Long, String> getDataSourceIdToNameMap() {
return Collections.unmodifiableMap(dataSourceIdToNameMap); return Collections.unmodifiableMap(dataSourceIdToNameMap);
} }
/** public String selectDataSources() {
* 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 {
List<AbstractFile> files = this.sleuthkitCase.findAllFilesWhere(getSqlWhereClause()); Map<Long, String> dataSources = this.getDataSourceIdToNameMap();
for (AbstractFile file : files) { Set<String> dataSourceStrings = new HashSet<>();
String currentMd5 = file.getMd5Hash(); for (AbstractFile child : getChildren()) {
if(parentNodes.containsKey(currentMd5)){ String dataSource = dataSources.get(child.getDataSourceObjectId());
parentNodes.get(currentMd5).add(file);
} else { dataSourceStrings.add(dataSource);
List<AbstractFile> children = new ArrayList<>();
children.add(file);
parentNodes.put(currentMd5, children);
}
} }
return this; return String.join(", ", dataSourceStrings);
} }
/** /**
@ -112,12 +107,4 @@ abstract class CommonFilesMetaData {
*/ */
protected abstract String getSqlWhereClause(); protected abstract String getSqlWhereClause();
/**
*
* @param t
* @return
*/
List<AbstractFile> getChildrenForFile(String md5) {
return this.parentNodes.get(md5);
}
} }

View File

@ -21,7 +21,9 @@ package org.sleuthkit.autopsy.commonfilesearch;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -30,6 +32,7 @@ import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel; import javax.swing.ComboBoxModel;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import javax.swing.event.ListDataListener; import javax.swing.event.ListDataListener;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; 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.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent; import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
import org.sleuthkit.datamodel.TskCoreException; 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 void addListenerToAll(ActionListener l) { //TODO double click the button
this.searchButton.addActionListener(l); 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<CommonFilesMetaData> collateFiles() throws TskCoreException, SQLException {
SleuthkitCase sleuthkitCase;
List<CommonFilesMetaData> 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<AbstractFile> files = sleuthkitCase.findAllFilesWhere(whereClause);
Map<String, List<AbstractFile>> parentNodes = new HashMap<>();
for (AbstractFile file : files) {
String currentMd5 = file.getMd5Hash();
if (parentNodes.containsKey(currentMd5)) {
parentNodes.get(currentMd5).add(file);
} else {
List<AbstractFile> 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({ @NbBundle.Messages({
"CommonFilesPanel.search.results.title=Common Files", "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 title = Bundle.CommonFilesPanel_search_results_title();
String pathText = Bundle.CommonFilesPanel_search_results_pathText(); String pathText = Bundle.CommonFilesPanel_search_results_pathText();
new SwingWorker<CommonFilesMetaData, Void>() { new SwingWorker<List<CommonFilesMetaData>, Void>() {
@Override @Override
@SuppressWarnings("FinallyDiscardsException") @SuppressWarnings("FinallyDiscardsException")
protected CommonFilesMetaData doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException { protected List<CommonFilesMetaData> doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException {
//TODO cleanup - encapsulate business logic //TODO cleanup - encapsulate business logic
if(singleDataSource) { if(singleDataSource) {
@ -143,9 +188,11 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
break; break;
} }
} }
return new SingleDataSourceCommonFiles(selectedObjId).collateFiles(); //return new SingleDataSourceCommonFiles(selectedObjId).collateFiles();
return collateFiles();
} else { } else {
return new AllCommonFiles().collateFiles(); //return new AllCommonFiles().collateFiles();
return collateFiles();
} }
} }
@ -154,7 +201,7 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
try { try {
super.done(); super.done();
CommonFilesMetaData metadata = get(); List<CommonFilesMetaData> metadata = get();
CommonFilesSearchNode commonFilesNode = new CommonFilesSearchNode(metadata); CommonFilesSearchNode commonFilesNode = new CommonFilesSearchNode(metadata);
@ -165,8 +212,11 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
DataResultTopComponent component = DataResultTopComponent.createInstance(title); DataResultTopComponent component = DataResultTopComponent.createInstance(title);
//component.enableTreeMode(); //component.enableTreeMode();
int totalNodes = 0;
DataResultTopComponent.initInstance(pathText, tableFilterWithDescendantsNode, metadata.getFilesMap().size(), component); for(CommonFilesMetaData meta : metadata) {
totalNodes += meta.getChildren().size();
}
DataResultTopComponent.initInstance(pathText, tableFilterWithDescendantsNode, totalNodes, component);
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
LOGGER.log(Level.SEVERE, "Interrupted while loading Common Files", ex); LOGGER.log(Level.SEVERE, "Interrupted while loading Common Files", ex);

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.commonfilesearch; package org.sleuthkit.autopsy.commonfilesearch;
import java.util.List;
import org.openide.nodes.Children; import org.openide.nodes.Children;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
@ -30,8 +31,8 @@ import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
*/ */
final public class CommonFilesSearchNode extends DisplayableItemNode { final public class CommonFilesSearchNode extends DisplayableItemNode {
CommonFilesSearchNode(CommonFilesMetaData metaData) { CommonFilesSearchNode(List<CommonFilesMetaData> metaDataList) {
super(Children.create(new CommonFilesChildren(metaData), true), Lookups.singleton(metaData)); super(Children.create(new CommonFilesChildren(metaDataList), true), Lookups.singleton(metaDataList));
} }
@NbBundle.Messages({ @NbBundle.Messages({

View File

@ -20,7 +20,9 @@
package org.sleuthkit.autopsy.commonfilesearch; package org.sleuthkit.autopsy.commonfilesearch;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
@ -30,8 +32,8 @@ public class SingleDataSourceCommonFiles extends CommonFilesMetaData {
private final String whereClause; private final String whereClause;
SingleDataSourceCommonFiles(long dataSourceId) throws TskCoreException, SQLException, NoCurrentCaseException{ SingleDataSourceCommonFiles(String md5, List<AbstractFile> childNodes, long dataSourceId) throws TskCoreException, SQLException, NoCurrentCaseException{
super(); super(md5, childNodes);
Object[] args = new String[] {Long.toString(dataSourceId), Long.toString(dataSourceId)}; Object[] args = new String[] {Long.toString(dataSourceId), Long.toString(dataSourceId)};
this.whereClause = String.format( this.whereClause = String.format(

View File

@ -24,6 +24,10 @@ import java.util.Map;
import org.openide.nodes.Children; import org.openide.nodes.Children;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; 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 * 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 int commonFileCount;
private final String dataSources; private final String dataSources;
public CommonFileParentNode(Children children, String md5Hash, int commonFileCount, String dataSources) { public CommonFileParentNode(CommonFilesMetaData metaData) {
super(children); super(Children.create(
this.commonFileCount = commonFileCount; new CommonFilesDescendants(metaData.getChildren(),
this.dataSources = dataSources; metaData.getDataSourceIdToNameMap()), true),
this.md5Hash = md5Hash; Lookups.singleton(metaData));
this.commonFileCount = metaData.getChildren().size();
this.dataSources = metaData.selectDataSources();
this.md5Hash = metaData.getMd5();
this.setDisplayName(md5Hash); this.setDisplayName(md5Hash);
} }