19 package org.sleuthkit.autopsy.casemodule;
21 import java.awt.Frame;
22 import java.awt.event.ActionEvent;
23 import java.awt.event.ActionListener;
24 import java.beans.PropertyChangeListener;
25 import java.beans.PropertyChangeSupport;
27 import java.io.IOException;
28 import java.lang.reflect.InvocationTargetException;
29 import java.nio.file.InvalidPathException;
30 import java.nio.file.Path;
31 import java.nio.file.Paths;
32 import java.sql.Connection;
33 import java.sql.DriverManager;
34 import java.sql.Statement;
35 import java.text.SimpleDateFormat;
36 import java.util.Collection;
37 import java.util.Date;
38 import java.util.HashMap;
39 import java.util.HashSet;
40 import java.util.List;
42 import java.util.MissingResourceException;
44 import java.util.TimeZone;
45 import java.util.UUID;
46 import java.util.concurrent.CancellationException;
47 import java.util.concurrent.ExecutionException;
48 import java.util.concurrent.ExecutorService;
49 import java.util.concurrent.Executors;
50 import java.util.concurrent.Future;
51 import java.util.concurrent.TimeUnit;
52 import java.util.logging.Level;
53 import java.util.stream.Collectors;
54 import java.util.stream.Stream;
55 import javax.annotation.concurrent.GuardedBy;
56 import javax.swing.JOptionPane;
57 import javax.swing.SwingUtilities;
58 import org.openide.util.Lookup;
59 import org.openide.util.NbBundle;
60 import org.openide.util.NbBundle.Messages;
61 import org.openide.util.actions.CallableSystemAction;
62 import org.openide.windows.WindowManager;
142 @GuardedBy(
"currentCaseWriteLock")
155 @GuardedBy("currentCaseWriteLock")
157 @GuardedBy("currentCaseWriteLock")
190 if (typeName != null) {
191 for (CaseType c : CaseType.values()) {
192 if (typeName.equalsIgnoreCase(c.toString())) {
216 "Case_caseType_singleUser=Single-user case",
217 "Case_caseType_multiUser=Multi-user case"
220 if (fromString(typeName) == SINGLE_USER_CASE) {
221 return Bundle.Case_caseType_singleUser();
223 return Bundle.Case_caseType_multiUser();
233 this.typeName = typeName;
248 return (otherTypeName == null) ?
false : typeName.equals(otherTypeName);
374 .map(Events::toString)
375 .collect(Collectors.toSet()), listener);
386 .map(Events::toString)
387 .collect(Collectors.toSet()), listener);
439 return !(caseName.contains(
"\\") || caseName.contains(
"/") || caseName.contains(
":")
440 || caseName.contains(
"*") || caseName.contains(
"?") || caseName.contains(
"\"")
441 || caseName.contains(
"<") || caseName.contains(
">") || caseName.contains(
"|"));
467 "# {0} - exception message",
"Case.exceptionMessage.wrapperMessage={0}"
475 if (null != currentCase) {
476 String previousCaseDisplayName = currentCase.getDisplayName();
477 String previousCaseName = currentCase.getName();
478 String previousCaseDir = currentCase.getCaseDirectory();
482 logger.log(Level.SEVERE, String.format(
"Error closing the previous current case %s (%s) in %s", previousCaseDisplayName, previousCaseName, previousCaseDir), ex);
486 logger.log(Level.INFO,
"Creating current case {0} in {1}",
new Object[]{caseDisplayName, caseDir});
488 newCurrentCase.
create(caseType, caseDir, caseDisplayName, caseNumber, examiner);
489 currentCase = newCurrentCase;
490 logger.log(Level.INFO,
"Created currrent case {0} ({1}) in {2}",
new Object[]{newCurrentCase.getDisplayName(), newCurrentCase.getName(), newCurrentCase.getCaseDirectory()});
512 "# {0} - exception message",
"Case.openException.couldNotOpenCase=Could not open case: {0}",
513 "Case.progressIndicatorTitle.openingCase=Opening Case",
514 "Case.exceptionMessage.failedToReadMetadata=Failed to read metadata."
522 if (null != currentCase) {
526 logger.log(Level.SEVERE,
"Error closing the previous current case", ex);
531 logger.log(Level.INFO,
"Opening case with metadata file path {0} as current case", caseMetadataFilePath);
532 newCurrentCase.
open(Paths.get(caseMetadataFilePath));
533 currentCase = newCurrentCase;
534 logger.log(Level.INFO,
"Opened case with metadata file path {0} as current case", caseMetadataFilePath);
548 return currentCase != null;
560 if (null != caseToReturn) {
563 throw new IllegalStateException(NbBundle.getMessage(
Case.class,
"Case.getCurCase.exception.noneOpen"));
576 "# {0} - exception message",
"Case.closeException.couldNotCloseCase=Error closing case: {0}",
577 "Case.progressIndicatorTitle.closingCase=Closing Case"
581 if (null == currentCase) {
584 String caseName = currentCase.getName();
585 String caseDir = currentCase.getCaseDirectory();
589 logger.log(Level.INFO,
"Closing current case {0} in {1}",
new Object[]{caseName, caseDir});
597 logger.log(Level.INFO,
"Closed current case {0} in {1}",
new Object[]{caseName, caseDir});
618 if (null == currentCase) {
639 "# {0} - exception message",
"Case.deleteException.couldNotDeleteCase=Could not delete case: {0}",
640 "Case.progressIndicatorTitle.deletingCase=Deleting Case",
641 "Case.exceptionMessage.cannotDeleteCurrentCase=Cannot delete current case, it must be closed first",
642 "Case.progressMessage.checkingForOtherUser=Checking to see if another user has the case open...",
643 "Case.progressMessage.deletingTextIndex=Deleting text index...",
644 "Case.progressMessage.deletingCaseDatabase=Deleting case database...",
645 "Case.exceptionMessage.cancelled=Cancelled by user"
650 throw new CaseActionException(Bundle.Case_deleteException_couldNotDeleteCase(Bundle.Case_exceptionMessage_cannotDeleteCurrentCase()));
662 Bundle.Case_progressIndicatorTitle_deletingCase());
666 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
668 logger.log(Level.INFO,
"Deleting case with metadata file path {0}", metadata.getFilePath());
669 ExecutorService executor = Executors.newSingleThreadExecutor();
670 Future<Void> future = executor.submit(() -> {
671 if (CaseType.SINGLE_USER_CASE == metadata.
getCaseType()) {
678 progressIndicator.
start(Bundle.Case_progressMessage_checkingForOtherUser());
680 assert (null != dirLock);
685 progressIndicator.
start(Bundle.Case_progressMessage_deletingTextIndex());
687 searchService.deleteTextIndex(metadata);
690 if (CaseType.MULTI_USER_CASE == metadata.
getCaseType()) {
696 progressIndicator.
start(Bundle.Case_progressMessage_deletingCaseDatabase());
698 Class.forName(
"org.postgresql.Driver");
700 Statement statement = connection.createStatement();) {
702 statement.execute(deleteCommand);
714 logger.log(Level.INFO,
"Deleted case with metadata file path {0}", metadata.getFilePath());
715 }
catch (InterruptedException ex) {
716 throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getMessage()), ex);
717 }
catch (ExecutionException ex) {
718 throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getCause().getMessage()), ex);
719 }
catch (CancellationException ex) {
738 String uniqueCaseName = caseDisplayName.replaceAll(
"[^\\p{ASCII}]",
"_");
743 uniqueCaseName = uniqueCaseName.replaceAll(
"[\\p{Cntrl}]",
"_");
748 uniqueCaseName = uniqueCaseName.replaceAll(
"[ /?:'\"\\\\]",
"_");
753 uniqueCaseName = uniqueCaseName.toLowerCase();
758 SimpleDateFormat dateFormat =
new SimpleDateFormat(
"yyyyMMdd_HHmmss");
759 Date date =
new Date();
760 uniqueCaseName = uniqueCaseName +
"_" + dateFormat.format(date);
762 return uniqueCaseName;
773 static void createCaseDirectory(String caseDir, CaseType caseType)
throws CaseActionException {
775 File caseDirF =
new File(caseDir);
777 if (caseDirF.exists()) {
778 if (caseDirF.isFile()) {
780 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.existNotDir", caseDir));
782 }
else if (!caseDirF.canRead() || !caseDirF.canWrite()) {
783 throw new CaseActionException(
784 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.existCantRW", caseDir));
789 boolean result = (caseDirF).mkdirs();
791 if (result ==
false) {
792 throw new CaseActionException(
793 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreate", caseDir));
797 String hostClause =
"";
800 hostClause = File.separator + NetworkUtils.getLocalHostName();
802 result = result && (
new File(caseDir + hostClause + File.separator + EXPORT_FOLDER)).mkdirs()
803 && (
new File(caseDir + hostClause + File.separator + LOG_FOLDER)).mkdirs()
804 && (
new File(caseDir + hostClause + File.separator + TEMP_FOLDER)).mkdirs()
805 && (
new File(caseDir + hostClause + File.separator + CACHE_FOLDER)).mkdirs();
807 if (result ==
false) {
808 throw new CaseActionException(
809 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateCaseDir", caseDir));
812 final String modulesOutDir = caseDir + hostClause + File.separator +
MODULE_FOLDER;
813 result =
new File(modulesOutDir).mkdir();
815 if (result ==
false) {
816 throw new CaseActionException(
817 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateModDir",
821 final String reportsOutDir = caseDir + hostClause + File.separator +
REPORTS_FOLDER;
822 result =
new File(reportsOutDir).mkdir();
824 if (result ==
false) {
825 throw new CaseActionException(
826 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateReportsDir",
831 }
catch (MissingResourceException | CaseActionException e) {
832 throw new CaseActionException(
833 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.gen", caseDir), e);
844 static Map<Long, String> getImagePaths(SleuthkitCase db) {
845 Map<Long, String> imgPaths =
new HashMap<>();
847 Map<Long, List<String>> imgPathsList = db.getImagePaths();
848 for (Map.Entry<Long, List<String>> entry : imgPathsList.entrySet()) {
849 if (entry.getValue().size() > 0) {
850 imgPaths.put(entry.getKey(), entry.getValue().get(0));
853 }
catch (TskCoreException ex) {
854 logger.log(Level.SEVERE,
"Error getting image paths", ex);
868 "Case.exceptionMessage.cannotLocateMainWindow=Cannot locate main application window"
873 SwingUtilities.invokeAndWait(() -> {
874 mainFrame = WindowManager.getDefault().getMainWindow();
885 appName = mainFrame.getTitle();
887 }
catch (InterruptedException | InvocationTargetException ex) {
888 throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(Bundle.Case_exceptionMessage_cannotLocateMainWindow()), ex);
901 "Case.progressMessage.deletingCaseDirectory=Deleting case directory..."
907 progressIndicator.
start(Bundle.Case_progressMessage_deletingCaseDirectory());
909 logger.log(Level.SEVERE,
"Failed to fully delete case directory {0}", metadata.
getCaseDirectory());
916 SwingUtilities.invokeLater(() -> {
917 RecentCases.getInstance().removeRecentCase(metadata.
getCaseDisplayName(), metadata.getFilePath().toString());
932 @Messages({
"Case.creationException.couldNotAcquireResourcesLock=Failed to get lock on case resources"})
935 String resourcesNodeName = caseDir +
"_resources";
938 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock());
943 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock(), ex);
951 SwingUtilities.invokeLater(() -> {
958 if (null != backupDbPath) {
959 JOptionPane.showMessageDialog(
960 WindowManager.getDefault().getMainWindow(),
961 NbBundle.getMessage(
Case.class,
"Case.open.msgDlg.updated.msg", backupDbPath),
962 NbBundle.getMessage(
Case.class,
"Case.open.msgDlg.updated.title"),
963 JOptionPane.INFORMATION_MESSAGE);
971 Map<Long, String> imgPaths = getImagePaths(caseDb);
972 for (Map.Entry<Long, String> entry : imgPaths.entrySet()) {
973 long obj_id = entry.getKey();
974 String path = entry.getValue();
978 int response = JOptionPane.showConfirmDialog(
979 WindowManager.getDefault().getMainWindow(),
980 NbBundle.getMessage(
Case.class,
"Case.checkImgExist.confDlg.doesntExist.msg", appName, path),
981 NbBundle.getMessage(
Case.class,
"Case.checkImgExist.confDlg.doesntExist.title"),
982 JOptionPane.YES_NO_OPTION);
983 if (response == JOptionPane.YES_OPTION) {
984 MissingImageDialog.makeDialog(obj_id, caseDb);
986 logger.log(Level.SEVERE,
"User proceeding with missing image files");
1000 CallableSystemAction
1001 .get(CasePropertiesAction.class
1003 CallableSystemAction
1004 .get(CaseDeleteAction.class
1006 CallableSystemAction
1009 CallableSystemAction
1011 ).setEnabled(
false);
1018 RecentCases.getInstance().addRecentCase(newCurrentCase.
getDisplayName(), newCurrentCase.getCaseMetadata().getFilePath().toString());
1024 if (newCurrentCase.
hasData()) {
1040 SwingUtilities.invokeLater(() -> {
1051 CallableSystemAction
1053 ).setEnabled(
false);
1054 CallableSystemAction
1056 ).setEnabled(
false);
1057 CallableSystemAction
1058 .get(CasePropertiesAction.class
1059 ).setEnabled(
false);
1060 CallableSystemAction
1061 .get(CaseDeleteAction.class
1062 ).setEnabled(
false);
1063 CallableSystemAction
1065 ).setEnabled(
false);
1066 CallableSystemAction
1068 ).setEnabled(
false);
1080 Frame mainWindow = WindowManager.getDefault().getMainWindow();
1081 mainWindow.setTitle(appName);
1091 if (!caseName.isEmpty()) {
1092 Frame frame = WindowManager.getDefault().getMainWindow();
1093 frame.setTitle(caseName +
" - " + appName);
1101 File tempFolder =
new File(tempSubDirPath);
1102 if (tempFolder.isDirectory()) {
1103 File[] files = tempFolder.listFiles();
1104 if (files.length > 0) {
1105 for (File file : files) {
1106 if (file.isDirectory()) {
1149 return getCaseMetadata().getCreatedDate();
1176 return caseMetadata.getCaseNumber();
1185 return caseMetadata.getExaminer();
1194 return caseMetadata.getCaseDirectory();
1211 hostPath = Paths.get(caseDirectory);
1213 if (!hostPath.toFile().exists()) {
1214 hostPath.toFile().mkdirs();
1216 return hostPath.toString();
1289 return path.subpath(path.getNameCount() - 2, path.getNameCount()).toString();
1291 return path.subpath(path.getNameCount() - 1, path.getNameCount()).toString();
1305 List<Content> list = caseDb.getRootObjects();
1306 hasDataSources = (list.size() > 0);
1316 Set<TimeZone> timezones =
new HashSet<>();
1320 if ((dataSource != null) && (dataSource instanceof
Image)) {
1321 Image image = (Image) dataSource;
1322 timezones.add(TimeZone.getTimeZone(image.
getTimeZone()));
1326 logger.log(Level.SEVERE,
"Error getting data source time zones", ex);
1339 getCaseMetadata().setTextIndexName(textIndexName);
1358 if (!hasDataSources) {
1362 logger.log(Level.SEVERE,
"Error accessing case database", ex);
1467 String normalizedLocalPath;
1469 normalizedLocalPath = Paths.get(localPath).normalize().toString();
1470 }
catch (InvalidPathException ex) {
1471 String errorMsg =
"Invalid local path provided: " + localPath;
1474 Report report = this.caseDb.addReport(normalizedLocalPath, srcModuleName, reportName);
1487 return this.caseDb.getAllReports();
1499 for (
Report report : reports) {
1500 this.caseDb.deleteReport(report);
1522 void updateCaseName(String oldCaseName, String oldPath, String newCaseName, String newPath)
throws CaseActionException {
1524 caseMetadata.setCaseDisplayName(newCaseName);
1525 eventPublisher.
publish(
new AutopsyEvent(Events.NAME.toString(), oldCaseName, newCaseName));
1526 SwingUtilities.invokeLater(() -> {
1528 RecentCases.getInstance().updateRecentCase(oldCaseName, oldPath, newCaseName, newPath);
1531 }
catch (Exception ex) {
1532 Logger.getLogger(
Case.class
1533 .getName()).log(Level.SEVERE,
"Error updating case name in UI", ex);
1536 }
catch (CaseMetadataException ex) {
1537 throw new CaseActionException(NbBundle.getMessage(
this.getClass(),
"Case.updateCaseName.exception.msg"), ex);
1565 "Case.progressIndicatorTitle.creatingCase=Creating Case",
1566 "Case.progressIndicatorCancelButton.label=Cancel",
1567 "Case.progressMessage.preparing=Preparing...",
1568 "Case.progressMessage.openingCaseResources=<html>Preparing to open case resources.<br>This may take time if another user is upgrading the case.</html>"
1570 private void create(CaseType caseType, String caseDir, String caseDisplayName, String caseNumber, String examiner)
throws CaseActionException {
1580 Bundle.Case_progressIndicatorTitle_creatingCase(),
1581 new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
1582 Bundle.Case_progressIndicatorCancelButton_label(),
1587 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
1596 caseLockingExecutor = Executors.newSingleThreadExecutor();
1597 Future<Void> future = caseLockingExecutor.submit(() -> {
1598 if (CaseType.SINGLE_USER_CASE == caseType) {
1599 create(caseType, caseDir, caseDisplayName, caseNumber, examiner, progressIndicator);
1606 progressIndicator.start(Bundle.Case_progressMessage_openingCaseResources());
1607 acquireSharedCaseDirLock(caseDir);
1614 try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(caseDir)) {
1615 assert (null != resourcesLock);
1617 create(caseType, caseDir, caseDisplayName, caseNumber, examiner, progressIndicator);
1618 } catch (CaseActionException ex) {
1623 if (CaseType.MULTI_USER_CASE == caseType) {
1624 releaseSharedCaseDirLock(caseDir);
1639 listener.setCaseActionFuture(future);
1648 }
catch (InterruptedException ex) {
1649 throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getMessage()), ex);
1650 }
catch (ExecutionException ex) {
1651 throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getCause().getMessage()), ex);
1652 }
catch (CancellationException ex) {
1653 throw new CaseActionException(Bundle.Case_exceptionMessage_cancelled(), ex);
1655 if (RuntimeProperties.runningWithGUI()) {
1656 SwingUtilities.invokeLater(() -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(
false));
1683 "Case.exceptionMessage.emptyCaseName=Case name is empty.",
1684 "Case.progressMessage.creatingCaseDirectory=Creating case directory...",
1685 "Case.progressMessage.creatingCaseDatabase=Creating case database...",
1686 "Case.exceptionMessage.couldNotCreateCaseDatabaseName=Failed to create case database name from case name.",
1687 "Case.progressMessage.creatingCaseMetadataFile=Creating case metadata file...",
1688 "Case.exceptionMessage.couldNotCreateMetadataFile=Failed to create case metadata file.",
1689 "Case.exceptionMessage.couldNotCreateCaseDatabase=Failed to create case database."
1695 if (caseDisplayName.isEmpty()) {
1698 String caseName = displayNameToUniqueName(caseDisplayName);
1720 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDirectory());
1721 if (
new File(caseDir).exists() ==
false) {
1722 Case.createCaseDirectory(caseDir, caseType);
1728 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDatabase());
1729 String dbName = null;
1731 if (CaseType.SINGLE_USER_CASE == caseType) {
1737 dbName = SINGLE_USER_CASE_DB_NAME;
1739 }
else if (CaseType.MULTI_USER_CASE == caseType) {
1749 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseDatabase(), ex);
1757 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseMetadataFile());
1759 this.caseMetadata =
new CaseMetadata(caseDir, caseType, caseName, caseDisplayName, caseNumber, examiner, dbName);
1761 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateMetadataFile(), ex);
1764 openServices(progressIndicator);
1784 throw new CaseActionException(Bundle.Case_openException_couldNotOpenCase(Bundle.Case_exceptionMessage_failedToReadMetadata()), ex);
1796 Bundle.Case_progressIndicatorTitle_openingCase(),
1797 new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
1798 Bundle.Case_progressIndicatorCancelButton_label(),
1803 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
1812 CaseType caseType = caseMetadata.getCaseType();
1813 String caseName = caseMetadata.getCaseName();
1814 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
1815 caseLockingExecutor = Executors.newSingleThreadExecutor();
1816 Future<Void> future = caseLockingExecutor.submit(() -> {
1817 if (CaseType.SINGLE_USER_CASE == caseType) {
1818 openCaseDatabase(progressIndicator);
1819 openServices(progressIndicator);
1826 progressIndicator.start(Bundle.Case_progressMessage_openingCaseResources());
1827 acquireSharedCaseDirLock(caseMetadata.getCaseDirectory());
1833 try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(caseMetadata.getCaseDirectory())) {
1834 assert (null != resourcesLock);
1836 openCaseDatabase(progressIndicator);
1837 openServices(progressIndicator);
1838 } catch (CaseActionException ex) {
1843 if (CaseType.MULTI_USER_CASE == caseType) {
1844 releaseSharedCaseDirLock(caseName);
1859 listener.setCaseActionFuture(future);
1869 }
catch (InterruptedException ex) {
1870 throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getMessage()), ex);
1871 }
catch (ExecutionException ex) {
1872 throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getCause().getMessage()), ex);
1873 }
catch (CancellationException ex) {
1874 throw new CaseActionException(Bundle.Case_exceptionMessage_cancelled(), ex);
1876 if (RuntimeProperties.runningWithGUI()) {
1877 SwingUtilities.invokeLater(() -> ((ModalDialogProgressIndicator) progressIndicator).setVisible(
false));
1893 "Case.progressMessage.openingCaseDatabase=Opening case database...",
1894 "Case.exceptionMessage.couldNotOpenCaseDatabase=Failed to open case database."
1901 progressIndicator.
progress(Bundle.Case_progressMessage_openingCaseDatabase());
1902 if (CaseType.SINGLE_USER_CASE == caseMetadata.getCaseType()) {
1903 this.caseDb =
SleuthkitCase.
openCase(Paths.get(caseMetadata.getCaseDirectory(), caseMetadata.getCaseDatabaseName()).toString());
1913 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.open.exception.multiUserCaseNotEnabled"));
1916 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotOpenCaseDatabase(), ex);
1929 "Case.progressMessage.switchingLogDirectory=Switching log directory...",
1930 "Case.progressMessage.settingUpTskErrorReporting=Setting up SleuthKit error reporting...",
1931 "Case.progressMessage.openingCaseLevelServices=Opening case-level services...",
1932 "Case.progressMessage.openingApplicationServiceResources=Opening application service case resources...",
1933 "Case.progressMessage.settingUpNetworkCommunications=Setting up network communications...",})
1939 progressIndicator.
progress(Bundle.Case_progressMessage_switchingLogDirectory());
1945 progressIndicator.
progress(Bundle.Case_progressMessage_settingUpTskErrorReporting());
1946 this.sleuthkitErrorReporter =
new SleuthkitErrorReporter(MIN_SECS_BETWEEN_TSK_ERROR_REPORTS, NbBundle.getMessage(
Case.class,
"IntervalErrorReport.ErrorText"));
1947 this.caseDb.addErrorObserver(this.sleuthkitErrorReporter);
1952 progressIndicator.
progress(Bundle.Case_progressMessage_clearingTempDirectory());
1958 progressIndicator.
progress(Bundle.Case_progressMessage_openingCaseLevelServices());
1959 this.caseServices =
new Services(this.caseDb);
1965 progressIndicator.
progress(Bundle.Case_progressMessage_openingApplicationServiceResources());
1966 openAppServiceCaseResources();
1972 if (CaseType.MULTI_USER_CASE ==
this.caseMetadata.getCaseType()) {
1973 progressIndicator.
progress(Bundle.Case_progressMessage_settingUpNetworkCommunications());
1976 collaborationMonitor =
new CollaborationMonitor(this.getName());
1983 logger.log(Level.SEVERE,
"Failed to setup network communications", ex);
1986 SwingUtilities.invokeLater(() ->
MessageNotifyUtil.
Notify.
error(NbBundle.getMessage(
Case.class,
"Case.CollaborationSetup.FailNotify.Title"), NbBundle.getMessage(
Case.class,
"Case.CollaborationSetup.FailNotify.ErrMsg")));
1998 @NbBundle.Messages({
1999 "# {0} - service name",
"Case.serviceOpenCaseResourcesProgressIndicator.title={0} Opening Case Resources",
2000 "# {0} - service name",
"Case.servicesException.notificationTitle={0} Error",
2001 "# {0} - service name",
"Case.servicesException.serviceResourcesOpenCancelled=Opening case resources for {0} cancelled",
2002 "# {0} - service name",
"# {1} - exception message",
"Case.servicesException.serviceResourcesOpenError=Could not open case resources for {0} service: {1}"
2009 ExecutorService executor = Executors.newSingleThreadExecutor();
2017 Bundle.Case_serviceOpenCaseResourcesProgressIndicator_title(service.getServiceName()),
2018 new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
2019 Bundle.Case_progressIndicatorCancelButton_label(),
2024 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
2030 Future<Void> future = executor.submit(() -> {
2031 service.openCaseResources(context);
2040 }
catch (InterruptedException ex) {
2041 Case.
logger.log(Level.SEVERE, String.format(
"Unexpected interrupt while waiting on %s service to open case resources", service.getServiceName()), ex);
2043 }
catch (CancellationException ex) {
2049 Case.
logger.log(Level.WARNING, String.format(
"%s service opening of case resources cancelled", service.getServiceName()));
2052 Bundle.Case_servicesException_notificationTitle(service.getServiceName()),
2053 Bundle.Case_servicesException_serviceResourcesOpenCancelled(service.getServiceName())));
2055 }
catch (ExecutionException ex) {
2061 Case.
logger.log(Level.SEVERE, String.format(
"%s service failed to open case resources", service.getServiceName()), ex);
2064 Bundle.Case_servicesException_notificationTitle(service.getServiceName()),
2065 Bundle.Case_servicesException_serviceResourcesOpenError(service.getServiceName(), ex.getLocalizedMessage())));
2076 executor.shutdown();
2085 "Case.progressMessage.closingCaseResources=<html>Preparing to close case resources.<br>This may take time if another user is upgrading the case.</html>",
2086 "Case.progressMessage.notifyingCaseEventSubscribers=Notifying case event subscribers...",
2087 "Case.progressMessage.clearingTempDirectory=Clearing case temp directory...",
2088 "Case.progressMessage.closingCaseLevelServices=Closing case-level services...",
2089 "Case.progressMessage.closingApplicationServiceResources=Closing case-specific application service resources...",
2090 "Case.progressMessage.tearingDownNetworkCommunications=Tearing down network communications...",
2091 "Case.progressMessage.closingCaseDatabase=Closing case database...",
2092 "Case.progressMessage.tearingDownTskErrorReporting=Tearing down SleuthKit error reporting..."
2103 Bundle.Case_progressIndicatorTitle_closingCase());
2107 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
2116 Future<Void> future = caseLockingExecutor.submit(() -> {
2117 if (CaseType.SINGLE_USER_CASE == caseMetadata.getCaseType()) {
2118 close(progressIndicator);
2120 String caseName = caseMetadata.getCaseName();
2126 progressIndicator.
start(Bundle.Case_progressMessage_closingCaseResources());
2127 try (
CoordinationService.
Lock resourcesLock = acquireExclusiveCaseResourcesLock(caseMetadata.getCaseDirectory())) {
2128 assert (null != resourcesLock);
2129 close(progressIndicator);
2135 releaseSharedCaseDirLock(caseName);
2151 logger.log(Level.INFO,
"Closing case with metadata file path {0}", getCaseMetadata().getFilePath());
2153 }
catch (InterruptedException ex) {
2154 throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getMessage()), ex);
2155 }
catch (ExecutionException ex) {
2156 throw new CaseActionException(Bundle.Case_exceptionMessage_wrapperMessage(ex.getCause().getMessage()), ex);
2157 }
catch (CancellationException ex) {
2160 caseLockingExecutor.shutdown();
2174 if (CaseType.MULTI_USER_CASE == caseMetadata.getCaseType()) {
2175 progressIndicator.
progress(Bundle.Case_progressMessage_tearingDownNetworkCommunications());
2176 if (null != collaborationMonitor) {
2177 collaborationMonitor.shutdown();
2186 progressIndicator.
progress(Bundle.Case_progressMessage_closingApplicationServiceResources());
2187 closeAppServiceCaseResources();
2192 progressIndicator.
progress(Bundle.Case_progressMessage_closingCaseLevelServices());
2194 this.caseServices.close();
2195 }
catch (IOException ex) {
2196 logger.log(Level.SEVERE, String.format(
"Error closing internal case services for %s at %s",
this.getName(), this.getCaseDirectory()), ex);
2202 progressIndicator.
progress(Bundle.Case_progressMessage_closingCaseDatabase());
2208 progressIndicator.
progress(Bundle.Case_progressMessage_tearingDownTskErrorReporting());
2209 caseDb.removeErrorObserver(sleuthkitErrorReporter);
2214 progressIndicator.
progress(Bundle.Case_progressMessage_switchingLogDirectory());
2223 "# {0} - serviceName",
"Case.serviceCloseResourcesProgressIndicator.title={0} Closing Case Resources",
2224 "# {0} - service name",
"# {1} - exception message",
"Case.servicesException.serviceResourcesCloseError=Could not close case resources for {0} service: {1}"
2231 ExecutorService executor = Executors.newSingleThreadExecutor();
2239 Bundle.Case_serviceCloseResourcesProgressIndicator_title(service.getServiceName()));
2243 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
2246 Future<Void> future = executor.submit(() -> {
2247 service.closeCaseResources(context);
2255 }
catch (InterruptedException ex) {
2256 Case.
logger.log(Level.SEVERE, String.format(
"Unexpected interrupt while waiting on %s service to close case resources", service.getServiceName()), ex);
2258 }
catch (CancellationException ex) {
2259 Case.
logger.log(Level.SEVERE, String.format(
"Unexpected cancellation while waiting on %s service to close case resources", service.getServiceName()), ex);
2261 }
catch (ExecutionException ex) {
2262 Case.
logger.log(Level.SEVERE, String.format(
"%s service failed to open case resources", service.getServiceName()), ex);
2265 Bundle.Case_servicesException_notificationTitle(service.getServiceName()),
2266 Bundle.Case_servicesException_serviceResourcesCloseError(service.getServiceName(), ex.getLocalizedMessage())));
2277 executor.shutdown();
2288 @Messages({
"Case.creationException.couldNotAcquireDirLock=Failed to get lock on case directory."})
2292 if (null == caseDirLock) {
2296 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireDirLock(), ex);
2306 if (caseDirLock != null) {
2308 caseDirLock.release();
2311 logger.log(Level.SEVERE, String.format(
"Failed to release shared case directory lock for %s", caseDir), ex);
2323 File subDirectory = Paths.get(getOutputDirectory(), subDirectoryName).toFile();
2324 if (!subDirectory.exists()) {
2325 subDirectory.mkdirs();
2327 return subDirectory.toString();
2337 this.caseActionFuture = caseActionFuture;
2341 this.caseContext = caseContext;
2346 if (null != this.caseContext) {
2349 if (null != this.caseActionFuture) {
2350 this.caseActionFuture.cancel(
true);
2377 createAsCurrentCase(caseDir, caseDisplayName, caseNumber, examiner, CaseType.SINGLE_USER_CASE);
2401 public static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner, CaseType caseType)
throws CaseActionException {
2402 createAsCurrentCase(caseDir, caseDisplayName, caseNumber, examiner, caseType);
2418 openAsCurrentCase(caseMetadataFilePath);
2474 return new File(filePath).isFile();
2499 return isCaseOpen();
2513 return "ModuleOutput";
2526 public static PropertyChangeSupport
2528 return new PropertyChangeSupport(
Case.class
2542 return getModuleDirectory();
2562 Image newDataSource = caseDb.getImageById(imgId);
2563 notifyDataSourceAdded(newDataSource, UUID.randomUUID());
2564 return newDataSource;
2566 throw new CaseActionException(NbBundle.getMessage(
this.getClass(),
"Case.addImg.exception.msg"), ex);
2579 return getTimeZones();
2594 deleteReports(reports);
String getLogDirectoryPath()
static final AutopsyEventPublisher eventPublisher
List< Content > getDataSources()
String getModuleOutputDirectoryRelativePath()
void notifyContentTagDeleted(ContentTag deletedTag)
static final int MIN_SECS_BETWEEN_TSK_ERROR_REPORTS
static CaseType fromString(String typeName)
ExecutorService caseLockingExecutor
void publishLocally(AutopsyEvent event)
void notifyBlackBoardArtifactTagDeleted(BlackboardArtifactTag deletedTag)
Set< TimeZone > getTimeZones()
Image addImage(String imgPath, long imgId, String timeZone)
static synchronized IngestManager getInstance()
static CoordinationService.Lock acquireExclusiveCaseResourcesLock(String caseDir)
static boolean runningWithGUI
static void closeCurrentCase()
String getTempDirectory()
void cancelAllIngestJobs()
static boolean existsCurrentCase()
static void removePropertyChangeListener(PropertyChangeListener listener)
static final Logger logger
void publish(AutopsyEvent event)
void create(CaseType caseType, String caseDir, String caseDisplayName, String caseNumber, String examiner)
static final int RESOURCES_LOCK_TIMOUT_HOURS
String getLocalizedDisplayName()
void progress(String message)
ADDING_DATA_SOURCE_FAILED
static final String EXPORT_FOLDER
String getCaseDirectory()
static String convertTimeZone(String timeZoneId)
static boolean driveExists(String path)
static void openCoreWindows()
void addSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
synchronized static void setLogDirectory(String directoryPath)
static void addCaseNameToMainWindowTitle(String caseName)
static final String CACHE_FOLDER
static String getAutopsyVersion()
CaseType(String typeName)
String getReportDirectory()
static boolean getIsMultiUserModeEnabled()
void addReport(String localPath, String srcModuleName, String reportName)
static void updateGUIForCaseOpened(Case newCurrentCase)
static CaseDbConnectionInfo getDatabaseConnectionInfo()
String getModulesOutputDirAbsPath()
static void cleanupDeletedCase(CaseMetadata metadata, ProgressIndicator progressIndicator)
static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner, CaseType caseType)
void closeAppServiceCaseResources()
void setTextIndexName(String textIndexName)
static final String SINGLE_USER_CASE_DB_NAME
static void deleteCase(CaseMetadata metadata)
void deleteReports(Collection<?extends Report > reports, boolean deleteFromDisk)
List< Report > getAllReports()
static void clearTempSubDir(String tempSubDirPath)
static boolean isValidName(String caseName)
void create(CaseType caseType, String caseDir, String caseDisplayName, String caseNumber, String examiner, ProgressIndicator progressIndicator)
void acquireSharedCaseDirLock(String caseDir)
CollaborationMonitor collaborationMonitor
void releaseSharedCaseDirLock(String caseDir)
static void closeCoreWindows()
static String getModulesOutputDirRelPath()
void start(String message, int totalWorkUnits)
Set< TimeZone > getTimeZone()
static final String MODULE_FOLDER
static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner)
void openCaseDatabase(ProgressIndicator progressIndicator)
void openAppServiceCaseResources()
void openServices(ProgressIndicator progressIndicator)
static void invokeStartupDialog()
void openRemoteEventChannel(String channelName)
static String displayNameToUniqueName(String caseDisplayName)
static void openAsCurrentCase(String caseMetadataFilePath)
static void removeEventSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
Lock tryGetExclusiveLock(CategoryNode category, String nodePath, int timeOut, TimeUnit timeUnit)
static void getMainWindowAndAppName()
static final int DIR_LOCK_TIMOUT_HOURS
void close(ProgressIndicator progressIndicator)
CaseMetadata caseMetadata
SleuthkitCase getSleuthkitCase()
void closeRemoteEventChannel()
void notifyBlackBoardArtifactTagAdded(BlackboardArtifactTag newTag)
static PropertyChangeSupport getPropertyChangeSupport()
String getCacheDirectory()
static void addPropertyChangeListener(PropertyChangeListener listener)
void removeSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
String getModuleDirectory()
static void removeEventSubscriber(String eventName, PropertyChangeListener subscriber)
void deleteReports(Collection<?extends Report > reports)
void notifyDataSourceAdded(Content dataSource, UUID addingDataSourceEventId)
static boolean pathExists(String filePath)
SleuthkitErrorReporter sleuthkitErrorReporter
BLACKBOARD_ARTIFACT_TAG_ADDED
static void open(String caseMetadataFilePath)
static final Object currentCaseWriteLock
String getOutputDirectory()
static void error(String title, String message)
String getOrCreateSubdirectory(String subDirectoryName)
boolean equalsName(String otherTypeName)
static final String EVENT_CHANNEL_NAME
static Case getCurrentCase()
static String getLocalHostName()
synchronized static Logger getLogger(String name)
void open(Path caseMetadataFilePath)
static SleuthkitCase openCase(String dbPath)
static String convertToAlphaNumericFormat(String timeZoneId)
static final String LOG_FOLDER
static SleuthkitCase newCase(String dbPath)
String getBackupDatabasePath()
Lock tryGetSharedLock(CategoryNode category, String nodePath, int timeOut, TimeUnit timeUnit)
static synchronized CoordinationService getInstance()
static volatile Case currentCase
static String getVersion()
String getExportDirectory()
static void updateGUIForCaseClosed()
void notifyAddingDataSource(UUID eventId)
CoordinationService.Lock caseDirLock
static void addEventSubscriber(String eventName, PropertyChangeListener subscriber)
void notifyContentTagAdded(ContentTag newTag)
static StartupWindowProvider getInstance()
static void deleteCurrentCase()
static boolean deleteDir(File dirPath)
static void createAsCurrentCase(String caseDir, String caseDisplayName, String caseNumber, String examiner, CaseType caseType)
void notifyFailedAddingDataSource(UUID addingDataSourceEventId)
static void warn(String title, String message)
static boolean isCaseOpen()
String getTextIndexName()
static final String REPORTS_FOLDER
static final String TEMP_FOLDER
BLACKBOARD_ARTIFACT_TAG_DELETED
static void addEventSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)