From 22bb45f80f281673084d1954063f6bee6ee083bf Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 13 Apr 2020 11:56:40 -0400 Subject: [PATCH 1/7] added open file systems method to case open method --- .../sleuthkit/autopsy/casemodule/Case.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index b70845e3df..4ca47bd658 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -60,6 +60,7 @@ import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; +import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; @@ -125,6 +126,7 @@ import org.sleuthkit.datamodel.CaseDbConnectionInfo; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.FileSystem; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.Report; import org.sleuthkit.datamodel.SleuthkitCase; @@ -1979,6 +1981,8 @@ public class Case { openAppServiceCaseResources(progressIndicator); checkForCancellation(); openCommunicationChannels(progressIndicator); + checkForCancellation(); + openFileSystems(); return null; } catch (CaseActionException ex) { @@ -1996,6 +2000,51 @@ public class Case { throw ex; } } + + /** + * Reads a sector from each file system of each image of a case to do an eager open of the filesystems in case. + * @throws CaseActionCancelledException Exception thrown if task is cancelled. + */ + private void openFileSystems() throws CaseActionCancelledException { + String caseName = (this.caseDb != null) ? this.caseDb.getDatabaseName() : "null"; + + List images = null; + try { + images = this.caseDb.getImages(); + } catch (TskCoreException ex) { + logger.log( + Level.SEVERE, + String.format("Could not obtain images while opening case: %s.", caseName), + ex); + + return; + } + + checkForCancellation(); + byte[] tempBuff = new byte[512]; + + for (Image image : images) { + Collection fileSystems = this.caseDb.getFileSystems(image); + checkForCancellation(); + for (FileSystem fileSystem : fileSystems) { + try { + fileSystem.read(tempBuff, 0, 512); + } + catch (TskCoreException ex) { + String imageStr = image.getName(); + String fileSysStr = fileSystem.getName(); + + logger.log( + Level.WARNING, + String.format("Could not open filesystem: %s in image: %s for case: %s.", fileSysStr, imageStr, caseName), + ex); + } + + checkForCancellation(); + } + + } + } /** * A case action (interface CaseAction) that opens a case, deletes From a87bea71d488b7ffff91dfe3f803d00f51fb005b Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Mon, 13 Apr 2020 15:57:45 -0400 Subject: [PATCH 2/7] adding progress updates --- .../org/sleuthkit/autopsy/casemodule/Case.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 4ca47bd658..9071880d0b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -1982,7 +1982,7 @@ public class Case { checkForCancellation(); openCommunicationChannels(progressIndicator); checkForCancellation(); - openFileSystems(); + openFileSystems(progressIndicator); return null; } catch (CaseActionException ex) { @@ -2001,13 +2001,20 @@ public class Case { } } + /** * Reads a sector from each file system of each image of a case to do an eager open of the filesystems in case. + * @param progressIndicator The progress indicator for the operation. * @throws CaseActionCancelledException Exception thrown if task is cancelled. */ - private void openFileSystems() throws CaseActionCancelledException { - String caseName = (this.caseDb != null) ? this.caseDb.getDatabaseName() : "null"; + @Messages({ + "# {0} - case", "Case.openFileSystems.retrievingImages=Retrieving images for case: {0}...", + "# {0} - image", "Case.openFileSystems.openingImage=Opening all filesystems for image: {0}..." + }) + private void openFileSystems(ProgressIndicator progressIndicator) throws CaseActionCancelledException { + String caseName = (this.caseDb != null) ? this.caseDb.getDatabaseName() : ""; + progressIndicator.progress(Bundle.Case_openFileSystems_retrievingImages(caseName)); List images = null; try { images = this.caseDb.getImages(); @@ -2024,6 +2031,10 @@ public class Case { byte[] tempBuff = new byte[512]; for (Image image : images) { + String imageStr = image.getName(); + + progressIndicator.progress(Bundle.Case_openFileSystems_openingImage(imageStr)); + Collection fileSystems = this.caseDb.getFileSystems(image); checkForCancellation(); for (FileSystem fileSystem : fileSystems) { @@ -2031,7 +2042,6 @@ public class Case { fileSystem.read(tempBuff, 0, 512); } catch (TskCoreException ex) { - String imageStr = image.getName(); String fileSysStr = fileSystem.getName(); logger.log( From e135994242144644889b0ce3455151191b3e1d46 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 14 Apr 2020 08:17:30 -0400 Subject: [PATCH 3/7] open background task thread --- .../sleuthkit/autopsy/casemodule/Case.java | 133 ++++++++++++------ 1 file changed, 92 insertions(+), 41 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 9071880d0b..d351efd5dd 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.casemodule; import org.sleuthkit.autopsy.featureaccess.FeatureAccessUtils; import com.google.common.annotations.Beta; import com.google.common.eventbus.Subscribe; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData; import java.awt.Frame; import java.awt.event.ActionEvent; @@ -1982,7 +1983,7 @@ public class Case { checkForCancellation(); openCommunicationChannels(progressIndicator); checkForCancellation(); - openFileSystems(progressIndicator); + openFileSystemsInBackground(); return null; } catch (CaseActionException ex) { @@ -2001,59 +2002,109 @@ public class Case { } } - + private static Future backgroundOpenFileSystemsFuture = null; + private static final ExecutorService startIngestJobsExecutor = + Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("Case-open-file-systems-%d").build()); + /** - * Reads a sector from each file system of each image of a case to do an eager open of the filesystems in case. - * @param progressIndicator The progress indicator for the operation. + * Starts a background task that reads a sector from each file system of each image of a case to do an eager open of + * the filesystems in case. If this method is called before another background file system read has finished the earlier + * one will be cancelled. + * * @throws CaseActionCancelledException Exception thrown if task is cancelled. */ @Messages({ "# {0} - case", "Case.openFileSystems.retrievingImages=Retrieving images for case: {0}...", "# {0} - image", "Case.openFileSystems.openingImage=Opening all filesystems for image: {0}..." }) - private void openFileSystems(ProgressIndicator progressIndicator) throws CaseActionCancelledException { - String caseName = (this.caseDb != null) ? this.caseDb.getDatabaseName() : ""; + private void openFileSystemsInBackground() throws CaseActionCancelledException { + if (backgroundOpenFileSystemsFuture != null && !backgroundOpenFileSystemsFuture.isDone()) + backgroundOpenFileSystemsFuture.cancel(true); - progressIndicator.progress(Bundle.Case_openFileSystems_retrievingImages(caseName)); - List images = null; - try { - images = this.caseDb.getImages(); - } catch (TskCoreException ex) { - logger.log( - Level.SEVERE, - String.format("Could not obtain images while opening case: %s.", caseName), - ex); - - return; + BackgroundOpenFileSystemsTask backgroundTask = new BackgroundOpenFileSystemsTask(this.caseDb, new LoggingProgressIndicator()); + backgroundOpenFileSystemsFuture = startIngestJobsExecutor.submit(backgroundTask); + } + + + + /** + * This task opens all the filesystems of all images in the case in the background. + * It also responds to cancellation events. + */ + private static class BackgroundOpenFileSystemsTask implements Runnable { + private final SleuthkitCase tskCase; + private final String caseName; + private final ProgressIndicator progressIndicator; + + + BackgroundOpenFileSystemsTask(SleuthkitCase tskCase, ProgressIndicator progressIndicator) { + this.tskCase = tskCase; + this.progressIndicator = progressIndicator; + caseName = (this.tskCase != null) ? this.tskCase.getDatabaseName() : ""; } - checkForCancellation(); - byte[] tempBuff = new byte[512]; + private List getImages() { + progressIndicator.progress(Bundle.Case_openFileSystems_retrievingImages(caseName)); + List images = null; + try { + images = this.tskCase.getImages(); + } catch (TskCoreException ex) { + logger.log( + Level.SEVERE, + String.format("Could not obtain images while opening case: %s.", caseName), + ex); - for (Image image : images) { - String imageStr = image.getName(); - - progressIndicator.progress(Bundle.Case_openFileSystems_openingImage(imageStr)); - - Collection fileSystems = this.caseDb.getFileSystems(image); - checkForCancellation(); - for (FileSystem fileSystem : fileSystems) { - try { - fileSystem.read(tempBuff, 0, 512); - } - catch (TskCoreException ex) { - String fileSysStr = fileSystem.getName(); - - logger.log( - Level.WARNING, - String.format("Could not open filesystem: %s in image: %s for case: %s.", fileSysStr, imageStr, caseName), - ex); - } - - checkForCancellation(); + return null; } - + return images; } + + private void openFileSystems(List images) throws CaseActionCancelledException { + byte[] tempBuff = new byte[512]; + + for (Image image : images) { + String imageStr = image.getName(); + + progressIndicator.progress(Bundle.Case_openFileSystems_openingImage(imageStr)); + + Collection fileSystems = this.tskCase.getFileSystems(image); + checkForCancellation(); + for (FileSystem fileSystem : fileSystems) { + try { + fileSystem.read(tempBuff, 0, 512); + } + catch (TskCoreException ex) { + String fileSysStr = fileSystem.getName(); + + logger.log( + Level.WARNING, + String.format("Could not open filesystem: %s in image: %s for case: %s.", fileSysStr, imageStr, caseName), + ex); + } + + checkForCancellation(); + } + + } + } + + @Override + public void run() { + try { + checkForCancellation(); + List images = getImages(); + if (images == null) + return; + + checkForCancellation(); + openFileSystems(images); + } + catch (CaseActionCancelledException ex) { + // EMPTY + // No action needs to be taken when this task is cancelled. + } + } + } /** From 7d186a78bded940c74a972adf53582a925bfd569 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 14 Apr 2020 15:49:13 -0400 Subject: [PATCH 4/7] commenting --- .../sleuthkit/autopsy/casemodule/Case.java | 119 +++++++++++------- 1 file changed, 77 insertions(+), 42 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index d351efd5dd..248525ccab 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -159,6 +159,9 @@ public class Case { private static final Logger logger = Logger.getLogger(Case.class.getName()); private static final AutopsyEventPublisher eventPublisher = new AutopsyEventPublisher(); private static final Object caseActionSerializationLock = new Object(); + private static Future backgroundOpenFileSystemsFuture = null; + private static final ExecutorService startIngestJobsExecutor + = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("Case-open-file-systems-%d").build()); private static volatile Frame mainFrame; private static volatile Case currentCase; private final CaseMetadata metadata; @@ -2001,48 +2004,71 @@ public class Case { throw ex; } } - - private static Future backgroundOpenFileSystemsFuture = null; - private static final ExecutorService startIngestJobsExecutor = - Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("Case-open-file-systems-%d").build()); - + /** - * Starts a background task that reads a sector from each file system of each image of a case to do an eager open of - * the filesystems in case. If this method is called before another background file system read has finished the earlier - * one will be cancelled. - * - * @throws CaseActionCancelledException Exception thrown if task is cancelled. + * Starts a background task that reads a sector from each file system of + * each image of a case to do an eager open of the filesystems in case. If + * this method is called before another background file system read has + * finished the earlier one will be cancelled. + * + * @throws CaseActionCancelledException Exception thrown if task is + * cancelled. */ @Messages({ "# {0} - case", "Case.openFileSystems.retrievingImages=Retrieving images for case: {0}...", "# {0} - image", "Case.openFileSystems.openingImage=Opening all filesystems for image: {0}..." }) private void openFileSystemsInBackground() throws CaseActionCancelledException { - if (backgroundOpenFileSystemsFuture != null && !backgroundOpenFileSystemsFuture.isDone()) + if (backgroundOpenFileSystemsFuture != null && !backgroundOpenFileSystemsFuture.isDone()) { backgroundOpenFileSystemsFuture.cancel(true); - + } + BackgroundOpenFileSystemsTask backgroundTask = new BackgroundOpenFileSystemsTask(this.caseDb, new LoggingProgressIndicator()); backgroundOpenFileSystemsFuture = startIngestJobsExecutor.submit(backgroundTask); } - - - + /** - * This task opens all the filesystems of all images in the case in the background. - * It also responds to cancellation events. + * This task opens all the filesystems of all images in the case in the + * background. It also responds to cancellation events. */ private static class BackgroundOpenFileSystemsTask implements Runnable { + private final SleuthkitCase tskCase; private final String caseName; private final ProgressIndicator progressIndicator; - + /** + * Main constructor for the BackgroundOpenFileSystemsTask. + * + * @param tskCase The case database to query for filesystems + * to open. + * @param progressIndicator The progress indicator for file systems + * opened. + */ BackgroundOpenFileSystemsTask(SleuthkitCase tskCase, ProgressIndicator progressIndicator) { this.tskCase = tskCase; this.progressIndicator = progressIndicator; caseName = (this.tskCase != null) ? this.tskCase.getDatabaseName() : ""; } - + + /** + * Checks if thread has been cancelled and throws an + * InterruptedException if it has. + * + * @throws InterruptedException The exception thrown if the operation + * has been cancelled. + */ + private void checkIfCancelled() throws InterruptedException { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + } + + /** + * Retrieves all images present in the sleuthkit case. + * + * @return All images present in the sleuthkit case. + */ private List getImages() { progressIndicator.progress(Bundle.Case_openFileSystems_retrievingImages(caseName)); List images = null; @@ -2050,61 +2076,70 @@ public class Case { images = this.tskCase.getImages(); } catch (TskCoreException ex) { logger.log( - Level.SEVERE, - String.format("Could not obtain images while opening case: %s.", caseName), - ex); + Level.SEVERE, + String.format("Could not obtain images while opening case: %s.", caseName), + ex); return null; } return images; } - - private void openFileSystems(List images) throws CaseActionCancelledException { + + /** + * Opens all file systems in the list of images provided. + * + * @param images The images whose file systems will be opened. + * + * @throws CaseActionCancelledException The exception thrown in the + * event that the operation is + * cancelled prior to completion. + */ + private void openFileSystems(List images) throws InterruptedException { byte[] tempBuff = new byte[512]; - + for (Image image : images) { String imageStr = image.getName(); progressIndicator.progress(Bundle.Case_openFileSystems_openingImage(imageStr)); Collection fileSystems = this.tskCase.getFileSystems(image); - checkForCancellation(); + checkIfCancelled(); for (FileSystem fileSystem : fileSystems) { try { - fileSystem.read(tempBuff, 0, 512); - } - catch (TskCoreException ex) { + fileSystem.read(tempBuff, 0, 512); + } catch (TskCoreException ex) { String fileSysStr = fileSystem.getName(); logger.log( - Level.WARNING, - String.format("Could not open filesystem: %s in image: %s for case: %s.", fileSysStr, imageStr, caseName), - ex); + Level.WARNING, + String.format("Could not open filesystem: %s in image: %s for case: %s.", fileSysStr, imageStr, caseName), + ex); } - checkForCancellation(); + checkIfCancelled(); } } } - + @Override public void run() { try { - checkForCancellation(); + checkIfCancelled(); List images = getImages(); - if (images == null) + if (images == null) { return; + } - checkForCancellation(); + checkIfCancelled(); openFileSystems(images); - } - catch (CaseActionCancelledException ex) { - // EMPTY - // No action needs to be taken when this task is cancelled. + } catch (InterruptedException ex) { + logger.log( + Level.INFO, + String.format("Background operation opening all file systems in %s has been cancelled.", caseName)); } } - + } /** From 0e2520d5c0ea3dbd4839ab351d66ad573e52d39d Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 14 Apr 2020 15:53:47 -0400 Subject: [PATCH 5/7] commenting --- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 248525ccab..917ddf6210 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -2071,9 +2071,8 @@ public class Case { */ private List getImages() { progressIndicator.progress(Bundle.Case_openFileSystems_retrievingImages(caseName)); - List images = null; try { - images = this.tskCase.getImages(); + return this.tskCase.getImages(); } catch (TskCoreException ex) { logger.log( Level.SEVERE, @@ -2082,7 +2081,6 @@ public class Case { return null; } - return images; } /** From 7def5251e09a8bad3bd31276fbed8e5cb400f6eb Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 16 Apr 2020 14:20:31 -0400 Subject: [PATCH 6/7] fixes based on review --- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 917ddf6210..dbfabb7a3e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -61,7 +61,6 @@ import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; -import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; @@ -160,7 +159,7 @@ public class Case { private static final AutopsyEventPublisher eventPublisher = new AutopsyEventPublisher(); private static final Object caseActionSerializationLock = new Object(); private static Future backgroundOpenFileSystemsFuture = null; - private static final ExecutorService startIngestJobsExecutor + private static final ExecutorService backgroundOpenFileSystemsExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("Case-open-file-systems-%d").build()); private static volatile Frame mainFrame; private static volatile Case currentCase; @@ -2007,8 +2006,8 @@ public class Case { /** * Starts a background task that reads a sector from each file system of - * each image of a case to do an eager open of the filesystems in case. If - * this method is called before another background file system read has + * each image of a case to do an eager open of the filesystems in the case. + * If this method is called before another background file system read has * finished the earlier one will be cancelled. * * @throws CaseActionCancelledException Exception thrown if task is @@ -2018,13 +2017,13 @@ public class Case { "# {0} - case", "Case.openFileSystems.retrievingImages=Retrieving images for case: {0}...", "# {0} - image", "Case.openFileSystems.openingImage=Opening all filesystems for image: {0}..." }) - private void openFileSystemsInBackground() throws CaseActionCancelledException { + private void openFileSystemsInBackground() { if (backgroundOpenFileSystemsFuture != null && !backgroundOpenFileSystemsFuture.isDone()) { backgroundOpenFileSystemsFuture.cancel(true); } BackgroundOpenFileSystemsTask backgroundTask = new BackgroundOpenFileSystemsTask(this.caseDb, new LoggingProgressIndicator()); - backgroundOpenFileSystemsFuture = startIngestJobsExecutor.submit(backgroundTask); + backgroundOpenFileSystemsFuture = backgroundOpenFileSystemsExecutor.submit(backgroundTask); } /** From 5fb341f51451bd85cc331662113306e6ee5e27cf Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 16 Apr 2020 14:49:55 -0400 Subject: [PATCH 7/7] rename of executor service --- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index dbfabb7a3e..5a703a4ea9 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -159,8 +159,8 @@ public class Case { private static final AutopsyEventPublisher eventPublisher = new AutopsyEventPublisher(); private static final Object caseActionSerializationLock = new Object(); private static Future backgroundOpenFileSystemsFuture = null; - private static final ExecutorService backgroundOpenFileSystemsExecutor - = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("Case-open-file-systems-%d").build()); + private static final ExecutorService openFileSystemsExecutor + = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("case-open-file-systems-%d").build()); private static volatile Frame mainFrame; private static volatile Case currentCase; private final CaseMetadata metadata; @@ -2023,7 +2023,7 @@ public class Case { } BackgroundOpenFileSystemsTask backgroundTask = new BackgroundOpenFileSystemsTask(this.caseDb, new LoggingProgressIndicator()); - backgroundOpenFileSystemsFuture = backgroundOpenFileSystemsExecutor.submit(backgroundTask); + backgroundOpenFileSystemsFuture = openFileSystemsExecutor.submit(backgroundTask); } /**