Autopsy  4.6.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-2018 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.MissingResourceException;
33 import java.util.Set;
34 import java.util.concurrent.ExecutionException;
35 import java.util.concurrent.TimeUnit;
36 import java.util.logging.Level;
37 import java.util.stream.Collectors;
38 import javax.swing.Action;
39 import org.apache.commons.lang3.StringUtils;
40 import org.openide.nodes.Sheet;
41 import org.openide.util.Lookup;
42 import org.openide.util.NbBundle;
43 import org.openide.util.WeakListeners;
44 import org.openide.util.lookup.Lookups;
53 import static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked;
56 import org.sleuthkit.datamodel.AbstractFile;
57 import org.sleuthkit.datamodel.BlackboardArtifact;
58 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
59 import org.sleuthkit.datamodel.BlackboardAttribute;
60 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
61 import org.sleuthkit.datamodel.Content;
62 import org.sleuthkit.datamodel.Tag;
63 import org.sleuthkit.datamodel.TskCoreException;
64 
69 public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifact> {
70 
71  private static final Logger LOGGER = Logger.getLogger(BlackboardArtifactNode.class.getName());
77 
78  private static Cache<Long, Content> contentCache = CacheBuilder.newBuilder()
79  .expireAfterWrite(1, TimeUnit.MINUTES).
80  build();
81 
82  private final BlackboardArtifact artifact;
83  private Content associated = null;
84 
85  private List<NodeProperty<? extends Object>> customProperties;
86 
87  private final static String NO_DESCR = NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.noDesc.text");
88 
89 
90  /*
91  * Artifact types which should have the full unique path of the associated
92  * content as a property.
93  */
94  private static final Integer[] SHOW_UNIQUE_PATH = new Integer[]{
95  BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
96  BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(),
97  BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
98  BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID(),};
99 
100  // TODO (RC): This is an unattractive alternative to subclassing BlackboardArtifactNode,
101  // cut from the same cloth as the equally unattractive SHOW_UNIQUE_PATH array
102  // above. It should be removed when and if the subclassing is implemented.
103  private static final Integer[] SHOW_FILE_METADATA = new Integer[]{
104  BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),};
105 
106  private final PropertyChangeListener pcl = new PropertyChangeListener() {
107  @Override
108  public void propertyChange(PropertyChangeEvent evt) {
109  String eventType = evt.getPropertyName();
110  if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString())) {
112  if (event.getAddedTag().getArtifact().equals(artifact)) {
113  updateSheet();
114  }
115  } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString())) {
117  if (event.getDeletedTagInfo().getArtifactID() == artifact.getArtifactID()) {
118  updateSheet();
119  }
120  } else if (eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) {
122  if (event.getAddedTag().getContent().equals(associated)) {
123  updateSheet();
124  }
125  } else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) {
127  if (event.getDeletedTagInfo().getContentID() == associated.getId()) {
128  updateSheet();
129  }
130  } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
131  if (evt.getNewValue() == null) {
132  // case was closed. Remove listeners so that we don't get called with a stale case handle
133  removeListeners();
134  contentCache.invalidateAll();
135  }
136  }
137  }
138  };
139 
148  private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
149 
158  public BlackboardArtifactNode(BlackboardArtifact artifact, String iconPath) {
159  super(artifact, createLookup(artifact));
160 
161  this.artifact = artifact;
162 
163  // Look for associated Content i.e. the source file for the artifact
164  for (Content lookupContent : this.getLookup().lookupAll(Content.class)) {
165  if ((lookupContent != null) && (!(lookupContent instanceof BlackboardArtifact))) {
166  this.associated = lookupContent;
167  break;
168  }
169  }
170 
171  this.setName(Long.toString(artifact.getArtifactID()));
172  this.setDisplayName();
173  this.setIconBaseWithExtension(iconPath);
175  }
176 
183  public BlackboardArtifactNode(BlackboardArtifact artifact) {
184  this(artifact, ExtractedContent.getIconFilePath(artifact.getArtifactTypeID()));
185  }
186 
196  @Override
197  protected void finalize() throws Throwable {
198  super.finalize();
199  removeListeners();
200  }
201 
202  private void removeListeners() {
204  }
205 
206  public BlackboardArtifact getArtifact() {
207  return this.artifact;
208  }
209 
210  @Override
211  @NbBundle.Messages({
212  "BlackboardArtifactNode.getAction.errorTitle=Error getting actions",
213  "BlackboardArtifactNode.getAction.resultErrorMessage=There was a problem getting actions for the selected result."
214  + " The 'View Result in Timeline' action will not be available.",
215  "BlackboardArtifactNode.getAction.linkedFileMessage=There was a problem getting actions for the selected result. "
216  + " The 'View File in Timeline' action will not be available."})
217  public Action[] getActions(boolean context) {
218  List<Action> actionsList = new ArrayList<>();
219  actionsList.addAll(Arrays.asList(super.getActions(context)));
220 
221  //if this artifact has a time stamp add the action to view it in the timeline
222  try {
224  actionsList.add(new ViewArtifactInTimelineAction(artifact));
225  }
226  } catch (TskCoreException ex) {
227  LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting arttribute(s) from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
228  MessageNotifyUtil.Notify.error(Bundle.BlackboardArtifactNode_getAction_errorTitle(), Bundle.BlackboardArtifactNode_getAction_resultErrorMessage());
229  }
230 
231  // if the artifact links to another file, add an action to go to that file
232  try {
233  AbstractFile c = findLinked(artifact);
234  if (c != null) {
236  }
237  } catch (TskCoreException ex) {
238  LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting linked file from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
239  MessageNotifyUtil.Notify.error(Bundle.BlackboardArtifactNode_getAction_errorTitle(), Bundle.BlackboardArtifactNode_getAction_linkedFileMessage());
240  }
241 
242  //if this artifact has associated content, add the action to view the content in the timeline
243  AbstractFile file = getLookup().lookup(AbstractFile.class);
244  if (null != file) {
246  }
247 
248  return actionsList.toArray(new Action[actionsList.size()]);
249  }
250 
251  @NbBundle.Messages({"# {0} - artifactDisplayName", "BlackboardArtifactNode.displayName.artifact={0} Artifact"})
257  private void setDisplayName() {
258  String displayName = ""; //NON-NLS
259 
260  // If this is a node for a keyword hit on an artifact, we set the
261  // display name to be the artifact type name followed by " Artifact"
262  // e.g. "Messages Artifact".
263  if (artifact != null
264  && (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()
265  || artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID())) {
266  try {
267  for (BlackboardAttribute attribute : artifact.getAttributes()) {
268  if (attribute.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
269  BlackboardArtifact associatedArtifact = Case.getOpenCase().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong());
270  if (associatedArtifact != null) {
271  if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
272  artifact.getDisplayName();
273  } else {
274  displayName = NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.displayName.artifact", associatedArtifact.getDisplayName());
275  }
276  }
277  }
278  }
279  } catch (TskCoreException | NoCurrentCaseException ex) {
280  // Do nothing since the display name will be set to the file name.
281  }
282  }
283 
284  if (displayName.isEmpty() && artifact != null) {
285  displayName = artifact.getName();
286  }
287 
288  this.setDisplayName(displayName);
289 
290  }
291 
297  public String getSourceName() {
298 
299  String srcName = "";
300  if (associated != null) {
301  srcName = associated.getName();
302  }
303  return srcName;
304  }
305 
306  @NbBundle.Messages({
307  "BlackboardArtifactNode.createSheet.artifactType.displayName=Artifact Type",
308  "BlackboardArtifactNode.createSheet.artifactType.name=Artifact Type",
309  "BlackboardArtifactNode.createSheet.artifactDetails.displayName=Artifact Details",
310  "BlackboardArtifactNode.createSheet.artifactDetails.name=Artifact Details",
311  "BlackboardArtifactNode.artifact.displayName=Artifact",
312  "BlackboardArtifactNode.createSheet.artifactMD5.displayName=MD5 Hash",
313  "BlackboardArtifactNode.createSheet.artifactMD5.name=MD5 Hash"})
314 
315  @Override
316  protected Sheet createSheet() {
317  Sheet sheet = super.createSheet();
318  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
319  if (sheetSet == null) {
320  sheetSet = Sheet.createPropertiesSet();
321  sheet.put(sheetSet);
322  }
323 
324  Map<String, Object> map = new LinkedHashMap<>();
325  fillPropertyMap(map, artifact);
326 
327  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.name"),
328  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.displayName"),
329  NO_DESCR,
330  this.getSourceName()));
331  if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
332  try {
333  BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
334  if (attribute != null) {
335  BlackboardArtifact associatedArtifact = Case.getOpenCase().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong());
336  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactType.name"),
337  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactType.displayName"),
338  NO_DESCR,
339  associatedArtifact.getDisplayName() + " " + NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.artifact.displayName")));
340  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactDetails.name"),
341  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactDetails.displayName"),
342  NO_DESCR,
343  associatedArtifact.getShortDescription()));
344  }
345  } catch (TskCoreException | NoCurrentCaseException ex) {
346  // Do nothing since the display name will be set to the file name.
347  }
348  }
349 
350  for (Map.Entry<String, Object> entry : map.entrySet()) {
351  sheetSet.put(new NodeProperty<>(entry.getKey(),
352  entry.getKey(),
353  NO_DESCR,
354  entry.getValue()));
355  }
356 
357  //append custom node properties
358  if (customProperties != null) {
359  for (NodeProperty<? extends Object> np : customProperties) {
360  sheetSet.put(np);
361  }
362  }
363 
364  final int artifactTypeId = artifact.getArtifactTypeID();
365 
366  // If mismatch, add props for extension and file type
367  if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID()) {
368  String ext = ""; //NON-NLS
369  String actualMimeType = ""; //NON-NLS
370  if (associated instanceof AbstractFile) {
371  AbstractFile af = (AbstractFile) associated;
372  ext = af.getNameExtension();
373  actualMimeType = af.getMIMEType();
374  if (actualMimeType == null) {
375  actualMimeType = ""; //NON-NLS
376  }
377  }
378  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.ext.name"),
379  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.ext.displayName"),
380  NO_DESCR,
381  ext));
382  sheetSet.put(new NodeProperty<>(
383  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.mimeType.name"),
384  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.mimeType.displayName"),
385  NO_DESCR,
386  actualMimeType));
387  }
388 
389  if (Arrays.asList(SHOW_UNIQUE_PATH).contains(artifactTypeId)) {
390  String sourcePath = ""; //NON-NLS
391  try {
392  sourcePath = associated.getUniquePath();
393  } catch (TskCoreException ex) {
394  LOGGER.log(Level.WARNING, "Failed to get unique path from: {0}", associated.getName()); //NON-NLS
395  }
396 
397  if (sourcePath.isEmpty() == false) {
398  sheetSet.put(new NodeProperty<>(
399  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.filePath.name"),
400  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.filePath.displayName"),
401  NO_DESCR,
402  sourcePath));
403  }
404 
405  if (Arrays.asList(SHOW_FILE_METADATA).contains(artifactTypeId)) {
406  AbstractFile file = associated instanceof AbstractFile ? (AbstractFile) associated : null;
407  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileModifiedTime.name"),
408  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileModifiedTime.displayName"),
409  "",
410  file == null ? "" : ContentUtils.getStringTime(file.getMtime(), file)));
411  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.name"),
412  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.displayName"),
413  "",
414  file == null ? "" : ContentUtils.getStringTime(file.getCtime(), file)));
415  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.name"),
416  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.displayName"),
417  "",
418  file == null ? "" : ContentUtils.getStringTime(file.getAtime(), file)));
419  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.name"),
420  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.displayName"),
421  "",
422  file == null ? "" : ContentUtils.getStringTime(file.getCrtime(), file)));
423  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.name"),
424  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.displayName"),
425  "",
426  associated.getSize()));
427  sheetSet.put(new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_artifactMD5_name(),
428  Bundle.BlackboardArtifactNode_createSheet_artifactMD5_displayName(),
429  "",
430  file == null ? "" : StringUtils.defaultString(file.getMd5Hash())));
431  }
432  } else {
433  String dataSourceStr = "";
434  try {
435  Content dataSource = associated.getDataSource();
436  if (dataSource != null) {
437  dataSourceStr = dataSource.getName();
438  } else {
439  dataSourceStr = getRootParentName();
440  }
441  } catch (TskCoreException ex) {
442  LOGGER.log(Level.WARNING, "Failed to get image name from {0}", associated.getName()); //NON-NLS
443  }
444 
445  if (dataSourceStr.isEmpty() == false) {
446  sheetSet.put(new NodeProperty<>(
447  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.dataSrc.name"),
448  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.dataSrc.displayName"),
449  NO_DESCR,
450  dataSourceStr));
451  }
452  }
453 
454  addTagProperty(sheetSet);
455 
456  return sheet;
457  }
458 
466  @NbBundle.Messages({
467  "BlackboardArtifactNode.createSheet.tags.displayName=Tags"})
468  protected void addTagProperty(Sheet.Set sheetSet) throws MissingResourceException {
469  // add properties for tags
470  List<Tag> tags = new ArrayList<>();
471  try {
473  tags.addAll(Case.getOpenCase().getServices().getTagsManager().getContentTagsByContent(associated));
474  } catch (TskCoreException | NoCurrentCaseException ex) {
475  LOGGER.log(Level.SEVERE, "Failed to get tags for artifact " + artifact.getDisplayName(), ex);
476  }
477  sheetSet.put(new NodeProperty<>("Tags", Bundle.BlackboardArtifactNode_createSheet_tags_displayName(),
478  NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", "))));
479  }
480 
481  private void updateSheet() {
482  this.setSheet(createSheet());
483  }
484 
485  private String getRootParentName() {
486  String parentName = associated.getName();
487  Content parent = associated;
488  try {
489  while ((parent = parent.getParent()) != null) {
490  parentName = parent.getName();
491  }
492  } catch (TskCoreException ex) {
493  LOGGER.log(Level.WARNING, "Failed to get parent name from {0}", associated.getName()); //NON-NLS
494  return "";
495  }
496  return parentName;
497  }
498 
506  if (null == customProperties) {
507  //lazy create the list
508  customProperties = new ArrayList<>();
509  }
510  customProperties.add(np);
511  }
512 
520  @SuppressWarnings("deprecation")
521  private void fillPropertyMap(Map<String, Object> map, BlackboardArtifact artifact) {
522  try {
523  for (BlackboardAttribute attribute : artifact.getAttributes()) {
524  final int attributeTypeID = attribute.getAttributeType().getTypeID();
525  //skip some internal attributes that user shouldn't see
526  if (attributeTypeID == ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()
527  || attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()
528  || attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()
529  || attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()
530  || attributeTypeID == ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE.getTypeID()) {
531  } else if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) {
532  addEmailMsgProperty(map, attribute);
533  } else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
534  map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
535  } else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID()
536  && attributeTypeID == ATTRIBUTE_TYPE.TSK_TEXT.getTypeID()) {
537  /*
538  * This was added because the RegRipper output would often
539  * cause the UI to get a black line accross it and hang if
540  * you hovered over large output or selected it. This
541  * reduces the amount of data in the table. Could consider
542  * doing this for all fields in the UI.
543  */
544  String value = attribute.getDisplayString();
545  if (value.length() > 512) {
546  value = value.substring(0, 512);
547  }
548  map.put(attribute.getAttributeType().getDisplayName(), value);
549  } else {
550  map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
551  }
552  }
553  } catch (TskCoreException ex) {
554  LOGGER.log(Level.SEVERE, "Getting attributes failed", ex); //NON-NLS
555  }
556  }
557 
565  private void addEmailMsgProperty(Map<String, Object> map, BlackboardAttribute attribute) {
566 
567  final int attributeTypeID = attribute.getAttributeType().getTypeID();
568 
569  // Skip certain Email msg attributes
570  if (attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID()
571  || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_HTML.getTypeID()
572  || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_RTF.getTypeID()
573  || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_BCC.getTypeID()
574  || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CC.getTypeID()
575  || attributeTypeID == ATTRIBUTE_TYPE.TSK_HEADERS.getTypeID()) {
576 
577  // do nothing
578  } else if (attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN.getTypeID()) {
579 
580  String value = attribute.getDisplayString();
581  if (value.length() > 160) {
582  value = value.substring(0, 160) + "...";
583  }
584  map.put(attribute.getAttributeType().getDisplayName(), value);
585  } else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
586  map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
587  } else {
588  map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
589  }
590 
591  }
592 
593  @Override
594  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
595  return visitor.visit(this);
596  }
597 
606  private static Lookup createLookup(BlackboardArtifact artifact) {
607  // Add the content the artifact is associated with
608  final long objectID = artifact.getObjectID();
609  try {
610  Content content = contentCache.get(objectID, () -> artifact.getSleuthkitCase().getContentById(objectID));
611  if (content == null) {
612  return Lookups.fixed(artifact);
613  } else {
614  return Lookups.fixed(artifact, content);
615  }
616  } catch (ExecutionException ex) {
617  LOGGER.log(Level.WARNING, "Getting associated content for artifact failed", ex); //NON-NLS
618  return Lookups.fixed(artifact);
619  }
620  }
621 
622  @Override
623  public boolean isLeafTypeNode() {
624  return true;
625  }
626 
627  @Override
628  public String getItemType() {
629  return getClass().getName();
630  }
631 
632  @Override
633  public <T> T accept(ContentNodeVisitor<T> visitor) {
634  return visitor.visit(this);
635  }
636 }
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:420
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:465
static ViewFileInTimelineAction createViewFileAction(AbstractFile file)
List< BlackboardArtifactTag > getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact)

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