generic search result table node; needs work in ThreePanelDAO and DataArtifactNodev2

This commit is contained in:
Greg DiCristofaro 2021-10-06 20:17:03 -04:00
parent 3d634568b8
commit 3a43a3915f
6 changed files with 229 additions and 205 deletions

View File

@ -40,10 +40,13 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResult;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.DataArtifactTypeNodev2;
import org.sleuthkit.autopsy.datamodel.DataArtifactNodev2;
import org.sleuthkit.autopsy.datamodel.SearchResultChildFactory.NodeCreator;
import org.sleuthkit.autopsy.datamodel.SearchResultTableNode;
import org.sleuthkit.autopsy.datamodel.ThreePanelDAO;
import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.DataArtifactTableDTO;
import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.DataArtifactTableSearchResultsDTO;
import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.RowResultDTO;
import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.SearchResultsDTO;
import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
import org.sleuthkit.datamodel.BlackboardArtifact;
@ -372,8 +375,7 @@ public final class DataResultTopComponent extends TopComponent implements DataRe
public void displayDataArtifact(BlackboardArtifact.Type artifactType, Long dataSourceId) {
try {
DataArtifactTableSearchResultsDTO table = threePanelDAO.getDataArtifactsForTable(artifactType, dataSourceId);
dataResultPanel.setNode(new DataArtifactTypeNodev2(table));
dataResultPanel.setNumberOfChildNodes(table.getTotalResultsCount());
displaySearchResults(table, DataArtifactNodev2::new);
} catch (ExecutionException | IllegalArgumentException ex) {
logger.log(Level.WARNING, MessageFormat.format(
"There was an error fetching data for artifact type: {0} and data source id: {1}.",
@ -382,6 +384,12 @@ public final class DataResultTopComponent extends TopComponent implements DataRe
ex);
}
}
public <T extends SearchResultsDTO<S>, S extends RowResultDTO> void displaySearchResults(T searchResults, NodeCreator<T, S> nodeCreator) {
dataResultPanel.setNode(new SearchResultTableNode(nodeCreator, searchResults));
dataResultPanel.setNumberOfChildNodes(
searchResults.getTotalResultsCount() > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) searchResults.getTotalResultsCount());
}
@Override
public void setTitle(String title) {

View File

@ -1,29 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.sleuthkit.autopsy.datamodel;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.DataArtifactTableDTO;
import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.DataArtifactTableSearchResultsDTO;
/**
*
* @author gregd
*/
public class DataArtifactFactoryv2 extends SearchResultChildFactory<DataArtifactTableSearchResultsDTO, DataArtifactTableDTO> {
public DataArtifactFactoryv2() {
}
public DataArtifactFactoryv2(DataArtifactTableSearchResultsDTO initialResults) {
super(initialResults);
}
@Override
protected Node createNodeForKey(DataArtifactTableSearchResultsDTO searchResults, DataArtifactTableDTO itemData) {
return new DataArtifactNodev2(searchResults, itemData);
}
}

View File

@ -1,56 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.sleuthkit.autopsy.datamodel;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.DataArtifactTableSearchResultsDTO;
import org.sleuthkit.autopsy.datamodel.utils.IconsUtil;
/**
*
* @author gregd
*/
public class DataArtifactTypeNodev2 extends AbstractNode {
private final SearchResultChildFactory<?,?> factory;
public DataArtifactTypeNodev2(DataArtifactTableSearchResultsDTO initialResults) {
this(initialResults, new DataArtifactFactoryv2(initialResults));
}
private DataArtifactTypeNodev2(DataArtifactTableSearchResultsDTO initialResults, DataArtifactFactoryv2 factory) {
super(Children.create(factory, true));
this.factory = factory;
setName(initialResults.getArtifactType().getTypeName());
setDisplayName(initialResults.getArtifactType().getDisplayName());
String iconPath = IconsUtil.getIconFilePath(initialResults.getArtifactType().getTypeID());
setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) == '/' ? iconPath.substring(1) : iconPath);
}
@Override
protected Sheet createSheet() {
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.name"),
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.displayName"),
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.desc"),
getDisplayName()));
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.name"),
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.displayName"),
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.desc"),
this.factory.getResultCount()));
return sheet;
}
}

