diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java index 087848dc5c..010beb87d3 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/ContainerSummary.java @@ -25,6 +25,7 @@ import java.util.HashSet; import java.util.Set; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.DataSource; @@ -64,6 +65,11 @@ public class ContainerSummary implements DefaultArtifactUpdateGovernor { return true; } + @Override + public boolean isRefreshRequired(AbstractFile file) { + return true; + } + @Override public Set getArtifactTypeIdsForRefresh() { return ARTIFACT_UPDATE_TYPE_IDS; diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java index 9932a6d120..e753a44a76 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java @@ -28,6 +28,7 @@ import java.util.stream.Collectors; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; @@ -62,6 +63,11 @@ public class MimeTypeSummary implements DefaultUpdateGovernor { return true; } + @Override + public boolean isRefreshRequired(AbstractFile file) { + return true; + } + @Override public boolean isRefreshRequired(IngestManager.IngestJobEvent evt) { return (evt != null && INGEST_JOB_EVENTS.contains(evt)); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java index 0361d53de8..ff4bcae0a0 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java @@ -26,6 +26,7 @@ import java.util.Set; import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; @@ -61,6 +62,11 @@ public class TypesSummary implements DefaultUpdateGovernor { return true; } + @Override + public boolean isRefreshRequired(AbstractFile file) { + return true; + } + @Override public boolean isRefreshRequired(IngestManager.IngestJobEvent evt) { return (evt != null && INGEST_JOB_EVENTS.contains(evt)); diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java index dab88646e0..b8fa2a6fa5 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java @@ -27,6 +27,7 @@ import java.util.logging.Level; import java.util.stream.Collectors; import javax.swing.JPanel; import javax.swing.SwingWorker; +import org.openide.util.Exceptions; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DataFetchResult; @@ -39,6 +40,7 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.UpdateGovernor; import org.sleuthkit.autopsy.ingest.IngestManager.IngestJobEvent; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; +import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.DataSource; @@ -140,6 +142,33 @@ abstract class BaseDataSourceSummaryPanel extends JPanel { return false; } + @Override + public boolean isRefreshRequired(AbstractFile file) { + DataSource currentDataSource = getDataSource(); + if (currentDataSource == null || file == null) { + return false; + } + + // make sure the file is for the current data source + Long fileDsId = null; + try { + Content fileDataSource = file.getDataSource(); + fileDsId = fileDataSource.getId(); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Unable to get the datasource for newly added file", ex); + } + + if (fileDsId != null && currentDataSource.getId() == fileDsId) { + for (UpdateGovernor governor : governors) { + if (governor.isRefreshRequired(file)) { + return true; + } + } + } + + return false; + } + @Override public boolean isRefreshRequired(IngestJobEvent evt) { for (UpdateGovernor governor : governors) { diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultUpdateGovernor.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultUpdateGovernor.java index 6ef7fab040..888e750740 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultUpdateGovernor.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultUpdateGovernor.java @@ -25,6 +25,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; +import org.sleuthkit.datamodel.AbstractFile; /** * The default UpdateGovernor where no updates will be triggered unless @@ -61,4 +62,9 @@ public interface DefaultUpdateGovernor extends UpdateGovernor { default Set getIngestJobEventUpdates() { return Collections.emptySet(); } + + @Override + default boolean isRefreshRequired(AbstractFile evt) { + return false; + } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/EventUpdateHandler.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/EventUpdateHandler.java index 4dbded0009..3e0f5c330e 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/EventUpdateHandler.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/EventUpdateHandler.java @@ -27,6 +27,8 @@ import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager.IngestJobEvent; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; +import org.sleuthkit.autopsy.ingest.events.FileAnalyzedEvent; +import org.sleuthkit.datamodel.AbstractFile; /** * Handles ingest and case events, and determines whether they should trigger an @@ -54,6 +56,9 @@ public class EventUpdateHandler { } else if (IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString().equals(eventType) && evt.getOldValue() instanceof ModuleContentEvent) { ModuleContentEvent contentEvent = (ModuleContentEvent) evt.getOldValue(); return EventUpdateHandler.this.isRefreshRequired(contentEvent); + } else if (IngestManager.IngestModuleEvent.FILE_DONE.toString().equals(eventType) && evt.getNewValue() instanceof AbstractFile) { + AbstractFile analyzedFile = (AbstractFile) evt.getNewValue(); + return EventUpdateHandler.this.isRefreshRequired(analyzedFile); } } return false; @@ -127,6 +132,17 @@ public class EventUpdateHandler { protected boolean isRefreshRequired(ModuleContentEvent evt) { return governor.isRefreshRequired(evt); } + + /** + * Handles whether or not a newly added AbstractFile should trigger an update. + * + * @param evt The AbstractFile. + * + * @return True if an update should occur. + */ + protected boolean isRefreshRequired(AbstractFile evt) { + return governor.isRefreshRequired(evt); + } /** * Handles whether or not a IngestJobEvent should trigger an update. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/UpdateGovernor.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/UpdateGovernor.java index 79d7eb678f..41918afb04 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/UpdateGovernor.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/UpdateGovernor.java @@ -24,6 +24,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.ingest.IngestManager.IngestJobEvent; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; +import org.sleuthkit.datamodel.AbstractFile; /** * Interface for determiining when data should update based on autopsy (i.e. @@ -77,4 +78,13 @@ public interface UpdateGovernor { * @return Whether or not this event should trigger an update. */ boolean isRefreshRequiredForCaseEvent(PropertyChangeEvent evt); + + /** + * Whether or not a newly added AbstractFile should trigger an update. + * + * @param evt The AbstractFile. + * + * @return True if an update should occur. + */ + boolean isRefreshRequired(AbstractFile evt); } diff --git a/Core/src/org/sleuthkit/autopsy/guiutils/RefreshThrottler.java b/Core/src/org/sleuthkit/autopsy/guiutils/RefreshThrottler.java index 2610642761..79893039f7 100755 --- a/Core/src/org/sleuthkit/autopsy/guiutils/RefreshThrottler.java +++ b/Core/src/org/sleuthkit/autopsy/guiutils/RefreshThrottler.java @@ -30,8 +30,8 @@ import org.sleuthkit.autopsy.ingest.IngestManager; /** * Utility class that can be used by UI nodes to reduce the number of - * potentially expensive UI refresh events when DATA_ADDED and CONTENT_CHANGED - * ingest manager events are received. + * potentially expensive UI refresh events when DATA_ADDED, CONTENT_CHANGED, and + * FILE_DONE ingest manager events are received. */ public class RefreshThrottler { @@ -66,7 +66,10 @@ public class RefreshThrottler { private static final long MIN_SECONDS_BETWEEN_REFRESH = 5; - private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED, IngestManager.IngestModuleEvent.CONTENT_CHANGED); + private static final Set INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of( + IngestManager.IngestModuleEvent.DATA_ADDED, + IngestManager.IngestModuleEvent.CONTENT_CHANGED, + IngestManager.IngestModuleEvent.FILE_DONE); /** * A RefreshTask is scheduled to run when an event arrives and there isn't @@ -96,7 +99,8 @@ public class RefreshThrottler { pcl = (PropertyChangeEvent evt) -> { String eventType = evt.getPropertyName(); if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString()) - || eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) { + || eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString()) + || eventType.equals(IngestManager.IngestModuleEvent.FILE_DONE.toString())) { if (!refresher.isRefreshRequired(evt)) { return; }