Autopsy  4.17.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExtractedContent.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2020 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.datamodel;
20 
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.Comparator;
26 import java.util.EnumSet;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Set;
30 import java.util.logging.Level;
31 import org.openide.nodes.ChildFactory;
32 import org.openide.nodes.Children;
33 import org.openide.nodes.Node;
34 import org.openide.nodes.Sheet;
35 import org.openide.util.NbBundle;
36 import org.openide.util.lookup.Lookups;
43 import org.sleuthkit.datamodel.Blackboard;
44 import org.sleuthkit.datamodel.BlackboardArtifact;
45 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT;
46 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
47 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_TL_EVENT;
48 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE;
49 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG;
50 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO;
51 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT;
52 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT;
53 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT;
54 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT;
55 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE;
56 import org.sleuthkit.datamodel.SleuthkitCase;
57 import org.sleuthkit.datamodel.TskCoreException;
59 
64 public class ExtractedContent implements AutopsyVisitableItem {
65 
67  public static final String NAME = NbBundle.getMessage(RootNode.class, "ExtractedContentNode.name.text");
68  private final long filteringDSObjId; // 0 if not filtering/grouping by data source
69  private SleuthkitCase skCase; // set to null after case has been closed
70  private Blackboard blackboard;
71 
77  public ExtractedContent(SleuthkitCase skCase) {
78  this(skCase, 0);
79  }
80 
87  public ExtractedContent(SleuthkitCase skCase, long objId) {
88  this.skCase = skCase;
89  this.filteringDSObjId = objId;
90  this.blackboard = skCase.getBlackboard();
91  }
92 
93  @Override
94  public <T> T accept(AutopsyItemVisitor<T> visitor) {
95  return visitor.visit(this);
96  }
97 
98  public SleuthkitCase getSleuthkitCase() {
99  return skCase;
100  }
101 
102  public class RootNode extends DisplayableItemNode {
103 
104  public RootNode(SleuthkitCase skCase) {
105  super(Children.create(new TypeFactory(), true), Lookups.singleton(NAME));
106  super.setName(NAME);
107  super.setDisplayName(NAME);
108  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/extracted_content.png"); //NON-NLS
109  }
110 
111  @Override
112  public boolean isLeafTypeNode() {
113  return false;
114  }
115 
116  @Override
117  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
118  return visitor.visit(this);
119  }
120 
121  @Override
122  protected Sheet createSheet() {
123  Sheet sheet = super.createSheet();
124  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
125  if (sheetSet == null) {
126  sheetSet = Sheet.createPropertiesSet();
127  sheet.put(sheetSet);
128  }
129 
130  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ExtractedContentNode.createSheet.name.name"),
131  NbBundle.getMessage(this.getClass(), "ExtractedContentNode.createSheet.name.displayName"),
132  NbBundle.getMessage(this.getClass(), "ExtractedContentNode.createSheet.name.desc"),
133  NAME));
134  return sheet;
135  }
136 
137  @Override
138  public String getItemType() {
139  return getClass().getName();
140  }
141  }
142 
148  private class TypeFactory extends ChildFactory.Detachable<BlackboardArtifact.Type> implements RefreshThrottler.Refresher {
149 
150  private final ArrayList<BlackboardArtifact.Type> doNotShow = new ArrayList<>();
151  // maps the artifact type to its child node
152  private final HashMap<BlackboardArtifact.Type, TypeNode> typeNodeList = new HashMap<>();
153 
160 
161  @SuppressWarnings("deprecation")
162  TypeFactory() {
163  super();
164 
165  // these are shown in other parts of the UI
166  doNotShow.add(new BlackboardArtifact.Type(TSK_GEN_INFO));
167  doNotShow.add(new BlackboardArtifact.Type(TSK_EMAIL_MSG));
168  doNotShow.add(new BlackboardArtifact.Type(TSK_HASHSET_HIT));
169  doNotShow.add(new BlackboardArtifact.Type(TSK_KEYWORD_HIT));
170  doNotShow.add(new BlackboardArtifact.Type(TSK_INTERESTING_FILE_HIT));
171  doNotShow.add(new BlackboardArtifact.Type(TSK_INTERESTING_ARTIFACT_HIT));
172  doNotShow.add(new BlackboardArtifact.Type(TSK_ACCOUNT));
173  doNotShow.add(new BlackboardArtifact.Type(TSK_DATA_SOURCE_USAGE));
174  doNotShow.add(new BlackboardArtifact.Type(TSK_DOWNLOAD_SOURCE));
175  doNotShow.add(new BlackboardArtifact.Type(TSK_TL_EVENT));
176 
177  //This is not meant to be shown in the UI at all. It is more of a meta artifact.
178  doNotShow.add(new BlackboardArtifact.Type(TSK_ASSOCIATED_OBJECT));
179  }
180 
181  private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
182  String eventType = evt.getPropertyName();
183  if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
184  // case was closed. Remove listeners so that we don't get called with a stale case handle
185  if (evt.getNewValue() == null) {
186  removeNotify();
187  skCase = null;
188  }
189  } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
190  || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
196  try {
198  refresh(false);
199  } catch (NoCurrentCaseException notUsed) {
203  }
204  }
205  };
206 
207  @Override
208  protected void addNotify() {
209  refreshThrottler.registerForIngestModuleEvents();
212  }
213 
214  @Override
215  protected void removeNotify() {
216  refreshThrottler.unregisterEventListener();
219  typeNodeList.clear();
220  }
221 
222  @Override
223  protected boolean createKeys(List<BlackboardArtifact.Type> list) {
224  if (skCase != null) {
225  try {
226  List<BlackboardArtifact.Type> types = (filteringDSObjId > 0)
227  ? blackboard.getArtifactTypesInUse(filteringDSObjId)
228  : skCase.getArtifactTypesInUse();
229 
230  types.removeAll(doNotShow);
231  Collections.sort(types,
232  new Comparator<BlackboardArtifact.Type>() {
233  @Override
234  public int compare(BlackboardArtifact.Type a, BlackboardArtifact.Type b) {
235  return a.getDisplayName().compareTo(b.getDisplayName());
236  }
237  });
238  list.addAll(types);
239 
240  // the create node method will get called only for new types
241  // refresh the counts if we already created them from a previous update
242  for (BlackboardArtifact.Type art : types) {
243  TypeNode node = typeNodeList.get(art);
244  if (node != null) {
245  node.updateDisplayName();
246  }
247  }
248  } catch (TskCoreException ex) {
249  Logger.getLogger(TypeFactory.class.getName()).log(Level.SEVERE, "Error getting list of artifacts in use: " + ex.getLocalizedMessage()); //NON-NLS
250  }
251  }
252  return true;
253  }
254 
255  @Override
256  protected Node createNodeForKey(BlackboardArtifact.Type key) {
257  TypeNode node = new TypeNode(key);
258  typeNodeList.put(key, node);
259  return node;
260  }
261 
262  @Override
263  public void refresh() {
264  refresh(false);
265  }
266 
267  @Override
268  public boolean isRefreshRequired(PropertyChangeEvent evt) {
269  String eventType = evt.getPropertyName();
270  if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
276  try {
283  final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue();
284  if (null != event && !(this.doNotShow.contains(event.getBlackboardArtifactType()))) {
285  return true;
286  }
287  } catch (NoCurrentCaseException notUsed) {
291  }
292  }
293  return false;
294  }
295  }
296 
303  public class TypeNode extends DisplayableItemNode {
304 
305  private final BlackboardArtifact.Type type;
306  private long childCount = 0;
307 
308  TypeNode(BlackboardArtifact.Type type) {
309  super(Children.create(new ArtifactFactory(type), true), Lookups.singleton(type.getDisplayName()));
310  super.setName(type.getTypeName());
311  this.type = type;
312  String iconPath = IconsUtil.getIconFilePath(type.getTypeID());
313  setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) == '/' ? iconPath.substring(1) : iconPath);
314  updateDisplayName();
315  }
316 
317  final void updateDisplayName() {
318  if (skCase == null) {
319  return;
320  }
321 
322  // NOTE: This completely destroys our lazy-loading ideal
323  // a performance increase might be had by adding a
324  // "getBlackboardArtifactCount()" method to skCase
325  try {
326  this.childCount = (filteringDSObjId > 0)
327  ? blackboard.getArtifactsCount(type.getTypeID(), filteringDSObjId)
328  : skCase.getBlackboardArtifactsTypeCount(type.getTypeID());
329  } catch (TskCoreException ex) {
330  Logger.getLogger(TypeNode.class.getName())
331  .log(Level.WARNING, "Error getting child count", ex); //NON-NLS
332  }
333  super.setDisplayName(type.getDisplayName() + " \u200E(\u200E" + childCount + ")\u200E");
334  }
335 
336  @Override
337  protected Sheet createSheet() {
338  Sheet sheet = super.createSheet();
339  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
340  if (sheetSet == null) {
341  sheetSet = Sheet.createPropertiesSet();
342  sheet.put(sheetSet);
343  }
344 
345  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.name"),
346  NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.displayName"),
347  NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.desc"),
348  type.getDisplayName()));
349 
350  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.name"),
351  NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.displayName"),
352  NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.desc"),
353  childCount));
354 
355  return sheet;
356  }
357 
358  @Override
359  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
360  return visitor.visit(this);
361  }
362 
363  @Override
364  public boolean isLeafTypeNode() {
365  return true;
366  }
367 
368  @Override
369  public String getItemType() {
370  return getClass().getName() + type.getDisplayName();
371  }
372  }
373 
377  private class ArtifactFactory extends BaseChildFactory<BlackboardArtifact> implements RefreshThrottler.Refresher {
378 
379  private final BlackboardArtifact.Type type;
380 
386  private final RefreshThrottler refreshThrottler = new RefreshThrottler(this);
387 
388  ArtifactFactory(BlackboardArtifact.Type type) {
389  super(type.getTypeName());
390  this.type = type;
391  }
392 
393  private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
394  String eventType = evt.getPropertyName();
395  if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
396  || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
403  try {
405  refresh(false);
406  } catch (NoCurrentCaseException notUsed) {
410  }
411  }
412  };
413 
414  @Override
415  protected void onAdd() {
416  refreshThrottler.registerForIngestModuleEvents();
418  }
419 
420  @Override
421  protected void onRemove() {
422  refreshThrottler.unregisterEventListener();
424  }
425 
426  @Override
427  protected Node createNodeForKey(BlackboardArtifact key) {
428  return new BlackboardArtifactNode(key);
429  }
430 
431  @Override
432  protected List<BlackboardArtifact> makeKeys() {
433  if (skCase != null) {
434  try {
435  List<BlackboardArtifact> arts;
436  if (filteringDSObjId > 0) {
437  arts = blackboard.getArtifacts(type.getTypeID(), filteringDSObjId);
438  } else {
439  arts = skCase.getBlackboardArtifacts(type.getTypeID());
440  }
441  for (BlackboardArtifact art : arts) {
442  //Cache attributes while we are off the EDT.
443  //See JIRA-5969
444  art.getAttributes();
445  }
446  return arts;
447  } catch (TskCoreException ex) {
448  Logger.getLogger(ArtifactFactory.class.getName()).log(Level.SEVERE, "Couldn't get blackboard artifacts from database", ex); //NON-NLS
449  }
450  }
451  return Collections.emptyList();
452  }
453 
454  @Override
455  public void refresh() {
456  refresh(false);
457  }
458 
459  @Override
460  public boolean isRefreshRequired(PropertyChangeEvent evt) {
461  String eventType = evt.getPropertyName();
462  if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
463 
470  try {
478  final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue();
479  if (null != event && event.getBlackboardArtifactType().equals(type)) {
480  return true;
481  }
482 
483  } catch (NoCurrentCaseException notUsed) {
487  }
488  }
489  return false;
490  }
491  }
492 }
boolean createKeys(List< BlackboardArtifact.Type > list)
static synchronized IngestManager getInstance()
final ArrayList< BlackboardArtifact.Type > doNotShow
void removeIngestJobEventListener(final PropertyChangeListener listener)
void addIngestJobEventListener(final PropertyChangeListener listener)
ExtractedContent(SleuthkitCase skCase, long objId)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:491
final HashMap< BlackboardArtifact.Type, TypeNode > typeNodeList
static final Set< IngestManager.IngestJobEvent > INGEST_JOB_EVENTS_OF_INTEREST
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:536

Copyright © 2012-2021 Basis Technology. Generated on: Tue Jan 19 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.