From 222bb7f81da14add8dddaff8bf2b029db6c38bc6 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 14 Feb 2022 14:53:08 -0500 Subject: [PATCH 1/8] working on tag dao integration --- .../autopsy/mainui/datamodel/TagsDAO.java | 8 + .../mainui/datamodel/TagsSearchParams.java | 33 +- .../autopsy/mainui/nodes/TagNameFactory.java | 762 ++++++++++++++++++ 3 files changed, 778 insertions(+), 25 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java diff --git a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java index b469d3efc3..bec9134ab6 100755 --- a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java +++ b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java @@ -398,6 +398,14 @@ public class TagsDAO extends AbstractDAO { return null; } + public TreeResultsDTO getNameCounts(Long dataSourceId) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + public TreeResultsDTO getTypeCounts(TagNameSearchParams searchParams) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + /** * Handles fetching and paging of data for allTags. */ diff --git a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsSearchParams.java b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsSearchParams.java index 5f5d862cf3..c91a9e51e1 100755 --- a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsSearchParams.java +++ b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsSearchParams.java @@ -24,7 +24,7 @@ import org.sleuthkit.datamodel.TagName; /** * Key for accessing data about tags from the DAO. */ -public class TagsSearchParams { +public class TagsSearchParams extends TagNameSearchParams { private static final String TYPE_ID = "TAG"; @@ -41,33 +41,21 @@ public class TagsSearchParams { } private final TagType type; - private final TagName tagName; - private final Long dataSourceId; public TagsSearchParams(TagName tagName, TagType type, Long dataSourceId) { - this.tagName = tagName; + super(tagName, dataSourceId); this.type = type; - this.dataSourceId = dataSourceId; - } - - public TagName getTagName() { - return tagName; } public TagType getTagType() { return type; } - public Long getDataSourceId() { - return dataSourceId; - } - @Override public int hashCode() { - int hash = 7; - hash = 23 * hash + Objects.hashCode(this.tagName); - hash = 23 * hash + Objects.hashCode(this.type); - hash = 23 * hash + Objects.hashCode(this.dataSourceId); + int hash = 3; + hash = 97 * hash + Objects.hashCode(this.type); + hash = 97 * hash + super.hashCode(); return hash; } @@ -83,16 +71,11 @@ public class TagsSearchParams { return false; } final TagsSearchParams other = (TagsSearchParams) obj; - if (!Objects.equals(this.tagName, other.tagName)) { + if (this.type != other.type) { return false; } - if (!Objects.equals(this.dataSourceId, other.dataSourceId)) { - return false; - } - if (!Objects.equals(this.type, other.type)) { - return false; - } - return true; + return super.equals(obj); } + } diff --git a/Core/src/org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java b/Core/src/org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java new file mode 100644 index 0000000000..62c1be6c6d --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java @@ -0,0 +1,762 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit 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.mainui.nodes; + +import java.util.Comparator; +import java.util.Objects; +import java.util.concurrent.ExecutionException; +import org.openide.nodes.Children; +import org.openide.util.Lookup; +import org.sleuthkit.autopsy.mainui.datamodel.MainDAO; +import org.sleuthkit.autopsy.mainui.datamodel.TagNameSearchParams; +import org.sleuthkit.autopsy.mainui.datamodel.TagsSearchParams; +import org.sleuthkit.autopsy.mainui.datamodel.TreeResultsDTO; +import org.sleuthkit.autopsy.mainui.datamodel.TreeResultsDTO.TreeItemDTO; +import org.sleuthkit.autopsy.mainui.datamodel.events.DAOAggregateEvent; +import org.sleuthkit.autopsy.mainui.datamodel.events.DAOEvent; +import org.sleuthkit.autopsy.mainui.datamodel.events.DeleteAnalysisResultEvent; +import org.sleuthkit.autopsy.mainui.datamodel.events.TreeEvent; + +/** + * Factory for displaying analysis result types in the tree. + */ +public class TagNameFactory extends TreeChildFactory { + + // GVDTODO + private static final String TAG_ICON = TBD; + + private final Long dataSourceId; + + /** + * Main constructor. + * + * @param dataSourceId The data source id to filter on or null if no filter. + */ + public TagNameFactory(Long dataSourceId) { + this.dataSourceId = dataSourceId; + } + + @Override + protected TreeResultsDTO getChildResults() throws IllegalArgumentException, ExecutionException { + return MainDAO.getInstance().getTagsDAO().getNameCounts(dataSourceId); + } + + @Override + protected TreeNode createNewNode(TreeResultsDTO.TreeItemDTO rowData) { + return new TagNameNode(rowData); + } + + @Override + protected TreeResultsDTO.TreeItemDTO getOrCreateRelevantChild(TreeEvent treeEvt) { + TreeResultsDTO.TreeItemDTO originalTreeItem = super.getTypedTreeItem(treeEvt, TagNameSearchParams.class); + + if (originalTreeItem != null + && (this.dataSourceId == null || Objects.equals(this.dataSourceId, originalTreeItem.getSearchParams().getDataSourceId()))) { + + // GVDTODO + return MainDAO.getInstance().getTagsDAO().getTagNameTreeItem(originalTreeItem); + } + return null; + } + + @Override + public int compare(TreeItemDTO o1, TreeItemDTO o2) { + return Comparator.comparing(tagTreeItem -> tagTreeItem.getSearchParams().getTagName().getDisplayName()) + .compare(o1, o2); + } + + @Override + protected void handleDAOAggregateEvent(DAOAggregateEvent aggEvt) { + for (DAOEvent evt : aggEvt.getEvents()) { + if (evt instanceof DeleteAnalysisResultEvent && evt.getType() == DAOEvent.Type.TREE) { + super.update(); + return; + } + } + + super.handleDAOAggregateEvent(aggEvt); + } + + + static class TagNameNode extends TreeNode { + + public TagNameNode(TreeResultsDTO.TreeItemDTO rowData) { + super(rowData.getName(), + TAG_ICON, + rowData, + Children.create(new TagTypeFactory(rowData.getSearchParams()), false), + getDefaultLookup(rowData)); + } + + } + + static class TagTypeFactory extends TreeChildFactory { + + private final TagNameSearchParams searchParams; + + TagTypeFactory(TagNameSearchParams searchParams) { + this.searchParams = searchParams; + } + + + @Override + protected TreeNode createNewNode(TreeItemDTO rowData) { + return new TagsTypeNode(rowData); + } + + @Override + protected TreeResultsDTO getChildResults() throws IllegalArgumentException, ExecutionException { + return MainDAO.getInstance().getTagsDAO().getTypeCounts(searchParams); + } + + @Override + protected TreeItemDTO getOrCreateRelevantChild(TreeEvent treeEvt) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public int compare(TreeItemDTO o1, TreeItemDTO o2) { + return Comparator.comparing(rowData -> rowData.getSearchParams().getTagType() == TagsSearchParams.TagType.FILE ? 0 : 1) + .compare(o1, o2); + } + + } + + static class TagsTypeNode extends TreeNode { + + private TagsTypeNode(TreeItemDTO rowData) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + } + +// /** +// * Display name and count of an analysis result type in the tree. +// */ +// static class AnalysisResultTypeTreeNode extends TreeNode { +// +// /** +// * Main constructor. +// * +// * @param itemData The data to display. +// */ +// AnalysisResultTypeTreeNode(TreeResultsDTO.TreeItemDTO itemData) { +// super(itemData.getSearchParams().getArtifactType().getTypeName(), +// getIconPath(itemData.getSearchParams().getArtifactType()), +// itemData); +// } +// +// @Override +// public void respondSelection(DataResultTopComponent dataResultPanel) { +// dataResultPanel.displayAnalysisResult(this.getItemData().getSearchParams()); +// } +// +// @Override +// public Optional getAnalysisResultType() { +// return Optional.ofNullable(this.getItemData().getSearchParams().getArtifactType()); +// } +// +// @Override +// public Optional getDataSourceIdForActions() { +// return Optional.ofNullable(this.getItemData().getSearchParams().getDataSourceId()); +// } +// +// @Override +// public Optional getNodeSpecificActions() { +// ActionsFactory.ActionGroup group = new ActionsFactory.ActionGroup(); +// +// Optional type = getAnalysisResultType(); +// Optional dsId = getDataSourceIdForActions(); +// if (type.isPresent()) { +// group.add(new DeleteAnalysisResultSetAction(type.get(), () -> Collections.emptyList(), dsId.isPresent() ? dsId.get() : null)); +// } +// +// return Optional.of(group); +// } +// +// } +// +// /** +// * An analysis result type node that has nested children. +// */ +// static class TreeTypeNode extends TreeNode { +// +// /** +// * Main constructor. +// * +// * @param itemData The data to display. +// */ +// TreeTypeNode(TreeResultsDTO.TreeItemDTO itemData, ChildFactory childFactory) { +// super(itemData.getSearchParams().getArtifactType().getTypeName(), +// getIconPath(itemData.getSearchParams().getArtifactType()), +// itemData, +// Children.create(childFactory, true), +// getDefaultLookup(itemData)); +// } +// +// @Override +// public Optional getDataSourceIdForActions() { +// return Optional.ofNullable(this.getItemData().getSearchParams().getDataSourceId()); +// } +// +// @Override +// public Optional getAnalysisResultType() { +// return Optional.ofNullable(this.getItemData().getSearchParams().getArtifactType()); +// } +// } +// +// /** +// * Factory displaying all analysis result configurations with count in the +// * tree. +// */ +// static class TreeConfigFactory extends AbstractAnalysisResultTreeFactory { +// +// private final BlackboardArtifact.Type artifactType; +// private final Long dataSourceId; +// private final String nullSetName; +// +// /** +// * Main constructor. +// * +// * @param artifactType The type of artifact. +// * @param dataSourceId The data source object id for which the results +// * should be filtered or null if no data source +// * filtering. +// * @param nullSetName The name of the set for artifacts with no +// * configuration value. If null, items are omitted. +// */ +// TreeConfigFactory(BlackboardArtifact.Type artifactType, Long dataSourceId, String nullSetName) { +// this.artifactType = artifactType; +// this.dataSourceId = dataSourceId; +// this.nullSetName = nullSetName; +// } +// +// protected BlackboardArtifact.Type getArtifactType() { +// return artifactType; +// } +// +// protected Long getDataSourceId() { +// return dataSourceId; +// } +// +// protected String getNullSetName() { +// return nullSetName; +// } +// +// @Override +// protected TreeResultsDTO getChildResults() throws IllegalArgumentException, ExecutionException { +// return MainDAO.getInstance().getAnalysisResultDAO().getConfigurationCounts(this.artifactType, this.dataSourceId, this.nullSetName); +// } +// +// @Override +// protected TreeNode createNewNode(TreeResultsDTO.TreeItemDTO rowData) { +// return new TreeConfigTypeNode(rowData); +// } +// +// @Override +// protected TreeResultsDTO.TreeItemDTO getOrCreateRelevantChild(TreeEvent treeEvt) { +// TreeResultsDTO.TreeItemDTO originalTreeItem = super.getTypedTreeItem(treeEvt, AnalysisResultSearchParam.class); +// +// if (originalTreeItem != null +// && originalTreeItem.getSearchParams().getArtifactType().equals(this.artifactType) +// && (this.dataSourceId == null || Objects.equals(this.dataSourceId, originalTreeItem.getSearchParams().getDataSourceId()))) { +// +// // generate new type so that if it is a subtree event (i.e. keyword hits), the right tree item is created. +// AnalysisResultSearchParam searchParam = originalTreeItem.getSearchParams(); +// return new TreeResultsDTO.TreeItemDTO<>( +// AnalysisResultSearchParam.getTypeId(), +// new AnalysisResultSearchParam(this.artifactType, searchParam.getConfiguration(), this.dataSourceId), +// searchParam.getConfiguration() == null ? 0 : searchParam.getConfiguration(), +// searchParam.getConfiguration() == null ? nullSetName : searchParam.getConfiguration(), +// originalTreeItem.getDisplayCount()); +// } +// return null; +// } +// +// @Override +// public int compare(TreeItemDTO o1, TreeItemDTO o2) { +// return STRING_COMPARATOR.compare(o1.getSearchParams().getConfiguration(), o2.getSearchParams().getConfiguration()); +// } +// +// @Override +// protected void handleDAOAggregateEvent(DAOAggregateEvent aggEvt) { +// for (DAOEvent evt : aggEvt.getEvents()) { +// if (evt instanceof DeleteAnalysisResultEvent && evt.getType() == DAOEvent.Type.TREE) { +// super.update(); +// return; +// } +// } +// +// super.handleDAOAggregateEvent(aggEvt); +// } +// +// } +// +// /** +// * A node for a set within an artifact type. +// */ +// static class TreeConfigTypeNode extends TreeNode { +// +// /** +// * Main constructor. +// * +// * @param itemData The data to display. +// */ +// TreeConfigTypeNode(TreeResultsDTO.TreeItemDTO itemData) { +// super(itemData.getSearchParams().getArtifactType().getTypeName() + "_SET_" + itemData.getSearchParams().getConfiguration(), +// getIconPath(itemData.getSearchParams().getArtifactType()), +// itemData, +// Children.LEAF, +// getDefaultLookup(itemData)); +// } +// +// @Override +// public void respondSelection(DataResultTopComponent dataResultPanel) { +// dataResultPanel.displayAnalysisResultConfig(this.getItemData().getSearchParams()); +// } +// +// @Override +// public Optional getDataSourceIdForActions() { +// return Optional.ofNullable(this.getItemData().getSearchParams().getDataSourceId()); +// } +// +// @Override +// public Optional getAnalysisResultType() { +// return Optional.ofNullable(this.getItemData().getSearchParams().getArtifactType()); +// } +// +// @Override +// public boolean hasAnalysisResultConfigurations() { +// return true; +// } +// +// @Override +// public List getAnalysisResultConfigurations() { +// return Collections.singletonList(this.getItemData().getSearchParams().getConfiguration()); +// } +// +// @Override +// public Optional getNodeSpecificActions() { +// ActionsFactory.ActionGroup group = new ActionsFactory.ActionGroup(); +// +// Optional type = getAnalysisResultType(); +// Optional dsId = getDataSourceIdForActions(); +// if (type.isPresent()) { +// group.add(new DeleteAnalysisResultSetAction( +// type.get(), +// () -> this.getAnalysisResultConfigurations(), +// dsId.isPresent() ? dsId.get() : null)); +// } +// +// return Optional.of(group); +// } +// } +// +// /** +// * A factory that shows all sets in keyword hits. +// */ +// @Messages({ +// "AnalysisResultTypeFactory_adHocName=Ad Hoc Results" +// }) +// public static class KeywordSetFactory extends AbstractAnalysisResultTreeFactory { +// +// private final Long dataSourceId; +// +// public KeywordSetFactory(Long dataSourceId) { +// this.dataSourceId = dataSourceId; +// } +// +// @Override +// protected TreeResultsDTO getChildResults() throws IllegalArgumentException, ExecutionException { +// return MainDAO.getInstance().getAnalysisResultDAO().getKwSetCounts(this.dataSourceId, Bundle.AnalysisResultTypeFactory_adHocName()); +// } +// +// @Override +// protected TreeResultsDTO.TreeItemDTO getOrCreateRelevantChild(TreeEvent treeEvt) { +// TreeResultsDTO.TreeItemDTO originalTreeItem = super.getTypedTreeItem(treeEvt, KeywordListSearchParam.class); +// +// if (originalTreeItem != null +// && originalTreeItem.getSearchParams().getArtifactType().equals(BlackboardArtifact.Type.TSK_KEYWORD_HIT) +// && (this.dataSourceId == null || Objects.equals(this.dataSourceId, originalTreeItem.getSearchParams().getDataSourceId()))) { +// +// // generate new type so that if it is a subtree event (i.e. keyword hits), the right tree item is created. +// KeywordListSearchParam searchParam = originalTreeItem.getSearchParams(); +// return new TreeResultsDTO.TreeItemDTO<>( +// KeywordListSearchParam.getTypeId(), +// new KeywordListSearchParam(this.dataSourceId, searchParam.getConfiguration(), searchParam.getSetName()), +// searchParam.getSetName() == null ? 0 : searchParam.getSetName(), +// searchParam.getSetName() == null ? Bundle.AnalysisResultTypeFactory_adHocName() : searchParam.getSetName(), +// originalTreeItem.getDisplayCount()); +// } +// return null; +// } +// +// @Override +// public int compare(TreeItemDTO o1, TreeItemDTO o2) { +// return STRING_COMPARATOR.compare(o1.getSearchParams().getSetName(), o2.getSearchParams().getSetName()); +// } +// +// @Override +// protected TreeNode createNewNode(TreeResultsDTO.TreeItemDTO rowData) { +// return new KeywordSetNode(rowData); +// } +// } +// +// static class KeywordSetNode extends TreeNode { +// +// private static final Logger logger = Logger.getLogger(KeywordSetNode.class.getName()); +// +// /** +// * Main constructor. +// * +// * @param itemData The data to display. +// */ +// public KeywordSetNode(TreeResultsDTO.TreeItemDTO itemData) { +// super("TSK_KEYWORD_HIT_SET_" + itemData.getSearchParams().getSetName(), +// getIconPath(itemData.getSearchParams().getArtifactType()), +// itemData, +// Children.create(new KeywordSearchTermFactory(itemData.getSearchParams()), true), +// getDefaultLookup(itemData)); +// } +// +// @Override +// public Optional getDataSourceIdForActions() { +// return Optional.ofNullable(this.getItemData().getSearchParams().getDataSourceId()); +// } +// +// @Override +// public Optional getAnalysisResultType() { +// return Optional.ofNullable(this.getItemData().getSearchParams().getArtifactType()); +// } +// +// @Override +// public boolean hasAnalysisResultConfigurations() { +// return true; +// } +// +// @Override +// public List getAnalysisResultConfigurations() { +// try { +// return MainDAO.getInstance().getAnalysisResultDAO().getKeywordHitConfigurations( +// this.getItemData().getSearchParams().getSetName(), +// this.getItemData().getSearchParams().getDataSourceId()); +// } catch (ExecutionException ex) { +// logger.log(Level.WARNING, "An exception occurred while fetching configurations.", ex); +// return Collections.emptyList(); +// } +// } +// +// @Override +// public Optional getNodeSpecificActions() { +// ActionsFactory.ActionGroup group = new ActionsFactory.ActionGroup(); +// +// Optional type = getAnalysisResultType(); +// Optional dsId = getDataSourceIdForActions(); +// if (type.isPresent()) { +// group.add(new DeleteAnalysisResultSetAction( +// type.get(), +// () -> this.getAnalysisResultConfigurations(), +// dsId.isPresent() ? dsId.get() : null)); +// } +// +// return Optional.of(group); +// } +// } +// +// /** +// * Factory for displaying all search terms (regex or exact) for a specific +// * set. +// */ +// static class KeywordSearchTermFactory extends AbstractAnalysisResultTreeFactory { +// +// private final KeywordListSearchParam setParams; +// +// /** +// * Main constructor. +// * +// * @param setParams The parameters for the set. +// */ +// KeywordSearchTermFactory(KeywordListSearchParam setParams) { +// this.setParams = setParams; +// } +// +// @Override +// protected TreeNode createNewNode(TreeResultsDTO.TreeItemDTO rowData) { +// return new KeywordSearchTermNode(rowData); +// } +// +// @Override +// protected TreeResultsDTO getChildResults() throws IllegalArgumentException, ExecutionException { +// return MainDAO.getInstance().getAnalysisResultDAO().getKeywordSearchTermCounts(this.setParams.getSetName(), this.setParams.getDataSourceId()); +// } +// +// @Override +// protected TreeResultsDTO.TreeItemDTO getOrCreateRelevantChild(TreeEvent treeEvt) { +// TreeResultsDTO.TreeItemDTO originalTreeItem = super.getTypedTreeItem(treeEvt, KeywordSearchTermParams.class); +// +// if (originalTreeItem != null +// && Objects.equals(originalTreeItem.getSearchParams().getSetName(), this.setParams.getSetName()) +// && (this.setParams.getDataSourceId() == null +// || Objects.equals(this.setParams.getDataSourceId(), originalTreeItem.getSearchParams().getDataSourceId()))) { +// +// KeywordSearchTermParams searchParam = originalTreeItem.getSearchParams(); +// String searchTermDisplayName = MainDAO.getInstance().getAnalysisResultDAO() +// .getSearchTermDisplayName(searchParam.getRegex(), searchParam.getSearchType()); +// +// return new TreeResultsDTO.TreeItemDTO<>( +// KeywordSearchTermParams.getTypeId(), +// new KeywordSearchTermParams( +// this.setParams.getSetName(), +// searchParam.getRegex(), +// searchParam.getSearchType(), +// searchParam.getConfiguration(), +// searchParam.hasChildren(), +// this.setParams.getDataSourceId() +// ), +// searchTermDisplayName, +// searchTermDisplayName, +// originalTreeItem.getDisplayCount() +// ); +// } +// return null; +// } +// +// @Override +// public int compare(TreeItemDTO o1, TreeItemDTO o2) { +// return STRING_COMPARATOR.compare(o1.getSearchParams().getRegex(), o2.getSearchParams().getRegex()); +// } +// +// @Override +// protected void handleDAOAggregateEvent(DAOAggregateEvent aggEvt) { +// for (DAOEvent evt : aggEvt.getEvents()) { +// if (evt instanceof DeleteAnalysisResultEvent && evt.getType() == DAOEvent.Type.TREE) { +// super.update(); +// return; +// } +// } +// +// super.handleDAOAggregateEvent(aggEvt); +// } +// +// } +// +// /** +// * A node for an individual search term. +// */ +// static class KeywordSearchTermNode extends TreeNode { +// +// private static final Logger logger = Logger.getLogger(KeywordSearchTermNode.class.getName()); +// +// /** +// * Main constructor. +// * +// * @param itemData The data for the search term. +// */ +// KeywordSearchTermNode(TreeResultsDTO.TreeItemDTO itemData) { +// super(itemData.getSearchParams().getRegex(), +// getIconPath(BlackboardArtifact.Type.TSK_KEYWORD_HIT), +// itemData, +// (itemData.getSearchParams().hasChildren() || itemData.getSearchParams().getSearchType() == TskData.KeywordSearchQueryType.REGEX +// // for regex queries always create a subtree, even if there is only one child +// ? Children.create(new KeywordFoundMatchFactory(itemData.getSearchParams()), true) +// : Children.LEAF), +// getDefaultLookup(itemData)); +// } +// +// @Override +// public void respondSelection(DataResultTopComponent dataResultPanel) { +// KeywordSearchTermParams searchTermParams = this.getItemData().getSearchParams(); +// +// if (!searchTermParams.hasChildren()) { +// KeywordHitSearchParam searchParams = new KeywordHitSearchParam(searchTermParams.getDataSourceId(), +// searchTermParams.getConfiguration(), +// // if literal, keyword is regex +// TskData.KeywordSearchQueryType.LITERAL.equals(searchTermParams.getSearchType()) ? searchTermParams.getRegex() : null, +// // if literal, no regex +// TskData.KeywordSearchQueryType.LITERAL.equals(searchTermParams.getSearchType()) ? null : searchTermParams.getRegex(), +// searchTermParams.getSearchType(), +// searchTermParams.getConfiguration()); +// dataResultPanel.displayKeywordHits(searchParams); +// } else { +// super.respondSelection(dataResultPanel); +// } +// } +// +// @Override +// public Optional getNodeSpecificActions() { +// ActionsFactory.ActionGroup group = new ActionsFactory.ActionGroup(); +// +// Optional type = getAnalysisResultType(); +// Optional dsId = getDataSourceIdForActions(); +// if (type.isPresent()) { +// group.add(new DeleteAnalysisResultSetAction( +// type.get(), +// () -> this.getAnalysisResultConfigurations(), +// dsId.isPresent() ? dsId.get() : null)); +// } +// +// return Optional.of(group); +// } +// +// public Optional getDataSourceIdForActions() { +// return Optional.ofNullable(this.getItemData().getSearchParams().getDataSourceId()); +// } +// +// @Override +// public Optional getAnalysisResultType() { +// return Optional.ofNullable(this.getItemData().getSearchParams().getArtifactType()); +// } +// +// @Override +// public boolean hasAnalysisResultConfigurations() { +// return true; +// } +// +// @Override +// public List getAnalysisResultConfigurations() { +// return Collections.singletonList(this.getItemData().getSearchParams().getConfiguration()); +// } +// } +// +// /** +// * A factory for found keyword matches based on the search term (for +// * regex/substring). +// */ +// public static class KeywordFoundMatchFactory extends AbstractAnalysisResultTreeFactory { +// +// private final KeywordSearchTermParams searchTermParams; +// +// /** +// * Main constructor. +// * +// * @param params The search term parameters. +// */ +// public KeywordFoundMatchFactory(KeywordSearchTermParams params) { +// this.searchTermParams = params; +// } +// +// @Override +// protected TreeNode createNewNode(TreeResultsDTO.TreeItemDTO rowData) { +// return new KeywordFoundMatchNode(rowData); +// } +// +// @Override +// protected TreeResultsDTO getChildResults() throws IllegalArgumentException, ExecutionException { +// return MainDAO.getInstance().getAnalysisResultDAO().getKeywordMatchCounts( +// this.searchTermParams.getSetName(), +// this.searchTermParams.getRegex(), +// this.searchTermParams.getSearchType(), +// this.searchTermParams.getDataSourceId()); +// } +// +// @Override +// protected TreeResultsDTO.TreeItemDTO getOrCreateRelevantChild(TreeEvent treeEvt) { +// TreeResultsDTO.TreeItemDTO originalTreeItem = super.getTypedTreeItem(treeEvt, KeywordHitSearchParam.class); +// +// if (originalTreeItem != null +// && Objects.equals(originalTreeItem.getSearchParams().getRegex(), this.searchTermParams.getRegex()) +// && Objects.equals(originalTreeItem.getSearchParams().getSearchType(), this.searchTermParams.getSearchType()) +// && Objects.equals(originalTreeItem.getSearchParams().getConfiguration(), this.searchTermParams.getConfiguration()) +// && (this.searchTermParams.getDataSourceId() == null +// || Objects.equals(this.searchTermParams.getDataSourceId(), originalTreeItem.getSearchParams().getDataSourceId()))) { +// +// // generate new type so that if it is a subtree event (i.e. keyword hits), the right tree item is created. +// KeywordHitSearchParam searchParam = originalTreeItem.getSearchParams(); +// return new TreeResultsDTO.TreeItemDTO<>( +// KeywordHitSearchParam.getTypeId(), +// new KeywordHitSearchParam( +// this.searchTermParams.getDataSourceId(), +// this.searchTermParams.getSetName(), +// searchParam.getKeyword(), +// this.searchTermParams.getRegex(), +// this.searchTermParams.getSearchType(), +// this.searchTermParams.getConfiguration() +// ), +// searchParam.getKeyword() == null ? "" : searchParam.getKeyword(), +// searchParam.getKeyword() == null ? "" : searchParam.getKeyword(), +// originalTreeItem.getDisplayCount() +// ); +// } +// return null; +// } +// +// @Override +// public int compare(TreeItemDTO o1, TreeItemDTO o2) { +// return STRING_COMPARATOR.compare(o1.getSearchParams().getKeyword(), o2.getSearchParams().getKeyword()); +// } +// +// @Override +// protected void handleDAOAggregateEvent(DAOAggregateEvent aggEvt) { +// for (DAOEvent evt : aggEvt.getEvents()) { +// if (evt instanceof DeleteAnalysisResultEvent && evt.getType() == DAOEvent.Type.TREE) { +// super.update(); +// return; +// } +// } +// +// super.handleDAOAggregateEvent(aggEvt); +// } +// } +// +// /** +// * A node signifying a match for a specific keyword given a regex/substring +// * search term. +// */ +// static class KeywordFoundMatchNode extends TreeNode { +// +// /** +// * Main constructor. +// * +// * @param itemData The data for the match parameters. +// */ +// public KeywordFoundMatchNode(TreeResultsDTO.TreeItemDTO itemData) { +// super(itemData.getSearchParams().getKeyword(), +// getIconPath(BlackboardArtifact.Type.TSK_KEYWORD_HIT), +// itemData, +// Children.LEAF, +// getDefaultLookup(itemData)); +// } +// +// @Override +// public void respondSelection(DataResultTopComponent dataResultPanel) { +// dataResultPanel.displayKeywordHits(this.getItemData().getSearchParams()); +// } +// +// @Override +// public Optional getDataSourceIdForActions() { +// return Optional.ofNullable(this.getItemData().getSearchParams().getDataSourceId()); +// } +// +// @Override +// public Optional getAnalysisResultType() { +// return Optional.ofNullable(this.getItemData().getSearchParams().getArtifactType()); +// } +// +// @Override +// public boolean hasAnalysisResultConfigurations() { +// return true; +// } +// +// @Override +// public List getAnalysisResultConfigurations() { +// return Collections.singletonList(this.getItemData().getSearchParams().getConfiguration()); +// } +// } + +} From c345ac9d3437135612618be6aa20b829ec743c23 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 14 Feb 2022 19:47:24 -0500 Subject: [PATCH 2/8] added file --- .../mainui/datamodel/TagNameSearchParams.java | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagNameSearchParams.java diff --git a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagNameSearchParams.java b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagNameSearchParams.java new file mode 100644 index 0000000000..424cc61a81 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagNameSearchParams.java @@ -0,0 +1,86 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2022 Basis Technology Corp. + * Contact: carrier sleuthkit 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.mainui.datamodel; + +import java.util.Objects; +import org.sleuthkit.datamodel.TagName; + +/** + * + * Search param for a tag name. + */ +public class TagNameSearchParams { + + private static final String TYPE_ID = "TAG_TYPE"; + + /** + * @return The type id for this search parameter. + */ + public static String getTypeId() { + return TYPE_ID; + } + + private final TagName tagName; + private final Long dataSourceId; + + public TagNameSearchParams(TagName tagName, Long dataSourceId) { + this.dataSourceId = dataSourceId; + this.tagName = tagName; + } + + public TagName getTagName() { + return tagName; + } + + public Long getDataSourceId() { + return dataSourceId; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 67 * hash + Objects.hashCode(this.tagName); + hash = 67 * hash + Objects.hashCode(this.dataSourceId); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final TagNameSearchParams other = (TagNameSearchParams) obj; + if (!Objects.equals(this.tagName, other.tagName)) { + return false; + } + if (!Objects.equals(this.dataSourceId, other.dataSourceId)) { + return false; + } + return true; + } + + + +} From 13946d7017684841405f76cbbe4e164674e23811 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 16 Feb 2022 08:52:57 -0500 Subject: [PATCH 3/8] fix extract action warning --- .../directorytree/actionhelpers/ExtractActionHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/actionhelpers/ExtractActionHelper.java b/Core/src/org/sleuthkit/autopsy/directorytree/actionhelpers/ExtractActionHelper.java index 386240ea86..bd7cc96a51 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/actionhelpers/ExtractActionHelper.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/actionhelpers/ExtractActionHelper.java @@ -327,7 +327,7 @@ public class ExtractActionHelper { @Override protected ExtractFscContentVisitor getChildVisitor(File childFile, ProgressHandle progress, SwingWorker worker) { - return new UIExtractionVisitor(childFile, progress, worker, false); + return new UIExtractionVisitor<>(childFile, progress, worker, false); } From 99eb6a9499e4ef1a7748490cc5082b2b66b1a946 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 16 Feb 2022 14:34:43 -0500 Subject: [PATCH 4/8] work towards tagging --- .../org/sleuthkit/autopsy/datamodel/Tags.java | 507 +------------ .../DirectoryTreeFilterChildren.java | 4 + .../autopsy/mainui/datamodel/TagsDAO.java | 191 ++++- .../mainui/datamodel/TagsSearchParams.java | 19 +- .../autopsy/mainui/nodes/TagNameFactory.java | 681 ++---------------- 5 files changed, 247 insertions(+), 1155 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index 34c8be3ec3..b26e8a6adb 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -18,39 +18,12 @@ */ package org.sleuthkit.autopsy.datamodel; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.Collections; -import java.util.Comparator; -import java.util.EnumSet; -import java.util.List; -import java.util.Observable; -import java.util.Observer; -import java.util.Set; -import java.util.logging.Level; -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.WeakListeners; import org.openide.util.lookup.Lookups; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.casemodule.services.TagsManager; -import org.sleuthkit.autopsy.core.UserPreferences; -import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.ingest.IngestManager; -import org.sleuthkit.autopsy.mainui.datamodel.TagsSearchParams; -import static org.sleuthkit.autopsy.mainui.datamodel.TagsSearchParams.TagType.FILE; -import static org.sleuthkit.autopsy.mainui.datamodel.TagsSearchParams.TagType.RESULT; -import org.sleuthkit.autopsy.corecomponents.SelectionResponder; -import org.sleuthkit.autopsy.tags.TagUtils; -import org.sleuthkit.datamodel.BlackboardArtifactTag; -import org.sleuthkit.datamodel.ContentTag; -import org.sleuthkit.datamodel.TagName; -import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.autopsy.mainui.nodes.TagNameFactory; /** * Instances of this class act as keys for use by instances of the @@ -58,67 +31,23 @@ import org.sleuthkit.datamodel.TskCoreException; * factory built on top of the NetBeans Children.Keys class. */ public class Tags { - // Creation of a RootNode object corresponding to a Tags object is done - // by a CreateAutopsyNodeVisitor dispatched from the AbstractContentChildren - // override of Children.Keys.createNodes(). - - private final static String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text"); - private static final Set INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED); - private static final String USER_NAME_PROPERTY = "user.name"; //NON-NLS - private final TagResults tagResults = new TagResults(); - private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS - - private final long filteringDSObjId; // 0 if not filtering/grouping by data source - - Tags() { - this(0); - } - - Tags(long dsObjId) { - this.filteringDSObjId = dsObjId; - } - - /** - * Return the display name used by the tags node in the tree. - * - * @return - DISPLAY_NAME - */ - public static String getTagsDisplayName() { - return DISPLAY_NAME; - } - - long filteringDataSourceObjId() { - return this.filteringDSObjId; - } - - - - /** - * This class largely does nothing except act as a top-level object that the - * other nodes can listen to. This mimics what other nodes have (keword - * search, etc.), but theirs stores data. - */ - private class TagResults extends Observable { - - public void update() { - setChanged(); - notifyObservers(); - } - } - /** * Instances of this class are the root nodes of tree that is a sub-tree of * the Autopsy presentation of the SleuthKit data model. The sub-tree * consists of content and blackboard artifact tags, grouped first by tag * type, then by tag name. */ - public class RootNode extends DisplayableItemNode { + public static class RootNode extends DisplayableItemNode { + private final static String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text"); + private final static String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS + private final Long dataSourceObjId; - public RootNode(long objId) { - super(Children.create(new TagNameNodeFactory(objId), true), Lookups.singleton(DISPLAY_NAME)); + public RootNode(Long dsId) { + super(Children.create(new TagNameFactory(dsId > 0 ? dsId : null), true), Lookups.singleton(DISPLAY_NAME)); super.setName(DISPLAY_NAME); super.setDisplayName(DISPLAY_NAME); this.setIconBaseWithExtension(ICON_PATH); + this.dataSourceObjId = dsId > 0 ? dsId : null; } @Override @@ -148,423 +77,9 @@ public class Tags { public String getItemType() { return getClass().getName(); } - - /** - * Cause the contents of the RootNode and its children to be updated. - */ - public void refresh() { - tagResults.update(); - } - - } - - private class TagNameNodeFactory extends ChildFactory.Detachable implements Observer { - - private final long filteringDSObjId; // 0 if not filtering/grouping by data source - - private final Set CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED, - Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED, - Case.Events.CONTENT_TAG_ADDED, - Case.Events.CONTENT_TAG_DELETED, - Case.Events.CURRENT_CASE); - - private final PropertyChangeListener pcl = new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - String eventType = evt.getPropertyName(); - if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString()) - || eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) { - /** - * Checking for a current case is a stop gap measure until a - * different way of handling the closing of cases is worked - * out. Currently, remote events may be received for a case - * that is already closed. - */ - try { - Case.getCurrentCaseThrows(); - refresh(true); - tagResults.update(); - } catch (NoCurrentCaseException notUsed) { - /** - * Case is closed, do nothing. - */ - } - } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) - || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) { - /** - * Checking for a current case is a stop gap measure until a - * different way of handling the closing of cases is worked - * out. Currently, remote events may be received for a case - * that is already closed. - */ - try { - Case.getCurrentCaseThrows(); - refresh(true); - tagResults.update(); - } catch (NoCurrentCaseException notUsed) { - /** - * Case is closed, do nothing. - */ - } - } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) { - // case was closed. Remove listeners so that this can be garbage collected - if (evt.getNewValue() == null) { - removeNotify(); - } - } - } - }; - - private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null); - - /** - * Constructor - * - * @param objId data source object id - */ - TagNameNodeFactory(long objId) { - this.filteringDSObjId = objId; - } - - @Override - protected void addNotify() { - IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl); - Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl); - tagResults.update(); - tagResults.addObserver(this); - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - IngestManager.getInstance().removeIngestJobEventListener(weakPcl); - Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakPcl); - tagResults.deleteObserver(this); - } - - @Override - protected boolean createKeys(List keys) { - try { - List tagNamesInUse; - if (UserPreferences.showOnlyCurrentUserTags()) { - String userName = System.getProperty(USER_NAME_PROPERTY); - tagNamesInUse = (filteringDSObjId > 0) - ? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUseForUser(filteringDSObjId, userName) - : Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUseForUser(userName); - } else { - tagNamesInUse = (filteringDSObjId > 0) - ? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(filteringDSObjId) - : Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(); - } - Collections.sort(tagNamesInUse, new Comparator() { - @Override - public int compare(TagName o1, TagName o2) { - return TagUtils.getDecoratedTagDisplayName(o1).compareTo(TagUtils.getDecoratedTagDisplayName(o2)); - } - }); - keys.addAll(tagNamesInUse); - } catch (TskCoreException | NoCurrentCaseException ex) { - Logger.getLogger(TagNameNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS - } - return true; - } - - @Override - protected Node createNodeForKey(TagName key) { - return new TagNameNode(key); - } - - @Override - public void update(Observable o, Object arg) { - refresh(true); - } - } - - /** - * Instances of this class are elements of Node hierarchies consisting of - * content and blackboard artifact tags, grouped first by tag type, then by - * tag name. - */ - public class TagNameNode extends DisplayableItemNode implements Observer { - - private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS - private final String BOOKMARK_TAG_ICON_PATH = "org/sleuthkit/autopsy/images/star-bookmark-icon-16.png"; //NON-NLS - private final TagName tagName; - - public TagNameNode(TagName tagName) { - super(Children.create(new TagTypeNodeFactory(tagName), true), Lookups.singleton(NbBundle.getMessage(TagNameNode.class, "TagNameNode.namePlusTags.text", tagName.getDisplayName()))); - this.tagName = tagName; - setName(TagUtils.getDecoratedTagDisplayName(tagName)); - updateDisplayName(); - if (tagName.getDisplayName().equals(TagsManager.getBookmarkTagDisplayName())) { - setIconBaseWithExtension(BOOKMARK_TAG_ICON_PATH); - } else { - setIconBaseWithExtension(ICON_PATH); - } - tagResults.addObserver(this); - } - - private void updateDisplayName() { - long tagsCount = 0; - try { - TagsManager tm = Case.getCurrentCaseThrows().getServices().getTagsManager(); - if (UserPreferences.showOnlyCurrentUserTags()) { - String userName = System.getProperty(USER_NAME_PROPERTY); - if (filteringDSObjId > 0) { - tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, filteringDSObjId, userName); - tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, filteringDSObjId, userName); - } else { - tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, userName); - tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, userName); - } - } else { - if (filteringDSObjId > 0) { - tagsCount = tm.getContentTagsCountByTagName(tagName, filteringDSObjId); - tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName, filteringDSObjId); - } else { - tagsCount = tm.getContentTagsCountByTagName(tagName); - tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName); - } - } - } catch (TskCoreException | NoCurrentCaseException ex) { - Logger.getLogger(TagNameNode.class.getName()).log(Level.SEVERE, "Failed to get tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS - } - setDisplayName(TagUtils.getDecoratedTagDisplayName(tagName) + " \u200E(\u200E" + tagsCount + ")\u200E"); - } - - @Override - protected Sheet createSheet() { - Sheet propertySheet = super.createSheet(); - Sheet.Set properties = propertySheet.get(Sheet.PROPERTIES); - if (properties == null) { - properties = Sheet.createPropertiesSet(); - propertySheet.put(properties); - } - properties.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "TagNameNode.createSheet.name.name"), - NbBundle.getMessage(this.getClass(), "TagNameNode.createSheet.name.displayName"), tagName.getDescription(), getName())); - return propertySheet; - } - - @Override - public T accept(DisplayableItemNodeVisitor visitor) { - // See classes derived from DisplayableItemNodeVisitor - // for behavior added using the Visitor pattern. - return visitor.visit(this); - } - - @Override - public boolean isLeafTypeNode() { - return false; - } - - @Override - public void update(Observable o, Object arg) { - updateDisplayName(); - } - - @Override - public String getItemType() { - return getClass().getName(); - } - } - - /** - * Creates nodes for the two types of tags: file and artifact. Does not need - * observer / messages since it always has the same children - */ - private class TagTypeNodeFactory extends ChildFactory { - - private final TagName tagName; - private final String CONTENT_TAG_TYPE_NODE_KEY = NbBundle.getMessage(TagNameNode.class, "TagNameNode.contentTagTypeNodeKey.text"); - private final String BLACKBOARD_ARTIFACT_TAG_TYPE_NODE_KEY = NbBundle.getMessage(TagNameNode.class, "TagNameNode.bbArtTagTypeNodeKey.text"); - - TagTypeNodeFactory(TagName tagName) { - super(); - this.tagName = tagName; - } - - @Override - protected boolean createKeys(List keys) { - keys.add(CONTENT_TAG_TYPE_NODE_KEY); - keys.add(BLACKBOARD_ARTIFACT_TAG_TYPE_NODE_KEY); - return true; - } - - @Override - protected Node createNodeForKey(String key) { - if (CONTENT_TAG_TYPE_NODE_KEY.equals(key)) { - return new ContentTagTypeNode(tagName); - } else if (BLACKBOARD_ARTIFACT_TAG_TYPE_NODE_KEY.equals(key)) { - return new BlackboardArtifactTagTypeNode(tagName); - } else { - Logger.getLogger(TagNameNode.class.getName()).log(Level.SEVERE, "{0} not a recognized key", key); //NON-NLS - return null; - } - } - } - - private final String CONTENT_DISPLAY_NAME = NbBundle.getMessage(ContentTagTypeNode.class, "ContentTagTypeNode.displayName.text"); - - /** - * Node for the content tags. Children are specific tags. Instances of this - * class are are elements of a directory tree sub-tree consisting of content - * and blackboard artifact tags, grouped first by tag type, then by tag - * name. - */ - public class ContentTagTypeNode extends DisplayableItemNode implements Observer, SelectionResponder { - - private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS - private final TagName tagName; - - public ContentTagTypeNode(TagName tagName) { - super(Children.LEAF, Lookups.singleton(tagName.getDisplayName() + " " + CONTENT_DISPLAY_NAME)); - this.tagName = tagName; - super.setName(CONTENT_DISPLAY_NAME); - updateDisplayName(); - this.setIconBaseWithExtension(ICON_PATH); - tagResults.addObserver(this); - } - - @Override - public void respondSelection(DataResultTopComponent dataResultPanel) { - dataResultPanel.displayTags(new TagsSearchParams(tagName, FILE, - filteringDataSourceObjId() > 0 ? filteringDataSourceObjId() : null)); - } - - private void updateDisplayName() { - long tagsCount = 0; - try { - - if (UserPreferences.showOnlyCurrentUserTags()) { - String userName = System.getProperty(USER_NAME_PROPERTY); - tagsCount = (filteringDSObjId > 0) - ? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, filteringDSObjId, userName) - : Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, userName); - } else { - tagsCount = (filteringDSObjId > 0) - ? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName, filteringDSObjId) - : Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName); - } - } catch (TskCoreException | NoCurrentCaseException ex) { - Logger.getLogger(ContentTagTypeNode.class.getName()).log(Level.SEVERE, "Failed to get content tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS - } - super.setDisplayName(CONTENT_DISPLAY_NAME + " (" + tagsCount + ")"); - } - - @Override - protected Sheet createSheet() { - Sheet propertySheet = super.createSheet(); - Sheet.Set properties = propertySheet.get(Sheet.PROPERTIES); - if (properties == null) { - properties = Sheet.createPropertiesSet(); - propertySheet.put(properties); - } - properties.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagTypeNode.createSheet.name.name"), - NbBundle.getMessage(this.getClass(), "ContentTagTypeNode.createSheet.name.displayName"), "", getName())); - return propertySheet; - } - - @Override - public T accept(DisplayableItemNodeVisitor visitor) { - return visitor.visit(this); - } - - @Override - public boolean isLeafTypeNode() { - return true; - } - - @Override - public void update(Observable o, Object arg) { - updateDisplayName(); - } - - @Override - public String getItemType() { - return getClass().getName(); - } - } - - private final String ARTIFACT_DISPLAY_NAME = NbBundle.getMessage(BlackboardArtifactTagTypeNode.class, "BlackboardArtifactTagTypeNode.displayName.text"); - - /** - * Instances of this class are elements in a sub-tree of the Autopsy - * presentation of the SleuthKit data model. The sub-tree consists of - * content and blackboard artifact tags, grouped first by tag type, then by - * tag name. - */ - public class BlackboardArtifactTagTypeNode extends DisplayableItemNode implements Observer, SelectionResponder { - - private final TagName tagName; - private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS - - public BlackboardArtifactTagTypeNode(TagName tagName) { - super(Children.LEAF, Lookups.singleton(tagName.getDisplayName() + " " + ARTIFACT_DISPLAY_NAME)); - this.tagName = tagName; - super.setName(ARTIFACT_DISPLAY_NAME); - this.setIconBaseWithExtension(ICON_PATH); - updateDisplayName(); - tagResults.addObserver(this); - } - - @Override - public void respondSelection(DataResultTopComponent dataResultPanel) { - dataResultPanel.displayTags(new TagsSearchParams(tagName, RESULT, - filteringDataSourceObjId() > 0 ? filteringDataSourceObjId() : null)); - } - - private void updateDisplayName() { - long tagsCount = 0; - try { - if (UserPreferences.showOnlyCurrentUserTags()) { - String userName = System.getProperty(USER_NAME_PROPERTY); - tagsCount = (filteringDSObjId > 0) - ? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, filteringDSObjId, userName) - : Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, userName); - } else { - tagsCount = (filteringDSObjId > 0) - ? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName, filteringDSObjId) - : Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName); - } - } catch (TskCoreException | NoCurrentCaseException ex) { - Logger.getLogger(BlackboardArtifactTagTypeNode.class.getName()).log(Level.SEVERE, "Failed to get blackboard artifact tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS - } - super.setDisplayName(ARTIFACT_DISPLAY_NAME + " (" + tagsCount + ")"); - } - - @Override - protected Sheet createSheet() { - Sheet propertySheet = super.createSheet(); - Sheet.Set properties = propertySheet.get(Sheet.PROPERTIES); - if (properties == null) { - properties = Sheet.createPropertiesSet(); - propertySheet.put(properties); - } - properties.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "BlackboardArtifactTagTypeNode.createSheet.name.name"), - NbBundle.getMessage(this.getClass(), "BlackboardArtifactTagTypeNode.createSheet.name.displayName"), "", getName())); - return propertySheet; - } - - @Override - public T accept(DisplayableItemNodeVisitor visitor) { - return visitor.visit(this); - } - - @Override - public boolean isLeafTypeNode() { - return true; - } - - @Override - public void update(Observable o, Object arg) { - updateDisplayName(); - } - - @Override - public String getItemType() { - return getClass().getName(); + + public Node clone() { + return new RootNode(dataSourceObjId); } } } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java index 8ceecea3cc..7f35282209 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterChildren.java @@ -37,6 +37,7 @@ import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.LocalDirectoryNode; import org.sleuthkit.autopsy.datamodel.SlackFileNode; +import org.sleuthkit.autopsy.datamodel.Tags; import org.sleuthkit.autopsy.datamodel.ViewsNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import org.sleuthkit.autopsy.datamodel.VolumeNode; @@ -92,6 +93,9 @@ class DirectoryTreeFilterChildren extends FilterNode.Children { } else if (origNode instanceof AnalysisResults.RootNode) { Node cloned = ((AnalysisResults.RootNode) origNode).clone(); return new Node[]{cloned}; + } else if (origNode instanceof Tags.RootNode) { + Node cloned = ((Tags.RootNode) origNode).clone(); + return new Node[]{cloned}; } else if (origNode instanceof ViewsNode) { Node cloned = ((ViewsNode) origNode).clone(); return new Node[]{cloned}; diff --git a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java index bec9134ab6..15ff8c2506 100755 --- a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java +++ b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java @@ -22,15 +22,20 @@ import org.sleuthkit.autopsy.mainui.datamodel.events.DAOEvent; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import java.beans.PropertyChangeEvent; +import java.sql.SQLException; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.ExecutionException; +import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; @@ -42,21 +47,29 @@ import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; +import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.core.UserPreferences; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.TimeZoneUtils; +import org.sleuthkit.autopsy.datamodel.Tags; import static org.sleuthkit.autopsy.mainui.datamodel.AbstractDAO.CACHE_DURATION; import static org.sleuthkit.autopsy.mainui.datamodel.AbstractDAO.CACHE_DURATION_UNITS; import static org.sleuthkit.autopsy.mainui.datamodel.AbstractDAO.CACHE_SIZE; import org.sleuthkit.autopsy.mainui.datamodel.TagsSearchParams.TagType; +import org.sleuthkit.autopsy.mainui.datamodel.TreeResultsDTO.TreeDisplayCount; import org.sleuthkit.autopsy.mainui.datamodel.TreeResultsDTO.TreeItemDTO; import org.sleuthkit.autopsy.mainui.datamodel.events.TagsEvent; import org.sleuthkit.autopsy.mainui.datamodel.events.TreeCounts; import org.sleuthkit.autopsy.mainui.datamodel.events.TreeEvent; import org.sleuthkit.autopsy.mainui.nodes.DAOFetcher; +import org.sleuthkit.autopsy.tags.TagUtils; import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.BlackboardArtifactTag; +import org.sleuthkit.datamodel.CaseDbAccessManager; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; +import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.Tag; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; @@ -85,6 +98,8 @@ import org.sleuthkit.datamodel.TskCoreException; "TagsDAO.tagColumns.userNameColLbl=User Name"}) public class TagsDAO extends AbstractDAO { + private static final Logger logger = Logger.getLogger(TagsDAO.class.getName()); + private static final String USER_NAME_PROPERTY = "user.name"; //NON-NLS private static final List FILE_TAG_COLUMNS = Arrays.asList( @@ -122,14 +137,12 @@ public class TagsDAO extends AbstractDAO { return new ColumnKey(name, name, Bundle.TagsDAO_fileColumns_noDescription()); } - private final Cache, SearchResultsDTO> searchParamsCache = - CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).expireAfterAccess(CACHE_DURATION, CACHE_DURATION_UNITS).build(); + private final Cache, SearchResultsDTO> searchParamsCache + = CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).expireAfterAccess(CACHE_DURATION, CACHE_DURATION_UNITS).build(); private final TreeCounts treeCounts = new TreeCounts<>(); public SearchResultsDTO getTags(TagsSearchParams key, long startItem, Long maxCount) throws ExecutionException, IllegalArgumentException { - if (key.getTagName() == null) { - throw new IllegalArgumentException("Must have non-null tag name"); - } else if (key.getDataSourceId() != null && key.getDataSourceId() <= 0) { + if (key.getDataSourceId() != null && key.getDataSourceId() <= 0) { throw new IllegalArgumentException("Data source id must be greater than 0 or null"); } else if (key.getTagType() == null) { throw new IllegalArgumentException("Must have non-null tag type"); @@ -175,13 +188,14 @@ public class TagsDAO extends AbstractDAO { private SearchResultsDTO fetchResultTags(SearchParams cacheKey) throws NoCurrentCaseException, TskCoreException { Long dataSourceId = cacheKey.getParamData().getDataSourceId(); - TagName tagName = cacheKey.getParamData().getTagName(); + TagName tagNameId = cacheKey.getParamData().getTagName(); + TagsManager tm = Case.getCurrentCase().getServices().getTagsManager(); // get all tag results List allTags = new ArrayList<>(); List artifactTags = (dataSourceId != null && dataSourceId > 0) - ? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName, dataSourceId) - : Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName); + ? tm.getBlackboardArtifactTagsByTagName(tagNameId, dataSourceId) + : tm.getBlackboardArtifactTagsByTagName(tagNameId); if (UserPreferences.showOnlyCurrentUserTags()) { String userName = System.getProperty(USER_NAME_PROPERTY); for (BlackboardArtifactTag tag : artifactTags) { @@ -233,13 +247,15 @@ public class TagsDAO extends AbstractDAO { private SearchResultsDTO fetchFileTags(SearchParams cacheKey) throws NoCurrentCaseException, TskCoreException { Long dataSourceId = cacheKey.getParamData().getDataSourceId(); - TagName tagName = cacheKey.getParamData().getTagName(); + TagName tagNameId = cacheKey.getParamData().getTagName(); + + TagsManager tm = Case.getCurrentCase().getServices().getTagsManager(); // get all tag results List allTags = new ArrayList<>(); List contentTags = (dataSourceId != null && dataSourceId > 0) - ? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName, dataSourceId) - : Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByTagName(tagName); + ? tm.getContentTagsByTagName(tagNameId, dataSourceId) + : tm.getContentTagsByTagName(tagNameId); if (UserPreferences.showOnlyCurrentUserTags()) { String userName = System.getProperty(USER_NAME_PROPERTY); for (ContentTag tag : contentTags) { @@ -307,10 +323,10 @@ public class TagsDAO extends AbstractDAO { private TreeItemDTO getTreeItem(TagsEvent evt, TreeResultsDTO.TreeDisplayCount count) { return new TreeItemDTO<>( - TagsSearchParams.getTypeId(), - new TagsSearchParams(evt.getTagName(), evt.getTagType(), evt.getDataSourceId()), - evt.getTagName().getId(), - evt.getTagName().getDisplayName(), + TagsSearchParams.getTypeId(), + new TagsSearchParams(evt.getTagName(), evt.getTagType(), evt.getDataSourceId()), + evt.getTagName().getId(), + evt.getTagName().getDisplayName(), count); } @@ -398,12 +414,149 @@ public class TagsDAO extends AbstractDAO { return null; } - public TreeResultsDTO getNameCounts(Long dataSourceId) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + private SleuthkitCase getCase() throws NoCurrentCaseException, TskCoreException { + return Case.getCurrentCaseThrows().getSleuthkitCase(); } - public TreeResultsDTO getTypeCounts(TagNameSearchParams searchParams) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + public TreeResultsDTO getNameCounts(Long dataSourceId) throws ExecutionException { + Set indeterminateTagNameIds = this.treeCounts.getEnqueued().stream() + .filter(evt -> dataSourceId == null || evt.getDataSourceId() == dataSourceId) + .map(evt -> evt.getTagName()) + .collect(Collectors.toSet()); + + Map tagNameCount = new HashMap<>(); + try { + TagsManager tm = Case.getCurrentCaseThrows().getServices().getTagsManager(); + + List tagNamesInUse; + if (UserPreferences.showOnlyCurrentUserTags()) { + String userName = System.getProperty(USER_NAME_PROPERTY); + tagNamesInUse = (dataSourceId != null) + ? tm.getTagNamesInUseForUser(dataSourceId, userName) + : tm.getTagNamesInUseForUser(userName); + } else { + tagNamesInUse = (dataSourceId != null) + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(dataSourceId) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse(); + } + + for (TagName tagName : tagNamesInUse) { + if (indeterminateTagNameIds.contains(tagName)) { + tagNameCount.put(tagName, TreeDisplayCount.INDETERMINATE); + continue; + } + + long tagsCount; + if (UserPreferences.showOnlyCurrentUserTags()) { + String userName = System.getProperty(USER_NAME_PROPERTY); + if (dataSourceId != null) { + tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, dataSourceId, userName); + tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, dataSourceId, userName); + } else { + tagsCount = tm.getContentTagsCountByTagNameForUser(tagName, userName); + tagsCount += tm.getBlackboardArtifactTagsCountByTagNameForUser(tagName, userName); + } + } else { + if (dataSourceId != null) { + tagsCount = tm.getContentTagsCountByTagName(tagName, dataSourceId); + tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName, dataSourceId); + } else { + tagsCount = tm.getContentTagsCountByTagName(tagName); + tagsCount += tm.getBlackboardArtifactTagsCountByTagName(tagName); + } + } + + tagNameCount.put(tagName, TreeDisplayCount.getDeterminate(tagsCount)); + } + + } catch (NoCurrentCaseException | TskCoreException ex) { + throw new ExecutionException("An error occurred while fetching data artifact counts.", ex); + } + + List> tagNameParams = tagNameCount.entrySet().stream() + .map(e -> createTagNameTreeItem(e.getKey(), dataSourceId, e.getValue())) + .collect(Collectors.toList()); + + // return results + return new TreeResultsDTO<>(tagNameParams); + } + + public TreeItemDTO createTagNameTreeItem(TagName tagName, Long dataSourceId, TreeResultsDTO.TreeDisplayCount treeDisplayCount) { + return new TreeItemDTO<>( + TagNameSearchParams.getTypeId(), + new TagNameSearchParams(tagName, dataSourceId), + tagName.getId(), + tagName.getDisplayName(), + treeDisplayCount + ); + } + + private long getContentTagCount(Long dataSourceId, TagName tagName) throws NoCurrentCaseException, TskCoreException { + + if (UserPreferences.showOnlyCurrentUserTags()) { + String userName = System.getProperty(USER_NAME_PROPERTY); + return (dataSourceId != null) + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, dataSourceId, userName) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagNameForUser(tagName, userName); + } else { + return (dataSourceId != null) + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName, dataSourceId) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsCountByTagName(tagName); + } + } + + private long getArtifactTagCount(Long dataSourceId, TagName tagName) throws NoCurrentCaseException, TskCoreException { + if (UserPreferences.showOnlyCurrentUserTags()) { + String userName = System.getProperty(USER_NAME_PROPERTY); + return (dataSourceId != null) + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, dataSourceId, userName) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagNameForUser(tagName, userName); + } else { + return (dataSourceId != null) + ? Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName, dataSourceId) + : Case.getCurrentCaseThrows().getServices().getTagsManager().getBlackboardArtifactTagsCountByTagName(tagName); + } + } + + public TreeResultsDTO getTypeCounts(TagNameSearchParams searchParams) throws ExecutionException { + Long dataSourceId = searchParams.getDataSourceId(); + TagName tagName = searchParams.getTagName(); + + Set indeterminateTagTypes = this.treeCounts.getEnqueued().stream() + .filter(evt -> (dataSourceId == null || Objects.equals(evt.getDataSourceId(), dataSourceId)) && Objects.equals(tagName, evt.getTagName())) + .map(evt -> evt.getTagType()) + .collect(Collectors.toSet()); + + try { + return new TreeResultsDTO<>(Arrays.asList( + createTagTypeTreeItem( + tagName, + TagType.FILE, + dataSourceId, + indeterminateTagTypes.contains(TagType.FILE) + ? TreeDisplayCount.INDETERMINATE + : TreeDisplayCount.getDeterminate(getContentTagCount(dataSourceId, tagName))), + createTagTypeTreeItem( + tagName, + TagType.RESULT, + dataSourceId, + indeterminateTagTypes.contains(TagType.RESULT) + ? TreeDisplayCount.INDETERMINATE + : TreeDisplayCount.getDeterminate(getArtifactTagCount(dataSourceId, tagName))) + )); + } catch (NoCurrentCaseException | TskCoreException ex) { + throw new ExecutionException("An error occurred while fetching tag type counts.", ex); + } + } + + public TreeItemDTO createTagTypeTreeItem(TagName tagName, TagType tagType, Long dataSourceId, TreeResultsDTO.TreeDisplayCount treeDisplayCount) { + return new TreeItemDTO<>( + TagsSearchParams.getTypeId(), + new TagsSearchParams(tagName, tagType, dataSourceId), + tagName.getId(), + tagType.getDisplayName(), + treeDisplayCount + ); } /** diff --git a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsSearchParams.java b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsSearchParams.java index c91a9e51e1..b0153d2810 100755 --- a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsSearchParams.java +++ b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsSearchParams.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.mainui.datamodel; import java.util.Objects; +import org.openide.util.NbBundle.Messages; import org.sleuthkit.datamodel.TagName; /** @@ -35,9 +36,22 @@ public class TagsSearchParams extends TagNameSearchParams { return TYPE_ID; } + @Messages({ + "TagType_File_displayName=File Tags", + "TagType_Result_displayName=Result Tags",}) public enum TagType { - FILE, - RESULT; + FILE(Bundle.TagType_File_displayName()), + RESULT(Bundle.TagType_Result_displayName()); + + private final String displayName; + + TagType(String displayName) { + this.displayName = displayName; + } + + public String getDisplayName() { + return displayName; + } } private final TagType type; @@ -77,5 +91,4 @@ public class TagsSearchParams extends TagNameSearchParams { return super.equals(obj); } - } diff --git a/Core/src/org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java b/Core/src/org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java index 62c1be6c6d..3f28c90bb2 100644 --- a/Core/src/org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java +++ b/Core/src/org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java @@ -22,7 +22,7 @@ import java.util.Comparator; import java.util.Objects; import java.util.concurrent.ExecutionException; import org.openide.nodes.Children; -import org.openide.util.Lookup; +import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; import org.sleuthkit.autopsy.mainui.datamodel.MainDAO; import org.sleuthkit.autopsy.mainui.datamodel.TagNameSearchParams; import org.sleuthkit.autopsy.mainui.datamodel.TagsSearchParams; @@ -38,9 +38,8 @@ import org.sleuthkit.autopsy.mainui.datamodel.events.TreeEvent; */ public class TagNameFactory extends TreeChildFactory { - // GVDTODO - private static final String TAG_ICON = TBD; - + private static final String TAG_ICON = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; + private final Long dataSourceId; /** @@ -68,16 +67,18 @@ public class TagNameFactory extends TreeChildFactory { if (originalTreeItem != null && (this.dataSourceId == null || Objects.equals(this.dataSourceId, originalTreeItem.getSearchParams().getDataSourceId()))) { - - // GVDTODO - return MainDAO.getInstance().getTagsDAO().getTagNameTreeItem(originalTreeItem); + + return MainDAO.getInstance().getTagsDAO().createTagNameTreeItem( + originalTreeItem.getSearchParams().getTagName(), + dataSourceId, + originalTreeItem.getDisplayCount()); } return null; } @Override public int compare(TreeItemDTO o1, TreeItemDTO o2) { - return Comparator.comparing(tagTreeItem -> tagTreeItem.getSearchParams().getTagName().getDisplayName()) + return Comparator.comparing((TreeItemDTO tagTreeItem) -> tagTreeItem.getDisplayName()) .compare(o1, o2); } @@ -92,29 +93,33 @@ public class TagNameFactory extends TreeChildFactory { super.handleDAOAggregateEvent(aggEvt); } - - + + /** + * A node for a tag name. + */ static class TagNameNode extends TreeNode { public TagNameNode(TreeResultsDTO.TreeItemDTO rowData) { - super(rowData.getName(), + super(TagNameSearchParams.getTypeId() + "_" + Objects.toString(rowData.getId()), TAG_ICON, - rowData, + rowData, Children.create(new TagTypeFactory(rowData.getSearchParams()), false), getDefaultLookup(rowData)); } - + } - + + /** + * Factory displaying file type or result type underneath a tag name node. + */ static class TagTypeFactory extends TreeChildFactory { private final TagNameSearchParams searchParams; - + TagTypeFactory(TagNameSearchParams searchParams) { this.searchParams = searchParams; } - - + @Override protected TreeNode createNewNode(TreeItemDTO rowData) { return new TagsTypeNode(rowData); @@ -127,636 +132,38 @@ public class TagNameFactory extends TreeChildFactory { @Override protected TreeItemDTO getOrCreateRelevantChild(TreeEvent treeEvt) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + TreeResultsDTO.TreeItemDTO originalTreeItem = super.getTypedTreeItem(treeEvt, TagsSearchParams.class); + + if (originalTreeItem != null + && Objects.equals(this.searchParams.getTagName(), originalTreeItem.getSearchParams().getTagName()) + && (this.searchParams.getDataSourceId() == null || Objects.equals(this.searchParams.getDataSourceId(), originalTreeItem.getSearchParams().getDataSourceId()))) { + + return MainDAO.getInstance().getTagsDAO().createTagTypeTreeItem( + searchParams.getTagName(), + originalTreeItem.getSearchParams().getTagType(), + searchParams.getDataSourceId(), + originalTreeItem.getDisplayCount()); + } + return null; } @Override public int compare(TreeItemDTO o1, TreeItemDTO o2) { - return Comparator.comparing(rowData -> rowData.getSearchParams().getTagType() == TagsSearchParams.TagType.FILE ? 0 : 1) + return Comparator.comparing((TreeItemDTO rowData) -> rowData.getSearchParams().getTagType() == TagsSearchParams.TagType.FILE ? 0 : 1) .compare(o1, o2); } - + } - + static class TagsTypeNode extends TreeNode { private TagsTypeNode(TreeItemDTO rowData) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + super(TagsSearchParams.getTypeId() + "_" + Objects.toString(rowData.getId()), TAG_ICON, rowData); + } + + @Override + public void respondSelection(DataResultTopComponent dataResultPanel) { + dataResultPanel.displayTags(this.getItemData().getSearchParams()); } - } - -// /** -// * Display name and count of an analysis result type in the tree. -// */ -// static class AnalysisResultTypeTreeNode extends TreeNode { -// -// /** -// * Main constructor. -// * -// * @param itemData The data to display. -// */ -// AnalysisResultTypeTreeNode(TreeResultsDTO.TreeItemDTO itemData) { -// super(itemData.getSearchParams().getArtifactType().getTypeName(), -// getIconPath(itemData.getSearchParams().getArtifactType()), -// itemData); -// } -// -// @Override -// public void respondSelection(DataResultTopComponent dataResultPanel) { -// dataResultPanel.displayAnalysisResult(this.getItemData().getSearchParams()); -// } -// -// @Override -// public Optional getAnalysisResultType() { -// return Optional.ofNullable(this.getItemData().getSearchParams().getArtifactType()); -// } -// -// @Override -// public Optional getDataSourceIdForActions() { -// return Optional.ofNullable(this.getItemData().getSearchParams().getDataSourceId()); -// } -// -// @Override -// public Optional getNodeSpecificActions() { -// ActionsFactory.ActionGroup group = new ActionsFactory.ActionGroup(); -// -// Optional type = getAnalysisResultType(); -// Optional dsId = getDataSourceIdForActions(); -// if (type.isPresent()) { -// group.add(new DeleteAnalysisResultSetAction(type.get(), () -> Collections.emptyList(), dsId.isPresent() ? dsId.get() : null)); -// } -// -// return Optional.of(group); -// } -// -// } -// -// /** -// * An analysis result type node that has nested children. -// */ -// static class TreeTypeNode extends TreeNode { -// -// /** -// * Main constructor. -// * -// * @param itemData The data to display. -// */ -// TreeTypeNode(TreeResultsDTO.TreeItemDTO itemData, ChildFactory childFactory) { -// super(itemData.getSearchParams().getArtifactType().getTypeName(), -// getIconPath(itemData.getSearchParams().getArtifactType()), -// itemData, -// Children.create(childFactory, true), -// getDefaultLookup(itemData)); -// } -// -// @Override -// public Optional getDataSourceIdForActions() { -// return Optional.ofNullable(this.getItemData().getSearchParams().getDataSourceId()); -// } -// -// @Override -// public Optional getAnalysisResultType() { -// return Optional.ofNullable(this.getItemData().getSearchParams().getArtifactType()); -// } -// } -// -// /** -// * Factory displaying all analysis result configurations with count in the -// * tree. -// */ -// static class TreeConfigFactory extends AbstractAnalysisResultTreeFactory { -// -// private final BlackboardArtifact.Type artifactType; -// private final Long dataSourceId; -// private final String nullSetName; -// -// /** -// * Main constructor. -// * -// * @param artifactType The type of artifact. -// * @param dataSourceId The data source object id for which the results -// * should be filtered or null if no data source -// * filtering. -// * @param nullSetName The name of the set for artifacts with no -// * configuration value. If null, items are omitted. -// */ -// TreeConfigFactory(BlackboardArtifact.Type artifactType, Long dataSourceId, String nullSetName) { -// this.artifactType = artifactType; -// this.dataSourceId = dataSourceId; -// this.nullSetName = nullSetName; -// } -// -// protected BlackboardArtifact.Type getArtifactType() { -// return artifactType; -// } -// -// protected Long getDataSourceId() { -// return dataSourceId; -// } -// -// protected String getNullSetName() { -// return nullSetName; -// } -// -// @Override -// protected TreeResultsDTO getChildResults() throws IllegalArgumentException, ExecutionException { -// return MainDAO.getInstance().getAnalysisResultDAO().getConfigurationCounts(this.artifactType, this.dataSourceId, this.nullSetName); -// } -// -// @Override -// protected TreeNode createNewNode(TreeResultsDTO.TreeItemDTO rowData) { -// return new TreeConfigTypeNode(rowData); -// } -// -// @Override -// protected TreeResultsDTO.TreeItemDTO getOrCreateRelevantChild(TreeEvent treeEvt) { -// TreeResultsDTO.TreeItemDTO originalTreeItem = super.getTypedTreeItem(treeEvt, AnalysisResultSearchParam.class); -// -// if (originalTreeItem != null -// && originalTreeItem.getSearchParams().getArtifactType().equals(this.artifactType) -// && (this.dataSourceId == null || Objects.equals(this.dataSourceId, originalTreeItem.getSearchParams().getDataSourceId()))) { -// -// // generate new type so that if it is a subtree event (i.e. keyword hits), the right tree item is created. -// AnalysisResultSearchParam searchParam = originalTreeItem.getSearchParams(); -// return new TreeResultsDTO.TreeItemDTO<>( -// AnalysisResultSearchParam.getTypeId(), -// new AnalysisResultSearchParam(this.artifactType, searchParam.getConfiguration(), this.dataSourceId), -// searchParam.getConfiguration() == null ? 0 : searchParam.getConfiguration(), -// searchParam.getConfiguration() == null ? nullSetName : searchParam.getConfiguration(), -// originalTreeItem.getDisplayCount()); -// } -// return null; -// } -// -// @Override -// public int compare(TreeItemDTO o1, TreeItemDTO o2) { -// return STRING_COMPARATOR.compare(o1.getSearchParams().getConfiguration(), o2.getSearchParams().getConfiguration()); -// } -// -// @Override -// protected void handleDAOAggregateEvent(DAOAggregateEvent aggEvt) { -// for (DAOEvent evt : aggEvt.getEvents()) { -// if (evt instanceof DeleteAnalysisResultEvent && evt.getType() == DAOEvent.Type.TREE) { -// super.update(); -// return; -// } -// } -// -// super.handleDAOAggregateEvent(aggEvt); -// } -// -// } -// -// /** -// * A node for a set within an artifact type. -// */ -// static class TreeConfigTypeNode extends TreeNode { -// -// /** -// * Main constructor. -// * -// * @param itemData The data to display. -// */ -// TreeConfigTypeNode(TreeResultsDTO.TreeItemDTO itemData) { -// super(itemData.getSearchParams().getArtifactType().getTypeName() + "_SET_" + itemData.getSearchParams().getConfiguration(), -// getIconPath(itemData.getSearchParams().getArtifactType()), -// itemData, -// Children.LEAF, -// getDefaultLookup(itemData)); -// } -// -// @Override -// public void respondSelection(DataResultTopComponent dataResultPanel) { -// dataResultPanel.displayAnalysisResultConfig(this.getItemData().getSearchParams()); -// } -// -// @Override -// public Optional getDataSourceIdForActions() { -// return Optional.ofNullable(this.getItemData().getSearchParams().getDataSourceId()); -// } -// -// @Override -// public Optional getAnalysisResultType() { -// return Optional.ofNullable(this.getItemData().getSearchParams().getArtifactType()); -// } -// -// @Override -// public boolean hasAnalysisResultConfigurations() { -// return true; -// } -// -// @Override -// public List getAnalysisResultConfigurations() { -// return Collections.singletonList(this.getItemData().getSearchParams().getConfiguration()); -// } -// -// @Override -// public Optional getNodeSpecificActions() { -// ActionsFactory.ActionGroup group = new ActionsFactory.ActionGroup(); -// -// Optional type = getAnalysisResultType(); -// Optional dsId = getDataSourceIdForActions(); -// if (type.isPresent()) { -// group.add(new DeleteAnalysisResultSetAction( -// type.get(), -// () -> this.getAnalysisResultConfigurations(), -// dsId.isPresent() ? dsId.get() : null)); -// } -// -// return Optional.of(group); -// } -// } -// -// /** -// * A factory that shows all sets in keyword hits. -// */ -// @Messages({ -// "AnalysisResultTypeFactory_adHocName=Ad Hoc Results" -// }) -// public static class KeywordSetFactory extends AbstractAnalysisResultTreeFactory { -// -// private final Long dataSourceId; -// -// public KeywordSetFactory(Long dataSourceId) { -// this.dataSourceId = dataSourceId; -// } -// -// @Override -// protected TreeResultsDTO getChildResults() throws IllegalArgumentException, ExecutionException { -// return MainDAO.getInstance().getAnalysisResultDAO().getKwSetCounts(this.dataSourceId, Bundle.AnalysisResultTypeFactory_adHocName()); -// } -// -// @Override -// protected TreeResultsDTO.TreeItemDTO getOrCreateRelevantChild(TreeEvent treeEvt) { -// TreeResultsDTO.TreeItemDTO originalTreeItem = super.getTypedTreeItem(treeEvt, KeywordListSearchParam.class); -// -// if (originalTreeItem != null -// && originalTreeItem.getSearchParams().getArtifactType().equals(BlackboardArtifact.Type.TSK_KEYWORD_HIT) -// && (this.dataSourceId == null || Objects.equals(this.dataSourceId, originalTreeItem.getSearchParams().getDataSourceId()))) { -// -// // generate new type so that if it is a subtree event (i.e. keyword hits), the right tree item is created. -// KeywordListSearchParam searchParam = originalTreeItem.getSearchParams(); -// return new TreeResultsDTO.TreeItemDTO<>( -// KeywordListSearchParam.getTypeId(), -// new KeywordListSearchParam(this.dataSourceId, searchParam.getConfiguration(), searchParam.getSetName()), -// searchParam.getSetName() == null ? 0 : searchParam.getSetName(), -// searchParam.getSetName() == null ? Bundle.AnalysisResultTypeFactory_adHocName() : searchParam.getSetName(), -// originalTreeItem.getDisplayCount()); -// } -// return null; -// } -// -// @Override -// public int compare(TreeItemDTO o1, TreeItemDTO o2) { -// return STRING_COMPARATOR.compare(o1.getSearchParams().getSetName(), o2.getSearchParams().getSetName()); -// } -// -// @Override -// protected TreeNode createNewNode(TreeResultsDTO.TreeItemDTO rowData) { -// return new KeywordSetNode(rowData); -// } -// } -// -// static class KeywordSetNode extends TreeNode { -// -// private static final Logger logger = Logger.getLogger(KeywordSetNode.class.getName()); -// -// /** -// * Main constructor. -// * -// * @param itemData The data to display. -// */ -// public KeywordSetNode(TreeResultsDTO.TreeItemDTO itemData) { -// super("TSK_KEYWORD_HIT_SET_" + itemData.getSearchParams().getSetName(), -// getIconPath(itemData.getSearchParams().getArtifactType()), -// itemData, -// Children.create(new KeywordSearchTermFactory(itemData.getSearchParams()), true), -// getDefaultLookup(itemData)); -// } -// -// @Override -// public Optional getDataSourceIdForActions() { -// return Optional.ofNullable(this.getItemData().getSearchParams().getDataSourceId()); -// } -// -// @Override -// public Optional getAnalysisResultType() { -// return Optional.ofNullable(this.getItemData().getSearchParams().getArtifactType()); -// } -// -// @Override -// public boolean hasAnalysisResultConfigurations() { -// return true; -// } -// -// @Override -// public List getAnalysisResultConfigurations() { -// try { -// return MainDAO.getInstance().getAnalysisResultDAO().getKeywordHitConfigurations( -// this.getItemData().getSearchParams().getSetName(), -// this.getItemData().getSearchParams().getDataSourceId()); -// } catch (ExecutionException ex) { -// logger.log(Level.WARNING, "An exception occurred while fetching configurations.", ex); -// return Collections.emptyList(); -// } -// } -// -// @Override -// public Optional getNodeSpecificActions() { -// ActionsFactory.ActionGroup group = new ActionsFactory.ActionGroup(); -// -// Optional type = getAnalysisResultType(); -// Optional dsId = getDataSourceIdForActions(); -// if (type.isPresent()) { -// group.add(new DeleteAnalysisResultSetAction( -// type.get(), -// () -> this.getAnalysisResultConfigurations(), -// dsId.isPresent() ? dsId.get() : null)); -// } -// -// return Optional.of(group); -// } -// } -// -// /** -// * Factory for displaying all search terms (regex or exact) for a specific -// * set. -// */ -// static class KeywordSearchTermFactory extends AbstractAnalysisResultTreeFactory { -// -// private final KeywordListSearchParam setParams; -// -// /** -// * Main constructor. -// * -// * @param setParams The parameters for the set. -// */ -// KeywordSearchTermFactory(KeywordListSearchParam setParams) { -// this.setParams = setParams; -// } -// -// @Override -// protected TreeNode createNewNode(TreeResultsDTO.TreeItemDTO rowData) { -// return new KeywordSearchTermNode(rowData); -// } -// -// @Override -// protected TreeResultsDTO getChildResults() throws IllegalArgumentException, ExecutionException { -// return MainDAO.getInstance().getAnalysisResultDAO().getKeywordSearchTermCounts(this.setParams.getSetName(), this.setParams.getDataSourceId()); -// } -// -// @Override -// protected TreeResultsDTO.TreeItemDTO getOrCreateRelevantChild(TreeEvent treeEvt) { -// TreeResultsDTO.TreeItemDTO originalTreeItem = super.getTypedTreeItem(treeEvt, KeywordSearchTermParams.class); -// -// if (originalTreeItem != null -// && Objects.equals(originalTreeItem.getSearchParams().getSetName(), this.setParams.getSetName()) -// && (this.setParams.getDataSourceId() == null -// || Objects.equals(this.setParams.getDataSourceId(), originalTreeItem.getSearchParams().getDataSourceId()))) { -// -// KeywordSearchTermParams searchParam = originalTreeItem.getSearchParams(); -// String searchTermDisplayName = MainDAO.getInstance().getAnalysisResultDAO() -// .getSearchTermDisplayName(searchParam.getRegex(), searchParam.getSearchType()); -// -// return new TreeResultsDTO.TreeItemDTO<>( -// KeywordSearchTermParams.getTypeId(), -// new KeywordSearchTermParams( -// this.setParams.getSetName(), -// searchParam.getRegex(), -// searchParam.getSearchType(), -// searchParam.getConfiguration(), -// searchParam.hasChildren(), -// this.setParams.getDataSourceId() -// ), -// searchTermDisplayName, -// searchTermDisplayName, -// originalTreeItem.getDisplayCount() -// ); -// } -// return null; -// } -// -// @Override -// public int compare(TreeItemDTO o1, TreeItemDTO o2) { -// return STRING_COMPARATOR.compare(o1.getSearchParams().getRegex(), o2.getSearchParams().getRegex()); -// } -// -// @Override -// protected void handleDAOAggregateEvent(DAOAggregateEvent aggEvt) { -// for (DAOEvent evt : aggEvt.getEvents()) { -// if (evt instanceof DeleteAnalysisResultEvent && evt.getType() == DAOEvent.Type.TREE) { -// super.update(); -// return; -// } -// } -// -// super.handleDAOAggregateEvent(aggEvt); -// } -// -// } -// -// /** -// * A node for an individual search term. -// */ -// static class KeywordSearchTermNode extends TreeNode { -// -// private static final Logger logger = Logger.getLogger(KeywordSearchTermNode.class.getName()); -// -// /** -// * Main constructor. -// * -// * @param itemData The data for the search term. -// */ -// KeywordSearchTermNode(TreeResultsDTO.TreeItemDTO itemData) { -// super(itemData.getSearchParams().getRegex(), -// getIconPath(BlackboardArtifact.Type.TSK_KEYWORD_HIT), -// itemData, -// (itemData.getSearchParams().hasChildren() || itemData.getSearchParams().getSearchType() == TskData.KeywordSearchQueryType.REGEX -// // for regex queries always create a subtree, even if there is only one child -// ? Children.create(new KeywordFoundMatchFactory(itemData.getSearchParams()), true) -// : Children.LEAF), -// getDefaultLookup(itemData)); -// } -// -// @Override -// public void respondSelection(DataResultTopComponent dataResultPanel) { -// KeywordSearchTermParams searchTermParams = this.getItemData().getSearchParams(); -// -// if (!searchTermParams.hasChildren()) { -// KeywordHitSearchParam searchParams = new KeywordHitSearchParam(searchTermParams.getDataSourceId(), -// searchTermParams.getConfiguration(), -// // if literal, keyword is regex -// TskData.KeywordSearchQueryType.LITERAL.equals(searchTermParams.getSearchType()) ? searchTermParams.getRegex() : null, -// // if literal, no regex -// TskData.KeywordSearchQueryType.LITERAL.equals(searchTermParams.getSearchType()) ? null : searchTermParams.getRegex(), -// searchTermParams.getSearchType(), -// searchTermParams.getConfiguration()); -// dataResultPanel.displayKeywordHits(searchParams); -// } else { -// super.respondSelection(dataResultPanel); -// } -// } -// -// @Override -// public Optional getNodeSpecificActions() { -// ActionsFactory.ActionGroup group = new ActionsFactory.ActionGroup(); -// -// Optional type = getAnalysisResultType(); -// Optional dsId = getDataSourceIdForActions(); -// if (type.isPresent()) { -// group.add(new DeleteAnalysisResultSetAction( -// type.get(), -// () -> this.getAnalysisResultConfigurations(), -// dsId.isPresent() ? dsId.get() : null)); -// } -// -// return Optional.of(group); -// } -// -// public Optional getDataSourceIdForActions() { -// return Optional.ofNullable(this.getItemData().getSearchParams().getDataSourceId()); -// } -// -// @Override -// public Optional getAnalysisResultType() { -// return Optional.ofNullable(this.getItemData().getSearchParams().getArtifactType()); -// } -// -// @Override -// public boolean hasAnalysisResultConfigurations() { -// return true; -// } -// -// @Override -// public List getAnalysisResultConfigurations() { -// return Collections.singletonList(this.getItemData().getSearchParams().getConfiguration()); -// } -// } -// -// /** -// * A factory for found keyword matches based on the search term (for -// * regex/substring). -// */ -// public static class KeywordFoundMatchFactory extends AbstractAnalysisResultTreeFactory { -// -// private final KeywordSearchTermParams searchTermParams; -// -// /** -// * Main constructor. -// * -// * @param params The search term parameters. -// */ -// public KeywordFoundMatchFactory(KeywordSearchTermParams params) { -// this.searchTermParams = params; -// } -// -// @Override -// protected TreeNode createNewNode(TreeResultsDTO.TreeItemDTO rowData) { -// return new KeywordFoundMatchNode(rowData); -// } -// -// @Override -// protected TreeResultsDTO getChildResults() throws IllegalArgumentException, ExecutionException { -// return MainDAO.getInstance().getAnalysisResultDAO().getKeywordMatchCounts( -// this.searchTermParams.getSetName(), -// this.searchTermParams.getRegex(), -// this.searchTermParams.getSearchType(), -// this.searchTermParams.getDataSourceId()); -// } -// -// @Override -// protected TreeResultsDTO.TreeItemDTO getOrCreateRelevantChild(TreeEvent treeEvt) { -// TreeResultsDTO.TreeItemDTO originalTreeItem = super.getTypedTreeItem(treeEvt, KeywordHitSearchParam.class); -// -// if (originalTreeItem != null -// && Objects.equals(originalTreeItem.getSearchParams().getRegex(), this.searchTermParams.getRegex()) -// && Objects.equals(originalTreeItem.getSearchParams().getSearchType(), this.searchTermParams.getSearchType()) -// && Objects.equals(originalTreeItem.getSearchParams().getConfiguration(), this.searchTermParams.getConfiguration()) -// && (this.searchTermParams.getDataSourceId() == null -// || Objects.equals(this.searchTermParams.getDataSourceId(), originalTreeItem.getSearchParams().getDataSourceId()))) { -// -// // generate new type so that if it is a subtree event (i.e. keyword hits), the right tree item is created. -// KeywordHitSearchParam searchParam = originalTreeItem.getSearchParams(); -// return new TreeResultsDTO.TreeItemDTO<>( -// KeywordHitSearchParam.getTypeId(), -// new KeywordHitSearchParam( -// this.searchTermParams.getDataSourceId(), -// this.searchTermParams.getSetName(), -// searchParam.getKeyword(), -// this.searchTermParams.getRegex(), -// this.searchTermParams.getSearchType(), -// this.searchTermParams.getConfiguration() -// ), -// searchParam.getKeyword() == null ? "" : searchParam.getKeyword(), -// searchParam.getKeyword() == null ? "" : searchParam.getKeyword(), -// originalTreeItem.getDisplayCount() -// ); -// } -// return null; -// } -// -// @Override -// public int compare(TreeItemDTO o1, TreeItemDTO o2) { -// return STRING_COMPARATOR.compare(o1.getSearchParams().getKeyword(), o2.getSearchParams().getKeyword()); -// } -// -// @Override -// protected void handleDAOAggregateEvent(DAOAggregateEvent aggEvt) { -// for (DAOEvent evt : aggEvt.getEvents()) { -// if (evt instanceof DeleteAnalysisResultEvent && evt.getType() == DAOEvent.Type.TREE) { -// super.update(); -// return; -// } -// } -// -// super.handleDAOAggregateEvent(aggEvt); -// } -// } -// -// /** -// * A node signifying a match for a specific keyword given a regex/substring -// * search term. -// */ -// static class KeywordFoundMatchNode extends TreeNode { -// -// /** -// * Main constructor. -// * -// * @param itemData The data for the match parameters. -// */ -// public KeywordFoundMatchNode(TreeResultsDTO.TreeItemDTO itemData) { -// super(itemData.getSearchParams().getKeyword(), -// getIconPath(BlackboardArtifact.Type.TSK_KEYWORD_HIT), -// itemData, -// Children.LEAF, -// getDefaultLookup(itemData)); -// } -// -// @Override -// public void respondSelection(DataResultTopComponent dataResultPanel) { -// dataResultPanel.displayKeywordHits(this.getItemData().getSearchParams()); -// } -// -// @Override -// public Optional getDataSourceIdForActions() { -// return Optional.ofNullable(this.getItemData().getSearchParams().getDataSourceId()); -// } -// -// @Override -// public Optional getAnalysisResultType() { -// return Optional.ofNullable(this.getItemData().getSearchParams().getArtifactType()); -// } -// -// @Override -// public boolean hasAnalysisResultConfigurations() { -// return true; -// } -// -// @Override -// public List getAnalysisResultConfigurations() { -// return Collections.singletonList(this.getItemData().getSearchParams().getConfiguration()); -// } -// } - } From a06fec7fe9cdbe35850ffa06fa2e64f4c77d9c75 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 16 Feb 2022 14:40:41 -0500 Subject: [PATCH 5/8] commenting --- .../autopsy/mainui/datamodel/TagsDAO.java | 65 +++++++++++++++++-- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java index 15ff8c2506..e1e5ac5b23 100755 --- a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java +++ b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java @@ -414,10 +414,15 @@ public class TagsDAO extends AbstractDAO { return null; } - private SleuthkitCase getCase() throws NoCurrentCaseException, TskCoreException { - return Case.getCurrentCaseThrows().getSleuthkitCase(); - } - + /** + * Returns the counts of each tag name. + * + * @param dataSourceId The data source object id to filter on. + * + * @return The tree item results. + * + * @throws ExecutionException + */ public TreeResultsDTO getNameCounts(Long dataSourceId) throws ExecutionException { Set indeterminateTagNameIds = this.treeCounts.getEnqueued().stream() .filter(evt -> dataSourceId == null || evt.getDataSourceId() == dataSourceId) @@ -481,6 +486,15 @@ public class TagsDAO extends AbstractDAO { return new TreeResultsDTO<>(tagNameParams); } + /** + * Creates a tag name tree item. + * + * @param tagName The tag name. + * @param dataSourceId The data source object id or null if not present. + * @param treeDisplayCount The tree display count. + * + * @return The tree item dto. + */ public TreeItemDTO createTagNameTreeItem(TagName tagName, Long dataSourceId, TreeResultsDTO.TreeDisplayCount treeDisplayCount) { return new TreeItemDTO<>( TagNameSearchParams.getTypeId(), @@ -491,6 +505,18 @@ public class TagsDAO extends AbstractDAO { ); } + /** + * The count of content tags. + * + * @param dataSourceId The data source id where the content tag should + * appear or null. + * @param tagName The tag name. + * + * @return The count. + * + * @throws NoCurrentCaseException + * @throws TskCoreException + */ private long getContentTagCount(Long dataSourceId, TagName tagName) throws NoCurrentCaseException, TskCoreException { if (UserPreferences.showOnlyCurrentUserTags()) { @@ -505,6 +531,18 @@ public class TagsDAO extends AbstractDAO { } } + /** + * The count of result tags. + * + * @param dataSourceId The data source id where the result tag should appear + * or null. + * @param tagName The tag name. + * + * @return The count. + * + * @throws NoCurrentCaseException + * @throws TskCoreException + */ private long getArtifactTagCount(Long dataSourceId, TagName tagName) throws NoCurrentCaseException, TskCoreException { if (UserPreferences.showOnlyCurrentUserTags()) { String userName = System.getProperty(USER_NAME_PROPERTY); @@ -518,6 +556,15 @@ public class TagsDAO extends AbstractDAO { } } + /** + * Returns the counts of file and result type given the search params. + * + * @param searchParams The tag name search params. + * + * @return The tree item results. + * + * @throws ExecutionException + */ public TreeResultsDTO getTypeCounts(TagNameSearchParams searchParams) throws ExecutionException { Long dataSourceId = searchParams.getDataSourceId(); TagName tagName = searchParams.getTagName(); @@ -549,6 +596,16 @@ public class TagsDAO extends AbstractDAO { } } + /** + * Creates a tag type tree item. + * + * @param tagName The tag name. + * @param tagType The tag type. + * @param dataSourceId The data source object id or null if not present. + * @param treeDisplayCount The tree display count. + * + * @return The tree item dto. + */ public TreeItemDTO createTagTypeTreeItem(TagName tagName, TagType tagType, Long dataSourceId, TreeResultsDTO.TreeDisplayCount treeDisplayCount) { return new TreeItemDTO<>( TagsSearchParams.getTypeId(), From 822d79f573facc65533b655f3e58369b08dc6830 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 16 Feb 2022 14:41:26 -0500 Subject: [PATCH 6/8] commenting --- .../org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java b/Core/src/org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java index 3f28c90bb2..0a7d99f627 100644 --- a/Core/src/org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java +++ b/Core/src/org/sleuthkit/autopsy/mainui/nodes/TagNameFactory.java @@ -155,6 +155,10 @@ public class TagNameFactory extends TreeChildFactory { } + /** + * A tag type (i.e. File/Result) tree node. Clicking on this will go to + * results. + */ static class TagsTypeNode extends TreeNode { private TagsTypeNode(TreeItemDTO rowData) { From d15bbdfb81a8411da21ffef27cf6141c31d0ddff Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 16 Feb 2022 15:09:59 -0500 Subject: [PATCH 7/8] fixes --- .../datamodel/DisplayableItemNodeVisitor.java | 21 ----------- .../datamodel/RootContentChildren.java | 2 +- .../org/sleuthkit/autopsy/datamodel/Tags.java | 37 +++++++++++++++++-- .../mainui/datamodel/Bundle.properties-MERGED | 2 + .../autopsy/mainui/datamodel/TagsDAO.java | 8 ++-- 5 files changed, 41 insertions(+), 29 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index 76b7b7f352..766f2b713d 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -91,12 +91,6 @@ public interface DisplayableItemNodeVisitor { */ T visit(Tags.RootNode node); - T visit(Tags.TagNameNode node); - - T visit(Tags.ContentTagTypeNode node); - - T visit(Tags.BlackboardArtifactTagTypeNode node); - /* * Reports @@ -270,21 +264,6 @@ public interface DisplayableItemNodeVisitor { return defaultVisit(node); } - @Override - public T visit(Tags.TagNameNode node) { - return defaultVisit(node); - } - - @Override - public T visit(Tags.ContentTagTypeNode node) { - return defaultVisit(node); - } - - @Override - public T visit(Tags.BlackboardArtifactTagTypeNode node) { - return defaultVisit(node); - } - @Override public T visit(Reports.ReportsListNode node) { return defaultVisit(node); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/RootContentChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/RootContentChildren.java index 695c3f6930..4ac4df209a 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/RootContentChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/RootContentChildren.java @@ -97,7 +97,7 @@ public class RootContentChildren extends Children.Keys { public static Node createNode(Object key) { if (key instanceof Tags) { Tags tagsNodeKey = (Tags) key; - return tagsNodeKey.new RootNode(tagsNodeKey.filteringDataSourceObjId()); + return new Tags.RootNode(tagsNodeKey.filteringDataSourceObjId()); } else if (key instanceof DataSources) { DataSources dataSourcesKey = (DataSources) key; return new DataSourceFilesNode(dataSourcesKey.filteringDataSourceObjId()); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index b26e8a6adb..c2239340ca 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -31,6 +31,30 @@ import org.sleuthkit.autopsy.mainui.nodes.TagNameFactory; * factory built on top of the NetBeans Children.Keys class. */ public class Tags { + private final static String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text"); + private final long filteringDSObjId; // 0 if not filtering/grouping by data source + + Tags() { + this(0); + } + + Tags(long dsObjId) { + this.filteringDSObjId = dsObjId; + } + + /** + * Return the display name used by the tags node in the tree. + * + * @return - DISPLAY_NAME + */ + public static String getTagsDisplayName() { + return DISPLAY_NAME; + } + + long filteringDataSourceObjId() { + return this.filteringDSObjId; + } + /** * Instances of this class are the root nodes of tree that is a sub-tree of * the Autopsy presentation of the SleuthKit data model. The sub-tree @@ -38,16 +62,16 @@ public class Tags { * type, then by tag name. */ public static class RootNode extends DisplayableItemNode { - private final static String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text"); + private final static String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS private final Long dataSourceObjId; public RootNode(Long dsId) { - super(Children.create(new TagNameFactory(dsId > 0 ? dsId : null), true), Lookups.singleton(DISPLAY_NAME)); + super(Children.create(new TagNameFactory(dsId != null && dsId> 0 ? dsId : null), true), Lookups.singleton(DISPLAY_NAME)); super.setName(DISPLAY_NAME); super.setDisplayName(DISPLAY_NAME); this.setIconBaseWithExtension(ICON_PATH); - this.dataSourceObjId = dsId > 0 ? dsId : null; + this.dataSourceObjId = dsId != null && dsId> 0 ? dsId : null; } @Override @@ -81,5 +105,12 @@ public class Tags { public Node clone() { return new RootNode(dataSourceObjId); } + + /** + * Cause the contents of the RootNode and its children to be updated. + */ + public void refresh() { + this.refresh(); + } } } diff --git a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/Bundle.properties-MERGED index 067caeaded..4fe5bc1c15 100644 --- a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/Bundle.properties-MERGED @@ -117,3 +117,5 @@ TagsDAO.tagColumns.sourceNameColLbl=Source Name TagsDAO.tagColumns.sourcePathColLbl=Source File Path TagsDAO.tagColumns.typeColLbl=Result Type TagsDAO.tagColumns.userNameColLbl=User Name +TagType_File_displayName=File Tags +TagType_Result_displayName=Result Tags diff --git a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java index e1e5ac5b23..9f94b0d5d9 100755 --- a/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java +++ b/Core/src/org/sleuthkit/autopsy/mainui/datamodel/TagsDAO.java @@ -361,9 +361,9 @@ public class TagsDAO extends AbstractDAO { Collection daoEvents = Collections.singletonList(data); - Collection treeEvents = this.treeCounts.enqueueAll(daoEvents).stream() - .map(arEvt -> new TreeEvent(getTreeItem(arEvt, TreeResultsDTO.TreeDisplayCount.INDETERMINATE), false)) - .collect(Collectors.toList()); + Collection treeEvents = daoEvents.stream() + .map(arEvt -> new TreeEvent(getTreeItem(arEvt, TreeResultsDTO.TreeDisplayCount.UNSPECIFIED), true)) + .collect(Collectors.toSet()); return Stream.of(daoEvents, treeEvents) .flatMap(lst -> lst.stream()) @@ -610,7 +610,7 @@ public class TagsDAO extends AbstractDAO { return new TreeItemDTO<>( TagsSearchParams.getTypeId(), new TagsSearchParams(tagName, tagType, dataSourceId), - tagName.getId(), + tagName.getId() + "_" + tagType.name(), tagType.getDisplayName(), treeDisplayCount ); From eb2a7203541c46124d849e8f32425d20e18d3a05 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 16 Feb 2022 16:09:33 -0500 Subject: [PATCH 8/8] Added tag events to sleuthkit --- .../sleuthkit/autopsy/casemodule/Case.java | 102 ++++++------------ .../casemodule/services/TagsManager.java | 46 ++------ 2 files changed, 43 insertions(+), 105 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 9c048e3176..5abb9a0056 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -671,6 +671,38 @@ public class Case { public void publishAnalysisResultDeleted(TskEvent.AnalysisResultsDeletedTskEvent event) { eventPublisher.publish(new AnalysisResultDeletedEvent(event.getAnalysisResultObjectIds())); } + + @Subscribe + public void publishBlackboardArtifactTagDeleted(TskEvent.BlackboardArtifactTagsDeletedTskEvent event) { + List tags = event.getTags(); + for(BlackboardArtifactTag tag: tags) { + eventPublisher.publish(new BlackBoardArtifactTagDeletedEvent(tag)); + } + } + + @Subscribe + public void publishBlackboardTagAdded(TskEvent.BlackboardArtifactTagsAddedTskEvent event) { + List tags = event.getTags(); + for(BlackboardArtifactTag tag: tags) { + eventPublisher.publish(new BlackBoardArtifactTagAddedEvent(tag)); + } + } + + @Subscribe + public void publishContentTagAdded(TskEvent.ContentTagsAddedTskEvent event) { + List tags = event.getTags(); + for(ContentTag tag: tags) { + eventPublisher.publish(new ContentTagAddedEvent(tag)); + } + } + + @Subscribe + public void publishContentTagDeleted(TskEvent.ContentTagsDeletedTskEvent event) { + List tags = event.getTags(); + for(ContentTag tag: tags) { + eventPublisher.publish(new ContentTagDeletedEvent(tag)); + } + } } /** @@ -1820,41 +1852,6 @@ public class Case { eventPublisher.publish(new DataSourceNameChangedEvent(dataSource, newName)); } - /** - * Notifies case event subscribers that a content tag has been added. - * - * This should not be called from the event dispatch thread (EDT) - * - * @param newTag new ContentTag added - */ - public void notifyContentTagAdded(ContentTag newTag) { - notifyContentTagAdded(newTag, null); - } - - /** - * Notifies case event subscribers that a content tag has been added. - * - * This should not be called from the event dispatch thread (EDT) - * - * @param newTag The added ContentTag. - * @param deletedTagList List of ContentTags that were removed as a result - * of the addition of newTag. - */ - public void notifyContentTagAdded(ContentTag newTag, List deletedTagList) { - eventPublisher.publish(new ContentTagAddedEvent(newTag, deletedTagList)); - } - - /** - * Notifies case event subscribers that a content tag has been deleted. - * - * This should not be called from the event dispatch thread (EDT) - * - * @param deletedTag ContentTag deleted - */ - public void notifyContentTagDeleted(ContentTag deletedTag) { - eventPublisher.publish(new ContentTagDeletedEvent(deletedTag)); - } - /** * Notifies case event subscribers that a tag definition has changed. * @@ -1885,41 +1882,6 @@ public class Case { } } - /** - * Notifies case event subscribers that an artifact tag has been added. - * - * This should not be called from the event dispatch thread (EDT) - * - * @param newTag new BlackboardArtifactTag added - */ - public void notifyBlackBoardArtifactTagAdded(BlackboardArtifactTag newTag) { - notifyBlackBoardArtifactTagAdded(newTag, null); - } - - /** - * Notifies case event subscribers that an artifact tag has been added. - * - * This should not be called from the event dispatch thread (EDT) - * - * @param newTag The added ContentTag. - * @param removedTagList List of ContentTags that were removed as a result - * of the addition of newTag. - */ - public void notifyBlackBoardArtifactTagAdded(BlackboardArtifactTag newTag, List removedTagList) { - eventPublisher.publish(new BlackBoardArtifactTagAddedEvent(newTag, removedTagList)); - } - - /** - * Notifies case event subscribers that an artifact tag has been deleted. - * - * This should not be called from the event dispatch thread (EDT) - * - * @param deletedTag BlackboardArtifactTag deleted - */ - public void notifyBlackBoardArtifactTagDeleted(BlackboardArtifactTag deletedTag) { - eventPublisher.publish(new BlackBoardArtifactTagDeletedEvent(deletedTag)); - } - /** * Adds a report to the case. * diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index a4bd51bcce..53c695cf9d 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -66,9 +66,9 @@ public class TagsManager implements Closeable { private static String PROJECT_VIC_TAG_SET_NAME = "Project VIC"; private static final Object lock = new Object(); - + private final Map allTagNameMap = Collections.synchronizedMap(new HashMap<>()); - + private final PropertyChangeListener listener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { @@ -95,7 +95,7 @@ public class TagsManager implements Closeable { } } }; - + private final PropertyChangeListener weakListener = WeakListeners.propertyChange(listener, null); static { @@ -300,12 +300,12 @@ public class TagsManager implements Closeable { try { List tagSetsInCase = taggingMgr.getTagSets(); if (tagSetsInCase.isEmpty()) { - + // add the standard tag names for (TagNameDefinition def : TagNameDefinition.getStandardTagNameDefinitions()) { taggingMgr.addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus()); } - + //Assume new case and add all tag sets for (TagSetDefinition setDef : TagSetDefinition.readTagSetDefinitions()) { List tagNamesInSet = new ArrayList<>(); @@ -317,12 +317,12 @@ public class TagsManager implements Closeable { taggingMgr.addTagSet(setDef.getName(), tagNamesInSet); } } - } + } - for(TagName tagName: caseDb.getAllTagNames()) { + for (TagName tagName : caseDb.getAllTagNames()) { allTagNameMap.put(tagName.getDisplayName(), tagName); } - + } catch (TskCoreException ex) { LOGGER.log(Level.SEVERE, "Error updating standard tag name and tag set definitions", ex); } catch (IOException ex) { @@ -332,7 +332,7 @@ public class TagsManager implements Closeable { for (TagNameDefinition tagName : TagNameDefinition.getTagNameDefinitions()) { tagName.saveToCase(caseDb); } - + Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_UPDATED), weakListener); Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_ADDED), weakListener); Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_DELETED), weakListener); @@ -359,7 +359,7 @@ public class TagsManager implements Closeable { * @throws TskCoreException If there is an error querying the case database. */ public TagSet getTagSet(TagName tagName) throws TskCoreException { - return caseDb.getTaggingManager().getTagSet(tagName); + return caseDb.getTaggingManager().getTagSet(tagName); } /** @@ -383,7 +383,7 @@ public class TagsManager implements Closeable { * @return A list, possibly empty, of TagName objects. */ public synchronized List getAllTagNames() { - + List tagNames = new ArrayList<>(); tagNames.addAll(allTagNameMap.values()); return tagNames; @@ -636,14 +636,6 @@ public class TagsManager implements Closeable { */ public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws TskCoreException { TaggingManager.ContentTagChange tagChange = caseDb.getTaggingManager().addContentTag(content, tagName, comment, beginByteOffset, endByteOffset); - try { - Case currentCase = Case.getCurrentCaseThrows(); - - currentCase.notifyContentTagAdded(tagChange.getAddedTag(), tagChange.getRemovedTags().isEmpty() ? null : tagChange.getRemovedTags()); - - } catch (NoCurrentCaseException ex) { - throw new TskCoreException("Added a tag to a closed case", ex); - } return tagChange.getAddedTag(); } @@ -657,11 +649,6 @@ public class TagsManager implements Closeable { */ public void deleteContentTag(ContentTag tag) throws TskCoreException { caseDb.deleteContentTag(tag); - try { - Case.getCurrentCaseThrows().notifyContentTagDeleted(tag); - } catch (NoCurrentCaseException ex) { - throw new TskCoreException("Deleted a tag from a closed case", ex); - } } /** @@ -857,12 +844,6 @@ public class TagsManager implements Closeable { */ public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException { TaggingManager.BlackboardArtifactTagChange tagChange = caseDb.getTaggingManager().addArtifactTag(artifact, tagName, comment); - try { - Case currentCase = Case.getCurrentCaseThrows(); - currentCase.notifyBlackBoardArtifactTagAdded(tagChange.getAddedTag(), tagChange.getRemovedTags().isEmpty() ? null : tagChange.getRemovedTags()); - } catch (NoCurrentCaseException ex) { - throw new TskCoreException("Added a tag to a closed case", ex); - } return tagChange.getAddedTag(); } @@ -876,11 +857,6 @@ public class TagsManager implements Closeable { */ public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException { caseDb.deleteBlackboardArtifactTag(tag); - try { - Case.getCurrentCaseThrows().notifyBlackBoardArtifactTagDeleted(tag); - } catch (NoCurrentCaseException ex) { - throw new TskCoreException("Deleted a tag from a closed case", ex); - } } /**