Autopsy  4.15.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;
58 
63 public class ExtractedContent implements AutopsyVisitableItem {
64 
66  public static final String NAME = NbBundle.getMessage(RootNode.class, "ExtractedContentNode.name.text");
67  private final long filteringDSObjId; // 0 if not filtering/grouping by data source
68  private SleuthkitCase skCase; // set to null after case has been closed
69  private Blackboard blackboard;
70 
76  public ExtractedContent(SleuthkitCase skCase) {
77  this(skCase, 0);
78  }
79 
86  public ExtractedContent(SleuthkitCase skCase, long objId) {
87  this.skCase = skCase;
88  this.filteringDSObjId = objId;
89  this.blackboard = skCase.getBlackboard();
90  }
91 
92  @Override
93  public <T> T accept(AutopsyItemVisitor<T> visitor) {
94  return visitor.visit(this);
95  }
96 
97  public SleuthkitCase getSleuthkitCase() {
98  return skCase;
99  }
100 
101  public class RootNode extends DisplayableItemNode {
102 
103  public RootNode(SleuthkitCase skCase) {
104  super(Children.create(new TypeFactory(), true), Lookups.singleton(NAME));
105  super.setName(NAME);
106  super.setDisplayName(NAME);
107  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/extracted_content.png"); //NON-NLS
108  }
109 
110  @Override
111  public boolean isLeafTypeNode() {
112  return false;
113  }
114 
115  @Override
116  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
117  return visitor.visit(this);
118  }
119 
120  @Override
121  protected Sheet createSheet() {
122  Sheet sheet = super.createSheet();
123  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
124  if (sheetSet == null) {
125  sheetSet = Sheet.createPropertiesSet();
126  sheet.put(sheetSet);
127  }
128 
129  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ExtractedContentNode.createSheet.name.name"),
130  NbBundle.getMessage(this.getClass(), "ExtractedContentNode.createSheet.name.displayName"),
131  NbBundle.getMessage(this.getClass(), "ExtractedContentNode.createSheet.name.desc"),
132  NAME));
133  return sheet;
134  }
135 
136  @Override
137  public String getItemType() {
138  return getClass().getName();
139  }
140  }
141 
147  private class TypeFactory extends ChildFactory.Detachable<BlackboardArtifact.Type> implements RefreshThrottler.Refresher {
148 
149  private final ArrayList<BlackboardArtifact.Type> doNotShow = new ArrayList<>();
150  // maps the artifact type to its child node
151  private final HashMap<BlackboardArtifact.Type, TypeNode> typeNodeList = new HashMap<>();
152 
158  private final RefreshThrottler refreshThrottler = new RefreshThrottler(this);
159 
160  @SuppressWarnings("deprecation")
161  TypeFactory() {
162  super();
163 
164  // these are shown in other parts of the UI
165  doNotShow.add(new BlackboardArtifact.Type(TSK_GEN_INFO));
166  doNotShow.add(new BlackboardArtifact.Type(TSK_EMAIL_MSG));
167  doNotShow.add(new BlackboardArtifact.Type(TSK_HASHSET_HIT));
168  doNotShow.add(new BlackboardArtifact.Type(TSK_KEYWORD_HIT));
169  doNotShow.add(new BlackboardArtifact.Type(TSK_INTERESTING_FILE_HIT));
170  doNotShow.add(new BlackboardArtifact.Type(TSK_INTERESTING_ARTIFACT_HIT));
171  doNotShow.add(new BlackboardArtifact.Type(TSK_ACCOUNT));
172  doNotShow.add(new BlackboardArtifact.Type(TSK_DATA_SOURCE_USAGE));
173  doNotShow.add(new BlackboardArtifact.Type(TSK_DOWNLOAD_SOURCE));
174  doNotShow.add(new BlackboardArtifact.Type(TSK_TL_EVENT));
175 
176  //This is not meant to be shown in the UI at all. It is more of a meta artifact.
177  doNotShow.add(new BlackboardArtifact.Type(TSK_ASSOCIATED_OBJECT));
178  }
179 
180  private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
181  String eventType = evt.getPropertyName();
182  if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
183  // case was closed. Remove listeners so that we don't get called with a stale case handle
184  if (evt.getNewValue() == null) {
185  removeNotify();
186  skCase = null;
187  }
188  } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
189  || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
195  try {
197  refresh(false);
198  } catch (NoCurrentCaseException notUsed) {
202  }
203  }
204  };
205 
206  @Override
207  protected void addNotify() {
208  refreshThrottler.registerForIngestModuleEvents();
211  }
212 
213  @Override
214  protected void removeNotify() {
215  refreshThrottler.unregisterEventListener();
218  typeNodeList.clear();
219  }
220 
221  @Override
222  protected boolean createKeys(List<BlackboardArtifact.Type> list) {
223  if (skCase != null) {
224  try {
225  List<BlackboardArtifact.Type> types = (filteringDSObjId > 0)
226  ? blackboard.getArtifactTypesInUse(filteringDSObjId)
227  : skCase.getArtifactTypesInUse();
228 
229  types.removeAll(doNotShow);
230  Collections.sort(types,
231  new Comparator<BlackboardArtifact.Type>() {
232  @Override
233  public int compare(BlackboardArtifact.Type a, BlackboardArtifact.Type b) {
234  return a.getDisplayName().compareTo(b.getDisplayName());
235  }
236  });
237  list.addAll(types);
238 
239  // the create node method will get called only for new types
240  // refresh the counts if we already created them from a previous update
241  for (BlackboardArtifact.Type art : types) {
242  TypeNode node = typeNodeList.get(art);
243  if (node != null) {
244  node.updateDisplayName();
245  }
246  }
247  } catch (TskCoreException ex) {
248  Logger.getLogger(TypeFactory.class.getName()).log(Level.SEVERE, "Error getting list of artifacts in use: " + ex.getLocalizedMessage()); //NON-NLS
249  }
250  }
251  return true;
252  }
253 
254  @Override
255  protected Node createNodeForKey(BlackboardArtifact.Type key) {
256  TypeNode node = new TypeNode(key);
257  typeNodeList.put(key, node);
258  return node;
259  }
260 
261  @Override
262  public void refresh() {
263  refresh(false);
264  }
265 
266  @Override
267  public boolean isRefreshRequired(PropertyChangeEvent evt) {
268  String eventType = evt.getPropertyName();
269  if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
275  try {
282  final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue();
283  if (null != event && !(this.doNotShow.contains(event.getBlackboardArtifactType()))) {
284  return true;
285  }
286  } catch (NoCurrentCaseException notUsed) {
290  }
291  }
292  return false;
293  }
294  }
295 
302  public class TypeNode extends DisplayableItemNode {
303 
304  private final BlackboardArtifact.Type type;
305  private long childCount = 0;
306 
307  TypeNode(BlackboardArtifact.Type type) {
308  super(Children.create(new ArtifactFactory(type), true), Lookups.singleton(type.getDisplayName()));
309  super.setName(type.getTypeName());
310  this.type = type;
311  String iconPath = IconsUtil.getIconFilePath(type.getTypeID());
312  setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) == '/' ? iconPath.substring(1) : iconPath);
313  updateDisplayName();
314  }
315 
316  final void updateDisplayName() {
317  if (skCase == null) {
318  return;
319  }
320 
321  // NOTE: This completely destroys our lazy-loading ideal
322  // a performance increase might be had by adding a
323  // "getBlackboardArtifactCount()" method to skCase
324  try {
325  this.childCount = (filteringDSObjId > 0)
326  ? blackboard.getArtifactsCount(type.getTypeID(), filteringDSObjId)
327  : skCase.getBlackboardArtifactsTypeCount(type.getTypeID());
328  } catch (TskCoreException ex) {
329  Logger.getLogger(TypeNode.class.getName())
330  .log(Level.WARNING, "Error getting child count", ex); //NON-NLS
331  }
332  super.setDisplayName(type.getDisplayName() + " \u200E(\u200E" + childCount + ")\u200E");
333  }
334 
335  @Override
336  protected Sheet createSheet() {
337  Sheet sheet = super.createSheet();
338  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
339  if (sheetSet == null) {
340  sheetSet = Sheet.createPropertiesSet();
341  sheet.put(sheetSet);
342  }
343 
344  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.name"),
345  NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.displayName"),
346  NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.artType.desc"),
347  type.getDisplayName()));
348 
349  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.name"),
350  NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.displayName"),
351  NbBundle.getMessage(this.getClass(), "ArtifactTypeNode.createSheet.childCnt.desc"),
352  childCount));
353 
354  return sheet;
355  }
356 
357  @Override
358  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
359  return visitor.visit(this);
360  }
361 
362  @Override
363  public boolean isLeafTypeNode() {
364  return true;
365  }
366 
367  @Override
368  public String getItemType() {
369  return getClass().getName() + type.getDisplayName();
370  }
371  }
372 
376  private class ArtifactFactory extends BaseChildFactory<BlackboardArtifact> implements RefreshThrottler.Refresher {
377 
378  private final BlackboardArtifact.Type type;
379 
385  private final RefreshThrottler refreshThrottler = new RefreshThrottler(this);
386 
387  ArtifactFactory(BlackboardArtifact.Type type) {
388  super(type.getTypeName());
389  this.type = type;
390  }
391 
392  private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
393  String eventType = evt.getPropertyName();
394  if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
395  || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
402  try {
404  refresh(false);
405  } catch (NoCurrentCaseException notUsed) {
409  }
410  }
411  };
412 
413  @Override
414  protected void onAdd() {
415  refreshThrottler.registerForIngestModuleEvents();
417  }
418 
419  @Override
420  protected void onRemove() {
421  refreshThrottler.unregisterEventListener();
423  }
424 
425  @Override
426  protected Node createNodeForKey(BlackboardArtifact key) {
427  return new BlackboardArtifactNode(key);
428  }
429 
430  @Override
431  protected List<BlackboardArtifact> makeKeys() {
432  if (skCase != null) {
433  try {
434  List<BlackboardArtifact> arts;
435  if (filteringDSObjId > 0) {
436  arts = blackboard.getArtifacts(type.getTypeID(), filteringDSObjId);
437  } else {
438  arts = skCase.getBlackboardArtifacts(type.getTypeID());
439  }
440  for (BlackboardArtifact art : arts) {
441  //Cache attributes while we are off the EDT.
442  //See JIRA-5969
443  art.getAttributes();
444  }
445  return arts;
446  } catch (TskCoreException ex) {
447  Logger.getLogger(ArtifactFactory.class.getName()).log(Level.SEVERE, "Couldn't get blackboard artifacts from database", ex); //NON-NLS
448  }
449  }
450  return Collections.emptyList();
451  }
452 
453  @Override
454  public void refresh() {
455  refresh(false);
456  }
457 
458  @Override
459  public boolean isRefreshRequired(PropertyChangeEvent evt) {
460  String eventType = evt.getPropertyName();
461  if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
462 
469  try {
477  final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue();
478  if (null != event && event.getBlackboardArtifactType().equals(type)) {
479  return true;
480  }
481 
482  } catch (NoCurrentCaseException notUsed) {
486  }
487  }
488  return false;
489  }
490  }
491 }
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-2020 Basis Technology. Generated on: Mon Jul 6 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.