From ada91b260e7235d4821c0503ad527704b721d3ea Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 16 Sep 2020 12:04:31 -0400 Subject: [PATCH] updates to handle ingest events --- .../datamodel/MimeTypeSummary.java | 16 ++++++++ .../datamodel/TypesSummary.java | 17 +++++++++ .../ui/BaseDataSourceSummaryPanel.java | 21 ++++++++++ .../uiutils/DataFetchWorker.java | 13 +++++-- .../DefaultArtifactUpdateGovernor.java | 17 +++++++++ .../uiutils/DefaultUpdateGovernor.java | 10 +++++ .../uiutils/EventUpdateHandler.java | 38 ++++++++++++++++--- .../uiutils/UpdateGovernor.java | 21 ++++++++-- 8 files changed, 141 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java index f99e9f3a08..9932a6d120 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/MimeTypeSummary.java @@ -20,10 +20,13 @@ package org.sleuthkit.autopsy.datasourcesummary.datamodel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; import java.sql.SQLException; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Set; 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.DataSource; import org.sleuthkit.datamodel.TskCoreException; @@ -35,6 +38,9 @@ public class MimeTypeSummary implements DefaultUpdateGovernor { private final SleuthkitCaseProvider provider; + private static final Set INGEST_JOB_EVENTS = new HashSet<>( + Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); + /** * Main constructor. */ @@ -56,6 +62,16 @@ public class MimeTypeSummary implements DefaultUpdateGovernor { return true; } + @Override + public boolean isRefreshRequired(IngestManager.IngestJobEvent evt) { + return (evt != null && INGEST_JOB_EVENTS.contains(evt)); + } + + @Override + public Set getIngestJobEventUpdates() { + return INGEST_JOB_EVENTS; + } + /** * Get the number of files in the case database for the current data source * which have the specified mimetypes. diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java index 03f0951392..0361d53de8 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/datamodel/TypesSummary.java @@ -20,7 +20,11 @@ package org.sleuthkit.autopsy.datasourcesummary.datamodel; import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultUpdateGovernor; import java.sql.SQLException; +import java.util.Arrays; +import java.util.HashSet; +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.DataSource; import org.sleuthkit.datamodel.TskCoreException; @@ -31,6 +35,9 @@ import org.sleuthkit.datamodel.TskData; */ public class TypesSummary implements DefaultUpdateGovernor { + private static final Set INGEST_JOB_EVENTS = new HashSet<>( + Arrays.asList(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED)); + private final SleuthkitCaseProvider provider; /** @@ -54,6 +61,16 @@ public class TypesSummary implements DefaultUpdateGovernor { return true; } + @Override + public boolean isRefreshRequired(IngestManager.IngestJobEvent evt) { + return (evt != null && INGEST_JOB_EVENTS.contains(evt)); + } + + @Override + public Set getIngestJobEventUpdates() { + return INGEST_JOB_EVENTS; + } + /** * Get count of regular files (not directories) in a data source. * diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java index 30d9e949b7..dab88646e0 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/ui/BaseDataSourceSummaryPanel.java @@ -36,6 +36,7 @@ import org.sleuthkit.autopsy.datasourcesummary.uiutils.EventUpdateHandler; import org.sleuthkit.autopsy.datasourcesummary.uiutils.LoadableComponent; import org.sleuthkit.autopsy.datasourcesummary.uiutils.SwingWorkerSequentialExecutor; 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.BlackboardArtifact; @@ -139,6 +140,17 @@ abstract class BaseDataSourceSummaryPanel extends JPanel { return false; } + @Override + public boolean isRefreshRequired(IngestJobEvent evt) { + for (UpdateGovernor governor : governors) { + if (governor.isRefreshRequired(evt)) { + return true; + } + } + + return false; + } + @Override public boolean isRefreshRequiredForCaseEvent(PropertyChangeEvent evt) { for (UpdateGovernor governor : governors) { @@ -158,6 +170,15 @@ abstract class BaseDataSourceSummaryPanel extends JPanel { .flatMap(governor -> governor.getCaseEventUpdates().stream()) .collect(Collectors.toSet()); } + + @Override + public Set getIngestJobEventUpdates() { + // return the union of all case events sets from delegates. + return governors.stream() + .filter(governor -> governor.getIngestJobEventUpdates() != null) + .flatMap(governor -> governor.getIngestJobEventUpdates().stream()) + .collect(Collectors.toSet()); + } }; /** diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetchWorker.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetchWorker.java index 89f11f544c..a89b273fcc 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetchWorker.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DataFetchWorker.java @@ -71,6 +71,7 @@ public class DataFetchWorker extends SwingWorker { } private static final Logger logger = Logger.getLogger(DataFetchWorker.class.getName()); + private static final int MAX_INNER_EXCEPTION_DEPTH = 100; private final A args; private final DataFetcher processor; @@ -128,9 +129,15 @@ public class DataFetchWorker extends SwingWorker { return; } catch (ExecutionException ex) { Throwable inner = ex.getCause(); - // if cancelled during operation, simply return - if (inner instanceof InterruptedException) { - return; + for (int i = 0; i < MAX_INNER_EXCEPTION_DEPTH; i++) { + if (inner == null) { + break; + } else if (inner instanceof InterruptedException) { + // if cancelled during operation, simply return + return; + } else { + inner = inner.getCause(); + } } // otherwise, there is an error to log diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultArtifactUpdateGovernor.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultArtifactUpdateGovernor.java index b29b73d8f2..8fd4aac64c 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultArtifactUpdateGovernor.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultArtifactUpdateGovernor.java @@ -18,7 +18,11 @@ */ package org.sleuthkit.autopsy.datasourcesummary.uiutils; +import java.util.Arrays; +import java.util.HashSet; import java.util.Set; +import org.sleuthkit.autopsy.ingest.IngestManager; +import org.sleuthkit.autopsy.ingest.IngestManager.IngestJobEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; /** @@ -27,11 +31,24 @@ import org.sleuthkit.autopsy.ingest.ModuleDataEvent; */ public interface DefaultArtifactUpdateGovernor extends DefaultUpdateGovernor { + static final Set INGEST_JOB_EVENTS = new HashSet<>( + Arrays.asList(IngestJobEvent.COMPLETED, IngestJobEvent.CANCELLED)); + @Override default boolean isRefreshRequired(ModuleDataEvent evt) { return getArtifactTypeIdsForRefresh().contains(evt.getBlackboardArtifactType().getTypeID()); } + @Override + default boolean isRefreshRequired(IngestManager.IngestJobEvent evt) { + return (evt != null && INGEST_JOB_EVENTS.contains(evt)); + } + + @Override + default Set getIngestJobEventUpdates() { + return INGEST_JOB_EVENTS; + } + /** * @return The set of artifact type id's that should trigger an update. */ diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultUpdateGovernor.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultUpdateGovernor.java index c6897930f3..6ef7fab040 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultUpdateGovernor.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/DefaultUpdateGovernor.java @@ -22,6 +22,7 @@ import java.beans.PropertyChangeEvent; import java.util.Collections; import java.util.Set; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; @@ -46,9 +47,18 @@ public interface DefaultUpdateGovernor extends UpdateGovernor { return false; } + @Override + default boolean isRefreshRequired(IngestManager.IngestJobEvent evt) { + return false; + } + @Override default Set getCaseEventUpdates() { return Collections.emptySet(); } + @Override + default Set getIngestJobEventUpdates() { + return Collections.emptySet(); + } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/EventUpdateHandler.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/EventUpdateHandler.java index 8a7d89cdc2..4dbded0009 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/EventUpdateHandler.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/EventUpdateHandler.java @@ -24,6 +24,7 @@ import java.util.Set; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.guiutils.RefreshThrottler; 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; @@ -68,17 +69,31 @@ public class EventUpdateHandler { } }; + private final PropertyChangeListener ingestJobEventsListener = (evt) -> { + if (evt == null) { + return; + } + + String eventName = evt.getPropertyName(); + for (IngestJobEvent ingestEvt : IngestJobEvent.values()) { + if (ingestEvt.name().equals(eventName) && isRefreshRequired(ingestEvt)) { + onRefresh(); + } + } + }; + private final UpdateGovernor governor; private final Set caseEvents; + private final Set ingestEvents; private final Runnable onUpdate; /** * Constructor. * - * @param onUpdate The function to call if an update should be required. + * @param onUpdate The function to call if an update should be required. * @param governor The item used to determine if an update is required. If - * the governor requires an update, then onUpdate is - * triggered. + * the governor requires an update, then onUpdate is + * triggered. */ public EventUpdateHandler(Runnable onUpdate, UpdateGovernor governor) { if (onUpdate == null) { @@ -88,7 +103,7 @@ public class EventUpdateHandler { this.onUpdate = onUpdate; this.governor = governor; this.caseEvents = governor.getCaseEventUpdates(); - + this.ingestEvents = governor.getIngestJobEventUpdates(); } /** @@ -113,6 +128,17 @@ public class EventUpdateHandler { return governor.isRefreshRequired(evt); } + /** + * Handles whether or not a IngestJobEvent should trigger an update. + * + * @param evt The IngestJobEvent. + * + * @return True if an update should occur. + */ + protected boolean isRefreshRequired(IngestJobEvent evt) { + return governor.isRefreshRequired(evt); + } + /** * Handles whether or not a case event should trigger an update. * @@ -139,6 +165,7 @@ public class EventUpdateHandler { Case.addEventTypeSubscriber(caseEvents, caseEventsListener); } + IngestManager.getInstance().addIngestJobEventListener(ingestEvents, ingestJobEventsListener); refreshThrottler.registerForIngestModuleEvents(); } @@ -149,7 +176,8 @@ public class EventUpdateHandler { if (!caseEvents.isEmpty()) { Case.removeEventTypeSubscriber(caseEvents, caseEventsListener); } - + + IngestManager.getInstance().removeIngestJobEventListener(ingestEvents, ingestJobEventsListener); refreshThrottler.unregisterEventListener(); } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/UpdateGovernor.java b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/UpdateGovernor.java index c3b7ffb884..79d7eb678f 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/UpdateGovernor.java +++ b/Core/src/org/sleuthkit/autopsy/datasourcesummary/uiutils/UpdateGovernor.java @@ -19,9 +19,9 @@ package org.sleuthkit.autopsy.datasourcesummary.uiutils; import java.beans.PropertyChangeEvent; -import java.util.Collections; import java.util.Set; 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; @@ -34,9 +34,12 @@ public interface UpdateGovernor { /** * @return The set of Case Events for which data should be updated. */ - default Set getCaseEventUpdates() { - return Collections.emptySet(); - } + Set getCaseEventUpdates(); + + /** + * @return The set of Ingest Job Events for which data should be updated. + */ + Set getIngestJobEventUpdates(); /** * Given a module data event, whether or not an update should occur. @@ -56,6 +59,16 @@ public interface UpdateGovernor { */ boolean isRefreshRequired(ModuleContentEvent evt); + /** + * Given an ingest job event, determines whether or not an update should + * occur. + * + * @param evt The event. + * + * @return Whether or not this event should trigger an update. + */ + boolean isRefreshRequired(IngestJobEvent evt); + /** * Given a case event, whether or not an update should occur. *