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.nio.file.InvalidPathException;
29 import java.nio.file.Path;
30 import java.nio.file.Paths;
31 import java.sql.Connection;
32 import java.sql.DriverManager;
33 import java.sql.SQLException;
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.ThreadFactory;
52 import java.util.concurrent.TimeUnit;
53 import java.util.logging.Level;
54 import java.util.stream.Collectors;
55 import java.util.stream.Stream;
56 import javax.annotation.concurrent.GuardedBy;
57 import javax.annotation.concurrent.ThreadSafe;
58 import javax.swing.JOptionPane;
59 import javax.swing.SwingUtilities;
60 import org.openide.util.Lookup;
61 import org.openide.util.NbBundle;
62 import org.openide.util.NbBundle.Messages;
63 import org.openide.util.actions.CallableSystemAction;
64 import org.openide.windows.WindowManager;
118 import org.
sleuthkit.datamodel.TskUnsupportedSchemaVersionException;
158 WindowManager.getDefault().invokeWhenUIReady(
new Runnable() {
161 mainFrame = WindowManager.getDefault().getMainWindow();
184 if (typeName != null) {
186 if (typeName.equalsIgnoreCase(c.toString())) {
210 "Case_caseType_singleUser=Single-user case",
211 "Case_caseType_multiUser=Multi-user case"
214 if (fromString(typeName) == SINGLE_USER_CASE) {
215 return Bundle.Case_caseType_singleUser();
217 return Bundle.Case_caseType_multiUser();
227 this.typeName = typeName;
242 return (otherTypeName == null) ?
false : typeName.equals(otherTypeName);
394 .map(Events::toString)
395 .collect(Collectors.toSet()), listener);
406 .map(Events::toString)
407 .collect(Collectors.toSet()), listener);
430 eventTypes.forEach((
Events event) -> {
475 eventTypes.forEach((
Events event) -> {
489 return !(caseName.contains(
"\\") || caseName.contains(
"/") || caseName.contains(
":")
490 || caseName.contains(
"*") || caseName.contains(
"?") || caseName.contains(
"\"")
491 || caseName.contains(
"<") || caseName.contains(
">") || caseName.contains(
"|"));
543 "Case.exceptionMessage.emptyCaseName=Must specify a case name.",
544 "Case.exceptionMessage.emptyCaseDir=Must specify a case directory path."
548 throw new CaseActionException(Bundle.Case_exceptionMessage_emptyCaseName());
550 if (caseDir.isEmpty()) {
551 throw new CaseActionException(Bundle.Case_exceptionMessage_emptyCaseDir());
570 "Case.exceptionMessage.failedToReadMetadata=Failed to read case metadata.",
571 "Case.exceptionMessage.cannotOpenMultiUserCaseNoSettings=Multi-user settings are missing (see Tools, Options, Multi-user tab), cannot open a multi-user case."
576 metadata =
new CaseMetadata(Paths.get(caseMetadataFilePath));
578 throw new CaseActionException(Bundle.Case_exceptionMessage_failedToReadMetadata(), ex);
581 throw new CaseActionException(Bundle.Case_exceptionMessage_cannotOpenMultiUserCaseNoSettings());
592 return currentCase != null;
609 throw new IllegalStateException(NbBundle.getMessage(
Case.class,
"Case.getCurCase.exception.noneOpen"), ex);
632 if (openCase == null) {
633 throw new NoCurrentCaseException(NbBundle.getMessage(
Case.class,
"Case.getCurCase.exception.noneOpen"));
648 "# {0} - exception message",
"Case.closeException.couldNotCloseCase=Error closing case: {0}",
649 "Case.progressIndicatorTitle.closingCase=Closing Case"
653 if (null == currentCase) {
659 logger.log(Level.INFO,
"Closing current case {0} ({1}) in {2}",
new Object[]{closedCase.getDisplayName(), closedCase.getName(), closedCase.getCaseDirectory()});
662 logger.log(Level.INFO,
"Closed current case {0} ({1}) in {2}",
new Object[]{closedCase.getDisplayName(), closedCase.getName(), closedCase.getCaseDirectory()});
663 }
catch (CaseActionException ex) {
684 if (null == currentCase) {
705 "Case.progressIndicatorTitle.deletingCase=Deleting Case",
706 "Case.exceptionMessage.cannotDeleteCurrentCase=Cannot delete current case, it must be closed first.",
707 "Case.progressMessage.checkingForOtherUser=Checking to see if another user has the case open...",
708 "Case.exceptionMessage.cannotGetLockToDeleteCase=Cannot delete case because it is open for another user or there is a problem with the coordination service."
714 if (null != currentCase) {
715 throw new CaseActionException(Bundle.Case_exceptionMessage_cannotDeleteCurrentCase());
731 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
740 progressIndicator.
progress(Bundle.Case_progressMessage_checkingForOtherUser());
746 if (dirLock != null) {
749 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireDirLock());
754 throw new CaseActionException(Bundle.Case_exceptionMessage_cannotGetLockToDeleteCase(), ex);
758 progressIndicator.
finish();
773 "Case.exceptionMessage.cannotLocateMainWindow=Cannot locate main application window"
777 if (null != currentCase) {
780 }
catch (CaseActionException ex) {
789 logger.log(Level.INFO,
"Opening {0} ({1}) in {2} as the current case",
new Object[]{newCurrentCase.getDisplayName(), newCurrentCase.getName(), newCurrentCase.getCaseDirectory()});
790 newCurrentCase.
open(isNewCase);
791 currentCase = newCurrentCase;
792 logger.log(Level.INFO,
"Opened {0} ({1}) in {2} as the current case",
new Object[]{newCurrentCase.getDisplayName(), newCurrentCase.getName(), newCurrentCase.getCaseDirectory()});
798 logger.log(Level.INFO, String.format(
"Cancelled opening %s (%s) in %s as the current case", newCurrentCase.
getDisplayName(), newCurrentCase.
getName(), newCurrentCase.
getCaseDirectory()));
800 }
catch (CaseActionException ex) {
801 logger.log(Level.SEVERE, String.format(
"Error opening %s (%s) in %s as the current case", newCurrentCase.
getDisplayName(), newCurrentCase.
getName(), newCurrentCase.
getCaseDirectory()), ex);
819 String uniqueCaseName = caseDisplayName.replaceAll(
"[^\\p{ASCII}]",
"_");
824 uniqueCaseName = uniqueCaseName.replaceAll(
"[\\p{Cntrl}]",
"_");
829 uniqueCaseName = uniqueCaseName.replaceAll(
"[ /?:'\"\\\\]",
"_");
834 uniqueCaseName = uniqueCaseName.toLowerCase();
839 SimpleDateFormat dateFormat =
new SimpleDateFormat(
"yyyyMMdd_HHmmss");
840 Date date =
new Date();
841 uniqueCaseName = uniqueCaseName +
"_" + dateFormat.format(date);
843 return uniqueCaseName;
856 File caseDirF =
new File(caseDir);
858 if (caseDirF.exists()) {
859 if (caseDirF.isFile()) {
860 throw new CaseActionException(
861 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.existNotDir", caseDir));
863 }
else if (!caseDirF.canRead() || !caseDirF.canWrite()) {
864 throw new CaseActionException(
865 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.existCantRW", caseDir));
870 boolean result = (caseDirF).mkdirs();
872 if (result ==
false) {
873 throw new CaseActionException(
874 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreate", caseDir));
878 String hostClause =
"";
883 result = result && (
new File(caseDir + hostClause + File.separator + EXPORT_FOLDER)).mkdirs()
884 && (
new File(caseDir + hostClause + File.separator + LOG_FOLDER)).mkdirs()
885 && (
new File(caseDir + hostClause + File.separator + TEMP_FOLDER)).mkdirs()
886 && (
new File(caseDir + hostClause + File.separator + CACHE_FOLDER)).mkdirs();
888 if (result ==
false) {
889 throw new CaseActionException(
890 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateCaseDir", caseDir));
893 final String modulesOutDir = caseDir + hostClause + File.separator +
MODULE_FOLDER;
894 result =
new File(modulesOutDir).mkdir();
896 if (result ==
false) {
897 throw new CaseActionException(
898 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateModDir",
902 final String reportsOutDir = caseDir + hostClause + File.separator +
REPORTS_FOLDER;
903 result =
new File(reportsOutDir).mkdir();
905 if (result ==
false) {
906 throw new CaseActionException(
907 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateReportsDir",
912 }
catch (MissingResourceException | CaseActionException e) {
913 throw new CaseActionException(
914 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.gen", caseDir), e);
925 static Map<Long, String> getImagePaths(SleuthkitCase db) {
926 Map<Long, String> imgPaths =
new HashMap<>();
928 Map<Long, List<String>> imgPathsList = db.getImagePaths();
929 for (Map.Entry<Long, List<String>> entry : imgPathsList.entrySet()) {
930 if (entry.getValue().size() > 0) {
931 imgPaths.put(entry.getKey(), entry.getValue().get(0));
934 }
catch (TskCoreException ex) {
935 logger.log(Level.SEVERE,
"Error getting image paths", ex);
957 "Case.progressMessage.deletingTextIndex=Deleting text index...",
958 "Case.progressMessage.deletingCaseDatabase=Deleting case database...",
959 "Case.progressMessage.deletingCaseDirectory=Deleting case directory...",
960 "Case.exceptionMessage.errorsDeletingCase=Errors occured while deleting the case. See the application log for details"
964 boolean errorsOccurred =
false;
971 progressIndicator.
progress(Bundle.Case_progressMessage_deletingCaseDatabase());
972 CaseDbConnectionInfo db;
974 Class.forName(
"org.postgresql.Driver");
975 try (Connection connection = DriverManager.getConnection(
"jdbc:postgresql://" + db.getHost() +
":" + db.getPort() +
"/postgres", db.getUserName(), db.getPassword());
976 Statement statement = connection.createStatement();) {
978 statement.execute(deleteCommand);
984 errorsOccurred =
true;
993 progressIndicator.
progress(Bundle.Case_progressMessage_deletingTextIndex());
998 searchService.deleteTextIndex(metadata);
1003 errorsOccurred =
true;
1012 progressIndicator.
progress(Bundle.Case_progressMessage_deletingCaseDirectory());
1017 errorsOccurred =
true;
1029 SwingUtilities.invokeLater(() -> {
1030 RecentCases.getInstance().removeRecentCase(metadata.
getCaseDisplayName(), metadata.getFilePath().toString());
1034 if (errorsOccurred) {
1035 throw new CaseActionException(Bundle.Case_exceptionMessage_errorsDeletingCase());
1049 @Messages({
"Case.creationException.couldNotAcquireResourcesLock=Failed to get lock on case resources"})
1052 String resourcesNodeName = caseDir +
"_resources";
1055 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock());
1058 }
catch (InterruptedException ex) {
1061 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock(), ex);
1080 SwingUtilities.invokeLater(() -> {
1086 String backupDbPath = caseDb.getBackupDatabasePath();
1087 if (null != backupDbPath) {
1088 JOptionPane.showMessageDialog(
1090 NbBundle.getMessage(
Case.class,
"Case.open.msgDlg.updated.msg", backupDbPath),
1091 NbBundle.getMessage(
Case.class,
"Case.open.msgDlg.updated.title"),
1092 JOptionPane.INFORMATION_MESSAGE);
1100 Map<Long, String> imgPaths = getImagePaths(caseDb);
1101 for (Map.Entry<Long, String> entry : imgPaths.entrySet()) {
1102 long obj_id = entry.getKey();
1103 String path = entry.getValue();
1106 int response = JOptionPane.showConfirmDialog(
1108 NbBundle.getMessage(
Case.class,
"Case.checkImgExist.confDlg.doesntExist.msg", path),
1109 NbBundle.getMessage(
Case.class,
"Case.checkImgExist.confDlg.doesntExist.title"),
1110 JOptionPane.YES_NO_OPTION);
1111 if (response == JOptionPane.YES_OPTION) {
1112 MissingImageDialog.makeDialog(obj_id, caseDb);
1114 logger.log(Level.SEVERE,
"User proceeding with missing image files");
1126 if(!denyAddDataSourcePermissions.exists()) {
1130 CallableSystemAction.get(CasePropertiesAction.class).setEnabled(
true);
1131 CallableSystemAction.get(CaseDeleteAction.class).setEnabled(
true);
1142 RecentCases.getInstance().addRecentCase(newCurrentCase.
getDisplayName(), newCurrentCase.getMetadata().getFilePath().toString());
1152 if (newCurrentCase.
hasData()) {
1171 SwingUtilities.invokeLater(() -> {
1181 CallableSystemAction.get(
AddImageAction.class).setEnabled(
false);
1183 CallableSystemAction.get(CasePropertiesAction.class).setEnabled(
false);
1184 CallableSystemAction.get(CaseDeleteAction.class).setEnabled(
false);
1209 File tempFolder =
new File(tempSubDirPath);
1210 if (tempFolder.isDirectory()) {
1211 File[] files = tempFolder.listFiles();
1212 if (files.length > 0) {
1213 for (File file : files) {
1214 if (file.isDirectory()) {
1257 return metadata.getCreatedDate();
1346 hostPath = Paths.get(caseDirectory);
1348 if (!hostPath.toFile().exists()) {
1349 hostPath.toFile().mkdirs();
1351 return hostPath.toString();
1434 return path.subpath(path.getNameCount() - 2, path.getNameCount()).toString();
1436 return path.subpath(path.getNameCount() - 1, path.getNameCount()).toString();
1450 List<Content> list = caseDb.getRootObjects();
1451 hasDataSources = (list.size() > 0);
1461 Set<TimeZone> timezones =
new HashSet<>();
1464 final Content dataSource = c.getDataSource();
1465 if ((dataSource != null) && (dataSource instanceof Image)) {
1466 Image image = (Image) dataSource;
1467 timezones.add(TimeZone.getTimeZone(image.getTimeZone()));
1470 }
catch (TskCoreException ex) {
1471 logger.log(Level.SEVERE,
"Error getting data source time zones", ex);
1493 if (!hasDataSources) {
1496 }
catch (TskCoreException ex) {
1497 logger.log(Level.SEVERE,
"Error accessing case database", ex);
1594 logger.log(Level.WARNING,
"Unable to send notifcation regarding comment change due to no current case being open", ex);
1631 public void addReport(String localPath, String srcModuleName, String reportName)
throws TskCoreException {
1632 addReport(localPath, srcModuleName, reportName, null);
1649 public Report
addReport(String localPath, String srcModuleName, String reportName, Content parent)
throws TskCoreException {
1650 String normalizedLocalPath;
1652 if (localPath.toLowerCase().contains(
"http:")) {
1653 normalizedLocalPath = localPath;
1655 normalizedLocalPath = Paths.get(localPath).normalize().toString();
1657 }
catch (InvalidPathException ex) {
1658 String errorMsg =
"Invalid local path provided: " + localPath;
1659 throw new TskCoreException(errorMsg, ex);
1661 Report report = this.caseDb.addReport(normalizedLocalPath, srcModuleName, reportName, parent);
1675 return this.caseDb.getAllReports();
1686 public void deleteReports(Collection<? extends Report> reports)
throws TskCoreException {
1687 for (Report report : reports) {
1688 this.caseDb.deleteReport(report);
1710 "Case.exceptionMessage.metadataUpdateError=Failed to update case metadata"
1712 void updateCaseDetails(CaseDetails caseDetails)
throws CaseActionException {
1715 metadata.setCaseDetails(caseDetails);
1716 }
catch (CaseMetadataException ex) {
1717 throw new CaseActionException(Bundle.Case_exceptionMessage_metadataUpdateError(), ex);
1719 if (!oldCaseDetails.getCaseNumber().equals(caseDetails.
getCaseNumber())) {
1720 eventPublisher.
publish(
new AutopsyEvent(Events.NUMBER.toString(), oldCaseDetails.getCaseNumber(), caseDetails.
getCaseNumber()));
1722 if (!oldCaseDetails.getExaminerName().equals(caseDetails.
getExaminerName())) {
1723 eventPublisher.
publish(
new AutopsyEvent(Events.NUMBER.toString(), oldCaseDetails.getExaminerName(), caseDetails.
getExaminerName()));
1726 eventPublisher.
publish(
new AutopsyEvent(Events.NAME.toString(), oldCaseDetails.getCaseDisplayName(), caseDetails.
getCaseDisplayName()));
1728 eventPublisher.
publish(
new AutopsyEvent(Events.CASE_DETAILS.toString(), oldCaseDetails, caseDetails));
1729 if (RuntimeProperties.runningWithGUI()) {
1730 SwingUtilities.invokeLater(() -> {
1733 RecentCases.getInstance().updateRecentCase(oldCaseDetails.getCaseDisplayName(), metadata.getFilePath().toString(), caseDetails.
getCaseDisplayName(), metadata.getFilePath().toString());
1734 }
catch (Exception ex) {
1735 logger.log(Level.SEVERE,
"Error updating case name in UI", ex);
1763 metadata = caseMetaData;
1782 "Case.progressIndicatorTitle.creatingCase=Creating Case",
1783 "Case.progressIndicatorTitle.openingCase=Opening Case",
1784 "Case.progressIndicatorCancelButton.label=Cancel",
1785 "Case.progressMessage.preparing=Preparing...",
1786 "Case.progressMessage.preparingToOpenCaseResources=<html>Preparing to open case resources.<br>This may take time if another user is upgrading the case.</html>",
1787 "Case.progressMessage.cancelling=Cancelling...",
1788 "Case.exceptionMessage.cancelledByUser=Cancelled by user.",
1789 "# {0} - exception message",
"Case.exceptionMessage.execExceptionWrapperMessage={0}"
1791 private void open(
boolean isNewCase)
throws CaseActionException {
1800 String progressIndicatorTitle = isNewCase ? Bundle.Case_progressIndicatorTitle_creatingCase() : Bundle.Case_progressIndicatorTitle_openingCase();
1803 progressIndicatorTitle,
1804 new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
1805 Bundle.Case_progressIndicatorCancelButton_label(),
1806 cancelButtonListener);
1810 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
1828 caseLockingExecutor = Executors.newSingleThreadExecutor(threadFactory);
1829 Future<Void> future = caseLockingExecutor.submit(() -> {
1831 open(isNewCase, progressIndicator);
1840 progressIndicator.
progress(Bundle.Case_progressMessage_preparingToOpenCaseResources());
1843 assert(resourcesLock != null);
1844 open(isNewCase, progressIndicator);
1845 }
catch (CaseActionException ex) {
1852 if (null != cancelButtonListener) {
1861 }
catch (InterruptedException discarded) {
1870 if (null != cancelButtonListener) {
1873 future.cancel(
true);
1876 }
catch (CancellationException discarded) {
1886 }
catch (ExecutionException ex) {
1895 throw new CaseActionException(Bundle.Case_exceptionMessage_execExceptionWrapperMessage(ex.getCause().getLocalizedMessage()), ex);
1897 progressIndicator.
finish();
1914 if (Thread.currentThread().isInterrupted()) {
1924 if (Thread.currentThread().isInterrupted()) {
1930 if (Thread.currentThread().isInterrupted()) {
1933 }
catch (CaseActionException ex) {
1942 }
catch (InterruptedException discarded) {
1944 close(progressIndicator);
1960 "Case.progressMessage.creatingCaseDirectory=Creating case directory...",
1961 "Case.progressMessage.creatingCaseDatabase=Creating case database...",
1962 "# {0} - exception message",
"Case.exceptionMessage.couldNotCreateCaseDatabase=Failed to create case database:\n{0}",
1963 "Case.exceptionMessage.couldNotCreateMetadataFile=Failed to create case metadata file."
1973 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDirectory());
1980 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDatabase());
1989 metadata.setCaseDatabaseName(SINGLE_USER_CASE_DB_NAME);
1997 metadata.setCaseDatabaseName(caseDb.getDatabaseName());
1999 }
catch (TskCoreException ex) {
2000 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseDatabase(ex.getLocalizedMessage()), ex);
2002 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.databaseConnectionInfo.error.msg"), ex);
2004 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateMetadataFile(), ex);
2019 "Case.progressMessage.openingCaseDatabase=Opening case database...",
2020 "Case.exceptionMessage.couldNotOpenCaseDatabase=Failed to open case database.",
2021 "Case.unsupportedSchemaVersionMessage=Unsupported DB schema version - see log for details",
2022 "Case.databaseConnectionInfo.error.msg=Error accessing database server connection info. See Tools, Options, Multi-User.",
2023 "Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. "
2024 +
"See Tools, Options, Multi-user."
2028 progressIndicator.
progress(Bundle.Case_progressMessage_openingCaseDatabase());
2031 caseDb = SleuthkitCase.openCase(Paths.get(metadata.
getCaseDirectory(), databaseName).toString());
2036 throw new CaseActionException(Case_databaseConnectionInfo_error_msg(), ex);
2039 throw new CaseActionException(Case_open_exception_multiUserCaseNotEnabled());
2041 }
catch (TskUnsupportedSchemaVersionException ex) {
2042 throw new CaseActionException(Bundle.Case_unsupportedSchemaVersionMessage(), ex);
2043 }
catch (TskCoreException ex) {
2044 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotOpenCaseDatabase(), ex);
2057 "Case.progressMessage.switchingLogDirectory=Switching log directory...",
2058 "Case.progressMessage.clearingTempDirectory=Clearing case temp directory...",
2059 "Case.progressMessage.openingCaseLevelServices=Opening case-level services...",
2060 "Case.progressMessage.openingApplicationServiceResources=Opening application service case resources...",
2061 "Case.progressMessage.settingUpNetworkCommunications=Setting up network communications...",})
2067 progressIndicator.
progress(Bundle.Case_progressMessage_switchingLogDirectory());
2069 if (Thread.currentThread().isInterrupted()) {
2076 progressIndicator.
progress(Bundle.Case_progressMessage_clearingTempDirectory());
2078 if (Thread.currentThread().isInterrupted()) {
2085 progressIndicator.
progress(Bundle.Case_progressMessage_openingCaseLevelServices());
2086 this.caseServices =
new Services(caseDb);
2087 if (Thread.currentThread().isInterrupted()) {
2095 progressIndicator.
progress(Bundle.Case_progressMessage_openingApplicationServiceResources());
2097 if (Thread.currentThread().isInterrupted()) {
2106 progressIndicator.
progress(Bundle.Case_progressMessage_settingUpNetworkCommunications());
2109 if (Thread.currentThread().isInterrupted()) {
2112 collaborationMonitor =
new CollaborationMonitor(metadata.
getCaseName());
2119 logger.log(Level.SEVERE,
"Failed to setup network communications", ex);
2122 NbBundle.getMessage(
Case.class,
"Case.CollaborationSetup.FailNotify.Title"),
2123 NbBundle.getMessage(
Case.class,
"Case.CollaborationSetup.FailNotify.ErrMsg")));
2133 @NbBundle.Messages({
2134 "# {0} - service name",
"Case.serviceOpenCaseResourcesProgressIndicator.title={0} Opening Case Resources",
2135 "# {0} - service name",
"Case.serviceOpenCaseResourcesProgressIndicator.cancellingMessage=Cancelling opening case resources by {0}...",
2136 "# {0} - service name",
"Case.servicesException.notificationTitle={0} Error"
2156 cancelButtonListener =
new CancelButtonListener(Bundle.Case_serviceOpenCaseResourcesProgressIndicator_cancellingMessage(service.getServiceName()));
2159 Bundle.Case_serviceOpenCaseResourcesProgressIndicator_title(service.getServiceName()),
2160 new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
2161 Bundle.Case_progressIndicatorCancelButton_label(),
2162 cancelButtonListener);
2166 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
2168 String threadNameSuffix = service.getServiceName().replaceAll(
"[ ]",
"-");
2169 threadNameSuffix = threadNameSuffix.toLowerCase();
2171 ExecutorService executor = Executors.newSingleThreadExecutor(threadFactory);
2172 Future<Void> future = executor.submit(() -> {
2173 service.openCaseResources(context);
2176 if (null != cancelButtonListener) {
2188 }
catch (InterruptedException discarded) {
2193 future.cancel(
true);
2194 }
catch (CancellationException discarded) {
2202 }
catch (ExecutionException ex) {
2209 Case.
logger.log(Level.SEVERE, String.format(
"%s failed to open case resources for %s", service.getServiceName(), this.
getDisplayName()), ex);
2211 SwingUtilities.invokeLater(() -> {
2223 progressIndicator.
finish();
2226 if (Thread.currentThread().isInterrupted()) {
2235 private void close() throws CaseActionException {
2244 Bundle.Case_progressIndicatorTitle_closingCase());
2248 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
2257 Future<Void> future = caseLockingExecutor.submit(() -> {
2259 close(progressIndicator);
2266 progressIndicator.
progress(Bundle.Case_progressMessage_preparing());
2268 assert (null != resourcesLock);
2269 close(progressIndicator);
2283 }
catch (InterruptedException | CancellationException unused) {
2290 }
catch (ExecutionException ex) {
2291 throw new CaseActionException(Bundle.Case_exceptionMessage_execExceptionWrapperMessage(ex.getCause().getMessage()), ex);
2294 progressIndicator.
finish();
2304 "Case.progressMessage.shuttingDownNetworkCommunications=Shutting down network communications...",
2305 "Case.progressMessage.closingApplicationServiceResources=Closing case-specific application service resources...",
2306 "Case.progressMessage.closingCaseLevelServices=Closing case-level services...",
2307 "Case.progressMessage.closingCaseDatabase=Closing case database..."
2317 progressIndicator.
progress(Bundle.Case_progressMessage_shuttingDownNetworkCommunications());
2318 if (null != collaborationMonitor) {
2319 collaborationMonitor.shutdown();
2328 progressIndicator.
progress(Bundle.Case_progressMessage_closingApplicationServiceResources());
2334 if (null != caseServices) {
2335 progressIndicator.
progress(Bundle.Case_progressMessage_closingCaseLevelServices());
2337 this.caseServices.
close();
2338 }
catch (IOException ex) {
2339 logger.log(Level.SEVERE, String.format(
"Error closing internal case services for %s at %s",
this.getName(), this.
getCaseDirectory()), ex);
2346 if (null != caseDb) {
2347 progressIndicator.
progress(Bundle.Case_progressMessage_closingCaseDatabase());
2354 progressIndicator.
progress(Bundle.Case_progressMessage_switchingLogDirectory());
2363 "# {0} - serviceName",
"Case.serviceCloseResourcesProgressIndicator.title={0} Closing Case Resources",
2364 "# {0} - service name",
"# {1} - exception message",
"Case.servicesException.serviceResourcesCloseError=Could not close case resources for {0} service: {1}"
2376 Bundle.Case_serviceCloseResourcesProgressIndicator_title(service.getServiceName()));
2380 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
2382 String threadNameSuffix = service.getServiceName().replaceAll(
"[ ]",
"-");
2383 threadNameSuffix = threadNameSuffix.toLowerCase();
2385 ExecutorService executor = Executors.newSingleThreadExecutor(threadFactory);
2386 Future<Void> future = executor.submit(() -> {
2387 service.closeCaseResources(context);
2392 }
catch (InterruptedException ex) {
2393 Case.
logger.log(Level.SEVERE, String.format(
"Unexpected interrupt while waiting on %s service to close case resources", service.getServiceName()), ex);
2394 }
catch (CancellationException ex) {
2395 Case.
logger.log(Level.SEVERE, String.format(
"Unexpected cancellation while waiting on %s service to close case resources", service.getServiceName()), ex);
2396 }
catch (ExecutionException ex) {
2397 Case.
logger.log(Level.SEVERE, String.format(
"%s service failed to open case resources", service.getServiceName()), ex);
2400 Bundle.Case_servicesException_notificationTitle(service.getServiceName()),
2401 Bundle.Case_servicesException_serviceResourcesCloseError(service.getServiceName(), ex.getLocalizedMessage())));
2405 progressIndicator.
finish();
2418 @Messages({
"Case.creationException.couldNotAcquireDirLock=Failed to get lock on case directory"})
2423 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireDirLock());
2426 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireDirLock(), ex);
2441 logger.log(Level.SEVERE, String.format(
"Failed to release shared case directory lock for %s", caseDir), ex);
2454 if (!subDirectory.exists()) {
2455 subDirectory.mkdirs();
2457 return subDirectory.toString();
2548 ((ModalDialogProgressIndicator) progressIndicator).setCancelling(cancellationMessage);
2577 return new Thread(task, threadName);
2614 public static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner)
throws CaseActionException {
2639 public static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner,
CaseType caseType)
throws CaseActionException {
2655 public static void open(String caseMetadataFilePath)
throws CaseActionException {
2712 return new File(filePath).isFile();
2751 return "ModuleOutput";
2764 public static PropertyChangeSupport
2766 return new PropertyChangeSupport(
Case.class
2798 public Image
addImage(String imgPath,
long imgId, String timeZone)
throws CaseActionException {
2800 Image newDataSource = caseDb.getImageById(imgId);
2802 return newDataSource;
2803 }
catch (TskCoreException ex) {
2804 throw new CaseActionException(NbBundle.getMessage(
this.getClass(),
"Case.addImg.exception.msg"), ex);
2831 public void deleteReports(Collection<? extends Report> reports,
boolean deleteFromDisk)
throws TskCoreException {
String getLogDirectoryPath()
static final AutopsyEventPublisher eventPublisher
List< Content > getDataSources()
String getModuleOutputDirectoryRelativePath()
void notifyContentTagDeleted(ContentTag deletedTag)
Case(CaseMetadata caseMetaData)
static CaseType fromString(String typeName)
static final String CASE_ACTION_THREAD_NAME
void publishLocally(AutopsyEvent event)
static void createAsCurrentCase(CaseType caseType, String caseDir, CaseDetails caseDetails)
void notifyBlackBoardArtifactTagDeleted(BlackboardArtifactTag deletedTag)
String getExaminerPhone()
Set< TimeZone > getTimeZones()
static String getNameForTitle()
Image addImage(String imgPath, long imgId, String timeZone)
long getElapsedTimeSecs()
static synchronized IngestManager getInstance()
static CoordinationService.Lock acquireExclusiveCaseResourcesLock(String caseDir)
static boolean runningWithGUI
static void closeCurrentCase()
String getTempDirectory()
static boolean existsCurrentCase()
static void removePropertyChangeListener(PropertyChangeListener listener)
void start(String message, int totalWorkUnits)
static final Logger logger
void publish(AutopsyEvent event)
static final int RESOURCES_LOCK_TIMOUT_HOURS
String getLocalizedDisplayName()
ADDING_DATA_SOURCE_FAILED
static final String EXPORT_FOLDER
String getCaseDirectory()
static String getAppName()
void notifyTagDefinitionChanged(String changedTagName)
static volatile Frame mainFrame
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)
void notifyCentralRepoCommentChanged(long contentId, String newComment)
TaskThreadFactory(String threadName)
static final String CACHE_FOLDER
static String getAutopsyVersion()
CaseType(String typeName)
Case(CaseType caseType, String caseDir, CaseDetails caseDetails)
String getReportDirectory()
void createCaseData(ProgressIndicator progressIndicator)
static boolean getIsMultiUserModeEnabled()
void addReport(String localPath, String srcModuleName, String reportName)
static void updateGUIForCaseOpened(Case newCurrentCase)
static CaseDbConnectionInfo getDatabaseConnectionInfo()
String getModulesOutputDirAbsPath()
static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner, CaseType caseType)
void closeAppServiceCaseResources()
static final String SINGLE_USER_CASE_DB_NAME
static void deleteCase(CaseMetadata metadata)
void deleteReports(Collection<?extends Report > reports, boolean deleteFromDisk)
synchronized void closeRemoteEventChannel()
volatile ExecutorService caseLockingExecutor
List< Report > getAllReports()
static void clearTempSubDir(String tempSubDirPath)
static boolean isValidName(String caseName)
void acquireSharedCaseDirLock(String caseDir)
CollaborationMonitor collaborationMonitor
void releaseSharedCaseDirLock(String caseDir)
static void shutDownTaskExecutor(ExecutorService executor)
static void closeCoreWindows()
ProgressIndicator getProgressIndicator()
static String getModulesOutputDirRelPath()
Set< TimeZone > getTimeZone()
void openCaseData(ProgressIndicator progressIndicator)
static final String MODULE_FOLDER
static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner)
synchronized void openRemoteEventChannel(String channelName)
String getCaseDisplayName()
void openAppServiceCaseResources()
void openServices(ProgressIndicator progressIndicator)
static void invokeStartupDialog()
static String displayNameToUniqueName(String caseDisplayName)
void open(boolean isNewCase)
static void openAsCurrentCase(String caseMetadataFilePath)
static void removeEventSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
Lock tryGetExclusiveLock(CategoryNode category, String nodePath, int timeOut, TimeUnit timeUnit)
static final int DIR_LOCK_TIMOUT_HOURS
void close(ProgressIndicator progressIndicator)
SleuthkitCase getSleuthkitCase()
void notifyBlackBoardArtifactTagAdded(BlackboardArtifactTag newTag)
static PropertyChangeSupport getPropertyChangeSupport()
String getCacheDirectory()
static void addPropertyChangeListener(PropertyChangeListener listener)
void removeSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
String getModuleDirectory()
Thread newThread(Runnable task)
static void removeEventSubscriber(String eventName, PropertyChangeListener subscriber)
final CaseMetadata metadata
void deleteReports(Collection<?extends Report > reports)
void notifyDataSourceAdded(Content dataSource, UUID addingDataSourceEventId)
Report addReport(String localPath, String srcModuleName, String reportName, Content parent)
static boolean pathExists(String filePath)
BLACKBOARD_ARTIFACT_TAG_ADDED
static void open(String caseMetadataFilePath)
static void openAsCurrentCase(Case newCurrentCase, boolean isNewCase)
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)
static Case getCurrentCaseThrows()
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
static String convertToAlphaNumericFormat(String timeZoneId)
static final String LOG_FOLDER
Lock tryGetSharedLock(CategoryNode category, String nodePath, int timeOut, TimeUnit timeUnit)
String getConfigDirectory()
static String getAppName()
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)
void cancelAllIngestJobs(IngestJob.CancellationReason reason)
static final String CASE_RESOURCES_THREAD_NAME
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 final String CONFIG_FOLDER
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
static final Object caseActionSerializationLock
void open(boolean isNewCase, ProgressIndicator progressIndicator)
static boolean isCaseOpen()
String getTextIndexName()
static final String REPORTS_FOLDER
void progress(String message)
static void createCaseDirectory(String caseDir, CaseType caseType)
static final String TEMP_FOLDER
BLACKBOARD_ARTIFACT_TAG_DELETED
static void addEventSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
static void deleteCase(CaseMetadata metadata, ProgressIndicator progressIndicator)
static void error(String message)
String getExaminerEmail()