Fixes for Case operation cancellation infrastructure

This commit is contained in:
Richard Cordovano 2017-01-26 09:17:37 -05:00
parent 3ada14c54d
commit c6c45288f4
3 changed files with 309 additions and 279 deletions

View File

@ -43,6 +43,7 @@ import java.util.MissingResourceException;
import java.util.Set; import java.util.Set;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@ -95,7 +96,6 @@ import org.sleuthkit.autopsy.framework.ModalDialogProgressIndicator;
import org.sleuthkit.autopsy.framework.ProgressIndicator; import org.sleuthkit.autopsy.framework.ProgressIndicator;
import org.sleuthkit.autopsy.ingest.IngestJob; import org.sleuthkit.autopsy.ingest.IngestJob;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.RunIngestAction;
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
import org.sleuthkit.autopsy.timeline.OpenTimelineAction; import org.sleuthkit.autopsy.timeline.OpenTimelineAction;
import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.BlackboardArtifactTag;
@ -443,11 +443,11 @@ public class Case {
* exception. * exception.
*/ */
@Messages({ @Messages({
"# {0} - exception message", "Case.creationException.couldNotCreateCase=Could not create case: {0}", "# {0} - exception message", "Case.exceptionMessage.wrapperMessage={0}",
"Case.exceptionMessage.illegalCaseName=Case name contains illegal characters.", "Case.exceptionMessage.illegalCaseName=Case name contains illegal characters.",
"Case.exceptionMessage.lockAcquisitionInterrupted=Acquiring locks was interrupted.", "Case.exceptionMessage.cancelled=Cancelled by user.",
"Case.progressIndicatorTitle.creatingCase=Creating Case", "Case.progressIndicatorTitle.creatingCase=Creating Case",
"Case.progressIndicatorCancelButton.label=Cancel", "Case.progressIndicatorCancelButton.label=Cancelled",
"Case.progressMessage.preparing=Preparing...", "Case.progressMessage.preparing=Preparing...",
"Case.progressMessage.acquiringLocks=Acquiring locks...", "Case.progressMessage.acquiringLocks=Acquiring locks...",
"Case.progressMessage.finshing=Finishing..." "Case.progressMessage.finshing=Finishing..."
@ -482,7 +482,6 @@ public class Case {
} catch (IllegalCaseNameException ex) { } catch (IllegalCaseNameException ex) {
throw new CaseActionException(Bundle.Case_creationException_couldNotCreateCase(Bundle.Case_exceptionMessage_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
/* /*
* Set up either a GUI progress indicator or a logging progress * Set up either a GUI progress indicator or a logging progress
@ -507,7 +506,6 @@ public class Case {
* open is released in the same thread in which it was acquired, as is * open is released in the same thread in which it was acquired, as is
* required by the coordination service. * required by the coordination service.
*/ */
try {
Future<Case> future = getCaseLockingExecutor().submit(() -> { Future<Case> future = getCaseLockingExecutor().submit(() -> {
if (CaseType.SINGLE_USER_CASE == caseType) { if (CaseType.SINGLE_USER_CASE == caseType) {
newCase.open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator); newCase.open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator);
@ -520,9 +518,9 @@ public class Case {
try (CoordinationService.Lock nameLock = Case.acquireExclusiveCaseNameLock(caseName)) { try (CoordinationService.Lock nameLock = Case.acquireExclusiveCaseNameLock(caseName)) {
assert (null != nameLock); assert (null != nameLock);
/* /*
* Next, acquire a shared case directory lock that will * Next, acquire a shared case directory lock that will be
* be held as long as this node has this case open. This * held as long as this node has this case open. This will
* will prevent deletion of the case by another node. * prevent deletion of the case by another node.
*/ */
acquireSharedCaseDirLock(caseDir); acquireSharedCaseDirLock(caseDir);
/* /*
@ -536,8 +534,8 @@ public class Case {
newCase.open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator); newCase.open(caseDir, caseName, caseDisplayName, caseNumber, examiner, caseType, progressIndicator);
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
/* /*
* Release the case directory lock immediately * Release the case directory lock immediately if
* if there was a problem opening the case. * there was a problem opening the case.
*/ */
if (CaseType.MULTI_USER_CASE == caseType) { if (CaseType.MULTI_USER_CASE == caseType) {
releaseSharedCaseDirLock(caseName); releaseSharedCaseDirLock(caseName);
@ -549,10 +547,22 @@ public class Case {
} }
return newCase; return newCase;
}); });
/*
* If running with a GUI, give the future for the case creation task to
* the cancel button listener for the GUI progress indicator and make
* the progress indicator visible to the user.
*/
if (RuntimeProperties.runningWithGUI()) { if (RuntimeProperties.runningWithGUI()) {
listener.setCaseActionFuture(future); listener.setCaseActionFuture(future);
SwingUtilities.invokeLater(() -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(true)); SwingUtilities.invokeLater(() -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(true));
} }
/*
* Wait for the case creation task to finish.
*/
try {
logger.log(Level.INFO, "Attempting to create case {0} (display name = {1}) in directory = {2}", new Object[]{caseName, caseDisplayName, caseDir}); //NON-NLS
currentCase = future.get(); currentCase = future.get();
logger.log(Level.INFO, "Created case {0} in directory = {1}", new Object[]{caseName, caseDir}); //NON-NLS logger.log(Level.INFO, "Created case {0} in directory = {1}", new Object[]{caseName, caseDir}); //NON-NLS
if (RuntimeProperties.runningWithGUI()) { if (RuntimeProperties.runningWithGUI()) {
@ -560,12 +570,12 @@ public class Case {
} }
eventPublisher.publishLocally(new AutopsyEvent(Events.CURRENT_CASE.toString(), null, currentCase)); eventPublisher.publishLocally(new AutopsyEvent(Events.CURRENT_CASE.toString(), null, currentCase));
} catch (InterruptedException | ExecutionException ex) { } catch (InterruptedException ex) {
if (ex instanceof InterruptedException) { throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getMessage()), ex);
throw new CaseActionException(Bundle.Case_creationException_couldNotCreateCase(Bundle.Case_exceptionMessage_lockAcquisitionInterrupted()), ex); } catch (ExecutionException ex) {
} else { throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getCause().getMessage()), ex);
throw new CaseActionException(Bundle.Case_creationException_couldNotCreateCase(ex.getCause().getMessage()), ex); } catch (CancellationException ex) {
} throw new CaseActionException(Bundle.Case_exceptionMessage_cancelled(), ex);
} finally { } finally {
progressIndicator.finish(Bundle.Case_progressMessage_finshing()); progressIndicator.finish(Bundle.Case_progressMessage_finshing());
if (RuntimeProperties.runningWithGUI()) { if (RuntimeProperties.runningWithGUI()) {
@ -589,6 +599,7 @@ public class Case {
"Case.progressIndicatorTitle.openingCase=Opening Case", "Case.progressIndicatorTitle.openingCase=Opening Case",
"Case.exceptionMessage.failedToReadMetadata=Failed to read metadata." "Case.exceptionMessage.failedToReadMetadata=Failed to read metadata."
}) })
public static void openAsCurrentCase(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 * If running with the desktop GUI, this needs to be done before any
@ -609,9 +620,12 @@ public class Case {
closeCurrentCase(); closeCurrentCase();
} }
logger.log(Level.INFO, "Opening case with metadata file path {0}", caseMetadataFilePath); //NON-NLS CaseMetadata metadata;
try { try {
CaseMetadata metadata = new CaseMetadata(Paths.get(caseMetadataFilePath)); metadata = new CaseMetadata(Paths.get(caseMetadataFilePath));
} catch (CaseMetadataException ex) {
throw new CaseActionException(Bundle.Case_openException_couldNotOpenCase(Bundle.Case_exceptionMessage_failedToReadMetadata()), ex);
}
/* /*
* Set up either a GUI progress indicator or a logging progress * Set up either a GUI progress indicator or a logging progress
@ -630,31 +644,29 @@ public class Case {
progressIndicator.start(Bundle.Case_progressMessage_preparing()); progressIndicator.start(Bundle.Case_progressMessage_preparing());
/* /*
* Opening a case is always done in the same non-UI thread that will * Opening a case is always done in the same non-UI thread that will be
* be used later to close the case. If the case is a multi-user * used later to close the case. If the case is a multi-user case, this
* case, this ensures that case directory lock that is held as long * ensures that case directory lock that is held as long as the case is
* as the case is open is released in the same thread in which it * open is released in the same thread in which it was acquired, as is
* was acquired, as is required by the coordination service. * required by the coordination service.
*/ */
CaseType caseType = metadata.getCaseType(); CaseType caseType = metadata.getCaseType();
String caseName = metadata.getCaseName(); String caseName = metadata.getCaseName();
try {
Future<Case> future = getCaseLockingExecutor().submit(() -> { Future<Case> future = getCaseLockingExecutor().submit(() -> {
if (CaseType.SINGLE_USER_CASE == caseType) { if (CaseType.SINGLE_USER_CASE == caseType) {
caseToOpen.open(metadata, progressIndicator); caseToOpen.open(metadata, progressIndicator);
} else { } else {
/* /*
* First, acquire a shared case directory lock that will * First, acquire a shared case directory lock that will be held
* be held as long as this node has this case open, in * as long as this node has this case open, in order to prevent
* order to prevent deletion of the case by another * deletion of the case by another node.
* node.
*/ */
progressIndicator.start(Bundle.Case_progressMessage_acquiringLocks()); progressIndicator.start(Bundle.Case_progressMessage_acquiringLocks());
acquireSharedCaseDirLock(metadata.getCaseDirectory()); acquireSharedCaseDirLock(metadata.getCaseDirectory());
/* /*
* Next, acquire an exclusive case resources lock to * Next, acquire an exclusive case resources lock to ensure only
* ensure only one node at a time can * one node at a time can create/open/upgrade/close case
* create/open/upgrade/close case resources. * resources.
*/ */
try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(metadata.getCaseName())) { try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(metadata.getCaseName())) {
assert (null != resourcesLock); assert (null != resourcesLock);
@ -662,8 +674,8 @@ public class Case {
caseToOpen.open(metadata, progressIndicator); caseToOpen.open(metadata, progressIndicator);
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
/* /*
* Release the case directory lock immediately * Release the case directory lock immediately if there
* if there was a problem opening the case. * was a problem opening the case.
*/ */
if (CaseType.MULTI_USER_CASE == caseType) { if (CaseType.MULTI_USER_CASE == caseType) {
releaseSharedCaseDirLock(caseName); releaseSharedCaseDirLock(caseName);
@ -674,32 +686,41 @@ public class Case {
} }
return caseToOpen; return caseToOpen;
}); });
/*
* If running with a GUI, give the future for the case opening task to
* the cancel button listener for the GUI progress indicator and make
* the progress indicator visible to the user.
*/
if (RuntimeProperties.runningWithGUI()) { if (RuntimeProperties.runningWithGUI()) {
listener.setCaseActionFuture(future); listener.setCaseActionFuture(future);
SwingUtilities.invokeLater(() -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(true)); SwingUtilities.invokeLater(() -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(true));
} }
future.get();
/*
* Wait for the case opening task to finish.
*/
try {
logger.log(Level.INFO, "Opening case with metadata file path {0}", caseMetadataFilePath); //NON-NLS
currentCase = future.get(); currentCase = future.get();
logger.log(Level.INFO, "Opened case with metadata file path {0}", caseMetadataFilePath); //NON-NLS logger.log(Level.INFO, "Opened case with metadata file path {0}", caseMetadataFilePath); //NON-NLS
if (RuntimeProperties.runningWithGUI()) { if (RuntimeProperties.runningWithGUI()) {
updateGUIForCaseOpened(); updateGUIForCaseOpened();
} }
eventPublisher.publishLocally(new AutopsyEvent(Events.CURRENT_CASE.toString(), null, currentCase)); eventPublisher.publishLocally(new AutopsyEvent(Events.CURRENT_CASE.toString(), null, currentCase));
} catch (InterruptedException | ExecutionException ex) {
if (ex instanceof ExecutionException) { } catch (InterruptedException ex) {
throw new CaseActionException(Bundle.Case_openException_couldNotOpenCase(ex.getCause().getMessage()), ex); throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getMessage()), ex);
} else { } catch (ExecutionException ex) {
throw new CaseActionException(Bundle.Case_openException_couldNotOpenCase(Bundle.Case_exceptionMessage_lockAcquisitionInterrupted()), ex); throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getCause().getMessage()), ex);
} } catch (CancellationException ex) {
throw new CaseActionException(Bundle.Case_exceptionMessage_cancelled(), ex);
} finally { } finally {
progressIndicator.finish(Bundle.Case_progressMessage_finshing()); progressIndicator.finish(Bundle.Case_progressMessage_finshing());
if (RuntimeProperties.runningWithGUI()) { 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(Bundle.Case_exceptionMessage_failedToReadMetadata()), ex);
}
} }
/** /**
@ -763,14 +784,12 @@ public class Case {
listener.setCaseContext(caseContext); listener.setCaseContext(caseContext);
progressIndicator.start(Bundle.Case_progressMessage_preparing()); progressIndicator.start(Bundle.Case_progressMessage_preparing());
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 * Closing a case is always done in the same non-UI thread that
* opened/created the case. If the case is a multi-user case, this * opened/created the case. If the case is a multi-user case, this
* ensures that case directory lock that is held as long as the case * ensures that case directory lock that is held as long as the case is
* is open is released in the same thread in which it was acquired, * open is released in the same thread in which it was acquired, as is
* as is required by the coordination service. * required by the coordination service.
*/ */
Future<Void> future = getCaseLockingExecutor().submit(() -> { Future<Void> future = getCaseLockingExecutor().submit(() -> {
if (CaseType.SINGLE_USER_CASE == currentCase.getCaseType()) { if (CaseType.SINGLE_USER_CASE == currentCase.getCaseType()) {
@ -778,8 +797,8 @@ public class Case {
} else { } else {
String caseName = currentCase.getCaseMetadata().getCaseName(); String caseName = currentCase.getCaseMetadata().getCaseName();
/* /*
* Acquire an exclusive case resources lock to ensure only * Acquire an exclusive case resources lock to ensure only one
* one node at a time can create/open/upgrade/close the case * node at a time can create/open/upgrade/close the case
* resources. * resources.
*/ */
progressIndicator.start(Bundle.Case_progressMessage_acquiringLocks()); progressIndicator.start(Bundle.Case_progressMessage_acquiringLocks());
@ -788,25 +807,34 @@ public class Case {
currentCase.close(progressIndicator); currentCase.close(progressIndicator);
} finally { } finally {
/* /*
* Always release the case directory lock that was * Always release the case directory lock that was acquired
* acquired when the case was opened. * when the case was opened.
*/ */
releaseSharedCaseDirLock(caseName); releaseSharedCaseDirLock(caseName);
} }
} }
return null; return null;
}); });
/*
* If running with a GUI, give the future for the case closing task to
* the cancel button listener for the GUI progress indicator and make
* the progress indicator visible to the user.
*/
if (RuntimeProperties.runningWithGUI()) { if (RuntimeProperties.runningWithGUI()) {
listener.setCaseActionFuture(future); listener.setCaseActionFuture(future);
SwingUtilities.invokeLater(() -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(true)); SwingUtilities.invokeLater(() -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(true));
} }
try {
logger.log(Level.INFO, "Closing case with metadata file path {0}", currentCase.getCaseMetadata().getFilePath()); //NON-NLS
future.get(); future.get();
} catch (InterruptedException | ExecutionException ex) { } catch (InterruptedException ex) {
if (ex instanceof ExecutionException) { throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getMessage()), ex);
throw new CaseActionException(Bundle.Case_closeException_couldNotCloseCase(ex.getCause().getMessage()), ex); } catch (ExecutionException ex) {
} else { throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getCause().getMessage()), ex);
throw new CaseActionException(Bundle.Case_closeException_couldNotCloseCase(Bundle.Case_exceptionMessage_lockAcquisitionInterrupted()), ex); } catch (CancellationException ex) {
} throw new CaseActionException(Bundle.Case_exceptionMessage_cancelled(), ex);
} finally { } finally {
/* /*
* The case is no longer the current case, even if an exception was * The case is no longer the current case, even if an exception was
@ -865,8 +893,6 @@ public class Case {
throw new CaseActionException(Bundle.Case_deleteException_couldNotDeleteCase(Bundle.Case_exceptionMessage_cannotDeleteCurrentCase())); 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 * Set up either a GUI progress indicator or a logging progress
* indicator. * indicator.
@ -884,6 +910,7 @@ public class Case {
progressIndicator = new LoggingProgressIndicator(); progressIndicator = new LoggingProgressIndicator();
} }
progressIndicator.start(Bundle.Case_progressMessage_preparing()); progressIndicator.start(Bundle.Case_progressMessage_preparing());
Future<Void> future = getCaseLockingExecutor().submit(() -> { Future<Void> future = getCaseLockingExecutor().submit(() -> {
if (CaseType.SINGLE_USER_CASE == metadata.getCaseType()) { if (CaseType.SINGLE_USER_CASE == metadata.getCaseType()) {
cleanupDeletedCase(metadata, progressIndicator); cleanupDeletedCase(metadata, progressIndicator);
@ -906,10 +933,9 @@ public class Case {
if (CaseType.MULTI_USER_CASE == metadata.getCaseType()) { if (CaseType.MULTI_USER_CASE == metadata.getCaseType()) {
/* /*
* Delete the case database from the database * Delete the case database from the database server.
* server. The case database for a single-user case * The case database for a single-user case is in the
* is in the case directory and will be deleted whe * case directory and will be deleted whe it is deleted.
* it is deleted.
*/ */
progressIndicator.start(Bundle.Case_progressMessage_deletingCaseDatabase()); progressIndicator.start(Bundle.Case_progressMessage_deletingCaseDatabase());
CaseDbConnectionInfo db = UserPreferences.getDatabaseConnectionInfo(); CaseDbConnectionInfo db = UserPreferences.getDatabaseConnectionInfo();
@ -926,14 +952,17 @@ public class Case {
} }
return null; return null;
}); });
logger.log(Level.INFO, "Deleted case with metadata file path {0}", metadata.getFilePath()); //NON-NLS
try {
logger.log(Level.INFO, "Deleting case with metadata file path {0}", metadata.getFilePath()); //NON-NLS
future.get(); future.get();
} catch (InterruptedException | ExecutionException ex) { logger.log(Level.INFO, "Deleted case with metadata file path {0}", metadata.getFilePath()); //NON-NLS
if (ex instanceof ExecutionException) { } catch (InterruptedException ex) {
throw new CaseActionException(Bundle.Case_deleteException_couldNotDeleteCase(ex.getCause().getMessage()), ex); throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getMessage()), ex);
} else { } catch (ExecutionException ex) {
throw new CaseActionException(Bundle.Case_deleteException_couldNotDeleteCase(Bundle.Case_exceptionMessage_lockAcquisitionInterrupted()), ex); throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getCause().getMessage()), ex);
} } catch (CancellationException ex) {
throw new CaseActionException(Bundle.Case_exceptionMessage_cancelled(), ex);
} }
} }