View File

@ -11,30 +11,29 @@ import java.util.stream.Collectors;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node;
import org.sleuthkit.autopsy.datamodel.SearchResultChildFactory.ChildKey;
import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.RowResultDTO;
import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.SearchResultsDTO;
/**
*
* @author gregd
*/
public abstract class SearchResultChildFactory<T extends SearchResultsDTO<S>, S> extends ChildFactory<ChildKey<S, T>> {
public class SearchResultChildFactory<T extends SearchResultsDTO<S>, S extends RowResultDTO> extends ChildFactory<ChildKey<T, S>> {
private final NodeCreator<T,S> nodeCreator;
private T results;
public SearchResultChildFactory() {
this(null);
}
public SearchResultChildFactory(T initialResults) {
public SearchResultChildFactory(NodeCreator<T,S> nodeCreator, T initialResults) {
this.nodeCreator = nodeCreator;
this.results = initialResults;
}
@Override
protected boolean createKeys(List<ChildKey<S, T>> toPopulate) {
protected boolean createKeys(List<ChildKey<T, S>> toPopulate) {
T results = this.results;
if (results != null) {
List<ChildKey<S, T>> childKeys = results.getItems().stream()
List<ChildKey<T, S>> childKeys = results.getItems().stream()
.map((item) -> new ChildKey<>(results, item))
.collect(Collectors.toList());
@ -45,23 +44,27 @@ public abstract class SearchResultChildFactory<T extends SearchResultsDTO<S>, S>
}
@Override
protected Node createNodeForKey(ChildKey<S, T> key) {
return createNodeForKey(key.getSearchResults(), key.getChild());
protected Node createNodeForKey(ChildKey<T, S> key) {
return this.nodeCreator.create(key.getSearchResults(), key.getChild());
}
protected abstract Node createNodeForKey(T searchResults, S itemData);
public void update(T newResults) {
this.results = newResults;
this.refresh(false);
}
public int getResultCount() {
public long getResultCount() {
return results == null ? 0 : results.getTotalResultsCount();
}
public static interface NodeCreator<T extends SearchResultsDTO<S>, S extends RowResultDTO> {
Node create(T searchResults, S itemData);
}
static class ChildKey<S, T extends SearchResultsDTO<S>> {
static class ChildKey<T, S> {
private final T searchResults;
private final S child;

View File

@ -0,0 +1,60 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.sleuthkit.autopsy.datamodel;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.datamodel.SearchResultChildFactory.NodeCreator;
import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.RowResultDTO;
import org.sleuthkit.autopsy.datamodel.ThreePanelDAO.SearchResultsDTO;
/**
*
* @author gregd
*/
public class SearchResultTableNode<T extends SearchResultsDTO<S>, S extends RowResultDTO> extends AbstractNode {
private final SearchResultChildFactory<T, S> factory;
public SearchResultTableNode(NodeCreator<T,S> nodeCreator, SearchResultsDTO<S> initialResults) {
this(initialResults, new SearchResultChildFactory(nodeCreator, initialResults));
}
private SearchResultTableNode(SearchResultsDTO<S> initialResults, SearchResultChildFactory<T, S> factory) {
super(Children.create(factory, true));
this.factory = factory;
setName(initialResults.getTypeId());
setDisplayName(initialResults.getDisplayName());
// String iconPath = IconsUtil.getIconFilePath(initialResults.getArtifactType().getTypeID());
// setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) == '/' ? iconPath.substring(1) : iconPath);
}
@Override
protected Sheet createSheet() {
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.name"),
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.displayName"),
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.desc"),
getDisplayName()));
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.name"),
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.displayName"),
NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.desc"),
this.factory.getResultCount()));
return sheet;
}
}

View File

@ -18,7 +18,6 @@ import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.datamodel.AbstractFile;
@ -54,7 +53,7 @@ public class ThreePanelDAO {
}
private final Cache<DataArtifactCacheKey, DataArtifactTableSearchResultsDTO> dataArtifactCache = CacheBuilder.newBuilder().maximumSize(1000).build();
private final Cache<Long, List<FilesContentTableDTO>> filesCache = CacheBuilder.newBuilder().maximumSize(1000).build();
// private final Cache<Long, List<FilesContentTableDTO>> filesCache = CacheBuilder.newBuilder().maximumSize(1000).build();
private SleuthkitCase getCase() throws NoCurrentCaseException {
return Case.getCurrentCaseThrows().getSleuthkitCase();
@ -247,14 +246,13 @@ public class ThreePanelDAO {
// }
// return filesCache.get(parentId, () -> fetchChildFiles(parentId));
// }
public void dropFilesCache() {
filesCache.invalidateAll();
}
public void dropFilesCache(long parentId) {
filesCache.invalidate(parentId);
}
// public void dropFilesCache() {
// filesCache.invalidateAll();
// }
//
// public void dropFilesCache(long parentId) {
// filesCache.invalidate(parentId);
// }
private static class DataArtifactCacheKey {
@ -305,32 +303,22 @@ public class ThreePanelDAO {
}
public static class DataArtifactTableDTO {
private final long id;
private final Map<Integer, Object> attributeValues;
public static class DataArtifactTableDTO extends BaseRowResultDTO {
//private final Map<Integer, Object> attributeValues;
//private final String dataSourceName;
private final DataArtifact dataArtifact;
private final Content srcContent;
private final Content linkedFile;
private String dataSourceName;
private final boolean isTimelineSupported;
public DataArtifactTableDTO(long id, Map<Integer, Object> attributeValues, DataArtifact dataArtifact, Content srcContent, Content linkedFile, String dataSourceName) {
this.id = id;
this.attributeValues = attributeValues;
public DataArtifactTableDTO(DataArtifact dataArtifact, Content srcContent, Content linkedFile, boolean isTimelineSupported, List<Object> cellValues, long id) {
super(cellValues, id);
this.dataArtifact = dataArtifact;
this.srcContent = srcContent;
this.linkedFile = linkedFile;
this.dataSourceName = dataSourceName;
}
public long getId() {
return id;
}
public Map<Integer, Object> getAttributeValues() {
return attributeValues;
this.isTimelineSupported = isTimelineSupported;
}
public DataArtifact getDataArtifact() {
@ -345,14 +333,70 @@ public class ThreePanelDAO {
return linkedFile;
}
public String getDataSourceName() {
return dataSourceName;
public boolean isIsTimelineSupported() {
return isTimelineSupported;
}
}
public class ColumnKey {
private final String fieldName;
private final String displayName;
private final String description;
public ColumnKey(String fieldName, String displayName, String description) {
this.fieldName = fieldName;
this.displayName = displayName;
this.description = description;
}
public String getFieldName() {
return fieldName;
}
public String getDisplayName() {
return displayName;
}
public String getDescription() {
return description;
}
}
public interface RowResultDTO {
List<Object> getCellValues();
long getId();
}
public class BaseRowResultDTO implements RowResultDTO {
private final List<Object> cellValues;
private final long id;
public BaseRowResultDTO(List<Object> cellValues, long id) {
this.cellValues = cellValues;
this.id = id;
}
@Override
public List<Object> getCellValues() {
return cellValues;
}
@Override
public long getId() {
return id;
}
@Override
public int hashCode() {
int hash = 7;
hash = 67 * hash + (int) (this.id ^ (this.id >>> 32));
int hash = 3;
hash = 23 * hash + (int) (this.id ^ (this.id >>> 32));
return hash;
}
@ -367,95 +411,89 @@ public class ThreePanelDAO {
if (getClass() != obj.getClass()) {
return false;
}
final DataArtifactTableDTO other = (DataArtifactTableDTO) obj;
final BaseRowResultDTO other = (BaseRowResultDTO) obj;
if (this.id != other.id) {
return false;
}
return true;
}
}
public interface SearchResultsDTO<T> {
int getTotalResultsCount();
List<T> getItems();
public interface SearchResultsDTO<R extends RowResultDTO> {
String getTypeId();
String getDisplayName();
List<ColumnKey> getColumns();
List<R> getItems();
long getTotalResultsCount();
}
public static class DataArtifactTableSearchResultsDTO implements SearchResultsDTO<DataArtifactTableDTO> {
public class BaseSearchResultsDTO<R extends RowResultDTO> implements SearchResultsDTO<R> {
private final BlackboardArtifact.Type artifactType;
private final List<BlackboardAttribute.Type> attributeTypes;
private final List<DataArtifactTableDTO> items;
private final int totalResultsCount;
private final String typeId;
private final String displayName;
private final List<ColumnKey> columns;
private final List<R> items;
private final long totalResultsCount;
public DataArtifactTableSearchResultsDTO(BlackboardArtifact.Type artifactType, List<BlackboardAttribute.Type> attributeKeys, List<DataArtifactTableDTO> items) {
this(artifactType, attributeKeys, items, items.size());
public BaseSearchResultsDTO(String typeId, String displayName, List<ColumnKey> columns, List<R> items) {
this(typeId, displayName, columns, items, items == null ? 0 : items.size());
}
public DataArtifactTableSearchResultsDTO(BlackboardArtifact.Type artifactType, List<BlackboardAttribute.Type> attributeKeys, List<DataArtifactTableDTO> items, int totalResultsCount) {
this.artifactType = artifactType;
this.attributeTypes = attributeKeys;
public BaseSearchResultsDTO(String typeId, String displayName, List<ColumnKey> columns, List<R> items, long totalResultsCount) {
this.typeId = typeId;
this.displayName = displayName;
this.columns = columns;
this.items = items;
this.totalResultsCount = totalResultsCount;
}
@Override
public String getTypeId() {
return typeId;
}
@Override
public String getDisplayName() {
return displayName;
}
@Override
public List<ColumnKey> getColumns() {
return columns;
}
@Override
public List<R> getItems() {
return items;
}
@Override
public long getTotalResultsCount() {
return totalResultsCount;
}
}
public static class DataArtifactTableSearchResultsDTO extends BaseSearchResultsDTO<DataArtifactTableDTO> {
private static final String TYPE_ID = "DATA_ARTIFACT";
private final BlackboardArtifact.Type artifactType;
public DataArtifactTableSearchResultsDTO(BlackboardArtifact.Type artifactType, List<ColumnKey> columns, List<DataArtifactTableDTO> items) {
super(TYPE_ID, artifactType.getDisplayName(), columns, items);
this.artifactType = artifactType;
}
public BlackboardArtifact.Type getArtifactType() {
return artifactType;
}
public List<BlackboardAttribute.Type> getAttributeTypes() {
return attributeTypes;
}
@Override
public List<DataArtifactTableDTO> getItems() {
return items;
}
@Override
public int getTotalResultsCount() {
return totalResultsCount;
}
}
public enum FilesType {
DIR,
FILE
}
public static class FilesContentTableDTO {
private final Content content;
private final String displayName;
private final String extension;
private final long id;
public FilesContentTableDTO(Content content, String displayName, String extension, long id) {
this.content = content;
this.displayName = displayName;
this.extension = extension;
this.id = id;
}
public Content getContent() {
return content;
}
public String getDisplayName() {
return displayName;
}
public String getExtension() {
return extension;
}
public long getId() {
return id;
}
}
}