19 package org.sleuthkit.autopsy.datasourcesummary.ui;
21 import java.beans.PropertyChangeEvent;
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.List;
26 import java.util.function.Predicate;
27 import java.util.logging.Level;
28 import java.util.stream.Collectors;
29 import javax.swing.JPanel;
30 import javax.swing.SwingWorker;
31 import org.openide.util.NbBundle.Messages;
56 abstract class BaseDataSourceSummaryPanel
extends JPanel {
58 private static final long serialVersionUID = 1L;
60 private static final Logger logger = Logger.getLogger(BaseDataSourceSummaryPanel.class.getName());
62 private final SwingWorkerSequentialExecutor executor =
new SwingWorkerSequentialExecutor();
63 private final IngestModuleCheckUtil ingestModuleCheck =
new IngestModuleCheckUtil();
64 private final EventUpdateHandler updateHandler;
65 private final List<UpdateGovernor> governors;
67 private DataSource dataSource;
75 private final UpdateGovernor updateGovernor =
new UpdateGovernor() {
84 private boolean isInDataSource(BlackboardArtifact art, DataSource ds) {
87 return (art.getDataSource() != null && art.getDataSource().getId() == ds.getId());
88 }
catch (TskCoreException ex) {
89 logger.log(Level.WARNING,
"There was an error fetching datasource for artifact.", ex);
95 public boolean isRefreshRequired(ModuleDataEvent evt) {
96 DataSource ds = getDataSource();
98 if (ds == null || evt == null) {
104 if (evt.getArtifacts() != null
105 && !evt.getArtifacts().isEmpty()
106 && !evt.getArtifacts().stream().anyMatch((art) -> isInDataSource(art, ds))) {
111 for (UpdateGovernor governor : governors) {
112 if (governor.isRefreshRequired(evt)) {
121 public boolean isRefreshRequired(ModuleContentEvent evt) {
122 DataSource ds = getDataSource();
124 if (ds == null || evt == null) {
131 if (evt.getSource() instanceof Content
132 && ((Content) evt.getSource()).getDataSource() != null
133 && ((Content) evt.getSource()).getDataSource().getId() != ds.getId()) {
136 }
catch (TskCoreException ex) {
138 logger.log(Level.WARNING,
"There was an error fetching datasource for content.", ex);
141 for (UpdateGovernor governor : governors) {
142 if (governor.isRefreshRequired(evt)) {
151 public boolean isRefreshRequired(AbstractFile file) {
152 DataSource currentDataSource = getDataSource();
153 if (currentDataSource == null || file == null) {
158 Long fileDsId = null;
160 Content fileDataSource = file.getDataSource();
161 fileDsId = fileDataSource.getId();
162 }
catch (TskCoreException ex) {
163 logger.log(Level.WARNING,
"Unable to get the datasource for newly added file", ex);
166 if (fileDsId != null && currentDataSource.getId() == fileDsId) {
167 for (UpdateGovernor governor : governors) {
168 if (governor.isRefreshRequired(file)) {
178 public boolean isRefreshRequired(IngestJobEvent evt) {
179 for (UpdateGovernor governor : governors) {
180 if (governor.isRefreshRequired(evt)) {
189 public boolean isRefreshRequiredForCaseEvent(PropertyChangeEvent evt) {
190 for (UpdateGovernor governor : governors) {
191 if (governor.isRefreshRequiredForCaseEvent(evt)) {
200 public Set<Case.Events> getCaseEventUpdates() {
202 return governors.stream()
203 .filter(governor -> governor.getCaseEventUpdates() != null)
204 .flatMap(governor -> governor.getCaseEventUpdates().stream())
205 .collect(Collectors.toSet());
209 public Set<IngestJobEvent> getIngestJobEventUpdates() {
211 return governors.stream()
212 .filter(governor -> governor.getIngestJobEventUpdates() != null)
213 .flatMap(governor -> governor.getIngestJobEventUpdates().stream())
214 .collect(Collectors.toSet());
224 protected BaseDataSourceSummaryPanel(UpdateGovernor... governors) {
225 this.governors = (governors == null) ? Collections.emptyList() : Arrays.asList(governors);
226 this.updateHandler =
new EventUpdateHandler(this::onRefresh, updateGovernor);
227 this.updateHandler.register();
233 public void close() {
234 executor.cancelRunning();
235 updateHandler.unregister();
243 synchronized void setDataSource(DataSource dataSource) {
244 this.dataSource = dataSource;
245 this.executor.cancelRunning();
246 onNewDataSource(this.dataSource);
252 protected synchronized DataSource getDataSource() {
253 return this.dataSource;
262 protected void submit(List<? extends SwingWorker<?, ?>> workers) {
263 executor.submit(workers);
271 synchronized void onRefresh() {
273 fetchInformation(this.dataSource);
282 protected abstract void fetchInformation(DataSource dataSource);
292 protected void fetchInformation(List<DataFetchComponents<DataSource, ?>> dataFetchComponents, DataSource dataSource) {
293 if (dataSource == null || !Case.isCaseOpen()) {
294 dataFetchComponents.forEach((item) -> item.getResultHandler()
295 .accept(DataFetchResult.getSuccessResult(null)));
298 List<DataFetchWorker<?, ?>> workers = dataFetchComponents
300 .map((components) ->
new DataFetchWorker<>(components, dataSource))
301 .collect(Collectors.toList());
304 if (!workers.isEmpty()) {
315 protected abstract void onNewDataSource(DataSource dataSource);
326 protected void onNewDataSource(
327 List<DataFetchComponents<DataSource, ?>> dataFetchComponents,
328 List<? extends LoadableComponent<?>> loadableComponents,
329 DataSource dataSource) {
332 if (dataSource == null || !Case.isCaseOpen()) {
333 dataFetchComponents.forEach((item) -> item.getResultHandler()
334 .accept(DataFetchResult.getSuccessResult(null)));
338 loadableComponents.forEach((table) -> table.showDefaultLoadingMessage());
340 fetchInformation(dataSource);
352 "# {0} - module name",
353 "BaseDataSourceSummaryPanel_defaultNotIngestMessage=The {0} ingest module has not been run on this data source."
355 protected String getDefaultNoIngestMessage(String moduleName) {
356 return Bundle.BaseDataSourceSummaryPanel_defaultNotIngestMessage(moduleName);
364 protected IngestModuleCheckUtil getIngestModuleCheckUtil() {
365 return this.ingestModuleCheck;
381 protected <T>
void showResultWithModuleCheck(LoadableComponent<List<T>> component, DataFetchResult<List<T>> result, String factoryClass, String moduleName) {
382 Predicate<List<T>> hasResults = (lst) -> lst != null && !lst.isEmpty();
383 showResultWithModuleCheck(component, result, hasResults, factoryClass, moduleName);
401 protected <T>
void showResultWithModuleCheck(LoadableComponent<T> component, DataFetchResult<T> result,
402 Predicate<T> hasResults, String factoryClass, String moduleName) {
404 if (result != null && result.getResultType() == ResultType.SUCCESS && !hasResults.test(result.getData())) {
406 if (!ingestModuleCheck.isModuleIngested(getDataSource(), factoryClass)) {
407 component.showMessage(getDefaultNoIngestMessage(moduleName));
410 }
catch (TskCoreException | SleuthkitCaseProviderException ex) {
411 logger.log(Level.WARNING,
"There was an error while checking for ingest modules for datasource.", ex);
415 component.showDataFetchResult(result);