19 package org.sleuthkit.autopsy.datamodel;
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.util.Collections;
24 import java.util.EnumSet;
25 import java.util.HashMap;
26 import java.util.List;
28 import java.util.Objects;
30 import java.util.logging.Level;
31 import java.util.stream.Collectors;
32 import java.util.stream.Stream;
33 import org.openide.nodes.ChildFactory;
34 import org.openide.nodes.Children;
35 import org.openide.nodes.Node;
36 import org.openide.nodes.Sheet;
37 import org.openide.util.Lookup;
38 import org.openide.util.NbBundle;
39 import org.openide.util.WeakListeners;
40 import org.openide.util.lookup.Lookups;
53 import org.python.google.common.collect.Sets;
90 BaseArtifactNode(Children children, String icon, String name, String displayName) {
91 super(children, Lookups.singleton(name));
93 super.setDisplayName(displayName);
94 this.setIconBaseWithExtension(icon);
98 public boolean isLeafTypeNode() {
104 return visitor.
visit(
this);
108 protected Sheet createSheet() {
109 Sheet sheet = super.createSheet();
110 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
111 if (sheetSet == null) {
112 sheetSet = Sheet.createPropertiesSet();
116 sheetSet.put(
new NodeProperty<>(NbBundle.getMessage(
this.getClass(),
"ExtractedContentNode.createSheet.name.name"),
117 NbBundle.getMessage(
this.getClass(),
"ExtractedContentNode.createSheet.name.displayName"),
118 NbBundle.getMessage(
this.getClass(),
"ExtractedContentNode.createSheet.name.desc"),
119 super.getDisplayName()));
124 public String getItemType() {
125 return getClass().getName();
146 this(
new TypeNode(type, dsObjId), type);
157 this.node = typeNode;
159 .filter(t -> t != null)
160 .collect(Collectors.toSet());
177 Set<BlackboardArtifact.Type> getApplicableTypes() {
196 if (getClass() != obj.getClass()) {
212 static class TypeFactory
extends ChildFactory.Detachable<TypeNodeKey> implements
RefreshThrottler.Refresher {
219 @SuppressWarnings(
"deprecation")
222 TSK_DATA_SOURCE_USAGE,
227 TSK_ASSOCIATED_OBJECT
244 @SuppressWarnings("deprecation")
247 int typeId = type.getTypeID();
248 if (TSK_EMAIL_MSG.getTypeID() == typeId) {
250 return new TypeNodeKey(emailNode, TSK_EMAIL_MSG);
252 }
else if (TSK_ACCOUNT.getTypeID() == typeId) {
253 Accounts.AccountsRootNode accountsNode =
new Accounts(dsObjId).new AccountsRootNode();
254 return new TypeNodeKey(accountsNode, TSK_ACCOUNT);
256 }
else if (TSK_KEYWORD_HIT.getTypeID() == typeId) {
257 KeywordHits.RootNode keywordsNode =
new KeywordHits(skCase, dsObjId).new RootNode();
258 return new TypeNodeKey(keywordsNode, TSK_KEYWORD_HIT);
260 }
else if (TSK_INTERESTING_ITEM.getTypeID() == typeId) {
261 InterestingHits.RootNode interestingHitsNode =
new InterestingHits(skCase, TSK_INTERESTING_ITEM, dsObjId).new RootNode();
262 return new TypeNodeKey(interestingHitsNode, TSK_INTERESTING_ITEM);
263 }
else if (TSK_INTERESTING_ARTIFACT_HIT.getTypeID() == typeId) {
264 InterestingHits.RootNode interestingHitsNode =
new InterestingHits(skCase, TSK_INTERESTING_ARTIFACT_HIT, dsObjId).new RootNode();
265 return new TypeNodeKey(interestingHitsNode, TSK_INTERESTING_ARTIFACT_HIT);
266 }
else if (TSK_INTERESTING_FILE_HIT.getTypeID() == typeId) {
267 InterestingHits.RootNode interestingHitsNode =
new InterestingHits(skCase, TSK_INTERESTING_FILE_HIT, dsObjId).new RootNode();
268 return new TypeNodeKey(interestingHitsNode, TSK_INTERESTING_FILE_HIT);
269 }
else if (TSK_HASHSET_HIT.getTypeID() == typeId) {
270 HashsetHits.RootNode hashsetHits =
new HashsetHits(skCase, dsObjId).new RootNode();
271 return new TypeNodeKey(hashsetHits, TSK_HASHSET_HIT);
272 }
else if (TSK_MALWARE.getTypeID() == typeId) {
273 MalwareHits.RootNode malwareHits =
new MalwareHits(skCase, dsObjId).new RootNode();
274 return new TypeNodeKey(malwareHits, TSK_MALWARE);
276 return new TypeNodeKey(type, dsObjId);
281 private final Map<BlackboardArtifact.Type, TypeNodeKey> typeNodeMap =
new HashMap<>();
282 private final long filteringDSObjId;
289 private final RefreshThrottler refreshThrottler =
new RefreshThrottler(
this);
290 private final Category category;
292 private final PropertyChangeListener weakPcl;
302 TypeFactory(Category category,
long filteringDSObjId) {
304 this.filteringDSObjId = filteringDSObjId;
305 this.category = category;
307 PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
308 String eventType = evt.getPropertyName();
309 if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
311 if (evt.getNewValue() == null) {
314 }
else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
315 || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
323 Case.getCurrentCaseThrows();
325 }
catch (NoCurrentCaseException notUsed) {
333 weakPcl = WeakListeners.propertyChange(pcl, null);
337 protected void addNotify() {
339 refreshThrottler.registerForIngestModuleEvents();
341 Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
345 protected void finalize() throws Throwable {
347 refreshThrottler.unregisterEventListener();
348 IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
349 Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
354 protected boolean createKeys(List<TypeNodeKey> list) {
357 SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
358 List<BlackboardArtifact.Type> types = (this.filteringDSObjId > 0)
359 ? skCase.getBlackboard().getArtifactTypesInUse(this.filteringDSObjId)
360 : skCase.getArtifactTypesInUse();
362 List<TypeNodeKey> allKeysSorted = types.stream()
364 .filter(tp -> category.equals(tp.getCategory()) && !IGNORED_TYPES.contains(tp))
367 if (typeNodeMap.containsKey(tp)) {
368 TypeNodeKey typeKey = typeNodeMap.get(tp);
369 typeKey.getNode().updateDisplayName();
373 TypeNodeKey newTypeKey = getTypeKey(tp, skCase, filteringDSObjId);
374 for (BlackboardArtifact.Type recordType : newTypeKey.getApplicableTypes()) {
375 typeNodeMap.put(recordType, newTypeKey);
381 .filter(record -> record != null)
387 String aSafe = (a.getNode() == null || a.getNode().getDisplayName() == null) ?
"" : a.getNode().getDisplayName();
388 String bSafe = (b.getNode() == null || b.getNode().getDisplayName() == null) ?
"" : b.getNode().getDisplayName();
389 return aSafe.compareToIgnoreCase(bSafe);
391 .collect(Collectors.toList());
393 list.addAll(allKeysSorted);
395 }
catch (NoCurrentCaseException ex) {
396 logger.log(Level.WARNING,
"Trying to access case when no case is open.", ex);
397 }
catch (TskCoreException ex) {
398 logger.log(Level.SEVERE,
"Error getting list of artifacts in use: " + ex.getLocalizedMessage());
404 protected Node createNodeForKey(TypeNodeKey key) {
405 return key.getNode();
409 public void refresh() {
414 public boolean isRefreshRequired(PropertyChangeEvent evt) {
415 String eventType = evt.getPropertyName();
416 if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
423 Case.getCurrentCaseThrows();
429 final ModuleDataEvent
event = (ModuleDataEvent) evt.getOldValue();
430 if (null != event && category.equals(event.getBlackboardArtifactType().getCategory())
431 && !(IGNORED_TYPES.contains(event.getBlackboardArtifactType()))) {
434 }
catch (NoCurrentCaseException notUsed) {
472 super(children, lookup);
473 this.
types = Stream.of(
types).collect(Collectors.toSet());
500 if (filteringDSObjId > 0) {
501 count += skCase.getBlackboard().getArtifactsCount(type.getTypeID(),
filteringDSObjId);
503 count += skCase.getBlackboardArtifactsTypeCount(type.getTypeID());
513 void updateDisplayName() {
518 logger.log(Level.WARNING,
"Error fetching data when case closed.", ex);
519 }
catch (TskCoreException ex) {
520 logger.log(Level.WARNING,
"Error getting child count", ex);
522 super.setDisplayName(this.baseName +
" (" + this.childCount +
")");
532 static class TypeNode
extends UpdatableCountTypeNode {
534 private final BlackboardArtifact.Type type;
544 TypeNode(BlackboardArtifact.Type type,
long filteringDSObjId) {
545 super(Children.create(
new ArtifactFactory(type, filteringDSObjId),
true),
546 Lookups.singleton(type.getDisplayName()),
547 type.getDisplayName(),
551 super.setName(type.getTypeName());
553 String iconPath = IconsUtil.getIconFilePath(type.getTypeID());
554 setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) ==
'/' ? iconPath.substring(1) : iconPath);
558 protected Sheet createSheet() {
559 Sheet sheet = super.createSheet();
560 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
561 if (sheetSet == null) {
562 sheetSet = Sheet.createPropertiesSet();
566 sheetSet.put(
new NodeProperty<>(NbBundle.getMessage(
this.getClass(),
"ArtifactTypeNode.createSheet.artType.name"),
567 NbBundle.getMessage(
this.getClass(),
"ArtifactTypeNode.createSheet.artType.displayName"),
568 NbBundle.getMessage(
this.getClass(),
"ArtifactTypeNode.createSheet.artType.desc"),
569 type.getDisplayName()));
571 sheetSet.put(
new NodeProperty<>(NbBundle.getMessage(
this.getClass(),
"ArtifactTypeNode.createSheet.childCnt.name"),
572 NbBundle.getMessage(
this.getClass(),
"ArtifactTypeNode.createSheet.childCnt.displayName"),
573 NbBundle.getMessage(
this.getClass(),
"ArtifactTypeNode.createSheet.childCnt.desc"),
580 public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
581 return visitor.visit(
this);
585 public boolean isLeafTypeNode() {
590 public String getItemType() {
591 return getClass().getName() + type.getDisplayName();
620 super(type.getTypeName());
625 private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
626 String eventType = evt.getPropertyName();
646 private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
656 if (refreshThrottler != null) {
670 List<? extends BlackboardArtifact> arts;
672 switch (this.type.getCategory()) {
674 case ANALYSIS_RESULT:
675 arts = (filteringDSObjId > 0)
681 arts = (filteringDSObjId > 0)
693 @SuppressWarnings(
"unchecked")
694 List<BlackboardArtifact> toRet = (List<BlackboardArtifact>) (List<?>) arts;
697 logger.log(Level.WARNING,
"Trying to access case when no case is open.", ex);
699 logger.log(Level.SEVERE,
"Couldn't get blackboard artifacts from database", ex);
701 return Collections.emptyList();
711 String eventType = evt.getPropertyName();
729 if (null != event && event.getBlackboardArtifactType().equals(type)) {
void registerForIngestModuleEvents()
final long filteringDSObjId
static synchronized IngestManager getInstance()
List< DataArtifact > getDataArtifacts(long dataSourceObjId, Integer artifactTypeID)
static final Set< IngestManager.IngestJobEvent > INGEST_JOB_EVENTS_OF_INTEREST
Blackboard getBlackboard()
static final Type TSK_KEYWORD_HIT
static final Type TSK_TL_EVENT
static final Type TSK_DATA_SOURCE_USAGE
static final Type TSK_INTERESTING_ARTIFACT_HIT
void unregisterEventListener()
void removeIngestJobEventListener(final PropertyChangeListener listener)
List< BlackboardArtifact > makeKeys()
final long filteringDSObjId
void addIngestJobEventListener(final PropertyChangeListener listener)
static final Type TSK_ACCOUNT
final UpdatableCountTypeNode node
final Set< BlackboardArtifact.Type > types
final Set< BlackboardArtifact.Type > applicableTypes
boolean isRefreshRequired(PropertyChangeEvent evt)
UpdatableCountTypeNode(Children children, Lookup lookup, String baseName, long filteringDSObjId, BlackboardArtifact.Type...types)
static final Type TSK_GEN_INFO
SleuthkitCase getSleuthkitCase()
final BlackboardArtifact.Type type
T visit(DataSourceFilesNode in)
static final Type TSK_HASHSET_HIT
long fetchChildCount(SleuthkitCase skCase)
static final Type TSK_ASSOCIATED_OBJECT
synchronized static Logger getLogger(String name)
static final Type TSK_EMAIL_MSG
static Case getCurrentCaseThrows()
static final Type TSK_MALWARE
boolean equals(Object obj)
Node createNodeForKey(BlackboardArtifact key)
static final Type TSK_INTERESTING_ITEM
List< AnalysisResult > getAnalysisResultsByType(int artifactTypeId)
static final Type TSK_INTERESTING_FILE_HIT