Merge pull request #7247 from rcordovano/7977-fix-analysis-result-tagging

7977 fix analysis result tagging
This commit is contained in:
Richard Cordovano 2021-09-09 10:23:41 -04:00 committed by GitHub
commit fadf8abf3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 153 additions and 43 deletions

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2013-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -29,6 +29,7 @@ import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.BlackboardArtifactItem;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TagName;
@ -46,6 +47,8 @@ import org.sleuthkit.datamodel.TskCoreException;
})
public class AddBlackboardArtifactTagAction extends AddTagAction {
private static final long serialVersionUID = 1L;
// This class is a singleton to support multi-selection of nodes, since
// org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
// node in the array returns a reference to the same action object from Node.getActions(boolean).
@ -82,8 +85,14 @@ public class AddBlackboardArtifactTagAction extends AddTagAction {
* invocation of addTag(), we don't want to tag the same
* BlackboardArtifact more than once, so we dedupe the
* BlackboardArtifacts by stuffing them into a HashSet.
*
* RC (9/8/21): The documentation does NOT say that lookupAll() can
* return duplicates. That would be very broken. What motivated this
* "de-duping" ?
*/
selectedArtifacts.addAll(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
for (BlackboardArtifactItem<?> item : Utilities.actionsGlobalContext().lookupAll(BlackboardArtifactItem.class)) {
selectedArtifacts.add(item.getTskContent());
}
} else {
for (Content content : getContentToTag()) {
if (content instanceof BlackboardArtifact) {
@ -111,4 +120,10 @@ public class AddBlackboardArtifactTagAction extends AddTagAction {
}
}).start();
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2020 Basis Technology Corp.
* Copyright 2013-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -44,22 +44,29 @@ import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
/**
* An abstract base class for Actions that allow users to tag SleuthKit data
* An abstract super class for Actions that allow users to tag Sleuth Kit data
* model objects.
*/
abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
private static final long serialVersionUID = 1L;
private static final String NO_COMMENT = "";
private final Collection<Content> content = new HashSet<>();
private final Collection<Content> contentObjsToTag;
/**
* Constructs an instance of an abstract super class for Actions that allow
* users to tag Sleuth Kit data model objects.
*
* @param menuText The menu item text.
*/
AddTagAction(String menuText) {
super(menuText);
contentObjsToTag = new HashSet<>();
}
@Override
public JMenuItem getPopupPresenter() {
content.clear();
contentObjsToTag.clear();
return new TagMenu();
}
@ -70,7 +77,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
* @return The specified content for this action.
*/
Collection<Content> getContentToTag() {
return Collections.unmodifiableCollection(content);
return Collections.unmodifiableCollection(contentObjsToTag);
}
/**
@ -83,8 +90,8 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
* apply to the Content specified.
*/
public JMenuItem getMenuForContent(Collection<? extends Content> contentToTag) {
content.clear();
content.addAll(contentToTag);
contentObjsToTag.clear();
contentObjsToTag.addAll(contentToTag);
return new TagMenu();
}
@ -111,6 +118,11 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
*/
abstract protected void addTag(TagName tagName, String comment);
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
/**
* Instances of this class implement a context menu user interface for
* creating or selecting a tag name for a tag and specifying an optional tag
@ -126,7 +138,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
super(getActionDisplayName());
// Get the current set of tag names.
Map<String, TagName> tagNamesMap = null;
Map<String, TagName> tagNamesMap;
List<String> standardTagNames = TagsManager.getStandardTagNames();
Map<String, JMenu> tagSetMenuMap = new HashMap<>();
List<JMenuItem> standardTagMenuitems = new ArrayList<>();
@ -240,5 +252,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
return tagNameItem;
}
}
}

View File

@ -132,7 +132,7 @@ public class AnalysisResultsContentViewer implements DataContentViewer {
return true;
}
TskContentItem contentItem = node.getLookup().lookup(TskContentItem.class);
TskContentItem<?> contentItem = node.getLookup().lookup(TskContentItem.class);
if (!Objects.isNull(contentItem)) {
Content content = contentItem.getTskContent();
try {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 Basis Technology Corp.
* Copyright 2021-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -251,7 +251,7 @@ public class AnalysisResultsViewModel {
* selected in the content viewer and get the analyzed content
* as the source of the analysis results to display.
*/
selectedAnalysisResult = analysisResultItem.getAnalysisResult();
selectedAnalysisResult = analysisResultItem.getTskContent();
selectedObjectId = selectedAnalysisResult.getId();
analyzedContent = selectedAnalysisResult.getParent();
} else {
@ -260,7 +260,7 @@ public class AnalysisResultsViewModel {
* an analysis result. Use it as the source of the analysis
* results to display.
*/
TskContentItem contentItem = node.getLookup().lookup(TskContentItem.class);
TskContentItem<?> contentItem = node.getLookup().lookup(TskContentItem.class);
analyzedContent = contentItem.getTskContent();
selectedObjectId = analyzedContent.getId();
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2012-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -39,7 +39,6 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeIns
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance.Type;
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AnalysisResult;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Score;
@ -102,7 +101,7 @@ public abstract class AbstractContentNode<T extends Content> extends ContentNode
* @param content Underlying Content instances
*/
AbstractContentNode(T content) {
this(content, Lookups.fixed(content, new TskContentItem(content)));
this(content, Lookups.fixed(content, new TskContentItem<>(content)));
}
/**

View File

@ -22,30 +22,20 @@ import com.google.common.annotations.Beta;
import org.sleuthkit.datamodel.AnalysisResult;
/**
* An Autopsy Data Model item with an underlying analysis result Sleuth Kit Data
* An Autopsy Data Model item with an underlying AnalysisResult Sleuth Kit Data
* Model object.
*/
public class AnalysisResultItem extends TskContentItem {
public class AnalysisResultItem extends BlackboardArtifactItem<AnalysisResult> {
/**
* Constructs an Autopsy Data Model item with an underlying AnalysisResult
* Sleuth Kit Data Model object.
*
* @param analysisResult The analysis result.
* @param analysisResult The AnalysisResult object.
*/
@Beta
AnalysisResultItem(AnalysisResult analysisResult) {
super(analysisResult);
}
/**
* Gets the underlying analysis result.
*
* @return The analysis result.
*/
@Beta
public AnalysisResult getAnalysisResult() {
return (AnalysisResult) (getTskContent());
}
}

View File

@ -0,0 +1,44 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021-2021 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.datamodel;
import com.google.common.annotations.Beta;
import org.sleuthkit.datamodel.BlackboardArtifact;
/**
* An abstract super class for an Autopsy Data Model item class with an
* underlying BlackboardArtifact Sleuth Kit Data Model object, i.e., a
* DataArtifact or an AnalysisResult.
*
* @param <T> The concrete BlackboardArtifact sub class type.
*/
public abstract class BlackboardArtifactItem<T extends BlackboardArtifact> extends TskContentItem<T> {
/**
* Constructs an Autopsy Data Model item with an underlying
* BlackboardArtifact Sleuth Kit Data Model object.
*
* @param blackboardArtifact The BlackboardArtifact object.
*/
@Beta
BlackboardArtifactItem(T blackboardArtifact) {
super(blackboardArtifact);
}
}

View File

@ -81,6 +81,7 @@ import org.sleuthkit.autopsy.texttranslation.TextTranslationService;
import org.sleuthkit.autopsy.datamodel.utils.FileNameTransTask;
import org.sleuthkit.datamodel.AnalysisResult;
import org.sleuthkit.datamodel.BlackboardArtifact.Category;
import org.sleuthkit.datamodel.DataArtifact;
import org.sleuthkit.datamodel.Score;
/**
@ -366,18 +367,22 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
*
* NOTE: The creation of an Autopsy Data Model independent of the
* NetBeans nodes is a work in progress. At the time this comment is
* being written, this object is only used by the analysis content
* viewer.
* being written, this object is only being used to indicate the item
* represented by this BlackboardArtifactNode.
*/
TskContentItem artifactItem;
BlackboardArtifactItem<?> artifactItem;
if (artifact instanceof AnalysisResult) {
artifactItem = new AnalysisResultItem((AnalysisResult) artifact);
} else {
artifactItem = new TskContentItem(artifact);
artifactItem = new DataArtifactItem((DataArtifact) artifact);
}
/*
* Create the Lookup.
*
* NOTE: For now, we are putting both the Autopsy Data Model item and
* the Sleuth Kit Data Model item in the Lookup so that code that is not
* aware of the new Autopsy Data Model will still function.
*/
if (content == null) {
return Lookups.fixed(artifact, artifactItem);

View File

@ -0,0 +1,41 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021-2021 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.datamodel;
import com.google.common.annotations.Beta;
import org.sleuthkit.datamodel.DataArtifact;
/**
* An Autopsy Data Model item with an underlying DataArtifact Sleuth Kit Data
* Model object.
*/
public class DataArtifactItem extends BlackboardArtifactItem<DataArtifact> {
/**
* Constructs an Autopsy Data Model item with an underlying DataArtifact
* Sleuth Kit Data Model object.
*
* @param dataArtifact The DataArtifact object.
*/
@Beta
DataArtifactItem(DataArtifact dataArtifact) {
super(dataArtifact);
}
}

View File

@ -24,23 +24,25 @@ import org.sleuthkit.datamodel.Content;
/**
* An Autopsy Data Model item with an underlying Sleuth Kit Data Model object
* that implements the Sleuth Kit Data Model's Content interface.
*
* @param <T> The type of the underlying Sleuth Kit Data Model object.
*/
@Beta
public class TskContentItem {
public class TskContentItem<T extends Content> {
private final Content tskContent;
private final T content;
/**
* Constructs an Autopsy Data Model item with an underlying Sleuth Kit Data
* Model object that implements the Sleuth Kit Data Model's Content
* interface.
*
* @param content The underlying Sleuth Kit Data Model object.
* @param content The Sleuth Kit Data Model object.
*
*/
@Beta
TskContentItem(Content sleuthKitContent) {
this.tskContent = sleuthKitContent;
TskContentItem(T content) {
this.content = content;
}
/**
@ -49,8 +51,8 @@ public class TskContentItem {
* @return The Sleuth Kit Data Model object.
*/
@Beta
public Content getTskContent() {
return tskContent;
public T getTskContent() {
return content;
}
}