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;
25 import java.awt.Cursor;
27 import java.awt.Frame;
28 import java.awt.event.ActionEvent;
29 import java.awt.event.ActionListener;
30 import java.beans.PropertyChangeListener;
31 import java.beans.PropertyChangeSupport;
33 import java.lang.reflect.InvocationTargetException;
34 import java.nio.file.InvalidPathException;
35 import java.nio.file.Path;
36 import java.nio.file.Paths;
37 import java.sql.Connection;
38 import java.sql.DriverManager;
39 import java.sql.ResultSet;
40 import java.sql.SQLException;
41 import java.sql.Statement;
42 import java.text.SimpleDateFormat;
43 import java.util.Collection;
44 import java.util.Collections;
45 import java.util.Date;
46 import java.util.HashMap;
47 import java.util.HashSet;
48 import java.util.List;
51 import java.util.TimeZone;
52 import java.util.UUID;
53 import java.util.concurrent.CancellationException;
54 import java.util.concurrent.ExecutionException;
55 import java.util.concurrent.ExecutorService;
56 import java.util.concurrent.Executors;
57 import java.util.concurrent.Future;
58 import java.util.concurrent.ThreadFactory;
59 import java.util.concurrent.TimeUnit;
60 import java.util.logging.Level;
61 import java.util.stream.Collectors;
62 import java.util.stream.Stream;
63 import javax.annotation.concurrent.GuardedBy;
64 import javax.annotation.concurrent.ThreadSafe;
65 import javax.swing.JOptionPane;
66 import javax.swing.SwingUtilities;
67 import org.apache.commons.lang3.StringUtils;
68 import org.openide.util.Lookup;
69 import org.openide.util.NbBundle;
70 import org.openide.util.NbBundle.Messages;
71 import org.openide.util.actions.CallableSystemAction;
72 import org.openide.windows.WindowManager;
160 import org.
sleuthkit.datamodel.TskUnsupportedSchemaVersionException;
187 = Executors.newSingleThreadExecutor(
new ThreadFactoryBuilder().setNameFormat(
"case-open-file-systems-%d").build());
207 WindowManager.getDefault().invokeWhenUIReady(() -> {
208 mainFrame = WindowManager.getDefault().getMainWindow();
230 if (typeName != null) {
232 if (typeName.equalsIgnoreCase(c.toString())) {
256 "Case_caseType_singleUser=Single-user case",
257 "Case_caseType_multiUser=Multi-user case"
260 if (fromString(typeName) == SINGLE_USER_CASE) {
261 return Bundle.Case_caseType_singleUser();
263 return Bundle.Case_caseType_multiUser();
273 this.typeName = typeName;
288 return (otherTypeName == null) ?
false : typeName.equals(otherTypeName);
503 @SuppressWarnings(
"deprecation")
506 for (BlackboardArtifact.Type artifactType : event.getArtifactTypes()) {
516 event.getModuleName(),
518 event.getArtifacts(artifactType)));
537 }
catch (TskCoreException ex) {
538 logger.log(Level.SEVERE,
"Unable to retrieve the hasData status from the db", ex);
581 }
catch (TskCoreException ex) {
582 logger.log(Level.SEVERE,
"Unable to retrieve the hasData status from the db", ex);
641 .map(Events::toString)
642 .collect(Collectors.toSet()), listener);
653 .map(Events::toString)
654 .collect(Collectors.toSet()), listener);
677 eventTypes.forEach((
Events event) -> {
722 eventTypes.forEach((
Events event) -> {
736 return !(caseName.contains(
"\\") || caseName.contains(
"/") || caseName.contains(
":")
737 || caseName.contains(
"*") || caseName.contains(
"?") || caseName.contains(
"\"")
738 || caseName.contains(
"<") || caseName.contains(
">") || caseName.contains(
"|"));
790 "Case.exceptionMessage.emptyCaseName=Must specify a case name.",
791 "Case.exceptionMessage.emptyCaseDir=Must specify a case directory path."
795 throw new CaseActionException(Bundle.Case_exceptionMessage_emptyCaseName());
797 if (caseDir.isEmpty()) {
798 throw new CaseActionException(Bundle.Case_exceptionMessage_emptyCaseDir());
817 "# {0} - exception message",
"Case.exceptionMessage.failedToReadMetadata=Failed to read case metadata:\n{0}.",
818 "Case.exceptionMessage.cannotOpenMultiUserCaseNoSettings=Multi-user settings are missing (see Tools, Options, Multi-user tab), cannot open a multi-user case."
823 metadata =
new CaseMetadata(Paths.get(caseMetadataFilePath));
825 throw new CaseActionException(Bundle.Case_exceptionMessage_failedToReadMetadata(ex.getLocalizedMessage()), ex);
828 throw new CaseActionException(Bundle.Case_exceptionMessage_cannotOpenMultiUserCaseNoSettings());
839 return currentCase != null;
856 throw new IllegalStateException(NbBundle.getMessage(
Case.class,
"Case.getCurCase.exception.noneOpen"), ex);
880 if (openCase == null) {
881 throw new NoCurrentCaseException(NbBundle.getMessage(
Case.class,
"Case.getCurCase.exception.noneOpen"));
896 "# {0} - exception message",
"Case.closeException.couldNotCloseCase=Error closing case: {0}",
897 "Case.progressIndicatorTitle.closingCase=Closing Case"
901 if (null == currentCase) {
907 logger.log(Level.INFO,
"Closing current case {0} ({1}) in {2}",
new Object[]{closedCase.getDisplayName(), closedCase.getName(), closedCase.getCaseDirectory()});
909 logger.log(Level.INFO,
"Closed current case {0} ({1}) in {2}",
new Object[]{closedCase.getDisplayName(), closedCase.getName(), closedCase.getCaseDirectory()});
910 }
catch (CaseActionException ex) {
932 if (null == currentCase) {
952 "Case.progressIndicatorTitle.deletingDataSource=Removing Data Source"
954 static void deleteDataSourceFromCurrentCase(Long dataSourceObjectID)
throws CaseActionException {
956 if (null == currentCase) {
963 CaseMetadata caseMetadata = currentCase.
getMetadata();
971 Case theCase =
new Case(caseMetadata);
972 theCase.doOpenCaseAction(Bundle.Case_progressIndicatorTitle_deletingDataSource(), theCase::deleteDataSource, CaseLockType.EXCLUSIVE,
false, dataSourceObjectID);
993 "Case.progressIndicatorTitle.deletingCase=Deleting Case",
994 "Case.exceptionMessage.cannotDeleteCurrentCase=Cannot delete current case, it must be closed first.",
995 "# {0} - case display name",
"Case.exceptionMessage.deletionInterrupted=Deletion of the case {0} was cancelled."
999 if (null != currentCase) {
1000 throw new CaseActionException(Bundle.Case_exceptionMessage_cannotDeleteCurrentCase());
1010 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
1017 }
catch (InterruptedException ex) {
1023 throw new CaseActionException(Bundle.Case_exceptionMessage_deletionInterrupted(metadata.
getCaseDisplayName()), ex);
1027 progressIndicator.
finish();
1042 "Case.progressIndicatorTitle.creatingCase=Creating Case",
1043 "Case.progressIndicatorTitle.openingCase=Opening Case",
1044 "Case.exceptionMessage.cannotLocateMainWindow=Cannot locate main application window"
1048 if (null != currentCase) {
1051 }
catch (CaseActionException ex) {
1060 logger.log(Level.INFO,
"Opening {0} ({1}) in {2} as the current case",
new Object[]{newCurrentCase.getDisplayName(), newCurrentCase.getName(), newCurrentCase.getCaseDirectory()});
1061 String progressIndicatorTitle;
1064 progressIndicatorTitle = Bundle.Case_progressIndicatorTitle_creatingCase();
1065 openCaseAction = newCurrentCase::create;
1067 progressIndicatorTitle = Bundle.Case_progressIndicatorTitle_openingCase();
1068 openCaseAction = newCurrentCase::open;
1071 currentCase = newCurrentCase;
1072 logger.log(Level.INFO,
"Opened {0} ({1}) in {2} as the current case",
new Object[]{newCurrentCase.getDisplayName(), newCurrentCase.getName(), newCurrentCase.getCaseDirectory()});
1078 logger.log(Level.INFO, String.format(
"Cancelled opening %s (%s) in %s as the current case", newCurrentCase.
getDisplayName(), newCurrentCase.
getName(), newCurrentCase.
getCaseDirectory()));
1080 }
catch (CaseActionException ex) {
1081 logger.log(Level.SEVERE, String.format(
"Error opening %s (%s) in %s as the current case", newCurrentCase.
getDisplayName(), newCurrentCase.
getName(), newCurrentCase.
getCaseDirectory()), ex);
1099 String uniqueCaseName = caseDisplayName.replaceAll(
"[^\\p{ASCII}]",
"_");
1104 uniqueCaseName = uniqueCaseName.replaceAll(
"[\\p{Cntrl}]",
"_");
1109 uniqueCaseName = uniqueCaseName.replaceAll(
"[ /?:'\"\\\\]",
"_");
1114 uniqueCaseName = uniqueCaseName.toLowerCase();
1119 SimpleDateFormat dateFormat =
new SimpleDateFormat(
"yyyyMMdd_HHmmss");
1120 Date date =
new Date();
1121 uniqueCaseName = uniqueCaseName +
"_" + dateFormat.format(date);
1123 return uniqueCaseName;
1140 File caseDir =
new File(caseDirPath);
1141 if (caseDir.exists()) {
1142 if (caseDir.isFile()) {
1143 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.existNotDir", caseDirPath));
1144 }
else if (!caseDir.canRead() || !caseDir.canWrite()) {
1145 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.existCantRW", caseDirPath));
1152 if (!caseDir.mkdirs()) {
1153 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreate", caseDirPath));
1161 String hostPathComponent =
"";
1166 Path exportDir = Paths.get(caseDirPath, hostPathComponent, EXPORT_FOLDER);
1167 if (!exportDir.toFile().mkdirs()) {
1168 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateCaseDir", exportDir));
1171 Path logsDir = Paths.get(caseDirPath, hostPathComponent, LOG_FOLDER);
1172 if (!logsDir.toFile().mkdirs()) {
1173 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateCaseDir", logsDir));
1176 Path cacheDir = Paths.get(caseDirPath, hostPathComponent, CACHE_FOLDER);
1177 if (!cacheDir.toFile().mkdirs()) {
1178 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateCaseDir", cacheDir));
1181 Path moduleOutputDir = Paths.get(caseDirPath, hostPathComponent, MODULE_FOLDER);
1182 if (!moduleOutputDir.toFile().mkdirs()) {
1183 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateModDir", moduleOutputDir));
1186 Path reportsDir = Paths.get(caseDirPath, hostPathComponent, REPORTS_FOLDER);
1187 if (!reportsDir.toFile().mkdirs()) {
1188 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateReportsDir", reportsDir));
1199 static Map<Long, String> getImagePaths(SleuthkitCase db) {
1200 Map<Long, String> imgPaths =
new HashMap<>();
1202 Map<Long, List<String>> imgPathsList = db.getImagePaths();
1203 for (Map.Entry<Long, List<String>> entry : imgPathsList.entrySet()) {
1204 if (entry.getValue().size() > 0) {
1205 imgPaths.put(entry.getKey(), entry.getValue().get(0));
1208 }
catch (TskCoreException ex) {
1209 logger.log(Level.SEVERE,
"Error getting image paths", ex);
1225 "Case.creationException.couldNotAcquireResourcesLock=Failed to get lock on case resources"
1229 Path caseDirPath = Paths.get(caseDir);
1233 }
catch (InterruptedException ex) {
1236 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock(), ex);
1259 String backupDbPath = caseDb.getBackupDatabasePath();
1260 if (null != backupDbPath) {
1261 JOptionPane.showMessageDialog(
1263 NbBundle.getMessage(
Case.class,
"Case.open.msgDlg.updated.msg", backupDbPath),
1264 NbBundle.getMessage(
Case.class,
"Case.open.msgDlg.updated.title"),
1265 JOptionPane.INFORMATION_MESSAGE);
1272 Map<Long, String> imgPaths = getImagePaths(caseDb);
1273 for (Map.Entry<Long, String> entry : imgPaths.entrySet()) {
1274 long obj_id = entry.getKey();
1275 String path = entry.getValue();
1283 SwingUtilities.invokeAndWait(
new Runnable() {
1286 int response = JOptionPane.showConfirmDialog(
1288 NbBundle.getMessage(
Case.class,
"Case.checkImgExist.confDlg.doesntExist.msg", path),
1289 NbBundle.getMessage(
Case.class,
"Case.checkImgExist.confDlg.doesntExist.title"),
1290 JOptionPane.YES_NO_OPTION);
1291 if (response == JOptionPane.YES_OPTION) {
1292 MissingImageDialog.makeDialog(obj_id, caseDb);
1294 logger.log(Level.SEVERE,
"User proceeding with missing image files");
1300 }
catch (InterruptedException | InvocationTargetException ex) {
1301 logger.log(Level.SEVERE,
"Failed to show missing image confirmation dialog", ex);
1312 CallableSystemAction.get(CaseDetailsAction.class).setEnabled(
true);
1327 final boolean hasData = newCurrentCase.
hasData();
1329 SwingUtilities.invokeLater(() -> {
1338 mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1345 mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1361 SwingUtilities.invokeLater(() -> {
1371 CallableSystemAction.get(
AddImageAction.class).setEnabled(
false);
1374 CallableSystemAction.get(CaseDetailsAction.class).setEnabled(
false);
1376 CallableSystemAction.get(CaseDeleteAction.class).setEnabled(
false);
1520 hostPath = Paths.get(caseDirectory);
1522 if (!hostPath.toFile().exists()) {
1523 hostPath.toFile().mkdirs();
1525 return hostPath.toString();
1532 return Paths.get(System.getProperty(
"java.io.tmpdir"),
APP_NAME,
getName());
1544 Path basePath = null;
1549 basePath = (StringUtils.isBlank(customDirectory))
1551 : Paths.get(customDirectory, APP_NAME,
getName());
1569 : Paths.get(TEMP_FOLDER);
1571 File caseTempDir = basePath
1572 .resolve(caseRelPath)
1576 if (!caseTempDir.exists()) {
1577 caseTempDir.mkdirs();
1580 return caseTempDir.getAbsolutePath();
1653 return path.subpath(path.getNameCount() - 2, path.getNameCount()).toString();
1655 return path.subpath(path.getNameCount() - 1, path.getNameCount()).toString();
1669 return caseDb.getRootObjects();
1678 Set<TimeZone> timezones =
new HashSet<>();
1679 String query =
"SELECT time_zone FROM data_source_info";
1680 try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
1681 ResultSet timeZoneSet = dbQuery.getResultSet();
1682 while (timeZoneSet.next()) {
1683 String timeZone = timeZoneSet.getString(
"time_zone");
1684 if (timeZone != null && !timeZone.isEmpty()) {
1685 timezones.add(TimeZone.getTimeZone(timeZone));
1688 }
catch (TskCoreException | SQLException ex) {
1689 logger.log(Level.SEVERE,
"Error getting data source time zones", ex);
1733 hasDataSource =
true;
1841 logger.log(Level.WARNING,
"Unable to send notifcation regarding comment change due to no current case being open", ex);
1891 public void addReport(String localPath, String srcModuleName, String reportName)
throws TskCoreException {
1892 addReport(localPath, srcModuleName, reportName, null);
1909 public Report
addReport(String localPath, String srcModuleName, String reportName, Content parent)
throws TskCoreException {
1910 String normalizedLocalPath;
1912 if (localPath.toLowerCase().contains(
"http:")) {
1913 normalizedLocalPath = localPath;
1915 normalizedLocalPath = Paths.get(localPath).normalize().toString();
1917 }
catch (InvalidPathException ex) {
1918 String errorMsg =
"Invalid local path provided: " + localPath;
1919 throw new TskCoreException(errorMsg, ex);
1923 Report report = this.caseDb.addReport(normalizedLocalPath, srcModuleName, reportName, parent);
1937 return this.caseDb.getAllReports();
1948 public void deleteReports(Collection<? extends Report> reports)
throws TskCoreException {
1949 for (Report report : reports) {
1950 this.caseDb.deleteReport(report);
1955 }
catch (TskCoreException ex) {
1956 logger.log(Level.SEVERE,
"Unable to retrieve the hasData status from the db", ex);
1959 for (Report report : reports) {
1981 "Case.exceptionMessage.metadataUpdateError=Failed to update case metadata"
1983 void updateCaseDetails(CaseDetails caseDetails)
throws CaseActionException {
1986 metadata.setCaseDetails(caseDetails);
1987 }
catch (CaseMetadataException ex) {
1988 throw new CaseActionException(Bundle.Case_exceptionMessage_metadataUpdateError(), ex);
1992 CaseNodeData nodeData = CaseNodeData.readCaseNodeData(metadata.
getCaseDirectory());
1994 CaseNodeData.writeCaseNodeData(nodeData);
1995 }
catch (CaseNodeDataException | InterruptedException ex) {
1996 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotUpdateCaseNodeData(ex.getLocalizedMessage()), ex);
1999 if (!oldCaseDetails.getCaseNumber().equals(caseDetails.
getCaseNumber())) {
2000 eventPublisher.
publish(
new AutopsyEvent(Events.NUMBER.toString(), oldCaseDetails.getCaseNumber(), caseDetails.
getCaseNumber()));
2002 if (!oldCaseDetails.getExaminerName().equals(caseDetails.
getExaminerName())) {
2003 eventPublisher.
publish(
new AutopsyEvent(Events.NUMBER.toString(), oldCaseDetails.getExaminerName(), caseDetails.
getExaminerName()));
2006 eventPublisher.
publish(
new AutopsyEvent(Events.NAME.toString(), oldCaseDetails.getCaseDisplayName(), caseDetails.
getCaseDisplayName()));
2008 eventPublisher.
publish(
new AutopsyEvent(Events.CASE_DETAILS.toString(), oldCaseDetails, caseDetails));
2009 if (RuntimeProperties.runningWithGUI()) {
2010 SwingUtilities.invokeLater(() -> {
2014 }
catch (Exception ex) {
2015 logger.log(Level.SEVERE,
"Error updating case name in UI", ex);
2043 metadata = caseMetaData;
2077 "Case.progressIndicatorCancelButton.label=Cancel",
2078 "Case.progressMessage.preparing=Preparing...",
2079 "Case.progressMessage.cancelling=Cancelling...",
2080 "Case.exceptionMessage.cancelled=Cancelled.",
2081 "# {0} - exception message",
"Case.exceptionMessage.execExceptionWrapperMessage={0}"
2091 if (allowCancellation) {
2095 progressIndicatorTitle,
2096 new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
2097 Bundle.Case_progressIndicatorCancelButton_label(),
2098 cancelButtonListener);
2102 progressIndicatorTitle);
2107 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
2116 caseActionExecutor = Executors.newSingleThreadExecutor(threadFactory);
2117 Future<Void> future = caseActionExecutor.submit(() -> {
2119 caseAction.
execute(progressIndicator, additionalParams);
2123 if (null == resourcesLock) {
2124 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock());
2126 caseAction.
execute(progressIndicator, additionalParams);
2127 }
catch (CaseActionException ex) {
2134 if (null != cancelButtonListener) {
2143 }
catch (InterruptedException discarded) {
2147 if (null != cancelButtonListener) {
2150 future.cancel(
true);
2153 }
catch (CancellationException discarded) {
2159 }
catch (ExecutionException ex) {
2164 throw new CaseActionException(Bundle.Case_exceptionMessage_execExceptionWrapperMessage(ex.getCause().getLocalizedMessage()), ex);
2166 progressIndicator.
finish();
2186 assert (additionalParams == null);
2207 }
catch (CaseActionException ex) {
2216 }
catch (InterruptedException discarded) {
2218 close(progressIndicator);
2238 assert (additionalParams == null);
2258 }
catch (CaseActionException ex) {
2267 }
catch (InterruptedException discarded) {
2269 close(progressIndicator);
2284 "# {0} - case",
"Case.openFileSystems.retrievingImages=Retrieving images for case: {0}...",
2285 "# {0} - image",
"Case.openFileSystems.openingImage=Opening all filesystems for image: {0}..."
2288 if (backgroundOpenFileSystemsFuture != null && !backgroundOpenFileSystemsFuture.isDone()) {
2289 backgroundOpenFileSystemsFuture.cancel(
true);
2318 caseName = (this.tskCase != null) ? this.tskCase.getDatabaseName() :
"";
2329 if (Thread.interrupted()) {
2330 throw new InterruptedException();
2340 progressIndicator.
progress(Bundle.Case_openFileSystems_retrievingImages(caseName));
2342 return this.tskCase.getImages();
2343 }
catch (TskCoreException ex) {
2346 String.format(
"Could not obtain images while opening case: %s.", caseName),
2362 private void openFileSystems(List<Image> images)
throws TskCoreException, InterruptedException {
2363 byte[] tempBuff =
new byte[512];
2365 for (Image image : images) {
2366 String imageStr = image.getName();
2368 progressIndicator.
progress(Bundle.Case_openFileSystems_openingImage(imageStr));
2370 Collection<FileSystem> fileSystems = this.tskCase.getImageFileSystems(image);
2372 for (FileSystem fileSystem : fileSystems) {
2373 fileSystem.read(tempBuff, 0, 512);
2385 if (images == null) {
2393 String.format(
"Skipping background load of file systems due to large number of images in case (%d)", images.size()));
2399 }
catch (InterruptedException ex) {
2402 String.format(
"Background operation opening all file systems in %s has been cancelled.", caseName));
2403 }
catch (Exception ex) {
2405 logger.log(Level.WARNING,
"Error while opening file systems in background", ex);
2426 "Case.progressMessage.deletingDataSource=Removing the data source from the case...",
2427 "Case.exceptionMessage.dataSourceNotFound=The data source was not found.",
2428 "Case.exceptionMessage.errorDeletingDataSourceFromCaseDb=An error occurred while removing the data source from the case database.",
2429 "Case.exceptionMessage.errorDeletingDataSourceFromTextIndex=An error occurred while removing the data source from the text index.",})
2430 Void deleteDataSource(ProgressIndicator progressIndicator, Object additionalParams)
throws CaseActionException {
2431 assert (additionalParams instanceof Long);
2432 open(progressIndicator, null);
2434 progressIndicator.progress(Bundle.Case_progressMessage_deletingDataSource());
2435 Long dataSourceObjectID = (Long) additionalParams;
2437 DataSource dataSource = this.caseDb.getDataSource(dataSourceObjectID);
2438 if (dataSource == null) {
2439 throw new CaseActionException(Bundle.Case_exceptionMessage_dataSourceNotFound());
2441 SleuthkitCaseAdminUtil.deleteDataSource(this.caseDb, dataSourceObjectID);
2442 }
catch (TskDataException | TskCoreException ex) {
2443 throw new CaseActionException(Bundle.Case_exceptionMessage_errorDeletingDataSourceFromCaseDb(), ex);
2447 }
catch (KeywordSearchServiceException ex) {
2448 throw new CaseActionException(Bundle.Case_exceptionMessage_errorDeletingDataSourceFromTextIndex(), ex);
2450 eventPublisher.
publish(
new DataSourceDeletedEvent(dataSourceObjectID));
2453 close(progressIndicator);
2468 public SleuthkitCase
createPortableCase(String caseName, File portableCaseFolder)
throws TskCoreException {
2470 if (portableCaseFolder.exists()) {
2471 throw new TskCoreException(
"Portable case folder " + portableCaseFolder.toString() +
" already exists");
2473 if (!portableCaseFolder.mkdirs()) {
2474 throw new TskCoreException(
"Error creating portable case folder " + portableCaseFolder.toString());
2482 portableCaseMetadata.setCaseDatabaseName(SINGLE_USER_CASE_DB_NAME);
2484 throw new TskCoreException(
"Error creating case metadata", ex);
2488 SleuthkitCase portableSleuthkitCase;
2490 portableSleuthkitCase = SleuthkitCase.newCase(dbFilePath);
2492 return portableSleuthkitCase;
2505 if (Thread.currentThread().isInterrupted()) {
2506 throw new CaseActionCancelledException(Bundle.Case_exceptionMessage_cancelled());
2521 "Case.progressMessage.creatingCaseDirectory=Creating case directory..."
2528 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDirectory());
2530 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDirectory());
2542 "Case.progressMessage.switchingLogDirectory=Switching log directory..."
2545 progressIndicator.
progress(Bundle.Case_progressMessage_switchingLogDirectory());
2561 "Case.progressMessage.savingCaseMetadata=Saving case metadata to file...",
2562 "# {0} - exception message",
"Case.exceptionMessage.couldNotSaveCaseMetadata=Failed to save case metadata:\n{0}."
2565 progressIndicator.
progress(Bundle.Case_progressMessage_savingCaseMetadata());
2567 this.metadata.writeToFile();
2569 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotSaveCaseMetadata(ex.getLocalizedMessage()), ex);
2585 "Case.progressMessage.creatingCaseNodeData=Creating coordination service node data...",
2586 "# {0} - exception message",
"Case.exceptionMessage.couldNotCreateCaseNodeData=Failed to create coordination service node data:\n{0}."
2590 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseNodeData());
2594 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseNodeData(ex.getLocalizedMessage()), ex);
2611 "Case.progressMessage.updatingCaseNodeData=Updating coordination service node data...",
2612 "# {0} - exception message",
"Case.exceptionMessage.couldNotUpdateCaseNodeData=Failed to update coordination service node data:\n{0}."
2616 progressIndicator.
progress(Bundle.Case_progressMessage_updatingCaseNodeData());
2622 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotUpdateCaseNodeData(ex.getLocalizedMessage()), ex);
2633 "Case.progressMessage.clearingTempDirectory=Clearing case temp directory..."
2639 progressIndicator.
progress(Bundle.Case_progressMessage_clearingTempDirectory());
2655 "Case.progressMessage.creatingCaseDatabase=Creating case database...",
2656 "# {0} - exception message",
"Case.exceptionMessage.couldNotGetDbServerConnectionInfo=Failed to get case database server conneciton info:\n{0}.",
2657 "# {0} - exception message",
"Case.exceptionMessage.couldNotCreateCaseDatabase=Failed to create case database:\n{0}.",
2658 "# {0} - exception message",
"Case.exceptionMessage.couldNotSaveDbNameToMetadataFile=Failed to save case database name to case metadata file:\n{0}."
2661 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDatabase());
2670 metadata.setCaseDatabaseName(SINGLE_USER_CASE_DB_NAME);
2678 metadata.setCaseDatabaseName(caseDb.getDatabaseName());
2680 }
catch (TskCoreException ex) {
2681 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseDatabase(ex.getLocalizedMessage()), ex);
2683 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotGetDbServerConnectionInfo(ex.getLocalizedMessage()), ex);
2685 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotSaveDbNameToMetadataFile(ex.getLocalizedMessage()), ex);
2701 "Case.progressMessage.openingCaseDatabase=Opening case database...",
2702 "# {0} - exception message",
"Case.exceptionMessage.couldNotOpenCaseDatabase=Failed to open case database:\n{0}.",
2703 "# {0} - exception message",
"Case.exceptionMessage.unsupportedSchemaVersionMessage=Unsupported case database schema version:\n{0}.",
2704 "Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-User."
2707 progressIndicator.
progress(Bundle.Case_progressMessage_openingCaseDatabase());
2711 caseDb = SleuthkitCase.openCase(Paths.get(metadata.
getCaseDirectory(), databaseName).toString());
2715 throw new CaseActionException(Bundle.Case_open_exception_multiUserCaseNotEnabled());
2718 }
catch (TskUnsupportedSchemaVersionException ex) {
2719 throw new CaseActionException(Bundle.Case_exceptionMessage_unsupportedSchemaVersionMessage(ex.getLocalizedMessage()), ex);
2721 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotGetDbServerConnectionInfo(ex.getLocalizedMessage()), ex);
2722 }
catch (TskCoreException ex) {
2723 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotOpenCaseDatabase(ex.getLocalizedMessage()), ex);
2734 "Case.progressMessage.openingCaseLevelServices=Opening case-level services...",})
2736 progressIndicator.
progress(Bundle.Case_progressMessage_openingCaseLevelServices());
2737 this.caseServices =
new Services(caseDb);
2743 caseDb.registerForEvents(sleuthkitEventListener);
2758 @NbBundle.Messages({
2759 "Case.progressMessage.openingApplicationServiceResources=Opening application service case resources...",
2760 "# {0} - service name",
"Case.serviceOpenCaseResourcesProgressIndicator.title={0} Opening Case Resources",
2761 "# {0} - service name",
"Case.serviceOpenCaseResourcesProgressIndicator.cancellingMessage=Cancelling opening case resources by {0}...",
2762 "# {0} - service name",
"Case.servicesException.notificationTitle={0} Error"
2773 progressIndicator.
progress(Bundle.Case_progressMessage_openingApplicationServiceResources());
2785 cancelButtonListener =
new CancelButtonListener(Bundle.Case_serviceOpenCaseResourcesProgressIndicator_cancellingMessage(service.getServiceName()));
2788 Bundle.Case_serviceOpenCaseResourcesProgressIndicator_title(service.getServiceName()),
2789 new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
2790 Bundle.Case_progressIndicatorCancelButton_label(),
2791 cancelButtonListener);
2795 appServiceProgressIndicator.
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.openCaseResources(context);
2805 if (null != cancelButtonListener) {
2817 }
catch (InterruptedException discarded) {
2822 future.cancel(
true);
2823 }
catch (CancellationException discarded) {
2831 }
catch (ExecutionException ex) {
2838 Case.
logger.log(Level.SEVERE, String.format(
"%s failed to open case resources for %s", service.getServiceName(), this.
getDisplayName()), ex);
2840 SwingUtilities.invokeLater(() -> {
2852 appServiceProgressIndicator.
finish();
2870 "Case.progressMessage.settingUpNetworkCommunications=Setting up network communications...",
2871 "# {0} - exception message",
"Case.exceptionMessage.couldNotOpenRemoteEventChannel=Failed to open remote events channel:\n{0}.",
2872 "# {0} - exception message",
"Case.exceptionMessage.couldNotCreatCollaborationMonitor=Failed to create collaboration monitor:\n{0}."
2876 progressIndicator.
progress(Bundle.Case_progressMessage_settingUpNetworkCommunications());
2880 collaborationMonitor =
new CollaborationMonitor(metadata.
getCaseName());
2882 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotOpenRemoteEventChannel(ex.getLocalizedMessage()), ex);
2883 }
catch (CollaborationMonitor.CollaborationMonitorException ex) {
2884 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreatCollaborationMonitor(ex.getLocalizedMessage()), ex);
2912 Bundle.Case_progressIndicatorTitle_closingCase());
2916 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
2925 Future<Void> future = caseActionExecutor.submit(() -> {
2927 close(progressIndicator);
2934 progressIndicator.
progress(Bundle.Case_progressMessage_preparing());
2936 if (null == resourcesLock) {
2937 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock());
2939 close(progressIndicator);
2953 }
catch (InterruptedException | CancellationException unused) {
2960 }
catch (ExecutionException ex) {
2961 throw new CaseActionException(Bundle.Case_exceptionMessage_execExceptionWrapperMessage(ex.getCause().getMessage()), ex);
2964 progressIndicator.
finish();
2974 "Case.progressMessage.shuttingDownNetworkCommunications=Shutting down network communications...",
2975 "Case.progressMessage.closingApplicationServiceResources=Closing case-specific application service resources...",
2976 "Case.progressMessage.closingCaseDatabase=Closing case database..."
2986 progressIndicator.
progress(Bundle.Case_progressMessage_shuttingDownNetworkCommunications());
2987 if (null != collaborationMonitor) {
2988 collaborationMonitor.shutdown();
2997 progressIndicator.
progress(Bundle.Case_progressMessage_closingApplicationServiceResources());
3003 if (null != caseDb) {
3004 progressIndicator.
progress(Bundle.Case_progressMessage_closingCaseDatabase());
3005 caseDb.unregisterForEvents(sleuthkitEventListener);
3017 progressIndicator.
progress(Bundle.Case_progressMessage_switchingLogDirectory());
3026 "# {0} - serviceName",
"Case.serviceCloseResourcesProgressIndicator.title={0} Closing Case Resources",
3027 "# {0} - service name",
"# {1} - exception message",
"Case.servicesException.serviceResourcesCloseError=Could not close case resources for {0} service: {1}"
3040 Bundle.Case_serviceCloseResourcesProgressIndicator_title(service.getServiceName()));
3044 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
3046 String threadNameSuffix = service.getServiceName().replaceAll(
"[ ]",
"-");
3047 threadNameSuffix = threadNameSuffix.toLowerCase();
3049 ExecutorService executor = Executors.newSingleThreadExecutor(threadFactory);
3050 Future<Void> future = executor.submit(() -> {
3051 service.closeCaseResources(context);
3056 }
catch (InterruptedException ex) {
3057 Case.
logger.log(Level.SEVERE, String.format(
"Unexpected interrupt while waiting on %s service to close case resources", service.getServiceName()), ex);
3058 }
catch (CancellationException ex) {
3059 Case.
logger.log(Level.SEVERE, String.format(
"Unexpected cancellation while waiting on %s service to close case resources", service.getServiceName()), ex);
3060 }
catch (ExecutionException ex) {
3061 Case.
logger.log(Level.SEVERE, String.format(
"%s service failed to open case resources", service.getServiceName()), ex);
3064 Bundle.Case_servicesException_notificationTitle(service.getServiceName()),
3065 Bundle.Case_servicesException_serviceResourcesCloseError(service.getServiceName(), ex.getLocalizedMessage())));
3069 progressIndicator.
finish();
3080 "Case.lockingException.couldNotAcquireSharedLock=Failed to get a shared lock on the case.",
3081 "Case.lockingException.couldNotAcquireExclusiveLock=Failed to get an exclusive lock on the case."
3092 throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireSharedLock());
3094 throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireExclusiveLock());
3099 throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireSharedLock(), ex);
3101 throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireExclusiveLock(), ex);
3115 logger.log(Level.SEVERE, String.format(
"Failed to release shared case directory lock for %s",
getMetadata().
getCaseDirectory()), ex);
3128 if (!subDirectory.exists()) {
3129 subDirectory.mkdirs();
3131 return subDirectory.toString();
3147 "Case.exceptionMessage.errorsDeletingCase=Errors occured while deleting the case. See the application log for details."
3150 boolean errorsOccurred =
false;
3154 errorsOccurred =
true;
3160 }
catch (CaseActionException ex) {
3161 errorsOccurred =
true;
3167 if (errorsOccurred) {
3168 throw new CaseActionException(Bundle.Case_exceptionMessage_errorsDeletingCase());
3192 "Case.progressMessage.connectingToCoordSvc=Connecting to coordination service...",
3193 "# {0} - exception message",
"Case.exceptionMessage.failedToConnectToCoordSvc=Failed to connect to coordination service:\n{0}.",
3194 "Case.exceptionMessage.cannotGetLockToDeleteCase=Cannot delete case because it is open for another user or host.",
3195 "# {0} - exception message",
"Case.exceptionMessage.failedToLockCaseForDeletion=Failed to exclusively lock case for deletion:\n{0}.",
3196 "Case.progressMessage.fetchingCoordSvcNodeData=Fetching coordination service node data for the case...",
3197 "# {0} - exception message",
"Case.exceptionMessage.failedToFetchCoordSvcNodeData=Failed to fetch coordination service node data:\n{0}.",
3198 "Case.progressMessage.deletingResourcesCoordSvcNode=Deleting case resources coordination service node...",
3199 "Case.progressMessage.deletingCaseDirCoordSvcNode=Deleting case directory coordination service node..."
3202 progressIndicator.
progress(Bundle.Case_progressMessage_connectingToCoordSvc());
3208 throw new CaseActionException(Bundle.Case_exceptionMessage_failedToConnectToCoordSvc(ex.getLocalizedMessage()));
3212 boolean errorsOccurred =
false;
3214 if (dirLock == null) {
3216 throw new CaseActionException(Bundle.Case_exceptionMessage_cannotGetLockToDeleteCase());
3219 progressIndicator.
progress(Bundle.Case_progressMessage_fetchingCoordSvcNodeData());
3224 throw new CaseActionException(Bundle.Case_exceptionMessage_failedToFetchCoordSvcNodeData(ex.getLocalizedMessage()));
3229 progressIndicator.
progress(Bundle.Case_progressMessage_deletingResourcesCoordSvcNode());
3235 errorsOccurred =
true;
3236 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);
3238 }
catch (InterruptedException ex) {
3239 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);
3244 throw new CaseActionException(Bundle.Case_exceptionMessage_failedToLockCaseForDeletion(ex.getLocalizedMessage()));
3247 if (!errorsOccurred) {
3248 progressIndicator.
progress(Bundle.Case_progressMessage_deletingCaseDirCoordSvcNode());
3254 errorsOccurred =
true;
3258 if (errorsOccurred) {
3259 throw new CaseActionException(Bundle.Case_exceptionMessage_errorsDeletingCase());
3289 boolean errorsOccurred =
false;
3296 errorsOccurred =
true;
3299 errorsOccurred =
true;
3301 }
catch (CaseActionException ex) {
3302 errorsOccurred =
true;
3305 return errorsOccurred;
3329 "Case.progressMessage.deletingCaseDatabase=Deleting case database..."
3333 progressIndicator.
progress(Bundle.Case_progressMessage_deletingCaseDatabase());
3334 logger.log(Level.INFO, String.format(
"Deleting case database for %s (%s) in %s", caseNodeData.
getDisplayName(), caseNodeData.
getName(), caseNodeData.
getDirectory()));
3336 String url =
"jdbc:postgresql://" + info.getHost() +
":" + info.getPort() +
"/postgres";
3337 Class.forName(
"org.postgresql.Driver");
3338 try (Connection connection = DriverManager.getConnection(url, info.getUserName(), info.getPassword()); Statement statement = connection.createStatement()) {
3339 String dbExistsQuery =
"SELECT 1 from pg_database WHERE datname = '" + metadata.
getCaseDatabaseName() +
"'";
3340 try (ResultSet queryResult = statement.executeQuery(dbExistsQuery)) {
3341 if (queryResult.next()) {
3343 statement.execute(deleteCommand);
3384 "Case.progressMessage.deletingTextIndex=Deleting text index..."
3387 progressIndicator.
progress(Bundle.Case_progressMessage_deletingTextIndex());
3391 searchService.deleteTextIndex(metadata);
3427 "Case.progressMessage.deletingCaseDirectory=Deleting case directory..."
3430 progressIndicator.
progress(Bundle.Case_progressMessage_deletingCaseDirectory());
3432 throw new CaseActionException(String.format(
"Failed to delete %s", metadata.
getCaseDirectory()));
3444 "Case.progressMessage.removingCaseFromRecentCases=Removing case from Recent Cases menu..."
3448 progressIndicator.
progress(Bundle.Case_progressMessage_removingCaseFromRecentCases());
3449 SwingUtilities.invokeLater(() -> {
3465 boolean isNodeNodeEx =
false;
3466 Throwable cause = ex.getCause();
3467 if (cause != null) {
3468 String causeMessage = cause.getMessage();
3469 isNodeNodeEx = causeMessage.contains(NO_NODE_ERROR_MSG_FRAGMENT);
3471 return isNodeNodeEx;
3490 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);
3509 if (!hasDataSource) {
3524 String query =
"SELECT count(*) AS count FROM (SELECT * FROM data_source_info LIMIT 1)t";
3525 try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
3526 ResultSet resultSet = dbQuery.getResultSet();
3527 if (resultSet.next()) {
3528 return resultSet.getLong(
"count") > 0;
3531 }
catch (SQLException ex) {
3532 logger.log(Level.SEVERE,
"Error accessing case database", ex);
3533 throw new TskCoreException(
"Error accessing case databse", ex);
3548 String query =
"SELECT SUM(cnt) total FROM "
3549 +
"(SELECT COUNT(*) AS cnt FROM "
3550 +
"(SELECT * FROM tsk_objects LIMIT 1)t "
3552 +
"SELECT COUNT(*) AS cnt FROM "
3553 +
"(SELECT * FROM tsk_hosts LIMIT 1)r) s";
3554 try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
3555 ResultSet resultSet = dbQuery.getResultSet();
3556 if (resultSet.next()) {
3557 return resultSet.getLong(
"total") > 0;
3561 }
catch (SQLException ex) {
3562 logger.log(Level.SEVERE,
"Error accessing case database", ex);
3563 throw new TskCoreException(
"Error accessing case databse", ex);
3587 R
execute(T progressIndicator, V additionalParams)
throws CaseActionException;
3685 ((ModalDialogProgressIndicator) progressIndicator).
setCancelling(cancellationMessage);
3714 return new Thread(task, threadName);
3751 public static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner)
throws CaseActionException {
3776 public static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner,
CaseType caseType)
throws CaseActionException {
3792 public static void open(String caseMetadataFilePath)
throws CaseActionException {
3849 return new File(filePath).isFile();
3888 return "ModuleOutput";
3901 public static PropertyChangeSupport
3903 return new PropertyChangeSupport(
Case.class
3935 public Image
addImage(String imgPath,
long imgId, String timeZone)
throws CaseActionException {
3937 Image newDataSource = caseDb.getImageById(imgId);
3939 return newDataSource;
3940 }
catch (TskCoreException ex) {
3941 throw new CaseActionException(NbBundle.getMessage(
this.getClass(),
"Case.addImg.exception.msg"), ex);
3968 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)
void publishOsAccountsUpdatedEvent(TskEvent.OsAccountsUpdatedTskEvent event)
static synchronized IngestManager getInstance()
void deleteNode(CategoryNode category, String nodePath)
static final ExecutorService openFileSystemsExecutor
static final String NO_NODE_ERROR_MSG_FRAGMENT
void publishPersonsUpdatedEvent(TskEvent.PersonsUpdatedTskEvent event)
static boolean runningWithGUI
static void closeCurrentCase()
void publishHostsDeletedEvent(TskEvent.HostsDeletedTskEvent event)
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 publishOsAccountInstancesAddedEvent(TskEvent.OsAcctInstancesAddedTskEvent event)
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 publishHostsAddedToPersonEvent(TskEvent.HostsAddedToPersonTskEvent event)
void publishTimelineEventAddedEvent(TimelineManager.TimelineEventAddedEvent event)
synchronized static void setLogDirectory(String directoryPath)
volatile ExecutorService caseActionExecutor
void notifyCentralRepoCommentChanged(long contentId, String newComment)
static final String APP_NAME
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 String getCustomTempDirectory()
static CaseDbConnectionInfo getDatabaseConnectionInfo()
String getModulesOutputDirAbsPath()
static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner, CaseType caseType)
void publishPersonsDeletedEvent(TskEvent.PersonsDeletedTskEvent event)
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)
void publisHostsRemovedFromPersonEvent(TskEvent.HostsRemovedFromPersonTskEvent event)
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)
Path getBaseSystemTempPath()
synchronized void openRemoteEventChannel(String channelName)
String getCaseDisplayName()
void publishPersonsAddedEvent(TskEvent.PersonsAddedTskEvent event)
void createCaseNodeData(ProgressIndicator progressIndicator)
static void invokeStartupDialog()
void updateDataParameters()
void publishArtifactsPostedEvent(Blackboard.ArtifactsPostedEvent event)
CaseMetadata getMetadata()
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()
void publishOsAccountDeletedEvent(TskEvent.OsAccountsDeletedTskEvent event)
String getCacheDirectory()
static void addPropertyChangeListener(PropertyChangeListener listener)
void publishHostsUpdatedEvent(TskEvent.HostsUpdatedTskEvent event)
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 TempDirChoice getTempDirChoice()
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)
void publishOsAccountsAddedEvent(TskEvent.OsAccountsAddedTskEvent event)
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()
void publishHostsAddedEvent(TskEvent.HostsAddedTskEvent event)
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 synchronized DirectoryTreeTopComponent findInstance()
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
boolean dbHasDataSource()
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)
static final String TEMP_FOLDER
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()