diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml
index 28a8815bca..6e9df6d3f1 100644
--- a/Core/nbproject/project.xml
+++ b/Core/nbproject/project.xml
@@ -242,6 +242,7 @@
org.sleuthkit.autopsy.eventsorg.sleuthkit.autopsy.externalresultsorg.sleuthkit.autopsy.filesearch
+ org.sleuthkit.autopsy.frameworkorg.sleuthkit.autopsy.ingestorg.sleuthkit.autopsy.keywordsearchserviceorg.sleuthkit.autopsy.menuactions
diff --git a/Core/src/org/sleuthkit/autopsy/actions/ExitAction.java b/Core/src/org/sleuthkit/autopsy/actions/ExitAction.java
index 62cc26b532..8a76b6855e 100755
--- a/Core/src/org/sleuthkit/autopsy/actions/ExitAction.java
+++ b/Core/src/org/sleuthkit/autopsy/actions/ExitAction.java
@@ -43,8 +43,7 @@ final public class ExitAction implements ActionListener {
try {
Case.closeCurrentCase();
} catch (CaseActionException ex) {
- // RJCTODO: Pop up here
- Logger.getLogger(ExitAction.class.getName()).log(Level.SEVERE, "Error closing the current case", ex); //NON-NLS
+ Logger.getLogger(ExitAction.class.getName()).log(Level.SEVERE, "Error closing the current case on exit", ex); //NON-NLS
} finally {
LifecycleManager.getDefault().exit();
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
index a3fbca6426..f7a21711f5 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties
@@ -98,12 +98,9 @@ AddImageWizardIngestConfigVisual.getName.text=Configure Ingest Modules
AddImageWizardIterator.stepXofN=Step {0} of {1}
AddLocalFilesTask.localFileAdd.progress.text=Adding\: {0}/{1}
Case.getCurCase.exception.noneOpen=Cannot get the current case; there is no case open\!
-Case.create.exception.msg=Error creating a case\: {0} in dir {1}
Case.databaseConnectionInfo.error.msg=Error accessing database server connection info. See Tools, Options, Multi-user.
-Case.open.exception.blankCase.msg=Case name is blank.
Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the database with the following path has been made\:\n {0}
Case.open.msgDlg.updated.title=Case Database Schema Update
-Case.open.exception.checkFile.msg=Case file must have {0} extension.
Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-user.
Case.checkImgExist.confDlg.doesntExist.msg={0} has detected that one of the images associated with \n\
this case are missing. Would you like to search for them now?\n\
@@ -113,9 +110,6 @@ Please note that you will still be able to browse directories and generate repor
if you choose No, but you will not be able to view file content or run the ingest process.
Case.checkImgExist.confDlg.doesntExist.title=Missing Image
Case.addImg.exception.msg=Error adding image to the case
-Case.closeCase.exception.msg=Error while trying to close the current case.
-Case.deleteCase.exception.msg=Error deleting the case dir\: {0}
-Case.deleteCase.exception.msg2=Error deleting the case dir\: {0}
Case.updateCaseName.exception.msg=Error while trying to update the case name.
Case.updateExaminer.exception.msg=Error while trying to update the examiner.
Case.updateCaseNum.exception.msg=Error while trying to update the case number.
@@ -240,4 +234,3 @@ LocalFilesPanel.displayNameLabel.text=Logical File Set Display Name: Default
IngestJobInfoPanel.jLabel1.text=Ingest Modules
IngestJobInfoPanel.jLabel2.text=Ingest Jobs
CaseInformationPanel.closeButton.text=Close
-ProgressPanel.progressMessage.text=Message
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties
index 54716ba8cb..7f2500d454 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle_ja.properties
@@ -1,4 +1,3 @@
-Case.closeCase.exception.msgCTL_AddImage=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0...
CTL_AddImageButton=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0
CTL_CaseCloseAct=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u308b
CTL_CaseNewAction=\u65b0\u898f\u30b1\u30fc\u30b9...
@@ -80,21 +79,15 @@ AddImageWizardIngestConfigVisual.getName.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30
AddImageWizardIterator.stepXofN=\u30b9\u30c6\u30c3\u30d7{0}\uff0f{1}
AddLocalFilesTask.localFileAdd.progress.text=\u8ffd\u52a0\u4e2d\uff1a{0}/{1}
Case.getCurCase.exception.noneOpen=\u4f5c\u696d\u4e2d\u306e\u30b1\u30fc\u30b9\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\uff1b\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\uff01
-Case.create.exception.msg=\u30b1\u30fc\u30b9\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{1}\u306e{0}
-Case.open.exception.blankCase.msg=\u30b1\u30fc\u30b9\u540d\u304c\u7a7a\u767d\u3067\u3059\u3002
Case.open.msgDlg.updated.msg=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002\n\u6b21\u306e\u30d1\u30b9\u3092\u6301\u3064\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30b3\u30d4\u30fc\u304c\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f\uff1a\n\
{0}
Case.open.msgDlg.updated.title=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0
-Case.open.exception.checkFile.msg=\u30b1\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u306f{0}\u62e1\u5f35\u5b50\u304c\u5fc5\u8981\u3067\u3059\u3002
Case.checkImgExist.confDlg.doesntExist.msg={0} \u304c\u3053\u306e\u30b1\u30fc\u30b9\u306b\u95a2\u9023\u3059\u308b\u30a4\u30e1\u30fc\u30b8\u306e\u3046\u3061\uff11\u3064\u304c\u6b20\u843d\u3057\u3066\u3044\u308b\u306e\u3092\u691c\u51fa\u3057\u307e\u3057\u305f\u3002\u305d\u308c\u3092\u4eca\u304b\u3089\u691c\u7d22\u3057\u307e\u3059\u304b\uff1f\n\n\
\u4ee5\u524d\u3001\u30a4\u30e1\u30fc\u30b8\u306f\u6b21\u306b\u3042\u308a\u307e\u3057\u305f\uff1a\n\
{1}\n\
\u3044\u3044\u3048\u3092\u9078\u629e\u3057\u3066\u3082\u3001\u4eca\u5f8c\u3082\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u95b2\u89a7\u3057\u3001\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u304c\u3067\u304d\u307e\u3059\u304c\u3001\n\u30d5\u30a1\u30a4\u30eb\u30b3\u30f3\u30c6\u30f3\u30c4\u306e\u8868\u793a\u307e\u305f\u306f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30d7\u30ed\u30bb\u30b9\u306e\u5b9f\u884c\u304c\u3067\u304d\u306a\u304f\u306a\u308a\u307e\u3059\u3002
Case.checkImgExist.confDlg.doesntExist.title=\u6b20\u843d\u3057\u3066\u3044\u308b\u30a4\u30e1\u30fc\u30b8
Case.addImg.exception.msg=\u30b1\u30fc\u30b9\u306b\u30a4\u30e1\u30fc\u30b8\u3092\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
-Case.closeCase.exception.msg=\u4f5c\u696d\u4e2d\u306e\u30b1\u30fc\u30b9\u3092\u9589\u3058\u308b\u6700\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
-Case.deleteCase.exception.msg=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}
-Case.deleteCase.exception.msg2=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u524a\u9664\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a{0}
Case.updateCaseName.exception.msg=\u30b1\u30fc\u30b9\u540d\u3092\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
Case.updateExaminer.exception.msg=\u8abf\u67fb\u62c5\u5f53\u8005\u3092\u66f4\u65b0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
Case.updateCaseNum.exception.msg=\u30b1\u30fc\u30b9\u756a\u53f7\u3092\u66f4\u65b0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
index 1b91d37a82..c41d225b6d 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java
@@ -51,7 +51,6 @@ import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import javax.annotation.concurrent.GuardedBy;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.openide.util.Lookup;
@@ -76,22 +75,26 @@ import org.sleuthkit.autopsy.coordinationservice.CoordinationServiceNamespace;
import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.core.UserPreferencesException;
-import org.sleuthkit.autopsy.corecomponentinterfaces.AutopsyService;
-import org.sleuthkit.autopsy.corecomponentinterfaces.AutopsyService.CaseContext;
import org.sleuthkit.autopsy.corecomponentinterfaces.CoreComponentControl;
-import org.sleuthkit.autopsy.corecomponentinterfaces.ProgressIndicator;
import org.sleuthkit.autopsy.coreutils.DriveUtils;
import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
+import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
import org.sleuthkit.autopsy.coreutils.Version;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.autopsy.events.AutopsyEventException;
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
+import org.sleuthkit.autopsy.framework.AutopsyService;
+import org.sleuthkit.autopsy.framework.AutopsyService.CaseContext;
+import org.sleuthkit.autopsy.framework.LoggingProgressIndicator;
+import org.sleuthkit.autopsy.framework.ModalDialogProgressIndicator;
+import org.sleuthkit.autopsy.framework.ProgressIndicator;
import org.sleuthkit.autopsy.ingest.IngestJob;
import org.sleuthkit.autopsy.ingest.IngestManager;
+import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
import org.sleuthkit.autopsy.timeline.OpenTimelineAction;
import org.sleuthkit.datamodel.BlackboardArtifactTag;
import org.sleuthkit.datamodel.CaseDbConnectionInfo;
@@ -107,13 +110,11 @@ import org.sleuthkit.datamodel.TskCoreException;
*/
public class Case {
- /*
- * Constants.
- */
private static final int NAME_LOCK_TIMOUT_HOURS = 12;
private static final int SHARED_DIR_LOCK_TIMOUT_HOURS = 12;
private static final int RESOURCE_LOCK_TIMOUT_HOURS = 12;
private static final int MAX_SANITIZED_CASE_NAME_LEN = 47;
+ private static final String SINGLE_USER_CASE_DB_NAME = "autopsy.db";
private static final String EVENT_CHANNEL_NAME = "%s-Case-Events"; //NON-NLS
private static final String CACHE_FOLDER = "Cache"; //NON-NLS
private static final String EXPORT_FOLDER = "Export"; //NON-NLS
@@ -121,55 +122,33 @@ public class Case {
private static final String REPORTS_FOLDER = "Reports"; //NON-NLS
private static final String TEMP_FOLDER = "Temp"; //NON-NLS
private static final int MIN_SECS_BETWEEN_TSK_ERROR_REPORTS = 60;
- private static final String MODULE_FOLDER = "ModuleOutput"; //NON-NLS // RJCTODO
- private static final Logger LOGGER = Logger.getLogger(Case.class.getName());
- private static final ExecutorService caseActionExecutor = Executors.newSingleThreadExecutor();
+ private static final String MODULE_FOLDER = "ModuleOutput"; //NON-NLS
+ private static final Logger logger = Logger.getLogger(Case.class.getName());
+ private static final AutopsyEventPublisher eventPublisher = new AutopsyEventPublisher();
/*
- * A single-threaded executor used to guarantee that the case directory lock
- * for the current case is acquired and released in the same thread, as
- * required by the coordination service.
- */
- private static ExecutorService caseLockingExecutor;
-
- /*
- * The following group of fields is state associated with the "current case"
- * concept. This state is managed by a set of static methods that could be
- * refactored into a case manager class, which would be a step towards
- * supporting multiple open cases. RJCTODO: Write a story about this
+ * The application name, used to make the title of the main application
+ * window [application] name when there is no open case and [application
+ * name]-[curent case display name] when there is an open case. Initialized
+ * by getting the main window title before a case has been opened.
*
* TODO (JIRA-2231): Make the application name a RuntimeProperties item set
* by Installers.
*/
- @GuardedBy("Case.class")
private static String appName;
+
/*
- * The one and only open case.
+ * The following fields are the state associated with the currently open
+ * case. The coordination service lock on the case directory of the
+ * currently open is used to prevent deletion of a multi-user case by this
+ * node if it is open in another node. The case locking executor is a
+ * single-threaded executor to guarantee that the case directory lock is
+ * acquired and released in the same thread, as required by the coordination
+ * service.
*/
- @GuardedBy("Case.class")
private static Case currentCase;
- /*
- * A coordination service lock on the case directory of the one and only
- * open case. Used to prevent deletion of a multi-user case by this node if
- * it is open in another node.
- */
- @GuardedBy("Case.class")
- private static CoordinationService.Lock currentCaseDirLock; // RJCTODO: Move into case
- /*
- * The collaboration monitor for the current case. It is specific to the
- * current case because it uses an event channel with a name derived from
- * the name of the current case.
- */
- @GuardedBy("Case.class")
- private static CollaborationMonitor collaborationMonitor; // RJCTODO: Move into case
- /*
- * The publisher for case events, both locally and, if the case is a
- * multi-user case, to other nodes. This is part of the state for the
- * current case because it opens and closes an event channel with a name
- * derived from the name of the current case.
- */
- @GuardedBy("Case.class")
- private static final AutopsyEventPublisher eventPublisher = new AutopsyEventPublisher();
+ private static CoordinationService.Lock currentCaseDirLock;
+ private static ExecutorService caseLockingExecutor;
/*
* Case instance data.
@@ -177,6 +156,7 @@ public class Case {
private CaseMetadata caseMetadata;
private SleuthkitCase caseDb;
private SleuthkitErrorReporter sleuthkitErrorReporter;
+ private CollaborationMonitor collaborationMonitor;
private Services services;
private boolean hasDataSources;
@@ -221,9 +201,12 @@ public class Case {
/**
* Gets the localized display name for this case type.
*
- * @return The dis[play name.
+ * @return The display name.
*/
- @Messages({"Case_caseType_singleUser=Single-user case", "Case_caseType_multiUser=Multi-user case"})
+ @Messages({
+ "Case_caseType_singleUser=Single-user case",
+ "Case_caseType_multiUser=Multi-user case"
+ })
String getLocalizedDisplayName() {
if (fromString(typeName) == SINGLE_USER_CASE) {
return Bundle.Case_caseType_singleUser();
@@ -242,12 +225,12 @@ public class Case {
}
/**
- * Tests the equality of the type name of this case type with a case
- * type name.
+ * Tests the equality of the type name of this case type with another
+ * case type name.
*
- * @param otherTypeName A case type name
+ * @param otherTypeName A case type name,
*
- * @return True or false
+ * @return True or false,
*
* @deprecated Do not use.
*/
@@ -259,8 +242,8 @@ public class Case {
};
/**
- * An enumeration of the events (property change events) a case may publish
- * (fire).
+ * An enumeration of the case events (property change events) a case may
+ * publish (fire).
*/
public enum Events {
@@ -272,8 +255,8 @@ public class Case {
NAME,
/**
* The number of the current case has changed. The old value of the
- * PropertyChangeEvent is the old number (type: String), the new value
- * is the new case number (type: String).
+ * PropertyChangeEvent is the old case number (type: String), the new
+ * value is the new case number (type: String).
*/
NUMBER,
/**
@@ -287,7 +270,7 @@ public class Case {
* made. The old and new values of the PropertyChangeEvent are null.
* Cast the PropertyChangeEvent to
* org.sleuthkit.autopsy.casemodule.events.AddingDataSourceEvent to
- * access event data.
+ * access additional event data.
*/
ADDING_DATA_SOURCE,
/**
@@ -295,7 +278,7 @@ public class Case {
* The old and new values of the PropertyChangeEvent are null. Cast the
* PropertyChangeEvent to
* org.sleuthkit.autopsy.casemodule.events.AddingDataSourceFailedEvent
- * to access event data.
+ * to access additional event data.
*/
ADDING_DATA_SOURCE_FAILED,
/**
@@ -303,7 +286,7 @@ public class Case {
* of the PropertyChangeEvent is null, the new value is the newly-added
* data source (type: Content). Cast the PropertyChangeEvent to
* org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent to
- * access event data.
+ * access additional event data.
*/
DATA_SOURCE_ADDED,
/**
@@ -327,7 +310,7 @@ public class Case {
*/
REPORT_ADDED,
/**
- * A report has been added to the current case. The old value of the
+ * A report has been deleted from the current case. The old value of the
* PropertyChangeEvent is the report (type: Report), the new value is
* null.
*/
@@ -340,8 +323,7 @@ public class Case {
BLACKBOARD_ARTIFACT_TAG_ADDED,
/**
* A tag has been removed from an artifact associated with the current
- * case. The old value of the PropertyChangeEvent is is the tag info
- * (type:
+ * case. The old value of the PropertyChangeEvent is the tag info (type:
* BlackBoardArtifactTagDeletedEvent.DeletedBlackboardArtifactTagInfo),
* the new value is null.
*/
@@ -428,11 +410,7 @@ public class Case {
* Checks if a case display name is valid, i.e., does not include any
* characters that cannot be used in file names.
*
- *
- * RJCTODO: Not really needed any more with display name concept; what
- * happens in auto ingest? Make sure these things are in sanitize...etc.
- *
- * @param caseName The case name.
+ * @param caseName The candidate case name.
*
* @return True or false.
*/
@@ -462,13 +440,16 @@ public class Case {
* exception.
*/
@Messages({
- "Case.creationException.illegalCaseName=Could not create case: case name contains illegal characters.",
"# {0} - exception message", "Case.creationException.couldNotCreateCase=Could not create case: {0}",
+ "Case.exceptionMessage.illegalCaseName=Case name contains illegal characters.",
+ "Case.exceptionMessage.lockAcquisitionInterrupted=Acquiring locks was interrupted.",
"Case.progressIndicatorTitle.creatingCase=Creating Case",
- "Case.progressIndicatorCancelButton.cancelLabel=Cancel",
- "Case.progressMessage.preparingToCreateCase=Preparing to create case...",
- "Case.progressMessage.acquiringLocks=Acquiring locks...",})
- public synchronized static void createCurrentCase(String caseDir, String caseDisplayName, String caseNumber, String examiner, CaseType caseType) throws CaseActionException {
+ "Case.progressIndicatorCancelButton.label=Cancel",
+ "Case.progressMessage.preparing=Preparing...",
+ "Case.progressMessage.acquiringLocks=Acquiring locks...",
+ "Case.progressMessage.finshing=Finishing..."
+ })
+ public static void createAsCurrentCase(String caseDir, String caseDisplayName, String caseNumber, String examiner, CaseType caseType) throws CaseActionException {
/*
* If running with the desktop GUI, this needs to be done before any
* cases are created or opened so that the application name can be
@@ -496,9 +477,9 @@ public class Case {
try {
caseName = sanitizeCaseName(caseDisplayName);
} catch (IllegalCaseNameException ex) {
- throw new CaseActionException(Bundle.Case_creationException_illegalCaseName(), ex);
+ throw new CaseActionException(Bundle.Case_creationException_couldNotCreateCase(Bundle.Case_exceptionMessage_illegalCaseName()), ex);
}
- LOGGER.log(Level.INFO, "Attempting to create case {0} (display name = {1}) in directory = {2}", new Object[]{caseName, caseDisplayName, caseDir}); //NON-NLS
+ logger.log(Level.INFO, "Attempting to create case {0} (display name = {1}) in directory = {2}", new Object[]{caseName, caseDisplayName, caseDir}); //NON-NLS
/*
* Set up either a GUI progress indicator or a logging progress
@@ -507,11 +488,14 @@ public class Case {
CancelButtonListener listener = new CancelButtonListener();
ProgressIndicator progressIndicator;
if (RuntimeProperties.runningWithGUI()) {
- progressIndicator = new ModalDialogProgressIndicator(Bundle.Case_progressIndicatorTitle_creatingCase(), new String[]{Bundle.Case_progressIndicatorCancelButton_cancelLabel()}, Bundle.Case_progressIndicatorCancelButton_cancelLabel(), null, listener);
+ progressIndicator = new ModalDialogProgressIndicator(Bundle.Case_progressIndicatorTitle_creatingCase(), new String[]{Bundle.Case_progressIndicatorCancelButton_label()}, Bundle.Case_progressIndicatorCancelButton_label(), null, listener);
} else {
progressIndicator = new LoggingProgressIndicator();
}
- progressIndicator.start(Bundle.Case_progressMessage_preparingToCreateCase());
+ Case newCase = new Case();
+ CaseContext caseContext = new CaseContext(newCase, progressIndicator);
+ listener.setCaseContext(caseContext);
+ progressIndicator.start(Bundle.Case_progressMessage_preparing());
/*
* Creating a case is always done in the same non-UI thread that will be
@@ -521,8 +505,7 @@ public class Case {
* required by the coordination service.
*/
try {
- Future innerFuture = getCaseLockingExecutor().submit(() -> {
- Case newCase = new Case();
+ Future future = getCaseLockingExecutor().submit(() -> {
if (CaseType.SINGLE_USER_CASE == caseType) {
newCase.open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator);
} else {
@@ -542,48 +525,54 @@ public class Case {
/*
* Finally, acquire an exclusive case resources lock to
* ensure only one node at a time can
- * create/open/upgrade the case resources.
+ * create/open/upgrade/close the case resources.
*/
try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(caseName)) {
assert (null != resourcesLock);
- newCase.open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator);
+ try {
+ newCase.open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator);
+ } catch (CaseActionException ex) {
+ /*
+ * Release the case directory lock immediately
+ * if there was a problem opening the case.
+ */
+ if (CaseType.MULTI_USER_CASE == caseType) {
+ releaseSharedCaseDirLock(caseName);
+ }
+ throw ex;
+ }
}
}
}
return newCase;
});
if (RuntimeProperties.runningWithGUI()) {
- listener.setCaseActionFuture(innerFuture);
- SwingUtilities.invokeLater(()
- -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(true));
+ listener.setCaseActionFuture(future);
+ SwingUtilities.invokeLater(() -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(true));
}
- currentCase = innerFuture.get();
- LOGGER.log(Level.INFO, "Created case {0} in directory = {1}", new Object[]{caseName, caseDir}); //NON-NLS
+ currentCase = future.get();
+ logger.log(Level.INFO, "Created case {0} in directory = {1}", new Object[]{caseName, caseDir}); //NON-NLS
if (RuntimeProperties.runningWithGUI()) {
updateGUIForCaseOpened();
}
eventPublisher.publishLocally(new AutopsyEvent(Events.CURRENT_CASE.toString(), null, currentCase));
} catch (InterruptedException | ExecutionException ex) {
- if (CaseType.MULTI_USER_CASE == caseType) {
- releaseSharedCaseDirLock(caseName);
- }
if (ex instanceof InterruptedException) {
- throw new CaseActionException(Bundle.Case_creationException_couldNotCreateCase("Interrupted during locks acquisition"), ex); //RJCTODO
+ throw new CaseActionException(Bundle.Case_creationException_couldNotCreateCase(Bundle.Case_exceptionMessage_lockAcquisitionInterrupted()), ex);
} else {
throw new CaseActionException(Bundle.Case_creationException_couldNotCreateCase(ex.getCause().getMessage()), ex);
}
} finally {
- progressIndicator.finish(""); // RJCTODO: Is this right message? Nope
+ progressIndicator.finish(Bundle.Case_progressMessage_finshing());
if (RuntimeProperties.runningWithGUI()) {
- SwingUtilities.invokeLater(()
- -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(false));
+ SwingUtilities.invokeLater(() -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(false));
}
}
}
/**
- * Opens an existing Autopsy case and makes it the current case.
+ * Opens an existing case and makes it the current case.
*
* @param caseMetadataFilePath The path of the case metadata (.aut) file.
*
@@ -595,10 +584,9 @@ public class Case {
@Messages({
"# {0} - exception message", "Case.openException.couldNotOpenCase=Could not open case: {0}",
"Case.progressIndicatorTitle.openingCase=Opening Case",
- "Case.progressMessage.preparingToOpenCase=Preparing to open case...",
- "Case.creationException.couldNotCreateMetadataFile=Could not create case: failed to create case metadata file."
+ "Case.exceptionMessage.failedToReadMetadata=Failed to read metadata."
})
- public synchronized static void openCurrentCase(String caseMetadataFilePath) throws CaseActionException {
+ public static void openAsCurrentCase(String caseMetadataFilePath) throws CaseActionException {
/*
* If running with the desktop GUI, this needs to be done before any
* cases are created or opened so that the application name can be
@@ -618,7 +606,7 @@ public class Case {
closeCurrentCase();
}
- LOGGER.log(Level.INFO, "Opening case with metadata file path {0}", caseMetadataFilePath); //NON-NLS
+ logger.log(Level.INFO, "Opening case with metadata file path {0}", caseMetadataFilePath); //NON-NLS
try {
CaseMetadata metadata = new CaseMetadata(Paths.get(caseMetadataFilePath));
@@ -629,11 +617,14 @@ public class Case {
CancelButtonListener listener = new CancelButtonListener();
ProgressIndicator progressIndicator;
if (RuntimeProperties.runningWithGUI()) {
- progressIndicator = new ModalDialogProgressIndicator(Bundle.Case_progressIndicatorTitle_openingCase(), new String[]{Bundle.Case_progressIndicatorCancelButton_cancelLabel()}, Bundle.Case_progressIndicatorCancelButton_cancelLabel(), null, listener);
+ progressIndicator = new ModalDialogProgressIndicator(Bundle.Case_progressIndicatorTitle_openingCase(), new String[]{Bundle.Case_progressIndicatorCancelButton_label()}, Bundle.Case_progressIndicatorCancelButton_label(), null, listener);
} else {
progressIndicator = new LoggingProgressIndicator();
}
- progressIndicator.start(Bundle.Case_progressMessage_preparingToOpenCase());
+ Case caseToOpen = new Case();
+ CaseContext caseContext = new CaseContext(caseToOpen, progressIndicator);
+ listener.setCaseContext(caseContext);
+ progressIndicator.start(Bundle.Case_progressMessage_preparing());
/*
* Opening a case is always done in the same non-UI thread that will
@@ -646,9 +637,8 @@ public class Case {
String caseName = metadata.getCaseName();
try {
Future future = getCaseLockingExecutor().submit(() -> {
- Case openedCase = new Case();
if (CaseType.SINGLE_USER_CASE == caseType) {
- openedCase.open(metadata, progressIndicator);
+ caseToOpen.open(metadata, progressIndicator);
} else {
/*
* First, acquire a shared case directory lock that will
@@ -661,48 +651,63 @@ public class Case {
/*
* Next, acquire an exclusive case resources lock to
* ensure only one node at a time can
- * create/open/upgrade case resources.
+ * create/open/upgrade/close case resources.
*/
try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(metadata.getCaseName())) {
assert (null != resourcesLock);
- openedCase.open(metadata, progressIndicator);
+ try {
+ caseToOpen.open(metadata, progressIndicator);
+ } catch (CaseActionException ex) {
+ /*
+ * Release the case directory lock immediately
+ * if there was a problem opening the case.
+ */
+ if (CaseType.MULTI_USER_CASE == caseType) {
+ releaseSharedCaseDirLock(caseName);
+ }
+ throw ex;
+ }
}
}
- return openedCase;
+ return caseToOpen;
});
if (RuntimeProperties.runningWithGUI()) {
listener.setCaseActionFuture(future);
- SwingUtilities.invokeLater(()
- -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(true));
+ SwingUtilities.invokeLater(() -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(true));
}
future.get();
currentCase = future.get();
- LOGGER.log(Level.INFO, "Opened case {0} in directory = {1}", new Object[]{metadata.getCaseName(), metadata.getCaseDirectory()}); //NON-NLS
+ logger.log(Level.INFO, "Opened case with metadata file path {0}", caseMetadataFilePath); //NON-NLS
if (RuntimeProperties.runningWithGUI()) {
updateGUIForCaseOpened();
}
eventPublisher.publishLocally(new AutopsyEvent(Events.CURRENT_CASE.toString(), null, currentCase));
} catch (InterruptedException | ExecutionException ex) {
- if (CaseType.SINGLE_USER_CASE == caseType) {
- releaseSharedCaseDirLock(caseName);
- }
if (ex instanceof ExecutionException) {
throw new CaseActionException(Bundle.Case_openException_couldNotOpenCase(ex.getCause().getMessage()), ex);
} else {
- throw new CaseActionException(Bundle.Case_openException_couldNotOpenCase("Interrupted during locks acquisition"), ex);
+ throw new CaseActionException(Bundle.Case_openException_couldNotOpenCase(Bundle.Case_exceptionMessage_lockAcquisitionInterrupted()), ex);
}
} finally {
- progressIndicator.finish(""); // RJCTODO: Is this right message?
+ progressIndicator.finish(Bundle.Case_progressMessage_finshing());
if (RuntimeProperties.runningWithGUI()) {
- SwingUtilities.invokeLater(()
- -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(false));
+ SwingUtilities.invokeLater(() -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(false));
}
}
} catch (CaseMetadataException ex) {
- throw new CaseActionException(Bundle.Case_openException_couldNotOpenCase("Failed to access case metadata"), ex);
+ throw new CaseActionException(Bundle.Case_openException_couldNotOpenCase(Bundle.Case_exceptionMessage_failedToReadMetadata()), ex);
}
}
+ /**
+ * Checks if a case, the current case, is open.
+ *
+ * @return True or false.
+ */
+ public static boolean isCaseOpen() {
+ return currentCase != null;
+ }
+
/**
* Gets the current case, if there is one.
*
@@ -710,11 +715,10 @@ public class Case {
*
* @throws IllegalStateException if there is no current case.
*/
- public synchronized static Case getCurrentCase() {
+ public static Case getCurrentCase() {
if (currentCase != null) {
return currentCase;
} else {
- // This is for backawards compatibility. RJCTODO: Reference story
throw new IllegalStateException(NbBundle.getMessage(Case.class, "Case.getCurCase.exception.noneOpen"));
}
}
@@ -728,11 +732,10 @@ public class Case {
* exception.
*/
@Messages({
- "Case.caseActionException.noCurrentCase=There is no open case",
"# {0} - exception message", "Case.closeException.couldNotCloseCase=Error closing case: {0}",
- "Case.progressIndicatorTitle.closingCase=Closing Case",
- "Case.progressMessage.preparingToCloseCase=Preparing to close case...",})
- public synchronized static void closeCurrentCase() throws CaseActionException {
+ "Case.progressIndicatorTitle.closingCase=Closing Case"
+ })
+ public static void closeCurrentCase() throws CaseActionException {
if (null == currentCase) {
return;
}
@@ -741,15 +744,23 @@ public class Case {
* Set up either a GUI progress indicator or a logging progress
* indicator.
*/
+ CancelButtonListener listener = new CancelButtonListener();
ProgressIndicator progressIndicator;
if (RuntimeProperties.runningWithGUI()) {
- progressIndicator = new ModalDialogProgressIndicator(Bundle.Case_progressIndicatorTitle_closingCase(), null, null, null, null);
+ progressIndicator = new ModalDialogProgressIndicator(
+ Bundle.Case_progressIndicatorTitle_closingCase(),
+ new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
+ Bundle.Case_progressIndicatorCancelButton_label(),
+ null,
+ listener);
} else {
progressIndicator = new LoggingProgressIndicator();
}
- progressIndicator.start(Bundle.Case_progressMessage_preparingToCloseCase());
+ CaseContext caseContext = new CaseContext(currentCase, progressIndicator);
+ listener.setCaseContext(caseContext);
+ progressIndicator.start(Bundle.Case_progressMessage_preparing());
-// LOGGER.log(Level.INFO, "Opening case with metadata file path {0}", caseMetadataFilePath); //NON-NLS RJCTOD
+ logger.log(Level.INFO, "Closing case with metadata file path {0}", currentCase.getCaseMetadata().getFilePath()); //NON-NLS
try {
/*
* Closing a case is always done in the same non-UI thread that
@@ -763,7 +774,14 @@ public class Case {
currentCase.close(progressIndicator);
} else {
String caseName = currentCase.getCaseMetadata().getCaseName();
- try {
+ /*
+ * Acquire an exclusive case resources lock to ensure only
+ * one node at a time can create/open/upgrade/close the case
+ * resources.
+ */
+ progressIndicator.start(Bundle.Case_progressMessage_acquiringLocks());
+ try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(currentCase.getName())) {
+ assert (null != resourcesLock);
currentCase.close(progressIndicator);
} finally {
/*
@@ -776,27 +794,31 @@ public class Case {
return null;
});
if (RuntimeProperties.runningWithGUI()) {
- SwingUtilities.invokeLater(()
- -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(true));
+ listener.setCaseActionFuture(future);
+ SwingUtilities.invokeLater(() -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(true));
}
future.get();
-// LOGGER.log(Level.INFO, "Closed case {0} in directory = {1}", new Object[]{metadata.getCaseName(), metadata.getCaseDirectory()}); //NON-NLS RJCTODO
+ } catch (InterruptedException | ExecutionException ex) {
+ if (ex instanceof ExecutionException) {
+ throw new CaseActionException(Bundle.Case_closeException_couldNotCloseCase(ex.getCause().getMessage()), ex);
+ } else {
+ throw new CaseActionException(Bundle.Case_closeException_couldNotCloseCase(Bundle.Case_exceptionMessage_lockAcquisitionInterrupted()), ex);
+ }
+ } finally {
+ /*
+ * The case is no longer the current case, even if an exception was
+ * thrown.
+ */
+ logger.log(Level.INFO, "Closed case with metadata file path {0}", currentCase.getCaseMetadata().getFilePath()); //NON-NLS
+ Case closedCase = currentCase;
+ currentCase = null;
if (RuntimeProperties.runningWithGUI()) {
updateGUIForCaseClosed();
}
- eventPublisher.publishLocally(new AutopsyEvent(Events.CURRENT_CASE.toString(), null, currentCase));
- } catch (InterruptedException | ExecutionException ex) {
- if (ex instanceof ExecutionException) {
- throw new CaseActionException(Bundle.Case_openException_couldNotOpenCase(ex.getCause().getMessage()), ex); // RJCTODO
- } else {
- throw new CaseActionException(Bundle.Case_openException_couldNotOpenCase("Interrupted during locks acquisition"), ex); // RJCTODO
- }
- } finally {
- currentCase = null;
- progressIndicator.finish(""); // RJCTODO: Is this right message? Nope
+ eventPublisher.publishLocally(new AutopsyEvent(Events.CURRENT_CASE.toString(), closedCase, null));
+ progressIndicator.finish(Bundle.Case_progressMessage_finshing());
if (RuntimeProperties.runningWithGUI()) {
- SwingUtilities.invokeLater(()
- -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(false));
+ SwingUtilities.invokeLater(() -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(false));
}
}
}
@@ -809,9 +831,9 @@ public class Case {
* and may be a wrapper for a lower-level
* exception.
*/
- public synchronized static void deleteCurrentCase() throws CaseActionException {
+ public static void deleteCurrentCase() throws CaseActionException {
if (null == currentCase) {
- throw new CaseActionException(Bundle.Case_caseActionException_noCurrentCase());
+ return;
}
CaseMetadata metadata = currentCase.getCaseMetadata();
closeCurrentCase();
@@ -829,72 +851,93 @@ public class Case {
* and may be a wrapper for a lower-level
* exception.
*/
- public static synchronized void deleteCase(CaseMetadata metadata) throws CaseActionException {
- if (null != currentCase && 0 == metadata.getCaseDirectory().compareTo(currentCase.getCaseDirectory())) {
- // RJCTODO: Throw
+ @Messages({
+ "# {0} - exception message", "Case.deleteException.couldNotDeleteCase=Could not delete case: {0}",
+ "Case.progressIndicatorTitle.deletingCase=Deleting Case",
+ "Case.exceptionMessage.cannotDeleteCurrentCase=Cannot delete current case, it must be closed first.",
+ "Case.progressMessage.deletingTextIndex=Deleting text index...",
+ "Case.progressMessage.deletingCaseDatabase=Deleting case database..."
+ })
+ public static void deleteCase(CaseMetadata metadata) throws CaseActionException {
+ if (null != currentCase && 0 == metadata.getCaseDirectory().compareTo(metadata.getCaseDirectory())) {
+ throw new CaseActionException(Bundle.Case_deleteException_couldNotDeleteCase(Bundle.Case_exceptionMessage_cannotDeleteCurrentCase()));
}
+ logger.log(Level.INFO, "Deleting case with metadata file path {0}", metadata.getFilePath()); //NON-NLS
try {
/*
* Set up either a GUI progress indicator or a logging progress
* indicator.
*/
+ CancelButtonListener listener = new CancelButtonListener();
ProgressIndicator progressIndicator;
if (RuntimeProperties.runningWithGUI()) {
- progressIndicator = new ModalDialogProgressIndicator(Bundle.Case_progressIndicatorTitle_closingCase(), null, null, null, null); // RJCTODO
+ progressIndicator = new ModalDialogProgressIndicator(
+ Bundle.Case_progressIndicatorTitle_deletingCase(),
+ new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
+ Bundle.Case_progressIndicatorCancelButton_label(),
+ null,
+ listener);
} else {
progressIndicator = new LoggingProgressIndicator();
}
- progressIndicator.start(Bundle.Case_progressMessage_preparingToCloseCase());
+ progressIndicator.start(Bundle.Case_progressMessage_preparing());
Future future = getCaseLockingExecutor().submit(() -> {
if (CaseType.SINGLE_USER_CASE == metadata.getCaseType()) {
- cleanupDeletedCase(metadata);
+ cleanupDeletedCase(metadata, progressIndicator);
} else {
- String caseName = currentCase.getCaseMetadata().getCaseName();
/*
* First, acquire an exclusive case directory lock. The case
* cannot be deleted if another node has it open.
*/
- try (CoordinationService.Lock dirLock = acquireExclusiveLock(metadata.getCaseDirectory())) {
+ progressIndicator.start(Bundle.Case_progressMessage_acquiringLocks());
+ try (CoordinationService.Lock dirLock = CoordinationService.getServiceForNamespace(CoordinationServiceNamespace.getRoot()).tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, metadata.getCaseDatabasePath())) {
assert (null != dirLock);
- /*
- * Try to unload/delete the Solr core from the Solr
- * server. Do this before deleting the case directory
- * because the index files are in the case directory and
- * the deletion will fail if the core is not unloaded
- * first.
- */
- // RJCTODO: Need a method for this in keyword search service, code is in AIM at the moment
/*
- * Delete the case database from the database server.
+ * Delete the text index.
*/
- CaseDbConnectionInfo db = UserPreferences.getDatabaseConnectionInfo();
- Class.forName("org.postgresql.Driver"); //NON-NLS
- try (Connection connection = DriverManager.getConnection("jdbc:postgresql://" + db.getHost() + ":" + db.getPort() + "/postgres", db.getUserName(), db.getPassword()); //NON-NLS
- Statement statement = connection.createStatement();) {
- String deleteCommand = "DROP DATABASE \"" + metadata.getCaseDatabaseName() + "\""; //NON-NLS
- statement.execute(deleteCommand);
+ progressIndicator.start(Bundle.Case_progressMessage_deletingTextIndex());
+ for (KeywordSearchService searchService : Lookup.getDefault().lookupAll(KeywordSearchService.class)) {
+ searchService.deleteTextIndex(metadata.getTextIndexName());
}
- cleanupDeletedCase(metadata);
+ if (CaseType.MULTI_USER_CASE == metadata.getCaseType()) {
+ /*
+ * Delete the case database from the database
+ * server. The case database for a single-user case
+ * is in the case directory and will be deleted whe
+ * it is deleted.
+ */
+ progressIndicator.start(Bundle.Case_progressMessage_deletingCaseDatabase());
+ CaseDbConnectionInfo db = UserPreferences.getDatabaseConnectionInfo();
+ Class.forName("org.postgresql.Driver"); //NON-NLS
+ try (Connection connection = DriverManager.getConnection("jdbc:postgresql://" + db.getHost() + ":" + db.getPort() + "/postgres", db.getUserName(), db.getPassword()); //NON-NLS
+ Statement statement = connection.createStatement();) {
+ String deleteCommand = "DROP DATABASE \"" + metadata.getCaseDatabaseName() + "\""; //NON-NLS
+ statement.execute(deleteCommand);
+ }
+ }
+
+ cleanupDeletedCase(metadata, progressIndicator);
}
}
return null;
});
+ logger.log(Level.INFO, "Deleted case with metadata file path {0}", metadata.getFilePath()); //NON-NLS
future.get();
} catch (InterruptedException | ExecutionException ex) {
if (ex instanceof ExecutionException) {
- throw new CaseActionException(Bundle.Case_openException_couldNotOpenCase(ex.getCause().getMessage()), ex); // RJCTODO
+ throw new CaseActionException(Bundle.Case_deleteException_couldNotDeleteCase(ex.getCause().getMessage()), ex);
} else {
- throw new CaseActionException(Bundle.Case_openException_couldNotOpenCase("Interrupted during locks acquisition"), ex); // RJCTODO
+ throw new CaseActionException(Bundle.Case_deleteException_couldNotDeleteCase(Bundle.Case_exceptionMessage_lockAcquisitionInterrupted()), ex);
}
}
}
/**
* Sanitizes the case name for use as a PostgreSQL database name and in
- * ActiveMQ event channle (topic) names.
+ * ActiveMQ event channel (topic) names.
*
* PostgreSQL:
* http://www.postgresql.org/docs/9.4/static/sql-syntax-lexical.html 63
@@ -1016,19 +1059,6 @@ public class Case {
}
}
- /**
- * Deletes a case directory.
- *
- * @param casePath A case directory path.
- *
- * @return True if the deletion succeeded, false otherwise.
- */
- // RJCTODO: Get rid of this foolishness
- static boolean deleteCaseDirectory(File casePath) {
- LOGGER.log(Level.INFO, "Deleting case directory: {0}", casePath.getAbsolutePath()); //NON-NLS
- return FileUtil.deleteDir(casePath);
- }
-
/**
* Gets the paths of data sources that are images.
*
@@ -1046,7 +1076,7 @@ public class Case {
}
}
} catch (TskCoreException ex) {
- LOGGER.log(Level.SEVERE, "Error getting image paths", ex); //NON-NLS
+ logger.log(Level.SEVERE, "Error getting image paths", ex); //NON-NLS
}
return imgPaths;
}
@@ -1072,18 +1102,28 @@ public class Case {
appName = WindowManager.getDefault().getMainWindow().getTitle();
});
} catch (InterruptedException | InvocationTargetException ex) {
- LOGGER.log(Level.SEVERE, "Unexpected exception getting main window title", ex);
+ logger.log(Level.SEVERE, "Unexpected exception getting main window title", ex);
}
}
}
- // RJCTODO
- private static void cleanupDeletedCase(CaseMetadata metadata) {
+ /**
+ * Deletes the case directory of a deleted case and removes the case form
+ * the Recent Cases menu.
+ *
+ * @param metadata The case metadata.
+ * @param progressIndicator A progress indicator.
+ */
+ @Messages({
+ "Case.progressMessage.deletingCaseDirectory=Deleting case directory..."
+ })
+ private static void cleanupDeletedCase(CaseMetadata metadata, ProgressIndicator progressIndicator) {
/*
* Delete the case directory.
*/
+ progressIndicator.start(Bundle.Case_progressMessage_deletingCaseDirectory());
if (!FileUtil.deleteDir(new File(metadata.getCaseDirectory()))) {
- LOGGER.log(Level.SEVERE, "Failed to fully delete case directory {0}", metadata.getCaseDirectory());
+ logger.log(Level.SEVERE, "Failed to fully delete case directory {0}", metadata.getCaseDirectory());
}
/*
@@ -1147,29 +1187,16 @@ public class Case {
* @param caseDir The full path of the case directory.
*/
private static void releaseSharedCaseDirLock(String caseDir) {
- // RJCTODO: Guard currentCaseLock? Yep!
if (currentCaseDirLock != null) {
try {
currentCaseDirLock.release();
currentCaseDirLock = null;
} catch (CoordinationService.CoordinationServiceException ex) {
- LOGGER.log(Level.SEVERE, String.format("Failed to release shared case directory lock for %s", caseDir), ex);
+ logger.log(Level.SEVERE, String.format("Failed to release shared case directory lock for %s", caseDir), ex);
}
}
}
- private static CoordinationService.Lock acquireExclusiveLock(String nodePath) throws CaseActionException {
- try {
- CoordinationService.Lock lock = CoordinationService.getServiceForNamespace(CoordinationServiceNamespace.getRoot()).tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, nodePath);
- if (null == lock) {
- throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireDirLock()); // RJCTODO
- }
- return lock;
- } catch (CoordinationServiceException ex) {
- throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireNameLock(), ex); // RJCTODO
- }
- }
-
/**
* Acquires an exclusive case resources lock.
*
@@ -1204,7 +1231,6 @@ public class Case {
SleuthkitCase caseDb = currentCase.getSleuthkitCase();
- // RJCTODO: Test both of these conditions
/*
* If the case database was upgraded for a new schema and a backup
* database was created, notify the user.
@@ -1233,13 +1259,13 @@ public class Case {
if (!fileExists) {
int ret = JOptionPane.showConfirmDialog(
WindowManager.getDefault().getMainWindow(),
- NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.msg", appName, path), // RJCTODO: Don't use app name here
+ NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.msg", appName, path),
NbBundle.getMessage(Case.class, "Case.checkImgExist.confDlg.doesntExist.title"),
JOptionPane.YES_NO_OPTION);
if (ret == JOptionPane.YES_OPTION) {
MissingImageDialog.makeDialog(obj_id, caseDb);
} else {
- LOGGER.log(Level.WARNING, "Selected image files don't match old files!"); //NON-NLS // RJCTODO
+ logger.log(Level.SEVERE, "User proceeding with missing image files"); //NON-NLS
}
}
}
@@ -1259,7 +1285,7 @@ public class Case {
* of recent cases to the recent cases menu item and the
* open/create case dialog.
*/
- RecentCases.getInstance().addRecentCase(currentCase.getName(), currentCase.getCaseMetadata().getFilePath().toString()); // update the recent cases
+ RecentCases.getInstance().addRecentCase(currentCase.getDisplayName(), currentCase.getCaseMetadata().getFilePath().toString());
/*
* Open the top components (windows within the main application
@@ -1273,7 +1299,7 @@ public class Case {
* Reset the main window title to be [application name] - [case
* name], instead of just the application name.
*/
- addCaseNameToMainWindowTitle(currentCase.getName());
+ addCaseNameToMainWindowTitle(currentCase.getDisplayName());
});
}
}
@@ -1341,6 +1367,25 @@ public class Case {
return caseLockingExecutor;
}
+ /**
+ * Empties the temp subdirectory for the current case.
+ */
+ private static void clearTempSubDir(String tempSubDirPath) {
+ File tempFolder = new File(tempSubDirPath);
+ if (tempFolder.isDirectory()) {
+ File[] files = tempFolder.listFiles();
+ if (files.length > 0) {
+ for (File file : files) {
+ if (file.isDirectory()) {
+ FileUtil.deleteDir(file);
+ } else {
+ file.delete();
+ }
+ }
+ }
+ }
+ }
+
/**
* Gets the case database.
*
@@ -1382,7 +1427,6 @@ public class Case {
*
* @return The case name.
*/
- // RJCTODO: Check all uses of this!
public String getName() {
return getCaseMetadata().getCaseName();
}
@@ -1552,7 +1596,7 @@ public class Case {
}
}
} catch (TskCoreException ex) {
- LOGGER.log(Level.SEVERE, "Error getting data source time zones", ex); //NON-NLS
+ logger.log(Level.SEVERE, "Error getting data source time zones", ex); //NON-NLS
}
return timezones;
}
@@ -1588,7 +1632,7 @@ public class Case {
try {
hasDataSources = (getDataSources().size() > 0);
} catch (TskCoreException ex) {
- LOGGER.log(Level.SEVERE, "Error accessing case database", ex); //NON-NLS
+ logger.log(Level.SEVERE, "Error accessing case database", ex); //NON-NLS
}
}
return hasDataSources;
@@ -1741,10 +1785,8 @@ public class Case {
}
/**
- * Updates the case name.
- *
- * This should not be called from the EDT.
- *
+ * Updates the case display name name.
+ *
* @param oldCaseName The old case name.
* @param oldPath The old path name.
* @param newCaseName The new case name.
@@ -1752,11 +1794,11 @@ public class Case {
*/
void updateCaseName(String oldCaseName, String oldPath, String newCaseName, String newPath) throws CaseActionException {
try {
- caseMetadata.setCaseName(newCaseName);
+ caseMetadata.setCaseDisplayName(newCaseName);
eventPublisher.publish(new AutopsyEvent(Events.NAME.toString(), oldCaseName, newCaseName));
SwingUtilities.invokeLater(() -> {
try {
- RecentCases.getInstance().updateRecentCase(oldCaseName, oldPath, newCaseName, newPath); // update the recent case
+ RecentCases.getInstance().updateRecentCase(oldCaseName, oldPath, newCaseName, newPath);
addCaseNameToMainWindowTitle(newCaseName);
} catch (Exception ex) {
Logger.getLogger(Case.class.getName()).log(Level.SEVERE, "Error updating case name in UI", ex); //NON-NLS
@@ -1795,7 +1837,9 @@ public class Case {
@Messages({
"Case.progressMessage.creatingCaseDirectory=Creating case directory...",
"Case.progressMessage.creatingCaseDatabase=Creating case database...",
- "Case.progressMessage.creatingCaseMetadataFile=Creating case metadata file..."
+ "Case.progressMessage.creatingCaseMetadataFile=Creating case metadata file...",
+ "Case.exceptionMessage.couldNotCreateMetadataFile=Failed to create case metadata file.",
+ "Case.exceptionMessage.couldNotCreateCaseDatabase=Failed to create case database."
})
private void open(String caseDir, String caseName, String caseDisplayName, String caseNumber, String examiner, CaseType caseType, ProgressIndicator progressIndicator) throws CaseActionException {
/*
@@ -1830,7 +1874,7 @@ public class Case {
String dbName = null;
try {
if (caseType == CaseType.SINGLE_USER_CASE) {
- dbName = Paths.get(caseDir, "autopsy.db").toString(); // RJCTODO: Move to a const, fix non-relative path, need opening db message here
+ dbName = Paths.get(caseDir, SINGLE_USER_CASE_DB_NAME).toString();
this.caseDb = SleuthkitCase.newCase(dbName);
} else if (caseType == CaseType.MULTI_USER_CASE) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
@@ -1839,9 +1883,9 @@ public class Case {
this.caseDb = SleuthkitCase.newCase(dbName, UserPreferences.getDatabaseConnectionInfo(), caseDir);
}
} catch (TskCoreException ex) {
- throw new CaseActionException(String.format("Error creating the case database %s: %s", dbName, ex.getMessage()), ex); //NON-NLS RJCTOD
+ throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseDatabase(), ex);
} catch (UserPreferencesException ex) {
- throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.databaseConnectionInfo.error.msg"), ex); // RJCTODO
+ throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.databaseConnectionInfo.error.msg"), ex);
}
/*
@@ -1851,19 +1895,26 @@ public class Case {
try {
this.caseMetadata = new CaseMetadata(caseDir, caseType, caseName, caseDisplayName, caseNumber, examiner, dbName);
} catch (CaseMetadataException ex) {
- throw new CaseActionException(Bundle.Case_creationException_couldNotCreateMetadataFile(), ex);
+ throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateMetadataFile(), ex);
}
open(progressIndicator);
}
/**
- * Opens an exsiting case. RJCTODO
+ * Opens an existing case.
*
- * @param metadata
- * @param progressIndicator
+ * @param metadata The case metadata.
+ * @param progressIndicator A progress indicator.
*
- * @throws CaseActionException
+ * @throws CaseActionException if there is a problem opening the case. The
+ * exception will have a user-friendly message
+ * and may be a wrapper for a lower-level
+ * exception.
*/
+ @Messages({
+ "Case.progressMessage.openingCaseDatabase=Opening case database...",
+ "Case.exceptionMessage.couldNotOpenCaseDatabase=Failed to open case database."
+ })
private void open(CaseMetadata metadata, ProgressIndicator progressIndicator) throws CaseActionException {
this.caseMetadata = metadata;
@@ -1871,6 +1922,7 @@ public class Case {
* Open the case database.
*/
try {
+ progressIndicator.progress(Bundle.Case_progressMessage_openingCaseDatabase());
if (CaseType.SINGLE_USER_CASE == metadata.getCaseType()) {
this.caseDb = SleuthkitCase.openCase(metadata.getCaseDatabasePath());
} else if (UserPreferences.getIsMultiUserModeEnabled()) {
@@ -1878,14 +1930,13 @@ public class Case {
this.caseDb = SleuthkitCase.openCase(metadata.getCaseDatabaseName(), UserPreferences.getDatabaseConnectionInfo(), metadata.getCaseDirectory());
} catch (UserPreferencesException ex) {
- throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.databaseConnectionInfo.error.msg"), ex); // RJCTODO: What does this say?
+ throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.databaseConnectionInfo.error.msg"), ex);
}
} else {
throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.open.exception.multiUserCaseNotEnabled"));
}
} catch (TskCoreException ex) {
- // RJCTODO: Need proper exception message
- throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.databaseConnectionInfo.error.msg"), ex);
+ throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotOpenCaseDatabase(), ex);
}
open(progressIndicator);
}
@@ -1899,9 +1950,12 @@ public class Case {
@Messages({
"Case.progressMessage.switchingLogDirectory=Switching log directory...",
"Case.progressMessage.settingUpTskErrorReporting=Setting up SleuthKit error reporting...",
- "Case.progressMessage.clearingTempDirectory=Clearing case temp directory...",
"Case.progressMessage.openingCaseLevelServices=Opening case-level services...",
- "Case.progressMessage.openingApplicationServiceResources=Opening case-specific application service resources...",})
+ "Case.progressMessage.openingApplicationServiceResources=Opening case-specific application service resources...",
+ "Case.progressMessage.settingUpNetworkCommunications=Setting up network communications...",
+ "# {0} - service name", "# {1} - exception message", "Case.servicesException.serviceResourcesOpenError=Could not open case resources for {0} service: {1}",
+ "# {0} - service name", "Case.servicesException.notificationTitle={0} Service Error"
+ })
private void open(ProgressIndicator progressIndicator) {
/*
* Switch to writing to the application logs in the logs subdirectory.
@@ -1934,14 +1988,19 @@ public class Case {
*/
progressIndicator.progress(Bundle.Case_progressMessage_openingApplicationServiceResources());
AutopsyService.CaseContext context = new AutopsyService.CaseContext(this, progressIndicator);
- String serviceName = "";
for (AutopsyService service : Lookup.getDefault().lookupAll(AutopsyService.class)) {
try {
- serviceName = service.getServiceName();
service.openCaseResources(context);
} catch (AutopsyService.AutopsyServiceException ex) {
- // RJCTODO: Pop up error here?
- Case.LOGGER.log(Level.SEVERE, String.format("%s service failed to open case resources", serviceName), ex);
+ /*
+ * The case-specific application service resources are not
+ * essential. Log an error and notify the user, but do not
+ * throw.
+ */
+ Case.logger.log(Level.SEVERE, String.format("%s service failed to open case resources", service.getServiceName()), ex);
+ if (RuntimeProperties.runningWithGUI()) {
+ SwingUtilities.invokeLater(() -> MessageNotifyUtil.Notify.error(Bundle.Case_servicesException_notificationTitle(service.getServiceName()), Bundle.Case_servicesException_serviceResourcesOpenError(service.getServiceName(), ex.getLocalizedMessage())));
+ }
}
}
@@ -1950,21 +2009,40 @@ public class Case {
* other nodes.
*/
if (CaseType.MULTI_USER_CASE == this.caseMetadata.getCaseType()) {
+ progressIndicator.progress(Bundle.Case_progressMessage_settingUpNetworkCommunications());
try {
- eventPublisher.openRemoteEventChannel(String.format(EVENT_CHANNEL_NAME, this.getCaseMetadata().getCaseName()));
- collaborationMonitor = new CollaborationMonitor();
+ eventPublisher.openRemoteEventChannel(String.format(EVENT_CHANNEL_NAME, this.getName()));
+ collaborationMonitor = new CollaborationMonitor(this.getName());
} catch (AutopsyEventException | CollaborationMonitor.CollaborationMonitorException ex) {
- // RJCTODO: Explain why this is not a fatal error
- LOGGER.log(Level.SEVERE, "Failed to setup for collaboration", ex); //NON-NLS
- MessageNotifyUtil.Notify.error(NbBundle.getMessage(Case.class, "Case.CollaborationSetup.FailNotify.Title"), NbBundle.getMessage(Case.class, "Case.CollaborationSetup.FailNotify.ErrMsg"));
+ /*
+ * The collaboration monitor and event channel are not
+ * essential. Log an error and notify the user, but do not
+ * throw.
+ */
+ logger.log(Level.SEVERE, "Failed to setup network communications", ex); //NON-NLS
+ if (RuntimeProperties.runningWithGUI()) {
+ SwingUtilities.invokeLater(() -> MessageNotifyUtil.Notify.error(NbBundle.getMessage(Case.class, "Case.CollaborationSetup.FailNotify.Title"), NbBundle.getMessage(Case.class, "Case.CollaborationSetup.FailNotify.ErrMsg")));
+ }
}
}
}
- /*
- * RJCTODO
+ /**
+ * Closes the case.
+ *
+ * @param progressIndicator A progress indicator.
*/
+ @Messages({
+ "Case.progressMessage.cancellingIngestJobs=Cancelling ingest jobs...",
+ "Case.progressMessage.notifyingCaseEventSubscribers=Notifying case event subscribers...",
+ "Case.progressMessage.clearingTempDirectory=Clearing case temp directory...",
+ "Case.progressMessage.closingCaseLevelServices=Closing case-level services...",
+ "Case.progressMessage.closingApplicationServiceResources=Closing case-specific application service resources...",
+ "Case.progressMessage.tearingDownNetworkCommunications=Tearing down network communications...",
+ "Case.progressMessage.closingCaseDatabase=Closing case database...",
+ "Case.progressMessage.tearingDownTskErrorReporting=Tearing down SleuthKit error reporting..."
+ })
private void close(ProgressIndicator progressIndicator) {
/*
* Cancel all ingest jobs.
@@ -1972,12 +2050,14 @@ public class Case {
* TODO (JIRA-2227): Case closing should wait for ingest to stop to
* avoid changing the case database while ingest is still using it.
*/
+ progressIndicator.progress(Bundle.Case_progressMessage_cancellingIngestJobs());
IngestManager.getInstance().cancelAllIngestJobs(IngestJob.CancellationReason.CASE_CLOSED);
/*
* Notify all local case event subscribers that the case is closed and
* all interactions with the current case are no longer permitted.
*/
+ progressIndicator.progress(Bundle.Case_progressMessage_notifyingCaseEventSubscribers());
eventPublisher.publishLocally(new AutopsyEvent(Events.CURRENT_CASE.toString(), currentCase, null));
/*
@@ -1985,6 +2065,7 @@ public class Case {
* a multi-user case.
*/
if (CaseType.MULTI_USER_CASE == currentCase.getCaseType()) {
+ progressIndicator.progress(Bundle.Case_progressMessage_tearingDownNetworkCommunications());
if (null != collaborationMonitor) {
collaborationMonitor.shutdown();
}
@@ -1995,6 +2076,7 @@ public class Case {
* Allow all registered applications ervices providers to close
* resources related to the case.
*/
+ progressIndicator.progress(Bundle.Case_progressMessage_closingApplicationServiceResources());
AutopsyService.CaseContext context = new AutopsyService.CaseContext(currentCase, progressIndicator);
String serviceName = "";
for (AutopsyService service : Lookup.getDefault().lookupAll(AutopsyService.class)) {
@@ -2004,49 +2086,34 @@ public class Case {
service.closeCaseResources(context);
}
} catch (AutopsyService.AutopsyServiceException ex) {
- Case.LOGGER.log(Level.SEVERE, String.format("%s service failed to close case resources", serviceName), ex);
+ Case.logger.log(Level.SEVERE, String.format("%s service failed to close case resources", serviceName), ex);
}
}
/*
* Close the case-level services.
*/
+ progressIndicator.progress(Bundle.Case_progressMessage_closingCaseLevelServices());
try {
currentCase.getServices().close();
} catch (IOException ex) {
- LOGGER.log(Level.SEVERE, String.format("Error closing internal case services for %s", getName()), ex);
+ logger.log(Level.SEVERE, String.format("Error closing internal case services for %s at %s", this.getName(), this.getCaseDirectory()), ex);
}
/*
* Close the case database
*/
+ progressIndicator.progress(Bundle.Case_progressMessage_closingCaseDatabase());
this.caseDb.close();
/*
* Disconnect the SleuthKit layer error reporter.
*/
+ progressIndicator.progress(Bundle.Case_progressMessage_tearingDownTskErrorReporting());
this.caseDb.removeErrorObserver(this.sleuthkitErrorReporter);
- // RJCTODO: Reset the log directory?
- }
-
- /**
- * Empties the temp subdirectory for the current case.
- */
- private static void clearTempSubDir(String tempSubDirPath) {
- File tempFolder = new File(tempSubDirPath);
- if (tempFolder.isDirectory()) {
- File[] files = tempFolder.listFiles();
- if (files.length > 0) {
- for (File file : files) {
- if (file.isDirectory()) {
- FileUtil.deleteDir(file);
- } else {
- file.delete();
- }
- }
- }
- }
+ progressIndicator.progress(Bundle.Case_progressMessage_switchingLogDirectory());
+ Logger.setLogDirectory(PlatformUtil.getLogDirectory());
}
/**
@@ -2064,19 +2131,6 @@ public class Case {
}
- private final static class IllegalCaseNameException extends Exception {
-
- private static final long serialVersionUID = 1L;
-
- private IllegalCaseNameException(String message) {
- super(message);
- }
-
- private IllegalCaseNameException(String message, Throwable cause) {
- super(message, cause);
- }
- }
-
private final static class CancelButtonListener implements ActionListener {
private Future> caseActionFuture;
@@ -2086,7 +2140,7 @@ public class Case {
this.caseActionFuture = caseActionFuture;
}
- private void setCaseContext(CaseContext caseContext) { // RJCTODO: USe this
+ private void setCaseContext(CaseContext caseContext) {
this.caseContext = caseContext;
}
@@ -2102,6 +2156,36 @@ public class Case {
}
+ /**
+ * An exception to throw when a case name with invalid characters is
+ * encountered.
+ */
+ final static class IllegalCaseNameException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs an exception to throw when a case name with invalid
+ * characters is encountered.
+ *
+ * @param message The exception message.
+ */
+ IllegalCaseNameException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an exception to throw when a case name with invalid
+ * characters is encountered.
+ *
+ * @param message The exception message.
+ * @param cause The exceptin cause.
+ */
+ IllegalCaseNameException(String message, Throwable cause) {
+ super(message, cause);
+ }
+ }
+
/**
* Creates a new, single-user Autopsy case.
*
@@ -2123,7 +2207,7 @@ public class Case {
*/
@Deprecated
public static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner) throws CaseActionException {
- createCurrentCase(caseDir, caseDisplayName, caseNumber, examiner, CaseType.SINGLE_USER_CASE);
+ createAsCurrentCase(caseDir, caseDisplayName, caseNumber, examiner, CaseType.SINGLE_USER_CASE);
}
/**
@@ -2148,7 +2232,7 @@ public class Case {
*/
@Deprecated
public static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner, CaseType caseType) throws CaseActionException {
- createCurrentCase(caseDir, caseDisplayName, caseNumber, examiner, caseType);
+ createAsCurrentCase(caseDir, caseDisplayName, caseNumber, examiner, caseType);
}
/**
@@ -2164,19 +2248,7 @@ public class Case {
*/
@Deprecated
public static void open(String caseMetadataFilePath) throws CaseActionException {
- openCurrentCase(caseMetadataFilePath);
- }
-
- /**
- * Checks if case is currently open.
- *
- * @return True or false.
- *
- * @deprecated Do not use, this method is not relaible.
- */
- @Deprecated
- public static boolean isCaseOpen() {
- return currentCase != null;
+ openAsCurrentCase(caseMetadataFilePath);
}
/**
@@ -2337,7 +2409,4 @@ public class Case {
deleteReports(reports);
}
- @Deprecated
- public static final String propStartup = "LBL_StartupDialog"; //NON-NLS
-
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseActionHelper.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseActionHelper.java
deleted file mode 100644
index a488a05fb1..0000000000
--- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseActionHelper.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Autopsy Forensic Browser
- *
- * Copyright 2011-2017 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.casemodule;
-
-import java.awt.Cursor;
-import java.util.logging.Level;
-import org.openide.DialogDescriptor;
-import org.openide.DialogDisplayer;
-import org.openide.NotifyDescriptor;
-import org.openide.util.NbBundle;
-import org.openide.windows.WindowManager;
-import org.sleuthkit.autopsy.coreutils.Logger;
-import org.sleuthkit.autopsy.ingest.IngestJob;
-import org.sleuthkit.autopsy.ingest.IngestManager;
-
-/**
- * A utility class for common code for case actions.
- */
-class CaseActionHelper {
-
- /**
- * Tries to closes the current case, if any, with a checks to see if ingest
- * is running; if it is, the user is given the opportunity to let the ingest
- * continue and stop the case action.
- *
- * @param
- * @return True if the current case, if any, is closed, false otherwise.
- */
- // RJCTODO: Be sure to test this! Discard this class
- static boolean closeCaseAndContinueAction() {
- if (IngestManager.getInstance().isIngestRunning()) {
- NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
- NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning"), // RJCTODO
- NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title"), // RJCTODO
- NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
- descriptor.setValue(NotifyDescriptor.NO_OPTION);
- Object choice = DialogDisplayer.getDefault().notify(descriptor);
- if (null != choice && DialogDescriptor.YES_OPTION == choice) {
- IngestManager.getInstance().cancelAllIngestJobs(IngestJob.CancellationReason.USER_CANCELLED);
- // RJCTODO; refer to JIRA here for blocking wait on cancel...
- return true;
- } else {
- return false;
- }
- }
- WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
- try {
- Case.closeCurrentCase();
- } catch (CaseActionException ex) {
- // RJCTODO: Pop up here
- Logger.getLogger(NewCaseWizardAction.class.getName()).log(Level.SEVERE, "Error closing case.", ex); //NON-NLS
- }
- WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
- return true;
- }
-
- /**
- * Private contructor to prevent instantiation.
- */
- private CaseActionHelper() {
- }
-}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java
index 3090d3d18b..6556f97dc0 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java
@@ -22,6 +22,7 @@ import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.util.concurrent.ExecutionException;
+import java.util.logging.Level;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
@@ -38,11 +39,12 @@ import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.Presenter;
import org.openide.windows.WindowManager;
+import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
/**
* An action to close the current case and pop up the start up window that
- * allows a user to open another case.
+ * allows a user to open another case.
*/
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.casemodule.CaseCloseAction")
@ActionRegistration(displayName = "#CTL_CaseCloseAct", lazy = false)
@@ -52,6 +54,7 @@ import org.sleuthkit.autopsy.ingest.IngestManager;
public final class CaseCloseAction extends CallableSystemAction implements Presenter.Toolbar {
private static final long serialVersionUID = 1L;
+ private static final Logger logger = Logger.getLogger(CaseCloseAction.class.getName());
private final JButton toolbarButton = new JButton();
/**
@@ -77,8 +80,8 @@ public final class CaseCloseAction extends CallableSystemAction implements Prese
*/
if (IngestManager.getInstance().isIngestRunning()) {
NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
- NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning"), // RJCTODO
- NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title"), // RJCTODO
+ NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning"),
+ NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title"),
NotifyDescriptor.YES_NO_OPTION,
NotifyDescriptor.WARNING_MESSAGE);
descriptor.setValue(NotifyDescriptor.NO_OPTION);
@@ -105,7 +108,7 @@ public final class CaseCloseAction extends CallableSystemAction implements Prese
try {
get();
} catch (InterruptedException | ExecutionException ex) {
- // RJCTODO: Pop up error and log
+ logger.log(Level.SEVERE, "Error closing the current case", ex);
}
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
StartupWindowProvider.getInstance().open();
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java
index 865a8c8eec..9f12944278 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java
@@ -169,45 +169,10 @@ public final class CaseMetadata {
*
* @return The case display name.
*/
- // RJCTODO: Deal with the change
public String getCaseName() {
return caseName;
}
-
- /**
- * Sets the case display name. This does not change the name of the case
- * directory, the case database, or the text index name.
- *
- * @param caseName A case display name.
- */
- // RJCTODO: Deal with the change, remove this
- void setCaseName(String caseName) throws CaseMetadataException {
- String oldCaseName = caseName;
- this.caseName = caseName;
- try {
- writeToFile();
- } catch (CaseMetadataException ex) {
- this.caseName = oldCaseName;
- throw ex;
- }
- }
- /**
- * Sets the text index name.
- *
- * @param caseTextIndexName The text index name.
- */
- void setTextIndexName(String caseTextIndexName) throws CaseMetadataException {
- String oldIndexName = caseTextIndexName;
- this.textIndexName = caseTextIndexName;
- try {
- writeToFile();
- } catch (CaseMetadataException ex) {
- this.textIndexName = oldIndexName;
- throw ex;
- }
- }
-
/**
* Gets the case display name.
*
@@ -223,7 +188,6 @@ public final class CaseMetadata {
*
* @param caseName A case display name.
*/
- // RJCTODO: Deal with the change
void setCaseDisplayName(String caseName) throws CaseMetadataException {
String oldCaseName = caseName;
this.caseDisplayName = caseName;
@@ -282,6 +246,22 @@ public final class CaseMetadata {
}
}
+ /**
+ * Sets the text index name.
+ *
+ * @param caseTextIndexName The text index name.
+ */
+ void setTextIndexName(String caseTextIndexName) throws CaseMetadataException {
+ String oldIndexName = caseTextIndexName;
+ this.textIndexName = caseTextIndexName;
+ try {
+ writeToFile();
+ } catch (CaseMetadataException ex) {
+ this.textIndexName = oldIndexName;
+ throw ex;
+ }
+ }
+
/**
* Gets the text index name.
*
@@ -349,7 +329,6 @@ public final class CaseMetadata {
* @throws CaseMetadataException If there is an error writing to the case
* metadata file.
*/
- // RJCTODO: Should we have a backup copy of the file in case of error?
private void writeToFile() throws CaseMetadataException {
try {
/*
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java
index 26404fbfd7..6fb60d9e38 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseOpenAction.java
@@ -43,7 +43,9 @@ import org.sleuthkit.autopsy.coreutils.Version;
import org.sleuthkit.autopsy.ingest.IngestManager;
/**
- * An action that opens an existing case.
+ * An action that opens an existing case. It is associated with the Case/Open
+ * menu item via the layer.xml file, with a toolbar button, and with a button on
+ * the startup window.
*/
@ServiceProvider(service = CaseOpenAction.class)
public final class CaseOpenAction extends CallableSystemAction implements ActionListener {
@@ -82,8 +84,8 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
*/
if (IngestManager.getInstance().isIngestRunning()) {
NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
- NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning"), // RJCTODO
- NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title"), // RJCTODO
+ NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning"),
+ NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title"),
NotifyDescriptor.YES_NO_OPTION,
NotifyDescriptor.WARNING_MESSAGE);
descriptor.setValue(NotifyDescriptor.NO_OPTION);
@@ -116,7 +118,7 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
@Override
protected Void doInBackground() throws Exception {
- Case.openCurrentCase(path);
+ Case.openAsCurrentCase(path);
return null;
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java
index e0c4e75cab..e49887c931 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesForm.java
@@ -77,15 +77,15 @@ class CasePropertiesForm extends javax.swing.JPanel {
*/
CasePropertiesForm(Case currentCase, String crDate, String caseDir, Map imgPaths) throws CaseMetadata.CaseMetadataException {
initComponents();
- caseNameTextField.setText(currentCase.getName());
+ caseNameTextField.setText(currentCase.getDisplayName());
String caseNumber = currentCase.getNumber();
- if (!caseNumber.equals("")) {
+ if (!caseNumber.isEmpty()) {
caseNumberField.setText(caseNumber);
} else {
caseNumberField.setText("N/A");
}
String examiner = currentCase.getExaminer();
- if (!examiner.equals("")) {
+ if (!examiner.isEmpty()) {
examinerField.setText(examiner);
} else {
examinerField.setText("N/A");
@@ -303,13 +303,13 @@ class CasePropertiesForm extends javax.swing.JPanel {
* @param evt The action event
*/
private void updateCaseNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_updateCaseNameButtonActionPerformed
- String oldCaseName = Case.getCurrentCase().getName();
+ String oldCaseName = Case.getCurrentCase().getDisplayName();
String newCaseName = caseNameTextField.getText();
// check if the old and new case name is not equal
if (!oldCaseName.equals(newCaseName)) {
// check if the case name is empty
- if (newCaseName.trim().equals("")) {
+ if (newCaseName.trim().isEmpty()) {
JOptionPane.showMessageDialog(caller,
NbBundle.getMessage(this.getClass(),
"CasePropertiesForm.updateCaseName.msgDlg.empty.msg"),
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java b/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java
index bdb3ae29de..6042c24d12 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/CollaborationMonitor.java
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
- * Copyright 2011-2015 Basis Technology Corp.
+ * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier sleuthkit org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -77,8 +77,13 @@ final class CollaborationMonitor {
* collaborating nodes, informs the user of collaboration tasks on other
* nodes using progress bars, and monitors the health of key collaboration
* services.
+ *
+ * @param eventChannelPrefix The prefix for the remote events channel.
+ *
+ * @throws
+ * org.sleuthkit.autopsy.casemodule.CollaborationMonitor.CollaborationMonitorException
*/
- CollaborationMonitor() throws CollaborationMonitorException {
+ CollaborationMonitor(String eventChannelPrefix) throws CollaborationMonitorException {
/**
* Get the local host name so it can be used to identify the source of
* collaboration tasks broadcast by this node.
@@ -91,9 +96,7 @@ final class CollaborationMonitor {
*/
eventPublisher = new AutopsyEventPublisher();
try {
- Case openedCase = Case.getCurrentCase();
- String channelPrefix = openedCase.getTextIndexName();
- eventPublisher.openRemoteEventChannel(String.format(EVENT_CHANNEL_NAME, channelPrefix));
+ eventPublisher.openRemoteEventChannel(String.format(EVENT_CHANNEL_NAME, eventChannelPrefix));
} catch (AutopsyEventException ex) {
throw new CollaborationMonitorException("Failed to initialize", ex);
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/DeleteCurrentCaseAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/DeleteCurrentCaseAction.java
index ff60df9070..0de0c2365b 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/DeleteCurrentCaseAction.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/DeleteCurrentCaseAction.java
@@ -54,6 +54,7 @@ final class DeleteCurrentCaseAction extends CallableSystemAction {
try {
Case currentCase = Case.getCurrentCase();
String caseName = currentCase.getName();
+ String caseDirectory = currentCase.getCaseDirectory();
/*
* Do a confirmation dialog and close the current case if the user
@@ -68,16 +69,15 @@ final class DeleteCurrentCaseAction extends CallableSystemAction {
NotifyDescriptor.NO_OPTION));
if (null != response && DialogDescriptor.YES_OPTION == response) {
try {
- Case.deleteCurrentCase(); // RJCTODO: Test this!
+ Case.deleteCurrentCase();
} catch (CaseActionException ex) {
- logger.log(Level.SEVERE, String.format("Failed to delete case %s", caseName), ex);
+ logger.log(Level.SEVERE, String.format("Failed to delete case %s at %s", caseName, caseDirectory), ex);
JOptionPane.showMessageDialog(
null,
Bundle.Case_deleteCaseFailureMessageBox_message(ex.getMessage()),
Bundle.Case_deleteCaseFailureMessageBox_title(),
JOptionPane.ERROR_MESSAGE);
}
- // RJCTODO: Fix this
// because the "Delete Case" button is in the "CaseProperties" window, we have to close that window when we delete the case.
CasePropertiesAction.closeCasePropertiesWindow();
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java
index 1cceb7ab12..f76f620413 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java
@@ -33,7 +33,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgress
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.DataSourceUtils;
-import org.sleuthkit.autopsy.corecomponentinterfaces.AutoIngestDataSourceProcessor;
+import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
/**
* A image file data source processor that implements the DataSourceProcessor
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java
index 015f7751ea..305bb3dd90 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java
@@ -30,7 +30,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.DriveUtils;
-import org.sleuthkit.autopsy.corecomponentinterfaces.AutoIngestDataSourceProcessor;
+import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
/**
* A local drive data source processor that implements the DataSourceProcessor
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java
index 9c19cb2cfc..e207734714 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java
@@ -29,7 +29,7 @@ import org.openide.util.lookup.ServiceProviders;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
-import org.sleuthkit.autopsy.corecomponentinterfaces.AutoIngestDataSourceProcessor;
+import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
/**
* A local/logical files and/or directories data source processor that
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java
index b85215a2be..41a1ae7366 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java
@@ -27,9 +27,10 @@ import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
-import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
+import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
@@ -37,7 +38,9 @@ import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.SystemAction;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
+import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.ingest.IngestManager;
/**
* An action that creates and runs the new case wizard.
@@ -50,13 +53,28 @@ final class NewCaseWizardAction extends CallableSystemAction {
@Override
public void performAction() {
- if (CaseActionHelper.closeCaseAndContinueAction()) {
- WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); // RJCTODO: Is this right?
- runNewCaseWizard();
+ /*
+ * If ingest is running, give the user the option to abort changing
+ * cases.
+ */
+ // Is this right here?
+ if (IngestManager.getInstance().isIngestRunning()) {
+ NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
+ NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning"),
+ NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title"),
+ NotifyDescriptor.YES_NO_OPTION,
+ NotifyDescriptor.WARNING_MESSAGE);
+ descriptor.setValue(NotifyDescriptor.NO_OPTION);
+ Object response = DialogDisplayer.getDefault().notify(descriptor);
+ if (DialogDescriptor.NO_OPTION == response) {
+ return;
+ }
}
+ runNewCaseWizard();
}
private void runNewCaseWizard() {
+ WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
final WizardDescriptor wizardDescriptor = new WizardDescriptor(getNewCaseWizardPanels());
wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
wizardDescriptor.setTitle(NbBundle.getMessage(this.getClass(), "NewCaseWizardAction.newCase.windowTitle.text"));
@@ -72,7 +90,7 @@ final class NewCaseWizardAction extends CallableSystemAction {
final String caseName = (String) wizardDescriptor.getProperty("caseName"); //NON-NLS
String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS
CaseType caseType = CaseType.values()[(int) wizardDescriptor.getProperty("caseType")]; //NON-NLS
- Case.createCurrentCase(createdDirectory, caseName, caseNumber, examiner, caseType);
+ Case.createAsCurrentCase(createdDirectory, caseName, caseNumber, examiner, caseType);
return null;
}
@@ -84,16 +102,16 @@ final class NewCaseWizardAction extends CallableSystemAction {
addImageAction.actionPerformed(null);
} catch (InterruptedException | ExecutionException ex) {
logger.log(Level.SEVERE, String.format("Error creating case %s", wizardDescriptor.getProperty("caseName")), ex); //NON-NLS
- SwingUtilities.invokeLater(() -> {
- JOptionPane.showMessageDialog(
- WindowManager.getDefault().getMainWindow(),
- (ex instanceof ExecutionException ? ex.getCause().getMessage() : ex.getMessage()),
- NbBundle.getMessage(this.getClass(), "CaseCreateAction.msgDlg.cantCreateCase.msg"), //NON-NLS
- JOptionPane.ERROR_MESSAGE);
- StartupWindowProvider.getInstance().close(); // RC: Why close and open?
- StartupWindowProvider.getInstance().open();
- });
+ JOptionPane.showMessageDialog(
+ WindowManager.getDefault().getMainWindow(),
+ (ex instanceof ExecutionException ? ex.getCause().getMessage() : ex.getMessage()),
+ NbBundle.getMessage(this.getClass(), "CaseCreateAction.msgDlg.cantCreateCase.msg"), //NON-NLS
+ JOptionPane.ERROR_MESSAGE);
+ StartupWindowProvider.getInstance().close();
+ StartupWindowProvider.getInstance().open();
doFailedCaseCleanup(wizardDescriptor);
+ } finally {
+ WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
}.execute();
@@ -107,11 +125,8 @@ final class NewCaseWizardAction extends CallableSystemAction {
private void doFailedCaseCleanup(WizardDescriptor wizardDescriptor) {
String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS
if (createdDirectory != null) {
- Case.deleteCaseDirectory(new File(createdDirectory));
+ FileUtil.deleteDir(new File(createdDirectory));
}
- SwingUtilities.invokeLater(() -> {
- WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
- });
}
/**
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java
index 9cc94cd182..d22beb2d34 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardPanel1.java
@@ -35,6 +35,7 @@ import org.openide.WizardDescriptor;
import org.openide.WizardValidationException;
import org.openide.util.HelpCtx;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
+import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
/**
@@ -175,7 +176,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel {
try {
- Case.openCurrentCase(casePath);
+ Case.openAsCurrentCase(casePath);
} catch (CaseActionException ex) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", casePath), ex); //NON-NLS
SwingUtilities.invokeLater(() -> {
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/RecentCases.java b/Core/src/org/sleuthkit/autopsy/casemodule/RecentCases.java
index 2204da444a..0637e8e90c 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/RecentCases.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/RecentCases.java
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
- * Copyright 2011-2014 Basis Technology Corp.
+ * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier sleuthkit org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,13 +30,13 @@ import java.util.List;
import java.util.logging.Level;
import javax.swing.JMenuItem;
import org.apache.commons.lang.ArrayUtils;
+import org.openide.filesystems.FileUtil;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.Presenter;
-import org.openide.filesystems.FileUtil;
-import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.coreutils.ModuleSettings;
/**
* The action in this class is to clear the list of "Recent Cases". The
@@ -45,14 +45,13 @@ import org.sleuthkit.autopsy.coreutils.Logger;
*/
final class RecentCases extends CallableSystemAction implements Presenter.Menu {
- static final int LENGTH = 6;
- static final String NAME_PROP_KEY = "LBL_RecentCase_Name"; //NON-NLS
- static final String PATH_PROP_KEY = "LBL_RecentCase_Path"; //NON-NLS
- static final RecentCase BLANK_RECENTCASE = new RecentCase("", "");
-
- private final static RecentCases INSTANCE = new RecentCases();
-
- private Deque recentCases; // newest case is last case
+ private static final long serialVersionUID = 1L;
+ private static final int LENGTH = 6;
+ private static final String NAME_PROP_KEY = "LBL_RecentCase_Name"; //NON-NLS
+ private static final String PATH_PROP_KEY = "LBL_RecentCase_Path"; //NON-NLS
+ private static final RecentCase BLANK_RECENTCASE = new RecentCase("", "");
+ private final static RecentCases instance = new RecentCases();
+ private final Deque recentCases; // newest case is last case
/**
* Gets the instance of the RecentCases singleton.
@@ -61,8 +60,8 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
* @return INSTANCE the RecentCases singleton
*/
static public RecentCases getInstance() {
- INSTANCE.refreshRecentCases();
- return INSTANCE;
+ instance.refreshRecentCases();
+ return instance;
}
/**
@@ -84,7 +83,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
}
// Load recentCases from properties
- recentCases = new LinkedList();
+ recentCases = new LinkedList<>();
for (int i = 0; i < LENGTH; i++) {
final RecentCase rc = new RecentCase(getName(i), getPath(i));
@@ -256,7 +255,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
*/
@Override
public void actionPerformed(ActionEvent e) {
- UpdateRecentCases.hasRecentCase = false;
+ UpdateRecentCases.setHasRecentCase(false);
recentCases.clear();
@@ -375,7 +374,7 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
int i = 0;
String currentCaseName = null;
try {
- currentCaseName = Case.getCurrentCase().getName();
+ currentCaseName = Case.getCurrentCase().getDisplayName();
} catch (IllegalStateException ex) {
// in case there is no current case.
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java b/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java
index 693b294c1c..ae1606c417 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/RecentItems.java
@@ -25,14 +25,17 @@ import java.awt.event.ActionListener;
import java.io.File;
import java.util.logging.Level;
import javax.swing.JOptionPane;
+import org.openide.DialogDescriptor;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.ingest.IngestManager;
/**
- * An action listener that opens a recent case.
- *
- * IMPORTANT: Must be called in the Swing Event Dispatch Thread (EDT).
+ * An action listener for a specific case, associated with a Recent Cases menu
+ * item for the case by a DynamicMenuContent content JMenuItem.
*/
class RecentItems implements ActionListener {
@@ -41,7 +44,9 @@ class RecentItems implements ActionListener {
private final String caseMetaDataFilePath;
/**
- * Constructs an action listener that opens a recent case.
+ * Constructs an action listener for a specific case, associated with a
+ * Recent Cases menu item for the case by a DynamicMenuContent content
+ * JMenuItem.
*
* @param caseName The name of the case.
* @param caseMetaDataFilePath The path to the case metadata file.
@@ -52,37 +57,42 @@ class RecentItems implements ActionListener {
}
/**
- * Opens the recent case.
+ * Opens the case associated with the action.
*
* @param e the action event
*/
@Override
public void actionPerformed(ActionEvent e) {
- if (CaseActionHelper.closeCaseAndContinueAction()) {
- if (caseName.isEmpty() || caseMetaDataFilePath.isEmpty() || (!new File(caseMetaDataFilePath).exists())) {
- JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
- NbBundle.getMessage(this.getClass(), "RecentItems.openRecentCase.msgDlg.text", caseName),
- NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"),
- JOptionPane.ERROR_MESSAGE);
- RecentCases.getInstance().removeRecentCase(caseName, caseMetaDataFilePath);
- EventQueue.invokeLater(() -> {
- StartupWindowProvider.getInstance().open();
- });
- } else {
- WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
- try {
- Case.openCurrentCase(caseMetaDataFilePath);
- } catch (CaseActionException ex) {
- logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetaDataFilePath), ex); //NON-NLS
- WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
- JOptionPane.showMessageDialog(
- WindowManager.getDefault().getMainWindow(),
- ex.getMessage(), // Should be user-friendly
- NbBundle.getMessage(RecentItems.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
- JOptionPane.ERROR_MESSAGE);
- StartupWindowProvider.getInstance().open();
- }
+ /*
+ * If ingest is running, give the user the option to abort changing
+ * cases.
+ */
+ if (IngestManager.getInstance().isIngestRunning()) {
+ NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
+ NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning"),
+ NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title"),
+ NotifyDescriptor.YES_NO_OPTION,
+ NotifyDescriptor.WARNING_MESSAGE);
+ descriptor.setValue(NotifyDescriptor.NO_OPTION);
+ Object response = DialogDisplayer.getDefault().notify(descriptor);
+ if (DialogDescriptor.NO_OPTION == response) {
+ return;
}
}
+
+ WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+ try {
+ Case.openAsCurrentCase(caseMetaDataFilePath);
+ } catch (CaseActionException ex) {
+ logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetaDataFilePath), ex); //NON-NLS
+ JOptionPane.showMessageDialog(
+ WindowManager.getDefault().getMainWindow(),
+ ex.getMessage(), // Should be user-friendly
+ NbBundle.getMessage(RecentItems.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
+ JOptionPane.ERROR_MESSAGE);
+ StartupWindowProvider.getInstance().open();
+ } finally {
+ WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ }
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java b/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java
index 87c010e25b..6d57f3daac 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java
@@ -48,7 +48,7 @@ import org.sleuthkit.datamodel.TskData;
*/
public class SingleUserCaseConverter {
- static final String MODULE_FOLDER = "ModuleOutput"; //NON-NLS // RJCTODO
+ private static final String MODULE_FOLDER = "ModuleOutput"; //NON-NLS
private static final String AUTOPSY_DB_FILE = "autopsy.db"; //NON-NLS
private static final String DOTAUT = CaseMetadata.getFileExtension(); //NON-NLS
private static final String TIMELINE_FOLDER = "Timeline"; //NON-NLS
@@ -196,7 +196,7 @@ public class SingleUserCaseConverter {
CaseMetadata newCaseMetadata = new CaseMetadata(icd.getCaseOutputFolder().toString(),
CaseType.MULTI_USER_CASE,
icd.getNewCaseName(),
- icd.getNewCaseName(), // RJCTODO
+ icd.getNewCaseName(),
oldCaseMetadata.getCaseNumber(),
oldCaseMetadata.getExaminer(),
dbName);
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/UpdateRecentCases.java b/Core/src/org/sleuthkit/autopsy/casemodule/UpdateRecentCases.java
index 4d00a60606..29be82fe48 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/UpdateRecentCases.java
+++ b/Core/src/org/sleuthkit/autopsy/casemodule/UpdateRecentCases.java
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
- * Copyright 2011-2015 Basis Technology Corp.
+ * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier sleuthkit org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,17 +30,22 @@ import org.openide.util.actions.SystemAction;
*/
class UpdateRecentCases extends JMenuItem implements DynamicMenuContent {
- int length;
- static boolean hasRecentCase = false;
+ private static final long serialVersionUID = 1L;
+ private static int NUM_CASES_TO_DISPLAY;
+ private static boolean hasRecentCase = false;
/**
* the constructor
*/
UpdateRecentCases() {
// display last 5 cases.
- length = RecentCases.LENGTH - 1;
+ NUM_CASES_TO_DISPLAY = 5;
}
+ static void setHasRecentCase(boolean value) {
+ hasRecentCase = value;
+ }
+
/**
* Creates main menu/popup menu items. Null values will be later replaced by
* JSeparators. This method is called for popups and for menus. It's called
@@ -53,10 +58,10 @@ class UpdateRecentCases extends JMenuItem implements DynamicMenuContent {
public JComponent[] getMenuPresenters() {
String[] caseName = RecentCases.getInstance().getRecentCaseNames();
String[] casePath = RecentCases.getInstance().getRecentCasePaths();
- JComponent[] comps = new JComponent[length + 2]; // + 2 for separator and clear menu
+ JComponent[] comps = new JComponent[NUM_CASES_TO_DISPLAY + 2]; // + 2 for separator and clear menu
// if it has the recent menus, add them to the component list
- for (int i = 0; i < length; i++) {
+ for (int i = 0; i < NUM_CASES_TO_DISPLAY; i++) {
if ((!caseName[i].equals(""))) {
JMenuItem menuItem = new JMenuItem(caseName[i]);
menuItem.setActionCommand(caseName[i].toUpperCase());
@@ -68,11 +73,11 @@ class UpdateRecentCases extends JMenuItem implements DynamicMenuContent {
// if it has recent case, create clear menu
if (hasRecentCase) {
- comps[length] = new JSeparator();
+ comps[NUM_CASES_TO_DISPLAY] = new JSeparator();
JMenuItem clearMenu = new JMenuItem(
NbBundle.getMessage(UpdateRecentCases.class, "UpdateRecentCases.menuItem.clearRecentCases.text"));
clearMenu.addActionListener(SystemAction.get(RecentCases.class));
- comps[length + 1] = clearMenu;
+ comps[NUM_CASES_TO_DISPLAY + 1] = clearMenu;
} // otherwise, just create a disabled empty menu
else {
comps = new JComponent[1];
@@ -85,17 +90,15 @@ class UpdateRecentCases extends JMenuItem implements DynamicMenuContent {
}
/**
- * Updates main menu presenters. This method is called only by the main menu
- * processing.
+ * Updates the Recent Cases menu items.
*
- * @param jcs the previously used menu items returned by previous call to
- * getMenuPresenters() or synchMenuPresenters()
+ * @param menuItems A set of Recent Case menu items to be updated.
*
- * @return menu a new set of items to show in menu. Can be either an updated
- * old set of instances or a completely new one.
+ * @return A updated set of recent case menu items to show in the Recent
+ * Cases menu.
*/
@Override
- public JComponent[] synchMenuPresenters(JComponent[] jcs) {
+ public JComponent[] synchMenuPresenters(JComponent[] menuItems) {
return getMenuPresenters();
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/core/RuntimeProperties.java b/Core/src/org/sleuthkit/autopsy/core/RuntimeProperties.java
index 605fee4135..17999cc363 100644
--- a/Core/src/org/sleuthkit/autopsy/core/RuntimeProperties.java
+++ b/Core/src/org/sleuthkit/autopsy/core/RuntimeProperties.java
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
- * Copyright 2013-2015 Basis Technology Corp.
+ * Copyright 2013-2017 Basis Technology Corp.
* Contact: carrier sleuthkit org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -59,18 +59,33 @@ public class RuntimeProperties {
* Private constructor to prevent creation of instances of this class.
*/
private RuntimeProperties() {
-
}
- private final static class RuntimePropertiesException extends Exception {
+ /**
+ * Exception to throw if there is an error setting a runtime property.
+ */
+ public final static class RuntimePropertiesException extends Exception {
private static final long serialVersionUID = 1L;
- private RuntimePropertiesException(String message) {
+ /**
+ * Constructor for an exception to throw if there is an error setting
+ * a runtime property.
+ *
+ * @param message The exception message.
+ */
+ public RuntimePropertiesException(String message) {
super(message);
}
- private RuntimePropertiesException(String message, Throwable cause) {
+ /**
+ * Constructor for an exception to throw if there is an error setting
+ * a runtime property.
+ *
+ * @param message The exception message.
+ * @param cause The cause of the error.
+ */
+ public RuntimePropertiesException(String message, Throwable cause) {
super(message, cause);
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java
index 48c3127027..3bf74e42e8 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java
+++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Installer.java
@@ -46,7 +46,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
public class Installer extends ModuleInstall {
private static final long serialVersionUID = 1L;
- private static final Logger LOGGER = Logger.getLogger(Installer.class.getName());
+ private static final Logger logger = Logger.getLogger(Installer.class.getName());
private static Installer instance;
public synchronized static Installer getDefault() {
@@ -82,10 +82,9 @@ public class Installer extends ModuleInstall {
final String caseFile = argsProcessor.getDefaultArg();
if (caseFile != null && !caseFile.isEmpty() && caseFile.endsWith(CaseMetadata.getFileExtension()) && new File(caseFile).exists()) { //NON-NLS
try {
- Case.openCurrentCase(caseFile);
+ Case.openAsCurrentCase(caseFile);
} catch (CaseActionException ex) {
- // RJCTODO: SHould there be a popup here?
- LOGGER.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseFile), ex); //NON-NLS
+ logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseFile), ex); //NON-NLS
}
return;
}
@@ -105,7 +104,7 @@ public class Installer extends ModuleInstall {
try {
Case.closeCurrentCase();
} catch (CaseActionException ex) {
- LOGGER.log(Level.SEVERE, "Error closing current case", ex); //NON-NLS
+ logger.log(Level.SEVERE, "Error closing current case", ex); //NON-NLS
}
}
@@ -124,7 +123,7 @@ public class Installer extends ModuleInstall {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
- LOGGER.log(Level.WARNING, "Error setting OS-X look-and-feel", ex); //NON-NLS
+ logger.log(Level.WARNING, "Error setting OS-X look-and-feel", ex); //NON-NLS
}
// Store the keys that deal with menu items
@@ -140,7 +139,7 @@ public class Installer extends ModuleInstall {
try {
UIManager.setLookAndFeel(info.getClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
- LOGGER.log(Level.WARNING, "Error setting OS-X look-and-feel", ex); //NON-NLS
+ logger.log(Level.WARNING, "Error setting OS-X look-and-feel", ex); //NON-NLS
}
break;
}
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/AutoIngestDataSourceProcessor.java b/Core/src/org/sleuthkit/autopsy/framework/AutoIngestDataSourceProcessor.java
similarity index 92%
rename from Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/AutoIngestDataSourceProcessor.java
rename to Core/src/org/sleuthkit/autopsy/framework/AutoIngestDataSourceProcessor.java
index f7d50235da..e4acab8234 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/AutoIngestDataSourceProcessor.java
+++ b/Core/src/org/sleuthkit/autopsy/framework/AutoIngestDataSourceProcessor.java
@@ -16,9 +16,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.corecomponentinterfaces;
+package org.sleuthkit.autopsy.framework;
import java.nio.file.Path;
+import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
+import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
+import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
/**
* Interface implemented by DataSourceProcessors in order to be supported by
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/AutopsyService.java b/Core/src/org/sleuthkit/autopsy/framework/AutopsyService.java
similarity index 99%
rename from Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/AutopsyService.java
rename to Core/src/org/sleuthkit/autopsy/framework/AutopsyService.java
index 1bbc43b2c8..e4fa6958db 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/AutopsyService.java
+++ b/Core/src/org/sleuthkit/autopsy/framework/AutopsyService.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.corecomponentinterfaces;
+package org.sleuthkit.autopsy.framework;
import org.sleuthkit.autopsy.casemodule.Case;
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LoggingProgressIndicator.java b/Core/src/org/sleuthkit/autopsy/framework/LoggingProgressIndicator.java
similarity index 93%
rename from Core/src/org/sleuthkit/autopsy/casemodule/LoggingProgressIndicator.java
rename to Core/src/org/sleuthkit/autopsy/framework/LoggingProgressIndicator.java
index 4b99312fc9..3fcad59638 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/LoggingProgressIndicator.java
+++ b/Core/src/org/sleuthkit/autopsy/framework/LoggingProgressIndicator.java
@@ -16,16 +16,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.casemodule;
+package org.sleuthkit.autopsy.framework;
import java.util.logging.Level;
-import org.sleuthkit.autopsy.corecomponentinterfaces.ProgressIndicator;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* A progress indicator that writes progress to the Autopsy application log.
*/
-class LoggingProgressIndicator implements ProgressIndicator {
+public final class LoggingProgressIndicator implements ProgressIndicator {
private final Logger LOGGER = Logger.getLogger(LoggingProgressIndicator.class.getName());
private int totalWorkUnits;
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ModalDialogProgressIndicator.java b/Core/src/org/sleuthkit/autopsy/framework/ModalDialogProgressIndicator.java
similarity index 97%
rename from Core/src/org/sleuthkit/autopsy/casemodule/ModalDialogProgressIndicator.java
rename to Core/src/org/sleuthkit/autopsy/framework/ModalDialogProgressIndicator.java
index 19ff954ddf..f967ce1592 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/ModalDialogProgressIndicator.java
+++ b/Core/src/org/sleuthkit/autopsy/framework/ModalDialogProgressIndicator.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.casemodule;
+package org.sleuthkit.autopsy.framework;
import java.awt.Dialog;
import java.awt.event.ActionListener;
@@ -24,7 +24,7 @@ import javax.swing.SwingUtilities;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.util.HelpCtx;
-import org.sleuthkit.autopsy.corecomponentinterfaces.ProgressIndicator;
+import org.sleuthkit.autopsy.framework.ProgressIndicator;
/**
* A progress indicator that displays progress using a modal dialog with a
@@ -58,7 +58,7 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
public ActionListener getListener() {
return listener;
}
-
+
@Override
public void start(String message, int totalWorkUnits) {
SwingUtilities.invokeLater(new Runnable() {
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/ProgressIndicator.java b/Core/src/org/sleuthkit/autopsy/framework/ProgressIndicator.java
similarity index 98%
rename from Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/ProgressIndicator.java
rename to Core/src/org/sleuthkit/autopsy/framework/ProgressIndicator.java
index 2550f954b4..0f51d98d75 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/ProgressIndicator.java
+++ b/Core/src/org/sleuthkit/autopsy/framework/ProgressIndicator.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.corecomponentinterfaces;
+package org.sleuthkit.autopsy.framework;
/**
* An interface for progress indicators. A progress indicator can run in
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ProgressPanel.form b/Core/src/org/sleuthkit/autopsy/framework/ProgressPanel.form
similarity index 91%
rename from Core/src/org/sleuthkit/autopsy/casemodule/ProgressPanel.form
rename to Core/src/org/sleuthkit/autopsy/framework/ProgressPanel.form
index d3377cf55e..59678117af 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/ProgressPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/framework/ProgressPanel.form
@@ -42,7 +42,7 @@
-
+
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ProgressPanel.java b/Core/src/org/sleuthkit/autopsy/framework/ProgressPanel.java
similarity index 96%
rename from Core/src/org/sleuthkit/autopsy/casemodule/ProgressPanel.java
rename to Core/src/org/sleuthkit/autopsy/framework/ProgressPanel.java
index 613c2dd9c1..6d4e46cc42 100644
--- a/Core/src/org/sleuthkit/autopsy/casemodule/ProgressPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/framework/ProgressPanel.java
@@ -16,27 +16,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.casemodule;
+package org.sleuthkit.autopsy.framework;
/**
- * RJCTODO
+ * A progress panel consisting of a message label and a progress bar.
*/
class ProgressPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
- /**
- * RJCTODO
- */
ProgressPanel() {
initComponents();
this.progressBar.setMinimum(0);
}
- /**
- * RJCTODO
- * @param message
- */
void setMessage(String message) {
this.progressMessage.setText(message);
}
diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java
index 41745ce498..40fb95c2fa 100644
--- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java
+++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java
@@ -379,7 +379,7 @@ public class IngestManager {
* Case.getTextIndexName() API.
*/
Case openedCase = Case.getCurrentCase();
- String channelPrefix = openedCase.getTextIndexName();
+ String channelPrefix = openedCase.getName();
if (Case.CaseType.MULTI_USER_CASE == openedCase.getCaseType()) {
jobEventPublisher.openRemoteEventChannel(String.format(JOB_EVENT_CHANNEL_NAME, channelPrefix));
moduleEventPublisher.openRemoteEventChannel(String.format(MODULE_EVENT_CHANNEL_NAME, channelPrefix));
diff --git a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java
index af43facec9..59c9eefef8 100644
--- a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java
+++ b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java
@@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
- * Copyright 2011-2016 Basis Technology Corp.
+ * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier sleuthkit org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,36 +19,42 @@
package org.sleuthkit.autopsy.keywordsearchservice;
import java.io.Closeable;
+import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.TskCoreException;
/**
- * An implementation of a keyword search service.
- *
+ * An interface for implementations of a keyword search service.
+ *
* TODO (AUT-2158: This interface should not extend Closeable.
*/
public interface KeywordSearchService extends Closeable {
/**
- * Takes a Blackboard artifact and adds all of its attributes to the keyword
- * search index.
+ * Tries to connect to the keyword search service server.
*
- * @param artifact
+ * @param host The hostname or IP address of the service.
+ * @param port The port used by the service.
+ *
+ * @throws KeywordSearchServiceException if cannot connect.
+ */
+ public void tryConnect(String host, int port) throws KeywordSearchServiceException;
+
+ /**
+ * Adds an artifact to the keyword search text index as a concantenation of
+ * all of its attributes.
+ *
+ * @param artifact The artifact to index.
*
* @throws org.sleuthkit.datamodel.TskCoreException
*/
public void indexArtifact(BlackboardArtifact artifact) throws TskCoreException;
/**
- * Checks if we can communicate with the KeywordSearchService using the
- * passed-in host and port. Closes the connection upon exit. Throws if it
- * cannot communicate.
+ * Deletes the keyword search text index for a case.
*
- * @param host the remote hostname or IP address of the server
- * @param port the remote port of the server
- *
- * @throws KeywordSearchServiceException
+ * @param textIndexName The text index name.
*/
- public void tryConnect(String host, int port) throws KeywordSearchServiceException;
+ public void deleteTextIndex(String textIndexName);
}
diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/SilentProgressIndicator.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/SilentProgressIndicator.java
index c47b53a618..5c57ff2914 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/SilentProgressIndicator.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/SilentProgressIndicator.java
@@ -18,7 +18,7 @@
*/
package org.sleuthkit.autopsy.modules.hashdatabase;
-import org.sleuthkit.autopsy.corecomponentinterfaces.ProgressIndicator;
+import org.sleuthkit.autopsy.framework.ProgressIndicator;
/**
* A "silent" or "null" progress indicator.
diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java
index c3aba3434f..c1cffc9243 100644
--- a/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java
+++ b/Core/src/org/sleuthkit/autopsy/report/ReportExcel.java
@@ -301,7 +301,7 @@ class ReportExcel implements TableReportModule {
row = sheet.createRow(rowIndex);
row.setRowStyle(setStyle);
row.createCell(0).setCellValue(NbBundle.getMessage(this.getClass(), "ReportExcel.cellVal.caseName"));
- row.createCell(1).setCellValue(currentCase.getName());
+ row.createCell(1).setCellValue(currentCase.getDisplayName());
++rowIndex;
row = sheet.createRow(rowIndex);
diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java
index 6f32fd2f65..afad0d5746 100644
--- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java
+++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java
@@ -93,7 +93,7 @@ class ReportGenerator {
DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss");
Date date = new Date();
String dateNoTime = dateFormat.format(date);
- this.reportPath = currentCase.getReportDirectory() + File.separator + currentCase.getName() + " " + dateNoTime + File.separator;
+ this.reportPath = currentCase.getReportDirectory() + File.separator + currentCase.getDisplayName() + " " + dateNoTime + File.separator;
this.errorList = new ArrayList<>();
diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java
index 3a7da57e3f..4b643e2a02 100644
--- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java
+++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java
@@ -857,7 +857,7 @@ class ReportHTML implements TableReportModule {
iconPath = "favicon.ico";
}
index.append("\n").append(reportTitle).append(" ").append(
- NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.title", currentCase.getName())).append(
+ NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.title", currentCase.getDisplayName())).append(
"\n"); //NON-NLS
index.append("\n"); //NON-NLS
@@ -1017,7 +1017,7 @@ class ReportHTML implements TableReportModule {
Date date = new Date();
String datetime = datetimeFormat.format(date);
- String caseName = currentCase.getName();
+ String caseName = currentCase.getDisplayName();
String caseNumber = currentCase.getNumber();
String examiner = currentCase.getExaminer();
int imagecount;
diff --git a/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDb.java b/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDb.java
index 3348fdcafd..1de1db7eaa 100755
--- a/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDb.java
+++ b/Core/src/org/sleuthkit/autopsy/report/taggedhashes/AddTaggedHashesToHashDb.java
@@ -90,7 +90,7 @@ public class AddTaggedHashesToHashDb implements GeneralReportModule {
if (content instanceof AbstractFile) {
if (null != ((AbstractFile) content).getMd5Hash()) {
try {
- hashSet.addHashes(tag.getContent(), Case.getCurrentCase().getName());
+ hashSet.addHashes(tag.getContent(), Case.getCurrentCase().getDisplayName());
} catch (TskCoreException ex) {
Logger.getLogger(AddTaggedHashesToHashDb.class.getName()).log(Level.SEVERE, "Error adding hash for obj_id = " + tag.getContent().getId() + " to hash database " + hashSet.getHashSetName(), ex);
failedExports.add(tag.getContent().getName());
diff --git a/Core/src/org/sleuthkit/autopsy/test/TestAutopsyService.java b/Core/src/org/sleuthkit/autopsy/test/TestAutopsyService.java
index d0493384e6..0cd8897ff7 100644
--- a/Core/src/org/sleuthkit/autopsy/test/TestAutopsyService.java
+++ b/Core/src/org/sleuthkit/autopsy/test/TestAutopsyService.java
@@ -20,14 +20,14 @@ package org.sleuthkit.autopsy.test;
import java.util.logging.Level;
import org.openide.util.lookup.ServiceProvider;
-import org.sleuthkit.autopsy.corecomponentinterfaces.AutopsyService;
-import org.sleuthkit.autopsy.corecomponentinterfaces.ProgressIndicator;
import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.framework.AutopsyService;
+import org.sleuthkit.autopsy.framework.ProgressIndicator;
/**
* An implementation of the Autopsy service interface used for test purposes.
*/
-@ServiceProvider(service = AutopsyService.class)
+//@ServiceProvider(service = AutopsyService.class)
public class TestAutopsyService implements AutopsyService {
private static final Logger LOGGER = Logger.getLogger(TestAutopsyService.class.getName());
diff --git a/Core/src/org/sleuthkit/autopsy/timeline/actions/SaveSnapshotAsReport.java b/Core/src/org/sleuthkit/autopsy/timeline/actions/SaveSnapshotAsReport.java
index 7f0bf14f3a..04117963c7 100644
--- a/Core/src/org/sleuthkit/autopsy/timeline/actions/SaveSnapshotAsReport.java
+++ b/Core/src/org/sleuthkit/autopsy/timeline/actions/SaveSnapshotAsReport.java
@@ -100,7 +100,7 @@ public class SaveSnapshotAsReport extends Action {
setEventHandler(actionEvent -> {
//capture generation date and use to make default report name
Date generationDate = new Date();
- final String defaultReportName = FileUtil.escapeFileName(currentCase.getName() + " " + new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss").format(generationDate)); //NON_NLS
+ final String defaultReportName = FileUtil.escapeFileName(currentCase.getDisplayName() + " " + new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss").format(generationDate)); //NON_NLS
BufferedImage snapshot = SwingFXUtils.fromFXImage(nodeSupplier.get().snapshot(null, null), null);
//prompt user to pick report name
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCase.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCase.java
index 646191de39..6d37ca2a26 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCase.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCase.java
@@ -46,7 +46,6 @@ class AutoIngestCase implements Comparable {
*
* @param caseDirectoryPath The case directory path.
*/
- // RJCTODO: Throw instead of reporting error, let client decide what to do.
AutoIngestCase(Path caseDirectoryPath) {
this.caseDirectoryPath = caseDirectoryPath;
caseName = PathUtils.caseNameFromCaseDirectoryPath(caseDirectoryPath);
@@ -100,7 +99,6 @@ class AutoIngestCase implements Comparable {
*
* @return The last accessed date.
*/
- // RJCTODO: Throw instead of reporting error, let client decide what to do.
Date getLastAccessedDate() {
try {
BasicFileAttributes fileAttrs = Files.readAttributes(metadataFilePath, BasicFileAttributes.class);
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseDeletedEvent.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseDeletedEvent.java
index ab559de58e..3d3ff8951f 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseDeletedEvent.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseDeletedEvent.java
@@ -45,20 +45,10 @@ final class AutoIngestCaseDeletedEvent extends AutopsyEvent implements Serializa
this.nodeName = nodeName;
}
- /**
- * RJCTODO
- *
- * @return
- */
String getCaseName() {
return caseName;
}
- /**
- * RJCTODO
- *
- * @return
- */
String getNodeName() {
return nodeName;
}
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseManager.java
index e187cec054..1b95cd87be 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseManager.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCaseManager.java
@@ -72,7 +72,6 @@ final class AutoIngestCaseManager {
* this machine, but review mode is only for looking at cases created by
* automated ingest.
*/
- // RJCTODO: Write a story about this.
FileObject root = FileUtil.getConfigRoot();
FileObject openRecentCasesMenu = root.getFileObject("Menu/Case/OpenRecentCase");
if (openRecentCasesMenu != null) {
@@ -108,7 +107,7 @@ final class AutoIngestCaseManager {
/*
* Open the case.
*/
- Case.openCurrentCase(caseMetadataFilePath.toString());
+ Case.openAsCurrentCase(caseMetadataFilePath.toString());
/**
* Disable the add data source action in auto ingest examiner mode. This
@@ -117,7 +116,6 @@ final class AutoIngestCaseManager {
* enables the menus on EDT by calling SwingUtilities.invokeLater(), we
* have to do the same thing here to maintain the order of execution.
*/
- // RJCTODO: Write a story about this.
SwingUtilities.invokeLater(() -> {
CallableSystemAction.get(AddImageAction.class).setEnabled(false);
});
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePrioritizedEvent.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePrioritizedEvent.java
index 0687bc9c2e..5fbf380601 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePrioritizedEvent.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestCasePrioritizedEvent.java
@@ -25,7 +25,7 @@ import org.sleuthkit.autopsy.events.AutopsyEvent;
* Event published when an automated ingest manager prioritizes all or part of a
* case.
*/
-public final class AutoIngestCasePrioritizedEvent extends AutopsyEvent implements Serializable { // RJCTODO: Rename to AutoIngestPrioritizationEvent
+public final class AutoIngestCasePrioritizedEvent extends AutopsyEvent implements Serializable {
private static final long serialVersionUID = 1L;
private final String caseName;
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java
index ada7f61206..8372205fc6 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java
@@ -24,6 +24,7 @@ import java.nio.file.Paths;
import java.time.Instant;
import java.util.Comparator;
import java.util.Date;
+import java.util.Objects;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.Immutable;
import javax.annotation.concurrent.ThreadSafe;
@@ -55,9 +56,9 @@ public final class AutoIngestJob implements Comparable, Serializa
@GuardedBy("this")
transient private IngestJob ingestJob;
@GuardedBy("this")
- transient private boolean cancelled; // RJCTODO: Document
+ transient private boolean cancelled;
@GuardedBy("this")
- transient private boolean completed; // RJCTODO: Document
+ transient private boolean completed;
@GuardedBy("this")
private Date completedDate;
@GuardedBy("this")
@@ -81,7 +82,6 @@ public final class AutoIngestJob implements Comparable, Serializa
* indicate the the job is not completed, i.e., new
* Date(0L).
*/
- // RJCTODO: The null case directory is error-prone and the nodeName is confusing.
AutoIngestJob(Manifest manifest, Path caseDirectoryPath, int priority, String nodeName, Stage stage, Date completedDate, boolean errorsOccurred) {
this.manifest = manifest;
if (null != caseDirectoryPath) {
@@ -112,7 +112,6 @@ public final class AutoIngestJob implements Comparable, Serializa
*
* @return True or false
*/
- // RJCTODO: Use this or lose this
synchronized boolean hasCaseDirectoryPath() {
return (false == this.caseDirectoryPath.isEmpty());
}
@@ -161,21 +160,10 @@ public final class AutoIngestJob implements Comparable, Serializa
return this.priority;
}
- /**
- * RJCTODO
- *
- * @param newStage
- */
synchronized void setStage(Stage newStage) {
setStage(newStage, Date.from(Instant.now()));
}
- /**
- * RJCTODO
- *
- * @param state
- * @param stateStartedDate
- */
synchronized void setStage(Stage newState, Date stateStartedDate) {
if (Stage.CANCELLING == this.stage && Stage.COMPLETED != newState) {
return;
@@ -184,29 +172,14 @@ public final class AutoIngestJob implements Comparable, Serializa
this.stageStartDate = stateStartedDate;
}
- /**
- * RJCTODO:
- *
- * @return
- */
synchronized Stage getStage() {
return this.stage;
}
- /**
- * RJCTODO
- *
- * @return
- */
synchronized Date getStageStartDate() {
return this.stageStartDate;
}
- /**
- * RJCTODO
- *
- * @return
- */
synchronized StageDetails getStageDetails() {
String description;
Date startDate;
@@ -223,7 +196,7 @@ public final class AutoIngestJob implements Comparable, Serializa
if (!ingestModuleHandle.isCancelled()) {
description = ingestModuleHandle.displayName();
} else {
- description = String.format(Stage.CANCELLING_MODULE.getDisplayText(), ingestModuleHandle.displayName()); // RJCTODO: FIx this
+ description = String.format(Stage.CANCELLING_MODULE.getDisplayText(), ingestModuleHandle.displayName());
}
} else {
/**
@@ -248,26 +221,14 @@ public final class AutoIngestJob implements Comparable, Serializa
this.dataSourceProcessor = dataSourceProcessor;
}
- /**
- * RJCTODO
- */
- // RJCTODO: Consider moving this class into AIM and making this private
synchronized void setIngestJob(IngestJob ingestJob) {
this.ingestJob = ingestJob;
}
- /**
- * RJCTODO
- */
- // RJCTODO: Consider moving this class into AIM and making this private.
- // Or move the AID into a separate package. Or do not worry about it.
synchronized IngestJob getIngestJob() {
return this.ingestJob;
}
- /**
- * RJCTODO
- */
synchronized void cancel() {
setStage(Stage.CANCELLING);
cancelled = true;
@@ -280,26 +241,15 @@ public final class AutoIngestJob implements Comparable, Serializa
}
}
- /**
- * RJCTODO
- */
synchronized boolean isCancelled() {
return cancelled;
}
- /**
- * RJCTODO
- */
synchronized void setCompleted() {
setStage(Stage.COMPLETED);
completed = true;
}
- /**
- * RJCTODO
- *
- * @return
- */
synchronized boolean isCompleted() {
return completed;
}
@@ -321,7 +271,7 @@ public final class AutoIngestJob implements Comparable, Serializa
* @return True or false.
*/
synchronized Date getCompletedDate() {
- return completedDate; // RJCTODO: Consider returning null if == 0 (epoch)
+ return completedDate;
}
/**
@@ -342,23 +292,10 @@ public final class AutoIngestJob implements Comparable, Serializa
return this.errorsOccurred;
}
- /**
- * RJCTODO Gets name of the node associated with the job, possibly a remote
- * hose if the job is in progress.
- *
- * @return The node name.
- */
String getNodeName() {
return nodeName;
}
- /**
- * RJCTODO
- *
- * @param obj
- *
- * @return
- */
@Override
public boolean equals(Object obj) {
if (!(obj instanceof AutoIngestJob)) {
@@ -370,26 +307,12 @@ public final class AutoIngestJob implements Comparable, Serializa
return this.getManifest().getFilePath().equals(((AutoIngestJob) obj).getManifest().getFilePath());
}
- /**
- * RJCTODO
- *
- * @return
- */
@Override
public int hashCode() {
- // RJCTODO: Update this
- int hash = 7;
-// hash = 71 * hash + Objects.hashCode(this.dateCreated);
+ int hash = 71 * (Objects.hashCode(this.caseDirectoryPath));
return hash;
}
- /**
- * RJCTODO Default sorting is by ready file creation date, descending
- *
- * @param o
- *
- * @return
- */
@Override
public int compareTo(AutoIngestJob o) {
return -this.getManifest().getDateFileCreated().compareTo(o.getManifest().getDateFileCreated());
@@ -401,14 +324,6 @@ public final class AutoIngestJob implements Comparable, Serializa
*/
static class ReverseDateCompletedComparator implements Comparator {
- /**
- * RJCTODO
- *
- * @param o1
- * @param o2
- *
- * @return
- */
@Override
public int compare(AutoIngestJob o1, AutoIngestJob o2) {
return -o1.getStageStartDate().compareTo(o2.getStageStartDate());
@@ -420,14 +335,6 @@ public final class AutoIngestJob implements Comparable, Serializa
*/
public static class PriorityComparator implements Comparator {
- /**
- * RJCTODO
- *
- * @param job
- * @param anotherJob
- *
- * @return
- */
@Override
public int compare(AutoIngestJob job, AutoIngestJob anotherJob) {
return -(job.getPriority().compareTo(anotherJob.getPriority()));
@@ -442,14 +349,6 @@ public final class AutoIngestJob implements Comparable, Serializa
*/
static class AlphabeticalComparator implements Comparator {
- /**
- * RJCTODO
- *
- * @param o1
- * @param o2
- *
- * @return
- */
@Override
public int compare(AutoIngestJob o1, AutoIngestJob o2) {
if (o1.getNodeName().equalsIgnoreCase(LOCAL_HOST_NAME)) {
@@ -462,10 +361,6 @@ public final class AutoIngestJob implements Comparable, Serializa
}
}
- /**
- * RJCTODO
- */
- // RJCTODO: Combine this enum with StageDetails to make a single class.
enum Stage {
PENDING("Pending"),
@@ -494,40 +389,21 @@ public final class AutoIngestJob implements Comparable, Serializa
}
- /**
- * RJCTODO
- */
@Immutable
static final class StageDetails {
private final String description;
private final Date startDate;
- /**
- * RJCTODO
- *
- * @param description
- * @param startDate
- */
private StageDetails(String description, Date startDate) {
this.description = description;
this.startDate = startDate;
}
- /**
- * RJCTODO
- *
- * @return
- */
String getDescription() {
return this.description;
}
- /**
- * RJCTODO
- *
- * @return
- */
Date getStartDate() {
return this.startDate;
}
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobEvent.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobEvent.java
index e1c9464d00..55248e0a9c 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobEvent.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobEvent.java
@@ -22,28 +22,17 @@ import java.io.Serializable;
import javax.annotation.concurrent.Immutable;
import org.sleuthkit.autopsy.events.AutopsyEvent;
-/**
- * RJCTODO
- */
@Immutable
abstract class AutoIngestJobEvent extends AutopsyEvent implements Serializable {
private static final long serialVersionUID = 1L;
private final AutoIngestJob job;
- /**
- * RJCTODO
- *
- */
AutoIngestJobEvent(AutoIngestManager.Event eventSubType, AutoIngestJob job) {
super(eventSubType.toString(), null, null);
this.job = job;
}
- /**
- * RJCTODO
- * @return
- */
AutoIngestJob getJob() {
return this.job;
}
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobLogger.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobLogger.java
index e9406950fd..161a20286e 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobLogger.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobLogger.java
@@ -192,7 +192,7 @@ final class AutoIngestJobLogger {
* to acquire an exclusive lock on the
* log file.
*/
- void logDataSourceProcessorCancelled() throws AutoIngestJobLoggerException, InterruptedException { // RJCTODO: Is this used now?
+ void logDataSourceProcessorCancelled() throws AutoIngestJobLoggerException, InterruptedException {
log(MessageCategory.WARNING, "Cancelled adding data source to case");
}
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobStartedEvent.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobStartedEvent.java
index de2ef46ffd..b80157b3b4 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobStartedEvent.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobStartedEvent.java
@@ -28,9 +28,6 @@ public final class AutoIngestJobStartedEvent extends AutoIngestJobEvent implemen
private static final long serialVersionUID = 1L;
- /**
- * RJCTODO
- */
public AutoIngestJobStartedEvent(AutoIngestJob job) {
super(AutoIngestManager.Event.JOB_STARTED, job);
}
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobStatusEvent.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobStatusEvent.java
index 23a444f7d7..153cc04ced 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobStatusEvent.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobStatusEvent.java
@@ -28,9 +28,6 @@ public final class AutoIngestJobStatusEvent extends AutoIngestJobEvent implement
private static final long serialVersionUID = 1L;
- /**
- * RJCTODO
- */
public AutoIngestJobStatusEvent(AutoIngestJob job) {
super(AutoIngestManager.Event.JOB_STATUS_UPDATED, job);
}
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java
index a08ef06090..eb45ae0df4 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java
@@ -18,11 +18,9 @@
*/
package org.sleuthkit.autopsy.experimental.autoingest;
-import org.sleuthkit.autopsy.coordinationservice.CoordinationServiceNamespace;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
-import org.sleuthkit.autopsy.experimental.configuration.AutoIngestUserPreferences;
import java.io.File;
import java.io.IOException;
import static java.nio.file.FileVisitOption.FOLLOW_LINKS;
@@ -38,9 +36,6 @@ import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
-import org.sleuthkit.autopsy.modules.vmextractor.VirtualMachineFinder;
-import org.sleuthkit.autopsy.core.UserPreferences;
-import org.sleuthkit.datamodel.CaseDbConnectionInfo;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
@@ -54,13 +49,13 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
import java.util.Observable;
import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -69,65 +64,50 @@ import java.util.stream.Collectors;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.Immutable;
import javax.annotation.concurrent.ThreadSafe;
-import javax.swing.filechooser.FileFilter;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
-import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathFactory;
-import org.apache.commons.io.FilenameUtils;
+import org.apache.solr.client.solrj.impl.HttpSolrServer;
+import org.openide.util.Lookup;
import org.sleuthkit.autopsy.casemodule.Case;
-import org.sleuthkit.autopsy.casemodule.CaseActionException;
-import org.sleuthkit.autopsy.ingest.IngestManager;
-import org.openide.modules.InstalledFileLocator;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
-import org.sleuthkit.autopsy.casemodule.GeneralFilter;
-import org.sleuthkit.autopsy.casemodule.ImageDSProcessor;
-import org.sleuthkit.autopsy.core.RuntimeProperties;
-import org.sleuthkit.autopsy.core.ServicesMonitor;
-import org.sleuthkit.autopsy.core.UserPreferencesException;
-import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
-import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
-import org.sleuthkit.autopsy.coreutils.ExecUtil;
-import org.sleuthkit.autopsy.coreutils.NetworkUtils;
-import org.sleuthkit.autopsy.coreutils.PlatformUtil;
-import org.sleuthkit.autopsy.events.AutopsyEvent;
-import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
-import org.sleuthkit.autopsy.ingest.IngestJob;
-import org.sleuthkit.autopsy.ingest.IngestJobSettings;
-import org.sleuthkit.datamodel.Content;
+import org.sleuthkit.autopsy.casemodule.CaseActionException;
+import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock;
-import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration;
-import org.apache.solr.client.solrj.impl.HttpSolrServer;
-import org.openide.util.Lookup;
-import org.sleuthkit.autopsy.casemodule.CaseMetadata;
-import org.sleuthkit.autopsy.casemodule.LocalFilesDSProcessor;
+import org.sleuthkit.autopsy.coordinationservice.CoordinationServiceNamespace;
+import org.sleuthkit.autopsy.core.RuntimeProperties;
+import org.sleuthkit.autopsy.core.ServicesMonitor;
import org.sleuthkit.autopsy.core.ServicesMonitor.ServicesMonitorException;
+import org.sleuthkit.autopsy.core.UserPreferences;
+import org.sleuthkit.autopsy.core.UserPreferencesException;
+import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
+import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
+import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult;
-import org.sleuthkit.autopsy.coreutils.FileUtil;
+import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
+import org.sleuthkit.autopsy.coreutils.NetworkUtils;
+import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.autopsy.events.AutopsyEventException;
-import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason;
-import org.sleuthkit.autopsy.ingest.IngestJobStartResult;
-import org.sleuthkit.autopsy.ingest.IngestModuleError;
+import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
+import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestAlertFile.AutoIngestAlertFileException;
+import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobLogger.AutoIngestJobLoggerException;
import org.sleuthkit.autopsy.experimental.autoingest.FileExporter.FileExportException;
import org.sleuthkit.autopsy.experimental.autoingest.ManifestFileParser.ManifestFileParserException;
import org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus;
-import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.PENDING;
-import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.PROCESSING;
import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.COMPLETED;
import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.DELETED;
-import org.sleuthkit.autopsy.corecomponentinterfaces.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
-import org.sleuthkit.autopsy.coreutils.FileUtil;
-import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestAlertFile.AutoIngestAlertFileException;
-import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJobLogger.AutoIngestJobLoggerException;
+import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.PENDING;
+import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.ProcessingStatus.PROCESSING;
+import org.sleuthkit.autopsy.experimental.configuration.AutoIngestUserPreferences;
+import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration;
import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration.SharedConfigurationException;
+import org.sleuthkit.autopsy.ingest.IngestJob;
import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason;
-import org.sleuthkit.autopsy.corecomponentinterfaces.AutoIngestDataSourceProcessor;
+import org.sleuthkit.autopsy.ingest.IngestJobSettings;
+import org.sleuthkit.autopsy.ingest.IngestJobStartResult;
+import org.sleuthkit.autopsy.ingest.IngestManager;
+import org.sleuthkit.autopsy.ingest.IngestModuleError;
+import org.sleuthkit.datamodel.CaseDbConnectionInfo;
+import org.sleuthkit.datamodel.Content;
/**
* An auto ingest manager is responsible for processing auto ingest jobs defined
@@ -240,7 +220,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
eventPublisher.openRemoteEventChannel(EVENT_CHANNEL_NAME);
SYS_LOGGER.log(Level.INFO, "Opened auto ingest event channel");
} catch (AutopsyEventException ex) {
- throw new AutoIngestManagerStartupException("Failed to open aut ingest event channel", ex);
+ SYS_LOGGER.log(Level.SEVERE, "Failed to open auto ingest event channel", ex);
+ throw new AutoIngestManagerStartupException("Failed to open auto ingest event channel", ex);
}
rootInputDirectory = Paths.get(AutoIngestUserPreferences.getAutoModeImageFolder());
rootOutputDirectory = Paths.get(AutoIngestUserPreferences.getAutoModeResultsFolder());
@@ -249,7 +230,13 @@ public final class AutoIngestManager extends Observable implements PropertyChang
jobProcessingTaskFuture = jobProcessingExecutor.submit(jobProcessingTask);
jobStatusPublishingExecutor.scheduleAtFixedRate(new PeriodicJobStatusEventTask(), JOB_STATUS_EVENT_INTERVAL_SECONDS, JOB_STATUS_EVENT_INTERVAL_SECONDS, TimeUnit.SECONDS);
eventPublisher.addSubscriber(EVENT_LIST, instance);
- RuntimeProperties.setRunningWithGUI(false);
+ try {
+ RuntimeProperties.setRunningWithGUI(false);
+ SYS_LOGGER.log(Level.INFO, "Set running with desktop GUI runtime property to false");
+ } catch (RuntimeProperties.RuntimePropertiesException ex) {
+ SYS_LOGGER.log(Level.SEVERE, "Failed to set running with desktop GUI runtime property to false", ex);
+ throw new AutoIngestManagerStartupException("Failed to set running with desktop GUI runtime property to false", ex);
+ }
state = State.RUNNING;
errorState = ErrorState.NONE;
}
@@ -483,7 +470,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
}
for (AutoIngestJob job : hostNamesToRunningJobs.values()) {
runningJobs.add(job);
- runningJobs.sort(new AutoIngestJob.AlphabeticalComparator()); // RJCTODO: This sort should be done in the AID
+ runningJobs.sort(new AutoIngestJob.AlphabeticalComparator());
}
}
if (null != completedJobs) {
@@ -502,12 +489,12 @@ public final class AutoIngestManager extends Observable implements PropertyChang
}
inputScanExecutor.submit(new InputDirScanTask());
}
-
+
/**
* Start a scan of the input directories and wait for scan to complete.
*/
- void scanInputDirsAndWait(){
- if (State.RUNNING != state) {
+ void scanInputDirsAndWait() {
+ if (State.RUNNING != state) {
return;
}
SYS_LOGGER.log(Level.INFO, "Starting input scan of {0}", rootInputDirectory);
@@ -684,18 +671,22 @@ public final class AutoIngestManager extends Observable implements PropertyChang
return CaseDeletionResult.FAILED;
}
- /*
- * Acquire an exclusive lock on the case so it can be safely deleted.
- * This will fail if the case is open for review or a deletion operation
- * on this case is already in progress on another node.
- */
CaseDeletionResult result = CaseDeletionResult.FULLY_DELETED;
List manifestFileLocks = new ArrayList<>();
- try (Lock caseLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, caseDirectoryPath.toString())) {
- if (null == caseLock) {
- return CaseDeletionResult.FAILED;
- }
+ try {
synchronized (jobsLock) {
+ /*
+ * Get the case metadata.
+ */
+ CaseMetadata metaData;
+ Path caseMetaDataFilePath = Paths.get(caseDirectoryPath.toString(), caseName + CaseMetadata.getFileExtension());
+ try {
+ metaData = new CaseMetadata(caseMetaDataFilePath);
+ } catch (CaseMetadata.CaseMetadataException ex) {
+ SYS_LOGGER.log(Level.SEVERE, String.format("Failed to get case metadata file %s for case %s at %s", caseMetaDataFilePath, caseName, caseDirectoryPath), ex);
+ return CaseDeletionResult.FAILED;
+ }
+
/*
* Do a fresh input directory scan.
*/
@@ -703,12 +694,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang
scanner.scan();
Set manifestPaths = casesToManifests.get(caseName);
if (null == manifestPaths) {
- SYS_LOGGER.log(Level.SEVERE, "No manifest paths found for case {0}", caseName);
+ SYS_LOGGER.log(Level.SEVERE, String.format("No manifest paths found for case %s at %s", caseName, caseDirectoryPath));
return CaseDeletionResult.FAILED;
}
/*
- * Get all of the required manifest locks.
+ * Get exclusive locks on all of the manifests for the case.
+ * This will exclude other auot ingest nodes from doing anything
+ * with the case.
*/
for (Path manifestPath : manifestPaths) {
try {
@@ -719,20 +712,18 @@ public final class AutoIngestManager extends Observable implements PropertyChang
return CaseDeletionResult.FAILED;
}
} catch (CoordinationServiceException ex) {
- SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to acquire manifest lock for %s for case %s", manifestPath, caseName), ex);
+ SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to acquire manifest lock for %s for case %s at %s", manifestPath, caseName, caseDirectoryPath), ex);
return CaseDeletionResult.FAILED;
}
}
- /*
- * Get the case metadata.
- */
- CaseMetadata metaData;
- Path caseMetaDataFilePath = Paths.get(caseDirectoryPath.toString(), caseName + CaseMetadata.getFileExtension());
try {
- metaData = new CaseMetadata(caseMetaDataFilePath);
- } catch (CaseMetadata.CaseMetadataException ex) {
- SYS_LOGGER.log(Level.SEVERE, String.format("Failed to delete case metadata file %s for case %s", caseMetaDataFilePath, caseName));
+ /*
+ * Physically delete the case.
+ */
+ Case.deleteCase(metaData);
+ } catch (CaseActionException ex) {
+ SYS_LOGGER.log(Level.SEVERE, String.format("Failed to physically delete case %s at %s", caseName, caseDirectoryPath), ex);
return CaseDeletionResult.FAILED;
}
@@ -745,56 +736,11 @@ public final class AutoIngestManager extends Observable implements PropertyChang
nodeData.setStatus(ManifestNodeData.ProcessingStatus.DELETED);
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString(), nodeData.toArray());
} catch (InterruptedException | CoordinationServiceException ex) {
- SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set delete flag on manifest data for %s for case %s", manifestPath, caseName), ex);
+ SYS_LOGGER.log(Level.SEVERE, String.format("Error attempting to set delete flag on manifest data for %s for case %s at %s", manifestPath, caseName, caseDirectoryPath), ex);
return CaseDeletionResult.PARTIALLY_DELETED;
}
}
- /*
- * Try to unload/delete the Solr core from the Solr server. Do
- * this before deleting the case directory because the index
- * files are in the case directory and the deletion will fail if
- * the core is not unloaded first.
- */
- String textIndexName = metaData.getTextIndexName();
- try {
- unloadSolrCore(metaData.getTextIndexName());
- } catch (Exception ex) {
- /*
- * Could be a problem, or it could be that the core was
- * already unloaded (e.g., by the server due to resource
- * constraints).
- */
- SYS_LOGGER.log(Level.WARNING, String.format("Error deleting text index %s for %s", textIndexName, caseName), ex); //NON-NLS
- }
-
- /*
- * Delete the case database from the database server.
- */
- String caseDatabaseName = metaData.getCaseDatabaseName();
- try {
- deleteCaseDatabase(caseDatabaseName);
- } catch (SQLException ex) {
- SYS_LOGGER.log(Level.SEVERE, String.format("Unable to delete case database %s for %s", caseDatabaseName, caseName), ex); //NON-NLS
- result = CaseDeletionResult.PARTIALLY_DELETED;
- } catch (UserPreferencesException ex) {
- SYS_LOGGER.log(Level.SEVERE, String.format("Error accessing case database connection info, unable to delete case database %s for %s", caseDatabaseName, caseName), ex); //NON-NLS
- result = CaseDeletionResult.PARTIALLY_DELETED;
- } catch (ClassNotFoundException ex) {
- SYS_LOGGER.log(Level.SEVERE, String.format("Cannot load database driver, unable to delete case database %s for %s", caseDatabaseName, caseName), ex); //NON-NLS
- result = CaseDeletionResult.PARTIALLY_DELETED;
- }
-
- /*
- * Delete the case directory.
- */
- File caseDirectory = caseDirectoryPath.toFile();
- FileUtil.deleteDir(caseDirectory);
- if (caseDirectory.exists()) {
- SYS_LOGGER.log(Level.SEVERE, String.format("Failed to delete case directory %s for case %s", caseDirectoryPath, caseName));
- return CaseDeletionResult.PARTIALLY_DELETED;
- }
-
/*
* Remove the jobs for the case from the pending jobs queue and
* completed jobs list.
@@ -809,27 +755,27 @@ public final class AutoIngestManager extends Observable implements PropertyChang
notifyObservers(Event.CASE_DELETED);
return result;
- } catch (CoordinationServiceException ex) {
- SYS_LOGGER.log(Level.SEVERE, String.format("Error acquiring coordination service lock on case %s", caseName), ex);
- return CaseDeletionResult.FAILED;
-
} finally {
+ /*
+ * Always release the manifest locks, regardless of the outcome.
+ */
for (Lock lock : manifestFileLocks) {
try {
lock.release();
} catch (CoordinationServiceException ex) {
- SYS_LOGGER.log(Level.SEVERE, String.format("Failed to release manifest file lock when deleting case %s", caseName), ex);
+ SYS_LOGGER.log(Level.SEVERE, String.format("Failed to release manifest file lock when deleting case %s at %s", caseName, caseDirectoryPath), ex);
}
}
}
}
-
+
/**
* Get the current snapshot of the job lists.
+ *
* @return Snapshot of jobs lists
*/
- JobsSnapshot getCurrentJobsSnapshot(){
- synchronized(jobsLock){
+ JobsSnapshot getCurrentJobsSnapshot() {
+ synchronized (jobsLock) {
List runningJobs = new ArrayList<>();
getJobs(null, runningJobs, null);
return new JobsSnapshot(pendingJobs, runningJobs, completedJobs);
@@ -895,9 +841,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* Starts the process of cancelling the current job.
*
* Note that the current job is included in the running list for a while
- * because it can take some time
- * for the automated ingest process for the job to be shut down in
- * an orderly fashion.
+ * because it can take some time for the automated ingest process for the
+ * job to be shut down in an orderly fashion.
*/
void cancelCurrentJob() {
if (State.RUNNING != state) {
@@ -1655,8 +1600,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @throws CoordinationServiceException if there is an error while
* acquiring or releasing a
* manifest file lock.
- * @throws InterruptedException if the thread is interrupted while
- * reading the lock data
+ * @throws InterruptedException if the thread is interrupted
+ * while reading the lock data
*/
private Lock dequeueAndLockNextJob() throws CoordinationServiceException, InterruptedException {
SYS_LOGGER.log(Level.INFO, "Checking pending jobs queue for ready job, enforcing max jobs per case");
@@ -1694,8 +1639,8 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @throws CoordinationServiceException if there is an error while
* acquiring or releasing a
* manifest file lock.
- * @throws InterruptedException if the thread is interrupted while
- * reading the lock data
+ * @throws InterruptedException if the thread is interrupted
+ * while reading the lock data
*/
private Lock dequeueAndLockNextJob(boolean enforceMaxJobsPerCase) throws CoordinationServiceException, InterruptedException {
Lock manifestLock = null;
@@ -1714,18 +1659,18 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*/
continue;
}
-
+
ManifestNodeData nodeData = new ManifestNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath.toString()));
- if(! nodeData.getStatus().equals(PENDING)){
+ if (!nodeData.getStatus().equals(PENDING)) {
/*
- * Due to a timing issue or a missed event,
- * a non-pending job has ended up on the pending queue.
- * Skip the job and remove it from the queue.
+ * Due to a timing issue or a missed event, a
+ * non-pending job has ended up on the pending queue.
+ * Skip the job and remove it from the queue.
*/
iterator.remove();
continue;
}
-
+
if (enforceMaxJobsPerCase) {
int currentJobsForCase = 0;
for (AutoIngestJob runningJob : hostNamesToRunningJobs.values()) {
@@ -1806,9 +1751,9 @@ public final class AutoIngestManager extends Observable implements PropertyChang
if (jobProcessingTaskFuture.isCancelled()) {
currentJob.cancel();
}
-
+
nodeData = new ManifestNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath));
- if(currentJob.isCompleted() || currentJob.isCancelled()){
+ if (currentJob.isCompleted() || currentJob.isCancelled()) {
nodeData.setStatus(COMPLETED);
Date completedDate = new Date();
currentJob.setCompletedDate(completedDate);
@@ -1820,7 +1765,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
}
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestPath, nodeData.toArray());
-
boolean retry = (!currentJob.isCancelled() && !currentJob.isCompleted());
SYS_LOGGER.log(Level.INFO, "Completed processing of {0}, retry = {1}", new Object[]{manifestPath, retry});
if (currentJob.isCancelled()) {
@@ -1983,41 +1927,33 @@ public final class AutoIngestManager extends Observable implements PropertyChang
String caseName = manifest.getCaseName();
SYS_LOGGER.log(Level.INFO, "Opening case {0} for {1}", new Object[]{caseName, manifest.getFilePath()});
currentJob.setStage(AutoIngestJob.Stage.OPENING_CASE);
- try (Lock caseLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.CASES, caseName, 12, TimeUnit.HOURS)) { // RJCTODO: New lock type!
- if (null != caseLock) {
- try {
- Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, caseName);
- if (null != caseDirectoryPath) {
- Path metadataFilePath = caseDirectoryPath.resolve(manifest.getCaseName() + CaseMetadata.getFileExtension());
- Case.openCurrentCase(metadataFilePath.toString());
- } else {
- caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName);
- Case.createCurrentCase(caseDirectoryPath.toString(), currentJob.getManifest().getCaseName(), "", "", CaseType.MULTI_USER_CASE);
- /*
- * Sleep a bit before releasing the lock to ensure
- * that the new case folder is visible on the
- * network.
- */
- Thread.sleep(AutoIngestUserPreferences.getSecondsToSleepBetweenCases() * 1000);
- }
- currentJob.setCaseDirectoryPath(caseDirectoryPath);
- Case caseForJob = Case.getCurrentCase();
- SYS_LOGGER.log(Level.INFO, "Opened case {0} for {1}", new Object[]{caseForJob.getName(), manifest.getFilePath()});
- return caseForJob;
-
- } catch (CaseActionException ex) {
- throw new CaseManagementException(String.format("Error creating or opening case %s for %s", manifest.getCaseName(), manifest.getFilePath()), ex);
- } catch (IllegalStateException ex) {
- /*
- * Deal with the unfortunate fact that
- * Case.getCurrentCase throws IllegalStateException.
- */
- throw new CaseManagementException(String.format("Error getting current case %s for %s", manifest.getCaseName(), manifest.getFilePath()), ex);
- }
-
+ try {
+ Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, caseName);
+ if (null != caseDirectoryPath) {
+ Path metadataFilePath = caseDirectoryPath.resolve(manifest.getCaseName() + CaseMetadata.getFileExtension());
+ Case.openAsCurrentCase(metadataFilePath.toString());
} else {
- throw new CaseManagementException(String.format("Timed out acquiring case name lock for %s for %s", manifest.getCaseName(), manifest.getFilePath()));
+ caseDirectoryPath = PathUtils.createCaseFolderPath(rootOutputDirectory, caseName);
+ Case.createAsCurrentCase(caseDirectoryPath.toString(), currentJob.getManifest().getCaseName(), "", "", CaseType.MULTI_USER_CASE);
+ /*
+ * Sleep a bit before releasing the lock to ensure that the
+ * new case folder is visible on the network.
+ */
+ Thread.sleep(AutoIngestUserPreferences.getSecondsToSleepBetweenCases() * 1000);
}
+ currentJob.setCaseDirectoryPath(caseDirectoryPath);
+ Case caseForJob = Case.getCurrentCase();
+ SYS_LOGGER.log(Level.INFO, "Opened case {0} for {1}", new Object[]{caseForJob.getName(), manifest.getFilePath()});
+ return caseForJob;
+
+ } catch (CaseActionException ex) {
+ throw new CaseManagementException(String.format("Error creating or opening case %s for %s", manifest.getCaseName(), manifest.getFilePath()), ex);
+ } catch (IllegalStateException ex) {
+ /*
+ * Deal with the unfortunate fact that Case.getCurrentCase
+ * throws IllegalStateException.
+ */
+ throw new CaseManagementException(String.format("Error getting current case %s for %s", manifest.getCaseName(), manifest.getFilePath()), ex);
}
}
@@ -2118,7 +2054,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* Sleep to allow ingest event subscribers to do their event
* handling.
*/
- Thread.sleep(AutoIngestUserPreferences.getSecondsToSleepBetweenCases() * 1000); // RJCTODO: Change the setting description to be more generic
+ Thread.sleep(AutoIngestUserPreferences.getSecondsToSleepBetweenCases() * 1000);
}
if (currentJob.isCancelled() || jobProcessingTaskFuture.isCancelled()) {
@@ -2200,7 +2136,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
for (AutoIngestDataSourceProcessor processor : processorCandidates) {
try {
int confidence = processor.canProcess(dataSource.getPath());
- if(confidence > 0){
+ if (confidence > 0) {
validDataSourceProcessorsMap.put(processor, confidence);
}
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
@@ -2219,16 +2155,16 @@ public final class AutoIngestManager extends Observable implements PropertyChang
SYS_LOGGER.log(Level.WARNING, "Unsupported data source {0} for {1}", new Object[]{dataSource.getPath(), manifestPath}); // NON-NLS
return;
}
-
+
// Get an ordered list of data source processors to try
List validDataSourceProcessors = validDataSourceProcessorsMap.entrySet().stream()
- .sorted(Map.Entry.comparingByValue().reversed())
- .map(Map.Entry::getKey)
- .collect(Collectors.toList());
+ .sorted(Map.Entry.comparingByValue().reversed())
+ .map(Map.Entry::getKey)
+ .collect(Collectors.toList());
synchronized (ingestLock) {
// Try each DSP in decreasing order of confidence
- for(AutoIngestDataSourceProcessor selectedProcessor:validDataSourceProcessors){
+ for (AutoIngestDataSourceProcessor selectedProcessor : validDataSourceProcessors) {
jobLogger.logDataSourceProcessorSelected(selectedProcessor.getDataSourceType());
SYS_LOGGER.log(Level.INFO, "Identified data source type for {0} as {1}", new Object[]{manifestPath, selectedProcessor.getDataSourceType()});
try {
@@ -2249,7 +2185,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
SYS_LOGGER.log(Level.SEVERE, "All data source processors failed to process {0}", dataSource.getPath());
jobLogger.logFailedToAddDataSource();
// Throw an exception. It will get caught & handled upstream and will result in AIM auto-pause.
- throw new AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException("Failed to process " + dataSource.getPath() + " with all data source processors");
+ throw new AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException("Failed to process " + dataSource.getPath() + " with all data source processors");
}
} finally {
currentJob.setDataSourceProcessor(null);
@@ -2325,7 +2261,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
jobLogger.logDataSourceProcessorCancelled();
}
}
-
+
/**
* Analyzes the data source content returned by the data source
* processor using the configured set of data source level and file
@@ -2370,7 +2306,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
*/
ingestLock.wait();
IngestJob.ProgressSnapshot jobSnapshot = ingestJob.getSnapshot();
- for (IngestJob.ProgressSnapshot.DataSourceProcessingSnapshot snapshot : jobSnapshot.getDataSourceSnapshots()) { // RJCTODO: Are "child" jobs IngestJobs or DataSourceIngestJobs?
+ for (IngestJob.ProgressSnapshot.DataSourceProcessingSnapshot snapshot : jobSnapshot.getDataSourceSnapshots()) {
if (!snapshot.isCancelled()) {
List cancelledModules = snapshot.getCancelledDataSourceIngestModules();
if (!cancelledModules.isEmpty()) {
@@ -2421,7 +2357,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
}
} finally {
IngestManager.getInstance().removeIngestJobEventListener(ingestJobEventListener);
- currentJob.setIngestJob(null); // RJCTODO: Consider moving AutoIngestJob into AutoIngestManager so that this method can be made private
+ currentJob.setIngestJob(null);
}
}
@@ -2686,7 +2622,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* remote jobs. The auto ingest job status event is sent only if auto ingest
* manager has a currently running auto ingest job.
*/
- private final class PeriodicJobStatusEventTask implements Runnable { // RJCTODO: Rename to StatusPublishingTask, especially when publishing to the system dashboard
+ private final class PeriodicJobStatusEventTask implements Runnable {
private final long MAX_SECONDS_WITHOUT_UPDATE = JOB_STATUS_EVENT_INTERVAL_SECONDS * MAX_MISSED_JOB_STATUS_UPDATES;
@@ -2704,14 +2640,14 @@ public final class AutoIngestManager extends Observable implements PropertyChang
notifyObservers(Event.JOB_STATUS_UPDATED);
eventPublisher.publishRemotely(new AutoIngestJobStatusEvent(currentJob));
}
-
- if(AutoIngestUserPreferences.getStatusDatabaseLoggingEnabled()){
+
+ if (AutoIngestUserPreferences.getStatusDatabaseLoggingEnabled()) {
String message;
boolean isError = false;
- if(getErrorState().equals(ErrorState.NONE)){
- if(currentJob != null){
- message = "Processing " + currentJob.getManifest().getDataSourceFileName() +
- " for case " + currentJob.getManifest().getCaseName();
+ if (getErrorState().equals(ErrorState.NONE)) {
+ if (currentJob != null) {
+ message = "Processing " + currentJob.getManifest().getDataSourceFileName()
+ + " for case " + currentJob.getManifest().getCaseName();
} else {
message = "Paused or waiting for next case";
}
@@ -2719,9 +2655,9 @@ public final class AutoIngestManager extends Observable implements PropertyChang
message = getErrorState().toString();
isError = true;
}
- try{
+ try {
StatusDatabaseLogger.logToStatusDatabase(message, isError);
- } catch (SQLException | UserPreferencesException ex){
+ } catch (SQLException | UserPreferencesException ex) {
SYS_LOGGER.log(Level.WARNING, "Failed to update status database", ex);
}
}
@@ -2778,7 +2714,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
/*
* Events published by an auto ingest manager. The events are published
* locally to auto ingest manager clients that register as observers and are
- * broadcast to other auto ingest nodes. // RJCTODO: Is this true?
+ * broadcast to other auto ingest nodes.
*/
enum Event {
@@ -2794,31 +2730,31 @@ public final class AutoIngestManager extends Observable implements PropertyChang
}
/**
- * The current auto ingest error state.
+ * The current auto ingest error state.
*/
private enum ErrorState {
- NONE ("None"),
- COORDINATION_SERVICE_ERROR ("Coordination service error"),
+ NONE("None"),
+ COORDINATION_SERVICE_ERROR("Coordination service error"),
SHARED_CONFIGURATION_DOWNLOAD_ERROR("Shared configuration download error"),
- SERVICES_MONITOR_COMMUNICATION_ERROR ("Services monitor communication error"),
- DATABASE_SERVER_ERROR ("Database server error"),
- KEYWORD_SEARCH_SERVER_ERROR ("Keyword search server error"),
- CASE_MANAGEMENT_ERROR ("Case management error"),
- ANALYSIS_STARTUP_ERROR ("Analysis startup error"),
- FILE_EXPORT_ERROR ("File export error"),
- ALERT_FILE_ERROR ("Alert file error"),
- JOB_LOGGER_ERROR ("Job logger error"),
- DATA_SOURCE_PROCESSOR_ERROR ("Data source processor error"),
- UNEXPECTED_EXCEPTION ("Unknown error");
-
+ SERVICES_MONITOR_COMMUNICATION_ERROR("Services monitor communication error"),
+ DATABASE_SERVER_ERROR("Database server error"),
+ KEYWORD_SEARCH_SERVER_ERROR("Keyword search server error"),
+ CASE_MANAGEMENT_ERROR("Case management error"),
+ ANALYSIS_STARTUP_ERROR("Analysis startup error"),
+ FILE_EXPORT_ERROR("File export error"),
+ ALERT_FILE_ERROR("Alert file error"),
+ JOB_LOGGER_ERROR("Job logger error"),
+ DATA_SOURCE_PROCESSOR_ERROR("Data source processor error"),
+ UNEXPECTED_EXCEPTION("Unknown error");
+
private final String desc;
-
- private ErrorState(String desc){
+
+ private ErrorState(String desc) {
this.desc = desc;
}
-
+
@Override
- public String toString(){
+ public String toString() {
return desc;
}
}
@@ -2853,7 +2789,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @return The jobs collection.
*/
List getPendingJobs() {
- return this.pendingJobs;
+ return Collections.unmodifiableList(this.pendingJobs);
}
/**
@@ -2862,7 +2798,7 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @return The jobs collection.
*/
List getRunningJobs() {
- return this.runningJobs;
+ return Collections.unmodifiableList(this.runningJobs);
}
/**
@@ -2871,14 +2807,11 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* @return The jobs collection.
*/
List getCompletedJobs() {
- return this.completedJobs;
+ return Collections.unmodifiableList(this.completedJobs);
}
}
- /**
- * RJCTODO
- */
enum CaseDeletionResult {
FAILED,
PARTIALLY_DELETED,
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutopsyManifestFileParser.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutopsyManifestFileParser.java
index 380bbb15a9..0fe33092ca 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutopsyManifestFileParser.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutopsyManifestFileParser.java
@@ -34,9 +34,6 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
-/**
- * RJCTODO
- */
@Immutable
@ServiceProvider(service = ManifestFileParser.class)
public final class AutopsyManifestFileParser implements ManifestFileParser {
@@ -47,14 +44,6 @@ public final class AutopsyManifestFileParser implements ManifestFileParser {
private static final String DEVICE_ID_XPATH = "/Manifest/Collection/Image/ID/text()";
private static final String DATA_SOURCE_NAME_XPATH = "/Manifest/Collection/Image/Name/text()";
-
- /**
- * RJCTODO
- *
- * @param filePath
- *
- * @return
- */
@Override
public boolean fileIsManifest(Path filePath) {
boolean fileIsManifest = false;
@@ -71,15 +60,6 @@ public final class AutopsyManifestFileParser implements ManifestFileParser {
return fileIsManifest;
}
- /**
- * RJCTODO
- *
- * @param filePath
- *
- * @return
- *
- * @throws org.sleuthkit.autopsy.experimental.autoingest.ManifestFileParser.ManifestFileParserException
- */
@Override
public Manifest parse(Path filePath) throws ManifestFileParserException {
if (!fileIsManifest(filePath)) {
@@ -102,17 +82,6 @@ public final class AutopsyManifestFileParser implements ManifestFileParser {
}
}
- /**
- * RJCTODO
- *
- * @param manifestFilePath
- *
- * @return
- *
- * @throws ParserConfigurationException
- * @throws SAXException
- * @throws IOException
- */
private Document createManifestDOM(Path manifestFilePath) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Manifest.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Manifest.java
index 3acf895a9d..e5d7f1a6a3 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Manifest.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Manifest.java
@@ -29,9 +29,6 @@ import java.util.HashMap;
import java.util.Map;
import javax.annotation.concurrent.Immutable;
-/**
- * RJCTODO
- */
@Immutable
public final class Manifest implements Serializable {
@@ -43,17 +40,6 @@ public final class Manifest implements Serializable {
private final String dataSourcePath;
private final Map manifestProperties;
- /**
- * RJCTODO
- *
- * @param manifestFilePath
- * @param caseName
- * @param deviceId
- * @param dataSourcePath
- * @param manifestProperties
- *
- * @throws IOException
- */
public Manifest(Path manifestFilePath, String caseName, String deviceId, Path dataSourcePath, Map manifestProperties) throws IOException {
this.filePath = manifestFilePath.toString();
BasicFileAttributes attrs = Files.readAttributes(manifestFilePath, BasicFileAttributes.class);
@@ -64,65 +50,30 @@ public final class Manifest implements Serializable {
this.manifestProperties = new HashMap<>(manifestProperties);
}
- /**
- * RJCTODO
- *
- * @return
- */
public Path getFilePath() {
return Paths.get(this.filePath);
}
- /**
- * RJCTODO
- *
- * @return
- * @throws IOException
- */
public Date getDateFileCreated() {
return this.dateFileCreated;
}
- /**
- * RJCTODO
- *
- * @return
- */
public String getCaseName() {
return caseName;
}
- /**
- * RJCTODO
- *
- * @return
- */
public String getDeviceId() {
return deviceId;
}
- /**
- * RJCTODO
- *
- * @return
- */
public Path getDataSourcePath() {
return Paths.get(dataSourcePath);
}
- /**
- * RJCTODO
- * @return
- */
public String getDataSourceFileName() {
return Paths.get(dataSourcePath).getFileName().toString();
}
- /**
- * RJCTODO
- *
- * @return
- */
public Map getManifestProperties() {
return new HashMap<>(manifestProperties);
}
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ManifestFileParser.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ManifestFileParser.java
index 14111b0410..00fb2b9a5f 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ManifestFileParser.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ManifestFileParser.java
@@ -20,17 +20,11 @@ package org.sleuthkit.autopsy.experimental.autoingest;
import java.nio.file.Path;
-/**
- * RJCTODO:
- */
public interface ManifestFileParser {
boolean fileIsManifest(Path filePath);
Manifest parse(Path filePath) throws ManifestFileParserException;
- /**
- * Exception thrown if a manifest file cannot be parsed. RJCTODO
- */
public final static class ManifestFileParserException extends Exception {
private static final long serialVersionUID = 1L;
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ManifestNodeData.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ManifestNodeData.java
index e4e272edd3..498ac38cee 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ManifestNodeData.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ManifestNodeData.java
@@ -99,9 +99,6 @@ final class ManifestNodeData {
*
* @return True or false.
*/
- // RJCTODO: This is confusing, consider changing the API so that the use case is to
- // check the length of the node data from the coordination service before
- // constructing an instance of this object. That would be much more clear!
boolean coordSvcNodeDataWasSet() {
return this.coordSvcNodeDataWasSet;
}
diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java
index 622912f95a..852ab4714f 100644
--- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java
+++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/PathUtils.java
@@ -69,7 +69,7 @@ final class PathUtils {
*
* @return A list of the output case folder paths.
*/
- static List findCaseFolders(Path folderToSearch) { // RJCTODO: Rename
+ static List findCaseFolders(Path folderToSearch) {
File searchFolder = new File(folderToSearch.toString());
if (!searchFolder.isDirectory()) {
return Collections.emptyList();
@@ -135,7 +135,7 @@ final class PathUtils {
*
* @return A case folder path with a time stamp suffix.
*/
- static Path createCaseFolderPath(Path caseFoldersPath, String caseName) { // RJCTODO: Rename
+ static Path createCaseFolderPath(Path caseFoldersPath, String caseName) {
String folderName = caseName + "_" + TimeStampUtils.createTimeStamp();
return Paths.get(caseFoldersPath.toString(), folderName);
}
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexFinder.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexFinder.java
index 3e7a7c4ec7..80b686751b 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexFinder.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexFinder.java
@@ -31,7 +31,7 @@ import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.sleuthkit.autopsy.casemodule.Case;
-import org.sleuthkit.autopsy.corecomponentinterfaces.AutopsyService;
+import org.sleuthkit.autopsy.framework.AutopsyService;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.UNCPathUtilities;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexUpgrader.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexUpgrader.java
index ead8609d32..c07385e277 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexUpgrader.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexUpgrader.java
@@ -26,7 +26,7 @@ import java.util.List;
import java.util.logging.Level;
import org.apache.commons.lang.math.NumberUtils;
import org.openide.modules.InstalledFileLocator;
-import org.sleuthkit.autopsy.corecomponentinterfaces.AutopsyService;
+import org.sleuthkit.autopsy.framework.AutopsyService;
import org.sleuthkit.autopsy.coreutils.ExecUtil;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java
index c1d5771c99..f238062e1f 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java
@@ -30,7 +30,7 @@ import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders;
import org.sleuthkit.autopsy.core.RuntimeProperties;
-import org.sleuthkit.autopsy.corecomponentinterfaces.AutopsyService;
+import org.sleuthkit.autopsy.framework.AutopsyService;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
@@ -55,6 +55,14 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService {
ArtifactTextExtractor extractor = new ArtifactTextExtractor();
+ /**
+ * Adds an artifact to the keyword search text index as a concantenation of
+ * all of its attributes.
+ *
+ * @param artifact The artifact to index.
+ *
+ * @throws org.sleuthkit.datamodel.TskCoreException
+ */
@Override
public void indexArtifact(BlackboardArtifact artifact) throws TskCoreException {
if (artifact == null) {
@@ -77,21 +85,12 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService {
}
/**
- * Checks if we can communicate with Solr using the passed-in host and port.
- * Closes the connection upon exit. Throws if it cannot communicate with
- * Solr.
+ * Tries to connect to the keyword search service.
*
- * When issues occur, it attempts to diagnose them by looking at the
- * exception messages, returning the appropriate user-facing text for the
- * exception received. This method expects the Exceptions messages to be in
- * English and compares against English text.
- *
- * @param host the remote hostname or IP address of the Solr server
- * @param port the remote port for Solr
- *
- * @throws
- * org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchServiceException
+ * @param host The hostname or IP address of the service.
+ * @param port The port used by the service.
*
+ * @throws KeywordSearchServiceException if cannot connect.
*/
@Override
public void tryConnect(String host, int port) throws KeywordSearchServiceException {
@@ -138,6 +137,24 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService {
}
}
+ /**
+ * Deletes the keyword search text index for a case.
+ *
+ * @param textIndexName The text index name.
+ */
+ @Override
+ public void deleteTextIndex(String textIndexName) {
+ /*
+ * Send a core unload request to the Solr server, with the parameters
+ * that request deleting the index and the instance directory
+ * (deleteInstanceDir removes everything related to the core, the index
+ * directory, the configuration files, etc.) set to true.
+ */
+// String url = "http://" + UserPreferences.getIndexingServerHost() + ":" + UserPreferences.getIndexingServerPort() + "/solr";
+// HttpSolrServer solrServer = new HttpSolrServer(url);
+// org.apache.solr.client.solrj.request.CoreAdminRequest.unloadCore(textIndexName, true, true, solrServer);
+ }
+
@Override
public void close() throws IOException {
}