mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 18:17:43 +00:00
Move ChildFactories into classes which use them. Make CommonFilesMetaDataBuilder to handle queries/ list of model building / deduping files. Simplifies CommonFilesMetaData by separating business logic from model and CommonFilesPanel. Removes yet another query by re-using the dataSourceIdMap from CommonFilesPanel for model creation, so now CommonFiles is down to 2 queries total, including UI building.
This commit is contained in:
parent
084f29ae28
commit
4d75dabe23
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.List;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Node;
|
||||
import org.sleuthkit.autopsy.datamodel.CommonFileParentNode;
|
||||
|
||||
/**
|
||||
* Makes nodes for common files search results.
|
||||
*/
|
||||
public final class CommonFilesChildren extends ChildFactory<CommonFilesMetaData> {
|
||||
|
||||
private List<CommonFilesMetaData> metaDataList;
|
||||
|
||||
public CommonFilesChildren(List<CommonFilesMetaData> theMetaDataList) {
|
||||
super();
|
||||
this.metaDataList = theMetaDataList;
|
||||
}
|
||||
|
||||
protected void removeNotify() {
|
||||
metaDataList = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(CommonFilesMetaData metaData) {
|
||||
|
||||
return new CommonFileParentNode(metaData);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<CommonFilesMetaData> toPopulate) {
|
||||
toPopulate.addAll(metaDataList);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.List;
|
||||
import java.util.Map;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Node;
|
||||
import org.sleuthkit.autopsy.datamodel.CommonFileChildNode;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
|
||||
/**
|
||||
* Child generator for FileNodes of CommonFileParentNodes
|
||||
*/
|
||||
public class CommonFilesDescendants extends ChildFactory<AbstractFile> {
|
||||
|
||||
private final List<AbstractFile> descendants;
|
||||
private Map<Long, String> dataSourceMap;
|
||||
|
||||
public CommonFilesDescendants(List<AbstractFile> descendants, Map<Long, String> dataSourceMap){
|
||||
super();
|
||||
this.descendants = descendants;
|
||||
this.dataSourceMap = dataSourceMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(AbstractFile file){
|
||||
|
||||
final String dataSource = this.dataSourceMap.get(file.getDataSourceObjectId());
|
||||
|
||||
return new CommonFileChildNode(file, dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<AbstractFile> list) {
|
||||
list.addAll(this.descendants);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -28,7 +28,7 @@ import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Utility and wrapper around data required for Common Files Search results.
|
||||
* Utility and wrapper model around data required for Common Files Search results.
|
||||
* Subclass this to implement different selections of files from the case.
|
||||
*/
|
||||
public class CommonFilesMetaData {
|
||||
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Generates a List<CommonFilesMetaData> when collateFiles() is called, which organizes
|
||||
* AbstractFiles by md5 to prepare to display in viewer.
|
||||
*/
|
||||
class CommonFilesMetaDataBuilder {
|
||||
|
||||
private final Long selectedDataSourceId;
|
||||
private final Map<Long, String> dataSourceIdToNameMap;
|
||||
private final String singleDataSourceWhereClause = "md5 in (select md5 from tsk_files where data_source_obj_id=%s and (known != 1 OR known IS NULL) GROUP BY md5 HAVING COUNT(*) > 1) AND data_source_obj_id=%s order by md5";
|
||||
private final String allDataSourcesWhereClause = "md5 in (select md5 from tsk_files where (known != 1 OR known IS NULL) GROUP BY md5 HAVING COUNT(*) > 1) order by md5";
|
||||
|
||||
CommonFilesMetaDataBuilder(Long dataSourceId, Map<Long, String> dataSourceIdMap) {
|
||||
selectedDataSourceId = dataSourceId;
|
||||
dataSourceIdToNameMap = dataSourceIdMap;
|
||||
}
|
||||
|
||||
private void addDataSource(Set<String> dataSources, AbstractFile file, Map<Long, String> dataSourceIdToNameMap) {
|
||||
long datasourceId = file.getDataSourceObjectId();
|
||||
String dataSourceName = dataSourceIdToNameMap.get(datasourceId);
|
||||
dataSources.add(dataSourceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
List<CommonFilesMetaData> collateFiles() throws TskCoreException, SQLException {
|
||||
List<CommonFilesMetaData> metaDataModels = new ArrayList<>();
|
||||
Map<String, Set<String>> md5ToDataSourcesStringMap = new HashMap<>();
|
||||
|
||||
try {
|
||||
List<AbstractFile> files = FindCommonFiles();
|
||||
|
||||
Map<String, List<AbstractFile>> parentNodes = new HashMap<>();
|
||||
|
||||
collateParentChildRelationships(files, parentNodes, md5ToDataSourcesStringMap);
|
||||
for (String key : parentNodes.keySet()) {
|
||||
metaDataModels.add(new CommonFilesMetaData(key, parentNodes.get(key), String.join(", ", md5ToDataSourcesStringMap.get(key)), dataSourceIdToNameMap));
|
||||
}
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
}
|
||||
|
||||
return metaDataModels;
|
||||
}
|
||||
|
||||
private void collateParentChildRelationships(List<AbstractFile> files, Map<String, List<AbstractFile>> parentNodes, Map<String, Set<String>> md5ToDataSourcesStringMap) {
|
||||
for (AbstractFile file : files) {
|
||||
|
||||
String currentMd5 = file.getMd5Hash();
|
||||
|
||||
if (parentNodes.containsKey(currentMd5)) {
|
||||
parentNodes.get(currentMd5).add(file);
|
||||
Set<String> currenDataSources = md5ToDataSourcesStringMap.get(currentMd5);
|
||||
addDataSource(currenDataSources, file, dataSourceIdToNameMap);
|
||||
md5ToDataSourcesStringMap.put(currentMd5, currenDataSources);
|
||||
|
||||
} else {
|
||||
List<AbstractFile> children = new ArrayList<>();
|
||||
Set<String> dataSources = new HashSet<>();
|
||||
children.add(file);
|
||||
parentNodes.put(currentMd5, children);
|
||||
addDataSource(dataSources, file, dataSourceIdToNameMap);
|
||||
md5ToDataSourcesStringMap.put(currentMd5, dataSources);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private List<AbstractFile> FindCommonFiles() throws TskCoreException, NoCurrentCaseException {
|
||||
SleuthkitCase sleuthkitCase;
|
||||
sleuthkitCase = Case.getOpenCase().getSleuthkitCase();
|
||||
String whereClause = allDataSourcesWhereClause;
|
||||
if (selectedDataSourceId != 0L) {
|
||||
Object[] args = new String[]{Long.toString(selectedDataSourceId), Long.toString(selectedDataSourceId)};
|
||||
whereClause = String.format(singleDataSourceWhereClause, args);
|
||||
}
|
||||
List<AbstractFile> files = sleuthkitCase.findAllFilesWhere(whereClause);
|
||||
return files;
|
||||
}
|
||||
|
||||
}
|
@ -56,9 +56,9 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private final ComboBoxModel<String> dataSourcesList;
|
||||
private final Map<Long, String> dataSourceMap;
|
||||
private final Map<Long, String> dataSourceMap;
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(CommonFilesPanel.class.getName());
|
||||
private boolean singleDataSource;
|
||||
@ -67,7 +67,7 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
/**
|
||||
* Creates new form CommonFilesPanel
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
@NbBundle.Messages({
|
||||
"CommonFilesPanel.title=Common Files Panel",
|
||||
"CommonFilesPanel.exception=Unexpected Exception loading DataSources."})
|
||||
public CommonFilesPanel() {
|
||||
@ -75,131 +75,51 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
String[] dataSourcesNames = new String[1];
|
||||
this.dataSourceMap = new HashMap<>();
|
||||
selectedDataSource = "";
|
||||
|
||||
|
||||
try {
|
||||
buildDataSourceMap(dataSourceMap);
|
||||
dataSourcesNames = dataSourceMap.values().toArray(dataSourcesNames);
|
||||
} catch (TskCoreException | NoCurrentCaseException | SQLException ex) {
|
||||
|
||||
LOGGER.log(Level.SEVERE, "Interrupted while loading Common Files Panel Data Sources", ex);
|
||||
MessageNotifyUtil.Message.error(Bundle.CommonFilesPanel_exception());
|
||||
|
||||
LOGGER.log(Level.SEVERE, "Interrupted while loading Common Files Panel Data Sources", ex);
|
||||
MessageNotifyUtil.Message.error(Bundle.CommonFilesPanel_exception());
|
||||
}
|
||||
this.dataSourcesList = new DataSourceComboBoxModel(dataSourcesNames);
|
||||
initComponents();
|
||||
updateUIButtons();
|
||||
}
|
||||
|
||||
|
||||
private void updateUIButtons() {
|
||||
boolean multipleDataSources = this.caseHasMultipleSources();
|
||||
allDataSourcesRadioButton.setEnabled(multipleDataSources);
|
||||
allDataSourcesRadioButton.setSelected(multipleDataSources);
|
||||
if(!multipleDataSources) {
|
||||
withinDataSourceRadioButton.setSelected(true);
|
||||
withinDataSourceSelected(true);
|
||||
if (!multipleDataSources) {
|
||||
withinDataSourceRadioButton.setSelected(true);
|
||||
withinDataSourceSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean caseHasMultipleSources(){
|
||||
|
||||
private boolean caseHasMultipleSources() {
|
||||
return dataSourceMap.size() >= 2;
|
||||
}
|
||||
|
||||
private void buildDataSourceMap(Map<Long, String> dataSourceMap) throws TskCoreException, NoCurrentCaseException, SQLException {
|
||||
Case currentCase = Case.getOpenCase();
|
||||
SleuthkitCase tskDb = currentCase.getSleuthkitCase();
|
||||
CaseDbQuery query = tskDb.executeQuery("select obj_id, name from tsk_files where obj_id in (SELECT obj_id FROM tsk_objects WHERE obj_id in (select obj_id from data_source_info))");
|
||||
|
||||
ResultSet resultSet = query.getResultSet();
|
||||
while(resultSet.next()){
|
||||
Long objectId = resultSet.getLong(1);
|
||||
String dataSourceName = resultSet.getString(2);
|
||||
dataSourceMap.put(objectId, dataSourceName);
|
||||
}
|
||||
|
||||
private void buildDataSourceMap(Map<Long, String> dataSourceMap) throws TskCoreException, NoCurrentCaseException, SQLException {
|
||||
Case currentCase = Case.getOpenCase();
|
||||
SleuthkitCase tskDb = currentCase.getSleuthkitCase();
|
||||
CaseDbQuery query = tskDb.executeQuery("select obj_id, name from tsk_files where obj_id in (SELECT obj_id FROM tsk_objects WHERE obj_id in (select obj_id from data_source_info))");
|
||||
|
||||
ResultSet resultSet = query.getResultSet();
|
||||
while (resultSet.next()) {
|
||||
Long objectId = resultSet.getLong(1);
|
||||
String dataSourceName = resultSet.getString(2);
|
||||
dataSourceMap.put(objectId, dataSourceName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void addListenerToAll(ActionListener l) { //TODO double click the button
|
||||
this.searchButton.addActionListener(l);
|
||||
}
|
||||
|
||||
private Map<Long, String> loadDataSourcesMap(SleuthkitCase sleuthkitCase) throws SQLException, TskCoreException {
|
||||
Map<Long, String> dataSourceIdToNameMap = new HashMap<>();
|
||||
try (
|
||||
SleuthkitCase.CaseDbQuery query = sleuthkitCase.executeQuery("select obj_id, name from tsk_files where obj_id in (SELECT obj_id FROM tsk_objects WHERE obj_id in (select obj_id from data_source_info))");
|
||||
ResultSet resultSet = query.getResultSet()) {
|
||||
|
||||
while (resultSet.next()) {
|
||||
Long objectId = resultSet.getLong(1);
|
||||
String dataSourceName = resultSet.getString(2);
|
||||
dataSourceIdToNameMap.put(objectId, dataSourceName);
|
||||
}
|
||||
}
|
||||
return dataSourceIdToNameMap;
|
||||
}
|
||||
private void addDataSource(Set<String> dataSources, AbstractFile file, Map<Long,String> dataSourceIdToNameMap) {
|
||||
long datasourceId = file.getDataSourceObjectId();
|
||||
String dataSourceName = dataSourceIdToNameMap.get(datasourceId);
|
||||
dataSources.add(dataSourceName);
|
||||
}
|
||||
/**
|
||||
* 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(Long selectedObjId) throws TskCoreException, SQLException {
|
||||
|
||||
SleuthkitCase sleuthkitCase;
|
||||
List<CommonFilesMetaData> metaDataModels = new ArrayList<>();
|
||||
Map<String, Set<String>> md5ToDataSourcesStringMap = new HashMap<>();
|
||||
|
||||
try {
|
||||
sleuthkitCase = Case.getOpenCase().getSleuthkitCase();
|
||||
Map<Long, String> dataSourceIdToNameMap = loadDataSourcesMap(sleuthkitCase);
|
||||
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";
|
||||
if(selectedObjId != 0L) {
|
||||
Object[] args = new String[] {Long.toString(selectedObjId), Long.toString(selectedObjId)};
|
||||
whereClause = String.format(
|
||||
"md5 in (select md5 from tsk_files where data_source_obj_id=%s and (known != 1 OR known IS NULL) GROUP BY md5 HAVING COUNT(*) > 1) AND data_source_obj_id=%s order by md5",
|
||||
args);
|
||||
}
|
||||
|
||||
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);
|
||||
Set<String> currenDataSources = md5ToDataSourcesStringMap.get(currentMd5);
|
||||
addDataSource(currenDataSources, file, dataSourceIdToNameMap);
|
||||
md5ToDataSourcesStringMap.put(currentMd5, currenDataSources);
|
||||
|
||||
} else {
|
||||
List<AbstractFile> children = new ArrayList<>();
|
||||
Set<String> dataSources = new HashSet<>();
|
||||
children.add(file);
|
||||
parentNodes.put(currentMd5, children);
|
||||
addDataSource(dataSources, file, dataSourceIdToNameMap);
|
||||
md5ToDataSourcesStringMap.put(currentMd5, dataSources);
|
||||
}
|
||||
|
||||
}
|
||||
for (String key : parentNodes.keySet()) {
|
||||
metaDataModels.add(new CommonFilesMetaData(key, parentNodes.get(key), String.join(", ", md5ToDataSourcesStringMap.get(key)), dataSourceIdToNameMap));
|
||||
}
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return metaDataModels;
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"CommonFilesPanel.search.results.title=Common Files",
|
||||
@ -216,22 +136,25 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
|
||||
new SwingWorker<List<CommonFilesMetaData>, Void>() {
|
||||
|
||||
private Long determineDataSourceId() {
|
||||
Long selectedObjId = 0L;
|
||||
if (singleDataSource) {
|
||||
for (Entry<Long, String> dataSource : dataSourceMap.entrySet()) {
|
||||
if (dataSource.getValue().equals(selectedDataSource)) {
|
||||
selectedObjId = dataSource.getKey();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return selectedObjId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("FinallyDiscardsException")
|
||||
protected List<CommonFilesMetaData> doInBackground() throws TskCoreException, NoCurrentCaseException, SQLException {
|
||||
Long selectedObjId = determineDataSourceId();
|
||||
return new CommonFilesMetaDataBuilder(selectedObjId, dataSourceMap).collateFiles();
|
||||
|
||||
//TODO cleanup - encapsulate business logic
|
||||
Long selectedObjId = 0L;
|
||||
if(singleDataSource) {
|
||||
for (Entry<Long, String> dataSource : dataSourceMap.entrySet()) {
|
||||
if (dataSource.getValue().equals(selectedDataSource)) {
|
||||
selectedObjId = dataSource.getKey();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return collateFiles(selectedObjId);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -248,14 +171,13 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
TableFilterNode tableFilterWithDescendantsNode = new TableFilterNode(dataResultFilterNode);
|
||||
|
||||
DataResultTopComponent component = DataResultTopComponent.createInstance(title);
|
||||
|
||||
|
||||
//component.enableTreeMode();
|
||||
|
||||
int totalNodes = 0;
|
||||
for(CommonFilesMetaData meta : metadata) {
|
||||
for (CommonFilesMetaData meta : metadata) {
|
||||
totalNodes += meta.getChildren().size();
|
||||
}
|
||||
DataResultTopComponent.initInstance(pathText, tableFilterWithDescendantsNode, totalNodes, component);
|
||||
DataResultTopComponent.initInstance(pathText, tableFilterWithDescendantsNode, totalNodes, component);
|
||||
|
||||
} catch (InterruptedException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Interrupted while loading Common Files", ex);
|
||||
@ -281,16 +203,17 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
|
||||
private class DataSourceComboBoxModel extends AbstractListModel<String> implements ComboBoxModel<String> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final String[] dataSourceList;
|
||||
String selection = null;
|
||||
|
||||
|
||||
DataSourceComboBoxModel(String[] theDataSoureList) {
|
||||
dataSourceList = theDataSoureList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedItem(Object anItem) {
|
||||
selection = (String) anItem;
|
||||
@ -303,26 +226,25 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return dataSourceList.length;
|
||||
return dataSourceList.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementAt(int index) {
|
||||
return dataSourceList[index];
|
||||
return dataSourceList[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListDataListener(ListDataListener l) {
|
||||
this.listenerList.add(ListDataListener.class, l);
|
||||
this.listenerList.add(ListDataListener.class, l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListDataListener(ListDataListener l) {
|
||||
this.listenerList.remove(ListDataListener.class, l);
|
||||
this.listenerList.remove(ListDataListener.class, l);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -409,9 +331,9 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
}//GEN-LAST:event_searchButtonActionPerformed
|
||||
|
||||
private void allDataSourcesRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_allDataSourcesRadioButtonActionPerformed
|
||||
selectDataSourceComboBox.setEnabled(!allDataSourcesRadioButton.isSelected());
|
||||
singleDataSource = false;
|
||||
|
||||
selectDataSourceComboBox.setEnabled(!allDataSourcesRadioButton.isSelected());
|
||||
singleDataSource = false;
|
||||
|
||||
}//GEN-LAST:event_allDataSourcesRadioButtonActionPerformed
|
||||
|
||||
private void selectDataSourceComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectDataSourceComboBoxActionPerformed
|
||||
@ -424,7 +346,7 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
|
||||
|
||||
private void withinDataSourceSelected(boolean selected) {
|
||||
selectDataSourceComboBox.setEnabled(selected);
|
||||
if(selectDataSourceComboBox.isEnabled()) {
|
||||
if (selectDataSourceComboBox.isEnabled()) {
|
||||
selectDataSourceComboBox.setSelectedIndex(0);
|
||||
singleDataSource = true;
|
||||
}
|
||||
|
@ -19,20 +19,23 @@
|
||||
package org.sleuthkit.autopsy.commonfilesearch;
|
||||
|
||||
import java.util.List;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.datamodel.CommonFileParentNode;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
|
||||
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
|
||||
|
||||
/**
|
||||
* Encapsulates data used to display common files search results in the top
|
||||
* right pane.
|
||||
* Wrapper node for CommonFilesParentNode used to display common files search results in the top
|
||||
* right pane. Calls CommonFilesParentFactory.
|
||||
*/
|
||||
final public class CommonFilesSearchNode extends DisplayableItemNode {
|
||||
|
||||
CommonFilesSearchNode(List<CommonFilesMetaData> metaDataList) {
|
||||
super(Children.create(new CommonFilesChildren(metaDataList), true), Lookups.singleton(metaDataList));
|
||||
super(Children.create(new CommonFilesParentFactory(metaDataList), true), Lookups.singleton(metaDataList));
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
@ -56,4 +59,39 @@ final public class CommonFilesSearchNode extends DisplayableItemNode {
|
||||
public String getItemType() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* ChildFactory which builds CommonFileParentNodes from the CommonFilesMetaaData models.
|
||||
*/
|
||||
static class CommonFilesParentFactory extends ChildFactory<CommonFilesMetaData> {
|
||||
|
||||
/**
|
||||
* List of models, each of which is a parent node matching a single md5, containing children FileNodes.
|
||||
*/
|
||||
private List<CommonFilesMetaData> metaDataList;
|
||||
|
||||
CommonFilesParentFactory(List<CommonFilesMetaData> theMetaDataList) {
|
||||
this.metaDataList = theMetaDataList;
|
||||
}
|
||||
|
||||
protected void removeNotify() {
|
||||
metaDataList = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(CommonFilesMetaData metaData) {
|
||||
|
||||
return new CommonFileParentNode(metaData);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<CommonFilesMetaData> toPopulate) {
|
||||
toPopulate.addAll(metaDataList);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -20,13 +20,16 @@
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
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.CommonFilesDescendants;
|
||||
import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetaData;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
|
||||
/**
|
||||
* Represents a common files match - two or more files which appear to be the
|
||||
@ -40,7 +43,7 @@ public class CommonFileParentNode extends DisplayableItemNode {
|
||||
|
||||
public CommonFileParentNode(CommonFilesMetaData metaData) {
|
||||
super(Children.create(
|
||||
new CommonFilesDescendants(metaData.getChildren(),
|
||||
new CommonFilesChildFactory(metaData.getChildren(),
|
||||
metaData.getDataSourceIdToNameMap()), true),
|
||||
Lookups.singleton(metaData));
|
||||
this.commonFileCount = metaData.getChildren().size();
|
||||
@ -110,7 +113,36 @@ public class CommonFileParentNode extends DisplayableItemNode {
|
||||
public String getItemType() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Child generator for FileNodes of CommonFileParentNodes
|
||||
*/
|
||||
static class CommonFilesChildFactory extends ChildFactory<AbstractFile> {
|
||||
|
||||
private final List<AbstractFile> descendants;
|
||||
private final Map<Long, String> dataSourceMap;
|
||||
|
||||
CommonFilesChildFactory(List<AbstractFile> descendants, Map<Long, String> dataSourceMap){
|
||||
this.descendants = descendants;
|
||||
this.dataSourceMap = dataSourceMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(AbstractFile file){
|
||||
|
||||
final String dataSource = this.dataSourceMap.get(file.getDataSourceObjectId());
|
||||
|
||||
return new CommonFileChildNode(file, dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<AbstractFile> list) {
|
||||
list.addAll(this.descendants);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@NbBundle.Messages({
|
||||
"CommonFileParentPropertyType.fileColLbl=File",
|
||||
"CommonFileParentPropertyType.instanceColLbl=Instance Count",
|
||||
|
Loading…
x
Reference in New Issue
Block a user