diff --git a/.gitignore b/.gitignore
index 418d944b1e..1400fb33be 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,8 @@
!/CoreLibs/nbproject/project.xml
!/CoreLibs/nbproject/project.properties
+/Core/test/qa-functional/data/
+
/KeywordSearch/release/
/KeywordSearch/build/
/KeywordSearch/dist/
diff --git a/.travis.yml b/.travis.yml
index 90b51996f9..8cde465f7d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,10 +13,14 @@ before_install:
install:
- sudo apt-get install testdisk
- cd sleuthkit/sleuthkit
- - sh install-sleuthkit.sh
-script:
+ - sh travis_build.sh
+script:
+ - set -e
+ - echo "building autopsy..." && echo -en 'travis_fold:start:script.build\\r'
- cd $TRAVIS_BUILD_DIR/
- - ant build
+ - ant -q build
+ - echo -en 'travis_fold:end:script.build\\r'
+ - echo "testing autopsy..." && echo -en 'travis_fold:start:script.tests\\r'
- cd Core/
- - xvfb-run ant test
-
+ - xvfb-run ant -q test
+ - echo -en 'travis_fold:end:script.tests\\r'
diff --git a/Core/build.xml b/Core/build.xml
index 3555ff0711..401d0dfb6b 100644
--- a/Core/build.xml
+++ b/Core/build.xml
@@ -82,16 +82,20 @@
verbose="true"/>
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
diff --git a/Core/manifest.mf b/Core/manifest.mf
index 260c73c542..67d3366e22 100644
--- a/Core/manifest.mf
+++ b/Core/manifest.mf
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
OpenIDE-Module: org.sleuthkit.autopsy.core/10
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties
OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml
-OpenIDE-Module-Implementation-Version: 22
+OpenIDE-Module-Implementation-Version: 23
OpenIDE-Module-Requires: org.openide.windows.WindowManager
AutoUpdate-Show-In-Client: true
AutoUpdate-Essential-Module: true
diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties
index 02df4b01bb..7ae5484bc9 100644
--- a/Core/nbproject/project.properties
+++ b/Core/nbproject/project.properties
@@ -18,7 +18,20 @@ file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbi
file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar
file.reference.sqlite-jdbc-3.8.11.jar=release/modules/ext/sqlite-jdbc-3.8.11.jar
file.reference.StixLib.jar=release/modules/ext/StixLib.jar
-file.reference.sleuthkit-postgresql-4.6.0.jar=release/modules/ext/sleuthkit-postgresql-4.6.0.jar
+file.reference.sleuthkit-postgresql-4.6.1.jar=release/modules/ext/sleuthkit-postgresql-4.6.1.jar
+file.reference.bcprov-jdk15on-1.54.jar=release/modules/ext/bcprov-jdk15on-1.54.jar
+file.reference.jackcess-2.1.8.jar=release/modules/ext/jackcess-2.1.8.jar
+file.reference.jackcess-encrypt-2.1.2.jar=release/modules/ext/jackcess-encrypt-2.1.2.jar
+file.reference.jempbox-1.8.13.jar=release/modules/ext/jempbox-1.8.13.jar
+file.reference.javax.ws.rs-api-2.0.1.jar=release/modules/ext/javax.ws.rs-api-2.0.1.jar
+file.reference.cxf-core-3.0.16.jar=release/modules/ext/cxf-core-3.0.16.jar
+file.reference.cxf-rt-frontend-jaxrs-3.0.16.jar=release/modules/ext/cxf-rt-frontend-jaxrs-3.0.16.jar
+file.reference.cxf-rt-rs-client-3.0.16.jar=release/modules/ext/cxf-rt-rs-client-3.0.16.jar
+file.reference.cxf-rt-transports-http-3.0.16.jar=release/modules/ext/cxf-rt-transports-http-3.0.16.jar
+file.reference.fontbox-2.0.8.jar=release/modules/ext/fontbox-2.0.8.jar
+file.reference.pdfbox-2.0.8.jar=release/modules/ext/pdfbox-2.0.8.jar
+file.reference.pdfbox-tools-2.0.8.jar=release/modules/ext/pdfbox-tools-2.0.8.jar
+file.reference.sleuthkit-postgresql-4.6.1.jar=release/modules/ext/sleuthkit-postgresql-4.6.1.jar
file.reference.tika-core-1.17.jar=release/modules/ext/tika-core-1.17.jar
file.reference.tika-parsers-1.17.jar=release/modules/ext/tika-parsers-1.17.jar
file.reference.curator-client-2.8.0.jar=release/modules/ext/curator-client-2.8.0.jar
@@ -34,5 +47,5 @@ nbm.homepage=http://www.sleuthkit.org/
nbm.module.author=Brian Carrier
nbm.needs.restart=true
source.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0-sources.jar
-spec.version.base=10.10
+spec.version.base=10.11
diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml
index 0159ec9880..ac3ec60d44 100644
--- a/Core/nbproject/project.xml
+++ b/Core/nbproject/project.xml
@@ -327,6 +327,7 @@
org.sleuthkit.autopsy.eventsorg.sleuthkit.autopsy.filesearchorg.sleuthkit.autopsy.guiutils
+ org.sleuthkit.autopsy.healthmonitororg.sleuthkit.autopsy.ingestorg.sleuthkit.autopsy.keywordsearchserviceorg.sleuthkit.autopsy.menuactions
@@ -347,8 +348,8 @@
release/modules/ext/jdom-2.0.5.jar
- ext/sleuthkit-postgresql-4.6.0.jar
- release/modules/ext/sleuthkit-postgresql-4.6.0.jar
+ ext/sleuthkit-postgresql-4.6.1.jar
+ release/modules/ext/sleuthkit-postgresql-4.6.1.jarext/opencv-248.jar
@@ -410,10 +411,58 @@
ext/curator-client-2.8.0.jarrelease/modules/ext/curator-client-2.8.0.jar
+
+ ext/bcprov-jdk15on-1.54.jar
+ release/modules/ext/bcprov-jdk15on-1.54.jar
+
+
+ ext/jackcess-2.1.8.jar
+ release/modules/ext/jackcess-2.1.8.jar
+
+
+ ext/jackcess-encrypt-2.1.2.jar
+ release/modules/ext/jackcess-encrypt-2.1.2.jar
+
+
+ ext/jempbox-1.8.13.jar
+ release/modules/ext/jempbox-1.8.13.jar
+
+
+ ext/javax.ws.rs-api-2.0.1.jar
+ release/modules/ext/javax.ws.rs-api-2.0.1.jar
+
+
+ ext/cxf-rt-rs-client-3.0.16.jar
+ release/modules/ext/cxf-rt-rs-client-3.0.16.jar
+
+
+ ext/cxf-rt-transports-http-3.0.16.jar
+ release/modules/ext/cxf-rt-transports-http-3.0.16.jar
+
+
+ ext/cxf-core-3.0.16.jar
+ release/modules/ext/cxf-core-3.0.16.jar
+
+
+ ext/cxf-rt-frontend-jaxrs-3.0.16.jar
+ release/modules/ext/cxf-rt-frontend-jaxrs-3.0.16.jar
+ ext/tika-parsers-1.17.jarrelease/modules/ext/tika-parsers-1.17.jar
+
+ ext/fontbox-2.0.8.jar
+ release/modules/ext/fontbox-2.0.8.jar
+
+
+ ext/pdfbox-2.0.8.jar
+ release/modules/ext/pdfbox-2.0.8.jar
+
+
+ ext/pdfbox-tools-2.0.8.jar
+ release/modules/ext/pdfbox-tools-2.0.8.jar
+ ext/sqlite-jdbc-3.8.11.jarrelease/modules/ext/sqlite-jdbc-3.8.11.jar
diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java
index 47bd201ec1..7ad185ac8e 100644
--- a/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/AddBlackboardArtifactTagAction.java
@@ -84,7 +84,7 @@ public class AddBlackboardArtifactTagAction extends AddTagAction {
new Thread(() -> {
for (BlackboardArtifact artifact : selectedArtifacts) {
try {
- Case.getOpenCase().getServices().getTagsManager().addBlackboardArtifactTag(artifact, tagName, comment);
+ Case.getCurrentCaseThrows().getServices().getTagsManager().addBlackboardArtifactTag(artifact, tagName, comment);
} catch (TskCoreException | NoCurrentCaseException ex) {
Logger.getLogger(AddBlackboardArtifactTagAction.class.getName()).log(Level.SEVERE, "Error tagging result", ex); //NON-NLS
SwingUtilities.invokeLater(() -> {
diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddBookmarkTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddBookmarkTagAction.java
index 9e99922775..d6090b2ace 100644
--- a/Core/src/org/sleuthkit/autopsy/actions/AddBookmarkTagAction.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/AddBookmarkTagAction.java
@@ -45,7 +45,7 @@ public class AddBookmarkTagAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
try {
- Map tagNamesMap = Case.getOpenCase().getServices().getTagsManager().getDisplayNamesToTagNamesMap();
+ Map tagNamesMap = Case.getCurrentCaseThrows().getServices().getTagsManager().getDisplayNamesToTagNamesMap();
TagName bookmarkTagName = tagNamesMap.get(BOOKMARK);
/*
diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java
index dad777585f..602789735d 100644
--- a/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/AddContentTagAction.java
@@ -140,7 +140,7 @@ public class AddContentTagAction extends AddTagAction {
}
}
- Case.getOpenCase().getServices().getTagsManager().addContentTag(file, tagName, comment);
+ Case.getCurrentCaseThrows().getServices().getTagsManager().addContentTag(file, tagName, comment);
} catch (TskCoreException | NoCurrentCaseException ex) {
Logger.getLogger(AddContentTagAction.class.getName()).log(Level.SEVERE, "Error tagging result", ex); //NON-NLS
AbstractFile fileCopy = file;
diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddTagAction.java
index 12e23bdb30..7d0212b51c 100644
--- a/Core/src/org/sleuthkit/autopsy/actions/AddTagAction.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/AddTagAction.java
@@ -93,7 +93,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
// Get the current set of tag names.
Map tagNamesMap = null;
try {
- TagsManager tagsManager = Case.getOpenCase().getServices().getTagsManager();
+ TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap());
} catch (TskCoreException | NoCurrentCaseException ex) {
Logger.getLogger(TagsManager.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
@@ -170,7 +170,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup {
private void getAndAddTag(String tagDisplayName, TagName tagName, String comment) {
Case openCase;
try {
- openCase = Case.getOpenCase();
+ openCase = Case.getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
return;
diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java
index 28aa03bed8..18ae9ac7e5 100644
--- a/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteBlackboardArtifactTagAction.java
@@ -73,7 +73,7 @@ public class DeleteBlackboardArtifactTagAction extends AbstractAction {
new Thread(() -> {
for (BlackboardArtifactTag tag : selectedTags) {
try {
- Case.getOpenCase().getServices().getTagsManager().deleteBlackboardArtifactTag(tag);
+ Case.getCurrentCaseThrows().getServices().getTagsManager().deleteBlackboardArtifactTag(tag);
} catch (TskCoreException | NoCurrentCaseException ex) {
Logger.getLogger(DeleteBlackboardArtifactTagAction.class.getName()).log(Level.SEVERE, "Error deleting tag", ex); //NON-NLS
SwingUtilities.invokeLater(() -> {
diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java
index 065a023c2f..07cce02bfc 100644
--- a/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteContentTagAction.java
@@ -72,7 +72,7 @@ public class DeleteContentTagAction extends AbstractAction {
new Thread(() -> {
for (ContentTag tag : selectedTags) {
try {
- Case.getOpenCase().getServices().getTagsManager().deleteContentTag(tag);
+ Case.getCurrentCaseThrows().getServices().getTagsManager().deleteContentTag(tag);
} catch (TskCoreException | NoCurrentCaseException ex) {
Logger.getLogger(DeleteContentTagAction.class.getName()).log(Level.SEVERE, "Error deleting tag", ex); //NON-NLS
SwingUtilities.invokeLater(() -> {
diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java
index ce99fb1ec4..008cb419ff 100644
--- a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java
@@ -98,7 +98,7 @@ public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implem
protected Void doInBackground() throws Exception {
TagsManager tagsManager;
try {
- tagsManager = Case.getOpenCase().getServices().getTagsManager();
+ tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Error untagging artifact. No open case found.", ex); //NON-NLS
Platform.runLater(()
@@ -155,7 +155,7 @@ public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implem
Map tagNamesMap = null;
try {
// Get the current set of tag names.
- TagsManager tagsManager = Case.getOpenCase().getServices().getTagsManager();
+ TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap());
} catch (TskCoreException | NoCurrentCaseException ex) {
@@ -168,7 +168,7 @@ public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implem
if (null != tagNamesMap && !tagNamesMap.isEmpty()) {
try {
List existingTagsList
- = Case.getOpenCase().getServices().getTagsManager()
+ = Case.getCurrentCaseThrows().getServices().getTagsManager()
.getBlackboardArtifactTagsByArtifact(artifact);
for (Map.Entry entry : tagNamesMap.entrySet()) {
diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java
index abc316b33f..f336cd888f 100644
--- a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java
@@ -98,7 +98,7 @@ public class DeleteFileContentTagAction extends AbstractAction implements Presen
protected Void doInBackground() throws Exception {
TagsManager tagsManager;
try {
- tagsManager = Case.getOpenCase().getServices().getTagsManager();
+ tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Error untagging file. No open case found.", ex); //NON-NLS
Platform.runLater(() ->
@@ -152,7 +152,7 @@ public class DeleteFileContentTagAction extends AbstractAction implements Presen
Map tagNamesMap = null;
try {
// Get the current set of tag names.
- TagsManager tagsManager = Case.getOpenCase().getServices().getTagsManager();
+ TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
tagNamesMap = new TreeMap<>(tagsManager.getDisplayNamesToTagNamesMap());
} catch (TskCoreException | NoCurrentCaseException ex) {
@@ -165,7 +165,7 @@ public class DeleteFileContentTagAction extends AbstractAction implements Presen
if (null != tagNamesMap && !tagNamesMap.isEmpty()) {
try {
List existingTagsList =
- Case.getOpenCase().getServices().getTagsManager()
+ Case.getCurrentCaseThrows().getServices().getTagsManager()
.getContentTagsByContent(file);
for (Map.Entry entry : tagNamesMap.entrySet()) {
diff --git a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java
index f295a613a5..51665012cd 100644
--- a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java
@@ -139,7 +139,7 @@ public class GetTagNameAndCommentDialog extends JDialog {
// Tag name DTOs may be null (user tag names that have not been used do
// not exist in the database).
try {
- TagsManager tagsManager = Case.getOpenCase().getServices().getTagsManager();
+ TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
tagNamesSet.addAll(tagsManager.getAllTagNames());
} catch (TskCoreException | NoCurrentCaseException ex) {
diff --git a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java
index 4bdbf0bd29..21785f2003 100644
--- a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java
@@ -110,7 +110,7 @@ public class GetTagNameDialog extends JDialog {
// Get the current set of tag names and hash them for a speedy lookup in
// case the user chooses an existing tag name from the tag names table.
try {
- TagsManager tagsManager = Case.getOpenCase().getServices().getTagsManager();
+ TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
tagNamesMap.putAll(tagsManager.getDisplayNamesToTagNamesMap());
} catch (TskCoreException | NoCurrentCaseException ex) {
Logger.getLogger(GetTagNameDialog.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
@@ -348,7 +348,7 @@ public class GetTagNameDialog extends JDialog {
if (tagName == null) {
try {
- tagName = Case.getOpenCase().getServices().getTagsManager().addTagName(tagDisplayName, userTagDescription, TagName.HTML_COLOR.NONE, status);
+ tagName = Case.getCurrentCaseThrows().getServices().getTagsManager().addTagName(tagDisplayName, userTagDescription, TagName.HTML_COLOR.NONE, status);
dispose();
} catch (TskCoreException | NoCurrentCaseException ex) {
Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, "Error adding " + tagDisplayName + " tag name", ex); //NON-NLS
@@ -361,7 +361,7 @@ public class GetTagNameDialog extends JDialog {
tagName = null;
} catch (TagsManager.TagNameAlreadyExistsException ex) {
try {
- tagName = Case.getOpenCase().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(tagDisplayName);
+ tagName = Case.getCurrentCaseThrows().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(tagDisplayName);
} catch (TskCoreException | NoCurrentCaseException ex1) {
Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, tagDisplayName + " exists in database but an error occurred in retrieving it.", ex1); //NON-NLS
JOptionPane.showMessageDialog(this,
diff --git a/Core/src/org/sleuthkit/autopsy/actions/OpenLogFolderAction.java b/Core/src/org/sleuthkit/autopsy/actions/OpenLogFolderAction.java
index 021ecd6278..fb178c797d 100644
--- a/Core/src/org/sleuthkit/autopsy/actions/OpenLogFolderAction.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/OpenLogFolderAction.java
@@ -58,7 +58,7 @@ public final class OpenLogFolderAction implements ActionListener {
/*
* Open the log directory for the case.
*/
- Case currentCase = Case.getOpenCase();
+ Case currentCase = Case.getCurrentCaseThrows();
logDir = new File(currentCase.getLogDirectoryPath());
} catch (NoCurrentCaseException ex) {
/*
diff --git a/Core/src/org/sleuthkit/autopsy/actions/OpenOutputFolderAction.java b/Core/src/org/sleuthkit/autopsy/actions/OpenOutputFolderAction.java
index c79a559b2d..29b8d67960 100644
--- a/Core/src/org/sleuthkit/autopsy/actions/OpenOutputFolderAction.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/OpenOutputFolderAction.java
@@ -57,7 +57,7 @@ public final class OpenOutputFolderAction extends CallableSystemAction {
public void performAction() {
File outputDir;
try {
- Case currentCase = Case.getOpenCase();
+ Case currentCase = Case.getCurrentCaseThrows();
outputDir = new File(currentCase.getOutputDirectory());
if (outputDir.exists()) {
try {
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java
index 21a7bca103..cbcb06c936 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java
@@ -109,7 +109,7 @@ class AddImageTask implements Runnable {
public void run() {
Case currentCase;
try {
- currentCase = Case.getOpenCase();
+ currentCase = Case.getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Exception while getting open case.", ex);
return;
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java
index 23a963bf6a..6c6097717e 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardAddingProgressPanel.java
@@ -345,7 +345,7 @@ class AddImageWizardAddingProgressPanel extends ShortcutWizardDescriptorPanel {
new Thread(() -> {
try {
- Case.getOpenCase().notifyAddingDataSource(dataSourceId);
+ Case.getCurrentCaseThrows().notifyAddingDataSource(dataSourceId);
} catch (NoCurrentCaseException ex) {
Logger.getLogger(AddImageWizardAddingProgressVisual.class.getName()).log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS
}
@@ -417,9 +417,9 @@ class AddImageWizardAddingProgressPanel extends ShortcutWizardDescriptorPanel {
new Thread(() -> {
try {
if (!contents.isEmpty()) {
- Case.getOpenCase().notifyDataSourceAdded(contents.get(0), dataSourceId);
+ Case.getCurrentCaseThrows().notifyDataSourceAdded(contents.get(0), dataSourceId);
} else {
- Case.getOpenCase().notifyFailedAddingDataSource(dataSourceId);
+ Case.getCurrentCaseThrows().notifyFailedAddingDataSource(dataSourceId);
}
} catch (NoCurrentCaseException ex) {
Logger.getLogger(AddImageWizardAddingProgressVisual.class.getName()).log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardSelectDspVisual.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardSelectDspVisual.java
index e01773a79c..43bfed1caa 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardSelectDspVisual.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardSelectDspVisual.java
@@ -59,7 +59,7 @@ final class AddImageWizardSelectDspVisual extends JPanel {
selectedDsp = lastDspUsed;
//if the last selected DSP was the Local Disk DSP and it would be disabled then we want to select a different DSP
try {
- if ((Case.getOpenCase().getCaseType() == Case.CaseType.MULTI_USER_CASE) && selectedDsp.equals(LocalDiskDSProcessor.getType())) {
+ if ((Case.getCurrentCaseThrows().getCaseType() == Case.CaseType.MULTI_USER_CASE) && selectedDsp.equals(LocalDiskDSProcessor.getType())) {
selectedDsp = ImageDSProcessor.getType();
}
createDataSourceProcessorButtons();
@@ -131,7 +131,7 @@ final class AddImageWizardSelectDspVisual extends JPanel {
//Add the button
JToggleButton dspButton = createDspButton(dspType);
dspButton.addActionListener(cbActionListener);
- if ((Case.getOpenCase().getCaseType() == Case.CaseType.MULTI_USER_CASE) && dspType.equals(LocalDiskDSProcessor.getType())){
+ if ((Case.getCurrentCaseThrows().getCaseType() == Case.CaseType.MULTI_USER_CASE) && dspType.equals(LocalDiskDSProcessor.getType())){
dspButton.setEnabled(false); //disable the button for local disk DSP when this is a multi user case
dspButton.setSelected(false);
shouldAddMultiUserWarning = true;
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java
index e7e3702600..feae1ddb6b 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java
@@ -87,7 +87,7 @@ class AddLocalFilesTask implements Runnable {
List errors = new ArrayList<>();
try {
progress.setIndeterminate(true);
- FileManager fileManager = Case.getOpenCase().getServices().getFileManager();
+ FileManager fileManager = Case.getCurrentCaseThrows().getServices().getFileManager();
LocalFilesDataSource newDataSource = fileManager.addLocalFilesDataSource(deviceId, rootVirtualDirectoryName, "", localFilePaths, new ProgressUpdater());
newDataSources.add(newDataSource);
} catch (TskDataException | TskCoreException | NoCurrentCaseException ex) {
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
index ab28defc01..81f497214a 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
@@ -77,6 +77,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ReportAddedEvent;
import org.sleuthkit.autopsy.casemodule.services.Services;
+import org.sleuthkit.autopsy.commonfilesearch.CommonFilesSearchAction;
import org.sleuthkit.autopsy.communications.OpenCommVisualizationToolAction;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CategoryNode;
@@ -600,37 +601,41 @@ public class Case {
}
/**
- * Deprecated. Use getOpenCase() instead.
- *
- * Gets the current case, if there is one, at the time of the call.
+ * Gets the current case. This method should only be called by clients that
+ * can be sure a case is currently open. Some examples of suitable clients
+ * are data source processors, ingest modules, and report modules.
*
* @return The current case.
- *
- * @throws IllegalStateException if there is no current case.
- *
- * @deprecated. Use getOpenCase() instead.
*/
- @Deprecated
public static Case getCurrentCase() {
- /*
- * Throwing an unchecked exception is a bad idea here.
- *
- */
try {
- return getOpenCase();
+ return getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
+ /*
+ * Throw a runtime exception, since this is a programming error.
+ */
throw new IllegalStateException(NbBundle.getMessage(Case.class, "Case.getCurCase.exception.noneOpen"), ex);
}
}
/**
- * Gets the current open case, if there is one, at the time of the call.
+ * Gets the current case, if there is one, or throws an exception if there
+ * is no current case. This method should only be called by methods known to
+ * run in threads where it is possible that another thread has closed the
+ * current case. The exception provides some protection from the
+ * consequences of the race condition between the calling thread and a case
+ * closing thread, but it is not fool-proof. Background threads calling this
+ * method should put all operations in an exception firewall with a try and
+ * catch-all block to handle the possibility of bad timing.
*
- * @return The open case.
+ * TODO (JIRA-3825): Introduce a reference counting scheme for this get case
+ * method.
*
- * @throws NoCurrentCaseException if there is no open case.
+ * @return The current case.
+ *
+ * @throws NoCurrentCaseException if there is no current case.
*/
- public static Case getOpenCase() throws NoCurrentCaseException {
+ public static Case getCurrentCaseThrows() throws NoCurrentCaseException {
Case openCase = currentCase;
if (openCase == null) {
throw new NoCurrentCaseException(NbBundle.getMessage(Case.class, "Case.getCurCase.exception.noneOpen"));
@@ -1097,6 +1102,7 @@ public class Case {
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true);
CallableSystemAction.get(OpenTimelineAction.class).setEnabled(true);
CallableSystemAction.get(OpenCommVisualizationToolAction.class).setEnabled(true);
+ CallableSystemAction.get(CommonFilesSearchAction.class).setEnabled(true);
CallableSystemAction.get(OpenOutputFolderAction.class).setEnabled(false);
/*
@@ -1146,6 +1152,7 @@ public class Case {
CallableSystemAction.get(OpenTimelineAction.class).setEnabled(false);
CallableSystemAction.get(OpenCommVisualizationToolAction.class).setEnabled(false);
CallableSystemAction.get(OpenOutputFolderAction.class).setEnabled(false);
+ CallableSystemAction.get(CommonFilesSearchAction.class).setEnabled(false);
/*
* Clear the notifications in the notfier component in the lower
@@ -1560,8 +1567,8 @@ public class Case {
* @throws TskCoreException if there is a problem adding the report to the
* case database.
*/
- public Report addReport(String localPath, String srcModuleName, String reportName) throws TskCoreException {
- return addReport(localPath, srcModuleName, reportName, null);
+ public void addReport(String localPath, String srcModuleName, String reportName) throws TskCoreException {
+ addReport(localPath, srcModuleName, reportName, null);
}
/**
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java
index 2b333e2bdc..a389aca979 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseDeleteAction.java
@@ -66,7 +66,7 @@ final class CaseDeleteAction extends CallableSystemAction {
"# {0} - exception message", "Case.deleteCaseFailureMessageBox.message=Error deleting case: {0}",})
public void actionPerformed(ActionEvent e) {
try {
- Case currentCase = Case.getOpenCase();
+ Case currentCase = Case.getCurrentCaseThrows();
String caseName = currentCase.getName();
String caseDirectory = currentCase.getCaseDirectory();
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java
index 76c280f6b2..b8542552c4 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseInformationPanel.java
@@ -54,7 +54,7 @@ class CaseInformationPanel extends javax.swing.JPanel {
})
private void customizeComponents() {
try {
- propertiesPanel = new CasePropertiesPanel(Case.getOpenCase());
+ propertiesPanel = new CasePropertiesPanel(Case.getCurrentCaseThrows());
} catch (NoCurrentCaseException ex) {
Logger.getLogger(CaseInformationPanel.class.getName()).log(Level.INFO, "Exception while getting open case.", ex);
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesPanel.java
index c020e7b033..cc3c682830 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesPanel.java
@@ -50,7 +50,7 @@ final class CasePropertiesPanel extends javax.swing.JPanel {
void updateCaseInfo() {
try {
- theCase = Case.getOpenCase();
+ theCase = Case.getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex);
return;
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java
index be7905e010..2db469e371 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java
@@ -264,7 +264,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
try {
// verify that the image has a file system that TSK can process
- Case currentCase = Case.getOpenCase();
+ Case currentCase = Case.getCurrentCaseThrows();
if (!DataSourceUtils.imageHasFileSystem(dataSourcePath)) {
// image does not have a file system that TSK can process
return 0;
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java
index 6fa73b7ff7..56d5e67839 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java
@@ -319,7 +319,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
// Display warning if there is one (but don't disable "next" button)
try {
- if (false == PathValidator.isValid(path, Case.getOpenCase().getCaseType())) {
+ if (false == PathValidator.isValid(path, Case.getCurrentCaseThrows().getCaseType())) {
pathErrorLabel.setVisible(true);
pathErrorLabel.setText(Bundle.ImageFilePanel_pathValidation_dataSourceOnCDriveError());
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java
index e0b1ec8f01..9bce28753f 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/IngestJobInfoPanel.java
@@ -75,7 +75,7 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
private void refresh() {
try {
- SleuthkitCase skCase = Case.getOpenCase().getSleuthkitCase();
+ SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
List ingestJobs = skCase.getIngestJobs();
this.ingestJobs = ingestJobs;
this.repaint();
@@ -115,7 +115,7 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
IngestJobInfo currIngestJob = ingestJobs.get(rowIndex);
if (columnIndex == 0) {
try {
- SleuthkitCase skCase = Case.getOpenCase().getSleuthkitCase();
+ SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
return skCase.getContentById(currIngestJob.getObjectId()).getName();
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Failed to get content from db", ex);
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java
index b22f858b63..fc702076a0 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java
@@ -382,7 +382,7 @@ final class LocalDiskPanel extends JPanel {
}
private static String getDefaultImageWriterFolder() throws NoCurrentCaseException {
- return Paths.get(Case.getOpenCase().getModuleDirectory(), "Image Writer").toString();
+ return Paths.get(Case.getCurrentCaseThrows().getModuleDirectory(), "Image Writer").toString();
}
private void setPotentialImageWriterPath(LocalDisk disk) throws NoCurrentCaseException {
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java
index f98e8264ac..c7fa2c3de3 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java
@@ -197,7 +197,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor, AutoIngestDat
command.add("-f");
command.add("files");
command.add("-t");
- File l01Dir = new File(Case.getOpenCase().getModuleDirectory(), L01_EXTRACTION_DIR); //WJS-TODO change to getOpenCase() when that method exists
+ File l01Dir = new File(Case.getCurrentCaseThrows().getModuleDirectory(), L01_EXTRACTION_DIR); //WJS-TODO change to getOpenCase() when that method exists
if (!l01Dir.exists()) {
l01Dir.mkdirs();
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java
index ecfafd7844..3ab4088094 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesPanel.java
@@ -283,7 +283,7 @@ final class LocalFilesPanel extends javax.swing.JPanel {
errorLabel.setVisible(false);
try {
- final Case.CaseType currentCaseType = Case.getOpenCase().getCaseType();
+ final Case.CaseType currentCaseType = Case.getCurrentCaseThrows().getCaseType();
for (String currentPath : pathsList) {
if (!PathValidator.isValid(currentPath, currentCaseType)) {
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalEvidenceFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalEvidenceFilePanel.java
index 4e70d4b248..d38106a0ab 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/LogicalEvidenceFilePanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/LogicalEvidenceFilePanel.java
@@ -191,7 +191,7 @@ final class LogicalEvidenceFilePanel extends javax.swing.JPanel implements Docum
}
// display warning if there is one (but don't disable "next" button)
try {
- if (!PathValidator.isValid(path, Case.getOpenCase().getCaseType())) {
+ if (!PathValidator.isValid(path, Case.getCurrentCaseThrows().getCaseType())) {
errorLabel.setVisible(true);
errorLabel.setText(Bundle.LogicalEvidenceFilePanel_pathValidation_dataSourceOnCDriveError());
return false;
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java
index fa125e6a32..1efbffe190 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/MultiUserNode.java
@@ -115,19 +115,19 @@ final class MultiUserNode extends AbstractNode {
@Override
protected Sheet createSheet() {
- Sheet s = super.createSheet();
- Sheet.Set ss = s.get(Sheet.PROPERTIES);
- if (ss == null) {
- ss = Sheet.createPropertiesSet();
- s.put(ss);
+ Sheet sheet = super.createSheet();
+ Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
+ if (sheetSet == null) {
+ sheetSet = Sheet.createPropertiesSet();
+ sheet.put(sheetSet);
}
- ss.put(new NodeProperty<>(Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(),
+ sheetSet.put(new NodeProperty<>(Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(), Bundle.CaseNode_column_name(),
caseName));
- ss.put(new NodeProperty<>(Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(),
+ sheetSet.put(new NodeProperty<>(Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(), Bundle.CaseNode_column_createdTime(),
caseCreatedDate));
- ss.put(new NodeProperty<>(Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(),
+ sheetSet.put(new NodeProperty<>(Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(), Bundle.CaseNode_column_metadataFilePath(),
caseMetadataFilePath));
- return s;
+ return sheet;
}
@Override
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java
index 2f806bcecc..2b85a74333 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java
@@ -91,9 +91,9 @@ final class NewCaseWizardAction extends CallableSystemAction {
if (EamDb.isEnabled()) { //if the eam is enabled we need to save the case organization information now
EamDb dbManager = EamDb.getInstance();
if (dbManager != null) {
- CorrelationCase cRCase = dbManager.getCase(Case.getOpenCase());
+ CorrelationCase cRCase = dbManager.getCase(Case.getCurrentCaseThrows());
if (cRCase == null) {
- cRCase = dbManager.newCase(Case.getOpenCase());
+ cRCase = dbManager.newCase(Case.getCurrentCaseThrows());
}
if (!organizationName.isEmpty()) {
for (EamOrganization org : dbManager.getOrganizations()) {
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/OptionalCasePropertiesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/OptionalCasePropertiesPanel.java
index 0dae889f5b..4625727d94 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/OptionalCasePropertiesPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/OptionalCasePropertiesPanel.java
@@ -64,7 +64,7 @@ final class OptionalCasePropertiesPanel extends javax.swing.JPanel {
if (editCurrentCase) {
Case openCase;
try {
- openCase = Case.getOpenCase();
+ openCase = Case.getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex);
return;
@@ -94,7 +94,7 @@ final class OptionalCasePropertiesPanel extends javax.swing.JPanel {
private void setUpOrganizationData() {
if (EamDb.isEnabled()) {
try {
- Case currentCase = Case.getOpenCase();
+ Case currentCase = Case.getCurrentCaseThrows();
if (currentCase != null) {
EamDb dbManager = EamDb.getInstance();
selectedOrg = dbManager.getCase(currentCase).getOrg();
@@ -567,7 +567,7 @@ final class OptionalCasePropertiesPanel extends javax.swing.JPanel {
private void updateCaseDetails() throws NoCurrentCaseException {
if (caseDisplayNameTextField.isVisible()) {
try {
- Case.getOpenCase().updateCaseDetails(new CaseDetails(
+ Case.getCurrentCaseThrows().updateCaseDetails(new CaseDetails(
caseDisplayNameTextField.getText(), caseNumberTextField.getText(),
examinerTextField.getText(), tfExaminerPhoneText.getText(),
tfExaminerEmailText.getText(), taNotesText.getText()));
@@ -586,7 +586,7 @@ final class OptionalCasePropertiesPanel extends javax.swing.JPanel {
if (EamDb.isEnabled()) {
try {
EamDb dbManager = EamDb.getInstance();
- CorrelationCase correlationCase = dbManager.getCase(Case.getOpenCase());
+ CorrelationCase correlationCase = dbManager.getCase(Case.getCurrentCaseThrows());
if (caseDisplayNameTextField.isVisible()) {
correlationCase.setDisplayName(caseDisplayNameTextField.getText());
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/RecentCases.java b/Core/src/org/sleuthkit/autopsy/casemodule/RecentCases.java
index 6aeb3338d4..ccf592ca67 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/RecentCases.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/RecentCases.java
@@ -374,7 +374,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
int i = 0;
String currentCaseName = null;
try {
- currentCaseName = Case.getOpenCase().getDisplayName();
+ currentCaseName = Case.getCurrentCaseThrows().getDisplayName();
} catch (NoCurrentCaseException ex) {
// in case there is no current case.
}
@@ -407,7 +407,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
String[] casePaths = new String[LENGTH];
String currentCasePath = null;
try {
- currentCasePath = Case.getOpenCase().getMetadata().getFilePath().toString();
+ currentCasePath = Case.getCurrentCaseThrows().getMetadata().getFilePath().toString();
} catch (NoCurrentCaseException ex) {
/*
* There may be no current case.
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/BlackBoardArtifactTagAddedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/BlackBoardArtifactTagAddedEvent.java
index ad08e643fd..8c2a2d6dfa 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/events/BlackBoardArtifactTagAddedEvent.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/BlackBoardArtifactTagAddedEvent.java
@@ -47,6 +47,6 @@ public class BlackBoardArtifactTagAddedEvent extends TagAddedEvent implements S
* @throws TskCoreException
*/
ContentTag getTagByID() throws NoCurrentCaseException, TskCoreException {
- return Case.getOpenCase().getServices().getTagsManager().getContentTagByTagID(getTagID());
+ return Case.getCurrentCaseThrows().getServices().getTagsManager().getContentTagByTagID(getTagID());
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/DataSourceAddedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/DataSourceAddedEvent.java
index dcf575a5dc..84a99ee8b2 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/events/DataSourceAddedEvent.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/DataSourceAddedEvent.java
@@ -79,7 +79,7 @@ public final class DataSourceAddedEvent extends AutopsyEvent implements Serializ
}
try {
long id = (Long) super.getNewValue();
- dataSource = Case.getOpenCase().getSleuthkitCase().getContentById(id);
+ dataSource = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(id);
return dataSource;
} catch (NoCurrentCaseException | TskCoreException ex) {
logger.log(Level.SEVERE, "Error doing lazy load for remote event", ex); //NON-NLS
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/events/ReportAddedEvent.java b/Core/src/org/sleuthkit/autopsy/casemodule/events/ReportAddedEvent.java
index 2fe152d32e..7f35c625c5 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/events/ReportAddedEvent.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/events/ReportAddedEvent.java
@@ -70,7 +70,7 @@ public final class ReportAddedEvent extends AutopsyEvent implements Serializable
}
try {
long id = (Long) super.getNewValue();
- List reports = Case.getOpenCase().getSleuthkitCase().getAllReports();
+ List reports = Case.getCurrentCaseThrows().getSleuthkitCase().getAllReports();
for (Report thisReport : reports) {
if (thisReport.getId() == id) {
report = thisReport;
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java
index 7ab639f06b..292383980b 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Blackboard.java
@@ -1,14 +1,14 @@
/*
- * Sleuth Kit Data Model
+ * Autopsy Forensic Browser
*
- * Copyright 2011-2018 Basis Technology Corp.
+ * Copyright 2015-2018 Basis Technology Corp.
* Contact: carrier sleuthkit org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java
index 5c978f6378..fb02e7d2d4 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java
@@ -297,7 +297,7 @@ final class TagNameDefinition implements Comparable {
}
setting.append(tagName.toSettingsFormat());
try {
- SleuthkitCase caseDb = Case.getOpenCase().getSleuthkitCase();
+ SleuthkitCase caseDb = Case.getCurrentCaseThrows().getSleuthkitCase();
tagName.saveToCase(caseDb);
} catch (NoCurrentCaseException ex) {
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex);
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java
index 5073f4110b..419a92e8c9 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java
@@ -425,7 +425,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel {
for (String modifiedTagDisplayName : updatedStatusTags) {
//if user closes their case after options have been changed but before application of them is complete don't notify
try {
- Case.getOpenCase().notifyTagDefinitionChanged(modifiedTagDisplayName);
+ Case.getCurrentCaseThrows().notifyTagDefinitionChanged(modifiedTagDisplayName);
} catch (NoCurrentCaseException ex) {
Logger.getLogger(TagOptionsPanel.class.getName()).log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java
index b38165ef5c..f113a622fe 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java
@@ -99,7 +99,7 @@ public class TagsManager implements Closeable {
tagDisplayNames.add(tagType.getDisplayName());
});
try {
- TagsManager tagsManager = Case.getOpenCase().getServices().getTagsManager();
+ TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
for (TagName tagName : tagsManager.getAllTagNames()) {
tagDisplayNames.add(tagName.getDisplayName());
}
@@ -340,7 +340,7 @@ public class TagsManager implements Closeable {
ContentTag tag;
tag = caseDb.addContentTag(content, tagName, comment, beginByteOffset, endByteOffset);
try {
- Case.getOpenCase().notifyContentTagAdded(tag);
+ Case.getCurrentCaseThrows().notifyContentTagAdded(tag);
} catch (NoCurrentCaseException ex) {
throw new TskCoreException("Added a tag to a closed case", ex);
}
@@ -358,7 +358,7 @@ public class TagsManager implements Closeable {
public void deleteContentTag(ContentTag tag) throws TskCoreException {
caseDb.deleteContentTag(tag);
try {
- Case.getOpenCase().notifyContentTagDeleted(tag);
+ Case.getCurrentCaseThrows().notifyContentTagDeleted(tag);
} catch (NoCurrentCaseException ex) {
throw new TskCoreException("Deleted a tag from a closed case", ex);
}
@@ -470,7 +470,7 @@ public class TagsManager implements Closeable {
public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException {
BlackboardArtifactTag tag = caseDb.addBlackboardArtifactTag(artifact, tagName, comment);
try {
- Case.getOpenCase().notifyBlackBoardArtifactTagAdded(tag);
+ Case.getCurrentCaseThrows().notifyBlackBoardArtifactTagAdded(tag);
} catch (NoCurrentCaseException ex) {
throw new TskCoreException("Added a tag to a closed case", ex);
}
@@ -488,7 +488,7 @@ public class TagsManager implements Closeable {
public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException {
caseDb.deleteBlackboardArtifactTag(tag);
try {
- Case.getOpenCase().notifyBlackBoardArtifactTagDeleted(tag);
+ Case.getCurrentCaseThrows().notifyBlackBoardArtifactTagDeleted(tag);
} catch (NoCurrentCaseException ex) {
throw new TskCoreException("Deleted a tag from a closed case", ex);
}
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java
index c16d16d70c..2a86e7c279 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java
@@ -169,7 +169,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
private void showCaseDetails(int selectedRowViewIdx) {
Case openCase;
try {
- openCase = Case.getOpenCase();
+ openCase = Case.getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
Bundle.DataContentViewerOtherCases_noOpenCase_errMsg(),
@@ -225,7 +225,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
if (0 != otherCasesTable.getSelectedRowCount()) {
Calendar now = Calendar.getInstance();
String fileName = String.format("%1$tY%1$tm%1$te%1$tI%1$tM%1$tS_other_data_sources.csv", now);
- CSVFileChooser.setCurrentDirectory(new File(Case.getOpenCase().getExportDirectory()));
+ CSVFileChooser.setCurrentDirectory(new File(Case.getCurrentCaseThrows().getExportDirectory()));
CSVFileChooser.setSelectedFile(new File(fileName));
CSVFileChooser.setFileFilter(new FileNameExtensionFilter("csv file", "csv"));
@@ -434,7 +434,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
private Collection getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId) {
// @@@ Check exception
try {
- String caseUUID = Case.getOpenCase().getName();
+ String caseUUID = Case.getCurrentCaseThrows().getName();
EamDb dbManager = EamDb.getInstance();
Collection artifactInstances = dbManager.getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue()).stream()
.filter(artifactInstance -> !artifactInstance.getCorrelationCase().getCaseUUID().equals(caseUUID)
@@ -491,7 +491,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
if (af != null) {
Content dataSource = af.getDataSource();
dataSourceName = dataSource.getName();
- deviceId = Case.getOpenCase().getSleuthkitCase().getDataSource(dataSource.getId()).getDeviceId();
+ deviceId = Case.getCurrentCaseThrows().getSleuthkitCase().getDataSource(dataSource.getId()).getDeviceId();
}
} catch (TskException | NoCurrentCaseException ex) {
// do nothing.
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationDataSource.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationDataSource.java
index cba529954e..864bf50923 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationDataSource.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationDataSource.java
@@ -74,7 +74,7 @@ public class CorrelationDataSource implements Serializable {
public static CorrelationDataSource fromTSKDataSource(CorrelationCase correlationCase, Content dataSource) throws EamDbException {
Case curCase;
try {
- curCase = Case.getOpenCase();
+ curCase = Case.getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
throw new EamDbException("Autopsy case is closed");
}
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java
index 43812eeebf..69cad2abef 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java
@@ -90,7 +90,7 @@ public class EamArtifactUtil {
// if they asked for it, add the instance details associated with this occurance.
if (!eamArtifacts.isEmpty() && addInstanceDetails) {
try {
- Case currentCase = Case.getOpenCase();
+ Case currentCase = Case.getCurrentCaseThrows();
AbstractFile bbSourceFile = currentCase.getSleuthkitCase().getAbstractFileById(bbArtifact.getObjectID());
if (null == bbSourceFile) {
//@@@ Log this
@@ -98,9 +98,9 @@ public class EamArtifactUtil {
}
// make an instance for the BB source file
- CorrelationCase correlationCase = EamDb.getInstance().getCase(Case.getOpenCase());
+ CorrelationCase correlationCase = EamDb.getInstance().getCase(Case.getCurrentCaseThrows());
if (null == correlationCase) {
- correlationCase = EamDb.getInstance().newCase(Case.getOpenCase());
+ correlationCase = EamDb.getInstance().newCase(Case.getCurrentCaseThrows());
}
CorrelationAttributeInstance eamInstance = new CorrelationAttributeInstance(
correlationCase,
@@ -146,7 +146,7 @@ public class EamArtifactUtil {
// Get the associated artifact
BlackboardAttribute attribute = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
if (attribute != null) {
- BlackboardArtifact associatedArtifact = Case.getOpenCase().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong());
+ BlackboardArtifact associatedArtifact = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong());
return EamArtifactUtil.getCorrelationAttributeFromBlackboardArtifact(correlationType, associatedArtifact);
}
@@ -254,9 +254,9 @@ public class EamArtifactUtil {
try {
CorrelationAttribute.Type filesType = EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID);
eamArtifact = new CorrelationAttribute(filesType, af.getMd5Hash());
- CorrelationCase correlationCase = EamDb.getInstance().getCase(Case.getOpenCase());
+ CorrelationCase correlationCase = EamDb.getInstance().getCase(Case.getCurrentCaseThrows());
if (null == correlationCase) {
- correlationCase = EamDb.getInstance().newCase(Case.getOpenCase());
+ correlationCase = EamDb.getInstance().newCase(Case.getCurrentCaseThrows());
}
CorrelationAttributeInstance cei = new CorrelationAttributeInstance(
correlationCase,
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java
index da11671a08..570f5bca06 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java
@@ -163,8 +163,8 @@ final class CaseEventListener implements PropertyChangeListener {
try {
// Get the remaining tags on the content object
- Content content = Case.getOpenCase().getSleuthkitCase().getContentById(contentID);
- TagsManager tagsManager = Case.getOpenCase().getServices().getTagsManager();
+ Content content = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(contentID);
+ TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
List tags = tagsManager.getContentTagsByContent(content);
if (tags.stream()
@@ -244,7 +244,7 @@ final class CaseEventListener implements PropertyChangeListener {
} else { //BLACKBOARD_ARTIFACT_TAG_DELETED
Case openCase;
try {
- openCase = Case.getOpenCase();
+ openCase = Case.getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex);
return;
@@ -327,10 +327,10 @@ final class CaseEventListener implements PropertyChangeListener {
* that are tagged with the given tag name.
*/
try {
- TagName tagName = Case.getOpenCase().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(modifiedTagName);
+ TagName tagName = Case.getCurrentCaseThrows().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(modifiedTagName);
//First update the artifacts
//Get all BlackboardArtifactTags with this tag name
- List artifactTags = Case.getOpenCase().getSleuthkitCase().getBlackboardArtifactTagsByTagName(tagName);
+ List artifactTags = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboardArtifactTagsByTagName(tagName);
for (BlackboardArtifactTag bbTag : artifactTags) {
//start with assumption that none of the other tags applied to this Correlation Attribute will prevent it's status from being changed
boolean hasTagWithConflictingKnownStatus = false;
@@ -346,7 +346,7 @@ final class CaseEventListener implements PropertyChangeListener {
}
//Get the BlackboardArtifact which this BlackboardArtifactTag has been applied to.
BlackboardArtifact bbArtifact = bbTag.getArtifact();
- TagsManager tagsManager = Case.getOpenCase().getServices().getTagsManager();
+ TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
List tags = tagsManager.getBlackboardArtifactTagsByArtifact(bbArtifact);
//get all tags which are on this blackboard artifact
for (BlackboardArtifactTag t : tags) {
@@ -374,7 +374,7 @@ final class CaseEventListener implements PropertyChangeListener {
}
// Next update the files
- List fileTags = Case.getOpenCase().getSleuthkitCase().getContentTagsByTagName(tagName);
+ List fileTags = Case.getCurrentCaseThrows().getSleuthkitCase().getContentTagsByTagName(tagName);
//Get all ContentTags with this tag name
for (ContentTag contentTag : fileTags) {
//start with assumption that none of the other tags applied to this ContentTag will prevent it's status from being changed
@@ -384,7 +384,7 @@ final class CaseEventListener implements PropertyChangeListener {
// the status of the file in the central repository
if (tagName.getKnownStatus() == TskData.FileKnown.UNKNOWN) {
Content content = contentTag.getContent();
- TagsManager tagsManager = Case.getOpenCase().getServices().getTagsManager();
+ TagsManager tagsManager = Case.getCurrentCaseThrows().getServices().getTagsManager();
List tags = tagsManager.getContentTagsByContent(content);
//get all tags which are on this file
for (ContentTag t : tags) {
@@ -436,7 +436,7 @@ final class CaseEventListener implements PropertyChangeListener {
}
Case openCase;
try {
- openCase = Case.getOpenCase();
+ openCase = Case.getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex);
return;
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java
index a7c267c959..9dc784e0d0 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java
@@ -163,7 +163,7 @@ public class IngestEventsListener {
tifArtifact.addAttributes(attributes);
try {
// index the artifact for keyword search
- Blackboard blackboard = Case.getOpenCase().getSleuthkitCase().getBlackboard();
+ Blackboard blackboard = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard();
blackboard.publishArtifact(tifArtifact);
} catch (Blackboard.BlackboardException | NoCurrentCaseException ex) {
LOGGER.log(Level.SEVERE, "Unable to index blackboard artifact " + tifArtifact.getArtifactID(), ex); //NON-NLS
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java
index 0575905b37..76f51f3c55 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java
@@ -94,7 +94,7 @@ final class IngestModule implements FileIngestModule {
}
try {
- blackboard = Case.getOpenCase().getSleuthkitCase().getBlackboard();
+ blackboard = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard();
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Exception while getting open case.", ex);
return ProcessResult.ERROR;
@@ -233,7 +233,7 @@ final class IngestModule implements FileIngestModule {
}
Case autopsyCase;
try {
- autopsyCase = Case.getOpenCase();
+ autopsyCase = Case.getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Exception while getting open case.", ex);
throw new IngestModuleException("Exception while getting open case.", ex);
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModuleFactory.java b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModuleFactory.java
index 6ef03ae00d..2f732ac60f 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModuleFactory.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModuleFactory.java
@@ -68,7 +68,17 @@ public class IngestModuleFactory extends IngestModuleFactoryAdapter {
@Override
public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings settings) {
- return new IngestModule((IngestSettings) settings);
+ if (settings instanceof IngestSettings) {
+ return new IngestModule((IngestSettings) settings);
+ }
+ /*
+ * Compatibility check for older versions.
+ */
+ if (settings instanceof NoIngestModuleIngestJobSettings) {
+ return new IngestModule(new IngestSettings());
+ }
+
+ throw new IllegalArgumentException("Expected settings argument to be an instance of IngestSettings");
}
@Override
diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllDataSourcesCommonFilesAlgorithm.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllDataSourcesCommonFilesAlgorithm.java
new file mode 100644
index 0000000000..437d4d1885
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllDataSourcesCommonFilesAlgorithm.java
@@ -0,0 +1,56 @@
+/*
+ *
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2018 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.commonfilesearch;
+
+import java.util.Map;
+
+/**
+ * Provides logic for selecting common files from all data sources.
+ */
+final class AllDataSourcesCommonFilesAlgorithm extends CommonFilesMetadataBuilder {
+
+ private static final String WHERE_CLAUSE = "%s md5 in (select md5 from tsk_files where (known != 1 OR known IS NULL)%s GROUP BY md5 HAVING COUNT(*) > 1) order by md5"; //NON-NLS
+
+ /**
+ * Implements the algorithm for getting common files across all data
+ * sources.
+ *
+ * @param dataSourceIdMap a map of obj_id to datasource name
+ * @param filterByMediaMimeType match only on files whose mime types can be broadly categorized as media types
+ * @param filterByDocMimeType match only on files whose mime types can be broadly categorized as document types
+ */
+ AllDataSourcesCommonFilesAlgorithm(Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) {
+ super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType);
+
+ }
+
+ @Override
+ protected String buildSqlSelectStatement() {
+ Object[] args = new String[]{SELECT_PREFIX, determineMimeTypeFilter()};
+ return String.format(WHERE_CLAUSE, args);
+ }
+
+ @Override
+ protected String buildTabTitle() {
+ final String buildCategorySelectionString = this.buildCategorySelectionString();
+ final String titleTemplate = Bundle.CommonFilesMetadataBuilder_buildTabTitle_titleAll();
+ return String.format(titleTemplate, new Object[]{buildCategorySelectionString});
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties
new file mode 100644
index 0000000000..72ddffb748
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties
@@ -0,0 +1,15 @@
+CommonFilesPanel.searchButton.text=Search
+CommonFilesPanel.withinDataSourceRadioButton.text=At least one instance of a given MD5 must appear in the data source selected below:
+CommonFilesPanel.allDataSourcesRadioButton.text=Files can be in any data source
+CommonFilesPanel.cancelButton.text=Cancel
+CommonFilesPanel.cancelButton.actionCommand=Cancel
+CommonFilesPanel.selectedFileCategoriesButton.text=Match on the following file categories:
+CommonFilesPanel.selectedFileCategoriesButton.toolTipText=Select from the options below...
+CommonFilesPanel.pictureVideoCheckbox.text=Pictures and Videos
+CommonFilesPanel.documentsCheckbox.text=Documents
+CommonFilesPanel.commonFilesSearchLabel.text=Find duplicate files in the current case.
+CommonFilesPanel.allFileCategoriesRadioButton.toolTipText=No filtering applied to results...
+CommonFilesPanel.allFileCategoriesRadioButton.text=Match on all file types
+CommonFilesPanel.text=Indicate which data sources to consider while searching for duplicates:
+CommonFilesPanel.categoriesLabel.text=Indicate which file types to include in results:
+CommonFilesPanel.errorText.text=In order to search, you must select a file category.
diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesDialog.form b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesDialog.form
new file mode 100644
index 0000000000..7a6e3dabe5
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesDialog.form
@@ -0,0 +1,51 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesDialog.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesDialog.java
new file mode 100644
index 0000000000..204b3136a9
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesDialog.java
@@ -0,0 +1,94 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2018 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.commonfilesearch;
+
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+import org.openide.util.NbBundle;
+import org.openide.windows.WindowManager;
+
+/**
+ * Dialog box for configuring and running common files search.
+ */
+@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
+public final class CommonFilesDialog extends javax.swing.JDialog {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates new form CommonFilesDialog
+ */
+ @NbBundle.Messages({
+ "CommonFilesDialog.frame.title=Find Common Files",
+ "CommonFilesDialog.frame.msg=Find Common Files"})
+ public CommonFilesDialog() {
+ super(new JFrame(Bundle.CommonFilesDialog_frame_title()),
+ Bundle.CommonFilesDialog_frame_msg(), true);
+ initComponents();
+
+ this.setResizable(false);
+ this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ commonFilesPanel1 = new org.sleuthkit.autopsy.commonfilesearch.CommonFilesPanel();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ setSize(new java.awt.Dimension(340, 320));
+ addWindowListener(new java.awt.event.WindowAdapter() {
+ public void windowClosed(java.awt.event.WindowEvent evt) {
+ formWindowClosed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(commonFilesPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 0, Short.MAX_VALUE))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(commonFilesPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 0, Short.MAX_VALUE))
+ );
+
+ pack();
+ setLocationRelativeTo(null);
+ }// //GEN-END:initComponents
+
+ private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed
+ SwingUtilities.windowForComponent(this).dispose();
+ }//GEN-LAST:event_formWindowClosed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private org.sleuthkit.autopsy.commonfilesearch.CommonFilesPanel commonFilesPanel1;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java
new file mode 100644
index 0000000000..c7c70676b8
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadata.java
@@ -0,0 +1,71 @@
+/*
+ *
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2018 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.commonfilesearch;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Utility and wrapper model around data required for Common Files Search
+ * results. Subclass this to implement different selections of files from the
+ * case.
+ */
+final class CommonFilesMetadata {
+
+ private final Map metadata;
+
+ /**
+ * Create meta dat object which can be handed off to the node factories
+ *
+ * @param metadata map of md5 to parent-level node meta data
+ */
+ CommonFilesMetadata(Map metadata) {
+ this.metadata = metadata;
+ }
+
+ /**
+ * Find the meta data for the given md5.
+ *
+ * This is a convenience method - you can also iterate over
+ * getMetadata().
+ *
+ * @param md5 key
+ * @return
+ */
+ Md5Metadata getMetadataForMd5(String md5) {
+ return this.metadata.get(md5);
+ }
+
+ Map getMetadata() {
+ return Collections.unmodifiableMap(this.metadata);
+ }
+
+ /**
+ * How many distinct file instances exist for this metadata?
+ * @return number of file instances
+ */
+ int size() {
+ int count = 0;
+ for (Md5Metadata data : this.metadata.values()) {
+ count += data.size();
+ }
+ return count;
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadataBuilder.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadataBuilder.java
new file mode 100644
index 0000000000..339763fd4e
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesMetadataBuilder.java
@@ -0,0 +1,261 @@
+/*
+ *
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2018 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.commonfilesearch;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.openide.util.NbBundle;
+import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
+import org.sleuthkit.datamodel.HashUtility;
+import org.sleuthkit.datamodel.SleuthkitCase;
+import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
+import org.sleuthkit.datamodel.TskCoreException;
+
+/**
+ *
+ * Generates a List when
+ * findCommonFiles() is called, which organizes files by md5 to
+ * prepare to display in viewer.
+ *
+ * This entire thing runs on a background thread where exceptions are handled.
+ */
+@SuppressWarnings("PMD.AbstractNaming")
+abstract class CommonFilesMetadataBuilder {
+
+ private final Map dataSourceIdToNameMap;
+ private final boolean filterByMedia;
+ private final boolean filterByDoc;
+ private static final String filterByMimeTypesWhereClause = " and mime_type in (%s)"; //NON-NLS // where %s is csv list of mime_types to filter on
+
+ /*
+ * The set of the MIME types that will be checked for extension mismatches
+ * when checkType is ONLY_MEDIA.
+ * ".jpg", ".jpeg", ".png", ".psd", ".nef", ".tiff", ".bmp", ".tec"
+ * ".aaf", ".3gp", ".asf", ".avi", ".m1v", ".m2v", //NON-NLS
+ * ".m4v", ".mp4", ".mov", ".mpeg", ".mpg", ".mpe", ".mp4", ".rm", ".wmv", ".mpv", ".flv", ".swf"
+ */
+ private static final Set MEDIA_PICS_VIDEO_MIME_TYPES = Stream.of(
+ "image/bmp", //NON-NLS
+ "image/gif", //NON-NLS
+ "image/jpeg", //NON-NLS
+ "image/png", //NON-NLS
+ "image/tiff", //NON-NLS
+ "image/vnd.adobe.photoshop", //NON-NLS
+ "image/x-raw-nikon", //NON-NLS
+ "image/x-ms-bmp", //NON-NLS
+ "image/x-icon", //NON-NLS
+ "video/webm", //NON-NLS
+ "video/3gpp", //NON-NLS
+ "video/3gpp2", //NON-NLS
+ "video/ogg", //NON-NLS
+ "video/mpeg", //NON-NLS
+ "video/mp4", //NON-NLS
+ "video/quicktime", //NON-NLS
+ "video/x-msvideo", //NON-NLS
+ "video/x-flv", //NON-NLS
+ "video/x-m4v", //NON-NLS
+ "video/x-ms-wmv", //NON-NLS
+ "application/vnd.ms-asf", //NON-NLS
+ "application/vnd.rn-realmedia", //NON-NLS
+ "application/x-shockwave-flash" //NON-NLS
+ ).collect(Collectors.toSet());
+
+ /*
+ * The set of the MIME types that will be checked for extension mismatches
+ * when checkType is ONLY_TEXT_FILES.
+ * ".doc", ".docx", ".odt", ".xls", ".xlsx", ".ppt", ".pptx"
+ * ".txt", ".rtf", ".log", ".text", ".xml"
+ * ".html", ".htm", ".css", ".js", ".php", ".aspx"
+ * ".pdf"
+ */
+ private static final Set TEXT_FILES_MIME_TYPES = Stream.of(
+ "text/plain", //NON-NLS
+ "application/rtf", //NON-NLS
+ "application/pdf", //NON-NLS
+ "text/css", //NON-NLS
+ "text/html", //NON-NLS
+ "text/csv", //NON-NLS
+ "application/json", //NON-NLS
+ "application/javascript", //NON-NLS
+ "application/xml", //NON-NLS
+ "text/calendar", //NON-NLS
+ "application/x-msoffice", //NON-NLS
+ "application/x-ooxml", //NON-NLS
+ "application/msword", //NON-NLS
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document", //NON-NLS
+ "application/vnd.ms-powerpoint", //NON-NLS
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation", //NON-NLS
+ "application/vnd.ms-excel", //NON-NLS
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", //NON-NLS
+ "application/vnd.oasis.opendocument.presentation", //NON-NLS
+ "application/vnd.oasis.opendocument.spreadsheet", //NON-NLS
+ "application/vnd.oasis.opendocument.text" //NON-NLS
+ ).collect(Collectors.toSet());
+
+ /**
+ * Subclass this to implement different algorithms for getting common files.
+ *
+ * @param dataSourceIdMap a map of obj_id to datasource name
+ * @param filterByMediaMimeType match only on files whose mime types can be
+ * broadly categorized as media types
+ * @param filterByDocMimeType match only on files whose mime types can be
+ * broadly categorized as document types
+ */
+ CommonFilesMetadataBuilder(Map dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) {
+ dataSourceIdToNameMap = dataSourceIdMap;
+ filterByMedia = filterByMediaMimeType;
+ filterByDoc = filterByDocMimeType;
+ }
+
+ /**
+ * Use this as a prefix when building the SQL select statement.
+ *
+ *
+ *
You only have to specify the WHERE clause if you use this.
+ *
If you do not use this string, you must use at least the columns
+ * selected below, in that order.
+ *
+ */
+ static final String SELECT_PREFIX = "SELECT obj_id, md5, data_source_obj_id from tsk_files where"; //NON-NLS
+
+ /**
+ * Should build a SQL SELECT statement to be passed to
+ * SleuthkitCase.executeQuery(sql) which will select the desired file ids
+ * and MD5 hashes.
+ *
+ * The statement should select obj_id, md5, data_source_obj_id in that
+ * order.
+ *
+ * @return sql string select statement
+ */
+ protected abstract String buildSqlSelectStatement();
+
+ /**
+ * Generate a meta data object which encapsulates everything need to add the
+ * tree table tab to the top component.
+ *
+ * @return a data object with all of the matched files in a hierarchical
+ * format
+ * @throws TskCoreException
+ * @throws NoCurrentCaseException
+ * @throws SQLException
+ */
+ public CommonFilesMetadata findCommonFiles() throws TskCoreException, NoCurrentCaseException, SQLException {
+
+ Map commonFiles = new HashMap<>();
+
+ SleuthkitCase sleuthkitCase = Case.getCurrentCaseThrows().getSleuthkitCase();
+ String selectStatement = this.buildSqlSelectStatement();
+
+ try (
+ CaseDbQuery query = sleuthkitCase.executeQuery(selectStatement);
+ ResultSet resultSet = query.getResultSet()) {
+
+ while (resultSet.next()) {
+ Long objectId = resultSet.getLong(1);
+ String md5 = resultSet.getString(2);
+ Long dataSourceId = resultSet.getLong(3);
+ String dataSource = this.dataSourceIdToNameMap.get(dataSourceId);
+
+ if (md5 == null || HashUtility.isNoDataMd5(md5)) {
+ continue;
+ }
+
+ if (commonFiles.containsKey(md5)) {
+ final Md5Metadata md5Metadata = commonFiles.get(md5);
+ md5Metadata.addFileInstanceMetadata(new FileInstanceMetadata(objectId, dataSource));
+ } else {
+ final List fileInstances = new ArrayList<>();
+ fileInstances.add(new FileInstanceMetadata(objectId, dataSource));
+ Md5Metadata md5Metadata = new Md5Metadata(md5, fileInstances);
+ commonFiles.put(md5, md5Metadata);
+ }
+ }
+ }
+
+ return new CommonFilesMetadata(commonFiles);
+ }
+
+ /**
+ * Should be used by subclasses, in their
+ * buildSqlSelectStatement() function to create an SQL boolean
+ * expression which will filter our matches based on mime type. The
+ * expression will be conjoined to base query with an AND operator.
+ *
+ * @return sql fragment of the form:
+ * 'and "mime_type" in ( [comma delimited list of mime types] )'
+ * or empty string in the event that no types to filter on were given.
+ */
+ String determineMimeTypeFilter() {
+
+ Set mimeTypesToFilterOn = new HashSet<>();
+ String mimeTypeString = "";
+ if (filterByMedia) {
+ mimeTypesToFilterOn.addAll(MEDIA_PICS_VIDEO_MIME_TYPES);
+ }
+ if (filterByDoc) {
+ mimeTypesToFilterOn.addAll(TEXT_FILES_MIME_TYPES);
+ }
+ StringBuilder mimeTypeFilter = new StringBuilder(mimeTypesToFilterOn.size());
+ if (!mimeTypesToFilterOn.isEmpty()) {
+ for (String mimeType : mimeTypesToFilterOn) {
+ mimeTypeFilter.append('"').append(mimeType).append("\",");
+ }
+ mimeTypeString = mimeTypeFilter.toString().substring(0, mimeTypeFilter.length() - 1);
+ mimeTypeString = String.format(filterByMimeTypesWhereClause, new Object[]{mimeTypeString});
+ }
+ return mimeTypeString;
+ }
+
+ @NbBundle.Messages({
+ "CommonFilesMetadataBuilder.buildTabTitle.titleAll=Common Files (All Data Sources, %s)",
+ "CommonFilesMetadataBuilder.buildTabTitle.titleSingle=Common Files (Match Within Data Source: %s, %s)"
+ })
+ protected abstract String buildTabTitle();
+
+ @NbBundle.Messages({
+ "CommonFilesMetadataBuilder.buildCategorySelectionString.doc=Documents",
+ "CommonFilesMetadataBuilder.buildCategorySelectionString.media=Media",
+ "CommonFilesMetadataBuilder.buildCategorySelectionString.all=All File Categories"
+ })
+ protected String buildCategorySelectionString() {
+ if (!this.filterByDoc && !this.filterByMedia) {
+ return Bundle.CommonFilesMetadataBuilder_buildCategorySelectionString_all();
+ } else {
+ List filters = new ArrayList<>();
+ if (this.filterByDoc) {
+ filters.add(Bundle.CommonFilesMetadataBuilder_buildCategorySelectionString_doc());
+ }
+ if (this.filterByMedia) {
+ filters.add(Bundle.CommonFilesMetadataBuilder_buildCategorySelectionString_media());
+ }
+ return String.join(", ", filters);
+ }
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java
new file mode 100644
index 0000000000..0226baff58
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesNode.java
@@ -0,0 +1,95 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2018 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.commonfilesearch;
+
+import java.util.List;
+import org.openide.nodes.ChildFactory;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node;
+import org.openide.util.NbBundle;
+import org.openide.util.lookup.Lookups;
+import org.sleuthkit.autopsy.datamodel.Md5Node;
+import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
+import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
+
+/**
+ * Wrapper node for Md5Node used to display common files search
+ * results in the top right pane. Calls Md5NodeFactory.
+ */
+final public class CommonFilesNode extends DisplayableItemNode {
+
+ CommonFilesNode(CommonFilesMetadata metadataList) {
+ super(Children.create(new Md5NodeFactory(metadataList), true), Lookups.singleton(CommonFilesNode.class));
+ }
+
+ @NbBundle.Messages({
+ "CommonFilesNode.getName.text=Common Files"})
+ @Override
+ public String getName() {
+ return Bundle.CommonFilesNode_getName_text();
+ }
+
+ @Override
+ public T accept(DisplayableItemNodeVisitor visitor) {
+ return visitor.visit(this);
+ }
+
+ @Override
+ public boolean isLeafTypeNode() {
+ return false;
+ }
+
+ @Override
+ public String getItemType() {
+ return getClass().getName();
+ }
+
+ /**
+ * ChildFactory which builds CommonFileParentNodes from the
+ * CommonFilesMetaaData models.
+ */
+ static class Md5NodeFactory extends ChildFactory {
+
+ /**
+ * List of models, each of which is a parent node matching a single md5,
+ * containing children FileNodes.
+ */
+ private CommonFilesMetadata metadata;
+
+ Md5NodeFactory(CommonFilesMetadata metadata) {
+ this.metadata = metadata;
+ }
+
+ protected void removeNotify() {
+ metadata = null;
+ }
+
+ @Override
+ protected Node createNodeForKey(String md5) {
+ Md5Metadata metadata = this.metadata.getMetadataForMd5(md5);
+ return new Md5Node(metadata);
+ }
+
+ @Override
+ protected boolean createKeys(List list) {
+ list.addAll(this.metadata.getMetadata().keySet());
+ return true;
+ }
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.form b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.form
new file mode 100644
index 0000000000..c9d08c0536
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.form
@@ -0,0 +1,261 @@
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java
new file mode 100644
index 0000000000..ad278a4cb5
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonFilesPanel.java
@@ -0,0 +1,616 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2018 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.commonfilesearch;
+
+import java.io.File;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
+import java.util.logging.Level;
+import javax.swing.ComboBoxModel;
+import javax.swing.SwingUtilities;
+import javax.swing.SwingWorker;
+import org.openide.explorer.ExplorerManager;
+import org.openide.util.NbBundle;
+import org.sleuthkit.autopsy.casemodule.Case;
+import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
+import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
+import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
+import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
+import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
+import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
+import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
+import org.sleuthkit.autopsy.directorytree.DirectoryTreeTopComponent;
+import org.sleuthkit.datamodel.SleuthkitCase;
+import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
+import org.sleuthkit.datamodel.TskCoreException;
+
+/**
+ * Panel used for common files search configuration and configuration business
+ * logic. Nested within CommonFilesDialog.
+ */
+@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
+public final class CommonFilesPanel extends javax.swing.JPanel {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final Long NO_DATA_SOURCE_SELECTED = -1L;
+
+ private ComboBoxModel dataSourcesList = new DataSourceComboBoxModel();
+ private Map dataSourceMap;
+
+ private static final Logger LOGGER = Logger.getLogger(CommonFilesPanel.class.getName());
+ private boolean singleDataSource = false;
+ private String selectedDataSource = "";
+ private boolean pictureViewCheckboxState;
+ private boolean documentsCheckboxState;
+
+ /**
+ * Creates new form CommonFilesPanel
+ */
+ @NbBundle.Messages({
+ "CommonFilesPanel.title=Common Files Panel",
+ "CommonFilesPanel.exception=Unexpected Exception loading DataSources."})
+ public CommonFilesPanel() {
+ initComponents();
+
+ this.setupDataSources();
+
+ this.errorText.setVisible(false);
+ }
+
+ /**
+ * Sets up the data sources dropdown and returns the data sources map for
+ * future usage.
+ *
+ * @return a mapping of data source ids to data source names
+ */
+ @NbBundle.Messages({
+ "CommonFilesPanel.buildDataSourceMap.done.tskCoreException=Unable to run query against DB.",
+ "CommonFilesPanel.buildDataSourceMap.done.noCurrentCaseException=Unable to open case file.",
+ "CommonFilesPanel.buildDataSourceMap.done.exception=Unexpected exception building data sources map.",
+ "CommonFilesPanel.buildDataSourceMap.done.interupted=Something went wrong building the Common Files Search dialog box.",
+ "CommonFilesPanel.buildDataSourceMap.done.sqlException=Unable to query db for data sources.",
+ "CommonFilesPanel.buildDataSourcesMap.updateUi.noDataSources=No data sources were found."})
+ private void setupDataSources() {
+
+ new SwingWorker