19 package org.sleuthkit.autopsy.datamodel;
 
   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;
 
   32 import java.util.MissingResourceException;
 
   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;
 
   69 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
 
   71 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
 
   91     private static Cache<Long, Content> 
contentCache = CacheBuilder.newBuilder()
 
   92             .expireAfterWrite(1, TimeUnit.MINUTES).
 
  108         BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
 
  109         BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(),
 
  110         BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
 
  111         BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID(),};
 
  117         BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),};
 
  119     private final PropertyChangeListener 
pcl = 
new PropertyChangeListener() {
 
  121         public void propertyChange(PropertyChangeEvent evt) {
 
  122             String eventType = evt.getPropertyName();
 
  125                 if (event.getAddedTag().getArtifact().equals(artifact)) {
 
  130                 if (event.getDeletedTagInfo().getArtifactID() == artifact.getArtifactID()) {
 
  135                 if (event.getAddedTag().getContent().equals(associated)) {
 
  140                 if (event.getDeletedTagInfo().getContentID() == associated.getId()) {
 
  145                 if (event.getContentID() == associated.getId()) {
 
  149                 if (evt.getNewValue() == null) {
 
  152                     contentCache.invalidateAll();
 
  166     private final PropertyChangeListener 
weakPcl = WeakListeners.propertyChange(pcl, null);
 
  182         for (Content lookupContent : this.getLookup().lookupAll(Content.class)) {
 
  183             if ((lookupContent != null) && (!(lookupContent instanceof BlackboardArtifact))) {
 
  184                 this.associated = lookupContent;
 
  189         this.
setName(Long.toString(artifact.getArtifactID()));
 
  191         this.setIconBaseWithExtension(iconPath);
 
  230         "BlackboardArtifactNode.getAction.errorTitle=Error getting actions",
 
  231         "BlackboardArtifactNode.getAction.resultErrorMessage=There was a problem getting actions for the selected result." 
  232         + 
"  The 'View Result in Timeline' action will not be available.",
 
  233         "BlackboardArtifactNode.getAction.linkedFileMessage=There was a problem getting actions for the selected result. " 
  234         + 
" The 'View File in Timeline' action will not be available."})
 
  236         List<Action> actionsList = 
new ArrayList<>();
 
  237         actionsList.addAll(Arrays.asList(super.getActions(context)));
 
  238         AbstractFile file = getLookup().lookup(AbstractFile.class);
 
  245         } 
catch (TskCoreException ex) {
 
  246             logger.log(Level.SEVERE, MessageFormat.format(
"Error getting arttribute(s) from blackboard artifact{0}.", artifact.getArtifactID()), ex); 
 
  247             MessageNotifyUtil.
Notify.
error(Bundle.BlackboardArtifactNode_getAction_errorTitle(), Bundle.BlackboardArtifactNode_getAction_resultErrorMessage());
 
  252             AbstractFile c = findLinked(artifact);
 
  256         } 
catch (TskCoreException ex) {
 
  257             logger.log(Level.SEVERE, MessageFormat.format(
"Error getting linked file from blackboard artifact{0}.", artifact.getArtifactID()), ex); 
 
  258             MessageNotifyUtil.
Notify.
error(Bundle.BlackboardArtifactNode_getAction_errorTitle(), Bundle.BlackboardArtifactNode_getAction_linkedFileMessage());
 
  266         return actionsList.toArray(
new Action[actionsList.size()]);
 
  269     @NbBundle.Messages({
"# {0} - artifactDisplayName", 
"BlackboardArtifactNode.displayName.artifact={0} Artifact"})
 
  276         String displayName = 
""; 
 
  282                 && (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()
 
  283                 || artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID())) {
 
  285                 for (BlackboardAttribute attribute : artifact.getAttributes()) {
 
  286                     if (attribute.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
 
  288                         if (associatedArtifact != null) {
 
  289                             if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
 
  290                                 artifact.getDisplayName();
 
  292                                 displayName = NbBundle.getMessage(
BlackboardArtifactNode.class, 
"BlackboardArtifactNode.displayName.artifact", associatedArtifact.getDisplayName());
 
  302         if (displayName.isEmpty() && artifact != null) {
 
  303             displayName = artifact.getName();
 
  318         if (associated != null) {
 
  319             srcName = associated.getName();
 
  325         "BlackboardArtifactNode.createSheet.artifactType.displayName=Result Type",
 
  326         "BlackboardArtifactNode.createSheet.artifactType.name=Result Type",
 
  327         "BlackboardArtifactNode.createSheet.artifactDetails.displayName=Result Details",
 
  328         "BlackboardArtifactNode.createSheet.artifactDetails.name=Result Details",
 
  329         "BlackboardArtifactNode.createSheet.artifactMD5.displayName=MD5 Hash",
 
  330         "BlackboardArtifactNode.createSheet.artifactMD5.name=MD5 Hash",
 
  331         "BlackboardArtifactNode.createSheet.fileSize.name=Size",
 
  332         "BlackboardArtifactNode.createSheet.fileSize.displayName=Size",
 
  333         "BlackboardArtifactNode.createSheet.path.displayName=Path",
 
  334         "BlackboardArtifactNode.createSheet.path.name=Path"})
 
  338         Sheet sheet = super.createSheet();
 
  341         Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
 
  342         if (sheetSet == null) {
 
  343             sheetSet = Sheet.createPropertiesSet();
 
  347         Map<String, Object> map = 
new LinkedHashMap<>();
 
  351                 NbBundle.getMessage(
BlackboardArtifactNode.class, 
"BlackboardArtifactNode.createSheet.srcFile.displayName"),
 
  366         if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
 
  368                 BlackboardAttribute attribute = artifact.getAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
 
  369                 if (attribute != null) {
 
  372                             NbBundle.getMessage(
BlackboardArtifactNode.class, 
"BlackboardArtifactNode.createSheet.artifactType.displayName"),
 
  374                             associatedArtifact.getDisplayName()));
 
  376                             NbBundle.getMessage(
BlackboardArtifactNode.class, 
"BlackboardArtifactNode.createSheet.artifactDetails.displayName"),
 
  378                             associatedArtifact.getShortDescription()));
 
  385         for (Map.Entry<String, Object> entry : map.entrySet()) {
 
  393         if (customProperties != null) {
 
  399         final int artifactTypeId = artifact.getArtifactTypeID();
 
  402         if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID()) {
 
  404             String actualMimeType = 
""; 
 
  405             if (associated instanceof AbstractFile) {
 
  406                 AbstractFile af = (AbstractFile) associated;
 
  407                 ext = af.getNameExtension();
 
  408                 actualMimeType = af.getMIMEType();
 
  409                 if (actualMimeType == null) {
 
  419                     NbBundle.getMessage(
BlackboardArtifactNode.class, 
"BlackboardArtifactNode.createSheet.mimeType.displayName"),
 
  424         if (Arrays.asList(SHOW_UNIQUE_PATH).contains(artifactTypeId)) {
 
  425             String sourcePath = 
""; 
 
  427                 sourcePath = associated.getUniquePath();
 
  428             } 
catch (TskCoreException ex) {
 
  429                 logger.log(Level.WARNING, 
"Failed to get unique path from: {0}", associated.getName()); 
 
  432             if (sourcePath.isEmpty() == 
false) {
 
  435                         NbBundle.getMessage(
BlackboardArtifactNode.class, 
"BlackboardArtifactNode.createSheet.filePath.displayName"),
 
  440             if (Arrays.asList(SHOW_FILE_METADATA).contains(artifactTypeId)) {
 
  441                 AbstractFile file = associated instanceof AbstractFile ? (AbstractFile) associated : null;
 
  443                         NbBundle.getMessage(
BlackboardArtifactNode.class, 
"ContentTagNode.createSheet.fileModifiedTime.displayName"),
 
  447                         NbBundle.getMessage(
BlackboardArtifactNode.class, 
"ContentTagNode.createSheet.fileChangedTime.displayName"),
 
  451                         NbBundle.getMessage(
BlackboardArtifactNode.class, 
"ContentTagNode.createSheet.fileAccessedTime.displayName"),
 
  455                         NbBundle.getMessage(
BlackboardArtifactNode.class, 
"ContentTagNode.createSheet.fileCreatedTime.displayName"),
 
  461                         associated.getSize()));
 
  462                 sheetSet.put(
new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_artifactMD5_name(),
 
  463                         Bundle.BlackboardArtifactNode_createSheet_artifactMD5_displayName(),
 
  465                         file == null ? 
"" : StringUtils.defaultString(file.getMd5Hash())));
 
  468             String dataSourceStr = 
"";
 
  470                 Content dataSource = associated.getDataSource();
 
  471                 if (dataSource != null) {
 
  472                     dataSourceStr = dataSource.getName();
 
  476             } 
catch (TskCoreException ex) {
 
  477                 logger.log(Level.WARNING, 
"Failed to get image name from {0}", associated.getName()); 
 
  480             if (dataSourceStr.isEmpty() == 
false) {
 
  483                         NbBundle.getMessage(
BlackboardArtifactNode.class, 
"BlackboardArtifactNode.createSheet.dataSrc.displayName"),
 
  490         if (artifactTypeId == BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID()) {
 
  494             if (associated instanceof AbstractFile) {
 
  495                 AbstractFile af = (AbstractFile) associated;
 
  498                     path = af.getUniquePath();
 
  499                 } 
catch (TskCoreException ex) {
 
  500                     path = af.getParentPath();
 
  504                     NbBundle.getMessage(
BlackboardArtifactNode.class, 
"BlackboardArtifactNode.createSheet.fileSize.displayName"),
 
  525         List<Tag> tags = 
new ArrayList<>();
 
  530             logger.log(Level.SEVERE, 
"Failed to get tags for artifact " + artifact.getDisplayName(), ex);
 
  543         "BlackboardArtifactNode.createSheet.tags.displayName=Tags"})
 
  545     protected void addTagProperty(Sheet.Set sheetSet) 
throws MissingResourceException {
 
  547         List<Tag> tags = 
new ArrayList<>();
 
  552             logger.log(Level.SEVERE, 
"Failed to get tags for artifact " + artifact.getDisplayName(), ex);
 
  554         sheetSet.put(
new NodeProperty<>(
"Tags", Bundle.BlackboardArtifactNode_createSheet_tags_displayName(),
 
  555                 NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(
", "))));
 
  569         sheetSet.put(
new NodeProperty<>(
"Tags", Bundle.BlackboardArtifactNode_createSheet_tags_displayName(),
 
  570                 NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName()).collect(Collectors.joining(
", "))));
 
  578         return correlationAttribute;
 
  592     @NbBundle.Messages({
"BlackboardArtifactNode.createSheet.comment.name=C",
 
  593         "BlackboardArtifactNode.createSheet.comment.displayName=C"})
 
  596         for (Tag tag : tags) {
 
  597             if (!StringUtils.isBlank(tag.getComment())) {
 
  606         if (attribute != null && !StringUtils.isBlank(attribute.
getComment())) {
 
  613         sheetSet.put(
new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_comment_name(), Bundle.BlackboardArtifactNode_createSheet_comment_displayName(), 
NO_DESCR,
 
  625     @NbBundle.Messages({
"BlackboardArtifactNode.createSheet.score.name=S",
 
  626         "BlackboardArtifactNode.createSheet.score.displayName=S",
 
  627         "BlackboardArtifactNode.createSheet.notableFile.description=Associated file recognized as notable.",
 
  628         "BlackboardArtifactNode.createSheet.interestingResult.description=Result has an interesting result associated with it.",
 
  629         "BlackboardArtifactNode.createSheet.taggedItem.description=Result or associated file has been tagged.",
 
  630         "BlackboardArtifactNode.createSheet.notableTaggedItem.description=Result or associated file tagged with notable tag.",
 
  631         "BlackboardArtifactNode.createSheet.noScore.description=No score"})
 
  634         String description = Bundle.BlackboardArtifactNode_createSheet_noScore_description();
 
  635         if (associated instanceof AbstractFile) {
 
  636             if (((AbstractFile) associated).getKnown() == TskData.FileKnown.BAD) {
 
  638                 description = Bundle.BlackboardArtifactNode_createSheet_notableFile_description();
 
  644                 BlackboardAttribute attr = content.getAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SET_NAME));
 
  647                     if (hashDb.getHashSetName().equals(attr.getValueString())) {
 
  649                         description = Bundle.BlackboardArtifactNode_createSheet_notableFile_description();
 
  653             } 
catch (TskCoreException ex) {
 
  655                 logger.log(Level.WARNING, 
"Unable to get TSK_SET_NAME attribute for artifact of type TSK_HASHSET_HIT with artifact ID " + content.getArtifactID(), ex);
 
  659             if (score == 
Score.
NO_SCORE && !content.getArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT).isEmpty()) {
 
  661                 description = Bundle.BlackboardArtifactNode_createSheet_interestingResult_description();
 
  663         } 
catch (TskCoreException ex) {
 
  664             logger.log(Level.WARNING, 
"Error getting artifacts for artifact: " + content.getName(), ex);
 
  668             description = Bundle.BlackboardArtifactNode_createSheet_taggedItem_description();
 
  669             for (Tag tag : tags) {
 
  670                 if (tag.getName().getKnownStatus() == TskData.FileKnown.BAD) {
 
  672                     description = Bundle.BlackboardArtifactNode_createSheet_notableTaggedItem_description();
 
  677         sheetSet.put(
new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_score_name(), Bundle.BlackboardArtifactNode_createSheet_score_displayName(), description, score));
 
  680     @NbBundle.Messages({
"BlackboardArtifactNode.createSheet.count.name=O",
 
  681         "BlackboardArtifactNode.createSheet.count.displayName=O",
 
  682         "BlackboardArtifactNode.createSheet.count.noCentralRepo.description=Central repository was not enabled when this column was populated",
 
  683         "BlackboardArtifactNode.createSheet.count.hashLookupNotRun.description=Hash lookup had not been run on this artifact's associated file when the column was populated",
 
  684         "# {0} - occuranceCount",
 
  685         "BlackboardArtifactNode.createSheet.count.description=There were {0} datasource(s) found with occurances of the correlation value"})
 
  689         String description = Bundle.BlackboardArtifactNode_createSheet_count_noCentralRepo_description();
 
  694                 description = Bundle.BlackboardArtifactNode_createSheet_count_description(count);
 
  695             } 
else if (attribute != null) {
 
  696                 description = Bundle.BlackboardArtifactNode_createSheet_count_hashLookupNotRun_description();
 
  699             logger.log(Level.WARNING, 
"Error getting count of datasources with correlation attribute", ex);
 
  701             logger.log(Level.WARNING, 
"Unable to normalize data to get count of datasources with correlation attribute", ex);
 
  704                 new NodeProperty<>(Bundle.BlackboardArtifactNode_createSheet_count_name(), Bundle.BlackboardArtifactNode_createSheet_count_displayName(), description, count));
 
  712         String parentName = associated.getName();
 
  715             while ((parent = parent.getParent()) != null) {
 
  716                 parentName = parent.getName();
 
  718         } 
catch (TskCoreException ex) {
 
  719             logger.log(Level.WARNING, 
"Failed to get parent name from {0}", associated.getName()); 
 
  732         if (null == customProperties) {
 
  734             customProperties = 
new ArrayList<>();
 
  736         customProperties.add(np);
 
  746     @SuppressWarnings(
"deprecation")
 
  749             for (BlackboardAttribute attribute : artifact.getAttributes()) {
 
  750                 final int attributeTypeID = attribute.getAttributeType().getTypeID();
 
  752                 if (attributeTypeID == ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()
 
  753                         || attributeTypeID == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()
 
  754                         || attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()
 
  755                         || attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()
 
  756                         || attributeTypeID == ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE.getTypeID()) {
 
  757                 } 
else if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) {
 
  759                 } 
else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
 
  761                 } 
else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID()
 
  762                         && attributeTypeID == ATTRIBUTE_TYPE.TSK_TEXT.getTypeID()) {
 
  770                     String value = attribute.getDisplayString();
 
  771                     if (value.length() > 512) {
 
  772                         value = value.substring(0, 512);
 
  774                     map.put(attribute.getAttributeType().getDisplayName(), value);
 
  776                     map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
 
  779         } 
catch (TskCoreException ex) {
 
  780             logger.log(Level.SEVERE, 
"Getting attributes failed", ex); 
 
  793         final int attributeTypeID = attribute.getAttributeType().getTypeID();
 
  796         if (attributeTypeID == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID()
 
  797                 || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_HTML.getTypeID()
 
  798                 || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_RTF.getTypeID()
 
  799                 || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_BCC.getTypeID()
 
  800                 || attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CC.getTypeID()
 
  801                 || attributeTypeID == ATTRIBUTE_TYPE.TSK_HEADERS.getTypeID()) {
 
  804         } 
else if (attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN.getTypeID()) {
 
  806             String value = attribute.getDisplayString();
 
  807             if (value.length() > 160) {
 
  808                 value = value.substring(0, 160) + 
"...";
 
  810             map.put(attribute.getAttributeType().getDisplayName(), value);
 
  811         } 
else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
 
  814             map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
 
  821         return visitor.
visit(
this);
 
  834         final long objectID = artifact.getObjectID();
 
  836             Content content = contentCache.get(objectID, () -> artifact.getSleuthkitCase().getContentById(objectID));
 
  837             if (content == null) {
 
  838                 return Lookups.fixed(artifact);
 
  840                 return Lookups.fixed(artifact, content);
 
  842         } 
catch (ExecutionException ex) {
 
  843             logger.log(Level.WARNING, 
"Getting associated content for artifact failed", ex); 
 
  844             return Lookups.fixed(artifact);
 
  855         return getClass().getName();
 
  859     public <T> T accept(ContentNodeVisitor<T> visitor) {
 
  860         return visitor.visit(
this);
 
final void addTagProperty(Sheet.Set sheetSet, List< Tag > tags)
void addTagProperty(Sheet.Set sheetSet)
void fillPropertyMap(Map< String, Object > map, BlackboardArtifact artifact)
static String getStringTime(long epochSeconds, TimeZone tzone)
static boolean hasSupportedTimeStamp(BlackboardArtifact artifact)
final PropertyChangeListener weakPcl
static Cache< Long, Content > contentCache
void setName(String name)
final PropertyChangeListener pcl
BlackboardArtifactNode(BlackboardArtifact artifact, String iconPath)
static boolean useCentralRepo()
static Lookup createLookup(BlackboardArtifact artifact)
static final String NO_DESCR
static final Integer[] SHOW_FILE_METADATA
String getCorrelationValue()
T visit(DataSourcesNode in)
Action[] getActions(boolean context)
final void addScoreProperty(Sheet.Set sheetSet, List< Tag > tags)
Type getCorrelationType()
static ViewFileInTimelineAction createViewSourceFileAction(AbstractFile file)
static final Set< Case.Events > CASE_EVENTS_OF_INTEREST
Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttributeInstance.Type aType, String value)
TagsManager getTagsManager()
synchronized List< HashDb > getKnownBadFileHashSets()
static EamDb getInstance()
List< NodeProperty<?extends Object > > customProperties
static synchronized HashDbManager getInstance()
static CorrelationAttributeInstance getInstanceFromContent(Content content)
final List< Tag > getAllTagsFromDatabase()
String getRootParentName()
final BlackboardArtifact artifact
void addEmailMsgProperty(Map< String, Object > map, BlackboardAttribute attribute)
final void addCommentProperty(Sheet.Set sheetSet, List< Tag > tags, CorrelationAttributeInstance attribute)
final CorrelationAttributeInstance getCorrelationAttributeInstance()
SleuthkitCase getSleuthkitCase()
final void addCountProperty(Sheet.Set sheetSet, CorrelationAttributeInstance attribute)
BLACKBOARD_ARTIFACT_TAG_ADDED
static final Logger logger
static void error(String title, String message)
BlackboardArtifact getArtifact()
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
static boolean hideCentralRepoCommentsAndOccurrences()
void addNodeProperty(NodeProperty<?> np)
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
BlackboardArtifactNode(BlackboardArtifact artifact)
static final Integer[] SHOW_UNIQUE_PATH
static ViewFileInTimelineAction createViewFileAction(AbstractFile file)
BLACKBOARD_ARTIFACT_TAG_DELETED