Autopsy  4.5.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
BlackboardArtifactNode.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2017 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 com.google.common.cache.Cache;
22 import com.google.common.cache.CacheBuilder;
23 import java.beans.PropertyChangeEvent;
24 import java.beans.PropertyChangeListener;
25 import java.text.MessageFormat;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.EnumSet;
29 import java.util.LinkedHashMap;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.concurrent.ExecutionException;
34 import java.util.concurrent.TimeUnit;
35 import java.util.logging.Level;
36 import java.util.stream.Collectors;
37 import javax.swing.Action;
38 import org.openide.nodes.Sheet;
39 import org.openide.util.Lookup;
40 import org.openide.util.NbBundle;
41 import org.openide.util.WeakListeners;
42 import org.openide.util.lookup.Lookups;
50 import static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked;
53 import org.sleuthkit.datamodel.AbstractFile;
54 import org.sleuthkit.datamodel.BlackboardArtifact;
55 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
56 import org.sleuthkit.datamodel.BlackboardAttribute;
57 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
58 import org.sleuthkit.datamodel.Content;
59 import org.sleuthkit.datamodel.Tag;
60 import org.sleuthkit.datamodel.TskCoreException;
61 
66 public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifact> {
67 
68  private static final Logger LOGGER = Logger.getLogger(BlackboardArtifactNode.class.getName());
74 
75  private static Cache<Long, Content> contentCache = CacheBuilder.newBuilder()
76  .expireAfterWrite(1, TimeUnit.MINUTES).
77  build();
78 
79  private final BlackboardArtifact artifact;
80  private Content associated = null;
81  private List<NodeProperty<? extends Object>> customProperties;
82 
83  /*
84  * Artifact types which should have the full unique path of the associated
85  * content as a property.
86  */
87  private static final Integer[] SHOW_UNIQUE_PATH = new Integer[]{
88  BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
89  BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(),
90  BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
91  BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID(),};
92 
93  // TODO (RC): This is an unattractive alternative to subclassing BlackboardArtifactNode,
94  // cut from the same cloth as the equally unattractive SHOW_UNIQUE_PATH array
95  // above. It should be removed when and if the subclassing is implemented.
96  private static final Integer[] SHOW_FILE_METADATA = new Integer[]{
97  BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),};
98 
99  private final PropertyChangeListener pcl = new PropertyChangeListener() {
100  @Override
101  public void propertyChange(PropertyChangeEvent evt) {
102  String eventType = evt.getPropertyName();
103  if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString())) {
105  if (event.getAddedTag().getArtifact().equals(artifact)) {
106  updateSheet();
107  }
108  } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString())) {
110  if (event.getDeletedTagInfo().getArtifactID() == artifact.getArtifactID()) {
111  updateSheet();
112  }
113  } else if (eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) {
115  if (event.getAddedTag().getContent().equals(associated)) {
116  updateSheet();
117  }
118  } else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) {
120  if (event.getDeletedTagInfo().getContentID() == associated.getId()) {
121  updateSheet();
122  }
123  } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
124  if (evt.getNewValue() == null) {
125  // case was closed. Remove listeners so that we don't get called with a stale case handle
126  removeListeners();
127  contentCache.invalidateAll();
128  }
129  }
130  }
131  };
132 
141  private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
142 
151  public BlackboardArtifactNode(BlackboardArtifact artifact, String iconPath) {
152  super(artifact, createLookup(artifact));
153 
154  this.artifact = artifact;
155 
156  // Look for associated Content i.e. the source file for the artifact
157  for (Content lookupContent : this.getLookup().lookupAll(Content.class)) {
158  if ((lookupContent != null) && (!(lookupContent instanceof BlackboardArtifact))) {
159  this.associated = lookupContent;
160  break;
161  }
162  }
163 
164  this.setName(Long.toString(artifact.getArtifactID()));
165  this.setDisplayName();
166  this.setIconBaseWithExtension(iconPath);
168  }
169 
176  public BlackboardArtifactNode(BlackboardArtifact artifact) {
177  this(artifact, ExtractedContent.getIconFilePath(artifact.getArtifactTypeID()));
178  }
179 
188  @Override
189  protected void finalize() throws Throwable {
190  super.finalize();
191  removeListeners();
192  }
193 
194  private void removeListeners() {
196  }
197 
198  public BlackboardArtifact getArtifact() {
199  return this.artifact;
200  }
201 
202  @Override
203  @NbBundle.Messages({
204  "BlackboardArtifactNode.getAction.errorTitle=Error getting actions",
205  "BlackboardArtifactNode.getAction.resultErrorMessage=There was a problem getting actions for the selected result."
206  + " The 'View Result in Timeline' action will not be available.",
207  "BlackboardArtifactNode.getAction.linkedFileMessage=There was a problem getting actions for the selected result. "
208  + " The 'View File in Timeline' action will not be available."})
209  public Action[] getActions(boolean context) {
210  List<Action> actionsList = new ArrayList<>();
211  actionsList.addAll(Arrays.asList(super.getActions(context)));
212 
213  //if this artifact has a time stamp add the action to view it in the timeline
214  try {
216  actionsList.add(new ViewArtifactInTimelineAction(artifact));
217  }
218  } catch (TskCoreException ex) {
219  LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting arttribute(s) from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
220  MessageNotifyUtil.Notify.error(Bundle.BlackboardArtifactNode_getAction_errorTitle(), Bundle.BlackboardArtifactNode_getAction_resultErrorMessage());
221  }
222 
223  // if the artifact links to another file, add an action to go to that file
224  try {
225  AbstractFile c = findLinked(artifact);
226  if (c != null) {
228  }
229  } catch (TskCoreException ex) {
230  LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting linked file from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
231  MessageNotifyUtil.Notify.error(Bundle.BlackboardArtifactNode_getAction_errorTitle(), Bundle.BlackboardArtifactNode_getAction_linkedFileMessage());
232  }
233 
234  //if this artifact has associated content, add the action to view the content in the timeline
235  AbstractFile file = getLookup().lookup(AbstractFile.class);
236  if (null != file) {
238  }
239 
240  return actionsList.toArray(new Action[actionsList.size()]);
241  }
242 
243  @NbBundle.Messages({"# {0} - artifactDisplayName", "BlackboardArtifactNode.displayName.artifact={0} Artifact"})
249  private void setDisplayName() {
250  String displayName = ""; //NON-NLS
251 
252  // If this is a node for a keyword hit on an artifact, we set the
253  // display name to be the artifact type name followed by " Artifact"
254  // e.g. "Messages Artifact".
255  if (artifact != null
256  && (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()
257  || artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID())) {
258  try {
259  for (BlackboardAttribute attribute : artifact.getAttributes()) {
260  if (attribute.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
261  BlackboardArtifact associatedArtifact = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong());
262  if (associatedArtifact != null) {
263  if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
264  artifact.getDisplayName();
265  } else {
266  displayName = NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.displayName.artifact", associatedArtifact.getDisplayName());
267  }
268  }
269  }
270  }
271  } catch (TskCoreException ex) {
272  // Do nothing since the display name will be set to the file name.
273  }
274  }
275 
276  if (displayName.isEmpty() && artifact != null) {
277  displayName = artifact.getName();
278  }
279 
280  this.setDisplayName(displayName);
281 
282  }
283 
289  public String getSourceName() {
290 
291  String srcName = "";
292  if (associated != null) {
293  srcName = associated.getName();
294  }
295  return srcName;
296  }
297 
298  @NbBundle.Messages({
299  "BlackboardArtifactNode.createSheet.artifactType.displayName=Artifact Type",
300  "BlackboardArtifactNode.createSheet.artifactType.name=Artifact Type",
301  "BlackboardArtifactNode.createSheet.artifactDetails.displayName=Artifact Details",
302  "BlackboardArtifactNode.createSheet.artifactDetails.name=Artifact Details",
303  "BlackboardArtifactNode.artifact.displayName=Artifact"})
304 
305  @Override
306  protected Sheet createSheet() {
307  Sheet s = super.createSheet();
308  Sheet.Set ss = s.get(Sheet.PROPERTIES);
309  if (ss == null) {
310  ss = Sheet.createPropertiesSet();
311  s.put(ss);
312  }
313  final String NO_DESCR = NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.noDesc.text");
314 
315  Map<String, Object> map = new LinkedHashMap<>();
316  fillPropertyMap(map, artifact);
317 
318  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.name"),
319  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.displayName"),
320  NO_DESCR,
321  this.getSourceName()));
322  if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
323  try {
324  BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
325  if (attribute != null) {
326  BlackboardArtifact associatedArtifact = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong());
327  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactType.name"),
328  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactType.displayName"),
329  NO_DESCR,
330  associatedArtifact.getDisplayName() + " " + NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.artifact.displayName")));
331  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactDetails.name"),
332  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactDetails.displayName"),
333  NO_DESCR,
334  associatedArtifact.getShortDescription()));
335  }
336  } catch (TskCoreException ex) {
337  // Do nothing since the display name will be set to the file name.
338  }
339  }
340 
341  for (Map.Entry<String, Object> entry : map.entrySet()) {
342  ss.put(new NodeProperty<>(entry.getKey(),
343  entry.getKey(),
344  NO_DESCR,
345  entry.getValue()));
346  }
347 
348  //append custom node properties
349  if (customProperties != null) {
350  for (NodeProperty<? extends Object> np : customProperties) {
351  ss.put(np);
352  }
353  }
354 
355  final int artifactTypeId = artifact.getArtifactTypeID();
356 
357  // If mismatch, add props for extension and file type
358  if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID()) {
359  String ext = ""; //NON-NLS
360  String actualMimeType = ""; //NON-NLS
361  if (associated instanceof AbstractFile) {
362  AbstractFile af = (AbstractFile) associated;
363  ext = af.getNameExtension();
364  actualMimeType = af.getMIMEType();
365  if (actualMimeType == null) {
366  actualMimeType = ""; //NON-NLS
367  }
368  }
369  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.ext.name"),
370  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.ext.displayName"),
371  NO_DESCR,
372  ext));
373  ss.put(new NodeProperty<>(
374  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.mimeType.name"),
375  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.mimeType.displayName"),
376  NO_DESCR,
377  actualMimeType));
378  }
379 
380  if (Arrays.asList(SHOW_UNIQUE_PATH).contains(artifactTypeId)) {
381  String sourcePath = ""; //NON-NLS
382  try {
383  sourcePath = associated.getUniquePath();
384  } catch (TskCoreException ex) {
385  LOGGER.log(Level.WARNING, "Failed to get unique path from: {0}", associated.getName()); //NON-NLS
386  }
387 
388  if (sourcePath.isEmpty() == false) {
389  ss.put(new NodeProperty<>(
390  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.filePath.name"),
391  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.filePath.displayName"),
392  NO_DESCR,
393  sourcePath));
394  }
395 
396  if (Arrays.asList(SHOW_FILE_METADATA).contains(artifactTypeId)) {
397  AbstractFile file = associated instanceof AbstractFile ? (AbstractFile) associated : null;
398  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileModifiedTime.name"),
399  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileModifiedTime.displayName"),
400  "",
401  file != null ? ContentUtils.getStringTime(file.getMtime(), file) : ""));
402  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.name"),
403  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.displayName"),
404  "",
405  file != null ? ContentUtils.getStringTime(file.getCtime(), file) : ""));
406  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.name"),
407  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.displayName"),
408  "",
409  file != null ? ContentUtils.getStringTime(file.getAtime(), file) : ""));
410  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.name"),
411  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.displayName"),
412  "",
413  file != null ? ContentUtils.getStringTime(file.getCrtime(), file) : ""));
414  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.name"),
415  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.displayName"),
416  "",
417  associated.getSize()));
418  }
419  } else {
420  String dataSourceStr = "";
421  try {
422  Content dataSource = associated.getDataSource();
423  if (dataSource != null) {
424  dataSourceStr = dataSource.getName();
425  } else {
426  dataSourceStr = getRootParentName();
427  }
428  } catch (TskCoreException ex) {
429  LOGGER.log(Level.WARNING, "Failed to get image name from {0}", associated.getName()); //NON-NLS
430  }
431 
432  if (dataSourceStr.isEmpty() == false) {
433  ss.put(new NodeProperty<>(
434  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.dataSrc.name"),
435  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.dataSrc.displayName"),
436  NO_DESCR,
437  dataSourceStr));
438  }
439  }
440 
441  // add properties for tags
442  List<Tag> tags = new ArrayList<>();
443  try {
446  } catch (TskCoreException ex) {
447  LOGGER.log(Level.SEVERE, "Failed to get tags for artifact " + artifact.getDisplayName(), ex);
448  }
449  ss.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "BlackboardArtifactNode.createSheet.tags.displayName"),
450  NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", "))));
451 
452  return s;
453  }
454 
455  private void updateSheet() {
456  this.setSheet(createSheet());
457  }
458 
459  private String getRootParentName() {
460  String parentName = associated.getName();
461  Content parent = associated;
462  try {
463  while ((parent = parent.getParent()) != null) {
464  parentName = parent.getName();
465  }
466  } catch (TskCoreException ex) {
467  LOGGER.log(Level.WARNING, "Failed to get parent name from {0}", associated.getName()); //NON-NLS
468  return "";
469  }
470  return parentName;
471  }
472 
480  if (null == customProperties) {
481  //lazy create the list
482  customProperties = new ArrayList<>();
483  }
484  customProperties.add(np);
485  }
486 
494  @SuppressWarnings("deprecation")
495  private void fillPropertyMap(Map<String, Object> map, BlackboardArtifact artifact) {
496  try {
497  for (BlackboardAttribute attribute : artifact.getAttributes()) {
498  final int attributeTypeID = attribute.getAttributeType().getTypeID();
499  //skip some internal attributes that user shouldn't see
500  if (attributeTypeID == ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()
501  || attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()
502  || attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()
503  || attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()
504  || attributeTypeID == ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE.getTypeID()) {
505  } else if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) {
506  addEmailMsgProperty(map, attribute);
507  } else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
508  map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
509  } else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID()
510  && attributeTypeID == ATTRIBUTE_TYPE.TSK_TEXT.getTypeID()) {
511  /*
512  * This was added because the RegRipper output would often
513  * cause the UI to get a black line accross it and hang if
514  * you hovered over large output or selected it. This
515  * reduces the amount of data in the table. Could consider
516  * doing this for all fields in the UI.
517  */
518  String value = attribute.getDisplayString();
519  if (value.length() > 512) {
520  value = value.substring(0, 512);
521  }
522  map.put(attribute.getAttributeType().getDisplayName(), value);
523  } else {
524  map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
525  }
526  }
527  } catch (TskCoreException ex) {
528  LOGGER.log(Level.SEVERE, "Getting attributes failed", ex); //NON-NLS
529  }
530  }
531 
539  private void addEmailMsgProperty(Map<String, Object> map, BlackboardAttribute attribute) {
540 
541  final int attributeTypeID = attribute.getAttributeType().getTypeID();
542 
543  // Skip certain Email msg attributes
544  if (attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID()
545  || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_HTML.getTypeID()
546  || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_RTF.getTypeID()
547  || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_BCC.getTypeID()
548  || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CC.getTypeID()
549  || attributeTypeID == ATTRIBUTE_TYPE.TSK_HEADERS.getTypeID()) {
550 
551  // do nothing
552  } else if (attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN.getTypeID()) {
553 
554  String value = attribute.getDisplayString();
555  if (value.length() > 160) {
556  value = value.substring(0, 160) + "...";
557  }
558  map.put(attribute.getAttributeType().getDisplayName(), value);
559  } else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
560  map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
561  } else {
562  map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
563  }
564 
565  }
566 
567  @Override
568  public <T> T accept(DisplayableItemNodeVisitor<T> v) {
569  return v.visit(this);
570  }
571 
580  private static Lookup createLookup(BlackboardArtifact artifact) {
581  // Add the content the artifact is associated with
582  final long objectID = artifact.getObjectID();
583  try {
584  Content content = contentCache.get(objectID, () -> artifact.getSleuthkitCase().getContentById(objectID));
585  if (content == null) {
586  return Lookups.fixed(artifact);
587  } else {
588  return Lookups.fixed(artifact, content);
589  }
590  } catch (ExecutionException ex) {
591  LOGGER.log(Level.WARNING, "Getting associated content for artifact failed", ex); //NON-NLS
592  return Lookups.fixed(artifact);
593  }
594  }
595 
596  @Override
597  public boolean isLeafTypeNode() {
598  return true;
599  }
600 
601  @Override
602  public String getItemType() {
603  return getClass().getName();
604  }
605 
606  @Override
607  public <T> T accept(ContentNodeVisitor<T> v) {
608  return v.visit(this);
609  }
610 }
void fillPropertyMap(Map< String, Object > map, BlackboardArtifact artifact)
static String getStringTime(long epochSeconds, TimeZone tzone)
BlackboardArtifactNode(BlackboardArtifact artifact, String iconPath)
List< ContentTag > getContentTagsByContent(Content content)
static Lookup createLookup(BlackboardArtifact artifact)
static ViewFileInTimelineAction createViewSourceFileAction(AbstractFile file)
void addEmailMsgProperty(Map< String, Object > map, BlackboardAttribute attribute)
static void error(String title, String message)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:419
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:464
static ViewFileInTimelineAction createViewFileAction(AbstractFile file)
List< BlackboardArtifactTag > getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact)

Copyright © 2012-2016 Basis Technology. Generated on: Tue Feb 20 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.