mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 07:56:16 +00:00
Merge pull request #3389 from dgrove727/3468_ArtifactHits
3468 artifact hits
This commit is contained in:
commit
e5e87942e6
@ -33,6 +33,7 @@ import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.AdHocQueryResult;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Account;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
@ -52,7 +53,6 @@ public class ExtractedContentViewer implements DataContentViewer {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ExtractedContentViewer.class.getName());
|
||||
|
||||
private static final long INVALID_DOCUMENT_ID = 0L;
|
||||
private static final BlackboardAttribute.Type TSK_ASSOCIATED_ARTIFACT_TYPE = new BlackboardAttribute.Type(TSK_ASSOCIATED_ARTIFACT);
|
||||
public static final BlackboardAttribute.Type TSK_ACCOUNT_TYPE = new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE);
|
||||
|
||||
@ -92,54 +92,77 @@ public class ExtractedContentViewer implements DataContentViewer {
|
||||
currentNode = node;
|
||||
}
|
||||
|
||||
Lookup nodeLookup = node.getLookup();
|
||||
AbstractFile content = nodeLookup.lookup(AbstractFile.class);
|
||||
|
||||
/*
|
||||
* Assemble a collection of all of the indexed text "sources" for the
|
||||
* node.
|
||||
*/
|
||||
List<IndexedText> sources = new ArrayList<>();
|
||||
IndexedText highlightedHitText = null;
|
||||
IndexedText rawContentText = null;
|
||||
Lookup nodeLookup = node.getLookup();
|
||||
|
||||
AdHocQueryResult adHocQueryResult = nodeLookup.lookup(AdHocQueryResult.class);
|
||||
AbstractFile file = null;
|
||||
BlackboardArtifact artifact;
|
||||
|
||||
if (null != content && solrHasContent(content.getId())) {
|
||||
QueryResults hits = nodeLookup.lookup(QueryResults.class);
|
||||
BlackboardArtifact artifact = nodeLookup.lookup(BlackboardArtifact.class);
|
||||
if (hits != null) {
|
||||
/*
|
||||
* if there is a QueryReslt object, in the lookup use that. This
|
||||
* happens when a user selects a row in an ad-hoc search result
|
||||
* If we have an ad hoc query result, pull the file and artifact objects
|
||||
* from that. Otherwise, pull them from the lookup.
|
||||
*/
|
||||
highlightedHitText = new HighlightedText(content.getId(), hits);
|
||||
} else if (artifact != null
|
||||
&& artifact.getArtifactTypeID() == TSK_ACCOUNT.getTypeID()) {
|
||||
try {
|
||||
// if the artifact is an account artifact, get an account text .
|
||||
highlightedHitText = getAccountsText(content, nodeLookup);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to create AccountsText for " + content, ex); //NON-NLS
|
||||
|
||||
if (adHocQueryResult != null) {
|
||||
artifact = adHocQueryResult.getArtifact();
|
||||
Content content = adHocQueryResult.getContent();
|
||||
if (content instanceof AbstractFile) {
|
||||
file = (AbstractFile) content;
|
||||
}
|
||||
} else if (artifact != null
|
||||
&& artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) {
|
||||
} else {
|
||||
artifact = nodeLookup.lookup(BlackboardArtifact.class);
|
||||
file = nodeLookup.lookup(AbstractFile.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* First, get text with highlighted hits if this node is for a search
|
||||
* result.
|
||||
*/
|
||||
IndexedText highlightedHitText = null;
|
||||
if (adHocQueryResult != null) {
|
||||
/*
|
||||
* The node is an ad hoc search result node.
|
||||
*/
|
||||
highlightedHitText = new HighlightedText(adHocQueryResult.getSolrObjectId(), adHocQueryResult.getResults());
|
||||
} else if (artifact != null) {
|
||||
if (artifact.getArtifactTypeID() == TSK_KEYWORD_HIT.getTypeID()) {
|
||||
/*
|
||||
* The node is a keyword hit artifact node.
|
||||
*/
|
||||
try {
|
||||
//if there is kwh artifact use that to construct the HighlightedText
|
||||
highlightedHitText = new HighlightedText(artifact);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to create HighlightedText for " + artifact, ex); //NON-NLS
|
||||
}
|
||||
} else if (artifact.getArtifactTypeID() == TSK_ACCOUNT.getTypeID() && file != null) {
|
||||
try {
|
||||
BlackboardAttribute attribute = artifact.getAttribute(TSK_ACCOUNT_TYPE);
|
||||
if (attribute != null && Account.Type.CREDIT_CARD.getTypeName().equals(attribute.getValueString())) {
|
||||
/*
|
||||
* The node is an credit card account node.
|
||||
*/
|
||||
highlightedHitText = getAccountsText(file, nodeLookup);
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to create AccountsText for " + file, ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (highlightedHitText != null) {
|
||||
sources.add(highlightedHitText);
|
||||
}
|
||||
|
||||
/*
|
||||
* Next, add the "raw" (not highlighted) text, if any, for any
|
||||
* content associated with the node.
|
||||
* Next, add the "raw" (not highlighted) text, if any, for any file
|
||||
* associated with the node.
|
||||
*/
|
||||
rawContentText = new RawText(content, content.getId());
|
||||
IndexedText rawContentText = null;
|
||||
if (file != null) {
|
||||
rawContentText = new RawText(file, file.getId());
|
||||
sources.add(rawContentText);
|
||||
}
|
||||
|
||||
@ -149,22 +172,21 @@ public class ExtractedContentViewer implements DataContentViewer {
|
||||
*/
|
||||
IndexedText rawArtifactText = null;
|
||||
try {
|
||||
rawArtifactText = getRawArtifactText(nodeLookup);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error creating RawText for " + content, ex); //NON-NLS
|
||||
|
||||
}
|
||||
rawArtifactText = getRawArtifactText(artifact);
|
||||
if (rawArtifactText != null) {
|
||||
sources.add(rawArtifactText);
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error creating RawText for " + file, ex); //NON-NLS
|
||||
}
|
||||
|
||||
// Now set the default source to be displayed.
|
||||
if (null != highlightedHitText) {
|
||||
if (highlightedHitText != null) {
|
||||
currentSource = highlightedHitText;
|
||||
} else if (null != rawContentText) {
|
||||
currentSource = rawContentText;
|
||||
} else {
|
||||
} else if (rawArtifactText != null) {
|
||||
currentSource = rawArtifactText;
|
||||
} else {
|
||||
currentSource = rawContentText;
|
||||
}
|
||||
|
||||
// Push the text sources into the panel.
|
||||
@ -177,16 +199,15 @@ public class ExtractedContentViewer implements DataContentViewer {
|
||||
panel.updateControls(currentSource);
|
||||
|
||||
String contentName = "";
|
||||
if (content != null) {
|
||||
contentName = content.getName();
|
||||
if (file != null) {
|
||||
contentName = file.getName();
|
||||
}
|
||||
setPanel(contentName, sources);
|
||||
|
||||
}
|
||||
|
||||
static private IndexedText getRawArtifactText(Lookup nodeLookup) throws TskCoreException {
|
||||
static private IndexedText getRawArtifactText(BlackboardArtifact artifact) throws TskCoreException {
|
||||
IndexedText rawArtifactText = null;
|
||||
BlackboardArtifact artifact = nodeLookup.lookup(BlackboardArtifact.class);
|
||||
if (null != artifact) {
|
||||
/*
|
||||
* For keyword hit artifacts, add the text of the artifact that hit,
|
||||
@ -275,37 +296,69 @@ public class ExtractedContentViewer implements DataContentViewer {
|
||||
}
|
||||
|
||||
/*
|
||||
* Is there a credit card or keyword hit artifact in the lookup
|
||||
* If the lookup of the node contains an ad hoc search result object,
|
||||
* then there must be indexed text that produced the hit.
|
||||
*/
|
||||
Collection<? extends BlackboardArtifact> artifacts = node.getLookup().lookupAll(BlackboardArtifact.class);
|
||||
if (artifacts != null) {
|
||||
for (BlackboardArtifact art : artifacts) {
|
||||
final int artifactTypeID = art.getArtifactTypeID();
|
||||
if (artifactTypeID == TSK_ACCOUNT.getTypeID()) {
|
||||
AdHocQueryResult adHocQueryResult = node.getLookup().lookup(AdHocQueryResult.class);
|
||||
if (adHocQueryResult != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the lookup of the node contains either a keyword hit artifact or
|
||||
* one to many credit card account artifacts from a credit card account
|
||||
* numbers search, then there must be indexed text that produced the
|
||||
* hit(s).
|
||||
*/
|
||||
BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
|
||||
if (artifact != null) {
|
||||
final int artifactTypeID = artifact.getArtifactTypeID();
|
||||
if (artifactTypeID == TSK_KEYWORD_HIT.getTypeID()) {
|
||||
return true;
|
||||
} else if (artifactTypeID == TSK_ACCOUNT.getTypeID()) {
|
||||
try {
|
||||
BlackboardAttribute attribute = art.getAttribute(TSK_ACCOUNT_TYPE);
|
||||
BlackboardAttribute attribute = artifact.getAttribute(TSK_ACCOUNT_TYPE);
|
||||
if (attribute != null && Account.Type.CREDIT_CARD.getTypeName().equals(attribute.getValueString())) {
|
||||
return true;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error getting TSK_ACCOUNT_TYPE attribute from artifact " + art.getArtifactID(), ex);
|
||||
}
|
||||
} else if (artifactTypeID == TSK_KEYWORD_HIT.getTypeID()) {
|
||||
/*
|
||||
* If there is an error, log it and return true. The reason
|
||||
* for returning true is so that the user will have an
|
||||
* opportunity to see an error message in the panel when
|
||||
* this query fails again when setNode is called, instead of
|
||||
* having an unexpectedly disabled content viewer with no
|
||||
* other feedback.
|
||||
*/
|
||||
logger.log(Level.SEVERE, "Error getting TSK_ACCOUNT_TYPE attribute from artifact " + artifact.getArtifactID(), ex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* No highlighted text for a keyword hit, so is there any indexed text
|
||||
* at all for this node?
|
||||
* If the lookup of the node contains an artifact that is neither a
|
||||
* keyword hit artifact nor a credit card account artifact, check to see
|
||||
* if there is indexed text for the artifact.
|
||||
*/
|
||||
long documentID = getDocumentId(node);
|
||||
if (INVALID_DOCUMENT_ID == documentID) {
|
||||
return false;
|
||||
if (artifact != null) {
|
||||
return solrHasContent(artifact.getArtifactID());
|
||||
}
|
||||
|
||||
return solrHasContent(documentID);
|
||||
/*
|
||||
* If the lookup of the node contains no artifacts but does contain a
|
||||
* file, check to see if there is indexed text for the file.
|
||||
*/
|
||||
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
|
||||
if (file != null) {
|
||||
return solrHasContent(file.getId());
|
||||
}
|
||||
|
||||
/*
|
||||
* If the lookup of the node contains neither ad hoc search results, nor
|
||||
* artifacts, nor a file, there is no indexed text.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -357,57 +410,6 @@ public class ExtractedContentViewer implements DataContentViewer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the object ID to use as the document ID for accessing any indexed
|
||||
* text for the given node.
|
||||
*
|
||||
* @param node The node.
|
||||
*
|
||||
* @return The document ID or zero, which is an invalid document ID.
|
||||
*/
|
||||
private Long getDocumentId(Node node) {
|
||||
/**
|
||||
* If the node is a Blackboard artifact node for anything other than a
|
||||
* keyword hit, the document ID for the text extracted from the artifact
|
||||
* (the concatenation of its attributes) is the artifact ID, a large,
|
||||
* negative integer. If it is a keyword hit, see if there is an
|
||||
* associated artifact. If there is, get the associated artifact's ID
|
||||
* and return it.
|
||||
*/
|
||||
BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
|
||||
if (null != artifact) {
|
||||
if (artifact.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
|
||||
return artifact.getArtifactID();
|
||||
} else {
|
||||
try {
|
||||
// Get the associated artifact attribute and return its value as the ID
|
||||
BlackboardAttribute blackboardAttribute = artifact.getAttribute(TSK_ASSOCIATED_ARTIFACT_TYPE);
|
||||
if (blackboardAttribute != null) {
|
||||
return blackboardAttribute.getValueLong();
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error getting associated artifact attributes", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For keyword search hit artifact nodes and all other nodes, the
|
||||
* document ID for the extracted text is the ID of the associated
|
||||
* content, if any, unless there is an associated artifact, which is
|
||||
* handled above.
|
||||
*/
|
||||
Content content = node.getLookup().lookup(Content.class);
|
||||
if (content != null) {
|
||||
return content.getId();
|
||||
}
|
||||
|
||||
/*
|
||||
* No extracted text, return an invalid docuemnt ID.
|
||||
*/
|
||||
return 0L;
|
||||
}
|
||||
|
||||
private class NextFindActionListener implements ActionListener {
|
||||
|
||||
@Override
|
||||
|
@ -68,7 +68,7 @@ class HighlightedText implements IndexedText {
|
||||
|
||||
final private Server solrServer = KeywordSearch.getServer();
|
||||
|
||||
private final long objectId;
|
||||
private final long solrObjectId;
|
||||
/*
|
||||
* The keywords to highlight
|
||||
*/
|
||||
@ -104,14 +104,14 @@ class HighlightedText implements IndexedText {
|
||||
* search results. In that case we have the entire QueryResults object and
|
||||
* need to arrange the paging.
|
||||
*
|
||||
* @param objectId The objectID of the content whose text will be
|
||||
* @param solrObjectId The solrObjectId of the content whose text will be
|
||||
* highlighted.
|
||||
* @param QueryResults The QueryResults for the ad-hoc search from whose
|
||||
* results a selection was made leading to this
|
||||
* HighlightedText.
|
||||
*/
|
||||
HighlightedText(long objectId, QueryResults hits) {
|
||||
this.objectId = objectId;
|
||||
HighlightedText(long solrObjectId, QueryResults hits) {
|
||||
this.solrObjectId = solrObjectId;
|
||||
this.hits = hits;
|
||||
}
|
||||
|
||||
@ -127,9 +127,9 @@ class HighlightedText implements IndexedText {
|
||||
this.artifact = artifact;
|
||||
BlackboardAttribute attribute = artifact.getAttribute(TSK_ASSOCIATED_ARTIFACT);
|
||||
if (attribute != null) {
|
||||
this.objectId = attribute.getValueLong();
|
||||
this.solrObjectId = attribute.getValueLong();
|
||||
} else {
|
||||
this.objectId = artifact.getObjectID();
|
||||
this.solrObjectId = artifact.getObjectID();
|
||||
}
|
||||
|
||||
}
|
||||
@ -143,7 +143,7 @@ class HighlightedText implements IndexedText {
|
||||
return;
|
||||
}
|
||||
|
||||
this.numberPages = solrServer.queryNumFileChunks(this.objectId);
|
||||
this.numberPages = solrServer.queryNumFileChunks(this.solrObjectId);
|
||||
|
||||
if (artifact != null) {
|
||||
loadPageInfoFromArtifact();
|
||||
@ -190,7 +190,7 @@ class HighlightedText implements IndexedText {
|
||||
// Run a query to figure out which chunks for the current object have
|
||||
// hits for this keyword.
|
||||
|
||||
chunksQuery.addFilter(new KeywordQueryFilter(FilterType.CHUNK, this.objectId));
|
||||
chunksQuery.addFilter(new KeywordQueryFilter(FilterType.CHUNK, this.solrObjectId));
|
||||
|
||||
hits = chunksQuery.performQuery();
|
||||
loadPageInfoFromHits();
|
||||
@ -212,7 +212,7 @@ class HighlightedText implements IndexedText {
|
||||
for (KeywordHit hit : hits.getResults(k)) {
|
||||
int chunkID = hit.getChunkId();
|
||||
if (artifact != null) {
|
||||
if (chunkID != 0 && this.objectId == hit.getSolrObjectId()) {
|
||||
if (chunkID != 0 && this.solrObjectId == hit.getSolrObjectId()) {
|
||||
String hit1 = hit.getHit();
|
||||
if (keywords.stream().anyMatch(hit1::contains)) {
|
||||
numberOfHitsPerPage.put(chunkID, 0); //unknown number of matches in the page
|
||||
@ -221,7 +221,7 @@ class HighlightedText implements IndexedText {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (chunkID != 0 && this.objectId == hit.getSolrObjectId()) {
|
||||
if (chunkID != 0 && this.solrObjectId == hit.getSolrObjectId()) {
|
||||
|
||||
numberOfHitsPerPage.put(chunkID, 0); //unknown number of matches in the page
|
||||
currentHitPerPage.put(chunkID, 0); //set current hit to 0th
|
||||
@ -350,7 +350,7 @@ class HighlightedText implements IndexedText {
|
||||
SolrQuery q = new SolrQuery();
|
||||
q.setShowDebugInfo(DEBUG); //debug
|
||||
|
||||
String contentIdStr = Long.toString(this.objectId);
|
||||
String contentIdStr = Long.toString(this.solrObjectId);
|
||||
if (numberPages != 0) {
|
||||
chunkID = Integer.toString(this.currentPage);
|
||||
contentIdStr += "0".equals(chunkID) ? "" : "_" + chunkID;
|
||||
@ -423,7 +423,7 @@ class HighlightedText implements IndexedText {
|
||||
|
||||
return "<html><pre>" + highlightedContent + "</pre></html>"; //NON-NLS
|
||||
} catch (TskCoreException | KeywordSearchModuleException | NoOpenCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error getting highlighted text for Solr doc id " + objectId + ", chunkID " + chunkID + ", highlight query: " + highlightField, ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Error getting highlighted text for Solr doc id " + solrObjectId + ", chunkID " + chunkID + ", highlight query: " + highlightField, ex); //NON-NLS
|
||||
return Bundle.IndexedText_errorMessage_errorGettingText();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2017 Basis Technology Corp.
|
||||
* Copyright 2013-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -39,6 +39,7 @@ import org.sleuthkit.autopsy.actions.AddContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
||||
import org.sleuthkit.autopsy.directorytree.HashSearchAction;
|
||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.AdHocQueryResult;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentVisitor;
|
||||
@ -52,12 +53,18 @@ import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
|
||||
/**
|
||||
*
|
||||
* FilterNode containing properties and actions for keyword search.
|
||||
*/
|
||||
class KeywordSearchFilterNode extends FilterNode {
|
||||
|
||||
KeywordSearchFilterNode(QueryResults highlights, Node original) {
|
||||
super(original, null, new ProxyLookup(Lookups.singleton(highlights), original.getLookup()));
|
||||
/**
|
||||
* Instantiate a KeywordSearchFilterNode.
|
||||
*
|
||||
* @param adHocQueryResult The query content.
|
||||
* @param original The original source node.
|
||||
*/
|
||||
KeywordSearchFilterNode(AdHocQueryResult adHocQueryResult, Node original) {
|
||||
super(original, null, new ProxyLookup(Lookups.singleton(adHocQueryResult), original.getLookup()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -37,7 +37,6 @@ 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.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
@ -49,6 +48,7 @@ import org.sleuthkit.autopsy.datamodel.KeyValue;
|
||||
import org.sleuthkit.autopsy.datamodel.KeyValueNode;
|
||||
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.KeyValueQueryContent;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW;
|
||||
@ -66,7 +66,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
*/
|
||||
class KeywordSearchResultFactory extends ChildFactory<KeyValue> {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(KeywordSearchResultFactory.class.getName());
|
||||
private static final Logger logger = Logger.getLogger(KeywordSearchResultFactory.class.getName());
|
||||
|
||||
//common properties (superset of all Node properties) to be displayed as columns
|
||||
static final List<String> COMMON_PROPERTIES
|
||||
@ -140,7 +140,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValue> {
|
||||
try {
|
||||
queryResults = queryRequest.performQuery();
|
||||
} catch (KeywordSearchModuleException | NoOpenCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Could not perform the query " + queryRequest.getQueryString(), ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Could not perform the query " + queryRequest.getQueryString(), ex); //NON-NLS
|
||||
MessageNotifyUtil.Notify.error(Bundle.KeywordSearchResultFactory_query_exception_msg() + queryRequest.getQueryString(), ex.getCause().getMessage());
|
||||
return false;
|
||||
}
|
||||
@ -148,7 +148,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValue> {
|
||||
try {
|
||||
tskCase = Case.getCurrentCase().getSleuthkitCase();
|
||||
} catch (IllegalStateException ex) {
|
||||
LOGGER.log(Level.SEVERE, "There was no case open.", ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "There was no case open.", ex); //NON-NLS
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -165,11 +165,11 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValue> {
|
||||
try {
|
||||
content = tskCase.getContentById(hit.getContentID());
|
||||
if (content == null) {
|
||||
LOGGER.log(Level.SEVERE, "There was a error getting content by id."); //NON-NLS
|
||||
logger.log(Level.SEVERE, "There was a error getting content by id."); //NON-NLS
|
||||
return false;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "There was a error getting content by id.", ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "There was a error getting content by id.", ex); //NON-NLS
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -188,18 +188,20 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValue> {
|
||||
}
|
||||
|
||||
String hitName;
|
||||
BlackboardArtifact artifact = null;
|
||||
if (hit.isArtifactHit()) {
|
||||
try {
|
||||
hitName = tskCase.getBlackboardArtifact(hit.getArtifactID().get()).getDisplayName() + " Artifact"; //NON-NLS
|
||||
artifact = tskCase.getBlackboardArtifact(hit.getArtifactID().get());
|
||||
hitName = artifact.getDisplayName() + " Artifact"; //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting blckboard artifact by id", ex);
|
||||
logger.log(Level.SEVERE, "Error getting blckboard artifact by id", ex);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
hitName = contentName;
|
||||
}
|
||||
hitNumber++;
|
||||
tempList.add(new KeyValueQueryContent(hitName, properties, hitNumber, hit.getSolrObjectId(), content, queryRequest, queryResults));
|
||||
tempList.add(new KeyValueQueryContent(hitName, properties, hitNumber, hit.getSolrObjectId(), content, artifact, queryRequest, queryResults));
|
||||
|
||||
}
|
||||
|
||||
@ -250,13 +252,12 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValue> {
|
||||
Node resultNode;
|
||||
|
||||
if (key instanceof KeyValueQueryContent) {
|
||||
final Content content = ((KeyValueQueryContent) key).getContent();
|
||||
QueryResults hits = ((KeyValueQueryContent) key).getHits();
|
||||
AdHocQueryResult adHocQueryResult = new AdHocQueryResult((KeyValueQueryContent) key);
|
||||
|
||||
Node kvNode = new KeyValueNode(key, Children.LEAF, Lookups.singleton(content));
|
||||
Node kvNode = new KeyValueNode(key, Children.LEAF);
|
||||
|
||||
//wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization
|
||||
resultNode = new KeywordSearchFilterNode(hits, kvNode);
|
||||
resultNode = new KeywordSearchFilterNode(adHocQueryResult, kvNode);
|
||||
} else {
|
||||
resultNode = new EmptyNode("This Node Is Empty");
|
||||
resultNode.setDisplayName(NbBundle.getMessage(this.getClass(), "KeywordSearchResultFactory.createNodeForKey.noResultsFound.text"));
|
||||
@ -266,6 +267,75 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValue> {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This class encapsulates content, query results, and an associated Solr
|
||||
* object ID for storing in the Lookup to be read later.
|
||||
*/
|
||||
final class AdHocQueryResult {
|
||||
|
||||
private final long solrObjectId;
|
||||
private final Content content;
|
||||
private final BlackboardArtifact artifact;
|
||||
private final QueryResults results;
|
||||
|
||||
/**
|
||||
* Instantiate a AdHocQueryResult object.
|
||||
*
|
||||
* @param solrObjectId The Solr object ID associated with the object in
|
||||
* which the hit was found.
|
||||
* @param content The content for the query result.
|
||||
* @param artifact The artifact associated with the query result.
|
||||
* @param results The query results.
|
||||
*/
|
||||
AdHocQueryResult(KeyValueQueryContent key) {
|
||||
this.solrObjectId = key.getSolrObjectId();
|
||||
this.content = key.getContent();
|
||||
this.artifact = key.getArtifact();
|
||||
this.results = key.getHits();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Solr object ID associated with the object in which the hit
|
||||
* was found. This could be a file or an artifact.
|
||||
*
|
||||
* @return The Solr object ID.
|
||||
*/
|
||||
long getSolrObjectId() {
|
||||
return solrObjectId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content for the query result. This can be either a file or a
|
||||
* data source, and it may or may not be the content in which the hit
|
||||
* occurred. If the hit is in a file, the Content object represents that
|
||||
* file. But if the hit is in an artifact, the Content object represents
|
||||
* the source file or data source of the artifact.
|
||||
*
|
||||
* @return The content object.
|
||||
*/
|
||||
Content getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the artifact for the query result.
|
||||
*
|
||||
* @return The artifact.
|
||||
*/
|
||||
BlackboardArtifact getArtifact() {
|
||||
return artifact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query results.
|
||||
*
|
||||
* @return The query results.
|
||||
*/
|
||||
QueryResults getResults() {
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to display keyword search results in table. Eventually turned into a
|
||||
* node.
|
||||
@ -275,6 +345,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValue> {
|
||||
private final long solrObjectId;
|
||||
|
||||
private final Content content;
|
||||
private final BlackboardArtifact artifact;
|
||||
private final QueryResults hits;
|
||||
private final KeywordSearchQuery query;
|
||||
|
||||
@ -286,15 +357,17 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValue> {
|
||||
* @param map Contains content metadata, snippets, etc.
|
||||
* (property map)
|
||||
* @param id User incremented ID
|
||||
* @param solrObjectId
|
||||
* @param content File that had the hit.
|
||||
* @param solrObjectId The ID of the object.
|
||||
* @param content The content object.
|
||||
* @param artifact The blackboard artifact.
|
||||
* @param query Query used in search
|
||||
* @param hits Full set of search results (for all files! @@@)
|
||||
*/
|
||||
KeyValueQueryContent(String name, Map<String, Object> map, int id, long solrObjectId, Content content, KeywordSearchQuery query, QueryResults hits) {
|
||||
KeyValueQueryContent(String name, Map<String, Object> map, int id, long solrObjectId, Content content, BlackboardArtifact artifact, KeywordSearchQuery query, QueryResults hits) {
|
||||
super(name, map, id);
|
||||
this.solrObjectId = solrObjectId;
|
||||
this.content = content;
|
||||
this.artifact = artifact;
|
||||
|
||||
this.hits = hits;
|
||||
this.query = query;
|
||||
@ -304,6 +377,10 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValue> {
|
||||
return content;
|
||||
}
|
||||
|
||||
BlackboardArtifact getArtifact() {
|
||||
return artifact;
|
||||
}
|
||||
|
||||
long getSolrObjectId() {
|
||||
return solrObjectId;
|
||||
}
|
||||
@ -358,9 +435,9 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValue> {
|
||||
try {
|
||||
get();
|
||||
} catch (InterruptedException | CancellationException ex) {
|
||||
LOGGER.log(Level.WARNING, "User cancelled writing of ad hoc search query results for '{0}' to the blackboard", query.getQueryString()); //NON-NLS
|
||||
logger.log(Level.WARNING, "User cancelled writing of ad hoc search query results for '{0}' to the blackboard", query.getQueryString()); //NON-NLS
|
||||
} catch (ExecutionException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error writing of ad hoc search query results for " + query.getQueryString() + " to the blackboard", ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Error writing of ad hoc search query results for " + query.getQueryString() + " to the blackboard", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user