Autopsy  4.13.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 2011-2019 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.util.ArrayList;
25 import java.util.EnumSet;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.logging.Level;
30 import java.util.stream.Collectors;
31 import org.apache.commons.io.FilenameUtils;
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;
52 import static org.sleuthkit.autopsy.datamodel.Bundle.*;
62 import org.sleuthkit.datamodel.AbstractFile;
63 import org.sleuthkit.datamodel.BlackboardArtifact;
64 import org.sleuthkit.datamodel.Content;
65 import org.sleuthkit.datamodel.ContentTag;
66 import org.sleuthkit.datamodel.Tag;
67 import org.sleuthkit.datamodel.TskCoreException;
68 import org.sleuthkit.datamodel.TskData;
69 
75 public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends AbstractContentNode<T> {
76 
77  private static final Logger logger = Logger.getLogger(AbstractAbstractFileNode.class.getName());
78 
79  private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE,
81  private static final Set<IngestManager.IngestModuleEvent> INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(CONTENT_CHANGED);
82 
86  AbstractAbstractFileNode(T abstractFile) {
87  super(abstractFile);
88  String ext = abstractFile.getNameExtension();
89  if (StringUtils.isNotBlank(ext)) {
90  ext = "." + ext;
91  // If this is an archive file we will listen for ingest events
92  // that will notify us when new content has been identified.
93  if (FileTypeExtensions.getArchiveExtensions().contains(ext)) {
95  }
96  }
97 
99  backgroundTasksPool.submit(new TranslationTask(
100  new WeakReference<>(this), weakPcl));
101  }
102 
103  // Listen for case events so that we can detect when the case is closed
104  // or when tags are added.
106  }
107 
117  @Override
118  protected void finalize() throws Throwable {
119  super.finalize();
120  removeListeners();
121  }
122 
123  private void removeListeners() {
126  }
127 
128  private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
129  String eventType = evt.getPropertyName();
130 
131  // Is this a content changed event?
132  if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
133  if ((evt.getOldValue() instanceof ModuleContentEvent) == false) {
134  return;
135  }
136  ModuleContentEvent moduleContentEvent = (ModuleContentEvent) evt.getOldValue();
137  if ((moduleContentEvent.getSource() instanceof Content) == false) {
138  return;
139  }
140  Content newContent = (Content) moduleContentEvent.getSource();
141 
142  // Does the event indicate that content has been added to *this* file?
143  if (getContent().getId() == newContent.getId()) {
144  // If so, refresh our children.
145  try {
146  // We only want to refresh our parents children if we are in the
147  // data sources branch of the tree. The parent nodes in other
148  // branches of the tree (e.g. File Types and Deleted Files) do
149  // not need to be refreshed.
150  BaseChildFactory.post(getParentNode().getName(), new RefreshKeysEvent());
151  } catch (NullPointerException ex) {
152  // Skip
153  } catch (NoSuchEventBusException ex) {
154  logger.log(Level.WARNING, "Failed to post key refresh event", ex); //NON-NLS
155  }
156  }
157  } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
158  if (evt.getNewValue() == null) {
159  // case was closed. Remove listeners so that we don't get called with a stale case handle
160  removeListeners();
161  }
162  /*
163  * No need to do any asynchrony around tag added, deleted or CR
164  * change events, they are so infrequent and user driven that we can
165  * just keep a simple blocking approach, where we go out to the
166  * database ourselves.
167  */
168  } else if (eventType.equals(Case.Events.CONTENT_TAG_ADDED.toString())) {
170  if (event.getAddedTag().getContent().equals(content)) {
171  List<Tag> tags = this.getAllTagsFromDatabase();
172  Pair<Score, String> scorePropAndDescr = getScorePropertyAndDescription(tags);
173  Score value = scorePropAndDescr.getLeft();
174  String descr = scorePropAndDescr.getRight();
176  updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), descr, value),
177  new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute))
178  );
179  }
180  } else if (eventType.equals(Case.Events.CONTENT_TAG_DELETED.toString())) {
182  if (event.getDeletedTagInfo().getContentID() == content.getId()) {
183  List<Tag> tags = getAllTagsFromDatabase();
184  Pair<Score, String> scorePropAndDescr = getScorePropertyAndDescription(tags);
185  Score value = scorePropAndDescr.getLeft();
186  String descr = scorePropAndDescr.getRight();
188  updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), descr, value),
189  new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute))
190  );
191  }
192  } else if (eventType.equals(Case.Events.CR_COMMENT_CHANGED.toString())) {
194  if (event.getContentID() == content.getId()) {
195  List<Tag> tags = getAllTagsFromDatabase();
197  updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, getCommentProperty(tags, attribute)));
198  }
199  } else if (eventType.equals(NodeSpecificEvents.TRANSLATION_AVAILABLE.toString())) {
200  this.setDisplayName(evt.getNewValue().toString());
201  //Set the tooltip
202  this.setShortDescription(content.getName());
203  updateSheet(new NodeProperty<>(ORIGINAL_NAME.toString(), ORIGINAL_NAME.toString(), NO_DESCR, content.getName()));
204  } else if (eventType.equals(NodeSpecificEvents.SCO_AVAILABLE.toString()) && !UserPreferences.getHideSCOColumns()) {
205  SCOData scoData = (SCOData) evt.getNewValue();
206  if (scoData.getScoreAndDescription() != null) {
207  updateSheet(new NodeProperty<>(SCORE.toString(), SCORE.toString(), scoData.getScoreAndDescription().getRight(), scoData.getScoreAndDescription().getLeft()));
208  }
209  if (scoData.getComment() != null) {
210  updateSheet(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), NO_DESCR, scoData.getComment()));
211  }
212  if (scoData.getCountAndDescription() != null) {
213  updateSheet(new NodeProperty<>(OCCURRENCES.toString(), OCCURRENCES.toString(), scoData.getCountAndDescription().getRight(), scoData.getCountAndDescription().getLeft()));
214  }
215  }
216  };
225  private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
226 
227  /*
228  * This is called when the node is first initialized. Any new updates or
229  * changes happen by directly manipulating the sheet. That means we can fire
230  * off background events everytime this method is called and not worry about
231  * duplicated jobs.
232  */
233  @Override
234  protected synchronized Sheet createSheet() {
235  Sheet sheet = new Sheet();
236  Sheet.Set sheetSet = Sheet.createPropertiesSet();
237  sheet.put(sheetSet);
238 
239  //This will fire off fresh background tasks.
240  List<NodeProperty<?>> newProperties = getProperties();
241  newProperties.forEach((property) -> {
242  sheetSet.put(property);
243  });
244 
245  return sheet;
246  }
247 
248  @NbBundle.Messages({"AbstractAbstractFileNode.nameColLbl=Name",
249  "AbstractAbstractFileNode.originalName=Original Name",
250  "AbstractAbstractFileNode.createSheet.score.name=S",
251  "AbstractAbstractFileNode.createSheet.comment.name=C",
252  "AbstractAbstractFileNode.createSheet.count.name=O",
253  "AbstractAbstractFileNode.locationColLbl=Location",
254  "AbstractAbstractFileNode.modifiedTimeColLbl=Modified Time",
255  "AbstractAbstractFileNode.changeTimeColLbl=Change Time",
256  "AbstractAbstractFileNode.accessTimeColLbl=Access Time",
257  "AbstractAbstractFileNode.createdTimeColLbl=Created Time",
258  "AbstractAbstractFileNode.sizeColLbl=Size",
259  "AbstractAbstractFileNode.flagsDirColLbl=Flags(Dir)",
260  "AbstractAbstractFileNode.flagsMetaColLbl=Flags(Meta)",
261  "AbstractAbstractFileNode.modeColLbl=Mode",
262  "AbstractAbstractFileNode.useridColLbl=UserID",
263  "AbstractAbstractFileNode.groupidColLbl=GroupID",
264  "AbstractAbstractFileNode.metaAddrColLbl=Meta Addr.",
265  "AbstractAbstractFileNode.attrAddrColLbl=Attr. Addr.",
266  "AbstractAbstractFileNode.typeDirColLbl=Type(Dir)",
267  "AbstractAbstractFileNode.typeMetaColLbl=Type(Meta)",
268  "AbstractAbstractFileNode.knownColLbl=Known",
269  "AbstractAbstractFileNode.md5HashColLbl=MD5 Hash",
270  "AbstractAbstractFileNode.objectId=Object ID",
271  "AbstractAbstractFileNode.mimeType=MIME Type",
272  "AbstractAbstractFileNode.extensionColLbl=Extension"})
274 
275  NAME(AbstractAbstractFileNode_nameColLbl()),
276  ORIGINAL_NAME(AbstractAbstractFileNode_originalName()),
277  SCORE(AbstractAbstractFileNode_createSheet_score_name()),
278  COMMENT(AbstractAbstractFileNode_createSheet_comment_name()),
279  OCCURRENCES(AbstractAbstractFileNode_createSheet_count_name()),
280  LOCATION(AbstractAbstractFileNode_locationColLbl()),
281  MOD_TIME(AbstractAbstractFileNode_modifiedTimeColLbl()),
282  CHANGED_TIME(AbstractAbstractFileNode_changeTimeColLbl()),
283  ACCESS_TIME(AbstractAbstractFileNode_accessTimeColLbl()),
284  CREATED_TIME(AbstractAbstractFileNode_createdTimeColLbl()),
285  SIZE(AbstractAbstractFileNode_sizeColLbl()),
286  FLAGS_DIR(AbstractAbstractFileNode_flagsDirColLbl()),
287  FLAGS_META(AbstractAbstractFileNode_flagsMetaColLbl()),
288  MODE(AbstractAbstractFileNode_modeColLbl()),
289  USER_ID(AbstractAbstractFileNode_useridColLbl()),
290  GROUP_ID(AbstractAbstractFileNode_groupidColLbl()),
291  META_ADDR(AbstractAbstractFileNode_metaAddrColLbl()),
292  ATTR_ADDR(AbstractAbstractFileNode_attrAddrColLbl()),
293  TYPE_DIR(AbstractAbstractFileNode_typeDirColLbl()),
294  TYPE_META(AbstractAbstractFileNode_typeMetaColLbl()),
295  KNOWN(AbstractAbstractFileNode_knownColLbl()),
296  MD5HASH(AbstractAbstractFileNode_md5HashColLbl()),
297  ObjectID(AbstractAbstractFileNode_objectId()),
298  MIMETYPE(AbstractAbstractFileNode_mimeType()),
299  EXTENSION(AbstractAbstractFileNode_extensionColLbl());
300 
301  final private String displayString;
302 
303  private AbstractFilePropertyType(String displayString) {
304  this.displayString = displayString;
305  }
306 
307  @Override
308  public String toString() {
309  return displayString;
310  }
311  }
312 
316  private List<NodeProperty<?>> getProperties() {
317  List<NodeProperty<?>> properties = new ArrayList<>();
318  properties.add(new NodeProperty<>(NAME.toString(), NAME.toString(), NO_DESCR, getContentDisplayName(content)));
319  /*
320  * Initialize an empty place holder value. At the bottom, we kick off a
321  * background task that promises to update these values.
322  */
323 
325  properties.add(new NodeProperty<>(ORIGINAL_NAME.toString(), ORIGINAL_NAME.toString(), NO_DESCR, ""));
326  }
327 
328  // Create place holders for S C O
330  properties.add(new NodeProperty<>(SCORE.toString(), SCORE.toString(), VALUE_LOADING, ""));
331  properties.add(new NodeProperty<>(COMMENT.toString(), COMMENT.toString(), VALUE_LOADING, ""));
332  if (EamDb.isEnabled()) {
333  properties.add(new NodeProperty<>(OCCURRENCES.toString(), OCCURRENCES.toString(), VALUE_LOADING, ""));
334  }
335  // Get the SCO columns data in a background task
336  backgroundTasksPool.submit(new GetSCOTask(
337  new WeakReference<>(this), weakPcl));
338  }
339 
340  properties.add(new NodeProperty<>(MOD_TIME.toString(), MOD_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getMtime(), content)));
341  properties.add(new NodeProperty<>(CHANGED_TIME.toString(), CHANGED_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getCtime(), content)));
342  properties.add(new NodeProperty<>(ACCESS_TIME.toString(), ACCESS_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getAtime(), content)));
343  properties.add(new NodeProperty<>(CREATED_TIME.toString(), CREATED_TIME.toString(), NO_DESCR, ContentUtils.getStringTime(content.getCrtime(), content)));
344  properties.add(new NodeProperty<>(SIZE.toString(), SIZE.toString(), NO_DESCR, content.getSize()));
345  properties.add(new NodeProperty<>(FLAGS_DIR.toString(), FLAGS_DIR.toString(), NO_DESCR, content.getDirFlagAsString()));
346  properties.add(new NodeProperty<>(FLAGS_META.toString(), FLAGS_META.toString(), NO_DESCR, content.getMetaFlagsAsString()));
347  properties.add(new NodeProperty<>(KNOWN.toString(), KNOWN.toString(), NO_DESCR, content.getKnown().getName()));
348  properties.add(new NodeProperty<>(LOCATION.toString(), LOCATION.toString(), NO_DESCR, getContentPath(content)));
349  properties.add(new NodeProperty<>(MD5HASH.toString(), MD5HASH.toString(), NO_DESCR, StringUtils.defaultString(content.getMd5Hash())));
350  properties.add(new NodeProperty<>(MIMETYPE.toString(), MIMETYPE.toString(), NO_DESCR, StringUtils.defaultString(content.getMIMEType())));
351  properties.add(new NodeProperty<>(EXTENSION.toString(), EXTENSION.toString(), NO_DESCR, content.getNameExtension()));
352 
353  return properties;
354  }
355 
365  @NbBundle.Messages("AbstractAbstractFileNode.tagsProperty.displayName=Tags")
366  @Deprecated
367  protected void addTagProperty(Sheet.Set sheetSet) {
368  List<ContentTag> tags = getContentTagsFromDatabase();
369  sheetSet.put(new NodeProperty<>("Tags", AbstractAbstractFileNode_tagsProperty_displayName(),
370  NO_DESCR, tags.stream().map(t -> t.getName().getDisplayName())
371  .distinct()
372  .collect(Collectors.joining(", "))));
373  }
374 
385  @Deprecated
386  protected static String getHashSetHitsCsvList(AbstractFile file) {
387  try {
388  return StringUtils.join(file.getHashSetNames(), ", ");
389  } catch (TskCoreException tskCoreException) {
390  logger.log(Level.WARNING, "Error getting hashset hits: ", tskCoreException); //NON-NLS
391  return "";
392  }
393  }
394 
395  @NbBundle.Messages({
396  "AbstractAbstractFileNode.createSheet.count.displayName=O",
397  "AbstractAbstractFileNode.createSheet.count.hashLookupNotRun.description=Hash lookup had not been run on this file when the column was populated",
398  "# {0} - occurrenceCount",
399  "AbstractAbstractFileNode.createSheet.count.description=There were {0} datasource(s) found with occurrences of the MD5 correlation value"})
400  @Override
401  protected Pair<Long, String> getCountPropertyAndDescription(CorrelationAttributeInstance.Type attributeType, String attributeValue,
402  String defaultDescription) {
403  Long count = -1L; //The column renderer will not display negative values, negative value used when count unavailble to preserve sorting
404  String description = defaultDescription;
405  try {
406  //don't perform the query if there is no correlation value
407  if (attributeType != null && StringUtils.isNotBlank(attributeValue)) {
408  count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(attributeType, attributeValue);
409  description = Bundle.AbstractAbstractFileNode_createSheet_count_description(count);
410  } else if (attributeType != null) {
411  description = Bundle.AbstractAbstractFileNode_createSheet_count_hashLookupNotRun_description();
412  }
413  } catch (EamDbException ex) {
414  logger.log(Level.WARNING, "Error getting count of datasources with correlation attribute", ex);
416  logger.log(Level.WARNING, "Unable to normalize data to get count of datasources with correlation attribute", ex);
417  }
418  return Pair.of(count, description);
419  }
420 
421  @NbBundle.Messages({
422  "AbstractAbstractFileNode.createSheet.score.displayName=S",
423  "AbstractAbstractFileNode.createSheet.notableFile.description=File recognized as notable.",
424  "AbstractAbstractFileNode.createSheet.interestingResult.description=File has interesting result associated with it.",
425  "AbstractAbstractFileNode.createSheet.taggedFile.description=File has been tagged.",
426  "AbstractAbstractFileNode.createSheet.notableTaggedFile.description=File tagged with notable tag.",
427  "AbstractAbstractFileNode.createSheet.noScore.description=No score"})
428  @Override
429  protected Pair<DataResultViewerTable.Score, String> getScorePropertyAndDescription(List<Tag> tags) {
431  String description = Bundle.AbstractAbstractFileNode_createSheet_noScore_description();
432  if (content.getKnown() == TskData.FileKnown.BAD) {
434  description = Bundle.AbstractAbstractFileNode_createSheet_notableFile_description();
435  }
436  try {
437  if (score == DataResultViewerTable.Score.NO_SCORE && !content.getArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT).isEmpty()) {
439  description = Bundle.AbstractAbstractFileNode_createSheet_interestingResult_description();
440  }
441  } catch (TskCoreException ex) {
442  logger.log(Level.WARNING, "Error getting artifacts for file: " + content.getName(), ex);
443  }
444  if (!tags.isEmpty() && (score == DataResultViewerTable.Score.NO_SCORE || score == DataResultViewerTable.Score.INTERESTING_SCORE)) {
446  description = Bundle.AbstractAbstractFileNode_createSheet_taggedFile_description();
447  for (Tag tag : tags) {
448  if (tag.getName().getKnownStatus() == TskData.FileKnown.BAD) {
450  description = Bundle.AbstractAbstractFileNode_createSheet_notableTaggedFile_description();
451  break;
452  }
453  }
454  }
455  return Pair.of(score, description);
456  }
457 
458  @NbBundle.Messages({
459  "AbstractAbstractFileNode.createSheet.comment.displayName=C"})
460  @Override
461  protected HasCommentStatus getCommentProperty(List<Tag> tags, CorrelationAttributeInstance attribute) {
462 
464 
465  for (Tag tag : tags) {
466  if (!StringUtils.isBlank(tag.getComment())) {
467  //if the tag is null or empty or contains just white space it will indicate there is not a comment
469  break;
470  }
471  }
472  if (attribute != null && !StringUtils.isBlank(attribute.getComment())) {
475  } else {
477  }
478  }
479  return status;
480  }
481 
486  String getTranslatedFileName() {
487  //If already in complete English, don't translate.
488  if (content.getName().matches("^\\p{ASCII}+$")) {
489  return "";
490  }
491  TextTranslationService tts = TextTranslationService.getInstance();
492  if (tts.hasProvider()) {
493  //Seperate out the base and ext from the contents file name.
494  String base = FilenameUtils.getBaseName(content.getName());
495  try {
496  String translation = tts.translate(base);
497  String ext = FilenameUtils.getExtension(content.getName());
498 
499  //If we have no extension, then we shouldn't add the .
500  String extensionDelimiter = (ext.isEmpty()) ? "" : ".";
501 
502  //Talk directly to this nodes pcl, fire an update when the translation
503  //is complete.
504  if (!translation.isEmpty()) {
505  return translation + extensionDelimiter + ext;
506  }
507  } catch (NoServiceProviderException noServiceEx) {
508  logger.log(Level.WARNING, "Translate unsuccessful because no TextTranslator "
509  + "implementation was provided.", noServiceEx.getMessage());
510  } catch (TranslationException noTranslationEx) {
511  logger.log(Level.WARNING, "Could not successfully translate file name "
512  + content.getName(), noTranslationEx.getMessage());
513  }
514  }
515  return "";
516  }
517 
523  List<ContentTag> getContentTagsFromDatabase() {
524  List<ContentTag> tags = new ArrayList<>();
525  try {
526  tags.addAll(Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagsByContent(content));
527  } catch (TskCoreException | NoCurrentCaseException ex) {
528  logger.log(Level.SEVERE, "Failed to get tags for content " + content.getName(), ex);
529  }
530  return tags;
531  }
532 
533  @Override
534  protected List<Tag> getAllTagsFromDatabase() {
535  return new ArrayList<>(getContentTagsFromDatabase());
536  }
537 
538  @Override
540  CorrelationAttributeInstance attribute = null;
542  attribute = EamArtifactUtil.getInstanceFromContent(content);
543  }
544  return attribute;
545  }
546 
547  static String getContentPath(AbstractFile file) {
548  try {
549  return file.getUniquePath();
550  } catch (TskCoreException ex) {
551  logger.log(Level.SEVERE, "Except while calling Content.getUniquePath() on " + file.getName(), ex); //NON-NLS
552  return ""; //NON-NLS
553  }
554  }
555 
556  static String getContentDisplayName(AbstractFile file) {
557  String name = file.getName();
558  switch (name) {
559  case "..":
560  return DirectoryNode.DOTDOTDIR;
561  case ".":
562  return DirectoryNode.DOTDIR;
563  default:
564  return name;
565  }
566  }
567 
578  static public void fillPropertyMap(Map<String, Object> map, AbstractFile content) {
579  map.put(NAME.toString(), getContentDisplayName(content));
580  map.put(LOCATION.toString(), getContentPath(content));
581  map.put(MOD_TIME.toString(), ContentUtils.getStringTime(content.getMtime(), content));
582  map.put(CHANGED_TIME.toString(), ContentUtils.getStringTime(content.getCtime(), content));
583  map.put(ACCESS_TIME.toString(), ContentUtils.getStringTime(content.getAtime(), content));
584  map.put(CREATED_TIME.toString(), ContentUtils.getStringTime(content.getCrtime(), content));
585  map.put(SIZE.toString(), content.getSize());
586  map.put(FLAGS_DIR.toString(), content.getDirFlagAsString());
587  map.put(FLAGS_META.toString(), content.getMetaFlagsAsString());
588  map.put(KNOWN.toString(), content.getKnown().getName());
589  map.put(MD5HASH.toString(), StringUtils.defaultString(content.getMd5Hash()));
590  map.put(MIMETYPE.toString(), StringUtils.defaultString(content.getMIMEType()));
591  map.put(EXTENSION.toString(), content.getNameExtension());
592  }
593 }
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)
Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttributeInstance.Type aType, String value)
static CorrelationAttributeInstance getInstanceFromContent(Content content)
Pair< Long, String > getCountPropertyAndDescription(CorrelationAttributeInstance.Type attributeType, String attributeValue, String defaultDescription)
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:486
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:531

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