19 package org.sleuthkit.autopsy.casemodule;
22 import com.google.common.annotations.Beta;
23 import com.google.common.eventbus.Subscribe;
24 import com.google.common.util.concurrent.ThreadFactoryBuilder;
26 import java.awt.Frame;
27 import java.awt.event.ActionEvent;
28 import java.awt.event.ActionListener;
29 import java.beans.PropertyChangeListener;
30 import java.beans.PropertyChangeSupport;
32 import java.nio.file.InvalidPathException;
33 import java.nio.file.Path;
34 import java.nio.file.Paths;
35 import java.sql.Connection;
36 import java.sql.DriverManager;
37 import java.sql.ResultSet;
38 import java.sql.SQLException;
39 import java.sql.Statement;
40 import java.text.SimpleDateFormat;
41 import java.util.Collection;
42 import java.util.Date;
43 import java.util.HashMap;
44 import java.util.HashSet;
45 import java.util.List;
48 import java.util.TimeZone;
49 import java.util.UUID;
50 import java.util.concurrent.CancellationException;
51 import java.util.concurrent.ExecutionException;
52 import java.util.concurrent.ExecutorService;
53 import java.util.concurrent.Executors;
54 import java.util.concurrent.Future;
55 import java.util.concurrent.ThreadFactory;
56 import java.util.concurrent.TimeUnit;
57 import java.util.logging.Level;
58 import java.util.stream.Collectors;
59 import java.util.stream.Stream;
60 import javax.annotation.concurrent.GuardedBy;
61 import javax.annotation.concurrent.ThreadSafe;
62 import javax.swing.JOptionPane;
63 import javax.swing.SwingUtilities;
64 import org.openide.util.Lookup;
65 import org.openide.util.NbBundle;
66 import org.openide.util.NbBundle.Messages;
67 import org.openide.util.actions.CallableSystemAction;
68 import org.openide.windows.WindowManager;
137 import org.
sleuthkit.datamodel.TskUnsupportedSchemaVersionException;
163 = Executors.newSingleThreadExecutor(
new ThreadFactoryBuilder().setNameFormat(
"case-open-file-systems-%d").build());
180 WindowManager.getDefault().invokeWhenUIReady(() -> {
181 mainFrame = WindowManager.getDefault().getMainWindow();
203 if (typeName != null) {
205 if (typeName.equalsIgnoreCase(c.toString())) {
229 "Case_caseType_singleUser=Single-user case",
230 "Case_caseType_multiUser=Multi-user case"
233 if (fromString(typeName) == SINGLE_USER_CASE) {
234 return Bundle.Case_caseType_singleUser();
236 return Bundle.Case_caseType_multiUser();
246 this.typeName = typeName;
261 return (otherTypeName == null) ?
false : typeName.equals(otherTypeName);
428 @SuppressWarnings(
"deprecation")
431 for (BlackboardArtifact.Type artifactType : event.getArtifactTypes()) {
441 event.getModuleName(),
443 event.getArtifacts(artifactType)));
456 .map(Events::toString)
457 .collect(Collectors.toSet()), listener);
468 .map(Events::toString)
469 .collect(Collectors.toSet()), listener);
492 eventTypes.forEach((
Events event) -> {
537 eventTypes.forEach((
Events event) -> {
551 return !(caseName.contains(
"\\") || caseName.contains(
"/") || caseName.contains(
":")
552 || caseName.contains(
"*") || caseName.contains(
"?") || caseName.contains(
"\"")
553 || caseName.contains(
"<") || caseName.contains(
">") || caseName.contains(
"|"));
605 "Case.exceptionMessage.emptyCaseName=Must specify a case name.",
606 "Case.exceptionMessage.emptyCaseDir=Must specify a case directory path."
610 throw new CaseActionException(Bundle.Case_exceptionMessage_emptyCaseName());
612 if (caseDir.isEmpty()) {
613 throw new CaseActionException(Bundle.Case_exceptionMessage_emptyCaseDir());
632 "# {0} - exception message",
"Case.exceptionMessage.failedToReadMetadata=Failed to read case metadata:\n{0}.",
633 "Case.exceptionMessage.cannotOpenMultiUserCaseNoSettings=Multi-user settings are missing (see Tools, Options, Multi-user tab), cannot open a multi-user case."
638 metadata =
new CaseMetadata(Paths.get(caseMetadataFilePath));
640 throw new CaseActionException(Bundle.Case_exceptionMessage_failedToReadMetadata(ex.getLocalizedMessage()), ex);
643 throw new CaseActionException(Bundle.Case_exceptionMessage_cannotOpenMultiUserCaseNoSettings());
654 return currentCase != null;
671 throw new IllegalStateException(NbBundle.getMessage(
Case.class,
"Case.getCurCase.exception.noneOpen"), ex);
695 if (openCase == null) {
696 throw new NoCurrentCaseException(NbBundle.getMessage(
Case.class,
"Case.getCurCase.exception.noneOpen"));
711 "# {0} - exception message",
"Case.closeException.couldNotCloseCase=Error closing case: {0}",
712 "Case.progressIndicatorTitle.closingCase=Closing Case"
716 if (null == currentCase) {
722 logger.log(Level.INFO,
"Closing current case {0} ({1}) in {2}",
new Object[]{closedCase.getDisplayName(), closedCase.getName(), closedCase.getCaseDirectory()});
725 logger.log(Level.INFO,
"Closed current case {0} ({1}) in {2}",
new Object[]{closedCase.getDisplayName(), closedCase.getName(), closedCase.getCaseDirectory()});
726 }
catch (CaseActionException ex) {
747 if (null == currentCase) {
767 "Case.progressIndicatorTitle.deletingDataSource=Removing Data Source"
769 static void deleteDataSourceFromCurrentCase(Long dataSourceObjectID)
throws CaseActionException {
771 if (null == currentCase) {
778 CaseMetadata caseMetadata = currentCase.getMetadata();
786 Case theCase =
new Case(caseMetadata);
787 theCase.doOpenCaseAction(Bundle.Case_progressIndicatorTitle_deletingDataSource(), theCase::deleteDataSource, CaseLockType.EXCLUSIVE,
false, dataSourceObjectID);
808 "Case.progressIndicatorTitle.deletingCase=Deleting Case",
809 "Case.exceptionMessage.cannotDeleteCurrentCase=Cannot delete current case, it must be closed first.",
810 "# {0} - case display name",
"Case.exceptionMessage.deletionInterrupted=Deletion of the case {0} was cancelled."
814 if (null != currentCase) {
815 throw new CaseActionException(Bundle.Case_exceptionMessage_cannotDeleteCurrentCase());
825 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
832 }
catch (InterruptedException ex) {
838 throw new CaseActionException(Bundle.Case_exceptionMessage_deletionInterrupted(metadata.
getCaseDisplayName()), ex);
842 progressIndicator.
finish();
857 "Case.progressIndicatorTitle.creatingCase=Creating Case",
858 "Case.progressIndicatorTitle.openingCase=Opening Case",
859 "Case.exceptionMessage.cannotLocateMainWindow=Cannot locate main application window"
863 if (null != currentCase) {
866 }
catch (CaseActionException ex) {
875 logger.log(Level.INFO,
"Opening {0} ({1}) in {2} as the current case",
new Object[]{newCurrentCase.getDisplayName(), newCurrentCase.getName(), newCurrentCase.getCaseDirectory()});
876 String progressIndicatorTitle;
879 progressIndicatorTitle = Bundle.Case_progressIndicatorTitle_creatingCase();
880 openCaseAction = newCurrentCase::create;
882 progressIndicatorTitle = Bundle.Case_progressIndicatorTitle_openingCase();
883 openCaseAction = newCurrentCase::open;
886 currentCase = newCurrentCase;
887 logger.log(Level.INFO,
"Opened {0} ({1}) in {2} as the current case",
new Object[]{newCurrentCase.getDisplayName(), newCurrentCase.getName(), newCurrentCase.getCaseDirectory()});
893 logger.log(Level.INFO, String.format(
"Cancelled opening %s (%s) in %s as the current case", newCurrentCase.
getDisplayName(), newCurrentCase.
getName(), newCurrentCase.
getCaseDirectory()));
895 }
catch (CaseActionException ex) {
896 logger.log(Level.SEVERE, String.format(
"Error opening %s (%s) in %s as the current case", newCurrentCase.
getDisplayName(), newCurrentCase.
getName(), newCurrentCase.
getCaseDirectory()), ex);
914 String uniqueCaseName = caseDisplayName.replaceAll(
"[^\\p{ASCII}]",
"_");
919 uniqueCaseName = uniqueCaseName.replaceAll(
"[\\p{Cntrl}]",
"_");
924 uniqueCaseName = uniqueCaseName.replaceAll(
"[ /?:'\"\\\\]",
"_");
929 uniqueCaseName = uniqueCaseName.toLowerCase();
934 SimpleDateFormat dateFormat =
new SimpleDateFormat(
"yyyyMMdd_HHmmss");
935 Date date =
new Date();
936 uniqueCaseName = uniqueCaseName +
"_" + dateFormat.format(date);
938 return uniqueCaseName;
955 File caseDir =
new File(caseDirPath);
956 if (caseDir.exists()) {
957 if (caseDir.isFile()) {
958 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.existNotDir", caseDirPath));
959 }
else if (!caseDir.canRead() || !caseDir.canWrite()) {
960 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.existCantRW", caseDirPath));
967 if (!caseDir.mkdirs()) {
968 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreate", caseDirPath));
976 String hostPathComponent =
"";
981 Path exportDir = Paths.get(caseDirPath, hostPathComponent, EXPORT_FOLDER);
982 if (!exportDir.toFile().mkdirs()) {
983 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateCaseDir", exportDir));
986 Path logsDir = Paths.get(caseDirPath, hostPathComponent, LOG_FOLDER);
987 if (!logsDir.toFile().mkdirs()) {
988 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateCaseDir", logsDir));
991 Path cacheDir = Paths.get(caseDirPath, hostPathComponent, CACHE_FOLDER);
992 if (!cacheDir.toFile().mkdirs()) {
993 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateCaseDir", cacheDir));
996 Path moduleOutputDir = Paths.get(caseDirPath, hostPathComponent, MODULE_FOLDER);
997 if (!moduleOutputDir.toFile().mkdirs()) {
998 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateModDir", moduleOutputDir));
1001 Path reportsDir = Paths.get(caseDirPath, hostPathComponent, REPORTS_FOLDER);
1002 if (!reportsDir.toFile().mkdirs()) {
1003 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateReportsDir", reportsDir));
1014 static Map<Long, String> getImagePaths(SleuthkitCase db) {
1015 Map<Long, String> imgPaths =
new HashMap<>();
1017 Map<Long, List<String>> imgPathsList = db.getImagePaths();
1018 for (Map.Entry<Long, List<String>> entry : imgPathsList.entrySet()) {
1019 if (entry.getValue().size() > 0) {
1020 imgPaths.put(entry.getKey(), entry.getValue().get(0));
1023 }
catch (TskCoreException ex) {
1024 logger.log(Level.SEVERE,
"Error getting image paths", ex);
1040 "Case.creationException.couldNotAcquireResourcesLock=Failed to get lock on case resources"
1044 Path caseDirPath = Paths.get(caseDir);
1048 }
catch (InterruptedException ex) {
1051 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock(), ex);
1070 SwingUtilities.invokeLater(() -> {
1076 String backupDbPath = caseDb.getBackupDatabasePath();
1077 if (null != backupDbPath) {
1078 JOptionPane.showMessageDialog(
1080 NbBundle.getMessage(
Case.class,
"Case.open.msgDlg.updated.msg", backupDbPath),
1081 NbBundle.getMessage(
Case.class,
"Case.open.msgDlg.updated.title"),
1082 JOptionPane.INFORMATION_MESSAGE);
1090 Map<Long, String> imgPaths = getImagePaths(caseDb);
1091 for (Map.Entry<Long, String> entry : imgPaths.entrySet()) {
1092 long obj_id = entry.getKey();
1093 String path = entry.getValue();
1096 int response = JOptionPane.showConfirmDialog(
1098 NbBundle.getMessage(
Case.class,
"Case.checkImgExist.confDlg.doesntExist.msg", path),
1099 NbBundle.getMessage(
Case.class,
"Case.checkImgExist.confDlg.doesntExist.title"),
1100 JOptionPane.YES_NO_OPTION);
1101 if (response == JOptionPane.YES_OPTION) {
1102 MissingImageDialog.makeDialog(obj_id, caseDb);
1104 logger.log(Level.SEVERE,
"User proceeding with missing image files");
1115 CallableSystemAction.get(CaseDetailsAction.class).setEnabled(
true);
1129 RecentCases.getInstance().addRecentCase(newCurrentCase.
getDisplayName(), newCurrentCase.getMetadata().getFilePath().toString());
1139 if (newCurrentCase.
hasData()) {
1158 SwingUtilities.invokeLater(() -> {
1168 CallableSystemAction.get(
AddImageAction.class).setEnabled(
false);
1170 CallableSystemAction.get(CaseDetailsAction.class).setEnabled(
false);
1172 CallableSystemAction.get(CaseDeleteAction.class).setEnabled(
false);
1316 hostPath = Paths.get(caseDirectory);
1318 if (!hostPath.toFile().exists()) {
1319 hostPath.toFile().mkdirs();
1321 return hostPath.toString();
1334 File f = path.toFile();
1340 return path.toAbsolutePath().toString();
1413 return path.subpath(path.getNameCount() - 2, path.getNameCount()).toString();
1415 return path.subpath(path.getNameCount() - 1, path.getNameCount()).toString();
1429 return caseDb.getRootObjects();
1438 Set<TimeZone> timezones =
new HashSet<>();
1439 String query =
"SELECT time_zone FROM data_source_info";
1440 try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
1441 ResultSet timeZoneSet = dbQuery.getResultSet();
1442 while (timeZoneSet.next()) {
1443 String timeZone = timeZoneSet.getString(
"time_zone");
1444 if (timeZone != null && !timeZone.isEmpty()) {
1445 timezones.add(TimeZone.getTimeZone(timeZone));
1448 }
catch (TskCoreException | SQLException ex) {
1449 logger.log(Level.SEVERE,
"Error getting data source time zones", ex);
1471 boolean hasDataSources =
false;
1472 String query =
"SELECT count(*) AS count FROM data_source_info";
1473 try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
1474 ResultSet resultSet = dbQuery.getResultSet();
1475 if (resultSet.next()) {
1476 long numDataSources = resultSet.getLong(
"count");
1477 if (numDataSources > 0) {
1478 hasDataSources =
true;
1481 }
catch (TskCoreException | SQLException ex) {
1482 logger.log(Level.SEVERE,
"Error accessing case database", ex);
1484 return hasDataSources;
1604 logger.log(Level.WARNING,
"Unable to send notifcation regarding comment change due to no current case being open", ex);
1654 public void addReport(String localPath, String srcModuleName, String reportName)
throws TskCoreException {
1655 addReport(localPath, srcModuleName, reportName, null);
1672 public Report
addReport(String localPath, String srcModuleName, String reportName, Content parent)
throws TskCoreException {
1673 String normalizedLocalPath;
1675 if (localPath.toLowerCase().contains(
"http:")) {
1676 normalizedLocalPath = localPath;
1678 normalizedLocalPath = Paths.get(localPath).normalize().toString();
1680 }
catch (InvalidPathException ex) {
1681 String errorMsg =
"Invalid local path provided: " + localPath;
1682 throw new TskCoreException(errorMsg, ex);
1684 Report report = this.caseDb.addReport(normalizedLocalPath, srcModuleName, reportName, parent);
1698 return this.caseDb.getAllReports();
1709 public void deleteReports(Collection<? extends Report> reports)
throws TskCoreException {
1710 for (Report report : reports) {
1711 this.caseDb.deleteReport(report);
1733 "Case.exceptionMessage.metadataUpdateError=Failed to update case metadata"
1735 void updateCaseDetails(CaseDetails caseDetails)
throws CaseActionException {
1738 metadata.setCaseDetails(caseDetails);
1739 }
catch (CaseMetadataException ex) {
1740 throw new CaseActionException(Bundle.Case_exceptionMessage_metadataUpdateError(), ex);
1744 CaseNodeData nodeData = CaseNodeData.readCaseNodeData(metadata.
getCaseDirectory());
1746 CaseNodeData.writeCaseNodeData(nodeData);
1747 }
catch (CaseNodeDataException | InterruptedException ex) {
1748 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotUpdateCaseNodeData(ex.getLocalizedMessage()), ex);
1751 if (!oldCaseDetails.getCaseNumber().equals(caseDetails.
getCaseNumber())) {
1752 eventPublisher.
publish(
new AutopsyEvent(Events.NUMBER.toString(), oldCaseDetails.getCaseNumber(), caseDetails.
getCaseNumber()));
1754 if (!oldCaseDetails.getExaminerName().equals(caseDetails.
getExaminerName())) {
1755 eventPublisher.
publish(
new AutopsyEvent(Events.NUMBER.toString(), oldCaseDetails.getExaminerName(), caseDetails.
getExaminerName()));
1758 eventPublisher.
publish(
new AutopsyEvent(Events.NAME.toString(), oldCaseDetails.getCaseDisplayName(), caseDetails.
getCaseDisplayName()));
1760 eventPublisher.
publish(
new AutopsyEvent(Events.CASE_DETAILS.toString(), oldCaseDetails, caseDetails));
1761 if (RuntimeProperties.runningWithGUI()) {
1762 SwingUtilities.invokeLater(() -> {
1765 RecentCases.getInstance().updateRecentCase(oldCaseDetails.getCaseDisplayName(), metadata.getFilePath().toString(), caseDetails.
getCaseDisplayName(), metadata.getFilePath().toString());
1766 }
catch (Exception ex) {
1767 logger.log(Level.SEVERE,
"Error updating case name in UI", ex);
1795 metadata = caseMetaData;
1829 "Case.progressIndicatorCancelButton.label=Cancel",
1830 "Case.progressMessage.preparing=Preparing...",
1831 "Case.progressMessage.cancelling=Cancelling...",
1832 "Case.exceptionMessage.cancelled=Cancelled.",
1833 "# {0} - exception message",
"Case.exceptionMessage.execExceptionWrapperMessage={0}"
1843 if (allowCancellation) {
1847 progressIndicatorTitle,
1848 new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
1849 Bundle.Case_progressIndicatorCancelButton_label(),
1850 cancelButtonListener);
1854 progressIndicatorTitle);
1859 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
1868 caseActionExecutor = Executors.newSingleThreadExecutor(threadFactory);
1869 Future<Void> future = caseActionExecutor.submit(() -> {
1871 caseAction.
execute(progressIndicator, additionalParams);
1875 if (null == resourcesLock) {
1876 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock());
1878 caseAction.
execute(progressIndicator, additionalParams);
1879 }
catch (CaseActionException ex) {
1886 if (null != cancelButtonListener) {
1895 }
catch (InterruptedException discarded) {
1899 if (null != cancelButtonListener) {
1902 future.cancel(
true);
1905 }
catch (CancellationException discarded) {
1911 }
catch (ExecutionException ex) {
1916 throw new CaseActionException(Bundle.Case_exceptionMessage_execExceptionWrapperMessage(ex.getCause().getLocalizedMessage()), ex);
1918 progressIndicator.
finish();
1938 assert (additionalParams == null);
1959 }
catch (CaseActionException ex) {
1968 }
catch (InterruptedException discarded) {
1970 close(progressIndicator);
1990 assert (additionalParams == null);
2010 }
catch (CaseActionException ex) {
2019 }
catch (InterruptedException discarded) {
2021 close(progressIndicator);
2036 "# {0} - case",
"Case.openFileSystems.retrievingImages=Retrieving images for case: {0}...",
2037 "# {0} - image",
"Case.openFileSystems.openingImage=Opening all filesystems for image: {0}..."
2040 if (backgroundOpenFileSystemsFuture != null && !backgroundOpenFileSystemsFuture.isDone()) {
2041 backgroundOpenFileSystemsFuture.cancel(
true);
2070 caseName = (this.tskCase != null) ? this.tskCase.getDatabaseName() :
"";
2081 if (Thread.interrupted()) {
2082 throw new InterruptedException();
2092 progressIndicator.
progress(Bundle.Case_openFileSystems_retrievingImages(caseName));
2094 return this.tskCase.getImages();
2095 }
catch (TskCoreException ex) {
2098 String.format(
"Could not obtain images while opening case: %s.", caseName),
2114 private void openFileSystems(List<Image> images)
throws TskCoreException, InterruptedException {
2115 byte[] tempBuff =
new byte[512];
2117 for (Image image : images) {
2118 String imageStr = image.getName();
2120 progressIndicator.
progress(Bundle.Case_openFileSystems_openingImage(imageStr));
2122 Collection<FileSystem> fileSystems = this.tskCase.getImageFileSystems(image);
2124 for (FileSystem fileSystem : fileSystems) {
2125 fileSystem.read(tempBuff, 0, 512);
2137 if (images == null) {
2145 String.format(
"Skipping background load of file systems due to large number of images in case (%d)", images.size()));
2151 }
catch (InterruptedException ex) {
2154 String.format(
"Background operation opening all file systems in %s has been cancelled.", caseName));
2155 }
catch (Exception ex) {
2157 logger.log(Level.WARNING,
"Error while opening file systems in background", ex);
2178 "Case.progressMessage.deletingDataSource=Removing the data source from the case...",
2179 "Case.exceptionMessage.dataSourceNotFound=The data source was not found.",
2180 "Case.exceptionMessage.errorDeletingDataSourceFromCaseDb=An error occurred while removing the data source from the case database.",
2181 "Case.exceptionMessage.errorDeletingDataSourceFromTextIndex=An error occurred while removing the data source from the text index.",})
2182 Void deleteDataSource(ProgressIndicator progressIndicator, Object additionalParams)
throws CaseActionException {
2183 assert (additionalParams instanceof Long);
2184 open(progressIndicator, null);
2186 progressIndicator.progress(Bundle.Case_progressMessage_deletingDataSource());
2187 Long dataSourceObjectID = (Long) additionalParams;
2189 DataSource dataSource = this.caseDb.getDataSource(dataSourceObjectID);
2190 if (dataSource == null) {
2191 throw new CaseActionException(Bundle.Case_exceptionMessage_dataSourceNotFound());
2193 SleuthkitCaseAdminUtil.deleteDataSource(this.caseDb, dataSourceObjectID);
2194 }
catch (TskDataException | TskCoreException ex) {
2195 throw new CaseActionException(Bundle.Case_exceptionMessage_errorDeletingDataSourceFromCaseDb(), ex);
2199 }
catch (KeywordSearchServiceException ex) {
2200 throw new CaseActionException(Bundle.Case_exceptionMessage_errorDeletingDataSourceFromTextIndex(), ex);
2202 eventPublisher.
publish(
new DataSourceDeletedEvent(dataSourceObjectID));
2205 close(progressIndicator);
2220 public SleuthkitCase
createPortableCase(String caseName, File portableCaseFolder)
throws TskCoreException {
2222 if (portableCaseFolder.exists()) {
2223 throw new TskCoreException(
"Portable case folder " + portableCaseFolder.toString() +
" already exists");
2225 if (!portableCaseFolder.mkdirs()) {
2226 throw new TskCoreException(
"Error creating portable case folder " + portableCaseFolder.toString());
2234 portableCaseMetadata.setCaseDatabaseName(SINGLE_USER_CASE_DB_NAME);
2236 throw new TskCoreException(
"Error creating case metadata", ex);
2240 SleuthkitCase portableSleuthkitCase;
2242 portableSleuthkitCase = SleuthkitCase.newCase(dbFilePath);
2244 return portableSleuthkitCase;
2257 if (Thread.currentThread().isInterrupted()) {
2258 throw new CaseActionCancelledException(Bundle.Case_exceptionMessage_cancelled());
2273 "Case.progressMessage.creatingCaseDirectory=Creating case directory..."
2280 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDirectory());
2282 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDirectory());
2294 "Case.progressMessage.switchingLogDirectory=Switching log directory..."
2297 progressIndicator.
progress(Bundle.Case_progressMessage_switchingLogDirectory());
2313 "Case.progressMessage.savingCaseMetadata=Saving case metadata to file...",
2314 "# {0} - exception message",
"Case.exceptionMessage.couldNotSaveCaseMetadata=Failed to save case metadata:\n{0}."
2317 progressIndicator.
progress(Bundle.Case_progressMessage_savingCaseMetadata());
2319 this.metadata.writeToFile();
2321 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotSaveCaseMetadata(ex.getLocalizedMessage()), ex);
2337 "Case.progressMessage.creatingCaseNodeData=Creating coordination service node data...",
2338 "# {0} - exception message",
"Case.exceptionMessage.couldNotCreateCaseNodeData=Failed to create coordination service node data:\n{0}."
2342 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseNodeData());
2346 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseNodeData(ex.getLocalizedMessage()), ex);
2363 "Case.progressMessage.updatingCaseNodeData=Updating coordination service node data...",
2364 "# {0} - exception message",
"Case.exceptionMessage.couldNotUpdateCaseNodeData=Failed to update coordination service node data:\n{0}."
2368 progressIndicator.
progress(Bundle.Case_progressMessage_updatingCaseNodeData());
2374 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotUpdateCaseNodeData(ex.getLocalizedMessage()), ex);
2385 "Case.progressMessage.clearingTempDirectory=Clearing case temp directory..."
2391 progressIndicator.
progress(Bundle.Case_progressMessage_clearingTempDirectory());
2407 "Case.progressMessage.creatingCaseDatabase=Creating case database...",
2408 "# {0} - exception message",
"Case.exceptionMessage.couldNotGetDbServerConnectionInfo=Failed to get case database server conneciton info:\n{0}.",
2409 "# {0} - exception message",
"Case.exceptionMessage.couldNotCreateCaseDatabase=Failed to create case database:\n{0}.",
2410 "# {0} - exception message",
"Case.exceptionMessage.couldNotSaveDbNameToMetadataFile=Failed to save case database name to case metadata file:\n{0}."
2413 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDatabase());
2422 metadata.setCaseDatabaseName(SINGLE_USER_CASE_DB_NAME);
2430 metadata.setCaseDatabaseName(caseDb.getDatabaseName());
2432 }
catch (TskCoreException ex) {
2433 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseDatabase(ex.getLocalizedMessage()), ex);
2435 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotGetDbServerConnectionInfo(ex.getLocalizedMessage()), ex);
2437 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotSaveDbNameToMetadataFile(ex.getLocalizedMessage()), ex);
2453 "Case.progressMessage.openingCaseDatabase=Opening case database...",
2454 "# {0} - exception message",
"Case.exceptionMessage.couldNotOpenCaseDatabase=Failed to open case database:\n{0}.",
2455 "# {0} - exception message",
"Case.exceptionMessage.unsupportedSchemaVersionMessage=Unsupported case database schema version:\n{0}.",
2456 "Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-User."
2459 progressIndicator.
progress(Bundle.Case_progressMessage_openingCaseDatabase());
2463 caseDb = SleuthkitCase.openCase(Paths.get(metadata.
getCaseDirectory(), databaseName).toString());
2467 throw new CaseActionException(Bundle.Case_open_exception_multiUserCaseNotEnabled());
2469 }
catch (TskUnsupportedSchemaVersionException ex) {
2470 throw new CaseActionException(Bundle.Case_exceptionMessage_unsupportedSchemaVersionMessage(ex.getLocalizedMessage()), ex);
2472 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotGetDbServerConnectionInfo(ex.getLocalizedMessage()), ex);
2473 }
catch (TskCoreException ex) {
2474 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotOpenCaseDatabase(ex.getLocalizedMessage()), ex);
2485 "Case.progressMessage.openingCaseLevelServices=Opening case-level services...",})
2487 progressIndicator.
progress(Bundle.Case_progressMessage_openingCaseLevelServices());
2488 this.caseServices =
new Services(caseDb);
2494 caseDb.registerForEvents(sleuthkitEventListener);
2509 @NbBundle.Messages({
2510 "Case.progressMessage.openingApplicationServiceResources=Opening application service case resources...",
2511 "# {0} - service name",
"Case.serviceOpenCaseResourcesProgressIndicator.title={0} Opening Case Resources",
2512 "# {0} - service name",
"Case.serviceOpenCaseResourcesProgressIndicator.cancellingMessage=Cancelling opening case resources by {0}...",
2513 "# {0} - service name",
"Case.servicesException.notificationTitle={0} Error"
2524 progressIndicator.
progress(Bundle.Case_progressMessage_openingApplicationServiceResources());
2536 cancelButtonListener =
new CancelButtonListener(Bundle.Case_serviceOpenCaseResourcesProgressIndicator_cancellingMessage(service.getServiceName()));
2539 Bundle.Case_serviceOpenCaseResourcesProgressIndicator_title(service.getServiceName()),
2540 new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
2541 Bundle.Case_progressIndicatorCancelButton_label(),
2542 cancelButtonListener);
2546 appServiceProgressIndicator.
start(Bundle.Case_progressMessage_preparing());
2548 String threadNameSuffix = service.getServiceName().replaceAll(
"[ ]",
"-");
2549 threadNameSuffix = threadNameSuffix.toLowerCase();
2551 ExecutorService executor = Executors.newSingleThreadExecutor(threadFactory);
2552 Future<Void> future = executor.submit(() -> {
2553 service.openCaseResources(context);
2556 if (null != cancelButtonListener) {
2568 }
catch (InterruptedException discarded) {
2573 future.cancel(
true);
2574 }
catch (CancellationException discarded) {
2582 }
catch (ExecutionException ex) {
2589 Case.
logger.log(Level.SEVERE, String.format(
"%s failed to open case resources for %s", service.getServiceName(), this.
getDisplayName()), ex);
2591 SwingUtilities.invokeLater(() -> {
2603 appServiceProgressIndicator.
finish();
2621 "Case.progressMessage.settingUpNetworkCommunications=Setting up network communications...",
2622 "# {0} - exception message",
"Case.exceptionMessage.couldNotOpenRemoteEventChannel=Failed to open remote events channel:\n{0}.",
2623 "# {0} - exception message",
"Case.exceptionMessage.couldNotCreatCollaborationMonitor=Failed to create collaboration monitor:\n{0}."
2627 progressIndicator.
progress(Bundle.Case_progressMessage_settingUpNetworkCommunications());
2631 collaborationMonitor =
new CollaborationMonitor(metadata.
getCaseName());
2633 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotOpenRemoteEventChannel(ex.getLocalizedMessage()), ex);
2634 }
catch (CollaborationMonitor.CollaborationMonitorException ex) {
2635 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreatCollaborationMonitor(ex.getLocalizedMessage()), ex);
2663 Bundle.Case_progressIndicatorTitle_closingCase());
2667 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
2676 Future<Void> future = caseActionExecutor.submit(() -> {
2678 close(progressIndicator);
2685 progressIndicator.
progress(Bundle.Case_progressMessage_preparing());
2687 if (null == resourcesLock) {
2688 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock());
2690 close(progressIndicator);
2704 }
catch (InterruptedException | CancellationException unused) {
2711 }
catch (ExecutionException ex) {
2712 throw new CaseActionException(Bundle.Case_exceptionMessage_execExceptionWrapperMessage(ex.getCause().getMessage()), ex);
2715 progressIndicator.
finish();
2725 "Case.progressMessage.shuttingDownNetworkCommunications=Shutting down network communications...",
2726 "Case.progressMessage.closingApplicationServiceResources=Closing case-specific application service resources...",
2727 "Case.progressMessage.closingCaseDatabase=Closing case database..."
2737 progressIndicator.
progress(Bundle.Case_progressMessage_shuttingDownNetworkCommunications());
2738 if (null != collaborationMonitor) {
2739 collaborationMonitor.shutdown();
2748 progressIndicator.
progress(Bundle.Case_progressMessage_closingApplicationServiceResources());
2754 if (null != caseDb) {
2755 progressIndicator.
progress(Bundle.Case_progressMessage_closingCaseDatabase());
2756 caseDb.unregisterForEvents(sleuthkitEventListener);
2768 progressIndicator.
progress(Bundle.Case_progressMessage_switchingLogDirectory());
2777 "# {0} - serviceName",
"Case.serviceCloseResourcesProgressIndicator.title={0} Closing Case Resources",
2778 "# {0} - service name",
"# {1} - exception message",
"Case.servicesException.serviceResourcesCloseError=Could not close case resources for {0} service: {1}"
2791 Bundle.Case_serviceCloseResourcesProgressIndicator_title(service.getServiceName()));
2795 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
2797 String threadNameSuffix = service.getServiceName().replaceAll(
"[ ]",
"-");
2798 threadNameSuffix = threadNameSuffix.toLowerCase();
2800 ExecutorService executor = Executors.newSingleThreadExecutor(threadFactory);
2801 Future<Void> future = executor.submit(() -> {
2802 service.closeCaseResources(context);
2807 }
catch (InterruptedException ex) {
2808 Case.
logger.log(Level.SEVERE, String.format(
"Unexpected interrupt while waiting on %s service to close case resources", service.getServiceName()), ex);
2809 }
catch (CancellationException ex) {
2810 Case.
logger.log(Level.SEVERE, String.format(
"Unexpected cancellation while waiting on %s service to close case resources", service.getServiceName()), ex);
2811 }
catch (ExecutionException ex) {
2812 Case.
logger.log(Level.SEVERE, String.format(
"%s service failed to open case resources", service.getServiceName()), ex);
2815 Bundle.Case_servicesException_notificationTitle(service.getServiceName()),
2816 Bundle.Case_servicesException_serviceResourcesCloseError(service.getServiceName(), ex.getLocalizedMessage())));
2820 progressIndicator.
finish();
2831 "Case.lockingException.couldNotAcquireSharedLock=Failed to get a shared lock on the case.",
2832 "Case.lockingException.couldNotAcquireExclusiveLock=Failed to get an exclusive lock on the case."
2843 throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireSharedLock());
2845 throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireExclusiveLock());
2850 throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireSharedLock(), ex);
2852 throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireExclusiveLock(), ex);
2866 logger.log(Level.SEVERE, String.format(
"Failed to release shared case directory lock for %s", getMetadata().
getCaseDirectory()), ex);
2879 if (!subDirectory.exists()) {
2880 subDirectory.mkdirs();
2882 return subDirectory.toString();
2898 "Case.exceptionMessage.errorsDeletingCase=Errors occured while deleting the case. See the application log for details."
2901 boolean errorsOccurred =
false;
2905 errorsOccurred =
true;
2911 }
catch (CaseActionException ex) {
2912 errorsOccurred =
true;
2918 if (errorsOccurred) {
2919 throw new CaseActionException(Bundle.Case_exceptionMessage_errorsDeletingCase());
2943 "Case.progressMessage.connectingToCoordSvc=Connecting to coordination service...",
2944 "# {0} - exception message",
"Case.exceptionMessage.failedToConnectToCoordSvc=Failed to connect to coordination service:\n{0}.",
2945 "Case.exceptionMessage.cannotGetLockToDeleteCase=Cannot delete case because it is open for another user or host.",
2946 "# {0} - exception message",
"Case.exceptionMessage.failedToLockCaseForDeletion=Failed to exclusively lock case for deletion:\n{0}.",
2947 "Case.progressMessage.fetchingCoordSvcNodeData=Fetching coordination service node data for the case...",
2948 "# {0} - exception message",
"Case.exceptionMessage.failedToFetchCoordSvcNodeData=Failed to fetch coordination service node data:\n{0}.",
2949 "Case.progressMessage.deletingResourcesCoordSvcNode=Deleting case resources coordination service node...",
2950 "Case.progressMessage.deletingCaseDirCoordSvcNode=Deleting case directory coordination service node..."
2953 progressIndicator.
progress(Bundle.Case_progressMessage_connectingToCoordSvc());
2959 throw new CaseActionException(Bundle.Case_exceptionMessage_failedToConnectToCoordSvc(ex.getLocalizedMessage()));
2963 boolean errorsOccurred =
false;
2965 if (dirLock == null) {
2967 throw new CaseActionException(Bundle.Case_exceptionMessage_cannotGetLockToDeleteCase());
2970 progressIndicator.
progress(Bundle.Case_progressMessage_fetchingCoordSvcNodeData());
2975 throw new CaseActionException(Bundle.Case_exceptionMessage_failedToFetchCoordSvcNodeData(ex.getLocalizedMessage()));
2980 progressIndicator.
progress(Bundle.Case_progressMessage_deletingResourcesCoordSvcNode());
2986 errorsOccurred =
true;
2987 logger.log(Level.WARNING, String.format(
"Error deleting the case resources coordination service node for the case at %s (%s) in %s", metadata.
getCaseDisplayName(), metadata.
getCaseName(), metadata.
getCaseDirectory()), ex);
2989 }
catch (InterruptedException ex) {
2990 logger.log(Level.WARNING, String.format(
"Error deleting the case resources coordination service node for the case at %s (%s) in %s", metadata.
getCaseDisplayName(), metadata.
getCaseName(), metadata.
getCaseDirectory()), ex);
2995 throw new CaseActionException(Bundle.Case_exceptionMessage_failedToLockCaseForDeletion(ex.getLocalizedMessage()));
2998 if (!errorsOccurred) {
2999 progressIndicator.
progress(Bundle.Case_progressMessage_deletingCaseDirCoordSvcNode());
3005 errorsOccurred =
true;
3009 if (errorsOccurred) {
3010 throw new CaseActionException(Bundle.Case_exceptionMessage_errorsDeletingCase());
3040 boolean errorsOccurred =
false;
3047 errorsOccurred =
true;
3050 errorsOccurred =
true;
3052 }
catch (CaseActionException ex) {
3053 errorsOccurred =
true;
3056 return errorsOccurred;
3080 "Case.progressMessage.deletingCaseDatabase=Deleting case database..."
3084 progressIndicator.
progress(Bundle.Case_progressMessage_deletingCaseDatabase());
3085 logger.log(Level.INFO, String.format(
"Deleting case database for %s (%s) in %s", caseNodeData.
getDisplayName(), caseNodeData.
getName(), caseNodeData.
getDirectory()));
3087 String url =
"jdbc:postgresql://" + info.getHost() +
":" + info.getPort() +
"/postgres";
3088 Class.forName(
"org.postgresql.Driver");
3089 try (Connection connection = DriverManager.getConnection(url, info.getUserName(), info.getPassword()); Statement statement = connection.createStatement()) {
3090 String dbExistsQuery =
"SELECT 1 from pg_database WHERE datname = '" + metadata.
getCaseDatabaseName() +
"'";
3091 try (ResultSet queryResult = statement.executeQuery(dbExistsQuery)) {
3092 if (queryResult.next()) {
3094 statement.execute(deleteCommand);
3135 "Case.progressMessage.deletingTextIndex=Deleting text index..."
3138 progressIndicator.
progress(Bundle.Case_progressMessage_deletingTextIndex());
3142 searchService.deleteTextIndex(metadata);
3178 "Case.progressMessage.deletingCaseDirectory=Deleting case directory..."
3181 progressIndicator.
progress(Bundle.Case_progressMessage_deletingCaseDirectory());
3183 throw new CaseActionException(String.format(
"Failed to delete %s", metadata.
getCaseDirectory()));
3195 "Case.progressMessage.removingCaseFromRecentCases=Removing case from Recent Cases menu..."
3199 progressIndicator.
progress(Bundle.Case_progressMessage_removingCaseFromRecentCases());
3200 SwingUtilities.invokeLater(() -> {
3201 RecentCases.getInstance().removeRecentCase(metadata.
getCaseDisplayName(), metadata.getFilePath().toString());
3216 boolean isNodeNodeEx =
false;
3217 Throwable cause = ex.getCause();
3218 if (cause != null) {
3219 String causeMessage = cause.getMessage();
3220 isNodeNodeEx = causeMessage.contains(NO_NODE_ERROR_MSG_FRAGMENT);
3222 return isNodeNodeEx;
3241 logger.log(Level.SEVERE, String.format(
"Error updating deleted item flag %s for %s (%s) in %s", flag.name(), caseNodeData.
getDisplayName(), caseNodeData.
getName(), caseNodeData.
getDirectory()), ex);
3266 R
execute(T progressIndicator, V additionalParams)
throws CaseActionException;
3364 ((ModalDialogProgressIndicator) progressIndicator).
setCancelling(cancellationMessage);
3393 return new Thread(task, threadName);
3430 public static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner)
throws CaseActionException {
3455 public static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner,
CaseType caseType)
throws CaseActionException {
3471 public static void open(String caseMetadataFilePath)
throws CaseActionException {
3528 return new File(filePath).isFile();
3567 return "ModuleOutput";
3580 public static PropertyChangeSupport
3582 return new PropertyChangeSupport(
Case.class
3614 public Image
addImage(String imgPath,
long imgId, String timeZone)
throws CaseActionException {
3616 Image newDataSource = caseDb.getImageById(imgId);
3618 return newDataSource;
3619 }
catch (TskCoreException ex) {
3620 throw new CaseActionException(NbBundle.getMessage(
this.getClass(),
"Case.addImg.exception.msg"), ex);
3647 public void deleteReports(Collection<? extends Report> reports,
boolean deleteFromDisk)
throws TskCoreException {
String getLogDirectoryPath()
static final AutopsyEventPublisher eventPublisher
List< Content > getDataSources()
String getModuleOutputDirectoryRelativePath()
static CaseNodeData createCaseNodeData(final CaseMetadata metadata)
void notifyContentTagDeleted(ContentTag deletedTag)
Case(CaseMetadata caseMetaData)
static CaseType fromString(String typeName)
final SleuthkitEventListener sleuthkitEventListener
static final String CASE_ACTION_THREAD_NAME
static void setDeletedItemFlag(CaseNodeData caseNodeData, CaseNodeData.DeletedFlags flag)
void publishLocally(AutopsyEvent event)
static void createAsCurrentCase(CaseType caseType, String caseDir, CaseDetails caseDetails)
static String getCaseDirectoryNodePath(Path caseDirectoryPath)
void notifyBlackBoardArtifactTagDeleted(BlackboardArtifactTag deletedTag)
String getExaminerPhone()
Void open(ProgressIndicator progressIndicator, Object additionalParams)
Set< TimeZone > getTimeZones()
CoordinationService.Lock caseLock
static boolean deleteMultiUserCase(CaseNodeData caseNodeData, CaseMetadata metadata, ProgressIndicator progressIndicator, Logger logger)
static String getNameForTitle()
Image addImage(String imgPath, long imgId, String timeZone)
static synchronized IngestManager getInstance()
void deleteNode(CategoryNode category, String nodePath)
static final ExecutorService openFileSystemsExecutor
static final String NO_NODE_ERROR_MSG_FRAGMENT
static boolean runningWithGUI
static void closeCurrentCase()
static String getAppTempDirectory()
void setDeletedFlag(DeletedFlags flag)
void acquireCaseLock(CaseLockType lockType)
String getTempDirectory()
static boolean existsCurrentCase()
boolean isDeletedFlagSet(DeletedFlags flag)
static void removePropertyChangeListener(PropertyChangeListener listener)
void start(String message, int totalWorkUnits)
static final Logger logger
void notifyBlackBoardArtifactTagAdded(BlackboardArtifactTag newTag, List< BlackboardArtifactTag > removedTagList)
void publish(AutopsyEvent event)
String getLocalizedDisplayName()
static Future<?> backgroundOpenFileSystemsFuture
ADDING_DATA_SOURCE_FAILED
static final String EXPORT_FOLDER
static void createCaseDirectory(String caseDirPath, CaseType caseType)
String getCaseDirectory()
static String getAppName()
void notifyTagDefinitionChanged(String changedTagName)
void openFileSystemsInBackground()
void notifyContentTagAdded(ContentTag newTag, List< ContentTag > deletedTagList)
void deleteDataSource(Long dataSourceId)
static volatile Frame mainFrame
static String convertTimeZone(String timeZoneId)
static boolean driveExists(String path)
static void openCoreWindows()
static void deleteSingleUserCase(CaseMetadata metadata, ProgressIndicator progressIndicator)
void addSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
void publishTimelineEventAddedEvent(TimelineManager.TimelineEventAddedEvent event)
synchronized static void setLogDirectory(String directoryPath)
volatile ExecutorService caseActionExecutor
void notifyCentralRepoCommentChanged(long contentId, String newComment)
TaskThreadFactory(String threadName)
static final String CACHE_FOLDER
static String getAutopsyVersion()
CaseType(String typeName)
List< Image > getImages()
static void deleteMultiUserCaseDirectory(CaseNodeData caseNodeData, CaseMetadata metadata, ProgressIndicator progressIndicator, Logger logger)
Case(CaseType caseType, String caseDir, CaseDetails caseDetails)
String getReportDirectory()
static String getCaseResourcesNodePath(Path caseDirectoryPath)
static CaseNodeData readCaseNodeData(String nodePath)
static boolean getIsMultiUserModeEnabled()
void addReport(String localPath, String srcModuleName, String reportName)
static void updateGUIForCaseOpened(Case newCurrentCase)
void notifyDataSourceNameChanged(Content dataSource, String newName)
static CaseDbConnectionInfo getDatabaseConnectionInfo()
String getModulesOutputDirAbsPath()
static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner, CaseType caseType)
void closeAppServiceCaseResources()
static final int CASE_LOCK_TIMEOUT_MINS
static final String SINGLE_USER_CASE_DB_NAME
static void deleteCase(CaseMetadata metadata)
void deleteReports(Collection<?extends Report > reports, boolean deleteFromDisk)
synchronized void closeRemoteEventChannel()
KeywordSearchService getKeywordSearchService()
static final int CASE_RESOURCES_LOCK_TIMEOUT_HOURS
final long MAX_IMAGE_THRESHOLD
List< Report > getAllReports()
static boolean canAddDataSources()
static boolean isValidName(String caseName)
void openCaseDataBase(ProgressIndicator progressIndicator)
void createCaseDirectoryIfDoesNotExist(ProgressIndicator progressIndicator)
CollaborationMonitor collaborationMonitor
void openCommunicationChannels(ProgressIndicator progressIndicator)
static void shutDownTaskExecutor(ExecutorService executor)
static void closeCoreWindows()
ProgressIndicator getProgressIndicator()
static String getModulesOutputDirRelPath()
void saveCaseMetadataToFile(ProgressIndicator progressIndicator)
static void deleteMultiUserCaseTextIndex(CaseNodeData caseNodeData, CaseMetadata metadata, ProgressIndicator progressIndicator, Logger logger)
void doOpenCaseAction(String progressIndicatorTitle, CaseAction< ProgressIndicator, Object, Void > caseAction, CaseLockType caseLockType, boolean allowCancellation, Object additionalParams)
Set< TimeZone > getTimeZone()
static void writeCaseNodeData(CaseNodeData nodeData)
static final String MODULE_FOLDER
void openCaseLevelServices(ProgressIndicator progressIndicator)
static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner)
void openFileSystems(List< Image > images)
synchronized void openRemoteEventChannel(String channelName)
String getCaseDisplayName()
void createCaseNodeData(ProgressIndicator progressIndicator)
static void invokeStartupDialog()
void publishArtifactsPostedEvent(Blackboard.ArtifactsPostedEvent event)
static String displayNameToUniqueName(String caseDisplayName)
static void deleteFromRecentCases(CaseMetadata metadata, ProgressIndicator progressIndicator)
static void openAsCurrentCase(String caseMetadataFilePath)
static void removeEventSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
Lock tryGetExclusiveLock(CategoryNode category, String nodePath, int timeOut, TimeUnit timeUnit)
static boolean isNoNodeException(CoordinationServiceException ex)
void fireModuleDataEvent(ModuleDataEvent moduleDataEvent)
default void setCancelling(String cancellingMessage)
void setLastAccessDate(Date lastAccessDate)
void close(ProgressIndicator progressIndicator)
final 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()
void createCaseDatabase(ProgressIndicator progressIndicator)
Thread newThread(Runnable task)
static void removeEventSubscriber(String eventName, PropertyChangeListener subscriber)
void switchLoggingToCaseLogsDirectory(ProgressIndicator progressIndicator)
final CaseMetadata metadata
static void deleteTextIndex(CaseMetadata metadata, ProgressIndicator progressIndicator)
void deleteTempfilesFromCaseDirectory(ProgressIndicator progressIndicator)
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)
SleuthkitCase createPortableCase(String caseName, File portableCaseFolder)
R execute(T progressIndicator, V additionalParams)
BLACKBOARD_ARTIFACT_TAG_ADDED
static void open(String caseMetadataFilePath)
static void openAsCurrentCase(Case newCurrentCase, boolean isNewCase)
static CoordinationService.Lock acquireCaseResourcesLock(String caseDir)
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
Void create(ProgressIndicator progressIndicator, Object additionalParams)
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()
void openAppServiceCaseResources(ProgressIndicator progressIndicator, boolean isNewCase)
String getExportDirectory()
static void updateGUIForCaseClosed()
void notifyAddingDataSource(UUID eventId)
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)
static void deleteCaseDirectory(CaseMetadata metadata, ProgressIndicator progressIndicator)
static final String CASE_TEMP_DIR
void notifyFailedAddingDataSource(UUID addingDataSourceEventId)
static void deleteMultiUserCase(CaseMetadata metadata, ProgressIndicator progressIndicator)
static final String CONFIG_FOLDER
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
static final Object caseActionSerializationLock
static void deleteMultiUserCaseDatabase(CaseNodeData caseNodeData, CaseMetadata metadata, ProgressIndicator progressIndicator, Logger logger)
static boolean isCaseOpen()
String getTextIndexName()
static final String REPORTS_FOLDER
void progress(String message)
BLACKBOARD_ARTIFACT_TAG_DELETED
static void checkForCancellation()
static boolean canDeleteCurrentCase()
static void addEventSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
void updateCaseNodeData(ProgressIndicator progressIndicator)
static void error(String message)
final SleuthkitCase tskCase
static synchronized IngestServices getInstance()
String getExaminerEmail()