View File

@ -24,7 +24,6 @@ import javax.swing.SwingUtilities;
import org.openide.DialogDescriptor; import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer; import org.openide.DialogDisplayer;
import org.openide.util.HelpCtx; import org.openide.util.HelpCtx;
import org.sleuthkit.autopsy.framework.ProgressIndicator;
/** /**
* A progress indicator that displays progress using a modal dialog with a * A progress indicator that displays progress using a modal dialog with a
@ -51,6 +50,18 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor); dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor);
} }
public ModalDialogProgressIndicator(String title, HelpCtx helpCtx) {
progressPanel = new ProgressPanel();
DialogDescriptor dialogDescriptor = new DialogDescriptor(
progressPanel,
title,
true,
DialogDescriptor.NO_OPTION,
null,
null);
dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor);
}
public void setVisible(boolean isVisible) { public void setVisible(boolean isVisible) {
this.dialog.setVisible(isVisible); this.dialog.setVisible(isVisible);
} }

View File

@ -27,10 +27,10 @@ import org.sleuthkit.autopsy.framework.ProgressIndicator;
/** /**
* An implementation of the Autopsy service interface used for test purposes. * An implementation of the Autopsy service interface used for test purposes.
*/ */
//@ServiceProvider(service = AutopsyService.class) @ServiceProvider(service = AutopsyService.class)
public class TestAutopsyService implements AutopsyService { public class TestAutopsyService implements AutopsyService {
private static final Logger LOGGER = Logger.getLogger(TestAutopsyService.class.getName()); private static final Logger logger = Logger.getLogger(TestAutopsyService.class.getName());
@Override @Override
public String getServiceName() { public String getServiceName() {
@ -41,41 +41,31 @@ public class TestAutopsyService implements AutopsyService {
public void openCaseResources(CaseContext context) throws AutopsyServiceException { public void openCaseResources(CaseContext context) throws AutopsyServiceException {
ProgressIndicator progressIndicator = context.getProgressIndicator(); ProgressIndicator progressIndicator = context.getProgressIndicator();
try { try {
progressIndicator.start("Doing first task...", 100); logger.log(Level.INFO, "Test Autopsy Service started first task");
progressIndicator.start("Test Autopsy Service doing first task...", 100);
Thread.sleep(1000L); Thread.sleep(1000L);
progressIndicator.progress(10); progressIndicator.progress(20);
Thread.sleep(1000L); Thread.sleep(1000L);
progressIndicator.progress(10); progressIndicator.progress(40);
Thread.sleep(1000L); Thread.sleep(1000L);
progressIndicator.progress(10); progressIndicator.progress(60);
Thread.sleep(1000L); Thread.sleep(1000L);
progressIndicator.progress(10); progressIndicator.progress(80);
Thread.sleep(1000L); Thread.sleep(1000L);
progressIndicator.progress(10); progressIndicator.progress(100);
Thread.sleep(1000L); progressIndicator.finish("First task completed by Test Autopsy Service.");
progressIndicator.progress(10); logger.log(Level.INFO, "Test Autopsy Service completed first task");
Thread.sleep(1000L); logger.log(Level.INFO, "Test Autopsy Service started second task");
progressIndicator.progress(10); progressIndicator.start("Test Autopsy Service doing second task...");
Thread.sleep(1000L); for (int i = 0; i < 10000; ++i) {
progressIndicator.progress(10);
Thread.sleep(1000L);
progressIndicator.progress(10);
Thread.sleep(1000L);
progressIndicator.progress(10);
progressIndicator.finish("First task completed.");
progressIndicator.start("Doing second task...");
Thread.sleep(10000L);
progressIndicator.finish("Second task completed.");
} catch (InterruptedException ex) {
LOGGER.log(Level.INFO, "Autopsy Test Service caught interrupt while working");
if (context.cancelRequested()) { if (context.cancelRequested()) {
progressIndicator.finish("Cancelling..."); logger.log(Level.INFO, "Autopsy Test Service cancelled while doing second task, cancel requested = {0}", context.cancelRequested());
try {
Thread.sleep(1000L);
} catch (InterruptedException ex1) {
LOGGER.log(Level.INFO, "Autopsy Test Service caught interrupt while working");
} }
} }
progressIndicator.finish("Second task completed by Test Autopsy Service.");
logger.log(Level.INFO, "Second task completed by Test Autopsy Service");
} catch (InterruptedException ex) {
logger.log(Level.INFO, "Autopsy Test Service interrupted (cancelled) while doing first task, cancel requested = {0}", context.cancelRequested());
} }
} }