Autopsy  4.17.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
AbstractAbstractFileNode.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2012-2020 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.datamodel;
20 
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.lang.ref.WeakReference;
24 import java.text.MessageFormat;
25 import java.util.ArrayList;
26 import java.util.EnumSet;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.logging.Level;
31 import java.util.stream.Collectors;
32 import org.apache.commons.lang3.StringUtils;
33 import org.apache.commons.lang3.tuple.Pair;
34 import org.openide.nodes.Sheet;
35 import org.openide.util.NbBundle;
36 import org.openide.util.WeakListeners;
51 import static org.sleuthkit.autopsy.datamodel.Bundle.*;
61 import org.sleuthkit.datamodel.AbstractFile;
62 import org.sleuthkit.datamodel.BlackboardArtifact;
63 import org.sleuthkit.datamodel.Content;
64 import org.sleuthkit.datamodel.ContentTag;
65 import org.sleuthkit.datamodel.Tag;
66 import org.sleuthkit.datamodel.TskCoreException;
67 import org.sleuthkit.datamodel.TskData;
70 
76 public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends AbstractContentNode<T> {
77 
78  private static final Logger logger = Logger.getLogger(AbstractAbstractFileNode.class.getName());
79 
80  private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE,
82  private static final Set<IngestManager.IngestModuleEvent> INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(CONTENT_CHANGED);
83 
87  AbstractAbstractFileNode(T abstractFile) {
88  super(abstractFile);
89  String ext = abstractFile.getNameExtension();
90  if (StringUtils.isNotBlank(ext)) {
91  ext = "." + ext;
92  // If this is an archive file we will listen for ingest events
93  // that will notify us when new content has been identified.
94  if (FileTypeExtensions.getArchiveExtensions().contains(ext)) {
96  }
97  }
98 
99  try {
100  //See JIRA-5971
101  //Attempt to cache file path during construction of this UI component.
102  this.content.getUniquePath();
103  } catch (TskCoreException ex) {
104  logger.log(Level.SEVERE, String.format("Failed attempt to cache the "
105  + "unique path of the abstract file instance. Name: %s (objID=%d)",
106  this.content.getName(), this.content.getId()), ex);
107  }
108 
110  backgroundTasksPool.submit(new TranslationTask(
111  new WeakReference<>(this), weakPcl));
112  }
113 
114  // Listen for case events so that we can detect when the case is closed
115  // or when tags are added.
117  }
118 
128  @Override
129  protected void finalize() throws Throwable {
130  super.finalize();
131  removeListeners();
132  }
133 
134  private void removeListeners() {
137  }
138 
139  private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
140  String eventType = evt.getPropertyName();
141 
142  // Is this a content changed event?
143  if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
144  if ((evt.getOldValue() instanceof ModuleContentEvent) == false) {
145  return;
146  }
147  ModuleContentEvent moduleContentEvent = (ModuleContentEvent) evt.getOldValue();
148  if ((moduleContentEvent.getSource() instanceof Content) == false) {
149  return;
150  }
151  Content newContent = (Content) moduleContentEvent.getSource();
152 
153  // Does the event indicate that content has been added to *this* file?
154  if (getContent().getId() == newContent.getId()) {
155  // If so, refresh our children.
156  try {
157  // We only want to refresh our parents children if we are in the
158  // data sources branch of the tree. The parent nodes in other
159  // branches of the tree (e.g. File Types and Deleted Files) do
160  // not need to be refreshed.
161  BaseChildFactory.post(getParentNode().getName(), new RefreshKeysEvent());
162  } catch (NullPointerException ex) {
163  // Skip
164  } catch (NoSuchEventBusException ex) {
165  logger.log(Level.WARNING, "Failed to post key refresh event", ex); //NON-NLS
166  }
167  }
168  } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
169  if (evt.getNewValue() == null) {
170  // case was closed. Remove listeners so that we don't get called with a stale case handle
171  removeListeners();
172  }
173  /*
174  * No need to do any asynchrony around tag added, deleted or CR
175  * change events, they are so infrequent and user driven that we can
176  * just keep a simple blocking approach, where we go out to the
177  * database ourselves.
178  */
179  } else if (eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) {
181  if (event.getAddedTag().getContent().equals(content)) {
182  List<Tag> tags = this.getAllTagsFromDatabase();
183  Pair<Score, String> scorePropAndDescr = getScorePropertyAndDescription(tags);
184  Score value = scorePropAndDescr.getLeft();
185  String descr = scorePropAndDescr.getRight();
187  updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), descr, value),
188  new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute))
189  );
190  }
191  } else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) {
193  if (event.getDeletedTagInfo().getContentID() == content.getId()) {
194  List<Tag> tags = getAllTagsFromDatabase();
195  Pair<Score, String> scorePropAndDescr = getScorePropertyAndDescription(tags);
196  Score value = scorePropAndDescr.getLeft();
197  String descr = scorePropAndDescr.getRight();
199  updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), descr, value),
200  new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute))
201  );
202  }
203  } else if (eventType.equals(Case.Events.CR_COMMENT_CHANGED.toString())) {
205  if (event.getContentID() == content.getId()) {
206  List<Tag> tags = getAllTagsFromDatabase();
208  updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute)));
209  }
210  } else if (eventType.equals(NodeSpecificEvents.TRANSLATION_AVAILABLE.toString())) {
211  this.setDisplayName(evt.getNewValue().toString());
212  //Set the tooltip
213  this.setShortDescription(content.getName());
214  updateSheet(new NodeProperty<>(ORIGINAL_NAME.toString(), ORIGINAL_NAME.toString(), NO_DESCR, content.getName()));
215  } else if (eventType.equals(NodeSpecificEvents.SCO_AVAILABLE.toString()) && !UserPreferences.getHideSCOColumns()) {
216  SCOData scoData = (SCOData) evt.getNewValue();
217  if (scoData.getScoreAndDescription() != null) {
218  updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), scoData.getScoreAndDescription().getRight(), scoData.getScoreAndDescription().getLeft()));
219  }
220  if (scoData.getComment() != null) {
221  updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, scoData.getComment()));
222  }
223  if (scoData.getCountAndDescription() != null) {
224  updateSheet(new NodeProperty<>(OCCURRENCES.toString(), OCCURRENCES.toString(), scoData.getCountAndDescription().getRight(), scoData.getCountAndDescription().getLeft()));
225  }
226  }
227  };
236  private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
237 
238  /*
239  * This is called when the node is first initialized. Any new updates or
240  * changes happen by directly manipulating the sheet. That means we can fire
241  * off background events everytime this method is called and not worry about
242  * duplicated jobs.
243  */
244  @Override
245  protected synchronized Sheet createSheet() {
246  Sheet sheet = new Sheet();
247  Sheet.Set sheetSet = Sheet.createPropertiesSet();
248  sheet.put(sheetSet);
249 
250  //This will fire off fresh background tasks.
251  List<NodeProperty<?>> newProperties = getProperties();
252  newProperties.forEach((property) -> {
253  sheetSet.put(property);
254  });
255 
256  return sheet;
257  }
258 
259  @NbBundle.Messages({"AbstractAbstractFileNode.nameColLbl=Name",
260  "AbstractAbstractFileNode.originalName=Original Name",
261  "AbstractAbstractFileNode.createSheet.score.name=S",
262  "AbstractAbstractFileNode.createSheet.comment.name=C",
263  "AbstractAbstractFileNode.createSheet.count.name=O",
264  "AbstractAbstractFileNode.locationColLbl=Location",
265  "AbstractAbstractFileNode.modifiedTimeColLbl=Modified Time",
266  "AbstractAbstractFileNode.changeTimeColLbl=Change Time",
267  "AbstractAbstractFileNode.accessTimeColLbl=Access Time",
268  "AbstractAbstractFileNode.createdTimeColLbl=Created Time",
269  "AbstractAbstractFileNode.sizeColLbl=Size",
270  "AbstractAbstractFileNode.flagsDirColLbl=Flags(Dir)",
271  "AbstractAbstractFileNode.flagsMetaColLbl=Flags(Meta)",
272  "AbstractAbstractFileNode.modeColLbl=Mode",
273  "AbstractAbstractFileNode.useridColLbl=UserID",
274  "AbstractAbstractFileNode.groupidColLbl=GroupID",
275  "AbstractAbstractFileNode.metaAddrColLbl=Meta Addr.",
276  "AbstractAbstractFileNode.attrAddrColLbl=Attr. Addr.",
277  "AbstractAbstractFileNode.typeDirColLbl=Type(Dir)",
278  "AbstractAbstractFileNode.typeMetaColLbl=Type(Meta)",
279  "AbstractAbstractFileNode.knownColLbl=Known",
280  "AbstractAbstractFileNode.md5HashColLbl=MD5 Hash",
281  "AbstractAbstractFileNode.sha256HashColLbl=SHA-256 Hash",
282  "AbstractAbstractFileNode.objectId=Object ID",
283  "AbstractAbstractFileNode.mimeType=MIME Type",
284  "AbstractAbstractFileNode.extensionColLbl=Extension"})
286 
287  NAME(AbstractAbstractFileNode_nameColLbl()),
288  ORIGINAL_NAME(AbstractAbstractFileNode_originalName()),
289  SCORE(AbstractAbstractFileNode_createSheet_score_name()),
290  COMMENT(AbstractAbstractFileNode_createSheet_comment_name()),
291  OCCURRENCES(AbstractAbstractFileNode_createSheet_count_name()),
292  LOCATION(AbstractAbstractFileNode_locationColLbl()),
293  MOD_TIME(AbstractAbstractFileNode_modifiedTimeColLbl()),
294  CHANGED_TIME(AbstractAbstractFileNode_changeTimeColLbl()),
295  ACCESS_TIME(AbstractAbstractFileNode_accessTimeColLbl()),
296  CREATED_TIME(AbstractAbstractFileNode_createdTimeColLbl()),
297  SIZE(AbstractAbstractFileNode_sizeColLbl()),
298  FLAGS_DIR(AbstractAbstractFileNode_flagsDirColLbl()),
299  FLAGS_META(AbstractAbstractFileNode_flagsMetaColLbl()),
300  MODE(AbstractAbstractFileNode_modeColLbl()),
301  USER_ID(AbstractAbstractFileNode_useridColLbl()),
302  GROUP_ID(AbstractAbstractFileNode_groupidColLbl()),
303  META_ADDR(AbstractAbstractFileNode_metaAddrColLbl()),
304  ATTR_ADDR(AbstractAbstractFileNode_attrAddrColLbl()),
305  TYPE_DIR(AbstractAbstractFileNode_typeDirColLbl()),
306  TYPE_META(AbstractAbstractFileNode_typeMetaColLbl()),
307  KNOWN(AbstractAbstractFileNode_knownColLbl()),
308  MD5HASH(AbstractAbstractFileNode_md5HashColLbl()),
309  SHA256HASH(AbstractAbstractFileNode_sha256HashColLbl()),
310  ObjectID(AbstractAbstractFileNode_objectId()),
311  MIMETYPE(AbstractAbstractFileNode_mimeType()),
312  EXTENSION(AbstractAbstractFileNode_extensionColLbl());
313 
314  final private String displayString;
315 
316  private AbstractFilePropertyType(String displayString) {
317  this.displayString = displayString;
318  }
319 
320  @Override
321  public String toString() {
322  return displayString;
323  }
324  }
325 
329  private List<NodeProperty<?>> getProperties() {
330  List<NodeProperty<?>> properties = new ArrayList<>();
331  properties.add(new NodeProperty<>(NAME.toString(), NAME.toString(), NO_DESCR, getContentDisplayName(content)));
332  /*
333  * Initialize an empty place holder value. At the bottom, we kick off a
334  * background task that promises to update these values.
335  */
336 
338  properties.add(new NodeProperty<>(ORIGINAL_NAME.toString(), ORIGINAL_NAME.toString(), NO_DESCR, ""));
339  }
340 
341  // Create place holders for S C O
343  properties.add(new NodeProperty<>(SCORE.toString(), SCORE.toString(), VALUE_LOADING, ""));
344  properties.add(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), VALUE_LOADING, ""));
346  properties.add(new NodeProperty<>(OCCURRENCES.toString(), OCCURRENCES.toString(), VALUE_LOADING, ""));
347  }
348  // Get the SCO columns data in a background task
349  backgroundTasksPool.submit(new GetSCOTask(
350  new WeakReference<>(this), weakPcl));
351  }
352 
353  properties.add(new NodeProperty<>(MOD_TIME.toString(), MOD_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getMtime(), content)));
354  properties.add(new NodeProperty<>(CHANGED_TIME.toString(), CHANGED_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getCtime(), content)));
355  properties.add(new NodeProperty<>(ACCESS_TIME.toString(), ACCESS_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getAtime(), content)));
356  properties.add(new NodeProperty<>(CREATED_TIME.toString(), CREATED_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getCrtime(), content)));
357  properties.add(new NodeProperty<>(SIZE.toString(), SIZE.toString(), NO_DESCR, content.getSize()));
358  properties.add(new NodeProperty<>(FLAGS_DIR.toString(), FLAGS_DIR.toString(), NO_DESCR, content.getDirFlagAsString()));
359  properties.add(new NodeProperty<>(FLAGS_META.toString(), FLAGS_META.toString(), NO_DESCR, content.getMetaFlagsAsString()));
360  properties.add(new NodeProperty<>(KNOWN.toString(), KNOWN.toString(), NO_DESCR, content.getKnown().getName()));
361  properties.add(new NodeProperty<>(LOCATION.toString(), LOCATION.toString(), NO_DESCR, getContentPath(content)));
362  properties.add(new NodeProperty<>(MD5HASH.toString(), MD5HASH.toString(), NO_DESCR, StringUtils.defaultString(content.getMd5Hash())));
363  properties.add(new NodeProperty<>(SHA256HASH.toString(), SHA256HASH.toString(), NO_DESCR, StringUtils.defaultString(content.getSha256Hash())));
364  properties.add(new NodeProperty<>(MIMETYPE.toString(), MIMETYPE.toString(), NO_DESCR, StringUtils.defaultString(content.getMIMEType())));
365  properties.add(new NodeProperty<>(EXTENSION.toString(), EXTENSION.toString(), NO_DESCR, content.getNameExtension()));
366 
367  return properties;
368  }
369 
379  @NbBundle.Messages("AbstractAbstractFileNode.tagsProperty.displayName=Tags")
380  @Deprecated
381  protected void addTagProperty(Sheet.Set sheetSet) {
382  List<ContentTag> tags = getContentTagsFromDatabase();
383  sheetSet.put(new NodeProperty<>("Tags", AbstractAbstractFileNode_tagsProperty_displayName(),
384  NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName())
385  .distinct()
386  .collect(Collectors.joining(", "))));
387  }
388 
399  @Deprecated
400  protected static String getHashSetHitsCsvList(AbstractFile file) {
401  try {
402  return StringUtils.join(file.getHashSetNames(), ", ");
403  } catch (TskCoreException tskCoreException) {
404  logger.log(Level.WARNING, "Error getting hashset hits: ", tskCoreException); //NON-NLS
405  return "";
406  }
407  }
408 
409  @NbBundle.Messages({
410  "AbstractAbstractFileNode.createSheet.count.displayName=O",
411  "AbstractAbstractFileNode.createSheet.count.hashLookupNotRun.description=Hash lookup had not been run on this file when the column was populated",
412  "# {0} - occurrenceCount",
413  "AbstractAbstractFileNode.createSheet.count.description=There were {0} datasource(s) found with occurrences of the MD5 correlation value"})
414  @Override
415  protected Pair<Long, String> getCountPropertyAndDescription(CorrelationAttributeInstance.Type attributeType, String attributeValue,
416  String defaultDescription) {
417  Long count = -1L; //The column renderer will not display negative values, negative value used when count unavailble to preserve sorting
418  String description = defaultDescription;
419  try {
420  //don't perform the query if there is no correlation value
421  if (attributeType != null && StringUtils.isNotBlank(attributeValue)) {
423  description = Bundle.AbstractAbstractFileNode_createSheet_count_description(count);
424  } else if (attributeType != null) {
425  description = Bundle.AbstractAbstractFileNode_createSheet_count_hashLookupNotRun_description();
426  }
427  } catch (CentralRepoException ex) {
428  logger.log(Level.WARNING, "Error getting count of datasources with correlation attribute", ex);
430  logger.log(Level.WARNING, "Unable to normalize data to get count of datasources with correlation attribute", ex);
431  }
432  return Pair.of(count, description);
433  }
434 
435  @NbBundle.Messages({
436  "AbstractAbstractFileNode.createSheet.score.displayName=S",
437  "AbstractAbstractFileNode.createSheet.notableFile.description=File recognized as notable.",
438  "AbstractAbstractFileNode.createSheet.interestingResult.description=File has interesting result associated with it.",
439  "AbstractAbstractFileNode.createSheet.taggedFile.description=File has been tagged.",
440  "AbstractAbstractFileNode.createSheet.notableTaggedFile.description=File tagged with notable tag.",
441  "AbstractAbstractFileNode.createSheet.noScore.description=No score"})
442  @Override
443  protected Pair<DataResultViewerTable.Score, String> getScorePropertyAndDescription(List<Tag> tags) {
445  String description = Bundle.AbstractAbstractFileNode_createSheet_noScore_description();
446  if (content.getKnown() == TskData.FileKnown.BAD) {
448  description = Bundle.AbstractAbstractFileNode_createSheet_notableFile_description();
449  }
450  try {
451  if (score == DataResultViewerTable.Score.NO_SCORE && !content.getArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT).isEmpty()) {
453  description = Bundle.AbstractAbstractFileNode_createSheet_interestingResult_description();
454  }
455  } catch (TskCoreException ex) {
456  logger.log(Level.WARNING, "Error getting artifacts for file: " + content.getName(), ex);
457  }
458  if (!tags.isEmpty() && (score == DataResultViewerTable.Score.NO_SCORE || score == DataResultViewerTable.Score.INTERESTING_SCORE)) {
460  description = Bundle.AbstractAbstractFileNode_createSheet_taggedFile_description();
461  for (Tag tag : tags) {
462  if (tag.getName().getKnownStatus() == TskData.FileKnown.BAD) {
464  description = Bundle.AbstractAbstractFileNode_createSheet_notableTaggedFile_description();
465  break;
466  }
467  }
468  }
469  return Pair.of(score, description);
470  }
471 
472  @NbBundle.Messages({
473  "AbstractAbstractFileNode.createSheet.comment.displayName=C"})
474  @Override
475  protected HasCommentStatus getCommentProperty(List<Tag> tags, CorrelationAttributeInstance attribute) {
476 
478 
479  for (Tag tag : tags) {
480  if (!StringUtils.isBlank(tag.getComment())) {
481  //if the tag is null or empty or contains just white space it will indicate there is not a comment
483  break;
484  }
485  }
486  if (attribute != null && !StringUtils.isBlank(attribute.getComment())) {
489  } else {
491  }
492  }
493  return status;
494  }
495 
502  String getTranslatedFileName() {
503  try {
504  return FileNameTranslationUtil.translate(content.getName());
505  } catch (NoServiceProviderException | TranslationException ex) {
506  logger.log(Level.WARNING, MessageFormat.format("Error translating file name (objID={0}))", content.getId()), ex);
507  return "";
508  }
509  }
510 
516  List<ContentTag> getContentTagsFromDatabase() {
517  List<ContentTag> tags = new ArrayList<>();
518  try {
519  tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByContent(content));
520  } catch (TskCoreException | NoCurrentCaseException ex) {
521  logger.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex);
522  }
523  return tags;
524  }
525 
526  @Override
527  protected List<Tag> getAllTagsFromDatabase() {
528  return new ArrayList<>(getContentTagsFromDatabase());
529  }
530 
531  @Override
533  CorrelationAttributeInstance attribute = null;
535  attribute = CorrelationAttributeUtil.getCorrAttrForFile(content);
536  }
537  return attribute;
538  }
539 
540  static String getContentPath(AbstractFile file) {
541  try {
542  return file.getUniquePath();
543  } catch (TskCoreException ex) {
544  logger.log(Level.SEVERE, "Except while calling Content.getUniquePath() on " + file.getName(), ex); //NON-NLS
545  return ""; //NON-NLS
546  }
547  }
548 
549  static String getContentDisplayName(AbstractFile file) {
550  String name = file.getName();
551  switch (name) {
552  case "..":
553  return DirectoryNode.DOTDOTDIR;
554  case ".":
555  return DirectoryNode.DOTDIR;
556  default:
557  return name;
558  }
559  }
560 
571  static public void fillPropertyMap(Map<String, Object> map, AbstractFile content) {
572  map.put(NAME.toString(), getContentDisplayName(content));
573  map.put(LOCATION.toString(), getContentPath(content));
574  map.put(MOD_TIME.toString(), ContentUtils.getStringTime(content.getMtime(), content));
575  map.put(CHANGED_TIME.toString(), ContentUtils.getStringTime(content.getCtime(), content));
576  map.put(ACCESS_TIME.toString(), ContentUtils.getStringTime(content.getAtime(), content));
577  map.put(CREATED_TIME.toString(), ContentUtils.getStringTime(content.getCrtime(), content));
578  map.put(SIZE.toString(), content.getSize());
579  map.put(FLAGS_DIR.toString(), content.getDirFlagAsString());
580  map.put(FLAGS_META.toString(), content.getMetaFlagsAsString());
581  map.put(KNOWN.toString(), content.getKnown().getName());
582  map.put(MD5HASH.toString(), StringUtils.defaultString(content.getMd5Hash()));
583  map.put(SHA256HASH.toString(), StringUtils.defaultString(content.getSha256Hash()));
584  map.put(MIMETYPE.toString(), StringUtils.defaultString(content.getMIMEType()));
585  map.put(EXTENSION.toString(), content.getNameExtension());
586  }
587 }
synchronized void updateSheet(NodeProperty<?>...newProps)
void removeIngestModuleEventListener(final PropertyChangeListener listener)
static String getStringTime(long epochSeconds, TimeZone tzone)
static synchronized IngestManager getInstance()
static final Set< IngestManager.IngestModuleEvent > INGEST_MODULE_EVENTS_OF_INTEREST
Pair< DataResultViewerTable.Score, String > getScorePropertyAndDescription(List< Tag > tags)
static void fillPropertyMap(Map< String, Object > map, AbstractFile content)
Pair< Long, String > getCountPropertyAndDescription(CorrelationAttributeInstance.Type attributeType, String attributeValue, String defaultDescription)
static CorrelationAttributeInstance getCorrAttrForFile(AbstractFile file)
static void post(String nodeName, Object event)
void addIngestModuleEventListener(final PropertyChangeListener listener)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
HasCommentStatus getCommentProperty(List< Tag > tags, CorrelationAttributeInstance attribute)
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:491
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:536
Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttributeInstance.Type aType, String value)

Copyright © 2012-2021 Basis Technology. Generated on: Tue Jan 19 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.