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