Autopsy  4.4
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 java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.text.MessageFormat;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.LinkedHashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.logging.Level;
30 import java.util.stream.Collectors;
31 import javax.swing.Action;
32 import org.apache.commons.lang3.StringUtils;
33 import org.openide.nodes.Children;
34 import org.openide.nodes.Sheet;
35 import org.openide.util.Lookup;
36 import org.openide.util.NbBundle;
37 import org.openide.util.lookup.Lookups;
45 import static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked;
48 import org.sleuthkit.datamodel.AbstractFile;
49 import org.sleuthkit.datamodel.BlackboardArtifact;
50 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
51 import org.sleuthkit.datamodel.BlackboardAttribute;
52 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
53 import org.sleuthkit.datamodel.Content;
54 import org.sleuthkit.datamodel.Tag;
55 import org.sleuthkit.datamodel.TskCoreException;
56 
62 
63  private final BlackboardArtifact artifact;
64  private final Content associated;
65  private List<NodeProperty<? extends Object>> customProperties;
66  private static final Logger LOGGER = Logger.getLogger(BlackboardArtifactNode.class.getName());
67  /*
68  * Artifact types which should have the full unique path of the associated
69  * content as a property.
70  */
71  private static final Integer[] SHOW_UNIQUE_PATH = new Integer[]{
72  BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
73  BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(),
74  BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
75  BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID(),};
76 
77  // TODO (RC): This is an unattractive alternative to subclassing BlackboardArtifactNode,
78  // cut from the same cloth as the equally unattractive SHOW_UNIQUE_PATH array
79  // above. It should be removed when and if the subclassing is implemented.
80  private static final Integer[] SHOW_FILE_METADATA = new Integer[]{
81  BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),};
82 
83  private final PropertyChangeListener pcl = new PropertyChangeListener() {
84  @Override
85  public void propertyChange(PropertyChangeEvent evt) {
86  String eventType = evt.getPropertyName();
87  if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString())) {
89  if (event.getAddedTag().getArtifact().equals(artifact)) {
90  updateSheet();
91  }
92  } else if (eventType.equals(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString())) {
94  if (event.getDeletedTagInfo().getArtifactID() == artifact.getArtifactID()) {
95  updateSheet();
96  }
97  } else if (eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) {
99  if (event.getAddedTag().getContent().equals(associated)) {
100  updateSheet();
101  }
102  } else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) {
104  if (event.getDeletedTagInfo().getContentID() == associated.getId()) {
105  updateSheet();
106  }
107  } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
108  if (evt.getNewValue() == null) {
109  // case was closed. Remove listeners so that we don't get called with a stale case handle
110  removeListeners();
111  }
112  }
113  }
114  };
115 
123  public BlackboardArtifactNode(BlackboardArtifact artifact, String iconPath) {
124  super(Children.LEAF, createLookup(artifact));
125 
126  this.artifact = artifact;
127  //this.associated = getAssociatedContent(artifact);
128  this.associated = this.getLookup().lookup(Content.class);
129  this.setName(Long.toString(artifact.getArtifactID()));
130  this.setDisplayName();
131  this.setIconBaseWithExtension(iconPath);
133  }
134 
141  public BlackboardArtifactNode(BlackboardArtifact artifact) {
142  super(Children.LEAF, createLookup(artifact));
143 
144  this.artifact = artifact;
145  //this.associated = getAssociatedContent(artifact);
146  this.associated = this.getLookup().lookup(Content.class);
147  this.setName(Long.toString(artifact.getArtifactID()));
148  this.setDisplayName();
149  this.setIconBaseWithExtension(ExtractedContent.getIconFilePath(artifact.getArtifactTypeID())); //NON-NLS
151  }
152 
153  private void removeListeners() {
155  }
156 
157  @Override
158  @NbBundle.Messages({
159  "BlackboardArtifactNode.getAction.errorTitle=Error getting actions",
160  "BlackboardArtifactNode.getAction.resultErrorMessage=There was a problem getting actions for the selected result."
161  + " The 'View Result in Timeline' action will not be available.",
162  "BlackboardArtifactNode.getAction.linkedFileMessage=There was a problem getting actions for the selected result. "
163  + " The 'View File in Timeline' action will not be available."})
164  public Action[] getActions(boolean context) {
165  List<Action> actionsList = new ArrayList<>();
166  actionsList.addAll(Arrays.asList(super.getActions(context)));
167 
168  //if this artifact has a time stamp add the action to view it in the timeline
169  try {
171  actionsList.add(new ViewArtifactInTimelineAction(artifact));
172  }
173  } catch (TskCoreException ex) {
174  LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting arttribute(s) from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
175  MessageNotifyUtil.Notify.error(Bundle.BlackboardArtifactNode_getAction_errorTitle(), Bundle.BlackboardArtifactNode_getAction_resultErrorMessage());
176  }
177 
178  // if the artifact links to another file, add an action to go to that file
179  try {
180  AbstractFile c = findLinked(artifact);
181  if (c != null) {
183  }
184  } catch (TskCoreException ex) {
185  LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting linked file from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
186  MessageNotifyUtil.Notify.error(Bundle.BlackboardArtifactNode_getAction_errorTitle(), Bundle.BlackboardArtifactNode_getAction_linkedFileMessage());
187  }
188 
189  //if this artifact has associated content, add the action to view the content in the timeline
190  AbstractFile file = getLookup().lookup(AbstractFile.class);
191  if (null != file) {
193  }
194 
195  return actionsList.toArray(new Action[actionsList.size()]);
196  }
197 
198  @NbBundle.Messages({"# {0} - artifactDisplayName", "BlackboardArtifactNode.displayName.artifact={0} Artifact"})
204  private void setDisplayName() {
205  String displayName = ""; //NON-NLS
206  if (associated != null) {
207  displayName = associated.getName();
208  }
209 
210  // If this is a node for a keyword hit on an artifact, we set the
211  // display name to be the artifact type name followed by " Artifact"
212  // e.g. "Messages Artifact".
213  if (artifact != null
214  && (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()
215  || artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID())) {
216  try {
217  for (BlackboardAttribute attribute : artifact.getAttributes()) {
218  if (attribute.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
219  BlackboardArtifact associatedArtifact = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong());
220  if (associatedArtifact != null) {
221  if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
222  artifact.getDisplayName();
223  } else {
224  displayName = NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.displayName.artifact", associatedArtifact.getDisplayName());
225  }
226  }
227  }
228  }
229  } catch (TskCoreException ex) {
230  // Do nothing since the display name will be set to the file name.
231  }
232  }
233  this.setDisplayName(displayName);
234  }
235 
236  @NbBundle.Messages({
237  "BlackboardArtifactNode.createSheet.artifactType.displayName=Artifact Type",
238  "BlackboardArtifactNode.createSheet.artifactType.name=Artifact Type",
239  "BlackboardArtifactNode.createSheet.artifactDetails.displayName=Artifact Details",
240  "BlackboardArtifactNode.createSheet.artifactDetails.name=Artifact Details",
241  "BlackboardArtifactNode.artifact.displayName=Artifact"})
242 
243  @Override
244  protected Sheet createSheet() {
245  Sheet s = super.createSheet();
246  Sheet.Set ss = s.get(Sheet.PROPERTIES);
247  if (ss == null) {
248  ss = Sheet.createPropertiesSet();
249  s.put(ss);
250  }
251  final String NO_DESCR = NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.noDesc.text");
252 
253  Map<String, Object> map = new LinkedHashMap<>();
254  fillPropertyMap(map, artifact);
255 
256  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.name"),
257  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.srcFile.displayName"),
258  NO_DESCR,
259  this.getDisplayName()));
260  if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
261  try {
262  BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
263  if (attribute != null) {
264  BlackboardArtifact associatedArtifact = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong());
265  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactType.name"),
266  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactType.displayName"),
267  NO_DESCR,
268  associatedArtifact.getDisplayName() + " " + NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.artifact.displayName")));
269  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactDetails.name"),
270  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.artifactDetails.displayName"),
271  NO_DESCR,
272  associatedArtifact.getShortDescription()));
273  }
274  } catch (TskCoreException ex) {
275  // Do nothing since the display name will be set to the file name.
276  }
277  }
278 
279  for (Map.Entry<String, Object> entry : map.entrySet()) {
280  ss.put(new NodeProperty<>(entry.getKey(),
281  entry.getKey(),
282  NO_DESCR,
283  entry.getValue()));
284  }
285 
286  //append custom node properties
287  if (customProperties != null) {
288  for (NodeProperty<? extends Object> np : customProperties) {
289  ss.put(np);
290  }
291  }
292 
293  final int artifactTypeId = artifact.getArtifactTypeID();
294 
295  // If mismatch, add props for extension and file type
296  if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID()) {
297  String ext = ""; //NON-NLS
298  String actualMimeType = ""; //NON-NLS
299  if (associated instanceof AbstractFile) {
300  AbstractFile af = (AbstractFile) associated;
301  ext = af.getNameExtension();
302  actualMimeType = af.getMIMEType();
303  if (actualMimeType == null) {
304  actualMimeType = ""; //NON-NLS
305  }
306  }
307  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.ext.name"),
308  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.ext.displayName"),
309  NO_DESCR,
310  ext));
311  ss.put(new NodeProperty<>(
312  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.mimeType.name"),
313  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.mimeType.displayName"),
314  NO_DESCR,
315  actualMimeType));
316  }
317 
318  if (Arrays.asList(SHOW_UNIQUE_PATH).contains(artifactTypeId)) {
319  String sourcePath = ""; //NON-NLS
320  try {
321  sourcePath = associated.getUniquePath();
322  } catch (TskCoreException ex) {
323  LOGGER.log(Level.WARNING, "Failed to get unique path from: {0}", associated.getName()); //NON-NLS
324  }
325 
326  if (sourcePath.isEmpty() == false) {
327  ss.put(new NodeProperty<>(
328  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.filePath.name"),
329  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.filePath.displayName"),
330  NO_DESCR,
331  sourcePath));
332  }
333 
334  if (Arrays.asList(SHOW_FILE_METADATA).contains(artifactTypeId)) {
335  AbstractFile file = associated instanceof AbstractFile ? (AbstractFile) associated : null;
336  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileModifiedTime.name"),
337  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileModifiedTime.displayName"),
338  "",
339  file != null ? ContentUtils.getStringTime(file.getMtime(), file) : ""));
340  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.name"),
341  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileChangedTime.displayName"),
342  "",
343  file != null ? ContentUtils.getStringTime(file.getCtime(), file) : ""));
344  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.name"),
345  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileAccessedTime.displayName"),
346  "",
347  file != null ? ContentUtils.getStringTime(file.getAtime(), file) : ""));
348  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.name"),
349  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileCreatedTime.displayName"),
350  "",
351  file != null ? ContentUtils.getStringTime(file.getCrtime(), file) : ""));
352  ss.put(new NodeProperty<>(NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.name"),
353  NbBundle.getMessage(BlackboardArtifactNode.class, "ContentTagNode.createSheet.fileSize.displayName"),
354  "",
355  associated.getSize()));
356  }
357  } else {
358  String dataSourceStr = "";
359  try {
360  Content dataSource = associated.getDataSource();
361  if (dataSource != null) {
362  dataSourceStr = dataSource.getName();
363  } else {
364  dataSourceStr = getRootParentName();
365  }
366  } catch (TskCoreException ex) {
367  LOGGER.log(Level.WARNING, "Failed to get image name from {0}", associated.getName()); //NON-NLS
368  }
369 
370  if (dataSourceStr.isEmpty() == false) {
371  ss.put(new NodeProperty<>(
372  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.dataSrc.name"),
373  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.createSheet.dataSrc.displayName"),
374  NO_DESCR,
375  dataSourceStr));
376  }
377  }
378 
379  // add properties for tags
380  List<Tag> tags = new ArrayList<>();
381  try {
384  } catch (TskCoreException ex) {
385  LOGGER.log(Level.SEVERE, "Failed to get tags for artifact " + artifact.getDisplayName(), ex);
386  }
387  ss.put(new NodeProperty<>("Tags", NbBundle.getMessage(AbstractAbstractFileNode.class, "BlackboardArtifactNode.createSheet.tags.displayName"),
388  NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(", "))));
389 
390  return s;
391  }
392 
393  private void updateSheet() {
394  this.setSheet(createSheet());
395  }
396 
397  private String getRootParentName() {
398  String parentName = associated.getName();
399  Content parent = associated;
400  try {
401  while ((parent = parent.getParent()) != null) {
402  parentName = parent.getName();
403  }
404  } catch (TskCoreException ex) {
405  LOGGER.log(Level.WARNING, "Failed to get parent name from {0}", associated.getName()); //NON-NLS
406  return "";
407  }
408  return parentName;
409  }
410 
418  if (null == customProperties) {
419  //lazy create the list
420  customProperties = new ArrayList<>();
421  }
422  customProperties.add(np);
423  }
424 
432  @SuppressWarnings("deprecation")
433  private void fillPropertyMap(Map<String, Object> map, BlackboardArtifact artifact) {
434  try {
435  for (BlackboardAttribute attribute : artifact.getAttributes()) {
436  final int attributeTypeID = attribute.getAttributeType().getTypeID();
437  //skip some internal attributes that user shouldn't see
438  if (attributeTypeID == ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()
439  || attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()
440  || attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()
441  || attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()
442  || attributeTypeID == ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE.getTypeID()) {
443  }
444  else if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) {
445  addEmailMsgProperty (map, attribute);
446  }
447  else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
448  map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
449  } else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID()
450  && attributeTypeID == ATTRIBUTE_TYPE.TSK_TEXT.getTypeID()) {
451  /*
452  * This was added because the RegRipper output would often
453  * cause the UI to get a black line accross it and hang if
454  * you hovered over large output or selected it. This
455  * reduces the amount of data in the table. Could consider
456  * doing this for all fields in the UI.
457  */
458  String value = attribute.getDisplayString();
459  if (value.length() > 512) {
460  value = value.substring(0, 512);
461  }
462  map.put(attribute.getAttributeType().getDisplayName(), value);
463  }
464  else {
465  map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
466  }
467  }
468  } catch (TskCoreException ex) {
469  LOGGER.log(Level.SEVERE, "Getting attributes failed", ex); //NON-NLS
470  }
471  }
472 
480  private void addEmailMsgProperty(Map<String, Object> map, BlackboardAttribute attribute ) {
481 
482  final int attributeTypeID = attribute.getAttributeType().getTypeID();
483 
484  // Skip certain Email msg attributes
485  if (attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID()
486  || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_HTML.getTypeID()
487  || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_RTF.getTypeID()
488  || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_BCC.getTypeID()
489  || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CC.getTypeID()
490  || attributeTypeID == ATTRIBUTE_TYPE.TSK_HEADERS.getTypeID()
491  ) {
492 
493  // do nothing
494  }
495  else if (attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN.getTypeID()) {
496 
497  String value = attribute.getDisplayString();
498  if (value.length() > 160) {
499  value = value.substring(0, 160) + "...";
500  }
501  map.put(attribute.getAttributeType().getDisplayName(), value);
502  }
503  else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
504  map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
505  }
506  else {
507  map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
508  }
509 
510  }
511 
512  @Override
513  public <T> T accept(DisplayableItemNodeVisitor<T> v) {
514  return v.visit(this);
515  }
516 
524  private static Lookup createLookup(BlackboardArtifact artifact) {
525  List<Object> forLookup = new ArrayList<>();
526  forLookup.add(artifact);
527 
528  // Add the content the artifact is associated with
529  Content content = getAssociatedContent(artifact);
530  if (content != null) {
531  forLookup.add(content);
532  }
533 
534  return Lookups.fixed(forLookup.toArray(new Object[forLookup.size()]));
535  }
536 
537  private static Content getAssociatedContent(BlackboardArtifact artifact) {
538  try {
539  return artifact.getSleuthkitCase().getContentById(artifact.getObjectID());
540  } catch (TskCoreException ex) {
541  LOGGER.log(Level.WARNING, "Getting file failed", ex); //NON-NLS
542  }
543  throw new IllegalArgumentException(
544  NbBundle.getMessage(BlackboardArtifactNode.class, "BlackboardArtifactNode.getAssocCont.exception.msg"));
545  }
546 
547  @Override
548  public boolean isLeafTypeNode() {
549  return true;
550  }
551 
552  @Override
553  public String getItemType() {
554  return getClass().getName();
555  }
556 }
void fillPropertyMap(Map< String, Object > map, BlackboardArtifact artifact)
static String getStringTime(long epochSeconds, TimeZone tzone)
static void removePropertyChangeListener(PropertyChangeListener listener)
Definition: Case.java:369
BlackboardArtifactNode(BlackboardArtifact artifact, String iconPath)
static Lookup createLookup(BlackboardArtifact artifact)
synchronized List< BlackboardArtifactTag > getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact)
static Content getAssociatedContent(BlackboardArtifact artifact)
static ViewFileInTimelineAction createViewSourceFileAction(AbstractFile file)
void addEmailMsgProperty(Map< String, Object > map, BlackboardAttribute attribute)
static void addPropertyChangeListener(PropertyChangeListener listener)
Definition: Case.java:357
static void error(String title, String message)
synchronized static Logger getLogger(String name)
Definition: Logger.java:161
synchronized List< ContentTag > getContentTagsByContent(Content content)
static ViewFileInTimelineAction createViewFileAction(AbstractFile file)

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